# Solving state machine problem for a centipede

This topic is 2153 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to write a centipede game clone, and I have written a node class which is basically a circle. I'm trying to write an FSM to simulate node movements and bouncing with bricks or the screen, but the problem, that the FSM conflicts with other conditions. How would I resolve it ? For example one of the nodes can be at x <0 but they have y > 800.

for (var i:int = 0; i < m_nodes.length; i++)
{

if (m_nodes[i].x > 750)
{
m_nodes[i].current_dir = Node.Direction_DOWN;

}
else if (m_nodes[i].x < 40 && m_nodes[i].y < 600)
{
if (!m_nodes[i].current_dir == Node.Direction_RIGHT)
{
m_nodes[i].current_dir = Node.Direction_UP;
trace("dir up");
}

}

if (m_nodes[i].hitTestObject(m_bricks[i]) )
{
trace("hit");
m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}

if (m_nodes[i].y < 40 && m_nodes[i].x < 40)
{
m_nodes[i].current_dir = Node.Direction_RIGHT;

}

else if (m_nodes[i].y > 560 && m_nodes[i].x > 40)
{
m_nodes[i].current_dir = Node.Direction_LEFT;
}

if (m_nodes[i].current_dir == Node.Direction_LEFT)
{
m_nodes[i].vx = -5;
m_nodes[i].vy = 0;
}

else if (m_nodes[i].current_dir == Node.Direction_DOWN)
{

m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}
else if (m_nodes[i].current_dir == Node.Direction_RIGHT)
{

m_nodes[i].vx = 5;
m_nodes[i].vy = 0;
}

if (m_nodes[i].current_dir == Node.Direction_UP)
{

m_nodes[i].vx = 0;
m_nodes[i].vy = -5;
}

m_nodes[i].x += m_nodes[i].vx;
m_nodes[i].y += m_nodes[i].vy;

}

##### Share on other sites

It looks like you are trying to make it move clockwise around your gamearea?

If you have only 4 directions, you cant walk out of the area on both axis during a single frame. Also, aren't all nodes required to follow the headnode? So you don't need to do this for every node.

I'd probably check if there is a wall at currentPosition+movement, if yes turn right.

This is AS3 code? This line looks funny:

if (!m_nodes[i].current_dir == Node.Direction_RIGHT)


##### Share on other sites

Yes, I wanted it to move clockwise.

It moves correctly, but the collision check,  doesn't work at all. it only works with the 4th node, I don't know why

hehe, yea, I was assuming that the check statement returns true, and not it !.

##### Share on other sites

if (m_nodes[i].hitTestObject(m_bricks[i]) )
{
trace("hit");
m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}


You check every node against a more or less random brick.

How about you put your whole level into a grid, and every element has a boolean value indicating if you can pass it or not. Now, only for your headnode you take its position in grid coordinates, add the direction it is going to and check the grid at this position. If it says there is a wall you change the direction. After that you do the actual walking. This way you can put walls around your level and don't need to check against those magic numbers.

##### Share on other sites

A couple of things seem suspect to me.

This line looks like it only checks 1 brick in the m_bricks array corresponding to the specific node? Shouldn't you loop over all the bricks to see if you hit any of them?

if (m_nodes[i].hitTestObject(m_bricks[i]) )

I'm not 100% sure what you want your code to do. You mention centipede clone, but then talk about a circle and moving around the screen counter clockwise. Can you describe what you want to happen in more detail?  Doing so might point out the flaw in your state machine.

For some simple centipede logic, it might look something like this. We have a horizontal direction, so we look ahead at the next position

• If my currentPosition is a block (can happen after moving down from a collision in a previous step) flip horizontal direction.
• If nextPosition is off the board or a block, flip horizontalDirection, and move down a row.

Typically when your state machine isn't covering a particular state, either you need more states, or you need to simplify your state machine.

- Eck

##### Share on other sites

Thank you guys.

@Eck,

You really touched the logical fault, which was checking just one brick over all the centipede segments.

Is my design of the centipede correct ? according to the original clone ? Which I mean, I loop over the nodes and change the direction of each one based on an event ?

Uff, I used my other account here that was 12 years old :/

Edited by AhmedSaleh

##### Share on other sites

I fixed it by that code:

for ( var b:int = 0; b < m_bricks.length; b++ )
{
if (m_nodes[i].hitTestObject(m_bricks[b]) )
{
trace("hit");
m_nodes[i].vx = 0;
m_nodes[i].vy = 5;
}
}

Just replaced that and kept the other state-machine events. However it works only for the first hit, but other hits, the actions which is reversing the direction, doesn't occur. really weird.

##### Share on other sites

Warning (A0001): Ahmed limit reached in thread, increase MAX_AHMEDS via thread options

##### Share on other sites

hehe Paradigm shifter, I had a very old account, and I thought I forgot its credentials, now I have a new one, but I like to keep the old account for memories, it was created on 2001 :).

##### Share on other sites

As is already mentioned by BloodyEpi above, controlling each segment independently doesn't reflect that subsequent segments follow the respective predecessor. So, if a obstacle disappears for some reason, the centipede may segregate into two unintentionally. To solve this, let each subsequent segment get the position of its predecessor and calculate a direction change only for the head. This has the additional advantage that collision tests need not be done for every segment. Assuming that segment with index 0 means the head, and segment with index i+1 is the directly subsequent segment to those with index i, this should work:

for(int idxSegment =m_nodes.length-1; idxSegment>0; --idxSegment) {
m_nodes[idxSegment].x = m_nodes[idxSegment-1].x;
m_nodes[idxSegment].y = m_nodes[idxSegment-1].y;
}
// now calculate new head position here


Notice that the loop is entered only if the length is at least 2, and that it excludes the head from being updated therein.

Well, there is possibly a caveat with that code above. It works well if the speed of motion is not greater than 1 segment per cell. If it is greater, say N segments per cell, then the first N-1 segments following the head need to be updated if the calculation for the new head position has caused a direction change.

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 16
• 9
• 15
• 9
• 11