Jump to content

Whas
 Share

Recommended Posts

First and foremost, I want to thank the devs for making Phaser Editor, it's amazing! I'll definitely be purchasing it on my next paycheck (if my company doesn't expense it).

For a bit of background I'm new to web-based game development (and web programming as a whole), and Phaser Editor is my entry point! That being said I come from a background as a Unity developer, and so I apologize if many (if not all) of my questions relate more to Phaser and js as a whole and not Phaser Editor in particular, but I'm hoping for the way to best do things using Phaser Editor.

These questions are asked having done the "Mario-Style Platformer" tutorial found at:
https://gamedevacademy.org/make-a-mario-style-platformer-with-the-phaser-editor/



There are a few things I'm having a bit of trouble wrapping my head around:

What exactly is a prototype? Does every object (sprite) have one? Where/how can you access this? Is it the name of the original image file? The first instance you create? The name of a function you first need to write and then assign? How would that be done?

When you drag an object from assets to scene, or duplicate an object, does it create a new prototype, or a new instance?

Can you assign instance variables to prototypes/objects? Can this be done in the scene editor? (ie every "coin" has the variable "collected" set to "false" at start)
What is the best way to do this?

In the templates and the "Mario-Style Platformer" tutorial, all logic is done in Level.js. Can you instead place the logic of each prototype/object into its own script? (ie Player.js, Coin.js)

As Level.js already loads the assets.json, does every script need to do the same, or can they just access it from Level.js? How is cross-script referencing done?

In the same tutorial, all the fruits/coins are collected into a group. Is this a container/parent object? Are the elements then children? What is the best way/when is the best time to assign a variable to all elements? (I tried doing so in Create using "this.pickups.setAll("collected", false);", but when I checked the value in an element later it returned null)

In many Phaser examples online, Functions are done with out any form of container (ie Function preload()), and everything is executed by game (ie game.add._____) but in both the tutorial and the templates, functions are done through Level.protoype (ie Level.prototype.preload = function()), and everything is executed by this. (which I assume also points to Level.prototype?). Is there a difference? Is there a reason to doing things one way or the other?

What is the best way to check/set a value in each element of the group?
(ie  Instead of kill the fruit object upon overlap with player, I set them to play an animation. How would I then set them to destroy upon completion?)

Is there a way to find a specific element in a group (similar to an array index)?

Can you set parent child relations in the scene editor? If not how is this set?

Is there a way to use Vectors/containers to compare and assign values? (ie player.position = Vector2(x, y))

Is there a way to emulate/simulate a 3 button mouse/middle click? (ie ctrl + alt + left click)

I understand that at this time, Phaser Editor does not support Typescript. However as I am more familiar with C based OOP, many have suggested it. Would using Typescript externally alongside Phaser editor break workflow/the project? (From what I understand Phaser Editor does not support editing files externally?)

Sorry for the trouble, and thank you for your time!

 

Link to comment
Share on other sites

Hi @Whas 

Very interesting post, let's go step by step...

 

Quote

What exactly is a prototype? Does every object (sprite) have one? Where/how can you access this? Is it the name of the original image file? The first instance you create? The name of a function you first need to write and then assign? How would that be done?

 

A prototype in JavaScript is like a class in C# (I guess it is the lang you are using in Unity). Usually in Phaser tutorials, mails, etc.. the word class is used instead of prototype.

This is an example of how to create a "subclass" of a Phaser.Sprite:

MonsterBunny = function (game, x, y, rotateSpeed) {

    Phaser.Sprite.call(this, game, x, y, 'bunny');

    this.rotateSpeed = rotateSpeed;

};

MonsterBunny.prototype = Object.create(Phaser.Sprite.prototype);
MonsterBunny.prototype.constructor = MonsterBunny;

MonsterBunny.prototype.update = function() {

    this.angle += this.rotateSpeed;

};

The equivalent in C# is like this (if I remember well C# :) ):

class MonsterBunny : Phaser.Sprite 
{
	public double rotatedSpeed;
	
	public MonsterBunny(game, x, y, rotatedSpeed):base(game, x, y, "bunny")
	{
		this.rotatedSpeed = rotatedSpeed;
	}
	
	public override void update()
	{
		angle += rotatedSpeed;
	}
}

 

Does every object (sprite) have one?

In Phaser yes, in JavaScript I don't know, maybe primitive types has no prototypes. I mean, Phaser follows the OOP, all features are grouped in a classes (prototypes), for example, a sprite in Phaser.Sprite, a button in Phaser.Button, a state in Phaser.State, etc...

> Where/how can you access this?

To create an instance of a protoytpe just use the "new" keyword. Like in "var group = new Phaser.Group(game)". But in Phaser there are lot of "helper" methods to create the objects, for example, to create a sprite you can use the "game.add.sprite()" method, to create a group "game.add.group()", for simple games probably you don't need to create objects with the "new" keyword, unless you create custom objects like we do in Phaser Editor to create the scene, that is a subclass of Phaser.Group.

 

Is it the name of the original image file?

What image file? If you are talking about when you drop an image asset into the Phaser Editor canvas, the object gets the name of the asset key. But it is just the name used by the variable that references that object. For example if you drop an image asset with key "dog", it creates a `var dog = this.add.sprite(0, 0, "dog")`, but you can change the name of that variable in the property grid by setting it in the `Editor > name` property.

> The first instance you create? The name of a function you first need to write and then assign? How would that be done?

As you can see in the previous snippet, the prototype is created by defining a "special" function with a "prototype" field.

When you drag an object from assets to scene, or duplicate an object, does it create a new prototype, or a new instance?

It creates a new instance. The prototype remains the same. If you duplicate a Phaser.Sprite, it creates a new instance of Phaser.Sprite.

Can you assign instance variables to prototypes/objects? 

You can publish objects with instance variables. Just flag it as public in the property grid. Look this case, it will create a "fPlayer" instance var.

PublicVar.png

 

> Can this be done in the scene editor? (ie every "coin" has the variable "collected" set to "false" at start) What is the best way to do this?

Well, yet in the scene editor you cannot assign a custom prototype (class) to the objects, the objects are created using the "this.add.sprite", "this.add.group", etc.. methods. In a future we can support it, but in the meantime there are other options. Each sprite in Phaser has a "data" field made specially to put user data. You can use it to put the "collected" var ("coin.data.collected"). In the scene editor you can edit that property. It opens a simple text editor where you can write a "json" object that will be assigned to the coin. Read more about it here.

And sure, you can use the coinsGroup.setAll("collected", false) too. The "setAll" method of a group just do an iteration for all children and set the property value. It is the common practice in Phaser.

 

In the templates and the "Mario-Style Platformer" tutorial, all logic is done in Level.js. Can you instead place the logic of each prototype/object into its own script? (ie Player.js, Coin.js)

Yes, in Phaser you can do it, you can create a subclass of Phaser.Sprite and override the "update" method. To add it to the game, or group, just create an instance of your class with the right parameters. In the example of the prototype it does "var wabbit = new MonsterBunny(game, 200, 300, 1);". However you are free to do it in the way you like. I like to use "behavior" classes. I code the logic of the interaction of the coins with the world in CoinBehavior prototype (that I write in other file) and then I just call it in the game loop. In my personal opinion, custom sprites are good to apply transformations on the sprite, but for interactions with other objects I prefer to use this "behaviors" classes, that take as parameters the different elements of the game and I can use it in different levels.

As Level.js already loads the assets.json, does every script need to do the same, or can they just access it from Level.js? How is cross-script referencing done?

Cross script references is similar to C#. You declares elements (let's say classes) in any file but they will be available in all the scripts. The name of the script file does not matter, what matter is the name of the classes you define. To make a script "visible" to others, you have to include them in the <script> tag of the index.html file or you can add them to the assets.json using the "script" asset type. But warning, the scripts loaded via the assets.json are those you will use after the game is created, they are loaded just like any other asset (image, audio, etc..). The advantage to load game scripts qith the assets.json file is that it is done async, and you can get the progress of the load (this is a more advantage stuff).

The thing with the Level.js file is that there we define the Level state. In Phaser the loop of the game is implemented in states. You can create different states in different files, for example, a Menu.js file could contain a Menu state, that controls the game loop in the menu screen. And states also "loads" and "create" the objects. There is not need to load the assets (asstes.json) in all the scripts, else in all the states. Actually you can split the assets.json in sections and load one section or other in dependence of the state (in menu you would like to load buttons, in the Level coins).

In the same tutorial, all the fruits/coins are collected into a group. Is this a container/parent object? Are the elements then children?

Yes, it is the parent object of all the coins. In Phaser a group has different roles, like transformation or in this case, grouping objects of the same type/behavior.

> What is the best way/when is the best time to assign a variable to > all elements? (I tried doing so in Create using "this.pickups.setAll("collected", false);", but when I checked the value in an element later it returned null)

Well.. I should see the code you wrote in the create, but in that method is where you can init your objects, as you did.

In many Phaser examples online, Functions are done with out any form of container (ie Function preload()), and everything is executed by game (ie game.add._____) but in both the tutorial and the templates, functions are done through Level.protoype (ie Level.prototype.preload = function()), and everything is executed by this. (which I assume also points to Level.prototype?). Is there a difference? Is there a reason to doing things one way or the other?

 

Yes well, that's the pretty and the ugly of JavaScript or dynamic langs, you can do the same in different ways. For simplicity many Phaser examples uses object literals to create the states, the game injects all the needed methods in it, think like a class that is created dynamically. It is good for simple games and demos, but if you want inheritance you will be forced (I think) to use prototypes. In Phaser Editor we use prototypes for a simple reason, it helps the type inference engine, because with prototypes you are telling to the "compiler" the context of your code, so it can infers the available methods when you code "this.something". Sure, if your game instance is global, like in many examples, you can use game.add, game.load, etc... these are shortcuts to the current factory and loader, it is just a way in Phaser to write less. But again, it is good and beautiful for small games or demos, but in bigger games you would like to do encapsulate things in custom states, sprites, groups, behaviors, data classes, etc...

 

What is the best way to check/set a value in each element of the group?

By using the group.setAll("myproperty", myvalue);


> (ie  Instead of kill the fruit object upon overlap with player, I set them to play an animation. How would I then set them to destroy upon completion?)

What animation? Those made with frames? Or those made with tweens? In the first case, the play method has a final parameter killOnComplete:

{Phaser.Animation} Phaser.Sprite.play(name, frameRate, loop, killOnComplete)

In the second case, tweens, you can add listener to the onComplete signal, and kill the coin.

 

Is there a way to find a specific element in a group (similar to an array index)?

group.getAt(index)

 

But just look into the Phaser.Group doc, there are lot of useful methods there.

Can you set parent child relations in the scene editor? If not how is this set?

Yes, you can group elements. Just select the objects and press "G", it will create a new parent group with the selection as children. And you can break a group by pressing SHIFT+G.

 

Is there a way to use Vectors/containers to compare and assign values? (ie player.position = Vector2(x, y))

There is a Phaser.Point class used in many properties like anchors, scale, position. You can do things like sprite.position.set(10, 20).

 

Is there a way to emulate/simulate a 3 button mouse/middle click? (ie ctrl + alt + left click)

Hehe no idea! Check out the Phaser.Pointer class. You get the pointers from game.input.activePointer for example.

I understand that at this time, Phaser Editor does not support Typescript. However as I am more familiar with C based OOP, many have suggested it. Would using Typescript externally alongside Phaser editor break workflow/the project? (From what I understand Phaser Editor does not support editing files externally?)

Yes, you can use Phaser Editor for example to manage the assets and create the scenes but code typescript with other editors. There is not any problem with that. You can read this article about it.

 

Also, just a vanity thing, but can you add/edit editor themes? I'm using dark, but whenever it highlights other uses of a keyword, the highlight makes the word illegible.

 

Go to Windows > Preferences > JavaScript > Editor > Syntax Coloring. There you can change the style of different elements like keywords.

 

I hope that this answer make things more clear. Please do not hesitate to ask anything.

 

 

 

 

 

 

 

 

 

 

 

 

Link to comment
Share on other sites

Thanks! Though to clarify my question on a few points:

There is presently no way to add custom prototypes, or add a sprite as a Sprite sub-prototype in the editor?

For assigning instance variables to prototypes/objects in editor, I more meant adding new variables to objects in the scene,
but I believe you explained that that's not supported?

How then do you/what is the best way to manage properties regarding an object on an instance level?
ie you have "enemies", and they each need: health (float), state(enum{ idle, active, attacking, damage}), attackPower (float), etc.
and each would would have varying starting amounts, and different values at different points.

For the best way to check/set a value in each element of the group

I more meant something like "for each element in group, if (element.health < minValue){ element.kill();}

For setting parent in editor I more meant the ability to set one

object as another's parent 
ie set "gun" to be a child of "player", and "bullet" to be a child of "gun" (hierarchy)



For using setAll, I (attempt to) do so here: 

//Collectables
	//set reference to collectables group
	this.pickups = scene.fCollectable;
	
	//set the physics properties of the collectable sprites
	this.pickups.setAll("body.immovable", true);
	this.pickups.setAll("body.allowGravity", false);
	
	this.pickups.setAll("collected", false);
	this.pickups.callAll('animations.play','animations', 'Idle');

where setting "collected" doesn't work, but I assume my syntax is wrong? Do I somehow need to create the property first?


For animations, yes I meant frame animations. Can you set killOnComplete to all children in a group?

For emulating a three button mouse, I more meant in the Scene Editor - it requires middle click to pan.

 

1 hour ago, Arian Fornaris said:

Yes, you can use Phaser Editor for example to manage the assets and create the scenes but code typescript with other editors. There is not any problem with that. You can read this article about it.

Can you link me to that article? :)

