Разработка игры на Canvas, часть 5. Атака

Html5_canvas_logoДобрый день, уважаемые читатели!

Сегодня мы продолжаем писать нашу игру на canvas. И теперь мы переходим к самому интересному — атаке.

В данной статье мы сделаем:

  1. Анимацию игрока во время атаки
  2. Добавим возможность атаковать
  3. Добавим сам снаряд, которым атакует игрок
  4. Местами поправим наш код

 

Поехали!

 

Анимация игрока во время атаки

Прежде всего я обновил файл с анимациями игрока и добавил новые кадры атаки, а заодно и стрелу, которой будет атаковать наш игрок:

player-attack

 

Теперь пропишем анимацию атаки в коде.

animationsPlayer = {
  ...
  attackRight: [
	371, 20, 50, 51,
	435, 20, 50, 51,
	547, 20, 50, 51
  ],
  attackLeft: [
	378, 79, 50, 51,
	435, 79, 50, 51,
	488, 79, 50, 51
  ]
};

Готово.

 

Внесем сразу несколько переменных, которые нам понадобятся для стрельбы:

var canvasWidth = 600,//window.innerWidth;
	canvasHeight = 500,//window.innerHeight;
	direction = 'right', // изменили начальное значение
	arrowDirection = '',
	arrowSpeed  = 6,
	wizardSpeed = 0.5,
	wizards = [],
	lights = [], // массив объектов молний
	arrows = [],
	health = 100,
	lastFire = Date.now(); // для расчета стрельбы

Переменная lastFire понадобится для того, чтобы ограничить стрельбу игрока по времени.

Добавим игроку стрел:

player.speed = 3;
player.sizeX = 50;
player.sizeY = 50;
player.arrows = 100;

 

Выведем на экран количество стрел:

var gameLoop = new Konva.Animation(function(frame) {
	...
	simpleText.setAttr('text', 'Молний: ' + lights.length + ", Магов на карте: " + wizards.length + ' Здоровье: ' + Math.floor(health) + ", Стрел: " + player.arrows);
	...
}, layer);

 

Добавим возможность атаковать

Добавим возможность стрельбы по нажатию пробела. Здесь ничего сложного, если у игрока есть стрелы и с последнего выстрела прошло больше 500 мсек, то производим выстрел.

Для определения куда, полетит стрела мы добавим условие на проверку direction.

function handleInput() {

	if (player.attrs.animation == 'attackRight' ||
		player.attrs.animation == 'attackLeft') {
		animationAttack();
		return;
	}

	...
	if (direction == 'left') {
		player.attrs.animation = 'idleLeft';
	}

	if(input.isDown('DOWN') || input.isDown('s')) {
		if (player.attrs.y + player.speed < canvasHeight - player.sizeY) {
			...
			direction = 'right';
		}
	}

	if(input.isDown('UP') || input.isDown('w')) {
		if (player.attrs.y - player.speed > 0) {
			...
			direction = 'left';
		}
	}

	...
	
	if(input.isDown('SPACE') &&
       Date.now() - lastFire > 500 && player.arrows > 0) {
        
		player.attrs.animation = 'attackLeft';
		if (direction == 'right') {
			player.attrs.animation = 'attackRight';
		}
		player.frameIndex(0);
		
    }

}

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

function animationAttack() {
	
	if (player.frameIndex() >= 2) {
		makeBullet('arrow');
	}
	
}

Здесь по наступлению 3 фрейма анимации мы создаем стрелу.

Код для создания стрелы ниже:

function makeBullet(type, x, y) {
	
	if (type == 'light') {
		...

		// add the shape to the layer
		layer.add(light);
		// add the layer to the stage
		stage.add(layer);
		// start sprite animation
		light.start();
		
	}

	if (type == 'arrow') {
		var x = player.attrs.x;
        	var y = player.attrs.y;
	   
		var arrow = new Konva.Image({
			x: player.attrs.x + 25,
			y: player.attrs.y + 20,
			image: playerImg,
			width: 30,
			height: 10
		});
		
		// вырезаем стрелу из изображения игрока
		arrow.crop({
		  x: 7,
		  y: 150,
		  width: 30,
		  height: 10
		});
		
		arrow.direction = 'left';
		player.attrs.animation = 'idleLeft';
		if (direction == 'right') {
			arrow.direction = 'right';
			player.attrs.animation = 'idleRight';
		
			arrow.crop({
			  x: 7,
			  y: 137,
			  width: 30,
			  height: 10
			});
			
		}
		
		player.arrows--;		
		player.frameIndex(0);
		
		arrows.push(arrow);

		 // add the shape to the layer
		layer.add(arrow);
		// add the layer to the stage
		stage.add(layer);

        	lastFire = Date.now();
	}
	
}

В начале мы внесли код добавления молнии в условие if (type == ‘light’). Далее дописали добавление стрелы. Механизм такой же, как и для молнии. Только, чтобы получить статическое изображение стрелы, мы обрезали изображение игрока и оставили только область со стрелой. Причем в зависимости от направления стрелы меняется область для вырезания.

По направлению игрока мы определяем направление полета стрелы. Далее уменьшаем количество стрел у игрока и добавляем стрелы в массив стрел.

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

 

Летящая стрела

Когда мы создали стрелу, ее необходимо анимировать.

function moveBullet() {
	...
	
	// Update all the arrows
	for(var i = 0; i < arrows.length; i++) {
        var arrow = arrows[i];

        switch(arrow.direction) {
		case 'right': arrow.setX(arrow.attrs.x + arrowSpeed); 
			break;
		default:
			arrow.setX(arrow.attrs.x - arrowSpeed);
        }
		
        // удаляем стрелы за экраном
        if (arrow.attrs.x < 0 || arrow.attrs.x > canvasWidth) {
            arrows.splice(i, 1);
		    arrow.setX(-1000);
		    i--;
        }
    }


}

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

Если стрелы вышла за пределы экрана, то мы ее удаляем из массива стрел и забываем про нее.

Вот, что у нас получилось в итоге:

canvas-5-1

Как вы заметили выше, я убрал зеленый фон у молний 🙂 Так гораздо лучше 🙂

lights

 

На сегодня на этом остановимся. И в следующий раз мы займемся попаданием стрел во врага.

Подписывайтесь на рассылку 😉 Дальше интересней!

Если вопросы/пожелания? Пишите в комментарии.

Всем спасибо за внимание.

 

 

Автор статьи: Alex. Категория: JavaScript
Дата публикации: 06.09.2015