malinovsky,
да, но возможно там не совсем очевидны преимущества ООП подхода в общем и классов в частности, давай я тебе покажу:
<canvas width="600" height="400"></canvas>
<script>
class Game {
constructor(canvas) {
canvas.onmouseenter = () => this.start();
canvas.onmouseleave = () => this.pause();
this.ctx2d = canvas.getContext('2d');
this.ctx2d.fillText('START', 0, 10);
this.world = new Set();
this._last = 0;
this._step = (now) => {
this._loop = requestAnimationFrame(this._step);
this.delta = Math.min(now - this._last, 100) / 1000;
this._last = now;
this.update();
this.render();
};
}
start() {
if (!this._loop) this._loop = requestAnimationFrame(this._step);
}
pause() {
if (this._loop) this._loop = cancelAnimationFrame(this._loop);
}
collide(entity1, type) {
for (let entity2 of this.world) {
if (entity1 != entity2 &&
entity2.type & type &&
entity1.x < entity2.x + entity2.w &&
entity1.x + entity1.w > entity2.x &&
entity1.y < entity2.y + entity2.h &&
entity1.h + entity1.y > entity2.y) return true;
}
return false;
}
update() {
for (let entity of this.world) if (entity.update) entity.update(this);
}
render() {
this.ctx2d.clearRect(0, 0, 600, 400);
for (let entity of this.world) if (entity.render) entity.render(this);
if (!this.world.size) this.pause();
}
}
class StaticBase {
constructor(statics) {
Object.assign(this, { x: 0, y: 0, w: 10, h: 10, c: 'black' }, statics);
}
render(game) {
game.ctx2d.fillStyle = this.c;
game.ctx2d.fillRect(this.x, this.y, this.w, this.h);
}
}
class DynamicBase extends StaticBase {
constructor(statics, dynamics) {
super(statics);
Object.assign(this, { vx: 0, vy: 0 }, dynamics);
}
update(game) {
this.x += this.vx * game.delta;
this.y += this.vy * game.delta;
}
}
class SinusoidBase extends DynamicBase {
constructor(statics, sinusoid) {
super(statics, null);
Object.assign(this, { A: 0, B: 0, C: 0, D: 0, E: 0, F: 0, G: 0, H: 0, t: 0 }, sinusoid);
}
update(game) {
this.t += game.delta;
this.vx = this.A + this.B * Math.sin(this.C * this.t + this.D);
this.vy = this.E + this.F * Math.sin(this.G * this.t + this.H);
super.update(game);
}
}
const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8;
class Line extends StaticBase {
constructor(statics, extra) {
super(statics);
Object.assign(this, { type: LINE }, extra);
}
}
class Shot extends DynamicBase {
constructor(statics, dynamics, extra) {
super(statics, dynamics);
Object.assign(this, { type: SHOT }, extra);
}
update(game) {
super.update(game);
if (game.collide(this, PLAYER | SHOT | LINE)) game.world.delete(this);
}
}
class Ship extends SinusoidBase {
constructor(statics, sinusoid, extra) {
super(statics, sinusoid);
Object.assign(this, { type: SHIP }, extra);
}
update(game) {
super.update(game);
if (game.collide(this, PLAYER | SHOT | LINE)) game.world.delete(this);
}
}
const theGame = new Game(document.querySelector('canvas'));
theGame.world
.add(new Line({ x: 0, y: 5, w: 5, h: 375 }))
.add(new Line({ x: 0, y: 0, w: 600, h: 5 }))
.add(new Line({ x: 595, y: 5, w: 5, h: 375 }))
.add(new Line({ x: 0, y: 380, w: 600, h: 20 }))
.add(new Shot({ x: 100, y: 370, w: 5, h: 5 }, { vy: -50 }))
.add(new Shot({ x: 400, y: 370, w: 5, h: 5 }, { vy: -20 }))
.add(new Shot({ x: 400, y: 5, w: 5, h: 5 }, { vy: 40 }))
.add(new Ship({ x: 100, y: 5, c: 'gray' }, { E: 20 }))
.add(new Ship({ x: 5, y: 100, c: 'brown' }, { A: 30 }))
.add(new Ship({ x: 410, y: 10, c: 'orange'}, { B: -200, C: 1, E: 20, F: 100, G: 2, H: 1.5 }))
.add(new Ship({ x: 580, y: 60, c: 'red' }, { B: -100, C: 1, E: 10, F: 100, G: 1, H: 1.5 }))
.add(new Ship({ x: 200, y: 5, c: 'green' }, { B: 100, C: 4, E: 30 }))
.add(new Ship({ x: 280, y: 5, c: 'blue' }, { B: 300, C: 2, E: 20 }))
</script>
Как видишь теперь разрабатывать удобней и понятней, и не составит труда придумывать новые проекты (классы) сущностей на основе базовых или более сложных и заселять ими игровой мир. И чем сложнее разработка тем эти преимущества острее чувствуются, потому что человеку по природе естественно размышлять объектами.