Link to comment
Share on other sites

There is presently no way to add custom prototypes, or add a sprite as a Sprite sub-prototype in the editor?

Yes, you can use custom sprites, actually there is a wizard File > New > Sprite Source File that you can use, it creates a sprite sub-prototype. But the scene editor does not have any way to create the objects by using a custom prototype. It just uses the "game.add.sprite" pattern. But there is a workaround you can do. Since it is javascript, you can change later the prototype of the sprites. For example, if you have a player object made in the scene editor, later, in the create method you can change its prototype by the one you did:

var scene = new Scene1(this.game);
scene.fPlayer.__proto__ = MyPlayer.prototype;

or the preferred way in ECMA6 (already supported by firefox and chrome):

Object.setPrototypeOf(scene.fPlayer, MyPlayer.prototype);

If you want to change the prototype of many coins, just iterate the group of coins and set it:

coins.forEach(function (coin) {
	coin.__proto__ = MyCoin.prototype;
}, this);

Or use the setAll shortcut:

coins.setAll("__proto__", MySprite.prototype);

 

Please read more about changing prototypes here: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf

Warning: I never saw someone doing it in Phaser, people only create customs objects by using the "new" keyword, but as a workaround to the generated scene of Phaser Editor it should work well. In the article it says that it can be an expensive operation, but usually you are going to do it in the create method, that is executed once.

