Dinosaur Game for ClockworkPi PicoCalc
- introduction
- about the picocalc
- mmbasic programming
- coding with cursor
- the dinosaur game
- loading and running the program
Introduction
The Dinosaur Jump and Run Game is a classic endless runner game developed for the ClockworkPi PicoCalc. The player controls a dinosaur that must jump over obstacles while the speed continuously increases. The game is fully programmed in MMBasic and uses the PicoCalc's graphics capabilities for smooth animation.
The gameplay is simple: Press the Enter key to jump and avoid obstacles. The score increases continuously, and the speed increases every 100 points. The game saves the highscore on the SD card, so your best performance is preserved even after a restart.
About the PicoCalc
The ClockworkPi PicoCalc is a compact, portable computer based on the Raspberry Pi Pico. It features a 4-inch IPS display with 320x240 pixels, a full QWERTY keyboard with backlighting, and an SD card slot for data storage. The device runs on PicoMite, a special version of MMBasic optimized for the Raspberry Pi Pico.
MMBasic (or PicoMite) is a complete BASIC interpreter environment specifically developed for 32-bit microcontrollers. It offers extensive graphics functions, filesystem access, timers, and many other features that enable programming games and applications.
MMBasic Programming
MMBasic is a modern BASIC programming language developed for microcontrollers. It combines the simplicity of BASIC with powerful features such as floating-point numbers, extensive string processing, multidimensional arrays, and structured programming with subroutines and functions.
For the PicoCalc, PicoMite is used, a special port of MMBasic for the Raspberry Pi Pico. PicoMite supports all important MMBasic features and additionally provides hardware-specific functions for the PicoCalc display and peripherals.
The most important graphics commands used in the Dinosaur game are:
Box- Draws filled rectangles for spritesCircle- Draws circles (for the pterodactyl head)Line- Draws lines (for the ground)Text- Draws text on the screenRGB()- Creates color values for graphics commandsCls- Clears the screen
Coding with Cursor
The entire Dinosaur game was developed using Cursor, an AI-powered code editor that significantly accelerates the development process. Cursor combines the familiar interface of VS Code with advanced AI capabilities that can help write, refactor, and understand code.
When developing the Dinosaur game, Cursor's AI features were instrumental in several ways. To begin developing with Cursor, I started with making a plan like this:
# Dinosaur jump n run on the clockworkpi picocalc
create a jump and run game inspired by the dinosaur game in the chrome browser, when no internet is present.
The game is to be implemented in PicoMite MMbasic 6 (see Documentation here https://geoffg.net/Downloads/picomite/PicoMite_User_Manual.pdf)
- [ ] the dinosaur should be a sprite and can jump with enter button.
- [ ] The score is calculated by the distance the dino is running without hitting an obstacle.
- [ ] There a different kinds of obstables:
- [ ] cactus small
- [ ] cactus big
- [ ] flying pterodactyl
- [ ] the speed of the dino is increasing during the game every 100 score points
- [ ] in the the background we can see mountains, that are moving much slower as the foreground
- [ ] after hitting an obstacle the current score and the highscore are shown on the screens
Cursor's AI will help generate the initial code structure based on this plan.
One of Cursor's strengths is its ability to understand context. As you build the game, you can ask Cursor to add features incrementally:
- Sprite Creation: "Add a function to draw a running dinosaur sprite using Box commands"
- Physics: "Implement jump mechanics with gravity for the dinosaur"
- Collision Detection: "Add rectangle-based collision detection between the dinosaur and obstacles"
- File I/O: "Create functions to save and load highscore from SD card"
Cursor understands the existing codebase and can add new features that integrate seamlessly with what you've already written.
As the program grows, Cursor can help refactor and improve the code. You can select a section of code and ask Cursor to:
- Optimize performance
- Extract repeated code into subroutines
- Add comments and documentation
- Fix bugs or improve logic
When working with MMBasic, Cursor can help with syntax questions. If you're unsure about a command, you can ask Cursor directly, and it will provide examples and explanations based on MMBasic documentation.
For instance, when implementing the sprite drawing functions, Cursor
helped ensure the correct Box command syntax:
' Box syntax: X, Y, W, H, LW, C, FILL
Box x+8, y+12, 8, 6, 0, RGB(100, 150, 50), RGB(100, 150, 50)
When using Cursor to develop MMBasic programs, keep these best practices in mind:
- Start with structure: Define the overall program architecture first, then fill in details
- Use descriptive prompts: Be specific about what you want Cursor to generate
- Review generated code: Always review and test the code Cursor generates, especially for hardware-specific features
- Iterate: Build the program incrementally, testing each feature before moving to the next
- Reference documentation: Keep MMBasic documentation handy to verify Cursor's suggestions
Once the code is complete in Cursor, save the file as
dinosaur.bas. The file can then be transferred to the PicoCalc
via SD card. Copy the file to the root directory of the SD card, insert it
into the PicoCalc, and load it with:
LOAD "b:dinosaur.bas"
Using Cursor for development provides a much more efficient workflow than coding directly on the PicoCalc, especially for complex programs like the Dinosaur game with its multiple sprites, physics simulation, and file I/O operations. Of course cursor does not do everything right from the start, but you can feed the error back to cursor and it will try to fix it. Of course its helpful to also have some knowledge of the language and the syntax, to decide where to head. Sometimes the AI is lost in a dead end and you need to guide it back on track.
The Dinosaur Game
The Dinosaur game is divided into several logical sections. At the beginning of the program, all global variables are declared. These must be declared in MMBasic before they are used:
Dim HighScore As Integer
Dim DinoX As Integer
Dim DinoY As Integer
Dim DinoYVelocity
Dim IsJumping As Integer
Dim GroundY As Integer
Dim Score As Integer
Dim GameSpeed
Dim BaseSpeed
Dim ObstacleList(20, 3) As Integer ' x, y, type, active
Dim ObstacleCount As Integer
Dim GameOver As Integer
Dim FrameCount As Integer
Dim DinoFrame As Integer
Dim GameOverDrawn As Integer
The game saves the highscore on the SD card in drive
b:. The highscore functions automatically load and save the value:
Sub LoadHighScore
HighScore = 0
Open "b:highscore.txt" For Input As #1
Input #1, HighScore
Close #1
If HighScore < 0 Or HighScore > 1000000 Then
HighScore = 0
End If
End Sub
Sub SaveHighScore
Open "b:highscore.txt" For Output As #1
Print #1, HighScore
Flush #1
Close #1
End Sub
The sprites are drawn using Box commands. Each sprite
is a subroutine that receives the position as a parameter. The dinosaur
has two animations: one for running and one for jumping:
Sub DrawDinoRun(x, y)
' Körper (grün-braun) - BOX Syntax: X, Y, W, H, LW, C, FILL
Box x+8, y+12, 8, 6, 0, RGB(100, 150, 50), RGB(100, 150, 50)
' Beine
Box x+10, y+18, 2, 4, 0, RGB(80, 120, 40), RGB(80, 120, 40)
Box x+14, y+18, 2, 4, 0, RGB(80, 120, 40), RGB(80, 120, 40)
' Kopf (nach rechts)
Box x+12, y+4, 8, 6, 0, RGB(100, 150, 50), RGB(100, 150, 50)
' Auge (rechts im Kopf)
Box x+16, y+6, 1, 1, 0, RGB(255, 255, 255), RGB(255, 255, 255)
Box x+17, y+6, 1, 1, 0, RGB(0, 0, 0), RGB(0, 0, 0)
' Schwanz (links)
Box x+0, y+10, 4, 2, 0, RGB(100, 150, 50), RGB(100, 150, 50)
' Bauch (heller)
Box x+10, y+14, 4, 2, 0, RGB(150, 200, 100), RGB(150, 200, 100)
End Sub
There are different obstacle types: small cacti, large cacti, two small cacti side by side, and pterodactyls that fly in the air.
The main program consists of an infinite loop that continuously updates and redraws the game:
Main:
Print "Programm gestartet..."
InitGame
Print "Spiel initialisiert. Score="; Score; " HighScore="; HighScore
Cls
Do
UpdateGame
DrawGame
' Frame-Timing (ca. 60 FPS = 16ms pro Frame)
Pause 16
Loop Until 0
The UpdateGame subroutine handles game physics,
input, obstacle spawning, and collision detection. The
DrawGame subroutine draws all sprites and the score on
the screen.
The jump physics uses a simple gravity simulation:
' Dinosaurier-Physik (Sprung/Schwerkraft)
If IsJumping Then
DinoY = DinoY + DinoYVelocity
DinoYVelocity = DinoYVelocity + GRAVITY
' Auf dem Boden landen
If DinoY >= GROUND_LEVEL - DINO_HEIGHT Then
DinoY = GROUND_LEVEL - DINO_HEIGHT
DinoYVelocity = 0
IsJumping = 0
End If
End If
The constants GRAVITY and JUMP_STRENGTH
determine the jump behavior. These can be adjusted to make the game
harder or easier.
The collision detection uses a simple rectangle-to-rectangle check:
' Kollisionsprüfung
If Not (dinoRight < obsLeft Or dinoLeft > obsRight Or dinoBottom < obsTop Or dinoTop > obsBottom) Then
' Kollision!
GameOver = 1
GameOverDrawn = 0
UpdateHighScore Score
Exit For
End If
For each obstacle type, the corresponding dimensions are used to ensure precise collision detection.
Loading and Running the Program
To run the Dinosaur game on the PicoCalc, follow these steps:
- Copy the file
dinosaur.basto an SD card. The file should be saved in the root directory of the SD card. - Insert the SD card into the PicoCalc.
- Turn on the PicoCalc and wait until MMBasic/PicoMite has started.
- Load the program with the command:
TheLOAD "b:dinosaur.bas"b:denotes the SD card drive. - Start the program with:
RUN
The game starts automatically. Press the Enter key to jump. When the game is over, press Enter again to restart. The highscore is automatically saved on the SD card.
If you want to make changes to the code, you can edit the program
with EDIT or F4, change individual lines directly in the
MMBasic interpreter. Don't forget to save the program after changes
with SAVE "b:dinosaur.bas" or F2, which saves and starts the program directly.
From the idea to this running code it took me about 2 hours, including the time to write the plan and the time to write the code with the help of the AI. I find this quite impressive, since I only have a basic knowledge of the language and the syntax 😉
Disclaimer: I also used the cursor AI to write the text for this tutorial, so if you find any errors, please let me know.