Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - Wampus

Starbound was available on Steam from 4th Dec. If you don't know its a Terraria clone, sort of Terraria in space. Really its so similar to Terraria in its core mechanics and concept it could be an unofficial sequel imo. There has been a lot of hype about it for an indie game. I was amazed to see it reached the number one slot of the 'top sellers' on Steam yesterday and is still there, despite being a beta version. That's kind of amazing.  :) Am a little jealous.  :-[

Anyone else get the game? As a huge Terraria nerd I had to.  ::) Played it for 10 hours. Unsurprisingly it very much feels like a beta, kind of like a giant warehouse with more space than it can fill at the moment.

Announcements / Lab Assault
Lab Assault

Above is a screenshot from Lab Assault, a game created at the Vancouver Full Indie 48hour game jam. The theme was 'evil genius'. Try it (please  :P).

Controls: WASD or arrow keys to move, mouse to aim, left mouse button shoots, right mouse button lobs a grenade.

Kill everything that moves. When you see dynamite on the surrounding buildings, touch it to blow them up. There are power-ups inside.

More complete version now up: -

PC download
Mac download
HTML5 in browser
Original PC copy as it was at the end of the game jam

Currently the game is at it was at the end of the jam, i.e. unfinished with a few buggy quirks that pop up from time to time. I'll update this thread with a more 'final' version once I've tweaked the gameplay, added missing features and updated the credits to reflect the fact there were more sound people helping me out. Currently there is no way to win the game other than last longer than you did previously. Also, when you die, you just fall over face down and kind of stay there, with enemies collecting around you in a dodgy looking scene.

I had a lot of fun.  :) Best game jam I've ever done. There were over 100 people at the event. It makes a big difference when surrounded by other indie developers to help out and keep spirits up, especially when running on 8 hours of sleep over the whole 48 hours! At first I was working alone but I realized there was no way I'd have time to do the art and sound as well as code. Luckily a pixel artist finished what needed to be done with his first team so could join me late in the second day. Sound was done by a group of people who were helping everyone who needed assistance. Almost everyone was using Unity or XNA. People were curious about GLB when they saw the game.

Back story: One night an evil genius, genetically bred for warfare, escapes the secret lab he was being kept in. Setting up explosives on the surrounding lab buildings he plans his revenge. If he kills enough lab personnel and the monsters being bred there he can use their DNA to create his own super-army.
Interesting visual representation of how much code goes into different projects:-

Simple iPhone game: ~10 thousand lines of code (seems about right)
World of Warcraft server: ~27 million lines of code
Average modern high-end car: ~10 billion lines of code

Can you think of a way to quickly determine which functions are included in your code but never get called?

I've noticed that the standard codebase I'm using for new games/apps is getting very large, which slows down compiling time. Isn't much of an issue but it would be nice to know what I'm using and what I'm not, especially on slower machines and for 48hr game jams, etc.

Using the profiler and running through all the possible main game/app states its possible to see which functions get called. Very helpful. Can anyone think of a way to quickly determine which aren't used, i.e. aren't listed by the profiler? For example, is there are a way to quickly list all of the functions included in a game or app and then use the information from the profiler to eliminate un-used code?

I'm thinking that my codebase should start off all commented out and then I can un-comment the code as and when its needed. Still, that doesn't help with projects I've already been working on.
The attached proggy is an alternative way of handling sound in GLBasic. It should be simple to use and especially helpful for platforms that may only play a small number of sounds concurrently. At its base the code uses standard GLBasic commands. Because of this it should compile fine on all platforms. You can also use it in addition to other sound code without having to replace what you've done already, unless you want to.

Why do this at all? Because I wanted 1) a suitable and simple approach to the issue described in this thread, 2) an easy way to deal with needing multiple instances of the same sound playing at once, 3) universal volume control and 4) looping sounds.

The attached proggy uses only 4 channels. I did this deliberately for demonstration purposes. Of course, you'll probably want more than that with your apps. :)

Clicking the left mouse buttons plays a shooting sound. Pressing space starts or stops a looped sound. Clicking the right mouse button plays a wibbly sound that can't be interrupted until its finished. If what you see on screen seems confusing, sorry. There is a bunch of internal information you don't need to know being displayed for test purposes. I don't have the time to write a more suitable demonstration right now.

