Vectors and bullet aiming. [Getting inconsistent results :( ]

Started by
4 comments, last by oliii 15 years, 10 months ago
The bullet that I'm using has a constructor like this:
bullet(float xx, float yy, float zz, float x1, float y1, float z1,..) {

		x=xx, y=yy, z=zz;                    //sets origin
		t[0]=x1-xx, t[1]=y1-yy, t[2]=z1-zz;  //sets vec toward target i.e. r=r1-r2?
		norm(t);                             //normalize
//other stuff
}
When I shoot I do: bullet *p = new bullet(player.x,player.y,player.z,player.x-player.f.x,player.y-player.f.y,player.z-player.f.z,...); Note that f is player's forward vector and I'm sending (player.x MINUS player.f.x) because for whatever reason my forward vector is opposite to my direction of motion. As far as the player is concerned, this works perfectly. But I get super inconsistencies when it comes to having other object aim at player: bullet *p = new bullet(x,y,z,player.x,player.y,player.z,...); Shouldn't this code work? What I'm getting is the enemies hitting player only when it is in certain areas around the enemy. Otherwise it's pretty hopeless. I tried it without normalizing the vector t and it showed a line from the enemy to the player which at least suggests that something is working right. Where am I going wrong with this? Thanks. [Here's how I update bullet position, in case there's something wrong here: x+=(speed*t[0]); y+=(speed*t[1]); z+=(speed*t[2]); ]
Advertisement
I think your problem is probably not in the code you have posted. Try to find a specific example where the code doesn't do the right thing, and check by hand if all the computations make sense. You can post the specific example if you need help understanding it.
Well, as I said I don't understand why the enemies are shooting at random directions for few seconds (I made it so that it shoots continuously) most of the time and at the target for the rest. I tried some alterations and it seems that it is not moving in the direction that it should with the x+=speed*t[0] etc. code. Shouldn't ray tracing just be about getting a normalized vector and multiplying a scalar with it?
you should really use a vector class, that would help you a lot and make the code more bearable to read.

here's an example

inline void myDebugBreak(const char* assertString, const char* file, int line){	char buff[512]; 	sprintf_s(buff, sizeof(buff), "file \"%s\", line(%d) : assert(%s) failed.\n", file, line, assertString); 	fprintf(stderr, buff); 	DebugBreak(); }#define myAssert(A) { if(!(A)) { myDebugBreak(#A, __FILE__, __LINE__); } };class Vector{public:	union	{		float coord[3]; // coords as an array		struct { float x, y, z; }; // coords are a triple	};	Vector() 	{}	Vector(float ix, float iy, float iz) 	: x(ix)	, y(iy)	, z(iz) 	{}	Vector(const float* icoord) 	: x(icoord[0])	, y(icoord[1])	, z(icoord[2]) 	{}    Vector(const Vector& other) 	: x(other.x)	, y(other.y)	, z(other.z) 	{}		float operator[](int i) const { myAssert(i >= 0 && i < 3); return coord; }	float& operator[](int i) { myAssert(i >= 0 && i < 3); return coord; }	Vector& operator+=(const Vector& other) { x += other.x; y += other.y; z += other.z; return *this; }	Vector& operator-=(const Vector& other) { x -= other.x; y -= other.y; z -= other.z; return *this; }	Vector& operator*=(float k) { x *= k; y *= k; z *= k; return *this; }	Vector& operator/=(float k) { myAssert(fabs(k) > 1.0E-8f); float ik = 1.0f / k; return (*this) *= ik; }		Vector operator+(const Vector& other) const { Vector temp(*this); return temp += other; }	Vector operator-(const Vector& other) const { Vector temp(*this); return temp -= other; }	Vector operator*(float k) const { Vector temp(*this); return temp *= k; }	Vector operator/(float k) const { Vector temp(*this); return temp /= k; }		Vector operator-() const { return Vector(-x, -y, -z); }	friend Vector operator*(float k, const Vector& v) { return v * k; }	Vector scaleProduct(const Vector& other) const { return Vector((x*other.x), (y*other.y), (z*other.z)); }	Vector crossProduct(const Vector& other) const { return Vector((y*other.z) - (z*other.y), (z*other.x) - (x*other.z), (x*other.y) - (y*other.x)); }	float    dotProduct(const Vector& other) const { return (x*other.x) + (y*other.y) + (z*other.z); }		Vector operator&(const Vector& other) const { return crossProduct(other); } // cross product operator	Vector operator^(const Vector& other) const { return scaleProduct(other); } // scale product operator	float  operator*(const Vector& other) const { return   dotProduct(other); } // dot   product operator		float  lengthSquared() const { return (x*x + y*y + z*z); }	float  length() const { return sqrt(lengthSquared()); }		Vector normalised() const 	{ 		float l = length(); 		if(fabs(l) < 1.0E-8f) 		{			myAssert(!"zero-length vector cant be normalised");			return Vector(1, 0, 0);		}		return (*this) / l;	}		float normalise()	{ 		float l = length(); 		if(fabs(l) < 1.0E-8f) 		{			myAssert(!"zero-length vector cant be normalised");			x = y = z = 0.0f;			return 0.0f;		}		(*this) /= l;		return l;	}};


your code would look like

bullet::bullet(const Vector& origin, const Vector& target, ...) {    m_position = origin;    m_direction = (target - origin);    m_direction.normalise();}bullet::update(){    m_position += m_direction * m_speed;}bullet *p = new bullet(player.m_position, player.m_position - player.m_forward, ...);// or...


Otherwise, it looks like it's somewhere else in the code. maybe the normalisation is wrong?

[Edited by - oliii on June 17, 2008 8:02:52 AM]

Everything is better with Metal.

Wow! What an awesome post! Yeah I guess I'll have to switch to a vector class sometime. Not quite my question but thanks!

As I went over the normalization function I sort of found this:
v[0]=v[0]/mag(v);
v[1]=v[1]/mag(v);
...

I should really be kicking myself for being such a dolt.

Either way, however, the aiming is still off and I'm positive there's no more mistakes in the code. Only after increasing the bullet speed and some quick and dirty motion planning can I hit the target. What bothers me is that my previous efforts ditching vectors and using angles (atan2()) instead gave way better results. Anyway, thanks for info.
yep, that normalisation is wrong :)

Using a vector class is not only more efficient and easier on the eye, it makes it easier to catch bugs like these, it's easy to get a sign wrong and not notice.

One word of caution with operators, be careful of their precedence.

Everything is better with Metal.

This topic is closed to new replies.

Advertisement