Разработка игры на Canvas, часть 1. Начало

Html5_canvas_logoВсем привет!

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

Сегодня я запускаю цикл статей, где попытаюсь рассказать, как я буду делать новую игру.

Начнем с простого, определим, что будем делать. Моя идея следующая: сделать 2D игру на canvas.

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

Ваш приз: очки и, собственно, жизнь.

 

Что нам понадобится?

Для облегчения работы я поискал фреймворки для работы с canvas. В результате поисков я остановился на Konva.

Так же я подумал, что лучше прояснить, что нужно делать, нам поможет ментальная карта:

mindmap

 

Что ж, приступим!

Начнем мы с самого начала, естественно.

<!DOCTYPE html>
<html>
<head>
    <script src="konva.min.js"></script>
    <meta charset="utf-8">
    <title>Konva Game</title>
</head>
<body>
    <div id="container"></div>
</body>
</html>

Что мы сделали? Добавили наше будущее поле игры div#container и подключили скрипт фреймворка.

Добавим немного стилей в <head>.

body {
	margin: 0;
	padding: 0;
	overflow: hidden;
}

#container {
	margin: 20px auto;
	width: 600px;
	height: 500px;
	border: 2px solid black;
	background: url('bg.png') 0 0 repeat;
}

 

На выходе мы получим наше игровое поле, которое будет раскрашено травкой 🙂
field

 

JavaScript

Попробуем создать нашего игрока и разместить его на нашем игровом поле, сделать перемещение игрока по полю.

Для начала создадим наше поле.

var canvasWidth = 600;//window.innerWidth;
var canvasHeight = 500;//window.innerHeight;

var stage = new Konva.Stage({
	container: 'container',
	width: canvasWidth,
	height: canvasHeight
});

var layer = new Konva.Layer();

Поле сделано. Займемся игроком.

Так как игрок это не статическая картинка, а динамическое изображение, то для игрока нам понадобится спрайт с анимацией поведения. Возьмем пока что тот спрайт, который я нашел на просторах интернета. Этот странный зеленый цвет пока нам только на руку. Потом, когда уже будет не нужен, мы его аккуратненько уберем с помощью Photoshop.

wizard-1

 

Создание и размещение игрока

/* анимация каждого кадра игрока прописана в координатах
по принципу x, y, width, height
*/
var animationsPlayer = {
  idleRight: [ // игрок стоит и смотрит вправо
	2, 10, 48, 49,
	52, 10, 48, 49,
	102, 10, 48, 49,
	152, 10, 48, 49,
	202, 10, 48, 49,
	252, 10, 48, 49,
	302, 10, 48, 49,
	352, 10, 48, 49
  ]
};

var playerImg = new Image();
playerImg.src = 'wizard.png';

// задаем параметры изображения спрайта игрока
var player = new Konva.Sprite({
	x: 200, // положение
	y: 150,
	image: playerImg,
	animation: 'idleRight',
	animations: animationsPlayer, // изображение со всеми анимациями
	frameRate: 7, // скорость смены кадров
	frameIndex: 0 // начальный кадр
});

// добавляем спрайт игрока на игровой слой
layer.add(player);

// добавляем слой на стейдж
stage.add(layer);

// запускаем анимацию игрока
player.start();

Вот и все. У нас теперь есть игрок, который отображается на игровом поле и просто стоит, покачивается 🙂

 

Движение

Все-таки просто стоять и смотреть на игрока неинтересно. Добавим динамики — передвижение при нажатии на стрелочки.

// бесконечный цикл игры
var gameLoop = new Konva.Animation(function(frame) {
	handleInput();
}, layer);
gameLoop.start();

// отлавливание событий нажатия на "игровые" клавиши
function handleInput() {
    ...
}

 

Нам понадобится вспомогательная переменная direction для задания направления игрока. Добавим ее в начало, где задавались размеры для поля.

var canvasWidth = 600;//window.innerWidth;
var canvasHeight = 500;//window.innerHeight;
var direction = '';

 

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

