Hi All,
Been playing around with the new AppGameKit Studio, and decided to write Conway's Game Of Life.
Please find the source code below, and enjoy.
As a helpful read, the following link takes you to the Wikipedia reference for 'Game Of Life'
https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
The best pattern I find, is 'Die Hard', or 'Acorn'.
Paul.
//
// Project: GameOfLife
// Author: Paul Millard
// Created: 2019-05-18
//
// Free to use and experiment with. Comments welcome.
//
/*
Constants
*/
#constant KILLCELL 0
#constant LIVECELL 1
#constant GRIDWIDTH 120
#constant GRIDHEIGHT 120
#constant TRUE 1
#constant FALSE 0
#constant KEY_FROM 13
#constant KEY_ENTER 13
#constant KEY_SHIFT 16
#constant KEY_ESCAPE 27
#constant KEY_SPACE 32
#constant KEY_LEFT 37
#constant KEY_UP 38
#constant KEY_RIGHT 39
#constant KEY_DOWN 40
#constant KEY_TO 40
#constant EDIT_INIT 0
#constant EDIT_EDITING 1
#constant EDIT_DONE 2
// show all errors
SetErrorMode(2)
// set window properties
SetWindowTitle("GameOfLife")
SetWindowSize(GetDeviceWidth(), GetDeviceHeight(), 0)
SetWindowAllowResize(1) // allow the user to resize the window
// set display properties
SetVirtualResolution(GetDeviceWidth(), GetDeviceHeight()) // doesn't have to match the window
SetOrientationAllowed(1, 1, 1, 1) // allow both portrait and landscape on mobile devices
SetSyncRate(60, 0) // 30fps instead of 60 to save battery
SetScissor(0, 0, 0, 0) // use the maximum available screen space, no black borders
// Colour type
Type Color
red As Integer
green As Integer
blue As Integer
EndType
/*
Declare all variables and globals
*/
Global keys As Integer[512]
Global last As Float
Global now As Float
Global elapsed As Float
Global workGrid As Integer[GRIDWIDTH, GRIDHEIGHT]
Global displayGrid As Integer[GRIDWIDTH, GRIDHEIGHT]
Global oldGrid As Integer[GRIDWIDTH, GRIDHEIGHT]
Global editMode As Integer = EDIT_INIT
// Cursor flags
Global blinkTime As Float
Global blink As Integer
Global cellsFound As Integer
Global cX As Integer, cY As Integer
Global sX As Integer, sY As Integer
Global fX As Integer, fY As Integer
Global yellow As Color
Global green As Color
Global cellColor As Color
last = Timer()
yellow.red = 255
yellow.green = 255
yellow.blue = 0
green.red = 0
green.green = 255
green.blue = 0
sX = 0
fX = GRIDWIDTH
sY = 0
fY = GRIDHEIGHT
/*
Main loop
*/
Do
now = Timer()
elapsed = now - last
last = now
// Obtain key states
GetKeys()
// If system is in cell editing mode
If editMode <> EDIT_DONE
EditCells()
Else // System is in live cell generation mode
ProcessCells()
If keys[KEY_ENTER]
editMode = EDIT_INIT
EndIf
EndIf
If keys[KEY_ESCAPE] = 1
End
EndIf
RenderGrid()
// Uncomment to show timer
//Print("elapsed:" + Str(elapsed))
Sync()
Loop
/*
Function: GetKeys
Purpose: Obtain the key state for a limited number of keys used by the program
*/
Function GetKeys()
Local i As Integer
For i = KEY_FROM To KEY_TO
keys[i] = GetRawKeyPressed(i)
Next i
EndFunction
/*
Function: EditCells
Purpose: Handle editing of the cell grid using basic cursor and key navigation
*/
Function EditCells()
If editMode = EDIT_INIT
editMode = EDIT_EDITING
cX = GRIDWIDTH / 2
cY = GRIDHEIGHT / 2
ElseIf editMode = EDIT_EDITING
Print("[Arrows] Move Cursor")
Print("[SPACE] Toggle cell")
Print("[SHIFT] Clear")
Print("[ENTER] Go")
Print("[ESC] Quit")
EndIf
/*
Handle Up
*/
If keys[KEY_UP] = 1
If cY>0
Dec cY
EndIf
Endif
/*
Handle Down
*/
If keys[KEY_DOWN] = 1
If cY<GRIDHEIGHT
Inc cY
EndIf
EndIf
/*
Handle Left
*/
If keys[KEY_LEFT] = 1
If cX>0
Dec cX
EndIf
EndIf
/*
Handle Right
*/
If keys[KEY_RIGHT] = 1
If cX<GRIDWIDTH
Inc cX
EndIf
EndIf
/*
Toggle cell state
*/
If keys[KEY_SPACE] = 1
If workGrid[cX, cY] = LIVECELL
workGrid[cX, cY] = KILLCELL
Else
workGrid[cX, cY] = LIVECELL
EndIf
EndIf
/*
Clear grid
*/
If keys[KEY_SHIFT] = 1
For y = 0 To GRIDHEIGHT
For x = 0 To GRIDWIDTH
workGrid[x, y] = KILLCELL
Next x
Next y
EndIf
/*
Finish Editing
*/
If keys[KEY_ENTER] = 1
For y = sY To fY
For x = sX To fX
displayGrid[x, y] = workGrid[x, y]
Next x
Next y
editMode = EDIT_DONE
EndIf
EndFunction
/*
Obtain the cell count around a specific cell co-ordinate
mode=FALSE : workGrid
mode=TRUE : displayGrid
*/
Function GetCellCount(nX As Integer, nY As Integer, mode As Integer)
Local cellCount As Integer
Local vX As Integer, vY As Integer
Local cell As Integer
cellCount = 0
For y = (nY - 1) To (nY + 1)
For x = (nX - 1) To (nX + 1)
vX = x
vY = y
If x < 0
vX = GRIDWIDTH
ElseIf x > GRIDWIDTH
vX = 0
EndIf
If y < 0
vY = GRIDHEIGHT
ElseIf y > GRIDHEIGHT
vY = 0
EndIf
If mode = FALSE
cell = workGrid[vX, vY]
Else
cell = displayGrid[vX, vY]
EndIf
If cell = LIVECELL
Inc cellCount
EndIf
Next x
Next y
EndFunction cellCount
/*
Function: SetCell
Purpose: Sets the cell type for the display grid
*/
Function SetCell(x As Integer, y As Integer, cellType As Integer)
displayGrid[x, y] = cellType
EndFunction
/*
Function: SHowCell
Purpose: Draws the specified cell using the color provided
*/
Function ShowCell(x As Integer, y As Integer, col As Color)
Local sizeX As Float, sizeY As Float
Local pixX As Float, pixY As Float
Local rgb As Integer
rgb = MakeColor(col.red, col.green, col.blue)
sizeX = GetDeviceWidth() / (GRIDWIDTH + 1)
sizeY = GetDeviceHeight() / (GRIDHEIGHT + 1)
pixX = x * sizeX
pixY = y * sizeY
DrawBox(pixX + 1, pixY + 1, pixX + sizeX - 1, pixY + sizeY - 1, rgb, rgb, rgb, rgb, 1)
EndFunction
/*
Show New Display to screen
*/
Function RenderGrid()
ClearScreen()
For y = sY To fY
For x = sX To fX
// Draw Cell state
If editMode = EDIT_EDITING
If workGrid[x, y] = LIVECELL
ShowCell(x, y, yellow)
EndIf
Else
If displayGrid[x, y] = LIVECELL
ShowCell(x, y, yellow)
EndIf
EndIf
Next x
Next y
If blinkTime>0.2
blink = Not blink
blinkTime = 0
Else
blinkTime = blinkTime + elapsed
EndIf
If editMode = EDIT_EDITING And blink = TRUE
ShowCell(cX, cY, green)
EndIf
EndFunction
/*
Process the cell generation
*/
Function ProcessCells()
Local found As Integer
Local cellCount As Integer
found = FALSE
For y = 0 TO GRIDHEIGHT
For x = 0 TO GRIDWIDTH
If workGrid[x, y] = LIVECELL
If x < sX Then sX = x
If x > fX Then fX = x
If y < sY Then sY = y
If y > fY Then fY = y
found = TRUE
EndIf
Next x
Next y
Dec sX
Inc fX
Dec sY
Inc fY
If found = TRUE
If sX < 0 Then sX = 0
If sY < 0 Then sY = 0
If fX > GRIDWIDTH Then fX = GRIDWIDTH
If fY > GRIDHEIGHT Then fY = GRIDHEIGHT
Else
sX = 0
fX = GRIDWIDTH
sY = 0
fY = GRIDHEIGHT
EndIf
For y = sY TO fY
For x = sX TO fX
displayGrid[x, y] = workGrid[x, y]
// ******* Get number of neighbouring cells.
// ******* This number excludes the central cell.
cellCount = GetCellCount(x, y, FALSE)
If cellCount = 1 Then SetCell(x, y, KILLCELL)
If cellCount = 2 Then SetCell(x, y, KILLCELL)
If cellCount = 3 Then SetCell(x, y, LIVECELL)
If cellCount > 4 Then SetCell(x, y, KILLCELL)
Next x
Next y
workGrid = displayGrid
EndFunction