├── bg.png ├── main.css ├── README.md ├── physics.js ├── fps.js ├── request-animation-frame.js ├── index.html ├── game-loop.js └── ball.js /bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/magnars/blockout/master/bg.png -------------------------------------------------------------------------------- /main.css: -------------------------------------------------------------------------------- 1 | body {background: #669;} 2 | #game {background: #000 url(bg.png);} 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blockout 2 | 3 | Recreating one of my first games for the web to learn Canvas. 4 | -------------------------------------------------------------------------------- /physics.js: -------------------------------------------------------------------------------- 1 | var BLOCKS = this.BLOCKS || {}; 2 | 3 | BLOCKS.physics = {}; 4 | 5 | BLOCKS.physics.a = 0.5; // px/s^2, acceleration 6 | -------------------------------------------------------------------------------- /fps.js: -------------------------------------------------------------------------------- 1 | var BLOCKS = this.BLOCKS || {}; 2 | 3 | (function (B) { 4 | 5 | var lastTime = +new Date(); 6 | 7 | B.calculateFPS = function () { 8 | var now = +new Date(), 9 | fps = 1000 / (now - lastTime); 10 | lastTime = now; 11 | 12 | return fps; 13 | }; 14 | 15 | }(BLOCKS)); 16 | -------------------------------------------------------------------------------- /request-animation-frame.js: -------------------------------------------------------------------------------- 1 | window.requestNextAnimationFrame = window.requestAnimationFrame || 2 | window.webkitRequestAnimationFrame || 3 | window.mozRequestAnimationFrame || 4 | window.msRequestAnimationFrame || 5 | window.oRequestAnimationFrame || 6 | alert("Your browser does not support proper animation. May I suggest Chrome?"); 7 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Blockout 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /game-loop.js: -------------------------------------------------------------------------------- 1 | var canvas = document.getElementById("game"); 2 | var ctx = canvas.getContext("2d"); 3 | 4 | var world = { 5 | width: canvas.width, 6 | height: canvas.height 7 | }; 8 | 9 | var ball = BLOCKS.ball.create(75, 75, 250, 0); 10 | 11 | ctx.fillStyle = "rgba(255, 255, 255, 1);"; 12 | 13 | function renderWorld() { 14 | world.fps = BLOCKS.calculateFPS(); 15 | ctx.clearRect(0, 0, world.width, world.height); 16 | ball.tick(world); 17 | ball.draw(ctx); 18 | window.requestNextAnimationFrame(renderWorld); 19 | } 20 | 21 | window.requestNextAnimationFrame(renderWorld); 22 | -------------------------------------------------------------------------------- /ball.js: -------------------------------------------------------------------------------- 1 | var BLOCKS = this.BLOCKS || {}; 2 | 3 | BLOCKS.ball = { 4 | create: function (x, y, vx, vy) { 5 | var instance = Object.create(this); 6 | 7 | instance.x = x; // px from 0, x position 8 | instance.y = y; // px from 0, y position 9 | instance.vx = vx; // px/s, x velocity 10 | instance.vy = vy; // px/s, y velocity 11 | 12 | return instance; 13 | } 14 | }; 15 | 16 | BLOCKS.ball.draw = function (ctx) { 17 | ctx.beginPath(); 18 | ctx.arc(this.x, this.y, this.r, 0, Math.PI*2, true); 19 | ctx.fill(); 20 | }; 21 | 22 | BLOCKS.ball.tick = function (world) { 23 | this.adjustXVelocity(world); 24 | this.adjustYVelocity(world); 25 | this.x += this.vx / world.fps; 26 | this.y += this.vy / world.fps; 27 | }; 28 | 29 | BLOCKS.ball.adjustYVelocity = function (world) { 30 | var bottomEdgeY = this.y + this.r; 31 | if (bottomEdgeY < world.height) { 32 | this.vy += (this.terminalVelocity - this.vy) * BLOCKS.physics.a / world.fps; 33 | } else if (bottomEdgeY > world.height) { 34 | this.vy *= -1 * this.e; 35 | this.vx *= this.f; 36 | this.y = world.height - this.r; 37 | } 38 | }; 39 | 40 | BLOCKS.ball.adjustXVelocity = function (world) { 41 | if (this.x + this.r > world.width) { 42 | this.vx *= -1 * this.e; 43 | this.vy *= this.f; 44 | this.x = world.width - this.r; 45 | } else if (this.x - this.r < 0) { 46 | this.vx *= -1 * this.e; 47 | this.vy *= this.f; 48 | this.x = this.r; 49 | } 50 | }; 51 | 52 | BLOCKS.ball.terminalVelocity = 1000; // px/s 53 | BLOCKS.ball.e = 0.8; // %, coefficient of restitution 54 | BLOCKS.ball.f = 0.8; // %, friction 55 | BLOCKS.ball.r = 20; // px, radius 56 | --------------------------------------------------------------------------------