@@ -0,0 +1,3 @@ | |||
{ | |||
"presets": ["env"] | |||
} |
@@ -0,0 +1,2 @@ | |||
public/bundle.js | |||
node_modules |
@@ -0,0 +1,51 @@ | |||
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); | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
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; | |||
} | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
export default class Vec2 { | |||
constructor(x = 0, y = 0) { | |||
this.x = x; | |||
this.y = y; | |||
} | |||
set(x, y) { | |||
this.x = x; | |||
this.y = y; | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
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); | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
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(); |
@@ -0,0 +1,34 @@ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
{ | |||
"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" | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
<!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> |