Possible Phaser target?

Monkey Targets Forums/HTML5/Possible Phaser target?

Jesse(Posted 2015) [#1]
.


Jesse(Posted 2015) [#2]
I am trying to create a target to be able to use Phaser as a monkey target. I can get most of it working but the biggest problem is passing function as parameters for functions (if that makes any sense). Does any one have an idea how I can use an alternative solution for that?

I already have running the only limit so far is passing functions as parameters which is a big deal. really a show stopper.

This is [a/ phaser.io]phaser[/a]


SLotman(Posted 2015) [#3]
Hmmm? I don't know what Phaser is, but why would you need to pass a function as parameter? Is it a requirement in the Phaser SDK? What language does it use?

If its C++ - this is an example I use on my DX9 target:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
}

And then in the structure used by the CreateWindow call, this is how its filled:

// fill in the struct with the needed information
wc.lpfnWndProc = WindowProc; <--- name of the function

// register the window class
RegisterClassEx(&wc);


Jesse(Posted 2015) [#4]
Sorry, I just assumed since this was an html5 section it would be obvious to assume it would unquestionably be Javascript.

this phaser. It is a Javascript/Html5 game library/engine.

This is the javascript code for a demo:
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create, update: update, render: render });

function preload() {

    //  You can fill the preloader with as many assets as your game requires

    //  Here we are loading an image. The first parameter is the unique
    //  string by which we'll identify the image later in our code.

    //  The second parameter is the URL of the image (relative)
    game.load.image('phaser', 'assets/sprites/phaser.png');

}

var sprite;

function create() {

    //  To make the sprite move we need to enable Arcade Physics
    game.physics.startSystem(Phaser.Physics.ARCADE);

    sprite = game.add.sprite(game.world.centerX, game.world.centerY, 'phaser');
    sprite.anchor.set(0.5);

    //  And enable the Sprite to have a physics body:
    game.physics.arcade.enable(sprite);

}

function update () {

    //  If the sprite is > 8px away from the pointer then let's move to it
    if (game.physics.arcade.distanceToPointer(sprite, game.input.activePointer) > 8)
    {
        //  Make the object seek to the active pointer (mouse or touch).
        game.physics.arcade.moveToPointer(sprite, 300);
    }
    else
    {
        //  Otherwise turn off velocity because we're close enough to the pointer
        sprite.body.velocity.set(0);
    }

}

function render () {

	game.debug.inputInfo(32, 32);

}


and this is the monkey code I have working:

Import legend


Function Main:Int()
	New Game
	Return 1
End Function

Class Game Extends App
	
	Field game:Phaser
	
	Method New()
		game = CreateGame(800,600,Phaser.AUTO,"touch")
	End Method
	
	Method OnPreload()
		'  You can fill the preloader with as many assets as your game requires

		'  Here we are loading an image. The first parameter is the unique
		'  string by which we'll identify the image later in our code.

		'  The second parameter is the URL of the image (relative)
		game.load.Image("phaser", "data/phaser.png");

	End Method
	
	Method OnCreate()
		'  To make the sprite move we need to enable Arcade Physics
		game.physics.StartSystem(Physics.ARCADE);
		
		sprite = game.add.Sprite(game.world.centerX, game.world.centerY, "phaser");
		sprite.anchor.Set(0.5);
		
		'  And enable the Sprite to have a physics body:
		game.physics.arcade.Enable(sprite);
	End

	Field sprite:Sprite
	
	Method OnUpdate()
		'  If the sprite is > 8px away from the pointer Then let's move to it
	    If (game.physics.arcade.DistanceToPointer(sprite, game.input.activePointer) > 8)
			'  Make the Object seek To the active pointer (mouse Or touch).
			game.physics.arcade.MoveToPointer(sprite, 300);
	    Else
			'  Otherwise turn off velocity because we're close enough to the pointer
			sprite.body.velocity.Set(0);
		End

	End
	
	
	Method OnRender()
		game.debug.InputInfo(32, 32);
	End Method
	
End Class


and it works exactly as in this demo:
http://phaser.io/examples/v2/basics/04-image-follow-input


it can not run this code because of the function name as parameter:
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });

function preload() {

    game.load.spritesheet('mummy', 'assets/sprites/metalslug_mummy37x45.png', 37, 45, 18);

}

var sprites;
var rip = 0;

function create() {

    sprites = game.add.group();

    game.time.events.loop(50, createSprite, this);

}

function createSprite() {

    var mummy = sprites.create(0, game.world.randomY, 'mummy');

    mummy.animations.add('walk');

    mummy.play('walk', 10, true);

}

function update() {

    sprites.setAll('x', 10, true, true, 1);

    sprites.forEach(checkSprite, this, true);

}

function checkSprite(sprite) {

    try {
        if (sprite.x > game.width)
        {
            rip++;
            sprites.remove(sprite, true);
        }
    }
    catch (e)
    {
        console.log(sprite);
    }

}

function render() {

    game.debug.text("Group size: " + sprites.total, 32, 32);
    game.debug.text("Destroyed: " + rip, 32, 64);

}



all I am doing is opening the javascript code to Monkey-X. I can just about do everything that does not require passing functions to other functions as parameters. Phaser uses functions for event controls and its exactly where the problem is. I won't be able to continue unless I figure out how to do a work around. I am not sure if all of the base languages for monkey allow this but if that is the case my only other solution would be if Mark was to add that property to Monkey.


