[media]
[/media]
The problem I am trying to solve is that I want many (30+) enemies to track the player's location and react accordingly when the player is in line of sight (for example, fire at the player). Therefore the alorithm needs to be quite efficent. Currently what I am doing is making a sprite at the enemy's location, then fire it towards the player's location. As the sprite moves, it samples it's current location to check if it has either collided with an obsticle (where the method returns false) or it's target (returning true). In the video, the points at which the sprite is sampling is represented by yellow dots.
I am wanting to then ask two questions: is there a more efficient way of working out line of sight? Also, if someone could check my maths that would be extreemly helpful. The tracers dont seem to hit the player's center always so I know Im calculating something wrong.
Thanks for any help you can give, Im probably getting into stuff way too complex for me. This is in fact my first game and first C++ program. Yet I still need to go on to figure out how to do A* Jump point search! Argh!
The code for working out LOS is below:
#include "stdafx.h"
#include "Pathfinder.h"
#include "Game.h"
#define PI 3.14159265
//Returns true if target is in line of sight
bool Pathfinder::LineOfSight(float startx, float starty, float endx, float endy)
{
//Load tracer image
if(!_isLoaded)
Load("images/tracer.png");
_tracer.SetPosition(startx, starty);
//Get the angle between the start and end point
float angle = GetAngle(startx, starty, endx, endy);
//Calculate movement in x y coords depending on rotation
float xvel = 1;
float yvel = 1;
if(angle >= 0 && angle < 90) //q1
{
xvel = (angle/90);
yvel = 1 - (angle/90);
}
if(angle >= 90 && angle < 180) //q2
{
xvel = 1 - ((angle - 90)/90);
yvel = 0 - ((angle - 90)/90);
}
else if(angle >= 180 && angle < 270) //q3
{
xvel = 0 - ((angle - 180)/90);
yvel = ((angle - 180)/90) - 1;
}
else if (angle >= 270 && angle < 360) //q4
{
xvel = ((angle - 270)/90) - 1;
yvel = ((angle - 270)/90);
}
float increment = 15; //Distance traveled before sampling
float error = 10; //Max error when targeting end point
//While tracer is not at goal
while(((_tracer.GetPosition().x < endx - error) ||
(_tracer.GetPosition().x > endx + error)) &&
((_tracer.GetPosition().y < endy - error) ||
(_tracer.GetPosition().y > endy + error)))
{
//Move the tracer to next sampling point
_tracer.Move(xvel*(increment), yvel*(increment));
if(_isLoaded) //Draw tracer at this location
Game::GetWindow().Draw(_tracer);
//Check if the tracer collides with a impassable
//object on the tilemap
if(Game::GetGOM().GetTileMap()->Collision(_tracer.GetPosition()))
{
return false;
}
}
return true;
}
//Get angle between two points
float Pathfinder::GetAngle(float startx, float starty, float endx, float endy)
{
float mX = endx;
float mY = endy;
mX = mX - startx;
mY = mY - starty;
return atan2(-mY,mX) * (180 / PI) + 90;
}
void Pathfinder::Load(std::string filename)
{
if(_image.LoadFromFile(filename) == false)
{
_filename = "";
_isLoaded = false;
}
else
{
_filename = filename;
_tracer.SetImage(_image);
_isLoaded = true;
}
}
sf::Sprite Pathfinder::_tracer;
sf::Image Pathfinder::_image;
std::string Pathfinder::_filename;
bool Pathfinder::_isLoaded = false;