Motion


mac-10

Still Fresh
Joined
Oct 27, 2006
Messages
56
Age
44
Website
Visit site
Hi there

I am with out doubt a really newbie I have started to code up a space shoot ( really original ) using the SDL. I haven’t got my GP2x yet so I am just compiling it as a win exe. The problem I am having is that the motion of the sprites seems to be jerk or any tip that would be a great help.

Code:
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "SDL/SDL.h"
#define PHYSICSFPS 90

int gLastTick;
int shipSpeed = 1;
int shipX = 20, shipY = 120;
int shipFrame = 0;
int shipMaxFrame = 3;
int Max_Main_Bullets = 10;
int Max_Small_Bullets_1 = 10;
int Max_Small_Bullets_2 = 10;
int MaxEmenies = 20;
int FrameNum = 10;


int gKeyLeft;
int gKeyRight;
int gKeyUp;
int gKeyDown;
int exsFrame;

SDL_Surface *screen, *back, *ship ,*bullet, *exs, *ena;

typedef struct EnemySprite
{
int ObjNo, X, Y, Active, Frame;
}EnemySprite;

typedef struct BulletSprite
{
int ObjNo, X, Y, Active;
}BulletSprite;

typedef struct bgElements
{
int Frame, X, Y, Active;
}bgElements;

int i;

BulletSprite bull[10];
bgElements bgS[7];
EnemySprite enS[20];

// Load in an image and convert it to the display format
// for faster blitting.
SDL_Surface * ImageLoad(char *file)
{
  SDL_Surface *temp1, *temp2;
  temp1 = SDL_LoadBMP(file);
  temp2 = SDL_DisplayFormat(temp1);
  SDL_FreeSurface(temp1);
  return temp2;
}
void addBullet(void){
int flag = 1;
	for(i=1;i < Max_Main_Bullets; i++)
	{
	if(flag &&  bull[i].Active == 0){ 
			bull[i].Active = 1; 
			flag = 0;
			bull[i].X = shipX + 45;
			bull[i].Y = shipY + 15;			  
		  }
	   
	}
}

void DrawIMG(SDL_Surface *img, int x, int y)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}

void DrawIMG(SDL_Surface *img, int x, int y, int w, int h, int x2, int y2)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_Rect dest2;
  dest2.x = x2;
  dest2.y = y2;
  dest2.w = w;
  dest2.h = h;
  SDL_BlitSurface(img, &dest2, screen, &dest);
}

void aniexs(){

exsFrame += 1;
	if(exsFrame > 3) exsFrame = 0;
	 DrawIMG(exs,shipX - 8,shipY,22,26,21*exsFrame,0);  

}

void render(){

  int tick = SDL_GetTicks();

  if (tick <= gLastTick) 
  {
	SDL_Delay(1);
	return;
  }

  while (gLastTick < tick)
  {	 
  if (gKeyLeft) shipX -= shipSpeed;
  if (gKeyRight) shipX += shipSpeed;
  if (gKeyUp) shipY -= shipSpeed;
  if (gKeyDown) shipY += shipSpeed;

if(shipX > 280) shipX = 280;
if(shipX < 1) shipX = 1;
if(shipY > 215) shipY = 215;
if(shipY < 1) shipY = 1;
	SDL_FillRect(screen,0,0);

	for(i=1;i < 5; i++)
	{
		 if(bgS[i].Active){
		 bgS[i].X = bgS[i].X - 1;
		 DrawIMG(back, bgS[i].X ,bgS[i].Y,52,88,52*bgS[i].Frame,0);
		 if(bgS[i].X < -52){	
		 bgS[i].X=320+rand()%10; 
		 bgS[i].Frame = rand()%5; 
		 bgS[i].Y = rand()%160;
		 } 
		 } 
	}

	for(i=1;i < Max_Main_Bullets; i++)
	{
		if(bull[i].Active){
		   bull[i].X = bull[i].X + 2;
		   DrawIMG(bullet, bull[i].X ,bull[i].Y,9,9,0,0);
		   if(bull[i].X > 300)	bull[i].Active=0;			 
		   }
	   
	}

	for(i=1;i < MaxEmenies; i++)
	{
		 if(enS[i].Active){
		 enS[i].X = enS[i].X - 2;
		 DrawIMG(ena, enS[i].X ,enS[i].Y,34,33,34*enS[i].Frame,0);
		 if(enS[i].X < -52){	
		 enS[i].X=320+rand()%10; 
		 enS[i].Y = rand()%160;
		 } 
		 } 
	}

 aniexs();



  
	 DrawIMG(ship,shipX,shipY,43,29,0,0);
	 SDL_Flip(screen);
	 gLastTick += 1000 / PHYSICSFPS;
	 }
}

