The Hack Club Game Lab is a microworld to discover programming and the joys of making things you want with computers by making simple games. It's Hack Club's version of a fantasy console (ex. PICO-8), and is designed to help run engaging Hack Club meetings by making it easy to get started building things instead of explaining things!
The game lab is designed with the principles of constuctionism. It's the idea that people learn best when they make things that they care about which they can share with others. We made Game Lab so you can learn programming by building programs filled with character and delight.
Design goals:
- A new coder without any prior coding experience should be able to figure out how to build a game like Pong within an hour from looking at examples and tinkering
- New coders will generate ideas for their own games they feel they can build with Game Lab through looking at examples
- Experienced coders should have fun making games in Game Lab too!
Join #gamelab-dev
on the Hack Club Slack to join the develpoment discussion!
Check out a minimal example game: Superb Macedonian Plumber Bro.
The Hack Club Game Lab requires a local HTTP server to run in development. Here's how to get it running on your own machine.
Clone repo:
$ git clone https://github.com/hackclub/game-lab
Start a local HTTP server inside the repo:
$ cd game-lab/
$ python3 -m http.server 3000
And then go to https://localhost:3000 in your web browser, and it should work!
Game-Lab is in active development. We want to make sure you can play the games you make even if they aren't compatible with the newest version of the editor. If you made a game and need to run it on an old version of Game-Lab you can use this site: https://game-lab-server-1.maxwofford.repl.co/[SEMANTIC_VERSION]/index.html
For example the first release of Game-Lab is available here: https://game-lab-server-1.maxwofford.repl.co/0.1.0/index.html
Initialize the Game Engine:
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
e.add({
tags: ["test"],
x: 188,
y: 69,
sprite: test_sprite,
scale: 4,
})
e.start();
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
e.add({
tags: ["test"],
solid: true,
x: 135,
y: 114,
sprite: test_sprite,
scale: 4,
update(obj) {
obj.vy += 2;
}
})
e.add({
tags: ["floor"],
solid: true,
x: -6,
y: 283,
sprite: floor,
scale: 11,
})
e.start();
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
e.add({
tags: ["test"],
solid: true,
x: 135,
y: 114,
sprite: test_sprite,
scale: 4,
update(obj) {
obj.vy += 2;
}
})
e.add({
tags: ["floor"],
solid: true,
x: -6,
y: 283,
sprite: floor,
scale: 11,
})
e.start();
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
e.add({
tags: ["test"],
solid: true,
x: 135,
y: 114,
sprite: test_sprite,
scale: 4,
collides(me, them) {
if (e.pressedKey(" ")) {
if (them.hasTag("floor")) me.vy -= 19;
}
},
update(obj) {
obj.vy += 2;
if (e.heldKey("ArrowLeft")) obj.x -= 3;
if (e.heldKey("ArrowRight")) obj.x += 3;
}
})
e.add({
tags: ["floor"],
solid: true,
x: -6,
y: 283,
sprite: floor,
scale: 11,
})
e.start();
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
const ctx = e.ctx;
e.add({
tags: ["player"],
sprite: test_sprite,
scale: 3,
solid: true,
x: 50,
y: 16,
collides(me, them) {
if (them.hasTag("platform")) me.vx = them.vx;
if (e.pressedKey(" ")) {
if (them.hasTag("platform")) me.vy -= 11;
}
},
update: (obj) => {
obj.ay = 0.4;
if (e.heldKey("ArrowLeft")) obj.x -= 3;
if (e.heldKey("ArrowRight")) obj.x += 3;
},
})
const addPlatform = (x, y) => e.add({
tags: ["platform"],
sprite: floor,
scale: 3,
solid: true,
x: x,
y: y,
vx: -1,
bounce: -1,
update: (obj) => {
if (obj.x < 0) obj.vx = 1;
if (obj.x + obj.width > e.width) obj.vx = -1
},
})
addPlatform(50, 200);
addPlatform(20, 100);
e.start();
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
e.add({
update() {
e.ctx.fillStyle = "pink";
e.ctx.fillRect(0, 0, e.width, e.height);
}
})
e.start();
const canvas = document.querySelector(".game-canvas");
const e = createEngine(canvas, 300, 300);
const ctx = e.ctx;
e.add({
tags: ["player"],
sprite: test_sprite,
scale: 2,
x: 150,
y: 50,
update: (obj) => {
if (e.heldKey("ArrowUp")) obj.y -= 3;
if (e.heldKey("ArrowDown")) obj.y += 3;
},
})
e.add({
tags: ["target"],
sprite: floor,
scale: 3,
x: 112,
y: 232,
collides(me, them) {
if (them.hasTag("player")) e.remove("target");
}
})
e.start();
Refer to the following example for all the available object properties:
e.add({
tags: ["tag-name"],
solid: true,
x: 178,
y: 126,
vx: 1,
vy: 3,
ax: 0,
ay: 0,
sprite: ball,
scale: 2,
bounce: 1,
origin: [0, 0], // x: 0 - 1, y: 0 - 1, "left|center|right top|center|bottom", "center"
collides(me, them) {
if (them.hasTag("tag-name")) {
me.vx *= 1.3;
me.vy *= 1.3;
}
},
update: (obj) => {
if (e.heldKey("ArrowDown")) obj.y += 3;
if (e.pressedKey("ArrowUp")) obj.y -= 3;
if (obj.y < 0) obj.vy *= -1;
if (obj.y > e.height - obj.height) obj.vy *= -1;
if (obj.x < 0) {
e.end();
e.addText("Blue Wins", e.width/2, e.height/2, { color: "blue", size: 32 })
}
if (obj.x > e.width - obj.width) {
e.end();
e.addText("Red Wins", e.width/2, e.height/2, { color: "red", size: 32 })
}
},
})
The Hack Club Game Lab is open source and licensed under the MIT License. Fork, remix, and make it your own! Pull requests and other contributions greatly appreciated.