Welcome to the "Roids" sample game. This is a very simple "Asteroids" clone.
Select Project->Build (shortcut: Ctrl/Cmd + B) or run it directly by clicking here.
Turn the ship left and right with the arrow keys and fire at incoming meteors with space.
This sample shows how to assemble a simple Defold game from collections, game objects, components, scripts, factories, GUI scenes, collision objects, and a custom render script with post-processing effect of an old CRT screen.
The game starts (and it's also good to start exploring the project) with the game.project. This file tells Defold which collection to load first, which render script to use, where the input bindings are, and what the default display size is. In this project it points to main/main.collection, render/roids.render, and input/game.input_binding. The display is set up as a portrait-style 640x1136 game.
The main scene is main.collection. A collection is a scene (or a "prefab") made from game object instances and their components. The main collection contains the player, a background sprite, the meteor spawner, the GUI, the main game controller, a camera, and a full-screen quad used by the post-processing effect. A useful first exercise is to open the collection and click each object in the Outline to see which components are attached to it.
Read more in Project Settings manual and Basic Building Blocks manual.
- Defold reads
game.project. - It loads the bootstrap collection
main.collection. - The
maingame object runsmain.script. main.scriptinitializes lives and score, hides the player, stops the spawner, and posts anew_gamemessage to itself.- The
new_gameflow shows the "GET READY" GUI, waits briefly, and then sends messages that enable the player, start the spawner, and update the HUD.
This is a common Defold pattern: one object can coordinate the game by sending messages, while the other objects remain focused on their own jobs.
Read more about Scripts here and about Message passing here.
-
Main - main game object with
main.scriptis the small game state machine. It does not move the player or create meteor physics itself. Instead, it decides when the round starts, when the player gets another try, when the game is over, and when the score changes. It "talks" to the player, spawner, and HUD usingmsg.post(). -
Player -
player.gois the player ship game object. It has a script, a sprite, collision shapes, sounds, and two factories: one for lasers and one for explosions.player.scriptrequests input focus when the player is active, reads theleft,right, andfireactions, rotates the ship, switches the sprite animation between idle and thrust, and creates lasers withfactory.create(). -
Spawner (
spawner.script) creates meteors over time. It picks a position just outside the screen, aims roughly toward the player with a random offset, increases difficulty by raising meteor speed as more meteors spawn, and creates the meteor with a factory. It also keeps a table of live meteor ids so the playfield can be cleared after the player dies. -
Meteors - game objects
meteor_large.goandmeteor_small.goboth usemeteor.script. The difference is data, not duplicated code: the small meteor overrides thetypescript property tosmall, while the large meteor keeps the defaultlarge. When a large meteor is hit, the shared script creates two small meteors using the factory embedded in the large meteor object. -
Lasers - game object
laser.gouseslaser.script. A laser calculates its velocity from its rotation when it is created, moves forward every frame, deletes itself after traveling far enough, and also deletes itself on collision. -
Explosions - game object
explosion.gousesexplosion.script. It plays theexplodeflipbook animation and deletes itself when the animation is completed.
Additionally, input binding (game.input_binding) maps keys to action names. The player script does not check for raw keys directly; it checks for action ids such as left, right, and fire. This keeps controls separate from gameplay code.
The sample uses messages for the communication:
main.scriptsendsgo,hide,run,stop,delete_all,get_ready,game_over,set_lives, andset_scoremessages.- The player sends
player_diestomain.scriptafter colliding with a meteor. - Meteors send
meteor_createdandmeteor_destroyedto the spawner so it can maintain its live meteor list. - Meteors also send
meteor_destroyedtomain.scriptso the score can increase.
Read more in the manuals: Addressing and Message passing.
Collision objects are attached to the player, lasers, and meteors. Their collision groups and masks decide what can collide and with which other group - player objects collide with meteors, lasers collide with meteors, and meteors listen for both player and laser hits. When Defold detects a collision, scripts receive a collision_response message and decide what to do next.
Read more in the manuals: Physics, Collision objects, Collision messages.
hud.gui contains the score text, "GET READY", "GAME OVER", and a life icon template. hud.gui_script hides and shows nodes, formats the score with leading zeroes, clones the life icon for each remaining life, and plays UI sounds.
Find more details in the GUI manual,
The atlas assets/sprites.atlas has the game images and defines animations such as ship_idle, ship_thrust, laser, and explode. Scripts switch sprite animations with sprite.play_flipbook(), while GUI nodes reference atlas images such as the life icon.
Read more details in the Atlas, and Sprites manuals.
This project uses a custom render pipeline: render/roids.render with a render/roids.render_script.
The render script creates an off-screen render target, draws the tile sprites, particles, debug graphics, GUI, and text into that target, then switches back to the default. It then draws a full-screen quad from main.collection using render/crt.material. The material uses special shaders: render/crt.vp and render/crt.fp to blur the rendered image slightly and add CRT-like scanlines.
This is common for screen-space post-processing effects: first render the game to a separate texture (a render target), then render that texture to the screen with a shader.
Read more about rendering and shaders in the manuals: Render, Materials and Shaders.
- Pressing space is mapped to
fireininput/game.input_binding. player.scriptreceives that action inon_input().- The player script plays a sound and creates
laser.gowithfactory.create(). laser.scriptmoves the laser forward every frame.- If the laser hits a meteor, both objects receive
collision_response. meteor.scriptdeletes the meteor, tellsmain.scriptto add score, and may spawn smaller meteors.main.scriptsendsset_scoretohud.gui_script.- The HUD script updates the score text in
hud.gui.
Read more about using Factories here.
- Change the controls in
input/game.input_binding. This teaches how input actions are named before scripts use them. Maybe addA,Dfor actionsleftandrightrespectively or a gamepad support. - Change the number of starting lives in
main.script. Look for the line with initial lives definition. - Change the points awarded for each meteor in
main.script. Look for themeteor_destroyedmessage handler. - Make lasers faster or slower in
laser.script. Look for a coressponding variable. - Make lasers range longer in
laser.script. Check when object is deleted. - Make meteors spawn more or less often in
spawner.script. Look at thenextspawn()function. - Make the game get harder faster in
spawner.script. Look at howself.countaffects meteor velocity. - Change what happens when a large meteor is destroyed in
meteor.script. The split behavior is inside theself.type == hash("large")branch. - Edit the score or lives layout in
hud.gui, then readhud.gui_scriptto see how those nodes are changed at runtime. - Adjust the CRT effect in
render/crt.fp. The blur and scanline functions are meant to experiment with.
- Add a start screen. Add a new state in
main.script, show a GUI prompt inhud.gui, and only sendgoandrunafter the player presses a start action. If it's your first time doing adding screen transitions, check the Colorslide tutorial or the Collection Proxy manual. - Add a high score. Store the best score in
main.script, update it when the player dies, and add another text node inhud.guito display it. - Add touch/mouse controls. Add touch/mouse input bindings, GUI buttons and then handle those actions.
- Add powerups. Create a new game object with visual sprite, and a collision object components, spawn it with a factory randomly on meteor destruction, and make the player collision object detect it and handle what happens on collision.
- Add a new meteor type. Create another meteor game object that uses
meteor.scriptwith different properties, sprite, collision shape, or split behavior.
Check out the Learn Hub website for more examples, tutorials, manuals and API docs.
If you run into trouble, help is available in our forum.
Happy Defolding!
This project is released under the Creative Commons CC0 1.0 Universal license.
You’re free to use these assets in any project, personal or commercial. There’s no need to ask permission before using these. Giving attribution is not required, but is greatly appreciated! Full license text
Defold Foundation


