Make Coding Fun! 🎉
Developing a game in the browser
Marco Cecconi
@sklivvz
☝️ that was a hint to follow me on Twitter ☝️
The Main Loop ➰
Developing a game in the browser
/*
How to write on a CANVAS normally
*/
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = "30px Arial";
ctx.fillText("Hello World", 10, 50);
/*
How to draw on a CANVAS (Game Programming Sytle)
*/
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = "30px Arial";
var ticks = (new Date()).getTime();
ctx.clearRect(0, 0, 640, 480); // clear canvas
ctx.fillText("Hello World "+ticks%100, 10, 50);
window.requestAnimationFrame(draw);
}
draw();
Hello World!
Clear
Redraw
~30ms
Credits
Linh Pham - right curved arrow
Sprites and Assets 👻
Developing a game in the browser
/*
A simple animation
*/
// init
var x = 10;
var y = 50;
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = "30px Arial";
var ticks = (new Date()).getTime();
// update
x=(x+5)%640;
y=(y+5)%480;
// draw
ctx.clearRect(0, 0, 640, 480); // clear canvas
ctx.fillText("Hello World "+ticks%100, x, y);
window.requestAnimationFrame(draw);
}
draw();
/*
Sprite
*/
class Sprite {
constructor() {
// init
this._x=10;
this._y=50;
}
update(ticks) {
// update
this._x=(this._x+5)%640;
this._y=(this._y+5)%480;
}
// data for draw
get x() { return this._x; }
get y() { return this._y; }
}
/*
Loop with sprite
*/
// init
var hello = new Sprite();
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.font = "30px Arial";
var ticks = (new Date()).getTime();
// update
hello.update(ticks);
// draw
ctx.clearRect(0, 0, 640, 480); // clear canvas
ctx.fillText("Hello World "+ticks%100, hello.x, hello.y);
window.requestAnimationFrame(draw);
}
draw();
/* Sprite with Asset */
class Sprite {
constructor(asset) {
this._x=10;
this._y=50;
this._asset = asset;
}
update(ticks) {
this._x=(this._x+5)%640;
this._y=(this._y+5)%480;
}
draw(ctx, ticks) {
this._asset.draw(ctx, this, ticks);
}
get x() { return this._x; }
get y() { return this._y; }
}
class Asset {
draw(ctx, sprite, ticks) {
ctx.fillText("Hello World "+ticks%100, sprite.x, sprite.y);
}
}
Keyboard Input ⌨️
Developing a game in the browser
/* Hooking up the keyboard */
class Keyboard {
constructor() {
this._keys = new Set();
const k = this._keys;
document.addEventListener('keydown', function(evt) {
k.add(evt.code)
});
document.addEventListener('keyup', function(evt) {
k.delete(evt.code)
});
}
has(k) {
return this._keys.has(k);
}
}
/* Making Mario jump */
class Sprite {
constructor(asset) {
this._x=10;
this._y=160;
this._asset = asset;
this._jump = 0;
this._jumpPattern = [0, 5, 11, 15, 20, 24, 28, 32, 35, 38, 40, 42, 44, 45, 46, 47,
48, 48, 47, 46, 45, 44, 42, 40, 38, 35, 32, 28, 24, 20, 15, 10, 5];
}
update(ticks, keyboard) {
if(this._jump>0)
this._jump--;
if(this._jump==0 && keyboard.has('KeyJ'))
this._jump = this._jumpPattern.length-1;
this._x=(this._x+5)%640;
}
draw(ctx, ticks) {
this._asset.draw(ctx, this, ticks);
}
get x() { return this._x; }
get y() { return this._y - this._jumpPattern[this._jump]; }
}
Hit detection 💥
Developing a game in the browser
class DeadMario {
// A sprite that just falls down off the screen
// Uses the normal Mario asset
}
class Barrel {
constructor(asset) {
this._x=640;
this._y=170;
this._asset = asset;
}
update(ticks, keyboard) {
this._x=(this._x-3);
if (this._x<=0) this._x=640;
}
draw(ctx, ticks) {
this._asset.draw(ctx, this, ticks);
}
get x() { return this._x; }
get y() { return this._y; }
// All sprites export height and width
get h() { return 30; }
get w() { return 36; }
}
class BarrelAsset {
// draws a barrel using "barrel.png"
}
// returns true if point (px, py) is in rect (rx, ry, rw, rh)
function pointInRect(px, py, rx, ry, rw, rh) {
return rx<=px && (rx+rw>=px) && ry>=py && (ry-rh<=py);
}
rx, ry
rx, ry-rh
rx+rw, ry
rx+rw, ry-rh
px, py
// returns if any vertex of sprite 1 is inside the rect of sprite 2
// i.e. if there is any overlap
function collision(sprite1, sprite2) {
const x1 = sprite1.x;
const y1 = sprite1.y;
const w1 = sprite1.w;
const h1 = sprite1.h;
const x2 = sprite2.x;
const y2 = sprite2.y;
const w2 = sprite2.w;
const h2 = sprite2.h;
return pointInRect(x1,y1,x2,y2,w2,h2) || pointInRect(x1+w1,y1,x2,y2,w2,h2) ||
pointInRect(x1,y1-h1,x2,y2,w2,h2) || pointInRect(x1+w1,y1-h1,x2,y2,w2,h2);
}
sprite 2
sprite 1
Music and Sound 🎵
Developing a game in the browser
/*
Sound effects are trivial
*/
audio = new Audio('coin.mp3');
audio.play();
Scenes 🎭
Developing a game in the browser
Developing a game in the browser
https://is.gd/blasteroids
Developing a game in the browser
- ➰ Main Loop
- 👻 Sprites and Assets
- ⌨️ Keyboard
- 💥 Hit Detection
- 🎵 Music and Sound
- 🎭 Scenes
Questions? 🎮
Marco Cecconi
@sklivvz
☝️ that was a hint to follow me on Twitter ☝️
Repo: https://github.com/sklivvz/game-programming
Make Coding Fun! 🎉
By Marco Cecconi
Make Coding Fun! 🎉
In which the basics of how to write a 2D game in the browser are covered
- 680