int main (int argc, char *argv[])
{
	char *msg;
	int done;
  srand(time(NULL));
	Uint8* keys;

	for(i=1;i < Max_Main_Bullets; i++)
	{
		bull[i].X = 0;
		bull[i].Y = 0;
		bull[i].Active = 0;
		bull[i].ObjNo = i;
	}
	
	for(i=1;i < 5; i++)
	{
		bgS[i].X = rand()%500+52;
		bgS[i].Y = rand()%160;
		bgS[i].Active = 1;
		bgS[i].Frame = rand()%4;
	}
	
		for(i=1;i < MaxEmenies; i++)
	{
		enS[i].X = rand()%500+400;
		enS[i].Y = rand()%160;
		enS[i].Active = 1;
		enS[i].ObjNo = i;
		enS[i].Frame = rand()%4;
	}

	/* Initialize SDL */
	if (SDL_Init (SDL_INIT_VIDEO) < 0)
	{
		sprintf (msg, "Couldn't initialize SDL: %s\n", SDL_GetError ());
		free (msg);
		exit (1);
	}
	atexit (SDL_Quit);

	screen = SDL_SetVideoMode (320, 240, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
	if (screen == NULL)
	{
		sprintf (msg, "Couldn't set 320x240x16 video mode: %s\n",SDL_GetError ());
		free (msg);
		exit (2);
	}
	SDL_WM_SetCaption ("GET Lose", NULL);

  gKeyLeft = 0;
  gKeyRight = 0;
  gKeyUp = 0;
  gKeyDown = 0;
  exsFrame = 0;
  i = 0;

ship = ImageLoad("data/ship/ship.bmp");
exs = ImageLoad("data/ship/exs.bmp");
bullet = ImageLoad("data/bullet/but.bmp");
back = ImageLoad("data/bg/bg.bmp"); 
ena = ImageLoad("data/bad.bmp");

  
 SDL_SetColorKey(ship, SDL_SRCCOLORKEY,SDL_MapRGB(ship->format, 0, 255, 0));
 SDL_SetColorKey(exs, SDL_SRCCOLORKEY,SDL_MapRGB(exs->format, 0, 255, 0));
 SDL_SetColorKey(bullet, SDL_SRCCOLORKEY,SDL_MapRGB(bullet->format, 0, 255, 0));
SDL_SetColorKey(ena, SDL_SRCCOLORKEY,SDL_MapRGB(ena->format, 0, 0, 0));
 SDL_SetColorKey(back, SDL_SRCCOLORKEY,SDL_MapRGB(back->format, 0, 0, 0));
 
 gLastTick = SDL_GetTicks(); 
	done = 0;
	while (!done)
	{



   SDL_Event event;
	while (SDL_PollEvent(&event)) 
	{
	  switch (event.type) 
	  {
	  case SDL_KEYDOWN:
		switch (event.key.keysym.sym)
		{
		case SDLK_LEFT:
		  gKeyLeft = 1;
		  break;
		case SDLK_RIGHT:
		  gKeyRight = 1;
		  break;
		case SDLK_UP:
		  gKeyUp = 1;
		  break;
		case SDLK_DOWN:
		  gKeyDown = 1;
		  break;
		case SDLK_SPACE:
		 addBullet();
		  break;
		  
		}
		break;

	  case SDL_KEYUP:		  
		switch (event.key.keysym.sym)
		{
		case SDLK_ESCAPE:
		  return 0;
		case SDLK_LEFT:
		  gKeyLeft = 0;
		  break;
		case SDLK_RIGHT:
		  gKeyRight = 0;
		  break;
		case SDLK_UP:
		  gKeyUp = 0;
		  break;
		case SDLK_DOWN:
		  gKeyDown = 0;
		  break;
		}
		break;
			case SDL_QUIT:
				done = 1;
				break;
			default:
				break;
			}
		}


	   render(); 
	}

	return 0;
}


Also I have read on this forum that floating point calculation are a bad thing and should be avoided. My question is how do you produce positional vectors with out them.


Thanks


Ian Mac
 
To be honest, your code is a mess. For gods sake use telling names for your vars and methods and follow conventional coding conventions.
As for how to eliminate floating point operation: easy, use integers and avoid divisions.
 
is that any better ??

Code:
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include "SDL/SDL.h"
#define PHYSICSFPS 90

int gLastTick;
int shipSpeed = 1;
int shipX = 20, shipY = 120;
int ship_Frame = 0;
int ship_Max_Frame = 3;

int Max_Main_Bullets = 10;
int Max_Small_Bullets_1 = 10;
int Max_Small_Bullets_2 = 10;
int Max_Emenies = 20;
int Max_Background = 5;

int  gKeyLeft = 0;
int  gKeyRight = 0;
int  gKeyUp = 0;
int  gKeyDown = 0;
int  Flame_Frame = 0;

int  i = 0;



SDL_Surface *screen, ship_image, *flame_image, *bullet_image, *background_image, *enemy_image;



typedef struct EnemySprite
{
int ObjNo, X, Y, Active, Frame;
}EnemySprite;

typedef struct BulletSprite
{
int ObjNo, X, Y, Active;
}BulletSprite;

typedef struct bgElements
{
int Frame, X, Y, Active;
}bgElements;


BulletSprite bullet[10];
bgElements bgElement[7];
EnemySprite enemy[20];

/ * Image handlers */


SDL_Surface * ImageLoad(char *file)
{
  SDL_Surface *temp1, *temp2;
  temp1 = SDL_LoadBMP(file);
  temp2 = SDL_DisplayFormat(temp1);
  SDL_FreeSurface(temp1);
  return temp2;
}

void DrawIMG(SDL_Surface *img, int x, int y)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}

