AppEasy Version 1.4.1 is Now Available

AppEasy Version 1.4.1 is Now Available

AppEasy the cross platform mobile game and app development system for iPhone, iPad, Android and Windows that is aimed at all levels of experience releases latest update

AppEasy version 1.4.1 is now available for download from here.

Please upgrade to the latest version. Note that before updating, close down your current version of AppEasy, rename c:\AppEasy to c:\AppEasy2, install and run AppEasy 1.4 then copy any changes / certificates from c:\AppEasy2 to c:\AppEasy. Note that if you install the update before renaming c:\AppEasy then simply exit the AppEasy project manager, rename the folder and run AppEasy again.

Changes include:

Project Manager

  • XML pool settings have been removed as there is now need for them now

Core Engine

  • Removed the need for setting up the XML pool system. AppEasy now pre-scans files to count the tags and attributes and allocates its own pools on a per file basis
  • VideoCam now has direction property which specifies which camera to use (front or rear)
  • actor.children() added that returns a list of child actors
  • If a File resources target Variable is an array and the files contents contains comma delimited data then the data is split at commas and added to the array
  • New SceneSwitch example added that shows how to switch between different scenes
  • BUG FIX: XML system was trashing small areas of memory

AppEasy 1.4 available – New Lua API, Web View, Ad Support, Video Cam Streaming

AppEasy Version 1.4 is Now Available

AppEasy the cross platform mobile game and app development system for iPhone, iPad, Android and Windows that is aimed at all levels of experience releases latest update

AppEasy version 1.4 is now available for download from here.

Please upgrade to the latest version. Note that before updating, close down your current version of AppEasy, rename c:\AppEasy to c:\AppEasy2, install and run AppEasy 1.4 then copy any changes / certificates from c:\AppEasy2 to c:\AppEasy. Note that if you install the update before renaming c:\AppEasy then simply exit the AppEasy project manager, rename the folder and run AppEasy again.

Lua API has had a major overhaul

We felt that the Lua API was not going in the right direction and was starting to look messy so we rewrote it. Functions have now been split up into libraries to make the API more organised and easier to use. Heres a full list of the libraries we have planned:

  • actions – Deals with XOML actions
  • actor – Deals with actors
  • brush – Deals with brushes (coming soon)
  • camera – Deals with virtual scene cameras (coming soon)
  • facebook – Deals with facebook interaction (coming soon)
  • font – Deals with fonts (coming soon)
  • sys – Deals with general system interaction
  • http – Deals with HTTP communications (coming soon)
  • image – Deals with images (coming soon)
  • input – Deals with device input
  • market – Deals with in-app purchasing (coming soon)
  • media – Deals with audio and video playback
  • physics – Deals with physics (coming soon)
  • program – Deals with XOML programs
  • resource – Deals with generic resources
  • scene – Deals with scenes
  • shape – Deals with shapes (coming soon)
  • template – Deals with templates
  • timeline – Deals with timelines
  • variable – Deals with XOML variables

Over time new functions and even new libraries will appear

New Lua functionality has been added such as querying collision contacts, creating scenes, appending XOML arrays, controlling device vibration, disabling device power saving etc..

Web View

The Web View now works on iOS and Android. You can create web views of any size modal or none modal and either navigate them to a URL or write html / javascript content to them from actions, commands and scripts.

Video Cam Streaming

A new resource type called VideoCam has been added which enables streaming of the devices video camera to an Image, which can in turn be displayed via actors.

New Actor Properties

Actors have been given some new properties, including:

  • IgnoreCamera – Forces actor to ignore camera transform
  • Orphan – Allows child actors to sort via normal actor layers
  • UserData – A simple integer that can be used to store user data such as an index into a script table

Brush UV coordinates

Brushes got a new property called UV, which allows you to set the UV coordinates of the brush directly instead of using SrcRect. Currently only works with image brushes.

Ad Support Added

We decided to add support for HTML ads to AppEasy as they offer a wide range of features compared to basic text or banner ads. For example using HTML ads you have access to the following types of ads:

  • Animating banner and text ads of any size
  • Video ads
  • Interstitial ads
  • Interactive ads
  • Forms based ads
  • Offer walls

We have added information about ad integration to section 20 of the XOML User Guide. We have also added information showing how to get set up and integrated with Leadbolt. We will include additional integrations on the next release.

Complete list of changed in 1.4 include:

Changes to AppEasy Project Manager

  • If project is saved with no location then the location is set to the folder where the project is saved
  • You can now set the size of the XML pools used by AppEasy. Format is (max-tags,max-attributes). Note that these are preallocated data pools so they will eat into your applications memory, so you may need to increase the amount of memory available to your app. Each tag consumes 104 bytes and each attribute consumes 60 bytes plus additional space for parsed strings

