Jump to content

  • Log In with Google      Sign In   
  • Create Account

2D physics in a game.


Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
5 replies to this topic

#1 LAURENT*   Members   -  Reputation: 500

Like
0Likes
Like

Posted 30 May 2014 - 07:57 PM

I thought this was going to be a cake walk but implementing 2D physics is harder than I thought. I could use some logic help with this.

 

Something I tried.

I applied a constant gravity of 9. with the press of the space bar you move up. The only thing that happen was the character teleported up and floated down................

 

 



#2 Washu   Senior Moderators   -  Reputation: 7610

Like
5Likes
Like

Posted 30 May 2014 - 08:19 PM

Without code it is hard to tell what you're doing wrong... but here's something that might likely be the problem:

 

Your movement up is probably applying directly to the object you are moving. Instead you should apply a velocity to it, and compute the movement over the delta time of your physics step.


In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX


#3 Postie   Members   -  Reputation: 1422

Like
3Likes
Like

Posted 30 May 2014 - 10:50 PM

Typically, you'd apply a force to an object, which would cause that object to accelerate. Over time, acceleration alters the object's velocity. Over time, velocity alters the object's position.

 

Force, Acceleration, Velocity, Position and Time. Those are the 5 things you need to worry about. If however, you also want your object to rotate, then you have Torque, Angular acceleration, Angular velocity and Orientation to worry about.

 

Though it seems like 2D physics should be pretty easy compared to 3D physics, the concepts are actually the same, but some of the formulae are simpler since they involve one less dimension. 

 

I wrote a simple 2D physics engine in C# about 4 years ago, and Chris Hecker's articles on rigid body dynamics were an invaluable resource.

 


Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler

#4 LAURENT*   Members   -  Reputation: 500

Like
0Likes
Like

Posted 31 May 2014 - 08:14 AM

I think it's force I don't understand. I'll look up every word so I can be sure that's not the only thing I don't know. Anyways here is my sloppy ugly looking code. It uses 2 files. My game is isometric but I've gone over the logic. All I need to do is is to create 2D gravity for certain objects for my game to work correctly

 

 

Header file 

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

enum {EMPTY, CIRCLE, CROSS};
class Game
{
    public:
		Game::Game()
		{
			const int FRAMES_PER_SECOND = 30, YS_WIDTH = 30, YS_HEIGHT = 30, 
			SCREEN_WIDTH = 589, SCREEN_HEIGHT = 404;
			
			circle= IMG_Load("circle.jpg");   // rond = circle
			croix= IMG_Load("croix.jpg"); //
			board= IMG_Load("board.jpg"); // grille = board
			horizontale=IMG_Load("horizontale.jpg");
			verticale=IMG_Load("verticale.jpg");
			diagonale1=IMG_Load("diagonale1.png");
			diagonale2=IMG_Load("diagonale2.png");
			button=IMG_Load("button.png");
			//Initialize the velocity
		};
		//Tic tac toe Game function
		void character_level(SDL_Surface* screen);
      		void play(SDL_Surface* screen);
        	int check_victory(SDL_Surface* screen);

		
		//Velocity and movement funtions
	
		void handle_input(SDL_Surface* screen);
		
		void move(SDL_Surface* screen);
		
		void show(SDL_Surface* screen);
		
		
//The timer functions and various actions
	
		void start(SDL_Surface* screen);

		void stop(SDL_Surface* screen);
	
		void pause(SDL_Surface* screen);

		void unpause(SDL_Surface* screen);


	
		//Gets the timer's time
		
		int get_ticks(SDL_Surface* screen);



		//Checks the status of the timer

		bool is_started(SDL_Surface* screen);
	
		bool is_paused(SDL_Surface* screen);
		bool load_files();
		Game::~Game()
		{
			SDL_FreeSurface(horizontale);
			SDL_FreeSurface(verticale);
			SDL_FreeSurface(diagonale1);
			SDL_FreeSurface(diagonale2);
			SDL_FreeSurface(croix);
			SDL_FreeSurface(circle);
			SDL_FreeSurface(button);
			SDL_FreeSurface(board);	
		};
    private:
        SDL_Surface *board, *circle, *croix, *horizontale, *verticale, 
	*diagonale1, *diagonale2, *button, *YsguySheet,*LandPad;
		
	SDL_Event event;
        int continuer,  turn,  end, nowinner, x, y, xVel, yVel; 
	int space1, space2, space3, space4, space5, space6, space7, space8, space9;   
	//int YS_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT , YS_WIDTH, FRAMES_PER_SECOND;
        SDL_Rect boardPosition, positionforme, positionwon;
	SDL_Rect button1, button2, button3, button4, button5, button6, button7, button8, button9;
	SDL_Rect velocity;

	//The timers private variables
	//The clock time when the timer started
		
	int startTicks, pausedTicks;


	//The timer status
		
	bool paused;
	
	bool started;
};


#endif // GAME_H_INCLUDED

Cpp file 

#include <stdlib.h>
#include <stdio.h>
#include <SDL.h>
#include <SDL_image.h>
#include <time.h>
#include "Game.h"
#include <string>

SDL_Surface *load_image( std::string filename )
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;

    //The optimized surface that will be used
    SDL_Surface* optimizedImage = NULL;

    //Load the image
    loadedImage = IMG_Load( filename.c_str() );

    //If the image loaded
    if( loadedImage != NULL )
    {
        //Create an optimized surface
        optimizedImage = SDL_DisplayFormat( loadedImage );

        //Free the old surface
        SDL_FreeSurface( loadedImage );

        //If the surface was optimized
        if( optimizedImage != NULL )
        {
            //Color key surface
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );
        }
    }

    //Return the optimized surface
    return optimizedImage;
}