void DrawIMG(SDL_Surface *img, int x, int y, int w, int h, int x2, int y2)
{
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_Rect dest2;
  dest2.x = x2;
  dest2.y = y2;
  dest2.w = w;
  dest2.h = h;
  SDL_BlitSurface(img, &dest2, screen, &dest);
}

/* Initialize Images */

void init(){

ship_image = ImageLoad("data/ship/ship.bmp");
flame_image = ImageLoad("data/ship/exs.bmp");
bullet_image = ImageLoad("data/bullet/bullet.bmp");
enemy_image = ImageLoad("data/enemy.bmp");
background_image= ImageLoad("data/bg/background.bmp"); 

  /* Set Transparencies */
 SDL_SetColorKey(ship_image, SDL_SRCCOLORKEY,SDL_MapRGB(ship_image->format, 0, 255, 0));
 SDL_SetColorKey(flame_image, SDL_SRCCOLORKEY,SDL_MapRGB(flame_image->format, 0, 255, 0));
 SDL_SetColorKey(bullet_image, SDL_SRCCOLORKEY,SDL_MapRGB(bullet_image->format, 0, 255, 0));
 SDL_SetColorKey(enemy_image, SDL_SRCCOLORKEY,SDL_MapRGB(enemy_image->format, 0, 0, 0));
 SDL_SetColorKey(background_image, SDL_SRCCOLORKEY,SDL_MapRGB(background_image->format, 0, 0, 0));
}


/* create a active bullet */

void addBullet(void){
int flag = 1;
	for(i=1;i < Max_Main_Bullets; i++)
	{
	if(flag &&  bullet[i].Active == 0){ 
			flag = 0;
			bullet[i].Active = 1; 
			bullet[i].X = shipX + 45;
			bullet[i].Y = shipY + 15;			  
		  }
	   
	}
}


void animate_flames(){
Flame_Frame += 1;
	if(Flame_Frame > 3) Flame_Frame = 0;
	 DrawIMG(flame_image,shipX - 8,shipY,22,26,21*Flame_Frame,0);  
}