Changes to AppEasy Core Engine

  • Lua API has been replaced with a more intuitive Lua API
  • If you now try to add a resource that already exists in the scope it is loaded then a warning will be displayed and the resource will be overwritten
  • WebView now supports new Html attribute which can be used to pass html to the web view to be displayed
  • WebView now works in screen coordinates and not virtual canvas coordinates
  • Actors now have new UserData property that can be use to store a single integer, can be used to store index into script table / array for additional data
  • Actors now have new IgnoreCamera property that allows them to ignore the scenes camera transform
  • All examples now have schema set
  • All examples have been updated to use new Lua API
  • Actors have new property called Orphan. When set to true, actor is taken out of the usual sprite parent / child hierarchy and moves into the normal layer system. This enables child sprites to sort using layers, however actor to actor clipping may be affected
  • New scene.create() method added to allow creation of scenes from lua
  • New actor.getStartContacts() and actor.getEndContacts() functions added to give access to actors that a particular actor has started or ended collisions with
  • New VideoCam resource added that allows you to stream the devices video cam to an image
  • New ChangeVideoCam action added
  • New Lua functions added to change video cam media.changeVideoCam(), can be used to stop and start feed
  • New Lua variable.add() function added to add a value to a XOML variable
  • New Lua variable.append() function added that enables you to append additional elements onto the end of a XOML array
  • New Lua functions sys.vibrate() and sys.stopVibrate() added to control vibration
  • New Lua function sys.changePowerSaving() added to prevent back-light from switching off
  • New Lua function input.touchInfo() which returns information about touches
  • Image brush now supports setting of UV coordinates directly
  • Ads are now integrated via the web view (see section 20 of XOML User Guide)
  • BUG FIX: Some Lua functions were displaying incorrect errors and warnings
  • BUG FIX: Web view now works on iOS and Android (does not work on Windows)
  • BUG FIX: AspectLock fixed
  • BUG FIX: None batched sprites now render correctly at edges
  • BUG FIX: Some examples were broken
  • BUG FIX: Deleting particle actor that was child of another actor crashed when removing particle actor
  • BUG FIX: Particle actor placed inside parent actor didn’t scale by parents opacity when UseParentOpacity set
  • BUG FIX: Empty Param2 in FromTenplate action / commands crash
  • BUG FIX: Fixed changing orientation resizing
  • BUG FIX: Touch panning glitch fixed

Example Changes

  • Added New VideoCam example
  • Added new AdvancedCollision example
  • Added new DynamicWebView example

Marmalade SDK Tutorial – Integrating LUA Script Language

This tutorial is part of the Marmalade SDK tutorials collection. To see the tutorials index click here

Its been a while since I wrote a Marmalade SDk tutorial and to be honest I’ve been itching for the chance to start them back up, so I freed up a little time today to bring you this new tutorial.

Ok, decided that it was high time that IwGame had a proper scripting language, so took a look around various scripting languages including LUA, Javascript and AngelScript. Whilst we like them all and would like to integrate them all at some point, our first choice is LUA.

And as I am a complete LUA noob I decided to write a short tutorial showing how to integrate LUA so a) everyone can see how “not so difficult” (had to avoid the word easy, because that would be wrong) it is to integrate LUA and b) so I don’t forget how to do it myself in the future

I have created a small Marmalade app called lua_test that demonstrates the following:

  • Execute a string containing lua commands
  • Load and execute a lua file from C
  • Load and execute a specific function in a lua file from C
  • Load a lua file that executes a C function

With these basics you should be able to integrate LUA into your own project quite easily.

I’m not going to pretend that I am now a LUA expert after spending but a few hours learning how to integrate it, but I know a few things now to be confident to write this tutorial.

Setting up the MKB to support LUA

The first thing you need to do is edit your projects MKB file and the following sections:

packages
{
    lua
}

subprojects
{
    lua
}

LUA is not distributed with Marmalade, instead it is downloaded from the code repository when you run your MKB file. When you open up your MKB file you will notice a new lua filter has been added

Note that the version of LUA that is supported by the Marmalade SDK is currently 5.1.4

LUA header files

In order to access LUA you need to include the headers. However as we are including C headers into a C++ app we need to let the compiler know. With that in mind we add the headers as follows:

// LUA headers
extern "C"
{
   #include "lua.h"
   #include "lauxlib.h"
   #include "lualib.h"
}

LUA State

