Main Menu

For Foxes Sake WIP

Started by micky4fun, August 19, 2012, 03:54:41 AM

Previous topic - Next topic

micky4fun

Hi all

just wanted to keep forum , well BlinkOk mainly informed on whats happening with game as he as put in a lot or hard work gfx's side
well doing it as i can , as i am now out of work after 31 years in the same retail job , im trying to find work at the moment and its not easy and tacking up a lot of time , just writing my CV was a something i never done before , anyway , level 8 in almost done so theres not lots to do to get a full playable game finished , its been ages in the making when a month or so all could av been done , well just been a bad year i think

i have been looking about forums still , did like ScottieB battlezone a lot it looks excellent , but seems have to a stop at the moment ?

ok back soon i hope
mick :)

monkeybot

sorry to hear about that micky.

BlinkOk

it's been a tough year alright mate. hopefully it can only get better!
as always there is no rush here, so don't stress yourself, take as long as you want and good luck with the job hunting

kevin


That's not the best news..  Hopefully things pick up for you soon.

micky4fun

#304
Hi All

First of all thanks for all comments and personal messages wishing me luck guys ,


sorry this as taken so long to get done , but doing it as much as I can

this level took a little longer than I thought to finish and its the final level so have 8 in total  , anyway here it is , still some things to finish off , will now tidy up code a bit , wont go mad as it works as it is
I will look where I can improve parts of the game , add some sounds and other bits needed to get it all finished , will make it a bit harder so when you get hit you lose a bit more life

I did what said BlinkOk , I have made it so when you kill moving saws the inside saw stays where it is and you can lose energy if you hit it , well have fun
parts of the game require certain amount of gold coins before you can move on , so make sure you get them all , when done goes back to level 1 , so just re-run to play again

mick :)

BlinkOk

#305
awesome mr fun. i'm away today so it will take me a couple days to get to this.

ps: you are an evil man micky! do you know how many foxes were killed to make this game? and a lot more will go before i finish this level too!

kevin


Played the new update the other morning, don't think I manage to get through it..




micky4fun

#307
Quoteyou are an evil man micky! do you know how many foxes were killed to make this game? and a lot more will go before i finish this level too
lol , erm I am still on my first fox , hope you aint killing them all BlinkOk

Quote
Played the new update the other morning, don't think I manage to get through it..
oh dear , thats the trouble me non stop playing levels I do it easy with one fox , could take a few yellow saws out near paintbrush wheel that might help ,
did not want to make it to easy though as it wont last long

not to sure if there should be some kinda timer in game as you could just stand about and take you time doing levels , will have to think about that , or have your energy go down slowly even if you don't hit anything and at certain points in game you hit a block to add some extra energy , something to think about again

just putting in sound , I started a bit overboard I think, having the saws get louder as they get nearer to you and sound coming out of either left or right speaker depending where the saw was to you.
but decieded not to go that way and just keep it simple , a bit 8 bitty with the sounds

also found some small glitches on this level and others to , for instance once saw come out of yellow saws if you jump up and down on it quick nothing happens , so fix that , I know there is other bits that need doing in other levels , but that's straight forward , but got the main guts of game now , just wrapping it all up will take a week or so I would have thought

im really looking forward to doing something similar another platform game I think , but more thought out and maybe up/down than left/right , we will see

mick :)

ps tried the .exe of this game on a few pc's  and plays fine on them , right down to a Pentium dual core 2ghz win xp machine , an Athlon 1.66 single core did struggle with it though
played about the same speed as my mates quad core amd pheonom machine with windows 8

kevin

#308
Mick,

Quote
oh dear , thats the trouble me non stop playing levels I do it easy with one fox , could take a few yellow saws out near paintbrush wheel that might help ,
did not want to make it to easy though as it wont last long

 Unfortunately that's just what happens with familiarity, so getting the balance right for new players was always going to be difficult.    


 Having a bit of pick through the code again and there's a lot of redundancy in the program, which is throwing away performance.   Even though the program runs about 200fps (without vsync frame cap) on my 8 year old athlon system, the further down you go the more these things get magnified.    There's some areas where some easy gain can be made though.    

 Examples,


 Parallax
 
       The scrolling backdrops seem to be oversized.  Drawing transparent pixels aren't free to render, so if there's 3 layers and the second layer is 1/2 transparent then an easy gain is to clip the sections so they still overlap.  The slower the gpu the higher the potentially gain in fill rate.

       2 layer brute force example
     
