|
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> Как видишь теперь разрабатывать удобней и понятней, и не составит труда придумывать новые проекты (классы) сущностей на основе базовых или более сложных и заселять ими игровой мир. И чем сложнее разработка тем эти преимущества острее чувствуются, потому что человеку по природе естественно размышлять объектами. |
Rise,
спасибо за науку!!! :thanks: |
Rise,
Спасибо! Буду изучать) |
Стоит еще отметить, что это PLAYER | SHOT | LINE - битовая маска, до 32 констант можно создать и комбинировать их в разные маски, что весьма удобно:
const TYPE_NAME01 = 1 << 0, // ...0000000001 (2) 1 (10) TYPE_NAME02 = 1 << 1, // ...0000000010 (2) 2 (10) TYPE_NAME03 = 1 << 2, // ...0000000100 (2) 4 (10) TYPE_NAME04 = 1 << 3, // ...0000001000 (2) 8 (10) TYPE_NAME05 = 1 << 4, // ...0000010000 (2) 16 (10) TYPE_NAME06 = 1 << 5, // ...0000100000 (2) 32 (10) TYPE_NAME07 = 1 << 6, // ...0001000000 (2) 64 (10) TYPE_NAME08 = 1 << 7, // ...0010000000 (2) 128 (10) TYPE_NAME09 = 1 << 8, // ...0100000000 (2) 256 (10) TYPE_NAME10 = 1 << 9, // ...1000000000 (2) 512 (10) // ... ... ... // TYPE_NAME32 = 1 << 31,// ...10000000000000000000000000000000 (2) 2147483648 (10) TYPE_GROUP1 = TYPE_NAME01 | TYPE_NAME02 | TYPE_NAME03 | TYPE_NAME04 | TYPE_NAME05, // ...0000011111 (2) 31 (10) TYPE_GROUP2 = TYPE_NAME06 | TYPE_NAME07 | TYPE_NAME08 | TYPE_NAME09 | TYPE_NAME10, // ...1111100000 (2) 992 (10) TYPE_ALL = TYPE_GROUP1 | TYPE_GROUP2 ; // ...1111111111 (2) 1023 (10) demo(TYPE_ALL, 'all'); demo(TYPE_GROUP1, 'group 1'); demo(TYPE_GROUP2, 'group 2'); demo(TYPE_ALL ^ TYPE_NAME03 ^ TYPE_NAME08, '(^) all types except 3 and 8'); // ...1101111011 (2) 891 (10) demo(TYPE_ALL & ~TYPE_NAME03 & ~TYPE_NAME08, '(& ~) all types except 3 and 8'); // demo(TYPE_NAME03 | TYPE_GROUP2 ^ TYPE_NAME08, 'only type 3 and group 2 except type 8'); // ...1101100100 (2) 868 (10) function demo(type, note) { const mask = [null, null, null, null, null, null, null, null, null, null]; if (type & TYPE_NAME01) mask[9] = '01'; if (type & TYPE_NAME02) mask[8] = '02'; if (type & TYPE_NAME03) mask[7] = '03'; if (type & TYPE_NAME04) mask[6] = '04'; if (type & TYPE_NAME05) mask[5] = '05'; if (type & TYPE_NAME06) mask[4] = '06'; if (type & TYPE_NAME07) mask[3] = '07'; if (type & TYPE_NAME08) mask[2] = '08'; if (type & TYPE_NAME09) mask[1] = '09'; if (type & TYPE_NAME10) mask[0] = '10'; console.log(mask, note); } |
Rise,
:write: |
Цитата:
|
j0hnik,
маска |
Rise,
рони, Большое Вам спасибо, что помогаете новичкам. :thanks: Начал разбирать примеры с ООП и осознал - нужно учить ООП.:-? Вот например, почему это работает: class Game { constructor() { this.loop = (time) => { console.log(time); requestAnimationFrame(this.loop); }; this.loop(); } } var game = new Game(); а это нет: class Game { constructor() { this.loop = function(time) { console.log(time); requestAnimationFrame(this.loop); }; this.loop(); } } var game = new Game(); Почему в стрелочных функциях this ведет себя не так как в обычных? Совсем запутался.:blink: |
Взялся, блин, делать игры, математику не понимаю, ООП не знаю. В GameDev меня ждет большое будущее...:-E
|
Часовой пояс GMT +3, время: 10:21. |