Jump to content

Collision Without A Sprite?


Nebulocity
 Share

Recommended Posts

Is it possible to create boundaries that sprites can collide with, without actually giving those boundaries a sprite themselves?

My dilemma is that while I know what JSON is, I have never used it before.  I do not have "tiles" to use, so a tileset or tilemap are of little use to me.  What want to do is to have my player and baddies move through a maze, but not be able to walk through/over the walls in the maze.  The only thing that I can think of to do this would be, since the background image is technically a sprite, create a bunch of bounding boxes for each of the sprite walls.  But before going through this painstaking process, I wanted to see if someone else had a better idea (other than give up :huh: ).

It's an overhead style game, similar to the original Zelda game, and my monster movement code is listed below.  The problem that I'm afraid that I might have, is that I'm essentially "teleporting" the baddies to their new destination (moving 50 pixels every 3 seconds), instead of "walking" there.  Am I going about this all wrong?

	create: function () 	{		this.enemies = this.game.add.group();				for (var i = 0; i < 5; i++)		{			var enemy = this.enemies.create(150 + (100 * i), 50, 'enemy');			var lastXPos = enemy.x;			var lastYPos = enemy.y;		    enemy.animations.add('down', [0, 1], 7, true);		    enemy.animations.add('left', [2, 3], 7, true);		    enemy.animations.add('right', [4, 5], 7, true);		    enemy.animations.add('up', [6, 7], 7, true);		    enemy.animations.play('down');		    enemy.body.allowGravity = false;	    	enemy.body.collideWorldBounds = true;		}				clock = game.time.now + 3000;	},	update: function() 	{		if (game.time.now > clock) 		{			this.enemies.forEach(function(enemy)			{		 	var direction = Math.floor(Math.random() * (4 - 1 + 1) + 1);								if (direction == 1) 				{	// Move north					for (var i = 50; i != 0; i--) 					{						enemy.y -= 1;					}				} 				else if (direction == 2) 				{	// Move east					for (var i = 0; i < 50; i++) 					{						enemy.x += 1;					}				}				else if (direction == 3) 				{	// Move south					for (var i = 0; i < 50; i++) 					{						enemy.y += 1;					}				}				else if (direction == 4) 				{	// Move west					for (var i = 50; i != 0; i--) 					{						enemy.x -= 1;					}				}			});		}	}
Link to comment
Share on other sites

If you add in a sprite, with all the adding and loading etc but with the exception of giving it an image it is invisible. Add that sprite to a group and then add them in at the given X/Y and rotates needed to create the maze you require. Eg:

Var invisWall = game.add.sprite(100,100); you could then mess around with the size of each wall needed and add as you go within a group. There may be other ways to do this but not that I know of.

Link to comment
Share on other sites

Thank you for replying!  But without an actual sprite image, how do we tell it what size it's going to be?

 

var invisWall = game.add.sprite(100, 100);

 

Will create a sprite at the 100,100 location, but it has no size since I did not create it with an actual image, yes?  I assume that I would have to use something like creating new Point objects, but I'm not at home to try right now.  Something similar to this:

  
            Var invisWall = game.add.sprite(20, 5);
            inviswall.topLeft = new Point(20, 5);
            inviswall.topRight = new Point(780, 5):
            inviswall.bottomRight = new Point(780, 5);
            inviswall.bottomLeft = new Point(20, 45);

Link to comment
Share on other sites

you would have to tell the game how big it is. The reason i am now using this is for the floor of my game to which i have it as game.world.width.

That is its scale.x

You can set the size with scale.

Set it like so.

var invisWall = game.add.sprite(100, 100);invisWall.scale.x = game.world.width;

It will be as wide as the game world, after that just set the physics collision with the invisWall and you should be set to go.

 

Also try setting it to different sizes for the size you want it.  

Theres that or create an actual sprite with an image, set the sizes and rotates of the sprites and size, then set renderable = false; and that will also incur and invisible barrier but you can control your size a bit better and can debug better too. 

Using the none image approach can be a long process of trial and error for the size etc so try making a sprite not render instead.

Link to comment
Share on other sites

Oh ok.  I've attached an image of what my mazes will be similar to (I'm using this as a placeholder).  So for the walls 'inside' the maze, just set the X and Y scale to whatever the bottom-right corner is going to be (with the original placement position being the top left-corner, i.e. 100, 100)?  Cool!

Link to comment
Share on other sites

Heppell08,

 

Ok, I went back to re-arrange my code so that it was easier to read (it was all over the place, and just a mess).  The image that I uploaded previously was just a flat image, and those tree "walls" were just part of it - nothing there was a sprite that I had made at all.  So what I did was created a 32x32 sprite that was colored red, and then added that to the game as a wall, and scaled it to create an actual barrier that the player could not pass through.  I started to create more of these walls, placing them at the appropriate coordinates and with the appropriate scales, and then realized that I would have to do this for every map that I planned on making later on...

I went for a walk, and was wondering if it could be done differently, and this is what I was thinking.  I created a map that I was actually going to use (again, it's just an image, there are no objects on it other than the player and enemies).  Then, I opened it up in paint.net, and made a copy that basically had all of the "roads" cut out, so that the only thing left were magenta "walls".  I then loaded the original map, and then this "walls" map, into my Preload() function like this:

        game.load.image('map', 'images/BurritoMap.png');        game.load.image('walls', 'images/BurritoWalls.png');

Then, in my Create() function, I added the map and the walls as sprites (the walls after the map, so that it showed up on top of the map).  I set the wall to immovable, and was hoping that I'd be able to test for collisions this way, but it apparently doesn't work like this.  An interesting note, is that when I add wall.renderable = false; the player moves underneath the magenta "wall" map.  If I comment it out, the player moves on top of it.  Something to do with the way the images are layered, perhaps?

        game.add.sprite(0, 0, 'map');          wall = game.add.sprite(0,0,'walls');        wall.body.immovable = true;        // wall.renderable = false;

In my Update() function, I'm checking for collision between the player and the wall, but right now it's not working, and I'm wondering if you have an idea about why that is?  I only added player and wall to that because (as I understand it), each are references to sprites, so there's no need to add .sprite to them, right?  Either way, it's not working. 

game.physics.collide(player, wall);

I'll attach the files so that you (or anyone else) can see what I'm referring to with the map and walls images.

 

Link to comment
Share on other sites

The difference i see in your code is you are loading it in as the standard image. Nothing wrong in that but i load mine in as a group. So in my code i have this piece of code and it just works for me. 

platforms = game.add.group();	var ground = platforms.create(0, game.world.height - 64, 'ground');	ground.body.immovable = true;	ground.scale.x = game.world.width;        ground.renderable = false;

So i name the group platforms, then declare ground in the group and create. As for collisions:

game.physics.collide(player, platforms);

I just collide player with the group itself. Means you can add more barriers etc within the group. 

 

I also noticed you have 

var player, map, wall, enemies;

where i have:

var player;var map;var wall; var enemies;

Not sure if it makes a difference though.

 

But yeah, go for the group approach, it works for me.

Link to comment
Share on other sites

Thanks for replying again!  That's really odd, because I attempted to do it that way before, and it didn't work either.  That very same code is in the "first Phaser game" tutorial on the web site, and I tried to keep it similar (but change from a platformer to a "map style" game). 
 

        walls = game.add.group();        var wall = walls.create(0, 0, 'walls');        wall.body.immovable = true;        wall.renderable = true;

I was using game.physics.collide(player, walls); and nothing happened, so I changed it to call on my collision handler...

game.physics.collide(player, walls, collisionHandler, null, this);...    function collisionHandler() {        console.log(' Collision detected! ');    }

And nothing gets logged at all.  I guess there is no "easy" way to set up the walls, I'll just have to do them by hand like I was doing before.  "If it ain't broke..." right?  Ha!  Thanks for your help!

Link to comment
Share on other sites

also i mistyped something on that pastebin:

 

change this:

wallgroup - game.add.group();        wall = wallgroup.create(0,0,'walls');        wall.body.immovable = true;        wall.renderable = false

to this

wallgroup = game.add.group();        wall = wallgroup.create(0,0,'walls');        wall.body.immovable = true;        wall.renderable = false
Link to comment
Share on other sites

The image that has the pink in it, that's just a copy of the actual map itself, but I cut out the roads so that everything is transparent except the pink.  As in, when  the pink image is overlayed on top of the map image, i only want the player/enemy sprites to be able to walk where there is no pink.  Or am I thinking about this backwards?  I assumed it would act like some kind of masking effect.

 

I'm not actually using any Phaser functions or JavaScript to do anything to the pink image, though.  I just assumed that since that was a sprite, and the non-pink area was transparent, that other sprites in the game (enemies and the player) would not be able to move over them if a collision was detected.  I made 3 walls "manually" (using a 32x32 sprite, and scaling it to cover the area that I didn't want the player to be able to walk past) and it worked that way.  But it was going to take a lot of time manually estimating pixel location, adjusting it to fit, etc, so I figured I'd try it this way.
 

Your code didn't do anything different as far as how things interact.  The player sprite, when I try to move over the pink areas, just goes "under" them (like the pink sprite is a layer on top of the layer that the player is on, or something to that effect).  Still no collisions detected, etc. 
 

post-5969-0-79093200-1390742942.jpg

Link to comment
Share on other sites

So, something interesting just happened.  I changed my code from this:

game.load.image('walls', 'images/BurritoWalls.png');

to this:

game.load.image('walls', 'images/wallblock.png');

Where "wallblock.png" is just a 32x32 pink square.  I ran the game as-is, with only that adjustment, and it predictably put it at 0,0 in the top left corner of the screen.  I sent my player sprite over to bump into it...and it was solid...how weird.  So perhaps with the BurritoWalls.png sprite, that sprite is actually overlapping everything, and thus can't be collided with, because it's on top (which is why the player sprite can move underneath it).  Interesting!

I wonder if there's a way to do sprite masks in Phaser?  Quick, to the documentation, I go!
 

post-5969-0-30466300-1390743442.jpg

Link to comment
Share on other sites

Hmm that's strange then. I assumed it would work with the pink being technically visible as shown in your image. Maybe the 32x32 scaling option is how you should do it. Although this is your method, tiles also are good for colliding. I don't use tiles yet as I'm waiting 1.1.4 but if your scaling it working but taking time then maybe that's the only option. I'm just surprised at the pink wall not being able to collide. Theoretically it should I'd have assumed. I'll have another look at the image and collisions later and see what works for me and let you know how it goes.

Link to comment
Share on other sites

Thanks!

Speaking of tiles, I was poking around in the examples (since neither the examples or documentation seems to have anything on sprite masks), and found an example for loading tilemap data from JSON.
http://www.gametest.mobi/phaser/examples/_site/view_full.html?d=loader&f=load+tilemap+json.js&t=load%20tilemap%20json

 

I've never used JSON, as I'm not very savvy with JavaScript...I mainly work in C# and SQL back-end code and let the web developers in my officer deal with JSON, jQuery, etc, although I've been trying to learn it. 

 

Following the example, I came up with:

function preload(){           game.load.tilemap('mapData', 'js/BurritoMap.json', null, Phaser.Tilemap.TILED_JSON);           game.load.tileset('tiles', 'images/PathAndObjects_0.png', 32, 32);}function create(){            game.stage.backgroundColor = '#787878';            map = game.add.tilemap('mapData');            tileset = game.add.tileset('tiles');            layer = game.add.tilemapLayer(0, 0, 800, 600, tileset, map, 0);}

And wouldn't you believe it...the darned thing is now telling me that

  1. Uncaught ReferenceError: Phaser is not defined index.html:17
    1. (anonymous function)index.html:17

throwing an error at

var game = new Phaser.Game(800, 608, Phaser.AUTO, '', { preload: preload, create: create, update: update });

I'm pretty sure I'm pointing at it the right way in the JSON file that Tiled vomited out:
 

"properties":    {    }, "tileheight":32, "tilesets":[        {         "firstgid":1,         "image":"js\/PathAndObjects_0.png",         "imageheight":512,         "imagewidth":512,         "margin":0,         "name":"PathAndObjects_0",         "properties":            {            },         "spacing":0,         "tileheight":32,         "tilewidth":32,         "transparentcolor":"#ff00ff"        }], "tilewidth":32, "version":1, "width":25

It's 7am here, so I'm going to get myself some coffee and start the day off and mull it over.  The tilemap issues might be a different post to make entirely.

Link to comment
Share on other sites

In 1.1.4 the tile stuff is getting massively changed up and improved. The syntax is changing and they way they are used is changing too so I'm waiting for it to finish testing and hit master branch. As for you JSON issue, I've no idea on that either, I only use JSON for character animations. I haven't touched tile coding as of yet since I'm waiting until 1.1.4 :)

Link to comment
Share on other sites

Oh that's cool.  Character animations from JSON data?  How would that work, you pass certain animation sequences through as frame numbers, and then display those frames?  (Sorry if I'm asking too much, that just sounds very unique).  Then again, I've only ever created one game, and that was an RPG back in QBASIC in 1994...and the most complicated thing about that was creating "tiles" as just command-line "art" (lines, pixel-by-pixel coloring) stored in an array, lol.

Link to comment
Share on other sites

Just to put this out there, this is how I solved my problem with collisions.

I created a 32x32 pink tile, and placed that in the game as a "wall", and tried colliding the player against it (as mentioned above).  It worked, so I then shrunk that 32x32 tile down to a 1x1 pixel block, and placed it in the various corners on my map.  Then I used .scale.setTo(x,y) to scale the 1 pixel "wall" to the size I needed it.  For instance, for a horizontal "wall", I called .scale.setTo(500,1) to stretch it by 500% horizontally, but keep it 1 pixel in height.  Rather than blocking off entire areas of the map that can't be walked on (the grassy areas), I just created small lines that can't be passed.  There are gaps between some lines, but the player cannot move past them in any case, because the player sprite is too large.

You can view the example at: https://googledrive.com/host/0B6wdb6jvGmN6d0pqck9GNWpRNGs/index.html

 

Link to comment
Share on other sites

If you look up TexturePacker it creates sheets from sprites. Then when you add the JSON in just name than animation and it runs it. I have mine for walking in one direction and use scale x *=-1; to flip the image :)

:: whoosh ::

That was the sound of me not understanding a thing you said (other than flip, because that was easy, lol). Is this the same thing in the "shared sprite textures" example? If so....what are "atlases", and how do you even make JSON data for a sprite like that example did?

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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