Phaser.io - Load objects from Tiled - phaser-framework

I'm new to phaser, and for the past few days I've been trying to make a really simple game, platformer-style, where the player must navigate to certain areas before being able to exit the level.
I have the basics running, but now I can't seem to figure out how to check if the player is in those areas.
The relevant part of the code so far is as follows:
var game = new Phaser.Game(800, 600, Phaser.AUTO, "mygame", {
preload: preload,
create: create,
update: update,
render: render
});
function preload() {
game.load.tilemap("questMap", "assets/quest.json", null, Phaser.Tilemap.TILED_JSON);
game.load.image("tilesheet", "assets/tilesheet.png");
game.load.image("npc", "assets/npc.png");
game.load.spritesheet("player", "assets/player.png", 64, 64);
}
var map;
var tileset;
var groundBg;
var props;
var houses;
var houseProps;
var npc;
var ground;
var areas;
var player;
function create() {
game.physics.startSystem(Phaser.Physics.ARCADE);
game.stage.backgroundColor = "#A8DBFF";
map = game.add.tilemap("questMap");
map.addTilesetImage("tilesheet");
map.addTilesetImage("npc");
ground = map.createLayer("ground");
groundBg = map.createLayer("groundbg");
props = map.createLayer("props");
houses = map.createLayer("houses");
houseProps = map.createLayer("houseprops");
npc = map.createLayer("npc");
map.setCollisionBetween(1, 5000);
ground.resizeWorld();
Not too pretty, I know.
I've created the map with tiled and there are a lot of small props and decorative tiles, hence the multiple "map.createLayer()" calls. The only one with collision is the ground layer.
Now, on my Tiled file, I've created an Object layer and drawn small rectangles on the areas I want to check if the player is in. I thought this was going to be an easy process but I can't seem to figure out how to load those areas into Phaser, and then check if the player is within bounds.
Googling has given me some results, but none seem to fit, as they usually cover how to add a sprite to an object, which in this case does not apply.
I simply need that small area to exist and check if the player is there. I've also given names to each of those rectangles in Tiled, via the custom properties tab.

I would try using a transparent image as the area you wish to check if your sprite is over and use
if(sprite1.overlap(transparentImage)){
//do something
}

Related

How to access Object3D material after adding the GLTF

I want to duplicate my GLTF models with different positions/colors dynamically, to do so I have done:
const L_4_G = new Object3D();
...
const multiLoad_4 = (result, position) => {
const model = result.scene.children[0];
model.position.copy(position);
model.scale.set(0.05, 0.05, 0.05);
//
L_4_G.add(model.clone())
scene.add(model);
};
...
function duplicateModel4() {
L_4_G.translateX(-1.2)
L_4_G.translateY(0.0)//0.48
L_4_G.translateZ(1.2)
L_4_G.rotateY(Math.PI / 2);
scene.add(L_4_G);
}
I didn't find out how can I change the Object3D color from the documentation, can you please tell me how can I do that? thanks in advance.
Here is the full code that I'm using, and here are the models
Update
I have seen this solution, to store a set of colors in the object's userData and choose the color later:
L_2_G.userData.colors = {green : #00FF00, red : ..., ...}
L_2_G.children[0].material.color(userData.colors["green"])
But I'm getting an error that children[0] undefined, but I can see that this object has a child and a material, and color via the console: console.log(L_2_G.children), console.log(L_2_G.children.length)--> 0
Also I have tried getObjectByName as explained here:
scene.getObjectByName(name).children[0].material.color.set(color);
which also reslts: children[0] is undefined, scene.getObjectByName(name).children.length is 0.
THREE.Object3D is a base class for anything that can go in a scene graph, including lights, cameras, and empty objects. Not all Object3D instances have geometry or materials. You may be looking for the THREE.Mesh subclass which does have materials and colors.
In general, code like getObjectByName(...) and model = result.scene.children[0] is very content-specific. The file might contain many nested objects, and .children[0] just grabs the first part. It's usually best to traverse the scene graph instead, looking for the objects you want to modify (e.g. looking for all Meshes, or Meshes with a particular name).
const model = result.scene;
model.traverse((object) => {
if (object.isMesh) {
object.material.color.setHex( 0x404040 );
}
});
Then you can either add the entire group to your scene (scene.add(model)), or just add parts of it. Keep in mind that adding meshes to a new parent removes them from their previous parent, and you shouldn't do that while traversing the previous parent. Instead you can make a list of meshes, and add them in a second step:
const meshes = [];
result.scene.traverse((object) => {
if (object.isMesh) {
meshes.push(object);
}
});
for (const mesh of meshes) {
scene.add(mesh);
}
Finally, the position of an object is inherited from its parents. By removing the object from its original parents you might change its position in the scene. If you are planing to assign a new position to the object anyway, that is fine.

Select and manipulate particular paths within a path group fabric.js

I am making an app that involves shapes like cylinders and boxes, and need to be able to do this with fabric.js. I know about three.js but for my purposes, it must be in 2D.
Initially I thought I would just create them in 3D software and render images which can then be added to the canvas, which I did successfully...
However, I have run into a hurdle where fabric only allows patterns to be filled onto paths or objects (rect, circle etc.)....not images (png).
Since I absolutely need patterns, I now need to create these cylinders in SVG. I have gotten as far as making the cylinders in Illustrator, saving them as SVG's and then using them on the canvas, then adding fill patterns on them. So far so good.
Now I want to be able to fill a different pattern for the top of the cylinder, and a different pattern to the side BUT still have it as one object.
So...How can I select and manipulate particular paths within a path group? Is there anyway to give each path within the group a custom attribute (eg. name) which I can then target? Do I need to create two seperate SVG files and then add them seperately, and if so, how can I do this and still have it as one object?
Here's how I am adding the svg to the canvas...
fabric.loadSVGFromURL("/shapes/50-250R.png", function(objects) {
var oImg = fabric.util.groupSVGElements(objects);
oImg.perPixelTargetFind = true;
oImg.targetFindTolerance = 4;
oImg.componentType = "Shape";
oImg.lockUniScaling = true;
oImg.lockScalingX = true;
oImg.lockScalingY = true;
oImg.setControlsVisibility({'tl': false, 'tr': false, 'bl': false, 'br': false});
canvas.add(oImg);
canvas.renderAll();
});
Here is how I am adding the pattern...
var textureIMG = new Image;
textureIMG.crossOrigin = "anonymous";
textureIMG.src = texture.image;
obj.setFill(); //For some reason, the fill doesn't happen without this line.
var pattern = new fabric.Pattern({
source: textureIMG,
repeat: 'repeat'
});
if (obj instanceof fabric.PathGroup) {
obj.getObjects().forEach(function(o) {
o.setFill(pattern);
});
} else {
obj.setFill(pattern);
}
canvas.renderAll();
Thanks in advance.
So I managed to figure this out. Each path within the path group is stored in the 'paths' array of the object.
I can now add a pattern to the top of the cylinder using...
var obj = canvas.getActiveObject();
obj.paths[0].fill = patternOne;
and to the sides using...
obj.paths[1].fill = patternTwo;

Cant quite nail scaling the game on mobile. Its not showing all of the game but only part of the game

this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.scale.pageAlignHorizontally = true;
this.scale.pageAlignVertically = true;
this.scale.refresh();
Its a tiny game code which I have uploaded on http://scaleissue.site44.com/ so pls use browser dev tools to have a look.
As you will notice when u go to dev tools and choose mobile emulation (iphone 4, 5, 6 - landscape orientation only), the screen only shows the top-left corner of the actual game with scroll bars when in fact it should have scaled the game such that all of the game was being shown on the screen since I used
this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
(you might have to reload page to notice this issue when in dev tools). I tried the game on real mobile and still the same issue.
All relevant scaling code is under boot.js
Please help as I cant quite nail the issue having tried several scaling modes.
You can try to resize the canvas:
var width=window.innerWidth,
height=window.innerHeight,
dpr=window.devicePixelRatio || 1;
var game = window.game[NAMESPACE].game = new Phaser.Game(1024, 480, Phaser.AUTO, 'gameDiv');
var mainState = {
preload : function () {
game.scale.scaleMode = Phaser.ScaleManager.RESIZE ;
//game.canvas.style.width=width+'px';
game.canvas.style.height=height+'px';
},
create : function () {
this.stage.backgroundColor = '#0000db';
},
update : function () {}
};
//initialising Phaser
game.state.add('main', mainState);
game.state.start('main');
The rationale behind this code: The canvas.width value (which is a number) sets the size of the game, while the canvas.style.width value (which is a string) sets the size of the canvas element. To avoid deformations you should maintain the same ratio (in your case, the ratio is 1024/480) in both values. If you set the ScaleManager as RESIZE then this ratio is maintained automatically, that's the reason why I'm only setting the height.

cocos2d js - Touch on overlay sprites that move up together

I used latest version cocos2d-js to create my game. On the game screen, I added multiple sprites overlay in a row, like this
Overlay sprites
I added an event listener to move up a sprite on y-axis when it was clicked. However, when I clicked on the point that any two sprites contain, the two sprites moved up together.
This is my event listener code
var listener = cc.EventListener.create({
event: cc.EventListener.TOUCH_ONE_BY_ONE,
swallowTouches: true,
onTouchBegan: function (touch, event) {
var target = event.getCurrentTarget();
var location = target.convertToNodeSpace(touch.getLocation());
var targetSize = target.getContentSize();
var targetRectangle = cc.rect(0, 0, targetSize.width, targetSize.height);
if (cc.rectContainsPoint(targetRectangle, location)){
target.setPositionY(50);
}
}
});
How can I prevent to move them up together and move only one sprite?
Thanks.
onTouchBegan must returns boolean value as result, if returns true it's means touch was handled and event cycle will be stopped. Try to return true, if rect contains point.
Hope this helps. And sorry for my English.

How to use Maki svg icons with Snap.svg?

I'm experimenting with Snap in order to use svg and need to be able to use the Maki icons defined in https://github.com/mapbox/maki.
My plan is to load the svg's I need, and then instantiate them for particular icons on a piece of Snap paper. But in order for this to work, I need to place the icon at a particular place on the paper, but I can't get translation to work. Neither one of the translation techniques below works; the code works as is, but always places the icon at the top left.
What am I missing? There's not enough documentation on Snap, and I don't know if the problem is with the way the Maki icon svg is defined, or my use of Snap.
var icon = Snap.load("maki/bicycle-24.svg", function(f) {
var g = f.select("g").clone();
// var g = f.select("#layer1").clone(); // also works
// g.transform("t120,120");
// var t = new Snap.Matrix();
// t.translate(120,120);
// g.transform(t);
paper.append(g);
});
The cloning needs to happen after the append, as when loading an svg in Snap its just a fragment.
So you will need to do something like...
paper.append(f);
var element = paper.select('#someId').clone();
element.transform( myTransform );
Thank you! That did the trick! And since Snap is so poorly documented, I'm going to insert the code here that allows a general solution.
// Base set from which markers are constructed
var iconSet = paper.group();
iconSet.attr({ class: 'hide' });
// Instantiations of icons
var markers = paper.g();
// Now, create SVG shape
var icon = Snap.load("maki/bicycle-24.svg", function(icon) {
// Add it to the icon set
iconSet.append(icon);
// Instantiate it and remove from main view
var element = paper.select('#svg4460'); // Copies it!
// var element = paper.select('#base'); // Selects something but doesn't work
// var element = paper.select('#layer1'); // Selects something but doesn't work
// var element = paper.select('#bicycle-24'); // Silent fail
element = element.clone();
element.remove();
// Clone this icon and move it
var t = new Snap.Matrix();
t.translate(10,120);
element.transform(t);
// Insert into main document view (markers)
markers.add(element);
});

Resources