simple ball trajectory calculation

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
robertgarand
Posts: 69
Joined: Fri Feb 22, 2008 6:47 pm
Location: montreal
Contact:

simple ball trajectory calculation

Post by robertgarand »

Hi all,
I'm doing a canon simulation game. The canon don't move and throw shells at incoming objects. Player will adjust angle (x,y) and fire.
depending on world's gravity and shells type, the range will change.

I have the position and rotation of the canon (not a camera).
I have been searching for simple way to calculate next position of shell base on gravity, rotation(relative angle) and initial speed.

Collision detection is working.
Sound is working.
Canon orientation follows mouse proportionally.
works when using followstraightlineanimator...

Integrating an whole graphic engine seem a (big) bit of work for my application.(don't need, friction, joint, fluid, etc)
If someone could show me a short and sweet way to do the 3d math.
Could be fillling a matrix for followspline function...
I lately read a lot on physic, 3D graphical issues and engine, physic engines and haven't found what i need so far.
Irrlicht rocks !

Thanks for reading,
Robert
If it can't be writen, it can't exist
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

simple.....

x(t) = x+v*t+1/2*g*t²

This function dicribes the path of a simple bullet just plugin the values u want.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
robertgarand
Posts: 69
Joined: Fri Feb 22, 2008 6:47 pm
Location: montreal
Contact:

More precise

Post by robertgarand »

Thanks for the reply,
but what I need is a simple way to obtain the graphic world node coordinate of the shell's next position.
like roughly:

spherenode shell;
shell_struct
[oldpos(vector3df),
newpos(vector3df),
angle(X(f32 degrees),
Y(f32 degrees),
speed (f32 f/s),
weight(f32 pound)]

shellstruct[x].newpos = whatever_physic-graphic_function(shellstruct[x]);
shell[x]-> setPosition(newpos);

Angle is irrevelant since it is spherical shell.

I know it can be obvious for many, but I'm new to 3d graphic programming,
and I just want to know the right direction, for me, not the shell ;)
TIA,
regards, Robert
If it can't be writen, it can't exist
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

well i just told u how to.
u just plugin the time from start and u have the position.
u could also differentiate to get the speed at the time and then just add that to the position. but i really don't get the problem.

x is the start position in other words a irr::core::vector
v is the speed the shell was fired with also a irr::core::vector
g is maybe the eath acceleratin also a irr::core::vector
well and t is the time since the projectile was launched in seconds.
and x(t) is obviously the position at the time t also a irr::core::vector

oh and btw the weight doesn't matter at all.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

When you fire off the shell you know the direction you're firing it at.

So all you need to do is add that vector on each frame (probably normalised and then multiplied by some factor based on the elapsed time since the last frame to give the same speed at any framerate).

To handle the gravity you can just decrease the vertical velocity of the shell each time by a small amount.
Image Image Image
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

did't i tell him the same?
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

In a more confusing manner, yes ;)
Image Image Image
robertgarand
Posts: 69
Joined: Fri Feb 22, 2008 6:47 pm
Location: montreal
Contact:

I know physic, but not 3dgraphic...

Post by robertgarand »

Maybe what I am missing is the 3D theory on vector computation :oops:

The problem is that I don't know how to start from a position vector3d and an angle f32 x and y with speed f32 and get back the new position regarding 3d graphic and node position.
I read about quaternion ,euler, etc, where exactly should I look on wich function or property that compute, convert 3dvector in Irrlicht?
there is transformation, translation, conversion, etc, where must I look ?
Or do you have any short and clear tutorial on 3d math basic you can suggest :)

And I dont understand how a speed can be a vector3d ???
Like I said I am new to 3d graphic but I know there must be a way to use already build function or method to make the job more elegant and reusable.

Thanks a LOT for your time.
regards,
Robert
If it can't be writen, it can't exist
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

speed is a scalar, i.e. a value like 1, 2, 3.546 etc.
velocity is a vector, i.e. (0,-9.81,0)

so velocity basically tells you a direction in 3D space.

So when you fire the cannon you have a vector of the direction in which you want the shell to be fired, maybe it's (0,10,10). That means 10 units up and 10 units forward.

What you may want to do is normalise that so it's a unit vector (has a length of 1) and then multiply it by your shell speed value. If you did that each frame it would go in a straight line from the end of your cannon.

So then each frame you also apply the gravity so that it falls down.
Image Image Image
robertgarand
Posts: 69
Joined: Fri Feb 22, 2008 6:47 pm
Location: montreal
Contact:

thanks for answer

Post by robertgarand »

From what i understand I have two choices:
1) Using a whole physic engine
2) Manually make the computation.


I just tought (hope) that there was some kind of call to function(s) I could make with just the position, current speed, time interval and angle, that would return the new pos dealing with all conversion, normalisation etc...
It seems pretty basic need, already made in a class.

I actually don't know if you can add, substract, etc two vectors directly,
multiply a vector by a float, etc. The description of the functions are not all obvious for me...I wanted to avoid exhaustive readings...

Thanks a lot for your time, I'll keep on reading...
what you learn in digging is never a lost of time :)
I'll then make the function/class available to others.


Robert
If it can't be writen, it can't exist
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

