Here’s the simple ASCII demo game I promised you. You can start studying it now; the next release of SIMPL will include the fix for the bug I told you about, the one that keeps it from running at the right speed, which I’ve already fixed in my local working copy.
// ============================================================
// STAR CATCHER - a tiny game made of ASCII characters
// ============================================================
// Stars fall from the sky: catch them with your basket \_/.
// Left and Right move the basket. Miss three stars and the
// game is over.
//
// HOW IT WORKS
// The window is divided into a grid of square cells, like a
// sheet of squared paper: 20 columns and 16 rows. Each cell
// holds at most one ASCII character: a star is a "+", the
// basket is "\", "_" and "/" in three cells side by side, the
// ground is a row of "=".
//
// The game remembers only WHERE things are, as a row and a
// column of the grid (StarRow, StarCol, BasketCol). Many times
// a second it does the same three things, the GAME LOOP:
// 1. Input: read the keys, and move the basket.
// 2. Update: move the star, check whether it was caught.
// 3. Draw: clear the window and draw every character
// in its cell, then show the result.
// Moving a character from one cell to the next and drawing
// everything again is all there is to an animation: like the
// pages of a flip book, each frame is a little different from
// the one before.
// ============================================================
// ---------- The grid ----------
// The size of the grid, in cells, and of one cell, in pixels
CONSTANT Cols = 20
CONSTANT Rows = 14
CONSTANT Cell = 24
// ---------- What the game remembers ----------
DECLARE Screen : Canvas
// Where things are: a row from 1 (top) to Rows, a column from 1
// (left) to Cols. The basket is always on the last row, so only
// its column changes, and BasketCol is the column of its "\".
DECLARE BasketCol, StarRow, StarCol : INTEGER
DECLARE Score, Lives : INTEGER
// The clock of the falling star (see step 2 of the loop)
DECLARE FallTimer, FallInterval, LastTime, Now : REAL
// Which of its two shapes the star has now: it twinkles
DECLARE Twinkle : BOOLEAN
DECLARE Col : INTEGER
// ---------- Two procedures ----------
// Draws Text in the cell at Row and Col of the grid. This is the
// only place that turns cells into pixels: column 1 starts at
// x = 0, column 2 at x = Cell, and so on (4 more pixels move the
// character towards the middle of its cell). Everywhere else the
// program thinks in rows and columns, not in pixels.
PROCEDURE Put(Text : STRING, Row : INTEGER, Col : INTEGER)
CALL Screen.DrawText(Text, (Col - 1) * Cell + 4, (Row - 1) * Cell, Cell)
ENDPROCEDURE
// A new star at the top row, in a random column from 1 to Cols
PROCEDURE NewStar()
StarRow ← 1
StarCol ← INT(RAND(Cols)) + 1
ENDPROCEDURE
// ---------- Getting ready ----------
// The window: as wide as the grid, and two rows taller than the
// sky, for the ground and the score
Screen ← NEW Canvas(Cols * Cell, (Rows + 2) * Cell)
CALL Screen.SetBackground(10, 10, 30)
BasketCol ← Cols DIV 2
Score ← 0
Lives ← 3
// The star falls one cell every 0.25 seconds at the start
FallInterval ← 0.25
FallTimer ← 0
LastTime ← TIME()
CALL NewStar()
// ---------- The game loop ----------
WHILE Lives > 0 AND NOT Screen.ShouldQuit()
// 1. INPUT
// KeyPressed is TRUE only in the frame in which the key goes
// down, so each press moves the basket by exactly one cell.
// The basket can't leave the grid: its "\" stays from column
// 1 to column Cols - 2, so that its "/" is still inside.
IF Screen.KeyPressed("Left") AND BasketCol > 1 THEN
BasketCol ← BasketCol - 1
ENDIF
IF Screen.KeyPressed("Right") AND BasketCol < Cols - 2 THEN
BasketCol ← BasketCol + 1
ENDIF
// 2. UPDATE
// The loop goes round about 50 times a second, faster or
// slower depending on the computer. To make the star fall at
// the same speed everywhere, the program measures time with
// TIME() (seconds since the program started): FallTimer adds
// up the time that has passed, and each time it reaches
// FallInterval the star moves down one cell.
Now ← TIME()
FallTimer ← FallTimer + (Now - LastTime)
LastTime ← Now
IF FallTimer >= FallInterval THEN
FallTimer ← FallTimer - FallInterval
StarRow ← StarRow + 1
// A different shape at each step: the star twinkles
Twinkle ← NOT Twinkle
IF StarRow = Rows THEN
// The star has reached the basket's row. The basket
// fills three cells, from BasketCol to BasketCol + 2:
// the star is caught if its column is one of them.
IF StarCol >= BasketCol AND StarCol <= BasketCol + 2 THEN
Score ← Score + 1
// Each star caught makes the next ones a little
// faster, down to 0.08 seconds per cell
FallInterval ← MAX(0.08, FallInterval - 0.01)
ELSE
Lives ← Lives - 1
ENDIF
CALL NewStar()
ENDIF
ENDIF
// 3. DRAW
// Clear wipes the whole window with the background color, and
// everything is drawn again where it is now. Nothing has to
// be "rubbed out" from where it was before.
CALL Screen.Clear()
// The star, in yellow: "+" and "x" in turn, so it twinkles
CALL Screen.SetColor(255, 230, 80)
IF Twinkle THEN
CALL Put("+", StarRow, StarCol)
ELSE
CALL Put("x", StarRow, StarCol)
ENDIF
// The basket, in light blue: one character in each of its
// three cells, so it is exactly three cells wide, as the
// test in step 2 expects
CALL Screen.SetColor(120, 220, 255)
CALL Put("\", Rows, BasketCol)
CALL Put("_", Rows, BasketCol + 1)
CALL Put("/", Rows, BasketCol + 2)
// The ground, in green: an "=" in every cell of the row
// under the basket
CALL Screen.SetColor(90, 160, 90)
FOR Col ← 1 TO Cols
CALL Put("=", Rows + 1, Col)
NEXT Col
// The score, on the last row, in smaller characters
CALL Screen.SetColor(230, 230, 240)
CALL Screen.DrawText("Score " & STR(Score) & " Lives " & STR(Lives), 8, (Rows + 1) * Cell + 4, 20)
// Everything drawn so far appears in the window at once, so
// the player never sees a half-drawn frame
CALL Screen.Show()
// A short pause before the next frame: it lets the computer
// rest, and WAIT also reads the keys pressed in the meantime
CALL WAIT(0.02)
ENDWHILE
// ---------- The end ----------
// The last frame stays on the screen for two seconds, with the
// game over in the middle of the sky
IF Lives = 0 THEN
CALL Screen.SetColor(255, 90, 90)
CALL Screen.DrawText("GAME OVER", 138, 130, 48)
CALL Screen.Show()
CALL WAIT(2)
ENDIF
OUTPUT "Game over! You caught ", Score, " stars."
CALL Screen.Close()










