Solving state machine problem for a centipede

Started by
30 comments, last by haegarr 10 years, 4 months ago

In the Centipede arcade game the centipede could split in half; that happened if you shot it in the middle.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
Advertisement

In the Centipede arcade game the centipede could split in half; that happened if you shot it in the middle.

Yep, but that simply creates a 2nd instance, and the segments still follow their respective head.

However, the problem I hinted at can also be identified when looking at the video: The blocking parts are removed when hit by a couple of bullets. Now assume this situation: The centipede's head collides with a blocking part and changes direction. The player shoots, hits those blocking part, and it is removed just before the centipede's tail has reached the cell where the blocking part was formerly. Now, only looking at the current segment, it is not blocked from moving further its current direction. Hence the centipede gets split just because you shoot at a block.

This would be avoided if the segments follow their predecessor. If the centipede is split, then another instance with its own head is created, and behaves independently but analogous to its originator.

You can get following behaviour without knowing about the rest of the segments, as long as they start off in a line next to each other all going the same way and follow the same rules (and you do the movement from the head section first, so segments don't collide with each other).

The rules are:

Hit a mushroom: move down 1 block and flip horizontal direction vector. You don't do any collision with mushrooms for the move down step (so you can land in a mushroom, you can see that happening in the video).

Hit a poison mushroom: move down 1 block each tick until bottom of screen is hit then continue moving horizontally

If you move down a block you skip the moving horizontal step this tick.

Once you get off the bottom of the screen the centipede starts moving upwards for a few blocks as well (would have to check exactly what happens there).

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

@paradigm

Can you tell me what do you mean by move down 1 block ? should I make the game as tile maps ? or you mean just move an amount of pixels ?

In Centipede the graphics were tile based, are we talking about the same game (see video I posted)? You can have transitions from one tile to the next to make it look smoother but it is essentially a tile based game.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Thanks,

I'm trying to have a better way for controlling the directions of the segments.

so I added those xdir, ydir, initialized to 1,1. I don't know how to set a flexible directions.


if (m_nodes[i].x > 750){
m_nodes[i].ydir = 1;
m_nodes[i].xdir = 0;


} 

in game loop



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

any idea please ?

It is usual to compute the velocity as product of absolute speed (a scalar) and movement direction (a unit vector). The speed is further constant for the centipede, i.e. all segments move with the same speed. Assuming a time step of 1, the snippet would hence look like so:


m_nodes[i].x += m_speed * m_nodes[i].xdir;
m_nodes[i].y += m_speed * m_nodes[i].ydir;

Your former approach used the product of speed and direction (often termed "velocity") directly. As mentioned above, the movement direction should be a vector with unit length, so that the absolute value of the velocity vector is just the speed.

With the movement direction available as vector (xdir, ydir) you can implement some of the rules -- frankly provided by Paradigm Shifter in one of the posts above -- by formulas. I am not familiar with the rules, so I don't know how to react on special cases like what happens if after a downward step is taken the queued sidestep is blocked. So take the following as hints.

As mentioned in the ruleset, movement is changed on reason only. The reasons are collision with a mushroom or a border. The reaction is always to take a downward step. This is easily be implemented by setting the new direction:


if( collisionMushRoom || collisionLeftBorder || collisionRightBorder ) {
    m_nodes[i].xdir = 0;
    m_nodes[i].ydir = 1;
}

But the following movement has to be the inverse of the former one. This can be handled if the former direction is memorized or, probably better, the next direction is memorized. The formerly memorized direction is used as the current direction.


m_nodes[i].xdir = m_nodes[i].xdir_memo;
m_nodes[i].ydir = m_nodes[i].ydir_memo;

if( collisionMushRoom() || collisionLeftBorder() || collisionRightBorder() ) {
    m_nodes[i].xdir_memo = -m_nodes[i].xdir_memo;
    m_nodes[i].ydir_memo = 0;
    m_nodes[i].xdir = 0;
    m_nodes[i].ydir = 1;
}

Let's assume that the memorized direction is sideways to the right. The collision lookahead does not detect a collision. So the condition body is not entered and the centipede steps to the right. Next iteration ... the memorized direction is still to the right. Now let a mushroom block this step. The condition computes to true, the memorized direction is set to left, but the actual current direction is overridden to downward. Next iteration ... current direction is set to the left. Let's assume another mushroom there. The condition becomes true, the next direction is set to right, the current to downwards. Next iteration ... the way to the right is free, nothing special happens, the centipede steps to the right.

Some notices: The above scheme could be implemented using logical directions LEFT, RIGHT, DOWNWARD as well, so changing to (xdir, ydir) wasn't strictly necessary at this point. The above is, of course, not enough. You have to consider collisions with the floor as well as with poison mushrooms and, not to forget, the player's avatar. It may happen that the conditions need to be flagged with whether the current direction is sideways or else downwards...

You could get away with not storing a memo for the x direction, just negate it after every collision, but have a rule whereby y movement takes precedence (so if there is a y component of your velocity, ignore the x component until the next tick). You still need a poisoned flag (where you keep moving downwards every tick until you reach the bottom of the screen).

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

I found a problem with the above approach ( looping thru all nodes and check if a node collided with a mushroom), which is they are seperated, and if they collided, some times, they get glitches, and all the nodes get their own movement, and like all the nodes are distorted and they are randomly moving.

The problem is the other nodes should really follow the head, correct ?

How is it possible to let each node move down one and reverse the velocity ? and all of them should be synchronized ?



for each node
{for (var b:int = 0; b < m_bricks.length - 1; b++)
{


if (m_nodes[i].hitTestObject(m_bricks[b]))
{
trace("hit");


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




m_nodes[i].vx = m_nodes[i].previousDirX*-1;
m_nodes[i].vy = 0;


}


}

}

This topic is closed to new replies.

Advertisement