reference · house style
How spawn games are written.·
Every starter game is written the same way, so once you can read one you can read them all. These are the habits behind them. The checker looks for most of them and names them when your game skips one, and player two follows them in the code it writes for you.
The shape of a game·
The same parts, in the same order, in every starter. Each one starts with a banner comment, so you can jump to it.
- ABOUT THIS GAMEwhat it is, how you win and lose: your design
- SETTINGSthe numbers and colors you tune, as sliders
- STATEwhat the game remembers: score, lives, lists
- SPRITESthe player and the things that are always there
- MAIN LOOP
draw(), 30 times a second - PATTERNone banner per idea the game uses
- SHARED BLOCKSsmall helpers, the same in every game
The habits·
GP101 · game states
One variable says which screen you are on·
gameState is "start" on the title, "play" while you play, and "won" or "lost" at the end. draw() checks it, so every screen is one value of one variable. Add your own states beside these (a countdown, a round over), never instead of them.
var playing = false;
var dead = false;
var showWinScreen = false;
// "start", "play", "won" or "lost"
var gameState = "start";
GP102 · play again
startGame() puts everything back·
One function resets the score, the lives and the sprites, then sets gameState = "play". The title screen and both end screens call it, so SPACE always plays again.
if (keyWentDown("space")) {
gameState = "play"; // last game's score is still there
}
function startGame() {
clearAll(coins);
score = 0;
lives = START_LIVES;
gameState = "play";
}
sliders · fixed numbers
A number you tune is a slider; a number the game needs exact is not·
A speed, a gravity, how many, how long: put it in SETTINGS with a @knob line, and it becomes a slider on 03 make. A slider promises every value in its range still plays. A screen size or a tile size breaks the game when it moves, so it lives after STATE under the Fixed numbers heading, where no slider is offered.
// ===== SETTINGS =====
var TILE = 40;
player.x = player.x + 7;
// ===== SETTINGS =====
var SPEED = 7; // @knob number 2 15 "Speed"
// Fixed numbers (not sliders)
var TILE = 40; // one map square
GP104 · short draw()
draw() reads like a table of contents·
draw() runs 30 times a second. Keep it to a list of named jobs, and put each job in its own function. When something goes wrong, the name tells you where to look.
function draw() {
background(SKY_COLOR);
if (keyDown("left")) {
player.x = player.x - 7;
}
// ...80 more lines
}
function draw() {
background(SKY_COLOR);
if (gameState === "play") {
movePlayer();
spawnDrops();
checkGameOver();
}
drawSprites();
drawWords();
}
GP103 · clean up sprites
Take a sprite off the screen and out of its list, together·
Sprites made while you play go in a list. When one is caught or falls off the screen, removeAt(list, i) does both halves at once. Loop backwards, so taking one out does not skip the next.
for (var i = 0; i < coins.length; i++) {
if (player.isTouching(coins[i])) {
coins[i].destroy(); // still in the list
}
}
for (var i = coins.length - 1; i >= 0; i--) {
if (player.isTouching(coins[i])) {
removeAt(coins, i);
}
}
GP105 · lists, not numbered names
Many of the same thing go in one list·
Three enemies are one list, not enemy1, enemy2, enemy3. A list grows to thirty without new code, and one loop handles them all.
var enemy1 = createSprite(100, 0, 30, 30);
var enemy2 = createSprite(300, 0, 30, 30);
var enemy3 = createSprite(500, 0, 30, 30);
var enemies = [];
for (var i = 0; i < 3; i++) {
var x = 100 + i * 200;
enemies.push(createSprite(x, 0, 30, 30));
}
sprite data
What a sprite knows goes on the sprite·
A slime's health belongs to that slime. Set it when the slime is made, read it as slimes[i].health, and it leaves with the slime when removeAt takes it out. A second list kept in step is one more thing to forget. Pick a name the sprite does not have yet: life, scale and depth already mean something.
slimes.push(slime);
slimeHealth.push(3);
// ...and splice both, every time
slime.health = 3;
slimes.push(slime);
GP106 · write it once
The same lines twice means a function is missing·
Copy and paste works until you need to change it, and then you have to find every copy. Write it once, give it a name, call it from each place.
score = score + 1;
sparkAt(coin.x, coin.y, COIN_COLOR);
// ...the same two lines again for gems
// A grab: a point and a spark.
function grab(thing, color) {
score = score + 1;
sparkAt(thing.x, thing.y, color);
}
names
Names are words·
A name says what it holds: column, not col; snake, not s. You read your code far more often than you type it. Loop counters (i, j, k) and x, y, w, h are the names everyone already knows.
var c = Math.floor(x / 60);
var r = Math.floor(y / 60);
var column = Math.floor(x / 60);
var row = Math.floor(y / 60);
GP107 · comments
Every function says what it is for·
One line above each function, in plain words. Label each part with a banner. The next person to read your code is you, next week.
function tumble() {
wait = wait - 1;
// Count down the roll, then say it.
function tumble() {
wait = wait - 1;
GP108 · GP109 · leftovers
Every slider does something, and nothing sits unused·
A slider on 03 make changes one SETTINGS line. When nothing in the game reads that line any more, the slider does nothing. A function nobody calls, or a variable nobody reads, only makes the game longer to read. Use it or take it out: your earlier copies still have it.
var BOSS_SHOT_SPEED = 6; // @knob number 2 15 "Boss shot speed"
// ...
shot.velocityY = 6;
var BOSS_SHOT_SPEED = 6; // @knob number 2 15 "Boss shot speed"
// ...
shot.velocityY = BOSS_SHOT_SPEED;
art · feel
A picture never changes how the game plays, and every moment is seen·
Right after a sprite's art line, fitArt(sprite, w, h) fits the picture inside the sprite's own box, so a big drawing cannot make a level impossible. And where something happens, a grab, a hit, a crash, sparkAt(x, y, COLOR) shows it, because a sound slot starts switched off.
player.setAnimation("player");
score = score + 1;
player.setAnimation("player");
fitArt(player, 90, 24);
score = score + 1;
sparkAt(coin.x, coin.y, COIN_COLOR);
player two follows these too
Ask player two for something and the code it writes uses these habits. It never reworks code you already wrote to match them unless you ask: your game, your choices.
These are habits, not rules
The checker says works or solid, never "wrong", for a game that skips a habit, and your game still plays. The rules that stop a game from running are on Different from code.org and in the checker's own words.