Handling collision in world but not in update()


(Dondudu) #1

Hello there, I currently have a tightly packed grid of entities as shown below

Here is a picture (add a .png to the link) http://puu.sh/iTQ5P/b9b7caf84a

Each block is an entity with type “node”. Each entity also has a boolean field called “traversable”. Every entity is marked traversable except the grey blocks.

I want to check if there is a straight line between the two red nodes that doesn’t intersect a grey block. My idea for doing this was to create an entity in the world, rapidly move it from the first red block to the second red block, and checking for collisions with "node"s. If a “node” is collided with, then a second check will be performed to see if that node is traversable. If a non-traversable node is detected, then there must be a grey block between the two red blocks.

function detectStraightLine(inputNodeA:Node, inputNodeB:Node):Boolean {
		
		// create two temporary nodes
		var nodeA:Node = new Node(inputNodeA.x, inputNodeA.y, 0, 0);
		var nodeB:Node = new Node(inputNodeB.x, inputNodeB.y, 0, 0);
		
		
		// move A towards B and check for collision with nodes
		while ((nodeA.x != nodeB.x) || (nodeA.y != nodeB.y)) {
		
			nodeA.moveTowards(nodeB.x, nodeB.y, 5);
					
			if (nodeA.collide("node", nodeA.x, nodeA.y)) {
				trace("collision detected");
				// check if collided node is traversable
				return false;
			}
		}
		trace("straight line found");
		return true;
	}

I have done tests and the function successfully moves nodeA every iteration of the while loop by 5 units downwards. However I am not detecting any collisions at all with this method. Am I doing something fundamentally wrong?


(Mike Evmm) #2

Have you looked into world.collideLine?


(Dondudu) #3

That only returns the first entity the line collides with, correct? I need something that returns all the entities I collide with in the straight line, so that I can check if any of them are non-traversable.


(Mike Evmm) #4

Are the transversal and non-transversal entities the same type?


(Dondudu) #5

Yes, they are both of class Node extends Entity, with type “node”.


(Martí Angelats i Ribera) #7

Probably the easiest way is to use two different types. You can check all of them by simply checking twice (exactly the same performance).


(Dondudu) #8

I will try this, thanks for the advice. Do you have any idea why I’m not getting any collisions here though? Can collide() only be called within update function or something? All my other collides are done through update() and they work as expected.


(Martí Angelats i Ribera) #9

Be sure you are testing the line at the center of both Entity (Node in your case) and not directly the x and y (which is the top-left corner).


(Dondudu) #10

In the function in the original post, the function creates an invisible node of width and height both = 32. In a while loop, it progressively moves the invisible node towards the target node and checks for collisions in every iteration of the while loop. I felt this was quite generous for checking collisions yet it still didn’t detect any at all.

Collidable property is true for all nodes. All nodes have the same height and width defined in the Node constructor, 32x32.

I tried changing the checking renaming the rock nodes into another type and checking for that instead, but that didn’t collide either.

Is there any other information required?


(Martí Angelats i Ribera) #11

It’s way simpler of what are you doing.

//MyWorld.as

if (collideRect("solid-node", entityA.x+16, entityA.y+16, entityB.x+16, entityB.y+16))
{
    //do something
}

The type "solid-node" ia an example. The +16 part is becouse is half their width/height.

BTW, in the image you made, it seems you are trying to make a path finding. If you are using a grid, there are better options and more efficient and reliable algoriths (at least if you are doing what i think).


(Mike Evmm) #12

I don’t think this is good advice for what he’s trying to achieve, since he wants to check whether a block in that position would collide.
It has just occurred to me though: @Dondudu, are your hitboxes for nodeA and nodeB set correctly?


(Martí Angelats i Ribera) #13

In the code he posted he was actually trying to maike a function which would do the same as the collideRect. He wants to test if he can go into an straight line. He makes a copy of the original nodes and move them to check it.


(Mike Evmm) #14

If he needs to use the copy nodes to use the moveTorwards function then there’s no reason to use collideRect instead if regular collide.
@Dondudu I see no reason your code wouldn’t trace a collision. Maybe someone else is of more help :pensive:


(Martí Angelats i Ribera) #15

My idea is to not use that function at all. Instead of using

if (detectStraightLine(nodeA, nodeB))
{
//do something
}

is to use

if (!collideRect("solid-node", nodeA.x+16, nodeA.y+16, nodeB.x+16, nodeB.y+16))
{
//do something
}

(Jacob Albano) #16

The reason your code doesn’t detect collisions is because neither of your temporary nodes are ever actually in the world, so any calls to collide() will return null early.

A better approach would be to store the position of inputNodeA and move that, then reset its position when you return.


(Dondudu) #17

@Copying I renamed the type field of my nodes to “solid-node” and tried your code and I still cannot detect a collision. I even tried to make the size of the collision rectangle very large (1000x1000) by modifying the last two arguments.

@jacobalbano I tried this and still no collision is detected.

For now I have given up detecting a straight line between two nodes and am trying to get simple collision detection working now as a precursor.

                // this is within a function within MyWorld

                // get two nodes
		var nodeA:Node = getNode(6, 1, listOfNodes);
		var nodeB:Node =  getNode(6, 2, listOfNodes);
		
		// set the position of nodeA to the position of nodeB
		nodeA.x = nodeB.x;
		nodeA.y = nodeB.y;
		
                // some traces to prove things are normal
		trace(nodeA.collidable, nodeB.collidable);
		trace(nodeA.width, nodeA.height);
		trace(nodeB.height, nodeB.height);
		
		if (nodeA.collide("node", nodeA.x,nodeA.y)) {
			trace("got collision");
		} else {
			trace("no collision");
		}

The output is

true true
32 32
32 32
no collision

So unfortunately I can’t get even get the most basic collision working for some reason.


(Jacob Albano) #18

Are you sure all the nodes have been added to the world? You can check with trace(nodeA.world != null). All entities that are going to have collision checks done on them have to be in the same world.

If the collision types of nodeA and nodeB are always identical, you can pass nodeA.type to your collide() calls; might avoid some typos (if you did change it to “solid-node” the above code won’t work anyway, since you’re checking for “node”).

There’s no fundamental reason why a collision check shouldn’t work in any function you call it from, and if nothing is working even with a huge hitbox there’s probably something else going on.


(Dondudu) #19

@jacobalbano Your suggestion to trace for the world determined that the nodes weren’t yet added to the world yet at the time. Turns out it was because I was calling this function from the constructor of the world, so of course the nodes were not yet added to the world :frowning: It now collides as expected. Thank you very much!

@Copying I didn’t mention this earlier but I will also need to do checks for straight lines between diagonal nodes, which colliderect wouldn’t be approriate for. I will probably go back to my original method of moving a node. Thanks anyway!