Простой JavaScript холст игре


Вот ссылка на код на JSFiddle.

Это моя первая попытка играть с холста. Прежде чем я двигаться дальше, делать что-нибудь еще, было бы неплохо иметь представление от кого-то, кто знает, Canvas и JavaScript лучше меня.

Вещи, которые я ищу:

  • Способы оптимизации анимации

  • Пути оптимизации лазер рисования (я знаю, что мне нужно, чтобы очистить лазеры из массива каждый раз в некоторое время, когда они больше не в области черчения, просто не дошли еще.)

  • Способы оптимизации кода в целом и имеют хорошие повторного использования кода.

HTML-код:

<canvas id="world" style="height: 300px; width: 300px;" />

На JavaScript:

console.log("Game starting...");

var ship = new Object();
ship.name = "Enterprise";
ship.x = 0;
ship.y = 0;
ship.width = 50;
ship.left = false;
ship.right = false;
ship.up = false;
ship.down = false;
ship.fire = false;
ship.firerate = 5;
ship.cfirerate = 0;
var lazers = new Array();

var world = document.getElementById('world');
var cxt = world.getContext("2d");

$(document).bind('keydown', function(e) {
    if(e.keyCode==37){
        ship.left = true;
    }
    if(e.keyCode==38){
        ship.up = true;
    }
    if(e.keyCode==39){
        ship.right = true;
    }
    if(e.keyCode==40){
        ship.down = true;
    }
    if(e.keyCode==90){ //Z
        console.log("pew pew");
        ship.fire = true;
    }  
});
$(document).bind('keyup', function(e) {
    if(e.keyCode==37){
        ship.left = false;
    }
    if(e.keyCode==38){
        ship.up = false;
    }
    if(e.keyCode==39){
        ship.right = false;
    }
    if(e.keyCode==40){
        ship.down = false;
    }
    if(e.keyCode==90){ //Z
        ship.fire = false;
    }
});

function createLazer(type) {
if (type == 1) {//LEFT LAZER
    cxt.beginPath();
    cxt.moveTo(125+ship.x,140+ship.y);
    cxt.lineTo(125+ship.x,130+ship.y);
    var l = new Object();
    l.type = type;
    l.x = ship.x;
    l.y = ship.y;
    return l;
}
else if (type == 2) {//RIGHT LAZER
    cxt.beginPath();
    cxt.moveTo(125+ship.x+ship.width,140+ship.y);
    cxt.lineTo(125+ship.x+ship.width,130+ship.y);
    var l = new Object();
    l.type = type;
    l.x = ship.x;
    l.y = ship.y;
    return l;    
}
}

function drawWorld() {
cxt.fillStyle="#808080";
cxt.fillRect(0,0,300,300);
}
function drawLazers() {
for (x = 0; x < lazers.length; x++)
{
    cxt.beginPath();
    cxt.strokeStyle="#FF0000";
    if (lazers[x].type == 1) {
        cxt.moveTo(125+lazers[x].x,140+lazers[x].y);
        cxt.lineTo(125+lazers[x].x,120+lazers[x].y);
    }
    else if (lazers[x].type == 2) {
        cxt.moveTo(125+lazers[x].x+ship.width,140+lazers[x].y);
        cxt.lineTo(125+lazers[x].x+ship.width,120+lazers[x].y);
    }
    cxt.stroke();
    lazers[x].y = lazers[x].y - 6;

    //console.log("drawing lazer" + lazers[x].x + lazers[x].y);
}
}
function drawShip() {
if (ship.left) { ship.x = ship.x -5; }
if (ship.right) { ship.x = ship.x +5; }
if (ship.up) { ship.y = ship.y -5; }
if (ship.down) { ship.y = ship.y +5; }
if (ship.fire) {
    if (ship.cfirerate == 0) {
        lazers.push(createLazer(1));
        lazers.push(createLazer(2));
        ship.cfirerate = ship.firerate;
    }
}
if (ship.cfirerate != 0) {
    ship.cfirerate = ship.cfirerate - 1;
}

cxt.beginPath();
cxt.strokeStyle="#000000";
cxt.moveTo(125+ship.x,140+ship.y);
cxt.lineTo(150+ship.x,120+ship.y);
cxt.lineTo(175+ship.x,140+ship.y);
cxt.stroke();
}
function clear() {
cxt.clearRect(0, 0, 300, 300);
}

function gameLoop() {
drawWorld();
drawShip();
drawLazers();
}

setInterval(function() {
clear();
gameLoop();
}, 30);


1631
7
задан 5 августа 2011 в 06:08 Источник Поделиться
Комментарии
2 ответа

Классная программа!

Я поставил мой обзор код на JsFiddle.

