02-15-2005, 10:38 PM
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
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:
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))
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!"