Jump to content

  • Log In with Google      Sign In   
  • Create Account


Sprite Movings are Buzzing.


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
8 replies to this topic

#1 ibuki917   Members   -  Reputation: 106

Like
0Likes
Like

Posted 04 December 2012 - 08:22 PM

i am making shoot them up game.

however, bullets are buzzing.

bullet moving is not smooth.


My Develop Environment is MS Visual Studio 2010, Windows 7 and SDL 1.2

below is pseudo-code of my bullet moving logic.
process the code every frame.

double x;

double y;

double Speed;


//speed(angle) addition per frame. (addition may be 0.0 if unneccerary)

double speed_acc;
double angle_acc;
double Radian = abs(Angle - 360.0) * (PI / 180.0);

x = x + (Speed * Cos (Radian));

y = y + (Speed * Sin(Radian));


Speed = Speed + speed_acc;

Angle = Angle + angle_acc;


please help me.. and thank you for reading my question!

Sponsor:

#2 wqking   Members   -  Reputation: 756

Like
0Likes
Like

Posted 05 December 2012 - 03:09 AM

double Radian = abs(Angle - 360.0) * PI / 180.0;

Not sure if above line is the problem, I would caculate the multiply first, because PI / 180 may cause accuracy losing.

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.


#3 unbird   Crossbones+   -  Reputation: 4973

Like
1Likes
Like

Posted 05 December 2012 - 03:46 AM

Hardly. That division might even be eliminated by the compiler since PI / 180.0 is constant. Precision is seldom a problem in cases like these, you don't even need doubles for that.

But why the abs ? This is definitively a wrong conversion from degree to radians.

Also: I don't see you taking the time passed since the last frame into account (aka delta or deltaTime). Something like:
    double deltaSpeed = Speed * deltaTime;
    x = x + deltaSpeed * Cos(Radian);
    y = y + deltaSpeed * Sin(Radian);


#4 Aaru   Members   -  Reputation: 224

Like
-3Likes
Like

Posted 05 December 2012 - 09:41 AM

Posted Image

Edited by Aaru, 06 December 2012 - 11:59 AM.


#5 BeerNutts   Crossbones+   -  Reputation: 2766

Like
1Likes
Like

Posted 05 December 2012 - 10:54 AM

Use "floats" if you want things to move smoother.

double is a double precision float (which is what he is using), so, no, this is not a valid suggestion at all.
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#6 LorenzoGatti   Crossbones+   -  Reputation: 2628

Like
2Likes
Like

Posted 05 December 2012 - 11:47 AM

double Radian = abs(Angle - 360.0) * (PI / 180.0);
...
Angle = Angle + angle_acc;
Three times wrong.
  • Angle isn't bounded between 0 and 360, or any other interval.
  • When Angle decreases from slightly more than 360 to slightly less than 360, Radian "bounces" from positive and decreasing to positive and increasing.
  • You should use only one variable, measured in radians, to avoid a completely useless conversion.
Suggested fix:
angle=angle+angularVelocity;
if(angle>TWO_PI) angle= angle% TWO_PI;
if(angle<0.0) angle= TWO_PI -(-angle% TWO_PI);
...
cos(angle)

Produci, consuma, crepa

#7 Aaru   Members   -  Reputation: 224

Like
-6Likes
Like

Posted 05 December 2012 - 12:50 PM

Posted Image

Edited by Aaru, 06 December 2012 - 11:55 AM.


#8 BeerNutts   Crossbones+   -  Reputation: 2766

Like
2Likes
Like

Posted 05 December 2012 - 01:24 PM



Use "floats" if you want things to move smoother.

double is a double precision float (which is what he is using), so, no, this is not a valid suggestion at all.


It is a valid suggestion. Especially more valid than your useless comment.


I assumed, since this isn't the "For Beginners" forum, that I wouldn't have to explain what double precision float means, but, Aaru, you've proven otherwise.

A float is typically stored using 32-bits. This limits the precision it can obtain. When I say "precision" I mean the values it can represent, both in decimal digits, and in maximum value. A double is typically stored using 64-bits. Although, they could be exactly the same (since the C/C++ standards do not state otherwise), rarely is this the case.

So, in theory, using a float would lessen the precision of the moving sprite, while, practically, it would act exactly the same; thus, your suggestion is completely invalid.

Aaru, what reason do you say using a float would make it smoother?
My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

#9 Aaru   Members   -  Reputation: 224

Like
1Likes
Like

Posted 06 December 2012 - 11:33 AM

I wrote a simple program in SDL that shows a way of implementing Projectile Motion without any "buzzing".
Controls : ( R) : resets the balls position, "hold" (Space) : plays with the angle in a cool way
Hope It helps.

#include <SDL.h>
#include <SDL_image.h>
#include <cmath>

#define PI 3.14159265358979323846
#define WWIDTH 640
#define WHEIGHT 480
#define SPRITESIZE 48

