Jump to content

Raycasting help


ekstrakt
 Share

Recommended Posts

Hi all,

 

 

Having started with Phaser a few days ago, I can't find any example or documentation about raycasting.

 

So, to explain what I'm after:

For a simple platformer, I have a character that's shooting at enemies. But, I don't want the bullets to be objects (sprites), because of the fast speed (the collision check might fail).

So I thought about using raycasting, and have the first enemy in the line of sight take damage. Or, in some case, every enemy in the line of sight (until a specific tile is hit, the end of the world is reached, or a specific distance).

 

The ray is always horizontal, so that should help a bit.

Also, the ray might not pass through the sprites center, as some sprites are larger, some smaller, or the enemy is moving up/down/jumping.

 

I checked the "Tilemap Ray Cast" example, which is exactly what I'm trying to achieve, but it works with tiles, and I need it to work with objects (sprites).

From the source code, http://docs.phaser.io/TilemapLayer.js.html#sunlight-1-line-384 , it loops through all the tiles and checks every coordinate.

 

Taking reference from TilemapLayer.getRayCastTiles, I managed to get it correctly using this code:

rayPoints = ray.coordinatesOnLine(15); //15 is because enemy sprites are 16px widefor(var i=0; i<enemies.length; i++){  if(enemies[i].inCamera && spriteContainsPoint(enemies[i]) ){    enemies[i].tint=0x00ff00;  }else{    enemies[i].tint=0xffffff;  }}function spriteContainsPoint(){    //function which checks if the coordinate is inside the body of the sprite}

but I feel it is quite inneficient, as it loops through every enemy sprite and checks if it is inCamera and it's bounds.

 

 

 

A more efficient way would be the other way around: check if there is a sprite at a given coordinate:

rayPoints = ray.coordinatesOnLine(15);  //15 is because enemy sprites are 16px widefor(var i=0; i<rayPoints.length; i++){  checkForSpritesAtPoint(rayPoints[i][0], rayPoints[i][1]);}function checkForSpritesAtPoint(x, y){  //return array of sprites at given point, without looping through all}

This way I will also get the enemy sprites ordered by distance (closest to furthest).

Can this be achieved (layers, physics, magic ...)?

 

 

So, in short, what I need is a way to get every sprite that a line passes through, sorted by distance to the player (without checking all the enemies in the world, and every pixel they occupy).

Any ideas?

 

Link to comment
Share on other sites

This example probably has everything you need: http://gamemechanicexplorer.com/#raycasting-1

 

 

I forgot to mention that I read this, and also find it inefficient, as it loops through all the walls and creates 4 lines for checking, on every frame.

 

 

 

As I said in my post, I'm looking for more efficient way (is there a sprite at a point, without looping throught all).

Link to comment
Share on other sites

I guess given your specific needs, a more efficient way may be to create a temporary invisible collision body that goes from the player to the edge of the realistic range of the weapon. Then when testing overlap on that against enemies, for each overlapping enemy, do a tilemap raycast to each one to work out if it can be seen past the obstacles.

 

There are probably cleverer ways still, but you can spend weeks on this for marginal gains in performance - the overlap and ray casts are fast enough to be used in realtime, so using them only once whenever the player fires seems to me to be plenty efficient enough.

Link to comment
Share on other sites

  • 1 year later...

OK - I'm kind of curious how to do the point is in the sprite check.  I'm using P2 physics, and I'm stumped.  I've essentially got basic LOS working, but I have non-rectangular sprites which can provide cover.  I'm trying to see if the line intersects with the cover providing sprite and I get nothing but false positives.

 

The main thing I've tried is game.physics.p2.hitTest(point, spriteGroup.children) and it returns all the sprites as hit which makes no sense.

 

Am I missing something obvious?

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

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