Jump to content
  • Advertisement
Sign in to follow this  
FantasyVI

walking enemy - better algorithm sfml c++

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everyone

ok so I really don't know if you can call this an algorithm or not. please do let me know if this is an algorithm.
anyways I have been working for the past hour on a way to make an enemy (just an image :D) to move in a square way, and its working fine but i feel that its not as clean as it can be and i think there is a better way to do it but i don't know any better way to do this.

so what this algorithm or code will do is the following:-

1- make the image move 50 pixel on the x axis (move right). coordinates are (50,0)
2- when the image rech 50 pixel on the x axis it stops and then move 50 pixel on the y axis ( move down). coordinates are (50,50)
3- when the image rech 50 pixel on y axis it stops and then move -50 pixel on x axis (move left). coordinates are (0,50)
4- when the image rech 0 pixel on x it stops and move -50 pixel on the y axis (move up). coordinates are (0,0)
5- do the same in a loop.

so guys is there a better and cleaner way to do this?



#include "move.h"

move::move()
{
dirtimage.LoadFromFile("dirt.png");
dirtsprite.SetPosition(0,0);
Stop1=false;
Stop2=false;
Stop3=false;
}

void move::drawmap(sf::RenderWindow &window)
{
float ElapsedTime = window.GetFrameTime();
dirstprite.SetImage(dirtimage);

int posX = dirtsprite.GetPosition().x;
int posY = dirtsprite.GetPosition().y;

int Speed = 10;

int Up = -10;
int Down = 10;
int Right = 10;
int Left = -10;



if(posX <= 50 && Stop1==false)
dirtsprite.Move(Right * ElapsedTime * Speed, 0); // go right


if(posX >=50)
{
dirtsprite.Move(-(Right * ElapsedTime * Speed), 0); // stop going right

dirtsprite.Move( 0, Down * ElapsedTime * Speed); //go down
}

if(posY >=50)
{
dirtsprite.Move( 0, -(Down * ElapsedTime * Speed)); // stop going down
Stop1=true;
}

if(Stop1 == true)
dirtsprite.Move( Left * ElapsedTime * Speed, 0); //go left

if(posX == 0 && Stop1 == true)
{
dirtsprite.Move( -(Left * ElapsedTime * Speed), 0); //stop go left
Stop2 = true;
}

if(posX == 0 && Stop2==true)
dirtstprite.Move( 0, Up * ElapsedTime * Speed); // go Up

if(posX == 0 && posY == 0 )
{
dirtsprite.Move( 0, -(Up * ElapsedTime * Speed)); // stop go Up
Stop1 = false;
}


window.Draw(dirstsprite);

}

Share this post


Link to post
Share on other sites
Advertisement
There's nothing really "wrong" with what you have, but a large constraint to your enemy's AI is that it's entirely hardcoded in its logic. A better algorithm that would be more flexible would be to create a node based path that the enemy will take and repeat. The enemy would move toward the next node regardless of its current position, then continue to the next one once it reaches its destination.

The nodes in your case would be the four points (X,Y) of the square. Store the nodes in a dynamic container and you gain the flexibility to add or remove nodes on the fly. If the enemy ever gets off its path such as it chased the player, it could resume back on its path when instructed to since it's not hardcoded (and assuming there isn't anything obstructing its path).

Another important benefit to using something more flexible is that the system you write that moves the enemy could be reused for other enemies or new levels.

Share this post


Link to post
Share on other sites

There's nothing really "wrong" with what you have, but a large constraint to your enemy's AI is that it's entirely hardcoded in its logic. A better algorithm that would be more flexible would be to create a node based path that the enemy will take and repeat. The enemy would move toward the next node regardless of its current position, then continue to the next one once it reaches its destination.

The nodes in your case would be the four points (X,Y) of the square. Store the nodes in a dynamic container and you gain the flexibility to add or remove nodes on the fly. If the enemy ever gets off its path such as it chased the player, it could resume back on its path when instructed to since it's not hardcoded (and assuming there isn't anything obstructing its path).

Another important benefit to using something more flexible is that the system you write that moves the enemy could be reused for other enemies or new levels.


i tried to do this but really don't know how to do it. i found a tutorial that does exactly what i want it to do but its in Flash.

http://www.emanueleferonato.com/2007/10/06/make-a-flash-game-like-flash-element-tower-defense-part-1/

