Page 1 of 1

Enemy movement

Posted: Wed Jul 14, 2010 3:16 am
by PaperDuckyFTW
Im making a SDl platformer and atm im implimenting enemies.

So far it is in a class and I can spawn one onscreen which im happy about.
I can also make it move and collide with the tiles, which again im happy about.
What im not too happy about is how to make it have 'goomba' movement, as its not working

What I aim to do is have a 'enemy tile map', much like a tile map but instead creates a new enemy for each corresponding or respective number. So far I have it moving to the right, and when it collides with a wall tile what I want it to do is move in the opposite direction but I dont know how to do this.


Ive tried simple things like:

Code: Select all

x++;
if( ( collided_with_wall )&& (xvelocity greater then 0 ) )  //hit wall while moving right
{
     x - xvel;
     x--;
}
else
if ( collided with wall, and xvelocity less then 0 )  //hit wall while moving left
{
     x += xvel;
     x++;
}
Ive even tried just subtracting the velocity utthat didnt work. Does anyone know a solution?

Oh and how do I create the enemies from a enemy tile map? Better asked is how do I create more then one instance of the enemy? Im guessing its
new Enemy( x,y,variable); with the x and y variables being read from the map, btu when I tried it it didnt work. Ill try again but If you know thanks in advance

Re: Enemy movement

Posted: Wed Jul 14, 2010 3:25 am
by A Person
To switch directions just before you add the velocity to the position invert the velocity like so.

Code: Select all

velocity.x = -velocity.x;
velocity.y = -velocity.y;

Re: Enemy movement

Posted: Wed Jul 14, 2010 4:04 am
by X Abstract X
To add to what was already said, you seem to be modifying 'x' way more than you need to in your code. It does not matter what direction the monster is travelling when he collides, you simply multiply the velocity by -1.

Code: Select all

monster.x += monster.xVelocity;

if (collisionWithWall)
    monster.xVelocity = -monster.xVelocity;
To store your enemies, you might want to consider using some sort of container, like an std::vector.

Re: Enemy movement

Posted: Wed Jul 14, 2010 11:11 am
by wearymemory
X Abstract X wrote:To add to what was already said...
Perhaps it would be wiser in this situation to use absolute values:

Code: Select all

if (/* Colliding with the left wall. */) {
    deltaX = abs(deltaX);
}
if (/* Colliding with the right wall. */) {
    deltaX = -abs(deltaX);
}

...

x += deltaX;

Re: Enemy movement

Posted: Wed Jul 14, 2010 11:33 am
by A Person
Perhaps it would be wiser in this situation to use absolute values:
CODE: SELECT ALL
if (LeftCollides()) {
deltaX = abs(deltaX);
}
if (RightCollides()) {
deltaX = -abs(deltaX);
}

...

x += deltaX;
I'm pretty sure that would be unesscerary and may even cause a problem i would just stick to inverting the velocity :)

Re: Enemy movement

Posted: Wed Jul 14, 2010 12:47 pm
by wearymemory
A Person wrote: I'm pretty sure that would be unesscerary and may even cause a problem i would just stick to inverting the velocity :)
I believe it's adjunct, but not unnecessary. How do you suppose it could cause a problem? In effect, it's doing exactly what X Abstract X's code should do, but with the advantage of not getting stuck if the entity's overlapping distance was greater than its delta (or velocity).

Re: Enemy movement

Posted: Sat Jul 24, 2010 2:21 am
by PaperDuckyFTW
Thanks for all your posts, it might be easier to get help if i post the code which is bothering me

Code: Select all

//if its at edge of screen or collided with the top/bottom of tile
if( ( enemyCol.y < 0 ) || ( enemyCol.y + enemyCol.h > LEVEL_H ) || ( tile_collision( enemyCol ) ) )
	{
		enemyCol.y -= yVel; //stop moving down
		landed = true; 
		xVel = xVel; //make xvel a positive value
	}

//if enemys at left/right edge of screen or collided with left/right of tile
if( ( enemyCol.x < 0 ) || ( enemyCol.x + enemyCol.w > LEVEL_W) || ( tile_collision( enemyCol) ))
                {
		xVel = -xVel; //make xvel negative value
	}

	if( landed == true )
	{
                                //if we've landed, increase xpos by xvel
		enemyCol.x += xVel;
	}
So far it moves to the right and then when it collides with a tile, it moves back a few pixels, then moves right again, then back and forth. Some other methods are very similar to the current one, and all have the same result. Does this help you guys? It would be very appreciated if someone knew what im doing wrong. All i need it it to change direction when it collides with a tile

Re: Enemy movement

Posted: Sat Jul 24, 2010 4:36 am
by X Abstract X
First a few minor things I noticed.

xVel = xVel; //make xvel a positive value
That does nothing, you're just setting the variable equal to itself. If xVel is negative it will remain negative.

