{ | |||||
"presets": ["env"] | |||||
} |
public/bundle.js | |||||
node_modules |
import Rect from './Rect'; | |||||
import Vec2 from './Vec2'; | |||||
export class Trait { | |||||
constructor(entity, name) { | |||||
this.name = name; | |||||
this.entity = entity; | |||||
this.enabled = true; | |||||
} | |||||
init() {} | |||||
update(dt) {} | |||||
} | |||||
export default class Entity { | |||||
constructor(level) { | |||||
this.level = level; | |||||
this.bounds = new Rect(); | |||||
this.velocity = new Vec2(); | |||||
this.t = {}; | |||||
this.traits = []; | |||||
} | |||||
init() { | |||||
for (let trait of this.traits) { | |||||
trait.init(); | |||||
} | |||||
} | |||||
update(dt) { | |||||
for (let trait of this.traits) { | |||||
if (trait.enabled) | |||||
trait.update(dt); | |||||
} | |||||
this.bounds.pos.x += this.velocity.x * dt; | |||||
this.bounds.pos.y += this.velocity.y * dt; | |||||
} | |||||
draw(ctx) {} | |||||
has(name) { | |||||
let t = this.t[name]; | |||||
return t != null && t.enabled; | |||||
} | |||||
addTrait(t) { | |||||
this.t[t.name] = t; | |||||
this.traits.push(t); | |||||
} | |||||
} |
import Player from './entities/Player'; | |||||
export default class Level { | |||||
constructor(canvas) { | |||||
this.step = 1 / 120; | |||||
this.canvas = canvas; | |||||
this.ctx = canvas.getContext("2d"); | |||||
this.lastTime = null; | |||||
this.raf = null; | |||||
this.timeAcc = 0; | |||||
this.entities = []; | |||||
} | |||||
spawn(ent, x, y) { | |||||
ent.bounds.pos.set(x, y); | |||||
this.entities.push(ent); | |||||
ent.init(); | |||||
} | |||||
physics(dt) { | |||||
this.entities.forEach(ent => | |||||
ent.update(dt)); | |||||
this.entities.forEach(ent => { | |||||
ent.bounds.pos.x += ent.velocity.x * dt; | |||||
ent.bounds.pos.y += ent.velocity.y * dt; | |||||
}); | |||||
} | |||||
draw() { | |||||
this.canvas.width = window.innerWidth; | |||||
this.canvas.height = window.innerHeight; | |||||
this.entities.forEach(ent => ent.draw(this.ctx)); | |||||
} | |||||
update(time) { | |||||
if (this.lastTime != null) { | |||||
let dt = (time - this.lastTime) / 1000; | |||||
this.timeAcc += dt; | |||||
while (this.timeAcc > this.step) { | |||||
this.physics(this.step); | |||||
this.timeAcc -= this.step; | |||||
} | |||||
this.draw(); | |||||
} | |||||
this.lastTime = time; | |||||
this.raf = requestAnimationFrame(time => this.update(time)); | |||||
} | |||||
start() { | |||||
this.stop(); | |||||
this.lastTime = null; | |||||
this.update(); | |||||
} | |||||
stop() { | |||||
if (this.raf != null) { | |||||
cancelAnimationFrame(this.raf); | |||||
this.raf = null; | |||||
} | |||||
} | |||||
} |
import Vec2 from './Vec2'; | |||||
export default class Rect { | |||||
constructor(pos = new Vec2(), size = new Vec2()) { | |||||
this.pos = pos; | |||||
this.size = size; | |||||
} | |||||
draw(ctx) { | |||||
ctx.moveTo(this.left, this.top); | |||||
ctx.lineTo(this.right, this.top); | |||||
ctx.lineTo(this.right, this.bottom); | |||||
ctx.lineTo(this.left, this.bottom); | |||||
ctx.closePath(); | |||||
ctx.stroke(); | |||||
} | |||||
get top() { | |||||
return this.pos.y; | |||||
} | |||||
set top(n) { | |||||
this.pos.y = n; | |||||
} | |||||
get bottom() { | |||||
return this.pos.y + this.size.y; | |||||
} | |||||
set bottom(n) { | |||||
this.pos.y = n - this.size.y; | |||||
} | |||||
get left() { | |||||
return this.pos.x; | |||||
} | |||||
set left(n) { | |||||
this.pos.x = n; | |||||
} | |||||
get right() { | |||||
return this.pos.x + this.size.x; | |||||
} | |||||
set right(n) { | |||||
this.pos.x = n - this.size.x; | |||||
} | |||||
} |
export default class Vec2 { | |||||
constructor(x = 0, y = 0) { | |||||
this.x = x; | |||||
this.y = y; | |||||
} | |||||
set(x, y) { | |||||
this.x = x; | |||||
this.y = y; | |||||
} | |||||
} |
import Entity from '../Entity'; | |||||
import Vec2 from '../Vec2'; | |||||
import KeyboardControls from '../traits/KeyboardControls'; | |||||
export default class Player extends Entity { | |||||
constructor(level) { | |||||
super(level); | |||||
this.bounds.size.set(20, 20); | |||||
this.addTrait(new KeyboardControls(this)); | |||||
} | |||||
draw(ctx) { | |||||
this.bounds.draw(ctx); | |||||
} | |||||
} |
import Level from './Level'; | |||||
import Player from './entities/Player'; | |||||
import Vec2 from './Vec2'; | |||||
let level = new Level(document.getElementById("canvas")); | |||||
level.spawn(new Player(level), 20, 20); | |||||
level.start(); |
import {Trait} from '../Entity'; | |||||
export default class KeyboardControls extends Trait { | |||||
constructor(entity) { | |||||
super(entity, "keyboardControls"); | |||||
this.speed = 500; | |||||
this.map = { | |||||
KeyA: 'left', | |||||
KeyD: 'right', | |||||
}; | |||||
this.pressed = {}; | |||||
} | |||||
onkey(evt) { | |||||
let name = this.map[evt.code]; | |||||
if (name == null) return; | |||||
evt.preventDefault(); | |||||
this.pressed[name] = evt.type === 'keydown'; | |||||
} | |||||
init() { | |||||
window.addEventListener("keydown", e => this.onkey(e)); | |||||
window.addEventListener("keyup", e => this.onkey(e)); | |||||
} | |||||
update(dt) { | |||||
if (this.pressed.left) | |||||
this.entity.velocity.x -= this.speed * dt; | |||||
if (this.pressed.right) | |||||
this.entity.velocity.x += this.speed * dt; | |||||
} | |||||
} |
{ | |||||
"name": "smartgame", | |||||
"version": "1.0.0", | |||||
"description": "", | |||||
"main": "index.js", | |||||
"scripts": { | |||||
"test": "echo \"Error: no test specified\" && exit 1", | |||||
"build-dbg": "browserify js/main.js -t [ babelify --sourceMap ] --debug --outfile public/bundle.js", | |||||
"build-prod": "browserify js/main.js -t [ babelify --sourceMap ] --outfile public/bundle.js" | |||||
}, | |||||
"author": "", | |||||
"license": "ISC", | |||||
"devDependencies": { | |||||
"babel-core": "^6.26.0", | |||||
"babel-preset-env": "^1.6.1", | |||||
"babelify": "^8.0.0", | |||||
"browserify": "^14.5.0" | |||||
} | |||||
} |
<!DOCTYPE html> | |||||
<html> | |||||
<head> | |||||
<meta charset="utf-8"> | |||||
<title>Game</title> | |||||
<style> | |||||
body { | |||||
margin: 0; | |||||
} | |||||
canvas { | |||||
display: block; | |||||
} | |||||
</style> | |||||
</head> | |||||
<body> | |||||
<canvas id="canvas"></canvas> | |||||
<script src="bundle.js"></script> | |||||
</body> | |||||
</html> |