he does it like this

waypoint_x = new Array(40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420); waypoint_y = new Array(140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20);


i tried to do it in c++ but i just couldn't. if you could help me that would be amazing.
thank you.

Share this post


Link to post
Share on other sites


http://www.emanuelef...defense-part-1/

he does it like this

waypoint_x = new Array(40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420); waypoint_y = new Array(140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20);


i tried to do it in c++ but i just couldn't. if you could help me that would be amazing.
thank you.

in C++ you'd use something along the lines of:

const size_t kPathPoints = 11; //helps keep x & y pairs matched
const int waypoint_x[kPathPoints] = {40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420};
const int waypoint_y[kPathPoints] = {140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20};


Share this post


Link to post
Share on other sites

[quote name='FantasyVI' timestamp='1320091936' post='4878985']
http://www.emanuelef...defense-part-1/

he does it like this

waypoint_x = new Array(40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420); waypoint_y = new Array(140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20);


i tried to do it in c++ but i just couldn't. if you could help me that would be amazing.
thank you.

in C++ you'd use something along the lines of:

const size_t kPathPoints = 11; //helps keep x & y pairs matched
const int waypoint_x[kPathPoints] = {40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420};
const int waypoint_y[kPathPoints] = {140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20};



[/quote]

thank for the replay.

but yes doing this is easy

const int waypoint_x[kPathPoints] = {40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420};
const int waypoint_y[kPathPoints] = {140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20};


but what i meant is how can i make it move to these points. If i use sprite.setposition(40,140) the image postion will change to that place but not move there(or walk you know).
however if i use
sprite.move(40,140)
this will only offset it position and make it keep moving by offeset of (40,140).

my question is how can i make to move to that position and stop there?
and yes i know that my code already does that but there should be some kind of clean way to do it like using this array.


const int waypoint_x[kPathPoints] = {40, 140, 140, 220, 220, 80, 80, 340, 340, 420, 420};
const int waypoint_y[kPathPoints] = {140, 140, 60, 60, 240, 240, 320, 320, 100, 100, -20};


Share this post


Link to post
Share on other sites
The waypoint list gives the list of points to walk to. At any given point in time, the entity will have an array index variable indicating the current waypoint to walk to, call it waypointIndex or somesuch. When the entity needs to take a step it can do so by:


wpX = waypoint_x[waypointIndex];
wpY = waypoint_y[waypointIndex];

// Calculate direction vector
float vx = (float)wpX - (float)self->X;
float vy = (float)wpY - (float)self->Y;

// Normalize direction vector to unit length
float len = sqrt(vx*vx + vy*vy);
vx /= len;
vy /= len;

// Apply movement vector to move
self->X += vx * self->Speed * elapsedTime;
self->Y += vy * self->Speed * elapsedTime;


The entity can check to see if it has arrived at the waypoint by:


wpX = waypoint_x[waypointIndex];
wpY = waypoint_y[waypointIndex];

float vx = wpX - self->X;
float vy = wpY - self->Y;
float len = sqrt(vx*vx + vy*vy);

if (len < proximityLimit)
{
// Close enough, entity has arrived
return ENTITY_HAS_ARRIVED;
}


This code checks to see if the entity is within some specified distance (called here proximityLimit) of the destination waypoint. When dealing with floating-point vectors for movement, it is a bad idea to try to test if the entity has arrived by using == comparisons, since it is possible that they will fail due to slight over-stepping, and the entity will either just keep walking or will walk back and forth in a tiny area centered on the waypoint, vainly trying to reach it exactly, depending on if you cache your (vx,vy) vector or recalculate it every time.

This logic also does not include path-finding, which can complicate the process a tiny bit. Rather than just calculate a straight vector to the waypoint, the pathfinding-based solution will feed the entity position and waypoint location to the path-finder to obtain a path to follow. This path to follow may itself be a simple list of locations (mini-waypoints) which could be followed in the exact way described above, by calculating straight-line movement vectors.

Share this post