var animationsPlayer = {
  walkRight: [
	2, 131, 48, 49,
	58, 131, 48, 49,
	114, 131, 48, 49,
	170, 131, 48, 49,
	226, 131, 48, 49,
	282, 131, 48, 49,
	338, 131, 48, 49,
	394, 131, 48, 49,
	450, 131, 48, 49,
	506, 131, 48, 49,
	562, 131, 48, 49,
	618, 131, 48, 49,
	674, 131, 48, 49,
	730, 131, 48, 49,
	786, 131, 48, 49,
	842, 131, 48, 49,
	898, 131, 48, 49,
	954, 131, 48, 49
  ],
  walkLeft: [
	2, 191, 48, 49,
	58, 191, 48, 49,
	114, 191, 48, 49,
	170, 191, 48, 49,
	226, 191, 48, 49,
	282, 191, 48, 49,
	338, 191, 48, 49,
	394, 191, 48, 49,
	450, 191, 48, 49,
	506, 191, 48, 49,
	562, 191, 48, 49,
	618, 191, 48, 49,
	674, 191, 48, 49,
	730, 191, 48, 49,
	786, 191, 48, 49,
	842, 191, 48, 49,
	898, 191, 48, 49,
	954, 191, 48, 49
  ],
  idleRight: [ // уже прописывали
	...
  ],
  idleLeft: [
	2, 72, 48, 49,
	52, 72, 48, 49,
	102, 72, 48, 49,
	152, 72, 48, 49,
	202, 72, 48, 49,
	252, 72, 48, 49,
	302, 72, 48, 49,
	352, 72, 48, 49
  ]

};

 

Теперь займемся непосредственно отлавливанием нажатия стрелочек для передвижения игрока. Для определения нажатия на клавиши я взял готовый скрипт input.js, который подключил в блок <head>

<head>
    ...
    <script src="input.js"></script>
    ...
</head>

 

В JavaScript блок я дописал следующее:

// отлавливание событий нажатия на "игровые" клавиши
function handleInput() {

	player.attrs.animation = 'idleRight'; // движение по умолчанию
	if (direction == 'left' || direction == 'down') {
		player.attrs.animation = 'idleLeft';
	}

	if(input.isDown('DOWN') || input.isDown('s')) {
		player.attrs.animation = 'walkRight';
		player.setY(player.attrs.y + 1);
		direction = 'down';
	}

	if(input.isDown('UP') || input.isDown('w')) {
		player.attrs.animation = 'walkLeft';
		player.setY(player.attrs.y - 1);
		direction = 'up';
	}

	if(input.isDown('LEFT') || input.isDown('a')) {
		player.attrs.animation = 'walkLeft';
		player.setX(player.attrs.x - 1);
		direction = 'left';
	}

	if(input.isDown('RIGHT') || input.isDown('d')) {
		player.attrs.animation = 'walkRight';
		player.setX(player.attrs.x + 1);
		direction = 'right';
	}

}

 

Отлично. Теперь наш игрок реагирует на нажатия клавиш и перемещается по полю. Но что это? Игрок может выйти за границу! Недопустимо! Разберемся с этим. В функции handleInput() добавим ограничения движений

if(input.isDown('DOWN') || input.isDown('s')) {
	if (player.attrs.y + 1 < canvasHeight - 48) {
		...
	}
}

if(input.isDown('UP') || input.isDown('w')) {
	if (player.attrs.y - 1 > 0) {
		...
	}
}

if(input.isDown('LEFT') || input.isDown('a')) {
	if (player.attrs.x - 1 > 0) {
		...
	}
}

if(input.isDown('RIGHT') || input.isDown('d')) {
	if (player.attrs.x + 1 < canvasWidth - 48) {
		...
	}
}

Готово! Теперь наш игрок двигается только в рамках границы поля.

 

Думаю, что на сегодня хватит. Статья получилась довольно большой. Остальное в следующей части!

Остались вопросы? Пишите в комментариях. Если я где-то кардинально ошибся — так же напишите мне, пожалуйста. Будем разбираться 🙂

 

Спасибо за внимание! Подписывайтесь на рассылку 😉

 

 

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