Sprite Movings are Buzzing.

Started by
7 comments, last by YasinKhalil 11 years, 4 months ago
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!
Advertisement
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.

https://www.kbasm.com -- My personal website

https://github.com/wqking/eventpp  eventpp -- C++ library for event dispatcher and callback list

https://github.com/cpgf/cpgf  cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.

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);
dry.png

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)


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)

Omae Wa Mou Shindeiru

dry.png

[quote name='BeerNutts' timestamp='1354726463' post='5007440']
[quote name='Aaru' timestamp='1354722066' post='5007420']
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.
[/quote]

It is a valid suggestion. Especially more valid than your useless comment.
[/quote]

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)

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.

This topic is closed to new replies.

Advertisement