It should be fairly easy to use. For instance, this is a comparison of loading, playing and stopping a sound in GLBasic and how you would do it with SSound (keeping in mind SSound does more than what is shown here):-

GLBasic    ---    SSound
GLOBAL mysound%, channel%    ---    GLOBAL mysound%, channel%
mysound% = GENSOUND()
LOADSOUND "explosion.wav", mysound%, 1
    ---    mysound% =  SSLoad("explosion.wav")
channel% = PLAYSOUND(mysound%, 0.0, 1.0)    ---    channel% = SSPlay(mysound%)
STOPSOUND channel%    ---    SSKillSound(mysound%) or SSKillChan(channel%)
HUSH    ---    SSKillAllSounds()

However, if you want understand better how it works and what its doing you need to grasp these components:-

A sound is any standard .wav file you've loaded.

A buffer is the number of times a sound has been stored in memory. The more of these you assign for any sound, the more instances of that sound you can overlap at the same time without any cutting out or failing to play (depending on the mode - see below)

A channel is one of a limited set of available tracks that a sound can be played on. For example, on my Nexus 7 the number of sounds that can be played at the same time is set to 8 in GLBasic. Therefore the maximum number of channels should be set / would be set to 8.

The mode the sound is played with determines how it is treated by the routine. 0 is standard - the sound will be played on the next available channel. If no channel is available then it will be played on the channel that is the oldest, i.e. the sound that has been playing the longest is cut off to make way for the new sound. Also, if there aren't enough buffers for a new channel then an already used channel playing the sound is used. This works out fine on the ear in most cases. 1 is looped - the sound will continue to loop unless you tell it to stop and cannot be interrupted like a standard sound. 2 is not a looped sound but can't be interrupted, so will continue to play until it is finished unless you kill it. If no channels are available because all are taken up with uninterruptable sounds then a call to play a new sound will do nothing <- this should be rare because SSound was created to help prevent this in all but the worst cases.

OK, here are the commands:-

soundenum% = SSLoad ( filename$, buffers% )
Loads a sound from the current set directory with the name filename$. If your require it to be possible for more than one instance of the sound to be played at once, e.g. more than one overlapping sounds of bullets or explosions, then set the optional value buffers% to how many you anticipate. The value soundenum% is the index of the sound returned by SSLoad.

