← All the games

Drift

All of Drift is here, in Quantum's game language: drift.q, compiled for Godot 4.4.1, with no script besides. Point at a tag or an attribute to see what it does; a tag opens its entry in the language's reference.

Play in the browser
The 35 tags it uses, of the language's 145 qg:animation qg:become qg:burst qg:button qg:character qg:counter qg:damage qg:destroy qg:fullscreen qg:goto-scene qg:hud qg:language qg:menu qg:on-collision qg:on-damage qg:on-death qg:on-input qg:pause qg:phrase qg:play qg:prefab qg:rebind qg:resume qg:scene qg:shake qg:slider qg:sound qg:spawner qg:sprite qg:spritesheet qg:state qg:text qg:timer qg:touch-button qg:touch-stick
drift.q222 lines Download On GitHub
<q:application id="drift" type="game">  <!-- Drift: the vertical shooter that drives the game language (PLAN_GAMES_2.md).       A ship at the bottom of the screen, three waves of drones and tanks that       come down and shoot, then a boss with two phases; lives, score, and a high       score kept between runs. The ship, the drones, the tanks, the boss and the       sky are drawn for it by scripts/art/drift.py (CC0); the sounds are       Kenney's Pixel Platformer (CC0). -->  <q:set name="score" value="0" type="number" />  <q:set name="lives" value="3" type="number" />  <q:set name="high_score" value="0" type="number" saved="true" />  <!-- The ships, the boss and the sky are drawn for this game by scripts/art/drift.py (CC0). -->  <qg:spritesheet name="ships" src="assets/ships.png" tile="24" />  <qg:spritesheet name="boss" src="assets/boss.png" tile="40" />  <qg:spritesheet name="space" src="assets/space.png" tile="256x224" />  <qg:sound bus="effects" name="shoot" src="assets/kenney/audio/jump.ogg" />  <qg:sound bus="effects" name="hit" src="assets/kenney/audio/stomp.ogg" />  <qg:sound bus="effects" name="boom" src="assets/kenney/audio/block.ogg" />  <qg:sound bus="effects" name="hurt" src="assets/kenney/audio/hurt.ogg" />  <qg:sound bus="effects" name="win" src="assets/kenney/audio/win.ogg" />  <!-- The ship's shot: flies up, gone after 80 ticks or when it leaves the screen. -->  <qg:prefab name="Shot" tag="shot" sheet="ships" frame="8" hitbox="18x8"             ai="fly" heading="up" speed="240" lifetime="80">    <qg:on-collision with="enemy">      <qg:damage target="other" amount="1" />      <qg:destroy target="me" />    </qg:on-collision>    <qg:on-collision with="boss">      <qg:damage target="other" amount="1" />      <qg:destroy target="me" />    </qg:on-collision>  </qg:prefab>  <qg:prefab name="EnemyShot" tag="enemy-shot" sheet="ships" frame="9" hitbox="6x6"             ai="fly" heading="down" speed="120" lifetime="150" />  <!-- A drone: comes straight down, one hit. -->  <qg:prefab name="Drone" tag="enemy" sheet="ships" frame="2" hitbox="14x14"             ai="fly" heading="down" speed="45" lifetime="400" health="1">    <qg:animation name="walk" frames="2,3,4" fps="6" />    <qg:on-death>      <qg:play sound="boom" />      <qg:burst at="me" color="#ffcc44" count="10" />      <q:set name="score" value="{score + 100}" />    </qg:on-death>  </qg:prefab>  <!-- A tank: slow, three hits, shoots. -->  <qg:prefab name="Tank" tag="enemy" sheet="ships" frame="5" hitbox="16x16"             ai="fly" heading="down" speed="20" lifetime="900" health="3"             fire-prefab="EnemyShot" fire-every="90">    <qg:animation name="walk" frames="5,6,7" fps="8" />    <qg:on-damage>      <qg:play sound="hit" />    </qg:on-damage>    <qg:on-death>      <qg:play sound="boom" />      <qg:burst at="me" color="#ff6644" count="16" />      <q:set name="score" value="{score + 300}" />    </qg:on-death>  </qg:prefab>  <!-- The boss: sways across the top, twenty hits; angry below half. -->  <qg:prefab name="Boss" tag="boss" sheet="boss" frame="0" hitbox="20x20"             ai="sway" speed="30" health="12" fire-prefab="EnemyShot" fire-every="90">    <qg:state name="calm" frame="0" speed="30" fire-every="90" initial="true" />    <qg:state name="angry" frame="1" speed="70" fire-every="60" />    <qg:on-damage>      <qg:play sound="hit" />      <q:if condition="{me.health <= 6 and me.state == 'calm'}">        <qg:become target="me" state="angry" />      </q:if>    </qg:on-damage>    <qg:on-death>      <qg:play sound="win" />      <qg:burst at="me" color="#ffffff" count="40" />      <qg:shake at="me" frames="20" strength="4" />      <q:set name="score" value="{score + 5000}" />    </qg:on-death>  </qg:prefab>  <!-- the game in Portuguese and Spanish (a web page's ?lang=pt, the command line's q-lang, or the system's language) -->    <!-- on a phone: what the keys do, under a finger, in every scene -->  <qg:touch-stick x="40" y="184" />  <qg:touch-button action="jump" label="A" x="220" y="184" />  <qg:language lang="pt" name="Português">    <qg:phrase text="SCORE" as="PONTOS" />    <qg:phrase text="LIVES" as="VIDAS" />    <qg:phrase text="HIGH" as="RECORDE" />    <qg:phrase text="HERE IT COMES" as="LÁ VEM" />    <qg:phrase text="THE DRIFT IS CLEAR" as="O CAMPO ESTÁ LIMPO" />    <qg:phrase text="THE DRIFT IS CLEAR. PRESS JUMP." as="O CAMPO ESTÁ LIMPO. APERTE PULAR." />    <qg:phrase text="LOST IN THE DRIFT. PRESS JUMP." as="PERDIDO NO CAMPO. APERTE PULAR." />      <qg:phrase text="Resume" as="Continuar" />    <qg:phrase text="Sounds" as="Sons" />    <qg:phrase text="Full screen" as="Tela cheia" />    <qg:phrase text="on" as="sim" />    <qg:phrase text="off" as="não" />    <qg:phrase text="Fire" as="Atirar" /></qg:language>  <qg:language lang="es" name="Español">    <qg:phrase text="SCORE" as="PUNTOS" />    <qg:phrase text="LIVES" as="VIDAS" />    <qg:phrase text="HIGH" as="RÉCORD" />    <qg:phrase text="HERE IT COMES" as="AHÍ VIENE" />    <qg:phrase text="THE DRIFT IS CLEAR" as="EL CAMPO ESTÁ DESPEJADO" />    <qg:phrase text="THE DRIFT IS CLEAR. PRESS JUMP." as="EL CAMPO ESTÁ DESPEJADO. PULSA SALTAR." />    <qg:phrase text="LOST IN THE DRIFT. PRESS JUMP." as="PERDIDO EN EL CAMPO. PULSA SALTAR." />      <qg:phrase text="Resume" as="Continuar" />    <qg:phrase text="Sounds" as="Sonidos" />    <qg:phrase text="Full screen" as="Pantalla completa" />    <qg:phrase text="on" as="sí" />    <qg:phrase text="off" as="no" />    <qg:phrase text="Fire" as="Disparar" /></qg:language>  <qg:scene name="play" width="256" height="224" background="#0a0a1e" seed="3">    <qg:sprite sheet="space" x="128" y="112" />    <!-- Escape (or the joypad's B) pauses, with the options; again, or Resume, goes on -->    <qg:on-input action="cancel">      <q:if condition="{paused()}"><qg:resume /><q:else><qg:pause /></q:else></q:if>    </qg:on-input>    <qg:menu if="{paused()}" size="12">      <qg:button label="Resume"><qg:resume /></qg:button>      <qg:slider label="Sounds" bus="effects" />      <qg:button label="{tr('Full screen') + ': ' + (tr('on') if fullscreen() else tr('off'))}"><qg:fullscreen /></qg:button>      <qg:rebind label="Fire" action="jump" />    </qg:menu>    <q:set name="message" value="" />    <q:set name="boss_down" value="false" type="boolean" />    <q:function name="hurt" params="me">      <qg:play sound="hurt" />      <qg:shake at="me" frames="10" strength="3" />      <q:set name="lives" value="{lives - 1}" />      <q:if condition="{lives <= 0}">        <qg:goto-scene name="game-over" />      </q:if>    </q:function>    <qg:character id="ship" controller="ship" sheet="ships" frame="0" x="128" y="196" hitbox="12x12"                  speed="120" bounds="scene"                  fire-action="jump" fire-prefab="Shot" fire-every="8" fire-sound="shoot">      <qg:animation name="idle" frames="0,1" fps="12" />      <qg:on-collision with="enemy" cooldown="90">        <qg:destroy target="other" />        <q:call function="hurt" args="me" />      </qg:on-collision>      <qg:on-collision with="enemy-shot" cooldown="90">        <qg:destroy target="other" />        <q:call function="hurt" args="me" />      </qg:on-collision>      <qg:on-collision with="boss" cooldown="90">        <q:call function="hurt" args="me" />      </qg:on-collision>    </qg:character>    <!-- Three waves, then the boss. x="random" is from the scene's seed. -->    <qg:spawner prefab="Drone" from="60" every="40" count="8" x="random" y="-12" />    <qg:spawner prefab="Tank" from="500" every="120" count="3" x="random" y="-12" />    <qg:spawner prefab="Drone" from="900" every="25" count="12" x="random" y="-12" />    <qg:spawner prefab="Tank" from="950" every="150" count="2" x="random" y="-12" />    <qg:spawner prefab="Boss" from="1500" every="1" count="1" x="128" y="40" />    <qg:timer after="1440">      <q:set name="message" value="HERE IT COMES" />    </qg:timer>    <qg:on-death of="boss">      <q:set name="boss_down" value="true" />      <q:set name="message" value="THE DRIFT IS CLEAR" />      <qg:goto-scene name="victory" />    </qg:on-death>    <qg:hud position="top-left">      <qg:counter bind="score" label="SCORE" />      <qg:counter bind="lives" label="LIVES" />      <qg:counter bind="high_score" label="HIGH" />      <qg:text bind="message" />    </qg:hud>  </qg:scene>  <qg:scene name="victory" width="256" height="224" background="#102040">    <qg:sprite sheet="space" x="128" y="112" />    <q:set name="title" value="THE DRIFT IS CLEAR. PRESS JUMP." />    <q:if condition="{score > high_score}">      <q:set name="high_score" value="{score}" />    </q:if>    <qg:on-input action="jump">      <q:set name="score" value="0" />      <q:set name="lives" value="3" />      <qg:goto-scene name="play" />    </qg:on-input>    <qg:hud position="top-center">      <qg:text bind="title" />      <qg:counter bind="score" label="SCORE" />      <qg:counter bind="high_score" label="HIGH" />    </qg:hud>  </qg:scene>  <qg:scene name="game-over" width="256" height="224" background="#000000">    <qg:sprite sheet="space" x="128" y="112" />    <q:set name="title" value="LOST IN THE DRIFT. PRESS JUMP." />    <q:if condition="{score > high_score}">      <q:set name="high_score" value="{score}" />    </q:if>    <qg:on-input action="jump">      <q:set name="score" value="0" />      <q:set name="lives" value="3" />      <qg:goto-scene name="play" />    </qg:on-input>    <qg:hud position="top-center">      <qg:text bind="title" />      <qg:counter bind="score" label="SCORE" />      <qg:counter bind="high_score" label="HIGH" />    </qg:hud>  </qg:scene></q:application>