Thanks for posting the source. Seems to be pretty well put together. There's a few bits that can be improved. One that comes to mind is your usage of FlushKeys within an input loop. This can make the loop unresponsive to key input. As often it's flushing keys before the scan code is read. In other words it only needs flushing, if a valid input has been pressed.
psub Level(p_aLevelLock())
local key=0
local nLevelSelected=0
repeat
cls 0
; flushkeys
showstars(xStars#(),yStars#())
drawimage nMenuImg,0,0,1
setfont 11
centertext nResX/2,50,"LUNAR CAVES"
setfont 10
text nResX/2-100,200,"1 LEVEL 1"
//Level 2
if p_aLevelLock(2)=1
setfont 10
text nResX/2-100,230,"2 LEVEL 2"
else
setfont 12
text nResX/2-100,230,"2 LEVEL 2 Locked"
endif
//Level 3
if p_aLevelLock(3)=1
setfont 10
text nResX/2-100,260,"3 LEVEL 3"
else
setfont 12
text nResX/2-100,260,"3 LEVEL 3 Locked"
endif
sync
key=scancode()
;select level
if key>1 and key<10
;play level if unlocked
if p_aLevelLock(key-1)<>0
nLevelSelected=key-1
NLives=3
nScore=0
nRotateSpeed=4
LevelLoop (nLevelSelected,aRooms(),aMap(),aMapBg(),aPowerUp(),aPad(),aGem(),ship.shipdata,p_aLevelLock(),aShipLoc())
flushkeys
initstars(xStars#(),yStars#())
key=0
endif
endif
until esckey()
flushkeys
endpsub
Also, the changes to FX images have certainly dropped the video consumpting dramtically, but from what I can tell your rendering the current room constantly in the main loop. Given the size of the images, this will effect performance. In particular on slower, old clunkers.
What I was getting at previously, is that you should use a single screen sized video image as a backdrop cache. So when a room is changed, the FX buffers are drawn onto the video image once. Then we just draw the Video version each update. This costs a little extra video memory, but is best all round solution for performance and compatibility .
a bit like this..
path$="D:\LunarCaves\data\"
openscreen 1024,768,32,2
Dim Rooms(1)
Level$="Level1\"
LoadRooms(path$+Level$,Rooms())
print "loading"
// Backdrop IMage
BackdropIMage=LoadNewFXIMage(Path$+Level$+"Backrock.jpg")
// This (video) image, will hold the current room being displayed
RoomImage=NewImage(1024,768)
// Pick a random starting room, and reqrest a backdrop refresh
CurrentRoom=NewRoom()
CurrentRoomRefresh=true
// Calc Amount of video memory used
VideoMemory =CalcUsedImageMemory(1)
SystemMemory =CalcUsedImageMemory(2)
; Setfps 60
Do
// DRaw
// Check for a change of rooms ?
if CurrentRoomRefresh=true
// if there was, we copy/draw the FX version of the room image
// to the video version.
CurrentRoomRefresh=false
RenderToImage RoomImage
DrawImage BackdropIMage,0,0,false
DrawImage Rooms(CurrentRoom),0,0,true
rendertoscreen
endif
// Draw the backdrop (solid) as there's no need for a CLS.
DrawImage RoomImage,0,0,false
// Press Space to simulate changing rooms
if Spacekey()
CurrentRoom=NewRoom()
// request the backdrop image be refreshed
CurrentRoomRefresh=true
endif
// Dump some info to the screen
Text 0,0, " Current Room:"+str$(CurrentRoom)
text 0,20, " fps:"+str$(fps())
Text 0,40, " Video Memory:"+str$(VideoMemory)
Text 0,60, "System Memory:"+str$(SystemMemory)
Sync
loop
Function NewRoom()
repeat
ThisRoom=rnd(Getarrayelements(rooms(),1))
text 100,100,thisroom
until ThisRoom>0 and Rooms(ThisRoom)<>0
EndFunction ThisRoom
Function LoadRooms(path$,Rooms())
Size=GetArrayElements(rooms(),1)
For lp=1 to 100
file$=path$+str$(lp)+".png"
if Fileexist(file$)=true
if lp>size then redim Rooms(lp)
Rooms(lp)=loadNewFXIMage(file$)
RgbMaskImage rooms(lp),$00ffffff
Size=lp
cls 0
centertext 400,400,"Loading.."+str$(lp)
Sync
endif
next
EndFunction
Function DeleteRooms(Rooms())
For lp=1 to GetArrayElements(rooms(),1)
img=Rooms(lp)
if img>0
if GetImageStatus(img)
deleteimage img
endif
endif
Rooms(lp)=0
next
EndFunction
; **=------------------------------------------------------------------=*
; >> Calc Used Image Memory <<
; **=------------------------------------------------------------------=*
;
; This _debug_ function runs through the PB image list and returns the
; total number of bytes images are using. Due to the buffer locking it's
; not going to be fast, so don't call it every frame !
;
; **=------------------------------------------------------------------=*
Function CalcUsedImageMemory(IMageType)
local OldSurface=GetSurface()
local img
For Img=1 to GetImageQuantity()
If Img=1 or GetImageStatus(Img)=true
#print GetImageType(img)
if ImageType=GetImageType(img)
Rendertoimage Img
Lockbuffer
local ImgSize= GetImagePitch(Img)*GetIMageHeight(img)
unlockbuffer
// Check for screen. If so, add the second buffer
Memory=Memory+ImgSize
endif
Endif
next
if ImageType=1
img=0
Rendertoimage Img
Lockbuffer
local ImgSize= GetImagePitch(Img)*GetIMageHeight(img)
unlockbuffer
if Img=0 then ImgSize=ImgSize*2
Memory=Memory+ImgSize
endif
RenderToImage OldSurface
EndFunction Memory
Another option is to let the player choose the screen 'depth' they want to play in. Many older video cards, have limited 32bit support. Many of the really old one's don't support it at all. So running the game 16bit will not only 1/2 the memory consumption, it'd make it viable on really really old machines.
You could even take this further if you wanted, and make the refresh resize the scene to the 640,480 or 800,600.