void apply_surface( int x, int y,  SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL)
{
    //Holds offsets
   
	SDL_Rect offset;

    //Get offsets
    offset.x = x;
    offset.y = y;

    //Blit
    SDL_BlitSurface( source, clip, destination, &offset );
}
void character_movement( int x, int z,  SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL)
{
    //Holds offsets
   
	SDL_Rect movement;

    //Get offsets
    movement.x = x;
    movement.y = z;

    //Blit
    SDL_BlitSurface( source, clip, destination, &movement );
}



/*bool load_files()
{
    //Load the dot image
    YsguySheet = load_image( "YsguySheet.png" );

    //If there was a problem in loading the dot
    if( YsguySheet == NULL )
    {
        return false;
    }

    //If everything loaded fine
    return true;
}*/


void Game::character_level(SDL_Surface *screen)
{
	int continuer = 1, x = 0, y = 0, xVel = 0, yVel = 0, end=0;
	const int FRAMES_PER_SECOND = 30, YS_WIDTH = 30, YS_HEIGHT = 30, SCREEN_WIDTH = 589, SCREEN_HEIGHT = 404;
	SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
	int z =0, zVel =0; 
	int gravity = 9;
	int velocity = 36;
	

	int startTicks = 0;
	int pausedTicks = 0;
	bool paused = false;
	bool started = true;

////////Load the dot image
    LandPad = load_image("LandPad.png");
	YsguySheet = load_image( "YsguySheet.png" );
	
   
//////Load file done
		while(continuer)
		{ 
			zVel += gravity;

			//timer function start
			startTicks = SDL_GetTicks();

			 //While there's events to handle
			while (SDL_PollEvent( &event ))
			 {
					//SDL_WaitEvent(&event);
					if( event.type == SDL_QUIT )
					{
						 //Quit the program
						 continuer = 0;
						 break;
					}	

					//Handler Event function
					if( event.type == SDL_KEYDOWN )
					{
						//Adjust the velocity
						switch( event.key.keysym.sym )
						{
							case SDLK_UP: yVel -= YS_HEIGHT/10; break; 
							case SDLK_DOWN: yVel += YS_HEIGHT/10; break; 
							case SDLK_LEFT: xVel -= YS_WIDTH/10;  break; 
							case SDLK_RIGHT: xVel += YS_WIDTH/10; break;
							/////JUMPING//////////////////////////////////////
							case SDLK_SPACE: 
								for (zVel -= velocity ; zVel - 9 ; ) 

								
								
								
								break; 
								
								
					
						}
					  }

					else if( event.type == SDL_KEYUP )
					{
						 //Adjust the velocity
						 switch( event.key.keysym.sym )
						 {
							case SDLK_UP: yVel += YS_HEIGHT/10; break;
							case SDLK_DOWN: yVel -= YS_HEIGHT/10; break;
							case SDLK_LEFT: xVel += YS_WIDTH/10; break;
							case SDLK_RIGHT: xVel -= YS_WIDTH/10; break;						
						 }
					} //Handler ends here			 
			 } 

			
			 //Move function
			 x += xVel;
			 //If the dot went too far to the left or right
			if( ( x < 0 ) || ( x + YS_WIDTH > SCREEN_WIDTH ) )
			{
				//move back
				x -= xVel;
			}

			//Move the dot up or down
				y += yVel;

		    //If the dot went too far up or down
			if( ( y < 0 ) || ( y + YS_HEIGHT > SCREEN_HEIGHT ) )
			{
				//move back
				y -= yVel;
			} //Move ends here

			z += zVel;
			//If the dot went too far up or down
			if(  z > y )
			{
				//move back
				z -= zVel;
			} 

			
			SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));

			apply_surface(x, y, LandPad, screen);

			//Show the Ys on the screen
			character_movement(x , z, YsguySheet, screen);

	        //Update the screen
		    SDL_Flip(screen);
      
        //Cap the frame rate
        if( get_ticks(screen) < 1000 / FRAMES_PER_SECOND )
        {
            SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - get_ticks(screen) );
        }
    }
}










int Game::get_ticks(SDL_Surface* screen)
{
	//If the timer is running
    if( started == true )
    {
        //If the timer is paused
        if( paused == true )
        {
            //Return the number of ticks when the timer was paused
            return pausedTicks;
        }
        else
        {
            //Return the current time minus the start time
            return SDL_GetTicks() - startTicks;
        }
    }

    //If the timer isn't running
    return 0;
}

Edited by LAURENT*, 31 May 2014 - 08:20 AM.


#5 Postie   Members   -  Reputation: 1422

Like
3Likes
Like

Posted 01 June 2014 - 02:36 AM

Game physics is something that only works correctly if you update it at a constant, predictable rate, independent of the rate you're rendering to the screen. The way this is commonly achieved is to define how often you want to update your physics, eg, 20 times a second, and then calculate the elapsed time between each rendering frame. Accumulate that over several frames until you reach 1/20th of a second, then do a physics update, using 1/20th of a second as your time parameter in all your physics equations. This means that your physics updates are all done with the same time difference (or delta), and they happen predictably, which means the motion of your objects will be smooth.

 

I highly recommend you check out "Fix your timestep!", the seminal work on the topic.


Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler

#6 LAURENT*   Members   -  Reputation: 500

Like
0Likes
Like

Posted 01 June 2014 - 03:08 PM

I've found some source code of 2D games with acceptable physics. One even detects when the characters are touching the ground. Anyways thanks for the link. I see that you mention delta which was used in the sources I found. I love smooth and adore predictable so I guess I'll study delta time the most.






Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.




PARTNERS