In future versions of the scene editor we are going to support custom prototypes or custom object factories, yet we have to decide it.

> For assigning instance variables to prototypes/objects in editor, I more meant adding new variables to objects in the scene,
but I believe you explained that that's not supported?

I guess you mean that you need to add custom properties to the objects. Well, as I explained, in Phaser there is the "data" property, it is reserved only to put user data. In the editor you can edit that property, it is a simple text editor where you write the JSON value of data, so there you can put your own properties. But now I realize that maybe you want something like in VS/C#, where new properties can be edited in the property grid, as any other built-in property. It is an interesting feature and we just added it to the TODO list :). Maybe in the future we can create a more sophisticated way to create custom sprites with custom properties and support it in the scene editor.

 

How then do you/what is the best way to manage properties regarding an object on an instance level?
ie you have "enemies", and they each need: health (float), state(enum{ idle, active, attacking, damage}), attackPower (float), etc.
and each would would have varying starting amounts, and different values at different points.

Well, you have the option to use the "data" property of the sprites, for example:

sprite.data.state = STATE_IDLE;

It is jsvascript, you can add properties at any moment to any object.

but yet you can use the custom prototype, that I would use it if there are custom methods, if you only want to add custom props to an object, but logic still coded in other place, in the state or a behavior class, then I will keep using the sprite.data. You can init your objects like this:

 

