Thread: 2D Acceleration/Velocity Processing

  1. #1
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273

    Question 2D Acceleration/Velocity Processing

    Hello,

    In my spare time I'm having a go at creating a 2D platform game with what I hope to be a realistic simulation of physics. I've got a looong way to go, but something akin to what you might see with the Source engine, only in 2D.

    Anyways, I've tried creating a function that is called every frame to process the basics (collisions, gravity, etc.). However it doesn't work the way that I expect it to.

    When the object reaches the bounds of the screen I invert the acceleration vector to cancel out any movement, however I seem to get a slight jitter.

    Also, in the main game loop, during processing of input I add vectors to the player's acceleration vector whenever they press left, right, etc. but I don't see this reflected on screen.

    I think the problem might have something to do with scale but I'm not sure.

    My vector struct has both Cartesian and polar coordinates to aid debugging.

    (btw this is good old-fashioned C):-
    Code:
    // pGame = game object, uiTime = delta time in ticks
    void Physics_Think(t_game *pGame, unsigned int uiTime)
    {
    	t_physicsobject *pObject;
    	t_vector vNow;
    
    	// iterate through linked list of objects
    	pObject = (t_physicsobject *)pGame->listPhysics.lpHead;
    	while (pObject)
    	{
    		// don't bother processing if not visible
    		if (!(pObject->pspr->fFlags & SPRF_VISIBLE))
    		{
    			pObject = (t_physicsobject *)pObject->node.lpNext;
    			continue;
    		}
    
    		// collision test (to implement)
    		...
    		// apply gravity to acceleration (magnitude = 10, direction = 90 degrees)
    		Vector_Add(&pObject->vAcceleration, &pGame->vGravity);
    		// limit object to inside screen
    		if (pObject->vVelocity.dblDx < 0.0)
    		{
    			if (pObject->pspr->x + pObject->vVelocity.dblDx < 0)
    			{
    				pObject->pspr->x = 0;
    				Vector_Set(&vNow, pObject->vAcceleration.usMagnitude, 360 - pObject->vAcceleration.usDirection);
    				Vector_Add(&pObject->vAcceleration, &vNow);
    			}
    
    		}
    		else if (pObject->vVelocity.dblDx > 0.0)
    		{
    			if (pObject->pspr->x + pObject->vVelocity.dblDx >= 640 - pObject->pspr->w)
    			{
    				pObject->pspr->x = 640 - pObject->pspr->w;
    				Vector_Set(&vNow, pObject->vAcceleration.usMagnitude, 360 - pObject->vAcceleration.usDirection);
    				Vector_Add(&pObject->vAcceleration, &vNow);
    			}
    
    		}
    
    		if (pObject->vVelocity.dblDy < 0.0)
    		{
    			if (pObject->pspr->y + pObject->vVelocity.dblDy < 0)
    			{
    				pObject->pspr->y = 0;
    				Vector_Set(&vNow, pObject->vAcceleration.usMagnitude, 360 - pObject->vAcceleration.usDirection);
    				Vector_Add(&pObject->vAcceleration, &vNow);
    			}
    
    		}
    		else if (pObject->vVelocity.dblDy > 0.0)
    		{
    			if (pObject->pspr->y + pObject->vVelocity.dblDy >= 480 - pObject->pspr->h)
    			{
    				pObject->pspr->y = 480 - pObject->pspr->h;
    				Vector_Set(&vNow, pObject->vAcceleration.usMagnitude, 360 - pObject->vAcceleration.usDirection);
    				Vector_Add(&pObject->vAcceleration, &vNow);
    			}
    
    		}
    
    		// apply acceleration to velocity
    		Vector_Set(&vNow, pObject->usMass * pObject->vAcceleration.usMagnitude * uiTime, pObject->vAcceleration.usDirection);
    		Vector_Add(&pObject->vVelocity, &vNow);
    
    		// clamp
    		if (pObject->vVelocity.usMagnitude > 3000)
    			Vector_Set(&pObject->vVelocity, 3000, pObject->vVelocity.usDirection);
    
    		// move object
    		if (pObject->vVelocity.dblDx != 0)
    			pObject->pspr->x += pObject->vVelocity.dblDx;
    
    		if (pObject->vVelocity.dblDy != 0)
    			pObject->pspr->y += pObject->vVelocity.dblDy;
    
    		pObject = (t_physicsobject *)pObject->node.lpNext;
    	}
    
    }
    I'm not sure if I am supposed to be applying the full value of the gravity vector to the acceleration vector every frame. The acceleration vector is scaled to delta time before being added to the velocity.

    Little help?
    Last edited by SMurf; 11-16-2010 at 06:06 PM. Reason: Tired

  2. #2
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    The coding is good, it's the right idea, but there are lots of conceptual errors going on.

    1) Don't add gravity to the acceleration each frame. Acceleration due to gravity is constant - what happens in this code is a constant increase in acceleration. Set it to the gravity acceleration vector at the beginning and leave it alone - or if you need to, calculate and set net acceleration based on the forces that are currently acting on the object. But it's generally unwise to add to the acceleration vector like this.

    2) Consider the part in bold:
    Code:
    if (pObject->pspr->x + pObject->vVelocity.dblDx < 0)
    			{
    				pObject->pspr->x = 0;
    				Vector_Set(&vNow, pObject->vAcceleration.usMagnitude, 360 - pObject->vAcceleration.usDirection);
    				Vector_Add(&pObject->vAcceleration, &vNow);
    			}
    This is not the opposite of your original acceleration vector. Try a few test cases to see what I mean.
    You'll want to set the direction to 180+original to get the opposite motion.
    On the other hand, if you're going to cancel out acceleration, why don't you just set the magnitude to 0?

    3) Canceling out acceleration isn't going to keep the object in the screen anyway - an object with 0 acceleration will still move with its initial velocity. I'd suggest leaving acceleration as it is and setting velocity to 0, at least until collisions are properly implemented. And do this sort of clamping after your new position has been calculated. That has 2 benefits: you're can use the new current_position in those if statements (instead of calculating the next position for each comparison), and it eliminates that jitter you were describing.

    4)
    Code:
    Vector_Set(&vNow, pObject->usMass * pObject->vAcceleration.usMagnitude * uiTime, pObject->vAcceleration.usDirection);
    I'll leave it to you to decide what's wrong with this.

    Umm... with all that said, good luck .

    And take a look at this when you have time. It's a fantastic explanation of physics for game devs.
    Consider this post signed

  3. #3
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    Ah. This serves me right.
    I need more Coke for late-night coding (the drink, not the other stuff)...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Passing 2D arrays between functions
    By taurus in forum C Programming
    Replies: 10
    Last Post: 09-28-2009, 05:05 AM
  2. 2D in directX
    By fighter92 in forum Game Programming
    Replies: 6
    Last Post: 01-25-2009, 11:23 AM
  3. 2d to 3d: Image processing
    By arjunajay in forum C++ Programming
    Replies: 2
    Last Post: 07-19-2006, 09:39 PM
  4. Replies: 4
    Last Post: 03-02-2003, 09:12 AM
  5. file writing crashes
    By test in forum C Programming
    Replies: 25
    Last Post: 08-13-2002, 08:44 AM