Базовый обзор того, что я думал, чтобы улучшить:


  • Все постоянно о карте, корабль, лазеры, и ключей, все в одном месте для повышения масштабируемости.

  • Я использовал объект литералы и литералы массива, а не новый объект() и новый массив() , потому что через них короче и делает вещи легче манипулировать.

  • На клавиша вниз и клавиша вверх события обработчики был переработан с целью устранения дублирования кода.

  • В createLaser и drawLasers методов рефакторинга. Я удалил весь код для рисования от createLaser , потому что он, казалось, не делать ничего, и я снял расчетов в drawLasers , которые являются лишними с createLaser.

  • Я добавил код в drawLasers удалить лазером из массива, которые больше нет на карте. Я также удалить или переставить код рисования, который ничего не делал и был назвал слишком много раз. Я снял очистить() функция, потому что это, казалось, не делать ничего.

  • Я изменила отчетность форме Х = Х + У, Х = Х - У и Х = Х + 1 до Х += У, х= ги Х++, соответственно.

  • Я изменил один экземпляр формы массива.нажимаем(х); массив.толчок(г); в массив.толчок(Х,Y);

  • Я переименовал лазер для лазера , потому что я продолжал печатать лазера , и это вызвало ошибки, которые здесь трудно найти. Вы можете переименовать его обратно, если вы привыкли набирать лазер.

Вот копия пересмотренного кодекса:

console.log("Game starting...");

var ship = {
name: "Enterprise",
x: 125,
y: 120,
width: 50,
height: 40,
left: false,
right: false,
up: false,
down: false,
fire: false,
firerate: 5,
cfirerate: 0,
moveInterval: 5,
color: "#000000"
},
map = {
width: 300,
height: 300,
color: "#808080",
drawInterval: 30
},
laser = {
height: 20,
moveInterval: 6,
color: "#FF0000"
},
lasers = [],
keys = {
left: 37,
up: 38,
right: 39,
down: 40,
fire: 90 //Z
},
getKey = function(key) {
for (var i in keys) {
if (keys.hasOwnProperty(i)) {
if (keys[i] === key) {
return i
};
}
}
},
eventValues = {
keyup: false,
keydown: true
},
types = {
right: 1,
left: 2
};

var world = document.getElementById('world');
var cxt = world.getContext("2d");

$(document).bind('keydown keyup', function(e) {
var key = getKey(e.keyCode);
ship[key] = eventValues[e.type];
});

function createLaser(type) {
var x = ship.x;
if (type === types.right) {
x += ship.width;
}
var y = laser.height + ship.y;
return {
type: type,
x: x,
y: y,
}
}

function drawWorld() {
cxt.fillStyle = map.color;
cxt.fillRect(0, 0, map.width, map.height);
}

function drawLasers() {
cxt.beginPath();
cxt.strokeStyle = laser.color;
for (var i = 0; i < lasers.length; i++) {
var lsr = lasers[i];
if (lsr.y < -laser.height) {
lasers.splice(i, 1);
continue;
}
cxt.moveTo(lsr.x, lsr.y);
cxt.lineTo(lsr.x, lsr.y - laser.height);
cxt.stroke();
lsr.y -= laser.moveInterval;
}
}

function drawShip() {
if (ship.left) {
ship.x -= ship.moveInterval;
}
if (ship.right) {
ship.x += ship.moveInterval;
}
if (ship.up) {
ship.y -= ship.moveInterval;
}
if (ship.down) {
ship.y += ship.moveInterval;
}
if (ship.fire) {
if (ship.cfirerate === 0) {
lasers.push(createLaser(types.left), createLaser(types.right));
ship.cfirerate = ship.firerate;
}
}
if (ship.cfirerate !== 0) {
ship.cfirerate--;
}

cxt.beginPath();
cxt.strokeStyle = ship.color;
cxt.moveTo(ship.x, ship.y + (ship.height / 2));
cxt.lineTo(ship.x + (ship.width / 2), ship.y);
cxt.lineTo(ship.x + ship.width, ship.y + (ship.height / 2));
cxt.stroke();
}

function gameLoop() {
drawWorld();
drawShip();
drawLasers();
}

setInterval(gameLoop, map.drawInterval)

Если вы видите что-нибудь, что вы думаете, что это странно, или у вас есть вопрос о том, что я сделал, просто спросите меня об этом.

7
ответ дан 10 августа 2011 в 05:08 Источник Поделиться

Это больше личных предпочтений, чем каких-либо жестких требований, но я всегда предпочитаю литерал объекта синтаксис для индивидуальных заданий значение. Что бы превратить свои первоначальные заявления в этом:

var ship = {
name: "Enterprise",
x: 0,
y: 0.
width: 50,
left: false,
right: false,
up: false,
down: false,
fire: false,
firerate: 5,
cfirerate: 0
},
lazers = [];

Кроме того, несколько переменные могут быть объявлены в одном Варе заявление, если они разделены запятыми, и как показали.

Вы можете также извлечь выгоду из добавления границу, которая предотвращает корабль от перехода от мира. Как она стоит сейчас, вы можете потерять его.

1
ответ дан 9 августа 2011 в 04:08 Источник Поделиться