You also have:
enemyCol.y -= yVel //stop moving
That will work okay in some cases but could leave gaps in between your objects. Consider a case like this:
Player height = 10
A wall at height = 13
A player yVelocity of 7
Your player will be sitting at a height of 10 after the collision when the wall is at a height of 13.

Also, you don't need to be checking collision if the monster isn't changing position. Depending on how you have other things working, this could be causing a problem. It should be rearranged like this:

Code: Select all

if (landed) {
    enemyCol.x += xVel;

    if ( (enemyCol.x < 0) || (enemyCol.x + enemyCol.w > LEVEL_W) || (tile_collision(enemyCol )
        xVel = -xVel;
}

Re: Enemy movement

Posted: Sat Jul 24, 2010 9:45 am
by dandymcgee
X Abstract X wrote:First a few minor things I noticed.

Code: Select all

xVel = xVel; //make xvel a positive value
That does nothing, you're just setting the variable equal to itself. If xVel is negative it will remain negative.
Also:

Code: Select all

xVel = -xVel; //make xvel negative value
This will indeed negate xVel, but will not necessarily make it negative.

To make xVel positive (getting absolute value):

Code: Select all

#include <math.h>
abs(xVel);

//OR

//If xVel is less than zero negate it, otherwise let it be
xVel = (xVel < 0) ? -xVel : xVel;
To make xVel negative:

Code: Select all

//If xVel is greater than zero negate it, otherwise let it be
xVel = (xVel > 0) ? -xVel : xVel;

Re: Enemy movement

Posted: Tue Jul 27, 2010 3:25 am
by PaperDuckyFTW
ive tried all the ways you guys came up with but unfortunately nothing has worked. Im stumpt here as reading your posts made sence as to how it would work

Re: Enemy movement

Posted: Tue Jul 27, 2010 5:00 am
by X Abstract X
Pastebin the entire source if it isn't too big and you still need help.

Re: Enemy movement

Posted: Wed Jul 28, 2010 8:05 am
by PaperDuckyFTW
Thanks for your patience and help, and I hope this is what you means my post bin ^.^"
These are the relative codes:

Code: Select all

void Enemy::update_enemy()
{
	//set velocities
	yVel = 5;
	xVel = 1;

	//increase the y value (fall)
	enemyCol.y += yVel;

	//test to see if its landed
	bool landed = false;

	
	const int eFACE_LEFT = 0; //
	const int eFACE_RIGHT = 1;// Was testing another method
	int eFacing = eFACE_RIGHT;//

	if( xVel < 0 )
	{
		eFacing = eFACE_LEFT;
	}

	else if( xVel > 0 )
	{
		eFacing = eFACE_RIGHT;
	}

	

	//if collided with edge of screen or wall tile
	if( ( enemyCol.y < 0 ) || ( enemyCol.y + enemyCol.h > LEVEL_H ) || ( tile_collision( enemyCol ) ) )
	{
		//stop falling and allow enemy to move left/right
		enemyCol.y -= yVel;
		landed = true;	
		
	}

	
	//if we can move left/right
	if (landed) {
		//if we collided with wall, change direction
	    if ( (enemyCol.x < 0) || (enemyCol.x + enemyCol.w > LEVEL_W) || (tile_collision(enemyCol ) ) )
		    enemyCol.x = xVel -xVel;

		//move left/right
		enemyCol.x += xVel;
		}			
}

//then I have the enemy drawn after the player
luigi.update_player(); //move player
baddie.update_enemy(); //move enemy
If it would help and not be of too much inconvenience, I can upload the .exe and full source files.
Thanks if you can help and I hope it dont take too much of your time

Re: Enemy movement

Posted: Wed Jul 28, 2010 12:17 pm
by dandymcgee
This is what he meant by pastebin:
http://pastebin.com/wC8h421H ;)

Re: Enemy movement

Posted: Wed Jul 28, 2010 12:32 pm
by X Abstract X
You have the line:

Code: Select all

enemyCol.x = xVel - xVel;
That is equivalent to setting enemyCol.x to 0. I don't think that's what you want to do, you want to negate xVel instead. That line should be replaced with:

Code: Select all

xVel = -xVel;
You have another problem aswell. Each time you update you reset the velocities to be positive, that's no good. You should set the velocities once in the object's constructor or in an initialize() function that is called only ONCE (not in your game loop).

Re: Enemy movement

Posted: Wed Jul 28, 2010 7:12 pm
by PaperDuckyFTW
:worship: :worship: :worship: :worship: :worship: :worship: :worship:

Thankyou soo soo much. The problem was what you said, I was setting the velocity or position to 0 repetativly in the game loop. I did as you suggested, initialised it in the constructor and so it solved my issue.

Thankyou evryone who helped and I hope it wasnt time consuming lol
Now i learned another thing about game loops, which will help me when Im making a state machine