bool Running = true;
float DeltaTime = 0.0f;

int   X = WWIDTH/2;
int   Y = WHEIGHT/2;
float  SpeedX = 0.0f;
float  SpeedY = 0.0f;
float  MaxSpeedX = 2.01f;
float  MaxSpeedY = 2.01f;
float  AccelX = 5.0f;
float  AccelY = 5.0f;

int   Angle = 45;

SDL_Surface* SurfDisplay = NULL;
SDL_Surface* SurfBack = IMG_Load("./Background.jpg");
SDL_Surface* SurfProj = NULL;

void LoadData()
{
SDL_Surface* SurfTemp = IMG_Load("./Projectile.png");
SurfProj = SDL_DisplayFormatAlpha(SurfTemp);

SDL_FreeSurface(SurfTemp);
}

bool Init()
{
// Init
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
  return false;
}

// Vidio Init
if((SurfDisplay = SDL_SetVideoMode(WWIDTH, WHEIGHT, 32, SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
{
  return false;
}

//Set Window Title
SDL_WM_SetCaption("Projectile Motion","");
// Hide the Mouse Cursor
SDL_ShowCursor(0);
// Key Repeat
SDL_EnableKeyRepeat(1, SDL_DEFAULT_REPEAT_INTERVAL / 3);

//Load Projectile.png
LoadData();
}

bool Draw(SDL_Surface* SurfDest, SDL_Surface* SurfSrc, int X, int Y)
{
if(SurfDest == NULL || SurfSrc == NULL)
{
  return false;
}

SDL_Rect DestR;
DestR.x = X;
DestR.y = Y;
SDL_BlitSurface(SurfSrc, NULL, SurfDest, &DestR);
return true;
}
void OnEvent(SDL_Event* AnEvent)
{
switch(AnEvent->type)
{
  case SDL_QUIT:
   Running = false;
   break;
  case SDL_KEYDOWN:
   switch(AnEvent->key.keysym.sym)
   {
	case SDLK_ESCAPE:
	 Running = false;
	 break;
	case SDLK_r:
	 //Reset Projectile
	 X = WWIDTH/2;
	 Y = WHEIGHT/2;
	 Angle = 45;
	 break;
	case SDLK_SPACE:
	 //Cool Projectile Motion Path
	 Angle += tan(1* acos(1* asin(.1)));
	 break;
   }
   break;
  case SDL_MOUSEBUTTONDOWN:
   break;
}
}

void OnLoop()
{
SpeedX += AccelX * cos(Angle*PI/180) * DeltaTime;
SpeedY += AccelY * sin(-Angle*PI/180) * DeltaTime;

if(SpeedX > MaxSpeedX)  SpeedX =  MaxSpeedX;
if(SpeedX < -MaxSpeedX) SpeedX = -MaxSpeedX;
if(SpeedY > MaxSpeedY)  SpeedY =  MaxSpeedY;
if(SpeedY < -MaxSpeedY) SpeedY = -MaxSpeedY;

X += SpeedX;
Y += SpeedY;

//Keep Projectile In Window
if(Y < 0){SpeedY *= -1; Angle = -Angle-360;}
if(Y > WHEIGHT - SPRITESIZE){SpeedY *= -1; Angle = -Angle+360;}
if(X < 0){SpeedX *= -1; Angle = -Angle+180;}
if(X > WWIDTH - SPRITESIZE){SpeedX *= -1; Angle = -Angle-180;}

//Keep Angle Within The Range of +/- 360
if(Angle >= 360){Angle -= 360;};
if(Angle <= -360){Angle += 360;};

char Buffer[255];
sprintf(Buffer, "Projectile Motion. Current Angle: %d", Angle);
SDL_WM_SetCaption(Buffer, Buffer);
}

void OnDraw(SDL_Surface* screen)
{
//Draw The Background
Draw(screen,SurfBack,0,0);

//Draw The Projectile
Draw(screen,SurfProj,X,Y);

//Flip the Display Buffer
SDL_Flip(SurfDisplay);

}
void Cleanup()
{
SDL_FreeSurface(SurfDisplay);

SurfDisplay = NULL;

SDL_Quit();

exit(0);
}

int main(int argc, char* argv[])
{
SDL_Event Event;
Uint32 LastTime = NULL;

Init();

while(Running)
{
  DeltaTime = ((SDL_GetTicks() - LastTime) / 1000.0f) * 32.0f;
  while(SDL_PollEvent(&Event))
  {
   OnEvent(&Event);
  }
  OnLoop();
  OnDraw(SurfDisplay);
  LastTime = SDL_GetTicks();
  SDL_Delay(1);
}
Cleanup();
return 0;
}


Attached is the .exe to try it out.

Attached Files


Edited by Aaru, 06 December 2012 - 11:36 AM.





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