A lightweight JavaScript game engine
git clone git://soophie.de/game-engine
blob: 69b394f363e061a4cc8f28ea491488d3233c4ffe (3093 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
remove(item) {106
const i = this.items.findIndex(n => n === item);107
if(i !== -1) {108
this.items.splice(i, 1);109
}110
}111
[Symbol.iterator]() {112
return this.items.values();113
}114
}116
export class Surface {117
constructor(x, y, shape) {118
this.x = x;119
this.y = y;120
this.shape = shape;121
}122
update() {123
// empty124
}125
render(g) {126
if(this.shape instanceof Shape.Rect) {127
g.beginPath();128
g.rect(this.x, this.y, this.shape.width, this.shape.height);129
g.stroke();130
}131
if(this.shape instanceof Shape.Circle) {132
g.beginPath();133
g.arc(this.x, this.y, this.shape.radius, 2 * Math.PI, 0);134
g.stroke();135
}136
}137
}139
class Rect {140
constructor(width, height) {141
this.width = width;142
this.height = height;143
}144
}146
class Circle {147
constructor(radius) {148
this.radius = radius;149
}150
}