Link to post
Share on other sites
@[color=#CB021A]JTippetts

thank you very very much for taking the time to read my post and help me with my code, i really appreciate it.
I'm experiencing a small problem with the new code. i did this


int i=0;
float wpX = waypoint_x;
float wpY = waypoint_y;


because if i try to do this instead


float wpX = waypoint_x[waypointIndex];
float wpY = waypoint_y[waypointIndex];


i get a runtime error saying that i did not initialize waypoint_x and waypoint_y.
the problem i'm having is that ( i ) is starting from 1, not 0 and when it increment it go to 3 instead of 2. so the sprite move 64pixel up and then 64pixel down. what it should do is to move 64pixel to the right then down then left then up.

here is the full code

#include "Enemy.h"

Enemy::Enemy(void)
{
EnemyImage.LoadFromFile("Images/enemy.png");
EnemyImage.CreateMaskFromColor(sf::Color(255,255,255));
EnemySprite.SetPosition(0,0);

Stop1=false;
Stop2=false;
Stop3=false;
i=0;
}

Enemy::~Enemy(void)
{
}

void Enemy::Movment(sf::RenderWindow &window)
{
float ElapsedTime = window.GetFrameTime();
EnemySprite.SetImage(EnemyImage);

float X = EnemySprite.GetPosition().x;
float Y = EnemySprite.GetPosition().y;

int Speed = 50;

int const waypointIndex=4;
const float waypoint_x[waypointIndex] = {64, 0, -64, 0};
const float waypoint_y[waypointIndex] = {0, 64, 0, -64};


// Calculate direction vector
float wpX = waypoint_x;
float wpY = waypoint_y;


// Calculate direction vector
float vx = (float)wpX - (float)X;
float vy = (float)wpY - (float)Y;


// Normalize direction vector to unit length
float len = sqrt(vx*vx + vy*vy);
vx /= len;
vy /= len;

// Apply movement vector to move
X += vx * Speed * ElapsedTime;
Y += vy * Speed * ElapsedTime;

EnemySprite.SetPosition(X, Y); // go right

checking();
window.Draw(EnemySprite);
}

void Enemy::checking()
{
float X = EnemySprite.GetPosition().x;
float Y = EnemySprite.GetPosition().y;

int const waypointIndex=4;
const float waypoint_x[waypointIndex] = {64, 0, -64, 0};
const float waypoint_y[waypointIndex] = {0, 64, 0, -64};

float wpX = waypoint_x;
float wpY = waypoint_y[0];

float vx = wpX - X;
float vy = wpY - Y;
float len = sqrt(vx*vx + vy*vy);

float proximityLimit = 60;

if (len > proximityLimit)
{
i++;
if(i>=4)
i=0;
std::cout<<i;
}
}


I'm really sorry if i sound like I'm not trying to fix my own errors but i'm, I really am. I spent two hour trying to fix it but i just couldn't.
ironically i want to be a game programer but i'm not really good in physics and math.

i'm really sorry for being such a newbie.

Share this post


Link to post
Share on other sites

float wpX = waypoint_x;
float wpY = waypoint_y[0];


This looks like a bug in your posted code. You index waypoint_x using i, but you only index waypoint_y with 0, so you will always get a value of 0 for wpY.

And of course you'll get an error trying to do wpX = waypoint_x[waypointIndex] because earlier you set waypointIndex equal to 4 for the array initialization, and trying to index an array of length 4 with the index 4 results in an array out of bounds.

Share this post


Link to post
Share on other sites
Your code would more robust if you had a 2D vector holding your (x,y) coordinates.The way-point system of moving objects around is great, however on its own it suffers from 2 major limitation. Without proper collision checking the object can and will move through walls. Also, even with collision checking if a way point draws a path through a wall, the object will never reach its destination, collision checking will keep it at the wall and it will never reach the next way point. What you need is A* Pathing algorithm to set intermediate way-points for you dynamically. Its a bit too much to explain here so I will link you, You already have half the work done because A*uses a way-point system.

http://www.policyalmanac.org/games/aStarTutorial.htm


gLhf

Share this post


Link to post
Share on other sites
I thnk a big question here is.. can this enemy ever be knocked off its path? If not, then there's no concern about it needing intelligence to path around walls.

please be sure you define the limits of what this sprite is to do.. Our tendencies around here are to sometimes set you down the path of creating First person shooter enemies capable of hopping small hurdles, work in teams and patha round a graph representation of the game world....

Concise definition of what the character is supposed to do will allow you to implement systems that are useful.

The original post makes me believe it's simply an enemy that walks. like old enemies in Mario that didn't care where Mario went, they just did their pathing and if he hit them, he got hurt.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!