channel% = SSplay ( soundenum%, volume#, mode%, pan# )
Plays a sound loaded into the index soundenum%. The channel used is returned to channel% but you probably don't need to know this for most purposes so can leave it out. Values for volume#, mode% and pan# are also optional. Volume# and pan# work the same as GLBasic PLAYSOUND(). For mode% these are possible values:-
0 - Standard. Use this unless you need a looped sound or sound that must not be interrupted (e.g. a voice over).
1 - Looped sound. Sound will loop indefinitely unless stopped with SSKillSound, SSKillChan or SSKillAllSounds.
2 - Uninterruptable sound. Similar to GLBasic default behaviour, the sound will continue to play until it is completely finished and can't be interrupted.

SSInitialise ( numofchannels% )
If you want to use more or less channels than the default 8 then you need to call this function before you start loading sounds. numofchannels% is the required number of channels you want to use.

num% = SSTestNumSoundChannels% ( filename$, chanmax%)
Uses the .wave file in filename$ to test how many sound channels are available for use. I don't advise using this every time an app starts up. Just execute it on first boot and store the value for later reference. Use 1/4 second of total silence for the .wav file or the test may destroy the ears and/or speakers of the person using your app! The value chanmax% is the maximum number of channels to test for. By default its set to 64 but can be much larger. My main PC returns positive for > 2048 channels. Note: This function has not been tested on more than one PC and a good, recent android device. Not sure how reliable it will be unless tested.

SSUpdate ()
If you want to use sound looping then this must be present in your main loop. If you aren't going to use looping sounds then you don't need to use this function.

SSVolume ( vol# )
Sets the universal volume to vol#. All sounds played are proportional to the universal volume. For example, if you played a collision sound at full volume using SSPlay(collisionsound%, 1.0) and the universal volume was set to half at 0.5 then the resulting sound would be half the full volume.

SSKillSound ( soundenum% )
Stops playing the sound with index soundenum%. All channels playing the sound will be halted and all buffers for the sound are released.

SSKillChan ( channel% )
Alternative to SSKillSound. Stops playing the sound playing on channel channel%. Only the channel specified and consequent buffer will be clear. All other sounds are left alone.

SSKillAllSounds ()
Stops all sounds, freeing all buffers and channels.


There are other functions but almost all of them are internal to the commands above so you don't need to know anything about them.
My February entry for 1 Game a Month was Hamster VS Hellcat. I wanted to create a game where the game area rotates around the player character. Took a couple of days to code and an extra day to bug hunt, add audio, create some basic visual effects and other little things. Sound effects are actually the same as Porcupop. Didn't have time to create new sounds.

Click here to download the Windows version

I will add some Android controls soon. Should be OK for many Android devices. Runs at full speed on my Nexus 7 without issue.

Let me know what you think. Any feedback is appreciated.
Just found that SOUNDPLAYING() is always returning 0 on Windows. Haven't checked other platforms.

IDE version 11.261
I'm not sure how to describe this...I need some tool to create interesting paths for enemies to follow in a 3D game. For instance, something like the following video but in 3D:-

Can anyone think of such a tool? Or have an idea where I might be able to find one?

I need to create enemy wave patterns for a Space Harrier clone I'm working on. I only have a week to complete the game and I started today. Here is what I have so far:-

If you look at this remake of Space Harrier you'll see the kind of enemy wave movement patterns I'd like to be able to add to me game:-

I'm all ears! I need a solution soon. Not sure what to do.
If you want a personal challenge of completing a game a month and/or are looking for inspiration for small games there is a great community for such things.

One Game a Month

It was started by Ludum Dare aficionado Chris Kaitila. Its not a game jam thing but more to help push you to finish your projects and improve your game development skills. Good for feedback and encouragement.

Come join.  =D

OK, so when a client connected to a NET game quits with NETDESTROYPLAYER [their client ID number] the server command NETQUITPLAYER() pretty much consistently returns the wrong ID number.

NETQUITPLAYER should also keep returning the numbers of client IDs that have quit until reaching 0 but instead it sometimes misses them when more than one player have quit <- note, this is not a lag problem, unless lags of over 5 secs on a ethernet are to be expected.

In addition to the NETQUITPLAYER id being wrong, when a client uses NETDESTROYPLAYER they are not removed from the list of players found on the server with NETNUMPLAYERS() and NETGETPLAYERID, NETPLAYERNAME$.

The above behaviour is consistent on and between Windows and Android, i.e. its always the same, whether the host is an Android device or a Windows computer.

I have only tested this on LAN. I tested on IDE 11.171 and 10.283

On a tangent, does anyone know of a way to kick a client off the server? Doesn't seem to be a command for it.
I seem to be having problems receiving UDP packets in WebOS. Sending from WebOS is fine, which I've tested as a broadcast. For some reason I can't receive them in WebOS, either as broadcasts or directed to the local network IP address of the WebOS device I have (a Palm Pre3).  :|

I've checked and double checked that the IP address and port I'm sending to is correct. My code has been well tested with broadcasting and communicating between Windows, Android and iOS. All of them are fine talking to other and can pick up UDP packets sent by WebOS. Can't send back though. Has anyone else come across this?  O_O

The only (pointless) exception is if I'm sending and receiving to localhost on the same port for both client and server. Obviously that is useless for anything.
Hi! Does anyone know if GLB_ON_QUIT is called after SHOWSCREEN or immediately upon application exit, if there is a difference.

It has occurred to me that if a game is saved in GLB_ON_QUIT and the game is half way through a status and physics update the result could be disastrous on reloading. If its called after SHOWSCREEN then no problem, since status and physics updates will normally have been through one full step by then, unless your code is crazy.

If no one knows I'll code a test routine to find out. I imagine different devices might behave differently.
Competitions / Ludum Dare 24
Ludum Dare 24 theme is announcing in 1 min. Thought I'd take this moment to say, AAAAAAAAAAAAAAAH!
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: -

Code (glbasic) Select
// 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

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_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: -

Code (glbasic) Select
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


pmap[xnow][ynow] = 1 // is walkable


INC xnow

IF xnow = xmap

xnow = 0
INC ynow





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
ELSE // load sprites


// read sprite name
chr = 0
sprname$ = ""
WHILE chr <> 44


IF chr <> 44 THEN INC sprname$, CHR$(chr)


// move beyond space
FILESEEK 1, 1, 1

// read x position
chr = 0
num$ = ""
WHILE chr <> 44


IF chr <> 44 THEN INC num$, CHR$(chr)


tempspr.x = num$

// move beyond space
FILESEEK 1, 1, 1

// read y position
chr = 0
num$ = ""
WHILE chr <> 44


IF chr <> 44 THEN INC num$, CHR$(chr)


tempspr.y = num$

// move beyond space
FILESEEK 1, 1, 1

// read width
chr = 0
num$ = ""
WHILE chr <> 44


IF chr <> 44 THEN INC num$, CHR$(chr)


tempspr.w = num$

// move beyond space
FILESEEK 1, 1, 1

// read height
chr = 0
num$ = ""
WHILE chr <> 44


IF chr <> 44 THEN INC num$, CHR$(chr)


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
// End of testing

INC sprnum

WEND // end of end of file check

ENDIF // end of opening file

RETURN sprnum


FUNCTION SpriteAdd: idname$, index

SELECT idname$

CASE "bigsprite"

bigone = index


// do nout



// 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
patx = sprites[num].x+sprites[num].w
patxx = sprites[num].x

// if vertical flip
IF vflip = FALSE
paty = sprites[num].y
patyy = sprites[num].y+sprites[num].h
paty = sprites[num].y+sprites[num].h
patyy = sprites[num].y

// 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


// 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


// 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


FUNCTION Initialise:


IF plat$="ANDROID"
plats = 3 // Android
plats = 1 // Mac
plats = 2 // Linux
ELSEIF plat$="WIN32"
plats = 0 // The game is running on a PC computer
plats = 2 // Treat as Pre bug on WebOS 1.4.5

// 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




   STATIC OldTimeReport$,FPSDat,TimeReport$,FPSd,nada
   IF nada < 60
INC nada
FPSd = -1
OldTimeReport$=TimeReport$; FPSDat=FPSDat+1;
IF OldTimeReport$<>TimeReport$; FPSDat=0; ENDIF
  OldTimeReport$=TimeReport$; FPSDat=FPSDat+1;
  IF OldTimeReport$<>TimeReport$; FPSd=FPSDat ; FPSDat=0; ENDIF



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


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


//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


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)

SF_mflag = FALSE



// 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


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


// 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



// now check to see if there is consistency
IF sameflag = TRUE // we have a recommended

SELECT guess


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


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

// 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


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

CASE 0 // release the guess from memory

SF_guess = guess


// do nothing


ELSE // they are not the same!

SF_guess = 0
//SF_curd# = don't change because not sure!


ENDIF // end if reset = true


FUNCTION ReadControls:

MOUSESTATE mx, my, ma, mb

mx = (mx - xborder) / zoom
my = (my - yborder) / zoom

IF ma

INC press


press = 0


Read an article. Thought it should go here:

Thoughts? Is anyone surprised by this?
A bunch of dwarves descended on my little home and took me on a curious adventure to a lonely mountain. Acquired a wedding ring, lost a beer belly along the way and my long noodle arms have been replaced with pointlessly muscly things.

Been over a month and a half since I wrote a line of code. Feels strange getting back into things.
Humble Indie Bundle V is available for a fortnight. The usual pay what you want model is being used. Games included:-

Superbrothers: Sword & Sworcery EP

Don't know what else to say except wtaf.
I signed up for National Game Development Month. Here is my page:

Anyone else doing this or want to give it a try? Just two days left before it starts.  :O
Isometric look - code and some notes

You can download a compiled sample app here:
Instructions for the compiled app here:

Attached to this post is the source code.

There isn't much notation at all about what does what. I used TexturePacker for packing the textures (exporting as Gideos format). The layers of blocks were made with SimpleTileEditor. I wasn't intending this for general release, just a proof of concept after I had the idea. Sorry if the code is not very accessible.

[attachment deleted by admin]
Isometric look pseudo 3D 'engine'

You can download the example app here:

Left click and hold while moving the mouse to adjust view. Right click and hold while moving the mouse to rotate the view. Use the mouse wheel to zoom in or out.

I wrote this last night for fun after I had the idea about how it could be done. The whole scene is rendered with polyvectors and a little trigonometry math. Surfaces aren't drawn if they're covered up by other surfaces.

Since I can't think of anything to use it for that couldn't be done better in normal 3D or rendered isometric look bitmaps I probably won't ever use this for anything or develop it further. If anyone can think of a good use for this kind of look please let me know. :)