PlayBASIC Code: [Select]
   path$="beta_v4.0\gfx\"

Layer1=loadnewimage(path$+"background\bg1.png")
imagemaskcolour Layer1,argb(255,255,0,255)

Layer2=loadnewimage(path$+"background\bg02.png")

Do

; simulate parallax movement
Xpos# =mod(Xpos#-1 ,GetImageWidth(Layer1))
Xpos2# =mod(Xpos2#-0.5,GetImageWidth(Layer2))

; draw the two fields
DrawImage Layer2,xpos2#,0,false
DrawImage Layer2,xpos2#+GetImageWidth(Layer2),0,false

DrawImage Layer1,xpos#,0,true
DrawImage Layer1,xpos#+GetImageWidth(Layer1),0,true


text 0,0,fps()

Sync
loop


   


       2 layer brute force example clipped

PlayBASIC Code: [Select]
   path$="beta_v4.0\gfx\"

// load front image and trim it up, removing about 40% of it
TempIMage=loadnewimage(path$+"background\bg1.png")

Width =GetImageWidth(TempIMage)
Height =GetImageHeight(TempIMage)
Crop=320
Layer1=NewImage(width,Height-crop)
CopyRect TempImage,0,crop,width,Height,Layer1,0,0

DeleteImage TempImage
ImageMaskColour Layer1,rgb(255,0,255)

TempIMage=LoadNewImage(path$+"background\bg02.png")

Width =GetImageWidth(TempIMage)
Height =GetImageHeight(TempIMage)
Crop=20

Layer2=NewImage(width,Height-crop)

CopyRect TempImage,0,0,width,Height-crop,Layer2,0,0
deleteimage tempimage


Do
; simulate parallax movement
Width=GetImageWidth(Layer2)
Xpos2# =mod(Xpos2#-0.5,Width)

; draw the two fields
DrawImage Layer2,xpos2#,0,false
DrawImage Layer2,xpos2#+Width,0,false

Width=GetImageWidth(Layer1)
Xpos# =mod(Xpos#-1 ,Width)

Yoffset=GetScreenHeight()-GetImageHeight(Layer1)
DrawImage Layer1,xpos#,YOffset,true
DrawImage Layer1,xpos#+Width,YOffset,true

text 0,0,fps()

Sync
loop


   


       The second example is about 10% faster and is using approximately 3 meg less data in GPU's  video memory with no real effort.   Video memory is a finite resource and one we can't afford to waste.  While on the subject, I feel it'd be better not to load the parallax images into memory each level as video images.  Rather load them into memory as FX images, then copy the pixel data to the Video image when required.    On legacy systems with small video caches,  this could make the difference between is working or crashing.  

       I don't recall what indexes the parallax uses, but say  image 1000 is  layer 3, image 1001 is the second. So make a little function to copies the data down.    Eg.

PlayBASIC Code: [Select]
Function Init_Backdrop_Images(Layer3,Layer2)
Width =GetimageWidth(Layer3)
Height=GetimageHeight(Layer3)

CreateImage 1000,Width,Height
CopyREct Layer3,0,0,width,height, 1000,0,0

Width =GetimageWidth(Layer2)
Height=GetimageHeight(Layer2)

CreateImage 1001,Width,Height
CopyREct Layer2,0,0,width,height, 1001,0,0

EndFunction





 Redundancies

      One of the things that can cripple a programs performance is computational redundancy,  so things like falling through impossible decisions or computing a value multiple times where the result hasn't can have dire affects on performance.
     
      Here's an example of falling through a impossible decisions.
     
PlayBASIC Code: [Select]
      if playerx#<2940 and game_scene=1 then player_xpos#=550
if playerx#<3400 and game_scene=2 then player_xpos#=550
if playerx#<2720 and game_scene=3 then player_xpos#=550
if playerx#<4700 and game_scene=4 then player_xpos#=550
if playerx#<2650 and game_scene=5 then player_xpos#=550
if playerx#<4356 and game_scene=6 then player_xpos#=550
if playerx#<3240 and game_scene=7 then player_xpos#=550
if playerx#<4350 and game_scene=8 then player_xpos#=550