There's no pre-made function like that. But everything you need is available. You can do all those mathsy things to the vectors directly; adding, multiplying etc.
Image Image Image
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Let's try this again:

vector3df CurrentPosition;
vector3df OriginalPosition(0,0,0);
float CurrentTime((float)getTime());
float Speed(5.0f);
vector3df Velocity(getOrientation()*Speed); // You need to calculate your Orientation somehow
vector3df Gravity(0,-9.8f,0); //This will most likelly need to be scaled to your world

CurrentPosition = OriginalPosition + Velocity * CurrentTime + 0.5f * Gravity * (CurrentTime * CurrentTime);

Is that plug and play enough?

-EDIT-
Of course, lot's of improvement can be made, the first is to precalculate Gravity * 0.5f and use that instead, saving you that calculation each iteration for each object.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

One way of doing it.

Code: Select all

#include <irrlicht.h>
using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

class MyEventReceiver : public IEventReceiver
{
public:
	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event)
	{
		// Remember whether each key is down or up
		if (event.EventType == irr::EET_KEY_INPUT_EVENT)
			KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;

		return false;
	}

	// This is used to check whether a key is being held down
	virtual bool IsKeyDown(EKEY_CODE keyCode) const
	{
		return KeyIsDown[keyCode];
	}

	MyEventReceiver()
	{
		for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
			KeyIsDown[i] = false;
	}

private:
	// We use this array to store the current state of each key
	bool KeyIsDown[KEY_KEY_CODES_COUNT];
};


int main()
{
    MyEventReceiver receiver;
	IrrlichtDevice *device =
		createDevice( video::EDT_OPENGL, dimension2d<s32>(800, 600), 32,
			false, false, false, &receiver);

	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();

    device->setWindowCaption(L"W = up, S = down, SPACE = fire");

    ISceneNode * ball = smgr->addSphereSceneNode();

	(void)smgr->addCameraSceneNode(0, vector3df(50,30,-200), vector3df(50,0,0));

    f32 gunAngle = 0.f;
    f32 const GUN_LENGTH = 10.f;
    f32 const PROJECTILE_SPEED = 50.f;
    f32 const GRAVITY = -10.f;
    u32 then = device->getTimer()->getTime();
    u32 launchTime = 0;
    vector3df flightVector(0,0,0);

	while(device->run())
	{
        u32 now = device->getTimer()->getTime();
        f32 delta = (now - then) / 1000.f;
        then = now;

        if(receiver.IsKeyDown(KEY_KEY_W) && gunAngle < 90.f)
            gunAngle += 30.f * delta;
        else if(receiver.IsKeyDown(KEY_KEY_S) && gunAngle > 0.f)
            gunAngle -= 30.f * delta;

        f32 const angleRadians = DEGTORAD * gunAngle;

        if(0 == launchTime && receiver.IsKeyDown(KEY_SPACE))
        {
            flightVector.X = PROJECTILE_SPEED * cos(angleRadians);
            flightVector.Y = PROJECTILE_SPEED * sin(angleRadians);
            launchTime = now;
        }

        if(launchTime > 0)
        {
            flightVector.Y += GRAVITY * delta;
            ball->setPosition(ball->getAbsolutePosition() + flightVector * delta);

            if(ball->getAbsolutePosition().Y < 0.f)
            {
                ball->setPosition(vector3df(0,0,0));
                launchTime = 0;
            }
        }

        driver->beginScene(true, true, video::SColor(0,200,200,200));
		smgr->drawAll();

        driver->setTransform(ETS_WORLD, matrix4());
        driver->draw3DLine(vector3df(0,0,0),
                            vector3df(GUN_LENGTH * cos(angleRadians), GUN_LENGTH * sin(angleRadians), 0.f));

		driver->endScene();
	}

	device->drop();

	return 0;
}

Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
robertgarand
Posts: 69
Joined: Fri Feb 22, 2008 6:47 pm
Location: montreal
Contact:

thanks a lot for replies, great community :)

Post by robertgarand »

I will be able to do it with formulas.
The true way I was looking for is like using a certain createanimatortypeX,
on a scenenodetypeX that would respond to gravity and collision.

Then I would just have to "throw" the shell and wait for impact with the collision manager
All the overhead would have been taken care by itself,
insuring stability and effectiveness right away from well
tested code.

But everywhere I look, the node type can't be use with that animator,
and that animator can't just give impact event,
there is always a property missing in one or the other, from what I understand...
If I am wrong and someone knows, please let me hear from you.

Thanks alot again for your precious time :D
It's a pleasure to discover a very responding community.
I'll let you know the way I took,
Regards,
Robert
If it can't be writen, it can't exist
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

If you want it to work like that then you do need to use a physics engine to make it easy on yourself.

Although it's not that hard to do yourself as people have shown you, all you need to do for collision is then keep a list of all the shells you've fired and then each frame check them for collision against any objects of interest. That's shown in the collision tutorial with the particle you can fire and it gives an impact against the wall (although that's not real time collision as the collision point is decided when the particle is fired which won't work if you have objects moving around, though it's not hard to alter the code to make it work in realtime).
Image Image Image
Post Reply