Page 1 of 1

Example Bullet Code, needs 1 last issue figured out

Posted: Fri Jul 20, 2007 3:34 pm
by kendric
I thought I would share my projectile code with people and hopefully somebody will also have an idea why about 10-20% of the time bullets seem to be able to go through an enemy without a collision detected.

You will have to modify this depending on your model domain, as this uses all my game classes.

Just to sum up the logic:
Every frame the following happens for a bullet in the air:
First frame: calculate the distance to wall we will hit so we don't have to calculate collisions with the world scene node

All other frames:
take current position and create a line from there to next position given amount of time passed and flight speed

Do a ray cast check with custom ray cast code along that line(custom ray cast will be at the bottom)

If any collisions along the line, stop there and perform a hit

else move to the end of the line.

And here is the code (If you know how to make it preserve indentation please let me know)

Code: Select all

void Projectile::passTime(f32 amount)
{
       Object::passTime(amount);
	if(firstTick)
	{
		firstTick=false;
		line3df totalTravelLine;
		totalTravelLine.start=getSceneNode()->getPosition();
		totalTravelLine.end=direction*50000.0f;
wallDecal=myGameSceneManager->getSceneCollisionManager()->getCollisionPoint(totalTravelLine,game->world->getSceneNode()->getTriangleSelector(),expirePoint,expireTriangle);
		if(wallDecal)
		{
expireDistanceRemaining=expirePoint.getDistanceFrom(totalTravelLine.start);
		}
		else
		{
			printf("No wall hit.\n");// This should not happen
			expireDistanceRemaining=2500000000.0f;
		}
	}
	line3d<f32> line;
	line.start=getSceneNode()->getPosition();
	line.end = line.start + direction*speed*amount;
	lines.push_back(line);//i track these just so i can draw the incramental trajectories for debugging only(this is how i see that the line passes right through a scene node)
	expireDistanceRemaining-=line.getLength();
	ISceneNode* selectedSceneNode=NULL;
	f32 distanceSquared;
	vector3df collisionPoint;
	triangle3df collisionTriangle;
collisionCheck(myGameSceneManager->getRootSceneNode(),line,ProjectileSceneNodeFilter(thisProjectilePtr()),selectedSceneNode,collisionPoint,collisionTriangle,distanceSquared);
	bool hit=false;
	if(selectedSceneNode)
	{
		handleImpact(selectedSceneNode,collisionPoint,collisionTriangle,line);
		destroy();
	}
	else if(expireDistanceRemaining<=0.0f)
	{
		if(wallDecal&&hasBulletHole)
		{	
			shared_ptr<Decal> temp(new Decal());
			temp->init(game->world->getSceneNode(),expireTriangle,expirePoint,bulletHoleTexture,2);
			game->zone->addDecal(temp);
		}
		destroy();
	}
	else
	{
		getSceneNode()->setPosition(line.end);
	}
}


and the collision function(this is a modifcation to the one in irrlicht 
//! recursive method for going through all scene nodes and looking for the best triangle collision
void collisionCheck(ISceneNode* root,
					 const line3df& ray,SceneNodeFilter &filter,ISceneNode*& outBestNode,vector3df &outPoint,triangle3df &outTriangle,f32 &outDistanceSQ)
{
	core::vector3df edges[8];
	const core::list<ISceneNode*>& children = root->getChildren();
	core::list<ISceneNode*>::Iterator it = children.begin();
	for (; it != children.end(); ++it)
	{
		ISceneNode* current = *it;
		if (filter.allowNode(current))
		{
			// get world to object space transform
			core::matrix4 mat;
			if (!current->getAbsoluteTransformation().getInverse(mat))
			{
				continue;
			}
			// transform vector from world space to object space
			core::line3df line(ray);
			mat.transformVect(line.start);
			mat.transformVect(line.end);
			const core::aabbox3df& box = current->getBoundingBox();
			// do triangle intersection test in object space
			if (box.intersectsWithLine(line))
			{
				vector3df point;
				triangle3df triangle;
				bool hit=myGameSceneManager->getSceneCollisionManager()->getCollisionPoint(ray,current->getTriangleSelector(),point,triangle);
				if(hit)
				{
					float newDistance=point.getDistanceFromSQ(line.end);
					if(!outBestNode||newDistance<outDistanceSQ)
					{
						outBestNode = current;
						outDistanceSQ=newDistance;
						outPoint=point;
						outTriangle=triangle;
					}
				}
			}
		}
		collisionCheck(current, ray, filter,outBestNode,outPoint,outTriangle,outDistanceSQ);
	}
}
Also every node has this happen once at the beginning

ITriangleSelector* selector=myGameSceneManager->createTriangleSelectorFromBoundingBox(sceneNode);
sceneNode->setTriangleSelector(selector);

Posted: Fri Jul 20, 2007 4:16 pm
by beshrkayali
i'm not clear over here :?

is your problem some kind of collision detection??

if it is, this might help
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=22971

Re: Example Bullet Code, needs 1 last issue figured out

Posted: Fri Jul 20, 2007 5:49 pm
by Robert Y.
kendric wrote:... and hopefully somebody will also have an idea why about 10-20% of the time bullets seem to be able to go through an enemy without a collision detected.
Maybe it is because you don't use a metaselector? Also, which version of Irrlicht are you using?

Posted: Fri Jul 20, 2007 9:29 pm
by kendric
Yes my problem is collision detection. This code works most of the time. However wether its certain angles or what but you get into a state where you can shoot through an enemey over and over. If you move enough you get back to hitting them again..


As to the other question the latest build.