LUA holds no global variables so the interpreters current state has to be stored somewhere where it can be accessed from your code. In our simple examples, we create the LUA state using lua_open() which returns a pointer to the state then close it when we have finished using lua_close(). Ideally you would want to manage this pointer to the LUA state, depending on the scope and lifetime of LUA scripts in your app. All of our examples start and end with:

// Open LUA
lua_State *lua = lua_open();

// Add LUA libraries (standard libraries are libraries of code that provide some basic functionality such as print)
luaL_openlibs(lua);                                        // See http://www.lua.org/manual/5.1/manual.html#luaL_openlibs

//
// Do something with LUA
//

// Shut down the lua state
lua_close(lua);                                            // See http://www.lua.org/manual/5.1/manual.html#lua_close

LUA Stack

LUA passes information between C and LAU code via a stack. To pass information to a LUA function from C you push the name of the function that you wish to call onto the stack followed by any parameters that you wish to pass. When the LUA function returns it returns any return values (LUA can return multiple values) or an error on the stack. Similarly when calling a C function from LUA, LUA pushes the parameters onto the stack then calls the C function. The C function examines the parameters on the stack (C does not remove them, LUA removes them when it returns) and utilises the data passed from LUA, carries out some logic and returns.

More info on the LUA stack can be found at http://www.lua.org/pil/24.2.html

Calling a string containing LUA from C

Here’s some example code showing how to execute a piece of LUA contained within a string:

void CallLuaString(const char* string)
{
	s3eDebugOutputString("==== Calling a LUA string");

	// Open LUA
	lua_State *lua = lua_open();

	// Add LUA libraries
	luaL_openlibs(lua);										// See http://www.lua.org/manual/5.1/manual.html#luaL_openlibs

	// Pass the string to lua to execute
	if (luaL_loadbuffer(lua, string, strlen(string), "line") == 0)	// See http://www.lua.org/manual/5.1/manual.html#luaL_loadbuffer
	{
		if (lua_pcall(lua, 0, 0, 0) != 0)
		{
			// Output the error
			s3eDebugOutputString(lua_tostring(lua, -1));

			// Pop error message off the stack
			lua_pop(lua, 1);								// see http://www.lua.org/manual/5.1/manual.html#lua_pop
		}
	}

	// Shut down the lua state
	lua_close(lua);											// See http://www.lua.org/manual/5.1/manual.html#lua_close
}

In this example, we open LUA then ad the standard LUA libraries. We then load the supplied string as a LUA chunk using luaL_loadbuffer() then call it using lua_pcall(). If an error occurs then we display the error and pop it off the stack

Calling a LUA file from C

Our next example looks at how to call a LUA file from C, lets take a look at the code:

void CallLuaFile(const char* lua_filename)
{
	s3eDebugOutputString("==== Calling a LUA file");

	// Open LUA
	lua_State *lua = lua_open();

	// Add LUA libraries
	luaL_openlibs(lua);										// See http://www.lua.org/manual/5.1/manual.html#luaL_openlibs

	// Load our test LUA file
	if (luaL_loadfile(lua, lua_filename) == 0)				// See http://www.lua.org/manual/5.1/manual.html#lua_load
	{
		if (lua_pcall(lua, 0, 0, 0) != 0)					// See http://www.lua.org/manual/5.1/manual.html#lua_pcall
		{
			// Output the error
			s3eDebugOutputString(lua_tostring(lua, -1));

			// Pop error message off the stack
			lua_pop(lua, 1);								// see http://www.lua.org/manual/5.1/manual.html#lua_pop
		}
	}

	// Shut down the lua state
	lua_close(lua);											// See http://www.lua.org/manual/5.1/manual.html#lua_close
}

We begin this example much like we did our previous example, but instead of load_buffer() we call luaL_loadfile(), which basically does the same thing except it loads the data from a file.

Calling a LUA function from C

This example gets a little more complicated as we need to begin dealing with pushing data onto the LUA stack. Lets take a look at the code:

void CallLuaFunctionInFile(const char* lua_filename, const char* function_name, double arg0, double arg1)
{
	s3eDebugOutputString("==== Calling a LUA function from C");

	// Open LUA
	lua_State *lua = lua_open();

	// Add LUA libraries
	luaL_openlibs(lua);										// See http://www.lua.org/manual/5.1/manual.html#luaL_openlibs

	// Load our test LUA file
	if (luaL_loadfile(lua, lua_filename) == 0)				// See http://www.lua.org/manual/5.1/manual.html#lua_load
	{
		// Init the loaded lua file
		if (lua_pcall(lua, 0, 0, 0) == 0)					// See http://www.lua.org/manual/5.1/manual.html#lua_pcall
		{
			// Push the name of the function that we want to call onto the stack
			// NB: LUA uses a stack to pass information back and forth between LUA and C (see http://www.lua.org/pil/24.2.html)
			lua_getglobal(lua, function_name);				// Push function name that we want to call ontothe stack (see http://www.lua.org/manual/5.1/manual.html#lua_getglobal)
			lua_pushnumber(lua, arg0);						// Push function call argument 1
			lua_pushnumber(lua, arg1);						// Push function call argument 2

			if (lua_pcall(lua, 2, 1, 0) != 0)				// See http://www.lua.org/manual/5.1/manual.html#lua_pcall
				s3eDebugOutputString(lua_tostring(lua, -1));
			else
			{
				if (!lua_isnumber(lua, -1))					// http://www.lua.org/manual/5.1/manual.html#lua_isnumber
					s3eDebugOutputString("Function muust return a value");
				else
				{
					// Get th result returned from the LUA function
					double result = lua_tonumber(lua, -1);
				}
			}
			lua_pop(lua, 1);								// see http://www.lua.org/manual/5.1/manual.html#lua_pop
		}
	}

	// Shut down the lua state
	lua_close(lua);											// See http://www.lua.org/manual/5.1/manual.html#lua_close
}

Much of the code remains the same as the previous example, where we initialise LUA, load a LUA file and execute it. The difference is that we now push an actual function name and a number of parameters onto the stack using lua_getglobal() and lua_pushnumber(). We then make another call to LUA which executes the LUA function that we just stacked, e then check the return value and if itis not a number we display an error otherwise we pop the returned number off the stack and store it locally.

Calling a C function from LUA

Things get a little more complicated when you find that you need to call C functions from LUA. The first thing that we need to do is let LUA know that our C function is available to be called as well as define a protocol for how it should be called from LUA. Lets take a look at an example:

static int test_function(lua_State *lua)
{
	double d = 0;
	// Get the argument that was passed from lua
	if (lua_isnumber(lua, 1))
		d = lua_tonumber(lua, 1);
	else
		s3eDebugOutputString("test_function can only accept a number");

	// Square it
	d = d * d;

	// Push the result back onto the stack as a return value
	lua_pushnumber(lua, d);

	// Return the number of result arguments that were passed back to lua
	return 1;
}

void CallCFunctionFromLua()
{
	s3eDebugOutputString("==== Calling a C function from LUA");

	// Open LUA
	lua_State *lua = lua_open();

	// Add LUA libraries
	luaL_openlibs(lua);										// See http://www.lua.org/manual/5.1/manual.html#luaL_openlibs

	// Push the test function
	lua_pushcfunction(lua, test_function);					// See http://www.lua.org/manual/5.1/manual.html#lua_pushcfunction

	// Set the global test_function to the pushed C function
	lua_setglobal(lua, "test_function");					// See http://www.lua.org/manual/5.1/manual.html#lua_setglobal

	// Load our test LUA file
	if (luaL_loadfile(lua, "lua_test3.lua") == 0)			// See http://www.lua.org/manual/5.1/manual.html#lua_load
	{
		if (lua_pcall(lua, 0, 0, 0) != 0)					// See http://www.lua.org/manual/5.1/manual.html#lua_pcall
		{
			// Output the error
			s3eDebugOutputString(lua_tostring(lua, -1));

			// Pop error message off the stack
			lua_pop(lua, 1);								// see http://www.lua.org/manual/5.1/manual.html#lua_pop
		}
	}

	// Shut down the lua state
	lua_close(lua);											// See http://www.lua.org/manual/5.1/manual.html#lua_close}
}

Firstly we create a C function called test_function() which is declared from LUA’s standard C function prototype:

static int test_function(lua_State *lua)

This function accepts a lua state which we can query for information that was passed to it by LUA (on the stack). In our example, we firstly check to see if the value on the top of the stack is a number, if not we display an error, if so then we retrieve that number. Next we modify the number then push it back onto the stack so that it can be retrieved (returned to) by the calling LUA function. Note that the value returned from our C function represents the number of arguments that we returned on the stack. Lets take a quick look at the LUA code that made the call to our C test_function in the first place:

d = test_function(12);
print(d);
d = test_function("hello");    -- This will cause an error because we passed a string instead of a number
print(d);

As you can see it calls test_function twice. The first time it is successful because we passed a number, the second time we passed a string which test_function() detected as an error.

Ok, lets now take a look at the code that registers our C function so that LUA can use it (see CallCFunctionFromLua() above)

Firstly we call lua_pushcfunction(lua, test_function); which places our C function onto the stack. Next we call lua_setglobal(lua, “test_function”); to assign the function an actual name that LUA script can use to call the function.

Well that’s about it. I have included the source code for the lua_test app which you can download from here