Eventually, developers may need to perform platform-specific operations, such as controlling ads (showing and hiding), connecting the game to an on-line source in order to retrieve and exchange data, and much more. For this purpose, Ethanon Engine provides interfaces called Native Command Listeners that allow developers to send custom string-based commands from the game script (AngelScript) to the platform native code, like Java on Android, Objective-C on iOS/OSX or C++ on Windows and OSX.
The function ForwardCommand
can be used from the inside of the AngelScript's gameplay code to forward any string-based command, e.g.:
ForwardCommand("enable_ads");
ForwardCommand("disable_ads");
ForwardCommand("connect_to_facebook");
ForwardCommand("submit_score " + score);
iOS and Android implementations already parse and execute some basic commands by default:
ForwardCommand("upen_url http://ethanonengine.com/"); // opens the Ethanon website ForwardCommand("vibrate 100"); // vibrates the device during 100 ms
In order to read custom commands, the developer must implement a native command listener on each platform.
Once forwarded by the ForwardCommand
function, each string is sent to the local command listener object, so the developer may parse, identify and then perform anything he needs. Normally it happens in a place where he has access to the entire platform API.
If multiple commands are sent in a single game frame, they come bundled in a single string separated by '\n'
.
On Android, the standard Ethanon project includes the Java interface net.asantee.gs2d.io.NativeCommandListener
that, once registered to the main Ethanon Activity, calls its parseAndExecuteCommands
passing a list of commands separated by '\n'
:
package net.asantee.gs2d.io; public interface NativeCommandListener { public void parseAndExecuteCommands(String commands); }
Let's create a simple command listener that submits high scores to an on-line server. On the AngelScript side:
uint points = 9999; ForwardCommand("submit_score " + points);
On the Java side:
package com.mygame.io; import net.asantee.gs2d.io public class MyGameCommandListener implements NativeCommandListener { public void parseAndExecuteCommands(String commands) { if (!commands.equals("")) { String[] commandArray = commands.split("\n"); for (int t = 0; t < commandArray.length; t++) { executeCommand(commandArray[t]); } } } private void executeCommand(String cmd) { String[] words = cmd.split(" "); if (words[0].equals("submit_score")) { MyGame.submitScore(Integer.parseInt(words[1])); } } }
Finally, we must register our listener to the Ethanon activity. The net.asantee.ethanon.EthanonActivity
class inherits the void insertCommandListener(NativeCommandListener commandListener)
method which must be used (preferably in the onCreate
method) in order to register our custom command listener inside your activity's onStart
method:
public void onStart() { super.onStart(); insertCommandListener(new MyGameCommandListener()); }
After MyGameCommandListener
is inserted, Ethanon will automatically call our custom parseAndExecuteCommands
every time our game receives commands.
The C++ class Platform::NativeCommandListener
declared in the source file ethanon/toolkit/Source/src/gs2d/src/Platform/NativeCommandListener.h
provides an interface that, once registered, listens to every custom command sent by the game code, where the developer can use the Objective-C-based iOS frameworks and do anything an iOS app can do:
namespace Platform { class NativeCommandListener { public: virtual void ParseAndExecuteCommands(const gs2d::str_type::string& commands) = 0; }; } // namespace Platform
The Platform::NativeCommandListener
behaves like the Java's NativeCommandListener
on Android. Here is a small sample:
class MyGameCommmandListener : public Platform::NativeCommandListener { void ExecuteCommand(const gs2d::str_type::string& commandLine); public: void ParseAndExecuteCommands(const gs2d::str_type::string& commands); };
void MyGameCommmandListener::ParseAndExecuteCommands(const gs2d::str_type::string& commands) { std::vector<gs2d::str_type::string> commandLines = Platform::SplitString(commands, GS_L("\n")); for (std::size_t t = 0; t < commandLines.size(); t++) { ExecuteCommand(commandLines[t]); } } void MyGameCommmandListener::ExecuteCommand(const gs2d::str_type::string &commandLine) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString* line = [NSString stringWithUTF8String:commandLine.c_str()]; NSArray *words = [line componentsSeparatedByString:@" "]; NSString* word0 = [words objectAtIndex:0]; if ([word0 isEqual:@"submit_score"]) { NSString* word1 = [words objectAtIndex:1]; const double score = [word1 doubleValue]; MyGameAPI.SubmitScore(score); } [pool release]; }
For a more concrete working sample, take a look at the IOSNativeCommandListener.h
and IOSNativeCommandListener.mm
source files in the iOS Xcode project.
To register iOS's listener use the GLView
's method
insertCommandListener
:
[self insertCommandListener:(Platform::NativeCommandListenerPtr(new MyGameCommmandListener))];
The GLView
is an Objective-C interface located in the iOS Xcode project.