void render(){
  int tick = SDL_GetTicks();
  if (tick <= gLastTick) 
  {
	SDL_Delay(1);
	return;
  }

  while (gLastTick < tick)
  {	 
  if (gKeyLeft) shipX -= shipSpeed;
  if (gKeyRight) shipX += shipSpeed;
  if (gKeyUp) shipY -= shipSpeed;
  if (gKeyDown) shipY += shipSpeed;

if(shipX > 280) shipX = 280;
if(shipX < 1) shipX = 1;
if(shipY > 215) shipY = 215;
if(shipY < 1) shipY = 1;

SDL_FillRect(screen,0,0);


/* position bgElement */

	for(i=1;i < Max_Background; i++)
	{
		 if(bgElement[i].Active){
		 bgElement[i].X = bgElement[i].X - 1;
		 DrawIMG(background_image, bgElement[i].X ,bgElement[i].Y,52,88,52*bgElement[i].Frame,0);
		 if(bgElement[i].X < -52){	
		 bgElement[i].X=320+rand()%10; 
		 bgElement[i].Frame = rand()%5; 
		 bgElement[i].Y = rand()%160;
		 } 
		 } 
	}

/* position Active Bullets */

	for(i=1;i < Max_Main_Bullets; i++)
	{
		if(bullet[i].Active){
		   bullet[i].X = bullet[i].X + 2;
		   DrawIMG(bullet_image, bullet[i].X ,bullet[i].Y,9,9,0,0);
		   if(bullet[i].X > 300)	bullet[i].Active=0;			 
		   }
	   
	}

/* position Active Emenies */

	for(i=1;i < Max_Emenies; i++)
	{
		 if(enemy[i].Active){
		 enemy[i].X = enemy[i].X - 2;
		 DrawIMG(enemy_image, enemy[i].X ,enemy[i].Y,34,33,34*enemy[i].Frame,0);
		 if(enemy[i].X < -52){	
		 enemy[i].X=320+rand()%10; 
		 enemy[i].Y = rand()%160;
		 } 
		 } 
	}

	 animate_flames();

	 DrawIMG(ship_image,shipX,shipY,43,29,0,0);
	 SDL_Flip(screen);
	 gLastTick += 1000 / PHYSICSFPS;
	 }
}

int main (int argc, char *argv[])
{
	char *msg;
	int done;
	  srand(time(NULL));
	Uint8* keys;

/* Initialize Images */

	init();


	/* Initialize SDL */
	if (SDL_Init (SDL_INIT_VIDEO) < 0)
	{
		sprintf (msg, "Couldn't initialize SDL: %s\n", SDL_GetError ());
		free (msg);
		exit (1);
	}
	atexit (SDL_Quit);

	screen = SDL_SetVideoMode (320, 240, 16, SDL_SWSURFACE | SDL_DOUBLEBUF);
	if (screen == NULL)
	{
		sprintf (msg, "Couldn't set 320x240x16 video mode: %s\n",SDL_GetError ());
		free (msg);
		exit (2);
	}
	SDL_WM_SetCaption ("WoW there nice round here", NULL);

 
 gLastTick = SDL_GetTicks(); 
	done = 0;
	while (!done)
	{



   SDL_Event event;
	while (SDL_PollEvent(&event)) 
	{
	  switch (event.type) 
	  {
	  case SDL_KEYDOWN:
		switch (event.key.keysym.sym)
		{
		case SDLK_LEFT:
		  gKeyLeft = 1;
		  break;
		case SDLK_RIGHT:
		  gKeyRight = 1;
		  break;
		case SDLK_UP:
		  gKeyUp = 1;
		  break;
		case SDLK_DOWN:
		  gKeyDown = 1;
		  break;
		case SDLK_SPACE:
		 addBullet();
		  break;
		  
		}
		break;

	  case SDL_KEYUP:		  
		switch (event.key.keysym.sym)
		{
		case SDLK_ESCAPE:
		  return 0;
		case SDLK_LEFT:
		  gKeyLeft = 0;
		  break;
		case SDLK_RIGHT:
		  gKeyRight = 0;
		  break;
		case SDLK_UP:
		  gKeyUp = 0;
		  break;
		case SDLK_DOWN:
		  gKeyDown = 0;
		  break;
		}
		break;
			case SDL_QUIT:
				done = 1;
				break;
			default:
				break;
			}
		}


	   render(); 
	}

	return 0;
}
 
I am also pretty new to programming but i will see if i can help. :)

You want to ship to move 1 pixel every frame right?

This confuses me a bit in your render function

Code:
 if (tick <= gLastTick)
  {
	SDL_Delay(1);
	return;
  }
This is to cap the framerate i think? I would just use

while(SDL_GetTicks() - gLastTick <= 1000/PHYSICSFPS 90);

and instead of gLastTick += 1000 / PHYSICSFPS;

just put gLastTick = SDL_GetTicks(); at the end of the render function.

The next thing is this.
Code:
while (gLastTick < tick)
{	 
...
...
}
You are going to be moving the ship way more than 1 pixel per frame with this while loop, i would delete it(but still keep the code that is in it).

I hope this helps you.
 
Back
Top