ImmutableOctet(SKNG)(Posted 2015) [#5]
Yeah, if you want proper call-backs/delegates/function-pointers, then you'll have some problems with Monkey (In Monkey, we just use interfaces for this). To do something like this, you'll need to create your own module which handles this kind of thing in native code, then share common variables or classes with Monkey (Basically, what Mojo does). That being said, you could technically make a custom target based on the standard HTML5 one. This looks like it would be annoying when dealing with external code, as you'd probably need to create some kind of generic wrapper system. Monkey doesn't support passing functions as arguments, so you'd need to either use interfaces, or use generics with a few hacks.

The far better option is to port the entire thing to Monkey, though. Monkey has WebGL support, and most of what can be done in JavaScript can be easily plugged-into, or accessed from Monkey ('dom' module, for example). That's a pretty big project, though. Plus, it would still need some refactoring to work well. I'm not a JavaScript expert, I've messed with it before, but nothing major. I suppose technically, the compiler could have language-specific setups like this, but I doubt Mark would be okay with it.

Other than using the "mangled" names the compiler produces, I can't really see a way around this. Maybe with an interface being sent into external code? Not sure if interfaces can work like that with Monkey. So, besides being a nice API, is there a reason you want to use Phaser with Monkey? It's not like your code would be portable anyway. Maybe you like the way Monkey looks? Unless you're going to put the effort into a port, or possibly make a custom target/module, you can't really do much with it.

I vote for porting it, but that would take a bit of effort.


Jesse(Posted 2015) [#6]
.


Jesse(Posted 2015) [#7]

besides being a nice API, is there a reason you want to use Phaser with Monkey?



It's just a nerdy project I wanted to tackle. I kind of liked the idea of it being able to run on desktop and smart devices with out any modifications. It's a reach and flexible library. besides at the rate I was going it was going to be a quick and easy conversion.

Yea, I don't know if I want to tackle converting the whole library to monkey. Might be a nice library to convert though. Beside they are already working on a new version which according to them its a complete rewrite and not going to be compatible with previous versions.

I might tackle editing the compiler. Although I have not messed with compilers before, It might be a good challenge for me.

Thanks IO.


impixi(Posted 2015) [#8]
For simple callbacks:

1. Write a "wrapper" function or method, substituting the Function object type parameter with a string parameter. Use the object's built-in associative array to access the relevant method via the string.

2. Include the wrapper function/method in your Monkey Extern declarations.

3. Call the wrapper function/method as necessary, placing the desired callback in a string. The name should match exactly the Javascript equivalent.

Example
-------------

cbtest.js
//Javascript object:
function MyObj()
{
	this.action = null;
	
	this.doAction = function(pAction){this.action=pAction; this.action();};
	this.doThis = function() {alert("This!");};
	this.doThat = function() {alert("That!");};
}

//Wrapper method for Monkey's benefit:
MyObj.prototype.doActionFromStr = function (strAction)
{
	this.doAction(this[strAction]);
}


--

test.monkey
Strict

Import "cbtest.js"
Import mojo

Extern 
	Class TMyObj = "MyObj"
		Method DoActionFromStr:Void(strAction:String) = "doActionFromStr"
	End
Public

Function Main:Int()
	New MyApp
	Return 0
End

Class MyApp Extends App

	Field obj:TMyObj

	Method OnCreate:Int()
		obj = New TMyObj()
		SetUpdateRate 60
		Return 0
	End

	Method OnUpdate:Int()
		If MouseHit(MOUSE_LEFT)
			'Use the wrapper method. 
			'(Put the desired callback method in quotes). 
			obj.DoActionFromStr("doThis")	
		Else
			If MouseHit(MOUSE_RIGHT)
				obj.DoActionFromStr("doThat")
			Endif
		Endif
		Return 0
	End
	
	Method OnRender:Int()
		Cls 0, 0, 0
		DrawText "Left-click for THIS action. Right-click for THAT action", 10, 10
		Return 0
	End
	
End



Jesse(Posted 2015) [#9]
Thanks Impixi. I'll try that. Very much appreciated.


impixi(Posted 2015) [#10]
Although my above explanation only helps if you want to switch between existing Javascript functions. Such functionality *within* Monkey is a whole different problem (eg function pointers, callbacks, etc, in actual Monkey code.)

For my three.js wrapper, I cloned and modified mojo's HTML5 module. Also coded a more Monkey-friendly underlying application framework.

You might need to do something similar for your Phaser project.

An extract:


function ThreeApp()
{
	//TODO: Check validity of all created objects before use...
	
	this.monkeyCanvas = document.getElementById("GameCanvas");
	var glContext = initWebGL(this.monkeyCanvas);
	this.renderer = new THREE.WebGLRenderer(glContext);
	this.renderer.setSize(this.monkeyCanvas.width, this.monkeyCanvas.height);
	
	this.scene = null;
	this.camera = null;
	
	this.GetWidth = function(){return this.monkeyCanvas.width;};
	this.GetHeight = function(){return this.monkeyCanvas.height;};
	this.GetRenderer = function(){return this.renderer;};
	
	this.SetScene = function (scene) {this.scene = scene;};
	this.SetCamera = function (camera) {this.camera = camera;};
	
	this.OnRender = function() 
	{
		requestAnimationFrame(this.OnRender.bind(this));
		
		if ((this.scene!=null) && (this.camera!=null))
		{
			this.renderer.render(this.scene, this.camera);
		}
			
	};
	
	this.OnRender();
}



_

In Monkey, I just create a new ThreeApp and set my camera and scene objects accordingly. (And work within my modified Mojo HTML framework OnCreate and OnUpdate methods. OnRender is not used in my case.)

_


Jesse(Posted 2015) [#11]
I pretty much redid the the mojo module including all of the relevant brl files and I based it on the Html5 target. even though I am using the OnCreate OnUpdate, and OnRender, they don't work the same way. I am trying to make the target as close as possible to the original Phaser module. The onRender is mostly for debugging.

I haven't tried your example yet, it seems as it might be the solution for what I need to do.

I'll try tomorrow. Going to sleep now.

Thanks Again.