if playerx#>2940 and playerx#<4790 and game_scene=1 then player_xpos#=2940
if playerx#>3400 and playerx#<6100 and game_scene=2 then player_xpos#=3450
if playerx#>2720 and playerx#<6810 and game_scene=3 then player_xpos#=2725
if playerx#>4700 and playerx#<8258 and game_scene=4 then player_xpos#=4700
if playerx#>2650 and playerx#<6820 and game_scene=5 then player_xpos#=2650
if playerx#>4356 and playerx#<7618 and game_scene=6 then player_xpos#=4390
if playerx#>3240 and playerx#<8100 and game_scene=7 then player_xpos#=3240
if playerx#>4350 and playerx#<9370 and game_scene=8 then player_xpos#=4750

if playerx#>4790 and game_scene=1 then player_xpos#=4790
if playerx#>6100 and game_scene=2 then player_xpos#=6170
if playerx#>6810 and game_scene=3 then player_xpos#=6810
if playerx#>8258 and game_scene=4 then player_xpos#=8258
if playerx#>6820 and game_scene=5 then player_xpos#=6820
if playerx#>7618 and game_scene=6 then player_xpos#=7710
if playerx#>8100 and game_scene=7 then player_xpos#=8100
if playerx#>9370 and game_scene=8 then player_xpos#=9600




     To execute this tiny fragment,  the code is one big fixed cost operation.  In other words, no matter what game_scene is equal to, it's falling through at least 96 operations. We can reduxe that by grouping the code into blocks that act upon game_scene

     Ex.. So we grab the expressions that compare game_scene and pull them together..  Making this,
     
PlayBASIC Code: [Select]
      if playerx#<2940 and game_scene=1 then player_xpos#=550
if playerx#>2940 and playerx#<4790 and game_scene=1 then player_xpos#=2940
if playerx#>4790 and game_scene=1 then player_xpos#=4790


if playerx#<3400 and game_scene=2 then player_xpos#=550
if playerx#>3400 and playerx#<6100 and game_scene=2 then player_xpos#=3450
if playerx#>6100 and game_scene=2 then player_xpos#=6170

etc etc..




    If we screen on the leve, we cut the work load in half.  
PlayBASIC Code: [Select]
      if game_scene=1 
if playerx#<2940 then player_xpos#=550
if playerx#>2940 and playerx#<4790 then player_xpos#=2940
if playerx#>4790 then player_xpos#=4790
endif


if game_scene=2
if playerx#<3400 then player_xpos#=550
if playerx#>3400 and playerx#<6100 then player_xpos#=3450
if playerx#>6100 then player_xpos#=6170
endif


if game_scene=3
if playerx#<2720 then player_xpos#=550
if playerx#>2720 and playerx#<6810 then player_xpos#=2725
if playerx#>6810 then player_xpos#=6810
endif

if game_scene=4
if playerx#<4700 then player_xpos#=550
if playerx#>4700 and playerx#<8258 then player_xpos#=4700
if playerx#>8258 then player_xpos#=8258
endif

if game_scene=5
if playerx#<2650 then player_xpos#=550
if playerx#>2650 and playerx#<6820 then player_xpos#=2650
if playerx#>6820 then player_xpos#=6820
endif


if game_scene=6
if playerx#<4356 then player_xpos#=550
if playerx#>4356 and playerx#<7618 then player_xpos#=4390
if playerx#>7618 then player_xpos#=7710
endif

if game_scene=7
if playerx#<3240 then player_xpos#=550
if playerx#>3240 and playerx#<8100 then player_xpos#=3240
if playerx#>8100 then player_xpos#=8100
endif

if game_scene=8
if playerx#<4350 then player_xpos#=550
if playerx#>4350 and playerx#<9370 then player_xpos#=4750
if playerx#>9370 then player_xpos#=9600
endif





    This version now only falls through 16 operations (8 compares and 8 IF branches).  When a match is met,  it's falling through another 8 operations in the that branch.   So about 24 operations in total.    

    This type of chunk of code could replaced with typed array really, but my point is these little code redundancies  have a very nasty habit of building up and chewing through extra processor time.     If you have say only 100 characters in a level and there's say wasted 100 operations updating each character each frame,  than that's easily 10000 operations going down the drain.  


   Here's an example of a calculation redundancies,

