Rise,
Спасибо! Буду изучать) |
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
|
malinovsky,
"use strict" class Game { constructor() { let self = this; this.loop = function(time) { console.log(time); requestAnimationFrame(self.loop); }; this.loop(); } } var game = new Game(); "use strict" class Game { constructor() { this.loop = function(time) { console.log(time); requestAnimationFrame(this.loop); }.bind(this); this.loop(); } } var game = new Game(); |
Цитата:
|
Цитата:
this это ключевое слово в JavaScript которое на этапе лексического разбора заменяется на ссылку на вполне конкретный объект. Это поведение подробно описано в спецификации. Функции в JS это объекты первого типа т.е. их можно использовать как обычные переменные (сохранять передавать как параметры и.т.д.) функции в JS могут оперировать не только с параметрами и локальной областью видимости но и с переменными во внешней области видимости. Что заставляет интерпретатор при создании каждой функции в JS создавать [[skope]] ссылка на который есть в каждой функции. Если бы механизма сохранения внешнего окружения не было то у сохраненной или же переданной функции не было бы доступа к внешним переменным. Именно создание уникального окружения (LexicalEnvironment) для каждой функции и делает возможным механизм замыкания. this заменяется на ссылку на обычный object в котором нет ни явных ни скрытых ссылок на контекст в котором исполняется функция. Т.е. если совсем грубо и на пальцах написал ключевое слово function вне глобальной области видимости получи оверхед на создание окружения для функции. Раньше приходилось писать универсальную функцию и раскидывать логику условным ветвлением сейчас можно использовать стрелочные функции отчего код становится проще и понятнее и быстрее. |
Rise,
посмотри пожалуйста: class Game { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.world = new Set(); this._last = 0; this.count = 0; this.objPlayer = new Player(this.canvas.width/2-30, this.canvas.height-30, 30, 20, "rgb(173, 105, 82)", 200); this.world.add(this.objPlayer); 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)")); console.log(this.objPlayer); this.lastObjShot = false; this._step = (now) => { this._loop = requestAnimationFrame(this._step); this.delta = Math.min(now - this._last, 100) / 1000; this._last = now; this.shipsGenerator(); this.shotsGenerator(); 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.positionX < entity2.positionX + entity2.sizeX && entity1.positionX + entity1.sizeX > entity2.positionX && entity1.positionY < entity2.positionY + entity2.sizeY && entity1.sizeY + entity1.positionY > entity2.positionY) return true; } return false; } stop() { if (this._loop) this._loop = cancelAnimationFrame(this._loop); } shipsGenerator() { if(this.count > 10) { this.world.add(new Ship(Math.random() * 590|0, 5, 10, 10, "rgb(22, 105, 67)", 100)); this.count = 0; } this.count++; } shotsGenerator() { if(keyEvent.space) { if(this.lastObjShot) { if(this.lastObjShot.positionY+7 < 375) { this.lastObjShot = new Shot(this.objPlayer.positionX+11, 375, 7, 7, "rgb(173, 105, 82)", 100); this.world.add(this.lastObjShot); } } else { this.lastObjShot = new Shot(this.objPlayer.positionX+11, 375, 7, 7, "rgb(173, 105, 82)", 100); this.world.add(this.lastObjShot); } } } } class Rect { constructor(positionX, positionY, sizeX, sizeY, color, vel) { this.positionX = positionX; this.positionY = positionY; this.sizeX = sizeX; this.sizeY = sizeY; this.color = color; this.vel = vel || false; } render(game) { game.ctx.fillStyle = this.color; game.ctx.fillRect(this.positionX, this.positionY, this.sizeX, this.sizeY); } } const PLAYER = 1, SHIP = 2, SHOT = 4, LINE = 8; class Player extends Rect { constructor(positionX, positionY, sizeX, sizeY, color, vel) { super(positionX, positionY, sizeX, sizeY, color, vel); Object.assign(this, { type: PLAYER }); } update(game) { if(keyEvent.left) { this.positionX -= this.vel * game.delta; } if(keyEvent.right) { this.positionX += this.vel * game.delta; } if (game.collide(this, PLAYER | SHIP | LINE )) game.stop(); } } class Ship extends Rect { constructor(positionX, positionY, sizeX, sizeY, color, vel) { super(positionX, positionY, sizeX, sizeY, color, vel); Object.assign(this, { type: SHIP }); } update(game) { this.positionY += this.vel * game.delta; if (game.collide(this, PLAYER | SHOT | LINE )) game.world.delete(this); } } class Shot extends Rect { constructor(positionX, positionY, sizeX, sizeY, color, vel) { super(positionX, positionY, sizeX, sizeY, color, vel); Object.assign(this, { type: SHOT }); } update(game) { this.positionY -= this.vel * game.delta; if (game.collide(this, SHIP | SHOT | LINE )) game.world.delete(this); } } class Line extends Rect { constructor(positionX, positionY, sizeX, sizeY, color, vel) { super(positionX, positionY, sizeX, sizeY, color, vel); Object.assign(this, { type: LINE }); } } 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')); |
Часовой пояс GMT +3, время: 07:09. |