04-30-2005, 03:54 AM
This is a set of routines I threw together because SDL routines have a lot of things that I don't need since I'm blitting to a 2d surface. It includes routines to create a window based on a configuration held in a file, load a masked bitmap from a file including changing the video mode to something usable, blit a bitmap, read any input from the keyboard, mouse, or joysticks, and do a couple other trivial things. Eventually, I want to take this lib and make it so you can choose between SDL and OpenGL, so I may add a #define for SDL_Surface ptr so I can keep that open.
This works best when popped into a .bi file and included into your program so you don't have to do anything else.
I'll have to do a LOT more work on it before it's useful to most people, but I'm posting the initial code here anyway, since it's a useful amalgamation of subs/functions for anyone who doesn't want to have to trudge through setting up APIs when they just want to get something coded.
Functions are:
declare sub omaSDL_Init()
Creates a window based on a configuration stored in config.cfg, an example of which is in Star Phalanx and Rambo vs. Kitty Cat. If there is no file, it will create a 640x480x16bit window. If there's a problem, it will exit gracefully, with an error message describing the problem.
declare sub omaQuit ()
This will exit SDL and FB.
declare sub omaGetScreenDimensions (byref w as integer,byref h as integer)
This will return the dimensions of the screen surface.
declare Sub omaPageFlip()
Will flip the page, and do all the things which need to be done when that happens. It currently won't clear the screen when you pageflip, for better or for worse.
declare function omaLoadMaskedGraphic(filename$) as sdl_Surface ptr
This function will load a BMP file from filename$ into a sdl_Surface ptr you declare. It will also apply masking to the colour magenta (255,255,0), and convert the bitmap to the ideal screen surface. If there's an error, it will quit everything gracefully with a text error message describing the problem.
declare sub omaBlitImage(x as integer,y as integer,image as sdl_surface ptr)
There isn't much work involved in blitting with SDL, but this makes the job even easier.
declare sub omaDebugEvent (Text$)
Add a debug event. This currently prints to the screen if DebugEvents are active
declare sub omaDebugEventsActive (status as integer)
Activates or deactivates DebugEvents. This will give extra information from inside each routine (which uses it), and will display any messages you've included in your own code using the omaDebugEvent sub.
declare FUNCTION omaMultiKey (x)
This is the UltimaInput function. Any key press, mouse movement/button press or joystick movement/button press will activate a certain multikey code, which can be polled for.
declare FUNCTION omagetSingleEvent as integer
Another function from UltimaInput, this will wait for any input event, then return that event. This is useful for configuration because there are too many code events to remember!!
Here's a sample program showing most of the elements in action:
So without further talk, here it is.
This works best when popped into a .bi file and included into your program so you don't have to do anything else.
I'll have to do a LOT more work on it before it's useful to most people, but I'm posting the initial code here anyway, since it's a useful amalgamation of subs/functions for anyone who doesn't want to have to trudge through setting up APIs when they just want to get something coded.
Functions are:
declare sub omaSDL_Init()
Creates a window based on a configuration stored in config.cfg, an example of which is in Star Phalanx and Rambo vs. Kitty Cat. If there is no file, it will create a 640x480x16bit window. If there's a problem, it will exit gracefully, with an error message describing the problem.
declare sub omaQuit ()
This will exit SDL and FB.
declare sub omaGetScreenDimensions (byref w as integer,byref h as integer)
This will return the dimensions of the screen surface.
declare Sub omaPageFlip()
Will flip the page, and do all the things which need to be done when that happens. It currently won't clear the screen when you pageflip, for better or for worse.
declare function omaLoadMaskedGraphic(filename$) as sdl_Surface ptr
This function will load a BMP file from filename$ into a sdl_Surface ptr you declare. It will also apply masking to the colour magenta (255,255,0), and convert the bitmap to the ideal screen surface. If there's an error, it will quit everything gracefully with a text error message describing the problem.
Code:
Example:
dim mario as sdl_Surface ptr
mario = omaLoadMaskedGraphic("mario.bmp")
declare sub omaBlitImage(x as integer,y as integer,image as sdl_surface ptr)
There isn't much work involved in blitting with SDL, but this makes the job even easier.
Code:
Example:
omaBlitImage x, y, myBitmap
Add a debug event. This currently prints to the screen if DebugEvents are active
declare sub omaDebugEventsActive (status as integer)
Activates or deactivates DebugEvents. This will give extra information from inside each routine (which uses it), and will display any messages you've included in your own code using the omaDebugEvent sub.
declare FUNCTION omaMultiKey (x)
This is the UltimaInput function. Any key press, mouse movement/button press or joystick movement/button press will activate a certain multikey code, which can be polled for.
declare FUNCTION omagetSingleEvent as integer
Another function from UltimaInput, this will wait for any input event, then return that event. This is useful for configuration because there are too many code events to remember!!
Here's a sample program showing most of the elements in action:
Code:
'$include:'omalib.bi'
omaSDL_Init()
dim mario as SDL_Surface ptr
dim w, h
mario = omaLoadMaskedGraphic("mario.bmp")
while not omaMultiKey(27) 'while you don't press escape
omaGetScreenDimensions w,h
omaBlitImage int(rnd(1) * w), int(rnd(1) * h), mario
omaPageFlip ()
wend
omaQuit ()
So without further talk, here it is.
Code:
'omaLib SDL wrapper library
'By Saint SJ
'$include: "SDL\SDL.bi"
'****WRAPPER FUNCTION DECLARATIONS
declare sub omaBlitImage(x as integer,y as integer,image as sdl_surface ptr)
declare Sub omaPageFlip()
declare sub omaSDL_Init()
declare FUNCTION omaMultiKey (x)
declare FUNCTION omagetSingleEvent as integer
declare sub omaDebugEvent (Text$)
declare sub omaDebugEventsActive (status as integer)
declare function omaLoadMaskedGraphic(filename$) as sdl_Surface ptr
declare sub omaQuit ()
declare sub omaGetScreenDimensions (byref w as integer,byref h as integer)
'******Pixel surface declarations
dim shared omaScreenSurface as SDL_Surface ptr
dim shared omaFramesPerSecond
dim shared omaFramePeriod
dim shared omaDebugEvents
sub omaQuit ()
SDL_Quit()
end
end sub
function omaLoadMaskedGraphic(filename as string) as sdl_Surface ptr
dim LoadedFile as sdl_surface ptr
dim ConvertedFile as sdl_surface ptr
LoadedFile = SDL_LoadBMP(filename)
if LoadedFile = 0 then
omaDebugEvent Filename + ".bmp failed to load!"
sleep
omaQuit()
end if
SDL_SetColorKey LoadedFile, SDL_SrcColorKey, SDL_MapRGB(LoadedFile->Format, 255, 0, 255)
ConvertedFile = SDL_DisplayFormat(LoadedFile)
SDL_FreeSurface LoadedFile
omaLoadMaskedGraphic = ConvertedFile
end function
Sub omaPageFlip()
static omaOldTimer
SDL_Flip omaScreenSurface
SDL_PumpEvents
If omaOldTimer <= sdl_GetTicks () Then
omaOldTimer = sdl_GetTicks () + omaFramePeriod
Else
SDL_Delay (omaOldTimer - sdl_GetTicks)
End If
End Sub
sub omaBlitImage(x as integer,y as integer,image as sdl_surface ptr)
Dim Rectangle As SDL_Rect
Dim Rectangle2 As SDL_Rect
Rectangle.x = 0
Rectangle.y = 0
rectangle.w = image->w
rectangle.h = image->h
Rectangle2.x = x
Rectangle2.y = y
SDL_BlitSurface image, @rectangle, omaScreenSurface, @rectangle2
End Sub
sub omaSDL_Init ()
dim x AS STRING
dim Xres AS INTEGER
dim Yres AS INTEGER
dim depth AS INTEGER
dim ScreenOptions AS INTEGER
dim fileno AS INTEGER
'Before we open the screen, we have the simplest possible config.cfg reader.
'Later versions will use GetParameter$(x,y) to make config options on one line.
fileno = FreeFile
Open "config.cfg" For Input As #fileno
While Not EOF(fileno)
Input #fileno, x$
x$ = LCase$(LTrim$(RTrim$(x$)))
Select Case x$
Case "xres"
Input #fileno, x$
XRES = Val(LCase$(LTrim$(RTrim$(x$))))
Case "yres"
Input #fileno, x$
YRES = Val(LCase$(LTrim$(RTrim$(x$))))
Case "depth"
Input #fileno, x$
depth = Val(LCase$(LTrim$(RTrim$(x$))))
Case "sdl_hwsurface"
screenoptions = screenoptions OR SDL_HWSURFACE
Case "sdl_swsurface"
screenoptions = screenoptions OR SDL_SWSURFACE
Case "sdl_doublebuf"
screenoptions = screenoptions OR SDL_DOUBLEBUF
Case "sdl_fullscreen"
screenoptions = screenoptions OR SDL_FULLSCREEN
Case "sdl_hwaccel"
screenoptions = screenoptions OR SDL_HWACCEL
Case "sdl_hwpalette"
screenoptions = screenoptions OR SDL_HWPALETTE
End Select
'SDL_DOUBLEBUF )'or SDL_FULLSCREEN
Wend
Close #fileno
if XRES = 0 and YRES = 0 then
omaDebugEvent "There was no configuration file! Using default resolution!"
XRES = 640
YRES = 480
Depth = 16
ScreenOptions = SDL_SWSurface AND SDL_Doublebuf
end if
SDL_Init (SDL_INIT_VIDEO)
omaScreenSurface = SDL_SetVideoMode(XRES, YRES, depth, screenoptions)
If omaScreenSurface = 0 Then
omaDebugEvent "There was an error initilizing with SDL!"
omaDebugEvent "Parameters"
omaDebugEvent "Resolution: "+str$(XRES)+" x "+str$(YRES)
omaDebugEvent "Depth:"+str$(depth)
omaDebugEvent "Screen Options: "+str$(screenoptions)+" <- this is supposed to be a number"
omaDebugEvent ""
omaDebugEvent "Press any key to continue"
SDL_Quit
sleep
END 1
End If
omaFramesPerSecond = 30
omaFramePeriod = (1! / omaFramesPerSecond) * 1000!
end sub
FUNCTION omaMultiKey (x)
static keys(0 to 1024) as short
dim event as SDL_Event
dim num
dim a, b
'HIGHEST = 319 LOWEST = 0
'So, keyflag protocol:
'0-320 will be keyflags
'320-330 will be mouseFlags
'350-370 will be Joystick 1
'380-400 will be Joystick 2
while( SDL_PollEvent ( @event ) )
select case event.type
case SDL_KeyDOWN:
keys(event.key.keysym.sym) = -1
case SDL_KeyUP:
keys(event.key.keysym.sym) = 0
case SDL_MOUSEMOTION:
'326,327,328,329 are mouse movement events
keys(326) = (event.motion.xrel < 0)
keys(327) = (event.motion.xrel > 0)
keys(328) = (event.motion.yrel < 0)
keys(329) = (event.motion.yrel > 0)
case SDL_MOUSEBUTTONDown:
'SDL mouse buttons 321->325
num = 320+event.button.button
keys(num) = -1
case SDL_MOUSEBUTTONUP:
num = 320+event.button.button
keys(num) = 0
case SDL_JOYAXISMOTION
'axis events on
'400 + (Joysticknumber * 100) + (axis * 2)
'There won't be more than 5 axises on a joystick, so x00-x20 are
'reserved...
num = 400 + (event.jaxis.which * 100) + (event.jaxis.axis * 2)
keys(num) = (event.jaxis.value < 0)
keys(num + 1) = (event.jaxis.value > 0)
case SDL_JoyBallMotion
'jball
'x20-x40 are Ball events. 20 is room for 5 balls.
'There's something @£$£ up if 5 balls isn't enough for you.
'num=420 + (event.jaxis.which * 100) + (which * 4)
num = 420 + (event.jball.which * 100) + (event.jaxis.axis * 2)
keys(num) = (event.jball.xrel < 0)
keys(num+1) = (event.jball.xrel > 0)
keys(num+2) = (event.jball.yrel < 0)
keys(num+3) = (event.jball.yrel > 0)
case SDL_JoyHatMotion
'jhat
'x40-x80 are Hat events.40 is room for 5 hats.
'If you need 5 hats, I suggest surgery.
num = 440 + (event.jhat.which * 100) + (event.jhat.hat * 8)
for a = 1 to 8
keys(num + a) = 0
next a
keys(num + event.jhat.value) = -1
case SDL_JoyButtonDown
'button events are x80-x99
num = 40 + (event.jbutton.which * 100) + (event.jbutton.button)
keys(num) = -1
case SDL_JoyButtonUp
num = 40 + (event.jbutton.which * 100) + (event.jbutton.button)
keys(num) = 0
end select
wend
omaMultiKey = keys(x)
END FUNCTION
FUNCTION omaGetSingleEvent as integer
dim event as SDL_Event
dim num
dim a, b
'This function will return 0 if no event is in the queue, otherwise it'll return
'the keyflag protocol number.
'So, keyflag protocol:
'0-320 will be keyflags
'321-329 will be mouseFlags
'400-500 will be Joystick 1
'500-600 will be Joystick 2
'600-700 will be Joystick 3
'700-800 will be Joystick 4
'900-1000 will be Joystick 5
while( SDL_PollEvent ( @event ) )
select case event.type
case SDL_KeyDOWN:
omagetSingleEvent = event.key.keysym.sym
exit function
case SDL_MOUSEMOTION:
'326,327,328,329 are mouse movement events
if (event.motion.xrel < 0) then omagetSingleEvent = 326:exit function
if (event.motion.xrel > 0) then omagetSingleEvent = 327:exit function
if (event.motion.yrel < 0) then omagetSingleEvent = 328:exit function
if (event.motion.yrel > 0) then omagetSingleEvent = 329:exit function
case SDL_MOUSEBUTTONDown:
'SDL mouse buttons 321->325
omagetSingleEvent = 320+event.button.button
exit function
case SDL_JOYAXISMOTION
num = 400 + (event.jaxis.which * 100) + (event.jaxis.axis * 2)
omagetSingleEvent = num
exit function
case SDL_JoyBallMotion
'jball
'x20-x40 are Ball events. 20 is room for 5 balls.
'There's something @£$£ up if 5 balls isn't enough for you.
'num=420 + (event.jaxis.which * 100) + (which * 4)
num = 420 + (event.jball.which * 100) + (event.jaxis.axis * 2)
if (event.jball.xrel < 0) then omagetSingleEvent = num
if (event.jball.xrel > 0) then omagetSingleEvent = num + 1
if (event.jball.yrel < 0) then omagetSingleEvent = num + 2
if (event.jball.yrel > 0) then omagetSingleEvent = num + 3
exit function
case SDL_JoyHatMotion
'jhat
'x40-x80 are Hat events.40 is room for 5 hats.
'If you need 5 hats, I suggest surgery.
num = 440 + (event.jhat.which * 100) + (event.jhat.hat * 8)
omagetSingleEvent = num + event.jhat.value
exit function
case SDL_JoyButtonDown
'button events are x80-x99
num = 40 + (event.jbutton.which * 100) + (event.jbutton.button)
omagetSingleEvent = num
exit function
end select
wend
omaGetSingleEvent = 0
exit function
END FUNCTION
SUB omaDebugEvent (Text$)
if omaDebugEvents then print text$
end sub
sub omaDebugEventsActive(status as integer)
omaDebugEvents = status
end sub
sub omaGetScreenDimensions (byref w as integer,byref h as integer)
w = omaScreenSurface->w
h = omaScreenSurface->h
end sub