Rise,
this.delay -= game.delta; // NaN - а почему? пока сделал так: class Game { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.world = new Set(); this._last = 0; this.count = 0; this.world.add(new Player(this.canvas.width/2-30, this.canvas.height-30, 30, 20, "rgb(173, 105, 82)", 200)); this.world.add(new Attack(50)); this.world.add(new Line(0, 0, 600, 5, "rgb(36, 177, 219)")); this.world.add(new Line(0, 395, 600, 5, "rgb(36, 177, 219)")); this.lastObjShot = false; this._step = (now) => { this._loop = requestAnimationFrame(this._step); this.delta = Math.min(now - this._last, 100) / 1000; this._last = now; this.update(); this.render(); }; this._step(); } update() { for (let entity of this.world) if (entity.update) entity.update(this); } render() { this.ctx.fillStyle = "rgb(36, 177, 219)"; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); for (let entity of this.world) if (entity.render) entity.render(this); } 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; } stop() { if (this._loop) this._loop = cancelAnimationFrame(this._loop); } } class Rect { constructor() { } render(game) { game.ctx.fillStyle = this.color; game.ctx.fillRect(this.x, this.y, this.w, this.h); } } const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8; class Player extends Rect { constructor(px, py, pw, ph, c, v) { super(); Object.assign(this, { type: PLAYER, rate: 0.4, delay: 2, x : px, y : py, w : pw, h : ph, color : c, vel : v }); } update(game) { if(keyEvent.left) { this.x -= this.vel * game.delta; } if(keyEvent.right) { this.x += this.vel * game.delta; } this.delay -= 0.05; if (keyEvent.space && this.delay < 0) { this.delay = this.rate; game.world.add(new Shot(this.x+11, this.y-7, 7, 7, 'red', 100)); } if (game.collide(this, PLAYER | SHIP | LINE )) game.stop(); } } class Ship extends Rect { constructor(px, py, pw, ph, c, v) { super(); Object.assign(this, { type: SHIP, x : px, y : py, w : pw, h : ph, color : c, vel : v }); } update(game) { this.y += this.vel * game.delta; if (game.collide(this, PLAYER | SHOT | LINE )) game.world.delete(this); } } class Shot extends Rect { constructor(px, py, pw, ph, c, v) { super(); Object.assign(this, { type: SHOT, x : px, y : py, w : pw, h : ph, color : c, vel : v }); } update(game) { this.y -= this.vel * game.delta; if (game.collide(this, SHIP | SHOT | LINE )) game.world.delete(this); } } class Line extends Rect { constructor(px, py, pw, ph, c, v) { super(); Object.assign(this, { type: LINE, x : px, y : py, w : pw, h : ph, color : c, vel : v }); } } class Attack { constructor(s) { Object.assign(this, { size: s, rate: 0.5, delay: 0 }); } update(game) { this.delay -= 0.05; if (this.delay < 0) { this.delay = this.rate; game.world.add(new Ship(Math.random() * 590, 5, 10, 10, 'green', 100)); if (!--this.size) game.world.delete(this); } } } const keyEvent = { left : false, right : false, space : false }; window.onkeydown = function(e) { switch(e.keyCode) { case 37 : keyEvent.left = true; break; case 39 : keyEvent.right = true; break; case 32 : keyEvent.space = true; break; } }; window.onkeyup = function(e) { switch(e.keyCode) { case 37 : keyEvent.left = false; break; case 39 : keyEvent.right = false; break; case 32 : keyEvent.space = false; break; } }; const game = new Game(document.getElementById('canvas')); и у меня там кажется бардак в конструкторах :-? |
Rise,
спасибо) |
Rise,
Я тут еще заметил, что объекты при столкновении удаляются не все, например, если сталкивается пуля с противником и пуля удаляется первой, то противник может остаться и продолжить движение, поэтому я немного изменил код. Теперь вроде бы работает правильно. Жду твоего мнения. class Game { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.world = new Set(); this._last = 0; this.count = 0; this.world.add(new Player(this.canvas.width/2-30, this.canvas.height-30, 30, 20, "rgb(173, 105, 82)", 200)); this.world.add(new Attack(50)); this.lastObjShot = false; this._step = (now) => { this._loop = requestAnimationFrame(this._step); this.delta = Math.min(now - this._last, 100) / 1000; this._last = now; this.update(); this.render(); }; this._step(0); } update() { for (let entity of this.world) if (entity.update) entity.update(this); } render() { this.ctx.fillStyle = "rgb(36, 177, 219)"; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); for (let entity of this.world) if (entity.render) entity.render(this); } collide(entity1, type) { for (let entity2 of this.world) { if (entity1 != entity2 && entity1.x <= entity2.x + entity2.w && entity1.x + entity1.w >= entity2.x && entity1.y <= entity2.y + entity2.h && entity1.h + entity1.y >= entity2.y) { if(entity1.type == (SHOT || SHIP) && entity2.type == (SHIP || SHOT)) { this.world.delete(entity1); this.world.delete(entity2); } if(entity1.type == PLAYER && entity2.type == SHIP) { this.stop(); } } } } stop() { if (this._loop) this._loop = cancelAnimationFrame(this._loop); } } class Rect { constructor() { } render(game) { game.ctx.fillStyle = this.color; game.ctx.fillRect(this.x, this.y, this.w, this.h); } } const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8; class Player extends Rect { constructor(px, py, pw, ph, c, v, game) { super(); Object.assign(this, { type: PLAYER, rate: 0.1, delay: 0, x : px, y : py, w : pw, h : ph, color : c, vel : v }); } update(game) { if(keyEvent.left) { this.x -= this.vel * game.delta; } if(keyEvent.right) { this.x += this.vel * game.delta; } this.delay -= game.delta; if (keyEvent.space && this.delay < 0) { this.delay = this.rate; game.world.add(new Shot(this.x+11, this.y-8, 7, 7, 'red', 200)); } game.collide(this); } } class Ship extends Rect { constructor(px, py, pw, ph, c, v, game) { super(); Object.assign(this, { type: SHIP, x : px, y : py, w : pw, h : ph, color : c, vel : v }); game.ship = this; } update(game) { this.y += this.vel * game.delta; game.collide(this); } } class Shot extends Rect { constructor(px, py, pw, ph, c, v) { super(); Object.assign(this, { type: SHOT, x : px, y : py, w : pw, h : ph, color : c, vel : v }); } update(game) { this.y -= this.vel * game.delta; game.collide(this); if(this.y < 0) game.world.delete(this); } } class Attack { constructor(s) { Object.assign(this, { size: s, rate: 0.5, delay: 0 }); } update(game) { this.delay -= game.delta; if (this.delay < 0) { this.delay = this.rate; game.world.add(new Ship(Math.random() * 590, 5, 10, 10, 'green', 100, game)); if (!--this.size) game.world.delete(this); } } } const keyEvent = { left : false, right : false, space : false }; window.onkeydown = function(e) { switch(e.keyCode) { case 37 : keyEvent.left = true; break; case 39 : keyEvent.right = true; break; case 32 : keyEvent.space = true; break; } }; window.onkeyup = function(e) { switch(e.keyCode) { case 37 : keyEvent.left = false; break; case 39 : keyEvent.right = false; break; case 32 : keyEvent.space = false; break; } }; const game = new Game(document.getElementById('canvas')); |
Rise,
тоже самое, вот игра: https://himbotop.github.io/MFG3/ и сам код class Start { constructor(canvas, urlArr) { this.canvas = canvas; this.urlCache = {}; urlArr.forEach((url) => { this.load(url); }); } load(url) { let img = new Image(); img.onload = () => { this.urlCache[url] = img; if(this.isReady()) { new Game(this, new Player(this.canvas.width/2-60, this.canvas.height-100, 102, 83, this.get('img/ship.png'), 200), new Attack(50)); } }; this.urlCache[url] = false; img.src = url; } get(url) { return this.urlCache[url]; } isReady() { let ready = true; for(let k in this.urlCache) { if(this.urlCache.hasOwnProperty(k) && !this.urlCache[k]) { ready = false; } } return ready; } } class Game { constructor(resources, ...entities) { this.ctx = resources.canvas.getContext('2d'); this.resources = resources; this.terrainPattern = this.ctx.createPattern(this.resources.get('img/starfield.png'), 'repeat'); this.world = new Set(entities); this.cache = new Set(); this._last = 0; this.lastObjShot = false; this._step = (now) => { this._loop = requestAnimationFrame(this._step); this.delta = Math.min(now - this._last, 100) / 1000; this._last = now; this.update(); this.render(); }; this._step(0); } update() { for (let entity of this.world) if (entity.update) entity.update(this); for (let entity of this.cache) { this.world.delete(entity); this.cache.delete(entity); } } render() { this.ctx.fillStyle = this.terrainPattern; this.ctx.fillRect(0, 0, this.resources.canvas.width, this.resources.canvas.height); for (let entity of this.world) if (entity.render) entity.render(this); } 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; } stop() { if (this._loop) this._loop = cancelAnimationFrame(this._loop); } } class Draw { constructor(options) { const property = { x : null, y : null, w : null, h : null, image : null, vel : null }; let length = 0; for(let prop in property) { property[prop] = options[length]; length++ } Object.assign(this, property); } render(game) { game.ctx.drawImage(this.image, this.x, this.y, this.w, this.h) } } const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8; class Player extends Draw { constructor(...options) { super(options); Object.assign(this, { type: PLAYER, rate: 0.2, delay: 0 }); } update(game) { if(keyEvent.left) { this.x -= this.vel * game.delta; } if(keyEvent.right) { this.x += this.vel * game.delta; } this.delay -= game.delta; if (keyEvent.space && this.delay < 0) { this.delay = this.rate; game.world.add(new Shot(this.x+45, this.y-30, 10, 38, game.resources.get('img/bullet.png'), 300)); } if (game.collide(this, PLAYER | SHIP | LINE)) game.stop(); } } class Ship extends Draw { constructor(...options) { super(options); Object.assign(this, { type: SHIP }); } update(game) { this.y += this.vel * game.delta; if (game.collide(this, PLAYER | SHOT | LINE )) game.cache.add(this); } } class Shot extends Draw { constructor(...options) { super(options); Object.assign(this, { type: SHOT }); } update(game) { this.y -= this.vel * game.delta; if (game.collide(this, SHIP | SHOT | LINE )) game.world.delete(this); if(this.y < 0) game.world.delete(this); } } class Attack { constructor(s) { Object.assign(this, { size: s, rate: 0.5, delay: 0 }); } update(game) { this.delay -= game.delta; if (this.delay < 0) { this.delay = this.rate; game.world.add(new Ship(Math.random() * 590, 5, 66, 74, game.resources.get('img/enemy.png'), 100)); if (!--this.size) game.world.delete(this); } } } const keyEvent = { left : false, right : false, space : false }; window.onkeydown = function(e) { switch(e.keyCode) { case 37 : keyEvent.left = true; break; case 39 : keyEvent.right = true; break; case 32 : keyEvent.space = true; break; } }; window.onkeyup = function(e) { switch(e.keyCode) { case 37 : keyEvent.left = false; break; case 39 : keyEvent.right = false; break; case 32 : keyEvent.space = false; break; } }; const canvas = document.getElementById('canvas'); const start = new Start(canvas, ["img/bullet.png", "img/enemy.png", "img/ship.png", "img/starfield.png"]); |
Часовой пояс GMT +3, время: 07:07. |