enemies.setAll("data", {
	state: STATE_IDLE,
	attackPower : 1.5
});

By the way, not that Phaser sprites has built-in health variables.

 

> For using setAll, I (attempt to) do so here... where setting "collected" doesn't work, but I assume my syntax is wrong? Do I somehow need to create the property first?

Yes, I think you are right, you have to create the collected var first. But if you use the data property it works (things in Phaser are not like in Unity, there are lot of shortcus that allow to create games quickly and with fewer code, OOP does not have a strong presence):

this.pickups.setAll("data", { collected : true });

// later you can do

this.pickups.setAll("data.collected", false);

By the way, in the scene builder you can create "template objects", with your own settins, like custom "data", then you can copy/paste to reproduce them. Even you can copy/paste from different scenes, so you can create a scene only for template objects that you can use in all your real scenes. In the scene settings dialog you can uncheck the auto generate code option, so this template scene is going to be only for design purpose.

 

> For animations, yes I meant frame animations. Can you set killOnComplete to all children in a group?

Mmm... the killOnComplete can be set to the animation object. You can do something like:

 

coins.forEach(function (coin) {
	var animation = coin.animations.getAnimation("collect");
	animation.killOnComplete = true;
}, this);	

I did not test it but it should work. This is something we would be happy to support in the scene editor!

 

For emulating a three button mouse, I more meant in the Scene Editor - it requires middle click to pan.

Ah, do you mean that you want to pan for example by pressing Ctrl+Left Button? No, it is not supported, but it is something we can implement just right now for the next release that will be very soon :)

 

Well... it was a good round, there is nothing like user feedback to improve your product :) Thanks!

 

 

 

Link to comment
Share on other sites

Thanks so much for being so patient, and so transparent with both your Editor and just Phaser/JS in general, you're awesome! The ground work is all there, and it's a great resource for getting up and running. I especially enjoy the Tileable sprites from texture atlases, and the audio sprite editor (I've never worked with audio sprites before; it really saves time for trimming sfx!) . I'll be buying the editor in the next few days, and am excited to for updates and getting to see this grow.  A guide for Unity developers would be icing - not priority of course but it would have a strong hook for helping developers migrate/expand into web-game development (with a heavy dependency on Phaser Editor). :)

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...