Below is some base code I'm using for Ludum Dare. Nothing new here really. I'm including it so I don't have to worry about coding screen resizing, loading maps, loading TextureMap sprites, dealing with polyvector commands and frame skipping. This code should take care of all that so I can get on with making a terrible 2D game. :)
Globals: -
// Plaform and resolution settings
GLOBAL zoom# = 1.0 // proportional zoom for different screens. 1 is 800x480
GLOBAL plats% = 0 // for platform type - just PC for first release
GLOBAL xres#, yres# // actual screen resolution goes here
GLOBAL midxres#, midyres# // middle of screen
GLOBAL xvir#, yvir# // virtual screen size
GLOBAL xborder#, yborder# // border, if needed
GLOBAL xmap#, ymap# // map size
GLOBAL xtile#, ytile# // tile size
GLOBAL map%[] // the map array itself
GLOBAL pmap%[] // the path-finding map
TYPE texturemap
x# // x pos on sheet
y# // y pos on sheet
w# // width
h# // height
ENDTYPE
GLOBAL sprites#[] AS texturemap // Texture map for sprites
GLOBAL tiles#[] AS texturemap // Texture map for tiles
GLOBAL TMsprites% // where is sprite texture map held?
GLOBAL TMtiles% // where is tile texture held?
// Poly handling
GLOBAL xoff1#, yoff1# // rotation offsets
GLOBAL xoff2#, yoff2# // rotation offsets
GLOBAL xoff3#, yoff3# // rotation offsets
GLOBAL xoff4#, yoff4# // rotation offsets
GLOBAL SF_curd# = 16.66666666666667 // current d frame
GLOBAL throttle% = FALSE // should we limit the speed the app is going?
GLOBAL SF_fullflag% = FALSE // has 60FPS ever been reached as a guess?
// Not yet confirmed but useful
GLOBAL SF_timer#, SF_oldtimer# // timers for measuring speed of app
GLOBAL SF_baseFPS#
GLOBAL SF_framenum# = 60 // number of frames in loop count
GLOBAL SF_frames#[] // array for storing previous FPS times in
DIM SF_frames[SF_framenum] // 60 frames worth of timings to measure
GLOBAL SF_loopframe% = BOUNDS(SF_frames[], 0) // if this reached then loop to 0
GLOBAL SF_curframe% = 0 // current frame working on
GLOBAL SF_countframe% = 0 // how many frames have we counted so far. Doesn't go over SF_loopframe
GLOBAL SF_flagloop% = FALSE // is true once SF_loopframe has been done once
GLOBAL SF_sumframes# = 0 // summary of frame timings
GLOBAL SF_m# = 0 // running measure
GLOBAL SF_mflag% = FALSE // has a measure adjustment been made in the last 60 frames?
GLOBAL loopdo# = 0 // number of loops to go through
// The Guessing game
GLOBAL SF_guess% = 0 // If there is a guess this will be it
GLOBAL guessnum% = 3 // how many guesses / virtual seconds in a row have to be the same for SF_curd adjustment
GLOBAL curguess% = 0 // current guess
GLOBAL gstore#[] // array for guess counts
DIM gstore[guessnum] // arrays
// Controls
GLOBAL press# = 0 // how long has touch / button been pressed
GLOBAL mx#, my#, ma#, mb# // mouse button
Base Code: -
FUNCTION LoadMap: name$
LOCAL sbyte%
LOCAL xnow%, ynow%
LOCAL solid% = 10 // from this tile number upwards the way is unpassable
OPENFILE(1, name$, 1)
FILESEEK 1, 8, 0
READWORD 1, sbyte // bad integer type for direct read so put into sbyte first
xmap = sbyte // x dimension of map
READWORD 1, sbyte
ymap = sbyte // y dimension of map
READBYTE 1, sbyte
xtile = sbyte // x size for tile
READBYTE 1, sbyte
ytile = sbyte // y size for tile
DIM map[xmap][ymap] // dimension the array
DIM pmap[xmap][ymap] // dimension the pathfinding array
FOR i = 0 TO (xmap*ymap)-1
READBYTE 1, sbyte
map[xnow][ynow] = sbyte
IF sbyte >= solid // if tile is solid
pmap[xnow][ynow] = 0 // can't go here
ELSE
pmap[xnow][ynow] = 1 // is walkable
ENDIF
INC xnow
IF xnow = xmap
xnow = 0
INC ynow
ENDIF
NEXT
CLOSEFILE 1
ENDFUNCTION
FUNCTION LoadSprites: filename$, sprsheet%
LOCAL sprnum% // number of sprites successfully added
LOCAL tempspr# AS texturemap
LOCAL chr% // for reading back character
LOCAL sprname$ // sprite name
LOCAL num$ // to convert to number
// load new texture map into a sprite sheet
LOADSPRITE filename$+".png", sprsheet
IF OPENFILE(1, filename$+".txt", 1) = FALSE
PRINT "Damned odd!! Texture Packer file not found", 0, 0
PRINT filename$+".txt", 0, 10
PRINT GETCURRENTDIR$(), 0, 20
SHOWSCREEN
MOUSEWAIT
ELSE // load sprites
WHILE ENDOFFILE(1) = FALSE
// read sprite name
chr = 0
sprname$ = ""
WHILE chr <> 44
READUBYTE 1, chr
IF chr <> 44 THEN INC sprname$, CHR$(chr)
WEND
// move beyond space
FILESEEK 1, 1, 1
// read x position
chr = 0
num$ = ""
WHILE chr <> 44
READUBYTE 1, chr
IF chr <> 44 THEN INC num$, CHR$(chr)
WEND
tempspr.x = num$
// move beyond space
FILESEEK 1, 1, 1
// read y position
chr = 0
num$ = ""
WHILE chr <> 44
READUBYTE 1, chr
IF chr <> 44 THEN INC num$, CHR$(chr)
WEND
tempspr.y = num$
// move beyond space
FILESEEK 1, 1, 1
// read width
chr = 0
num$ = ""
WHILE chr <> 44
READUBYTE 1, chr
IF chr <> 44 THEN INC num$, CHR$(chr)
WEND
tempspr.w = num$
// move beyond space
FILESEEK 1, 1, 1
// read height
chr = 0
num$ = ""
WHILE chr <> 44
READUBYTE 1, chr
IF chr <> 44 THEN INC num$, CHR$(chr)
WEND
tempspr.h = num$
FILESEEK 1, 12, 1 // move on 14 bytes
// add new sprite to array
DIMPUSH sprites[], tempspr
sprname$=LEFT$(sprname$, LEN(sprname$)-4)
// assign an index number to new sprite
SpriteAdd(sprname$, sprnum)
// Testing
// DRAWSPRITE sprsheet, 0, 0
// PRINT "File position: "+FILEPOSITION (1), 0, 0
// PRINT "Sprite name: "+sprname$, 0, 10
// PRINT "Sprite number: "+sprnum, 0, 20
// PRINT "Sprite x: " +tempspr.x, 0, 30
// PRINT "Sprite y: " +tempspr.x, 0, 40
// PRINT "Sprite width: " +tempspr.w, 0, 50
// PRINT "Sprite height: " +tempspr.h, 0, 60
// SHOWSCREEN
// MOUSEWAIT
// End of testing
INC sprnum
WEND // end of end of file check
ENDIF // end of opening file
RETURN sprnum
ENDFUNCTION
FUNCTION SpriteAdd: idname$, index
SELECT idname$
CASE "bigsprite"
bigone = index
DEFAULT
// do nout
ENDSELECT
ENDFUNCTION
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Poly Roto Zoom Anim //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FUNCTION PolySprite: num%, xpos#, ypos#, angle# = 0, hotpoint% = 7, xscale# = 1.0, yscale# = 1.0, hflip% = FALSE, vflip% = FALSE, pcolour% = 16777215
LOCAL patx#, paty#, patxx#, patyy# // texture co-ords
LOCAL pltx#, plty#, plbx#, plby#, prbx#, prby#, prtx#, prty# // position co-ordinates
LOCAL porwidth#, porheight#, pwidth#, pheight# // position fixing
LOCAL porcentx#, porcenty#, pcentx#, pcenty# // for centering
LOCAL pminx#, pminy#, pmaxx#, pmaxy# // for rotation
LOCAL midx#, midy# // for mid points
LOCAL xoff1#, yoff1# // rotation offsets
LOCAL xoff2#, yoff2# // rotation offsets
LOCAL xoff3#, yoff3# // rotation offsets
LOCAL xoff4#, yoff4# // rotation offsets
// if horizontal flip
IF hflip = FALSE
patx = sprites[num].x
patxx = sprites[num].x+sprites[num].w
ELSE
patx = sprites[num].x+sprites[num].w
patxx = sprites[num].x
ENDIF
// if vertical flip
IF vflip = FALSE
paty = sprites[num].y
patyy = sprites[num].y+sprites[num].h
ELSE
paty = sprites[num].y+sprites[num].h
patyy = sprites[num].y
ENDIF
// calculate proportions for sprite
porwidth = sprites[num].w * zoom
porheight = sprites[num].h * zoom
pwidth = porwidth * xscale
pheight = porheight * yscale
porcentx = porwidth / 2
porcenty = porheight / 2
pcentx = pwidth / 2
pcenty = pheight / 2
// depending on hotpoint, reposition the final sprite
SELECT hotpoint
CASE 7 // top left
pltx = xpos * zoom
plty = ypos * zoom
CASE 8 // top
pltx = xpos * zoom - pcentx
plty = ypos * zoom
CASE 9 // top right
pltx = xpos * zoom - pwidth
plty = ypos * zoom
CASE 4 // left
pltx = xpos * zoom
plty = ypos * zoom - pcenty
CASE 5 // center
pltx = xpos * zoom - pcentx
plty = ypos * zoom - pcenty
CASE 6 // right
pltx = xpos * zoom - pwidth
plty = ypos * zoom - pcenty
CASE 1 // bottom left
pltx = xpos * zoom
plty = ypos * zoom - pheight
CASE 2 // bottom
pltx = xpos * zoom - pcentx
plty = ypos * zoom - pheight
CASE 3 // bottom right
pltx = xpos * zoom - pwidth
plty = ypos * zoom - pheight
DEFAULT // assume center, 5
pltx = xpos * zoom - pcentx
plty = ypos * zoom - pcenty
ENDSELECT
// now add other variables needed for sprite placement
plbx = pltx
plby = plty + pheight
prtx = pltx + pwidth
prty = plty
prbx = prtx
prby = plby
// if rotation is required then rotate the sprite co-ordinates
IF angle <> 0
midx = (pltx+prbx)/2
midy = (plty+prby)/2
xoff1 = ( (COS(angle)*(pltx-midx)) - (SIN(angle)*(plty-midy)) ) + porcentx * xscale
yoff1 = ( (SIN(angle)*(pltx-midx)) + (COS(angle)*(plty-midy)) ) + porcenty * yscale
xoff2 = ( (COS(angle)*(plbx-midx)) - (SIN(angle)*(plby-midy)) ) + porcentx * xscale
yoff2 = ( (SIN(angle)*(plbx-midx)) + (COS(angle)*(plby-midy)) ) - porcenty * yscale
xoff3 = ( (COS(angle)*(prtx-midx)) - (SIN(angle)*(prty-midy)) ) - porcentx * xscale
yoff3 = ( (SIN(angle)*(prtx-midx)) + (COS(angle)*(prty-midy)) ) + porcenty * yscale
xoff4 = ( (COS(angle)*(prbx-midx)) - (SIN(angle)*(prby-midy)) ) - porcentx * xscale
yoff4 = ( (SIN(angle)*(prbx-midx)) + (COS(angle)*(prby-midy)) ) - porcenty * yscale
INC pltx, xoff1
INC plty, yoff1
INC plbx, xoff2
INC plby, yoff2
INC prtx, xoff3
INC prty, yoff3
INC prbx, xoff4
INC prby, yoff4
ENDIF
// Draw final polyvector
POLYVECTOR pltx, plty, patx, paty, pcolour
POLYVECTOR plbx, plby, patx, patyy, pcolour
POLYVECTOR prbx, prby, patxx, patyy, pcolour
POLYVECTOR prbx, prby, patxx, patyy, pcolour
POLYVECTOR prtx, prty, patxx, paty, pcolour
POLYVECTOR pltx, plty, patx, paty, pcolour
ENDFUNCTION
FUNCTION Initialise:
LOCAL plat$ = PLATFORMINFO$("")
IF plat$="ANDROID"
plats = 3 // Android
GETDESKTOPSIZE xres, yres
AUTOPAUSE TRUE
ALLOWESCAPE FALSE
SETORIENTATION 0
ELSEIF plat$="MACOSX"
plats = 1 // Mac
GETSCREENSIZE xres, yres
SYSTEMPOINTER TRUE
AUTOPAUSE TRUE
ALLOWESCAPE TRUE
ELSEIF plat$="LINUX"
plats = 2 // Linux
GETSCREENSIZE xres, yres
SYSTEMPOINTER TRUE
AUTOPAUSE TRUE
ALLOWESCAPE TRUE
ELSEIF plat$="WIN32"
plats = 0 // The game is running on a PC computer
GETSCREENSIZE xres, yres
SYSTEMPOINTER TRUE
AUTOPAUSE TRUE
ALLOWESCAPE TRUE
ELSE
plats = 2 // Treat as Pre bug on WebOS 1.4.5
ENDIF
// cal midpoint
midxres = xres/2
midyres = yres/2
// Aspect ratio always 5:3 - my virtual screen is 800 x 480
IF xres/yres <= 1.666666666666667 // if x res is not too small for 5/3 aspect ratio
zoom = xres/800 // now we have our zoom factor
yborder = (yres - 480*zoom) / 2
xborder = 0
xvir = xres
yvir = yres - yborder*2
ELSE // more letterbox than 800x480
zoom = yres/480
xborder = (xres - 800*zoom) / 2
yborder = 0
yvir = yres
xvir = xres - xborder*2
ENDIF
ENDFUNCTION
FUNCTION OldFPS:
STATIC OldTimeReport$,FPSDat,TimeReport$,FPSd,nada
IF nada < 60
INC nada
FPSd = -1
OldTimeReport$=TimeReport$; FPSDat=FPSDat+1;
TimeReport$=PLATFORMINFO$("TIME")
IF OldTimeReport$<>TimeReport$; FPSDat=0; ENDIF
ELSE
OldTimeReport$=TimeReport$; FPSDat=FPSDat+1;
TimeReport$=PLATFORMINFO$("TIME")
IF OldTimeReport$<>TimeReport$; FPSd=FPSDat ; FPSDat=0; ENDIF
ENDIF
RETURN FPSd
ENDFUNCTION
FUNCTION FSMeasureTimerEnd:
SF_oldtimer = SF_timer
SF_timer = GETTIMERALL() // measure the timer at the end of this loop
SF_baseFPS = SF_timer - SF_oldtimer // work out how long it took for one complete loop
INC SF_m, SF_curd - SF_baseFPS
IF SF_flagloop = FALSE // if no loop yet
INC SF_sumframes, SF_baseFPS
SF_frames[SF_curframe] = SF_baseFPS // add the current time into the frames list but don't minus anything
ELSE // we have looped
DEC SF_sumframes, SF_frames[SF_curframe] // remove old value from total before adding new
INC SF_sumframes, SF_baseFPS // add new value
SF_frames[SF_curframe] = SF_baseFPS
ENDIF
INC SF_curframe, 1 // move on one frame
// See if we have reached one full measurement
IF SF_countframe < SF_loopframe
INC SF_countframe
IF SF_countframe = SF_loopframe // we have now made a complete loop
SF_flagloop = TRUE // so flag it
ENDIF
ENDIF
//Now, calculate the number of frames that need to be caught up with
loopdo = 0 // always assume nothing to be done next frame, just to be safe
IF SF_m < -SF_curd // if our measure is really low
LOCAL re_m# // remainder of measure after nasties removed
SF_mflag = TRUE // we have used the measure recalc
re_m = FMOD(-SF_m, SF_curd) // find the remainder when divided
loopdo = (-SF_m - re_m) / SF_curd
INC SF_m, loopdo*SF_curd
INC loopdo // add one more action loop, the normal action loop
ELSEIF SF_m > SF_curd // Oops. We running THAT fast, and subsquently potentially messing up frameskip calcs
SF_m = 0 // just reset to zero to be safe
loopdo = 1 // normal frames
ELSE
loopdo = 1 // Normal frames
ENDIF // End of measures taken on measure
// Do checks if we've reached end of the loopframe
IF SF_curframe = SF_loopframe
SF_curframe = 0 // have we reached the end? Then loop
FSGuess() // run guess checks
IF SF_mflag = FALSE // no skips this loop
SF_m = 0 // reset measure (for re-balancing)
ENDIF
SF_mflag = FALSE
ENDIF
ENDFUNCTION
// Guess the average FPS
FUNCTION FSGuess: reset% = FALSE
LOCAL guess% // this guess
LOCAL oldguess% // any guess to check
LOCAL sameflag% = TRUE
IF reset = TRUE // we reset the guess values and start again. Else
curguess = 0
REDIM gstore[0]
ELSE // we are actually meant to check
SELECT SF_sumframes
// CASE 1933 TO 2067 // 2000 base - guess is capped at 30 FPS ~ 2 FPS error margin
//
// guess = 30
CASE 1090 TO 1240 // 1200 base - guess is 50 FPS ~ -2 to +5FPS error margin
guess = 50
CASE 967 TO 1033 // 1000 base - guess is 60 FPS ~ 2 FPS error margin
guess = 60
CASE < 909 // faster than 66 FPS
guess = -1 // throttle advised
DEFAULT // do nothing
guess = 0 // we are lost somewhere
// do nothing
ENDSELECT
gstore[curguess] = guess // assign new guess
INC curguess // increase the counter
IF curguess = guessnum // reached the end of the guesses needed
curguess = 0 // reset loop
ENDIF
// run a check on all guesses.
oldguess = gstore[0] // all guesses must be the same as this one to work
FOR g = 1 TO guessnum-1
IF gstore[g] <> oldguess // if there is a difference
sameflag = FALSE
ENDIF
NEXT
// now check to see if there is consistency
IF sameflag = TRUE // we have a recommended
SELECT guess
CASE 60
IF SF_guess <> 60
SF_curd# = 16.66666666666667 // frame time
SF_guess = guess
SF_fullflag = TRUE // this app can run at 60FPS on the hardware
SF_m = 0 // reset frame reading
ENDIF
CASE 50
IF SF_guess <> 50 AND SF_fullflag = 0 // not already 50 and has never been 60FPS
SF_curd# = 20
SF_guess = guess
SF_m = 0 // reset frame reading
ENDIF
// CASE 30
//
// IF SF_guess <> 30
// SF_curd# = 16.66666666666667 // keep the same frame time as 60 FPS because the timers will compensate
// SF_guess = guess
// SF_m = 0 // reset frame reading
// ENDIF
CASE -1
IF SF_guess <> -1
SF_curd# = 16.66666666666667 // enforce 60 FPS because on very fast computer
SF_guess = guess
throttle = TRUE
SF_m = 0 // reset frame reading
LIMITFPS 60
ENDIF
CASE 0 // release the guess from memory
SF_guess = guess
DEFAULT
// do nothing
ENDSELECT
ELSE // they are not the same!
SF_guess = 0
//SF_curd# = don't change because not sure!
ENDIF
ENDIF // end if reset = true
ENDFUNCTION
FUNCTION ReadControls:
MOUSESTATE mx, my, ma, mb
mx = (mx - xborder) / zoom
my = (my - yborder) / zoom
IF ma
INC press
ELSE
press = 0
ENDIF
ENDFUNCTION
Thanks for sharing ... I must take a look :)