PlayBASIC Code: [Select]
          ThisTile  = PeekLevelTile(Mymap,fences   ,(playerx#-32)/64,(playery#-32)/64)
ThisTile2 = PeekLevelTile(Mymap,platform ,(playerx#-32)/64,(playery#+32)/64)
ThisTile3 = PeekLevelTile(Mymap,front ,(playerx#-32)/64,(playery#-32)/64)
ThisTile4 = PeekLevelTile(Mymap,trees ,(playerx#-32)/64,(playery#-32)/64)



   So here we're computing the Tile the player is over every time we peek the level.    So there's 4 operations to compute the X/Y coordinate once. So the fragment is at least 20 operations.  

PlayBASIC Code: [Select]
          PlayerTileX#=(playerx#-32)/64
PlayerTileY#=(playery#-32)/64
ThisTile = PeekLevelTile(Mymap,fences ,PlayerTileX#,PlayerTileY#)
ThisTile2 = PeekLevelTile(Mymap,platform ,PlayerTileX#,(playery#+32)/64)
ThisTile3 = PeekLevelTile(Mymap,front ,PlayerTileX#,PlayerTileY#)
ThisTile4 = PeekLevelTile(Mymap,trees ,PlayerTileX#,PlayerTileY#)



    Now we're down to about 10  operations.    

    In this loop, we're reading the sprite index and pulling the image from the 3 times more than is necessary.

PlayBASIC Code: [Select]
              for each mp()
if getspriteimage (mp.sprite)=311 or getspriteimage (mp.sprite)=301 then spriteimage mp.sprite,310
if getspriteimage (mp.sprite)=361 then spriteimage mp.sprite,360
next

 


    ie.
PlayBASIC Code: [Select]
              for each mp()
ThisSprite=mp.sprite
ThisImage=getspriteimage (ThisSprite)
if ThisImage=311 or ThisImage=301 then spriteimage ThisSprite,310
if ThisImage=361 then spriteimage ThisSprite,360
next

 

   Reading the sprite Index into a variable, means we don't have to query the list structure every time,  same with the reading the image index.  So there two less function and two less type reads at least.  More if there's a match.   Calling a function is one of the slowest things a program can do in management loop like this, as even though the call has a tiny cost, it's quickly magnified the more iterations of the loop that are required.

   
      This same type of redundancy error occurs in the update routine here...
PlayBASIC Code: [Select]
      for each dogs()

if dogs.object=chr_fish or dogs.object=chr_snail or dogs.object=chr_dog or dogs.object=chr_gamekeeper or dogs.object=chr_fire or dogs.object=chr_blades
dogs.oldorbit#=dogs.orbitx#
dogs.thisangle#=dogs.Angle#
dogs.orbitx#=dogs.mx#+(Cos(dogs.thisangle#)*dogs.RadiusX#)
dogs.orbity#=dogs.my#+(Sin(dogs.thisangle#)*dogs.RadiusY#)
positionsprite dogs.sprite,dogs.orbitx#,dogs.orbity#
dogs.Angle#=WrapAngle(dogs.Angle#,dogs.spd_rotate#)
endif

Select Dogs.object

etc etc







      This is pulling the Object type from dogs.object  at least 7 times per object..
 

PlayBASIC Code: [Select]
             ObjectType=Dogs.Object
if ObjectTYPE=chr_fish or ObjectTYPE=chr_snail or ObjectTYPE=chr_dog or ObjectTYPE=chr_gamekeeper or ObjectTYPE=chr_fire or ObjectTYPE=chr_blades

dogs.oldorbit#=dogs.orbitx#
dogs.thisangle#=dogs.Angle#
dogs.orbitx#=dogs.mx#+(Cos(dogs.thisangle#)*dogs.RadiusX#)
dogs.orbity#=dogs.my#+(Sin(dogs.thisangle#)*dogs.RadiusY#)
positionsprite dogs.sprite,dogs.orbitx#,dogs.orbity#
dogs.Angle#=WrapAngle(dogs.Angle#,dogs.spd_rotate#)
endif
Select ObjectTYPE

etc etc



   
     This executes about 40-45% faster. 


     But it's quicker to pull the state from an array, gets rid of the any calculations and just pre computes it.. 

PlayBASIC Code: [Select]
   ; character states
Constant chr_dead =1
Constant chr_snail =2
Constant chr_fish =3
Constant chr_dog =4
Constant chr_split =5
Constant chr_gamekeeper=6
constant chr_bullet =7
constant chr_fire =8
constant chr_blades =9


; table of what objects use the Swing controller AI
Dim Use_Swing_AI(100)

Use_Swing_AI(chr_fish)=true
Use_Swing_AI(chr_snail)=true
Use_Swing_AI(chr_dog)=true
Use_Swing_AI(chr_gamekeeper)=true
Use_Swing_AI(chr_fire)=true
Use_Swing_AI(chr_blades)=true


; Dog up type
Type TDog
Object
EndTYpe


DIm dogs as tDog list


For lp =0 to 100
Dogs =New tDog
T=Rndrange(chr_snail,chr_blades)
Dogs.object=t
next



Do

cls
frames++

startinterval 0
Counter=0

for each dogs()
if dogs.object=chr_fish or dogs.object=chr_snail or dogs.object=chr_dog or dogs.object=chr_gamekeeper or dogs.object=chr_fire or dogs.object=chr_blades
Counter++
endif
Select dogs.object
endselect
next

t1#+=EndInterval(0)
print t1#/frames
print Counter



startinterval 0
Counter=0
for each dogs()
ObjectType=Dogs.Object
if ObjectTYPE=chr_fish or ObjectTYPE=chr_snail or ObjectTYPE=chr_dog or ObjectTYPE=chr_gamekeeper or ObjectTYPE=chr_fire or ObjectTYPE=chr_blades
Counter++
endif
Select ObjectTYPE
endselect
next
t2#+=EndInterval(0)
print t2#/frames
print Counter



startinterval 0
Counter=0
for each dogs()
ObjectType=Dogs.Object
if Use_Swing_AI(ObjectTYPE)
Counter++
endif
Select ObjectTYPE
endselect
next
t3#+=EndInterval(0)
print t3#/frames
print Counter

Sync
loop







micky4fun

#309
Hi All

ok thanks Kevin , I see what you mean about the more operations in all the examples , I seemed to have used this way of doing it
for each mp()
                     if getspriteimage (mp.sprite)=311 or getspriteimage (mp.sprite)=301 then spriteimage mp.sprite,310
                     if getspriteimage (mp.sprite)=361 then spriteimage mp.sprite,360
                   next

quite a bit in different ways in different parts of my code and the logic if player#>550 and game_scene =1 etc , I see how it can make more operations
I will go through my code and change it to a more practical way of being calculated

as for the background scrolling I see what you are saying there to , I would have not had a clue how to do it this way , I will go through your example later on as well
I can see that all this will squeeze out a few extra frames , which all helps

mick :)

kevin


The easy way is to load up the pictures in your favourite paint package clip them off,  which is a better solution than loading into memory then clipping them in the program.   

Quote
I can see that all this will squeeze out a few extra frames , which all helps

   On newer systems it might only win back a few extra frames,  it's the older systems that will benefit the most.   

monkeybot

That's coming along very nicely,bloody tricky though!!!

micky4fun

Hi all

thanks monkeybot , cant make it to easy you will do all the levels in 5 mins lol , but then again not impossible , well its all done apart from full testing and slight game alterations to maybe make it a tad easier , properly in the way of energy top-up when a level is complete , so I will post full game tomorrow I would have thought or day after depending how long testing takes

BlinkOk if you have a look at it and see if we need any gfx's touches to it , maybe at end of level when it says well done action continues you might want to change txt gfx or something


mick :)

BlinkOk


micky4fun

Hi all

well well at last nearly a year and I have a fully playable game for testing , made it slightly easier by getting an extra life when level is complete max 3 lives and you start with full energy bar
some sounds still need finding and replacing , but this takes time to find them , please have a good play and see what you think
there is a screenvsync toggle on main screen before you start use F1 and F2 keys to toggle , will show in upper left corner of screen

you will not master straight away but over time is fairly straight forward

download here
http://rghost.net/48370855
password is playbasic

run For Foxes Sake.exe
will post code once a bit tidy up
mick :)