A lightweight JavaScript game engine
git clone git://soophie.de/game-engine
blob: 9cd2406921e16cd195dc633a9198eedadac76f6c (2974 bytes)[doc][blame][raw]
1
import { scaleCanvas } from './canvas.js';2
import * as Collision from './collision.js';4
export class Game {5
constructor(width, height, { fps } = {}) {6
this.width = width || 900;7
this.height = height || 600;8
this.fps = 1000 / (fps || 60);9
this.then = Date.now();10
this.canvas = document.createElement('canvas');11
scaleCanvas(this.canvas, this.width, this.height);12
this.g = this.canvas.getContext('2d');13
}14
start() {15
requestAnimationFrame(this.loop.bind(this));16
this.update();17
this.g.save();18
this.render(this.g);19
this.g.restore();20
}21
loop() {22
requestAnimationFrame(this.loop.bind(this));23
this.now = Date.now();24
this.elapsed = this.now - this.then;25
if(this.elapsed > this.fps) {26
this.then = this.now - (this.elapsed % this.fps);27
this.update();28
this.g.save();29
this.render(this.g);30
this.g.restore();31
}32
}33
update() {34
// empty35
}36
render() {37
this.g.clearRect(0, 0, this.width, this.height);38
}39
resize(width, height) {40
this.width = width;41
this.height = height;42
scaleCanvas(this.canvas, this.width, this.height);43
}44
}46
export class Group {47
constructor() {48
this.items = [];49
}50
update() {51
for(let item of this.items) {52
item.update();53
}54
}55
render(g) {56
for(let item of this.items) {57
g.save();58
item.render(g);59
g.restore();60
}61
}62
collide() {63
for(const i of this.items) {64
i.items = [];65
i.collided = false;66
}67
const duplicate = [];68
for(const a of this.items) {69
for(const b of this.items) {70
if(!duplicate.includes(b)) {71
if(a !== b) {72
let collided = false;73
if(a.shape instanceof Shape.Rect && b.shape instanceof Shape.Rect) {74
collided = Collision.collideRect(a, b);75
}76
else if(a.shape instanceof Shape.Circle && b.shape instanceof Shape.Circle) {77
collided = Collision.collideCircle(a, b);78
}79
else {80
collided = Collision.collideRectAndCircle(a, b);81
}82
if(!a.collided) {83
a.collided = collided;84
}85
if(!b.collided) {86
b.collided = collided;87
}88
if(collided) {89
if(!a.items.includes(b)) {90
a.items.push(b);91
}92
if(!b.items.includes(a)) {93
b.items.push(a);94
}95
}96
}97
}98
}99
duplicate.push(a);100
}101
}102
add(item) {103
this.items.push(item);104
}105
[Symbol.iterator]() {106
return this.items.values();107
}108
}110
export class Surface {111
constructor(x, y, shape) {112
this.x = x;113
this.y = y;114
this.shape = shape;115
}116
update() {117
// empty118
}119
render(g) {120
if(this.shape instanceof Shape.Rect) {121
g.beginPath();122
g.rect(this.x, this.y, this.shape.width, this.shape.height);123
g.stroke();124
}125
if(this.shape instanceof Shape.Circle) {126
g.beginPath();127
g.arc(this.x, this.y, this.shape.radius, 2 * Math.PI, 0);128
g.stroke();129
}130
}131
}133
class Rect {134
constructor(width, height) {135
this.width = width;136
this.height = height;137
}138
}140
class Circle {141
constructor(radius) {142
this.radius = radius;143
}144
}