Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
2D sprite rotation and movement
#1
The following is an update to the sprite animation / movement code that used the rotozoomer in sdl_gfx to "animate" a sprite turning 360 degrees. The sprite then will move in the direction it is facing based on some simple calculations.

However, simple or not, I seem to have run into a bit of a problem with the directional calculations
Code:
ship1.x = ship1.x - (ship1.speed * sin((ship1.facing * 3.14159) / 180))
    ship1.y = ship1.y - (ship1.speed * cos((ship1.facing * 3.14159) / 180))
used to determine forward movement of the "ship". I get good rotation of the sprite, but seem to only get forward movement in 8 directions only. The result is a sprite rotated at say 60 degrees but only moving at a 45 degree angle (like its sliding).

I have attempted looking up calculations for sprite movement this way, but have not found anything outside of what I have come up with.

Any help on this?

To test the complete code use the following:

Code:
option explicit

'  include the sdl header in order to easily use the sdl.dll
'$include: "sdl/sdl.bi"
'$include: "sdl/sdl_image.bi"
'$include: "sdl/sdl_gfx_rotozoom.bi"

'  some defines to make code easier to read/maintain
#define FALSE 0
#define TRUE  NOT FALSE
#define SCREEN_WIDTH  640
#define SCREEN_HEIGHT 480

'  declare subs
declare sub screen_render()

'  define a sprite type to encapsulate the different variables used
'  to control our simple sprite
type gamesprite
  image as SDL_Surface ptr
  facing as double
  x as long
  y as long
  speed as long
end type
'  declare a variable for our sprite as a simple sprite type
dim shared ship1 as gamesprite
'  declare a variable for our main screen
dim shared screen1 as SDL_Surface ptr
'  declare a variable to track events (keyboard, etc.)
dim event as SDL_Event
'  declare a general use variable to catch returning information from called functions
dim result as unsigned integer
'  declare a "flag" for tracking gamestate
'  this level the state of the game is either TRUE or FALSE
dim gamestate as integer
dim keys as byte ptr

'  initialize video mode subsystem
result = SDL_Init(SDL_INIT_VIDEO)
'  check for success/failure
if result <> 0 then
  end 1
end if

'  create an sdl window
screen1 = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_ANYFORMAT )
'  check for success/failure
if screen1 = 0 then
  SDL_Quit
  end 2
end if

'  load bitmap image into "sprite"
ship1.image = IMG_Load("sdl_ship02.png")
'  check for success/failure
if ship1.image = 0 then
  SDL_Quit
  end 3
end if
'  set the transparent color in our sprite image
SDL_SetColorKey(ship1.image, SDL_SRCCOLORKEY, SDL_MapRGB(ship1.image->format, 255, 0, 255))

'  set beginning values for sprite information
ship1.facing = 0
ship1.x = 300
ship1.y = 200
ship1.speed = 1

'  set game state
gamestate = TRUE
'  enter main game loop
do
  '  process events
  while SDL_PollEvent( @event ) <> 0
    '  check for user exit
    if event.type = SDL_QUIT_ then
      gamestate = FALSE
    end if
    '  check user keypress
    if event.type = SDL_KEYDOWN then
      '  escape key to exit
      if event.key.keysym.sym = SDLK_ESCAPE then gamestate = FALSE
    end if
  wend
  '  get current keyboard state (keys held down)
  keys = SDL_GetKeyState(NULL)
  if keys[SDLK_UP] then

    '  Angle is changed from degrees to radians since QBasic SIN and COS functions operate with radians.
    '  Angle Radians = (ship1.facing * 3.14159) / 180
    ship1.x = ship1.x - (ship1.speed * sin((ship1.facing * 3.14159) / 180))
    ship1.y = ship1.y - (ship1.speed * cos((ship1.facing * 3.14159) / 180))

  end if
  if keys[SDLK_LEFT] then
    ship1.facing = ship1.facing + 1
    if ship1.facing > 359 then ship1.facing = 0
  end if
  if keys[SDLK_RIGHT] then
    ship1.facing = ship1.facing - 1
    if ship1.facing < 0 then ship1.facing = 359
  end if
  '  call screen render routine
  screen_render
loop until gamestate = FALSE
SDL_FreeSurface( ship1.image )
SDL_Quit
end

'  screen_render
'  subroutine to handle the graphics updates
sub screen_render()
  dim blitdst as SDL_Rect
  dim scratch as SDL_Surface ptr
  '  lock surface if needed
  if SDL_MUSTLOCK( screen1 ) then
    if SDL_LockSurface( screen1 ) < 0 then
      exit sub
    end if
  end if
  '  perform graphics updates here
  '  clear entire screen
  SDL_FillRect(screen1, 0, 0)
  scratch = rotozoomSurface( ship1.image, ship1.facing, 1, SMOOTHING_ON)
  '  set screen "outline" to recieve sprite frame from main bitmap
  blitdst.x = ship1.x - (scratch->w / 2)
  blitdst.y = ship1.y - (scratch->h / 2)
  blitdst.w = 31
  blitdst.h = 31
  ' draw the sprite
  SDL_BlitSurface(scratch, 0, screen1, @blitdst)
  '  end graphics updates
  '  unlock surface if needed
  if SDL_MUSTLOCK( screen1 ) then
    SDL_UnlockSurface( screen1 )
  end if
  '  force entire screen update
  SDL_UpdateRect( screen1, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT )
end sub
ature has its way of warning a person away from danger: The distinct black and white coloration on a skunk, the chilling buzz of a rattlesanke, a redneck handing you his beer and saying "Watch this!"
Reply


Messages In This Thread
2D sprite rotation and movement - by steven_basic - 02-15-2005, 10:38 PM
2D sprite rotation and movement - by steven_basic - 02-16-2005, 03:14 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)