Создание игры на Javascript Canvas
Пошаговая разработка процесса создания игры Javascript Canvas при помощи MooTools и LibCanvas. Объяснение причин и логики добавления нового и рефакторинга существующего кода. Набор классов, с помощью которых возможна реализация различных эффектов.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 16.09.2010 |
Размер файла | 146,8 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
Федеральное государственное образовательное учреждение высшего профессионального образования «Чувашский государственный университет им. И.Н. Ульянова»
Дисциплина «Веб-технологии»
Курсовая работа по теме:
Создание игры на Javascript Canvas
Чебоксары - 2009 г.
Тема курсовой посвящена игре на нескольких человек за одним компьютером на Javascript Canvas. Я пошагово разобрала процесс создания такой игры при помощи MooTools и LibCanvas, останавливаясь на каждом мелком действии, объясняя причины и логику добавления нового и рефакторинга существующего кода.
MooTools -- это свободный JavaScript фреймворк для разработки кроссбраузерных веб-приложений и веб-сервисов.
MooTools является модульным, объектно-ориентированным фреймворком, созданным для помощи разработчикам JavaScript.
MooTools совместим и протестирован с браузерами: Safari 2+, Internet Explorer 6+, Firefox 2+ (и другими, основанными на движке Gecko), Opera 9+.
Фреймворк MooTools используется в CMS Typolight, Joomla 1.5, ZoneMinder, MODx.
Объектно-ориентированное программирование.
MooTools содержит мощную коллекцию классов и продвинутую систему наследования, которая позволяет вторичное использование кода, а также его расширение. Например:
var Animal = new Class({
initialize: function(name){
this.name = name;
}
});
var Cat = new Class({
Extends: Animal,
talk: function(){
return 'Meow!';
}
});
var Dog = new Class({
Extends: Animal,
talk: function(){
return 'Arf! Arf';
}
});
var Animals = {
a: new Cat('Missy'),
b: new Cat('Mr. Bojangles'),
c: new Dog('Lassie')
};
for(var animal in Animals) alert(animal.name + ': ' + animal.talk());
// Вывод функции alerts
//
// Missy: Meow!
// Mr. Bojangles: Meow!
// Lassie: Arf! Arf!
Также предоставляет собственный набор классов, с помощью которых возможна, например, реализация различных эффектов. К ним относятся изменения размеров окна браузера, показ и гашение объектов, эффекты движения и Ajax.
Правила.
Управляем игроком (Player), который должен поймать наживку (Bait) - и при этом увернуться от появляющихся "хищников" (Barrier). Цель игры - поймать максимальное количество наживок, не соприкоснувшись с хищниками. При соприкосновении с одним из хищников все они пропадают, а очки - обнуляются, что фактически, равносильно началу игры с нуля.
HTML файл
Создаем начальный файл, на котором будет наше канвас-приложение. Я воспользовалась файлами, размещенными на сайте libcanvas, но это - не обязательно. JavaScript-файлы добавлялись в процессе создания игры, но я не хочу больше возвращаться к этому файлу, потому объявлю их сразу. ./index.html
<!DOCTYPE html>
<html style="color:white;background:#111;">
<head>
<meta charset="utf-8" />
<title>Catch</title>
</head>
<body>
<canvas width="960" height="600" style="background: black"></canvas>
<script type="text/javascript" src="http://libcanvas.com/files/mootools.js"></script>
<script type="text/javascript" src="http://libcanvas.com/files/libcanvas"></script>
<script type="text/javascript" src="./js/GameObject.js"></script>
<script type="text/javascript" src="./js/Bait.js"></script>
<script type="text/javascript" src="./js/Barrier.js"></script>
<script type="text/javascript" src="./js/Player.js"></script>
<script type="text/javascript" src="./js/start.js"></script>
</body>
</html>
Создаем проект
Для начала создадим сам проект. Нам нужно сделать это только тогда, когда документ будет готов - воспользуемся предоставленным mootools событием "domready" Также создадим объект LibCanvas.Canvas2D, который поможет нам с анимацией. ./js/start.js
window.addEvent('domready', function () {
// с помощью Мутулз выберем первый елемент канвас на странице
var elem = $$('canvas')[0];
// На его основе создадим елемент LibCanvas
var libcanvas = new LibCanvas.Canvas2D(elem);
// Перерисовка будет осуществлятся каждый кадр, несмотря на наличие или отсутствие изменений
libcanvas.autoUpdate = true;
// Будем стремится к 60 fps
libcanvas.fps = 60;
// Стартуем наше приложение
libcanvas.start();
});
Добавляем пользователя
Добавим новый объект - Player, который будет управлятся мышью - его координаты будут равны координатам курсора мыши. Этот объект будет выглядеть как кружочек определенного цвета и размера (указанные в свойстве) ./js/Player.js
var Player = new Class({
Extends : LibCanvas.Behaviors.Drawable,
radius : 15,
color : '#080',
initialize : function () {
// Элемент libcanvas присвоится после создания игрока
// и после вызова метода initialize, потому необходимо
// подождать это славное событие (по аналогии с domready)
this.bind('libcanvasSet', function (){
this.shape = new LibCanvas.Shapes.Circle({
// центр мышки - объект LibCanvas.Point, указан по ссылке как центр
// текущего круга, потому круг всегда будет следовать за указателем
center : this.libcanvas.mouse.point,
radius : this.radius
});
});
},
draw : function () {
if (this.libcanvas.mouse.inCanvas) {
this.libcanvas.ctx.fill(this.shape, this.color);
}
}
});
Добавим в ./js/start.js перед libcanvas.start();:
libcanvas.listenMouse();
var player = new Player().setZIndex(30);
libcanvas.addElement(player);
Можно заметить, что результат не совсем такой, как мы ожидали, потому-что после каждого из кадров холст не очищается автоматически. Необходимо добавить очищающий и заливающий черным препроцессор в ./js/start.js
libcanvas.addProcessor('pre',
new LibCanvas.Processors.Clearer('#000')
);
Добавляем наживку
./js/Bait.js
var Bait = new Class({
Extends : LibCanvas.Behaviors.Drawable,
radius : 15,
color : '#f0f',
initialize : function () {
this.bind('libcanvasSet', function (){
this.shape = new LibCanvas.Shapes.Circle({
center : this.createPosition(),
radius : this.radius
});
});
},
createPosition : function () {
return this.libcanvas.ctx
// получаем элемент LibCanvas.Shapes.Rectangle размерами равный нашему холсту
.getFullRectangle()
// Берем из него случайную точку
.getRandomPoint();
},
draw : function () {
this.libcanvas.ctx.fill(this.shape, this.color);
}
});
Добавим в ./js/start.js:
// Возьмем индекс поменьше, чтобы наживка рисовалась под игроком
var bait = new Bait().setZIndex(20);
libcanvas.addElement(bait);
Рефакторинг - создаем родительский класс
У нас очень похожие классы Bait и Player. Давайте создадим класс GameObject, от которого у нас они будут наследоваться. Для начала вынесем createPosition из конструктора класса Player: ./js/Player.js
var Player = new Class({
// ...
initialize : function () {
// ..
this.shape = new LibCanvas.Shapes.Circle({
center : this.createPosition()
// ...
},
createPosition : function () {
return this.libcanvas.mouse.point;
},
Теперь создадим класс GameObject. Так как в коде он у нас должен идти раньше остальных классов - в имя файла добавим нолик, который изменит порядок ./js/0.GameObject.js
var GameObject = new Class({
Extends : LibCanvas.Behaviors.Drawable,
initialize : function () {
this.bind('libcanvasSet', function (){
this.shape = new LibCanvas.Shapes.Circle({
center : this.createPosition(),
radius : this.radius
});
});
},
// Получение полного ректангла - вынесли в метод и кешируем. Оно нам еще понадобится
getFull : function () {
return (this.full = this.full || this.libcanvas.ctx.getFullRectangle());
},
// по-умолчанию берем случайную точку, и только если надо иначе - переопределяем метод
createPosition : function () {
return this.getFull().getRandomPoint();
},
draw : function () {
this.libcanvas.ctx.fill(this.shape, this.color);
}
});
После этого можно облегчить другие классы: ./js/Bait.js
var Bait = new Class({
Extends : GameObject,
radius : 15,
color : '#f0f'
});
./js/Player.js
var Player = new Class({
Extends : GameObject,
radius : 15,
color : '#080',
createPosition : function () {
return this.libcanvas.mouse.point;
},
draw : function () {
if (this.libcanvas.mouse.inCanvas) {
this.parent();
}
}
});
Дружим игрока с наживкой
У нас на экране все двигается, но реально никакой реакции на наши действия нету. Давайте начнем с того, что подружим наживку и игрока - при набегании на неё, наживка должна перемещаться в другое случайное место. Для этого создадим отдельный от рендеринга таймаут, который будет проверять соприкасание. Пишем в конец ./js/start.js:
(function(){
bait.isCatched(player);
}.periodical(30));
Теперь надо реализовать метод isCatched в ./js/Bait.js:
isCatched : function (player) {
if (player.shape.intersect(this.shape)) {
this.move();
return true;
}
return false;
},
move : function () {
// перемещаем в случайное место
this.shape.center = this.createPosition();
}
Почти отлично, но мы видим, что перемещение грубовато и раздражающе. Лучше было бы, если бы наживка плавно убегала. Для этого можно воспользоваться одним из интерфейсов ЛибКанвас. Достаточно добавить одну строчку и слегка поменять метод move: Теперь надо реализовать метод isCatched в ./js/Bait.js:
var Bait = new Class({
Extends : GameObject,
Implements : [LibCanvas.Behaviors.Moveable],
// ...
move : function () {
// быстро (800), но плавно перемещаем в случайное место
this.moveTo(this.createPosition(), 800);
}
});
Добавим хищников
./js/Barrier.js:
var Barrier = new Class({
Extends : GameObject,
full : null,
speed : null,
radius : 8,
color : '#0ff',
initialize : function () {
this.parent();
this.speed = new LibCanvas.Point(
$random(2,5), $random(2,5)
);
// Через раз летим влево, а не вправо
$random(0,1) && (this.speed.x *= -1);
// Через раз летим вверх, а не вниз
$random(0,1) && (this.speed.y *= -1);
},
move : function () {
this.shape.center.move(this.speed);
return this;
},
intersect : function (player) {
return (player.shape.intersect(this.shape));
}
});
Также чуть изменим ./js/start.js, чтобы при ловле наживки появлялись хищники:
bait.isCatched(player);
// меняем на
if (bait.isCatched(player)) {
player.createBarrier();
}
player.checkBarriers();
Реализуем добавление барьеров для игрока, ./js/Player.js и двигаем их все каждую проверку:
barriers : [],
createBarrier : function () {
var barrier = new Barrier().setZIndex(10);
this.barriers.push(barrier);
// Надо не забыть добавить его в наш объект libcanvas, чтобы хищник рендерился
this.libcanvas.addElement(barrier);
return barrier;
},
checkBarriers : function () {
for (var i = this.barriers.length; i--;) {
if (this.barriers[i].move().intersect(this)) {
this.die();
return true;
}
}
return false;
},
die : function () { },;
Хищники отбиваются от стен, наживка получает небольшое время "неуязвимости"
Слегка меняем метод move класса Barrier, в файле ./js/Barrier.js:
move : function () {
var center = this.shape.center.move(this.speed);
// если объект не влез по ширине - разворачиваем его по оси X
if (!center.x.between(0,this.full.width)) {
(this.speed.x *= -1);
}
// если объект не влез по высоте - разворачиваем его по оси Y
if (!center.y.between(0,this.full.height)) {
(this.speed.y *= -1);
}
return this;
}
Вносим изменения в класс Bait, в файле ./js/Bait.js:
invulnerable : false,
isCatched : function (player) {
if (!this.invulnerable && player.shape.intersect(this.shape)) {
this.move();
// Делаем неуязвимой на 500 мс.
this.makeInvulnerable(500);
return true;
}
return false;
},
makeInvulnerable : function (time) {
this.invulnerable = true;
(function () {
this.invulnerable = false;
}.bind(this).delay(time));
},
Реализуем смерть и подсчет очков
Т.к. очки - это сколько раз поймана наживка и она равная количеству хищников на экране - сделать подсчет очков очень легко: Чуть расширим метод draw в классе Player, файл./js/Player.js :
draw : function () {
// ...
this.libcanvas.ctx.text({
text : 'Score : ' + this.barriers.length,
to : [20, 10, 200, 40],
color : this.color
});
},
// Т.к. очки - это всего-лишь количество хищников - при смерти достаточно удалить всех хищников
die : function () {
for (var i = this.barriers.length; i--;) {
this.libcanvas.rmElement(this.barriers[i]);
}
this.barriers = [];
}
Пример работы игры:
Реализуем многопользовательскую игру за одним компьютером.
Движение с клавиатуры
Для начала - перенесем управление с мышки на клавиатуру. В ./js/start.js меняем libcanvas.listenMouse() на libcanvas.listenKeyboard() В нем же в таймаут добавляемplayer.checkMovement();. В ./js/Player.js удаляем переопределение createPosition, в методе draw удаляем проверку мыши и реализуем движение с помощью стрелочек:
speed : 8,
checkMovement : function () {
var pos = this.shape.center;
if (this.libcanvas.getKey('left')) pos.x -= this.speed;
if (this.libcanvas.getKey('right')) pos.x += this.speed;
if (this.libcanvas.getKey('up')) pos.y -= this.speed;
if (this.libcanvas.getKey('down')) pos.y += this.speed;
},
Неприятный нюанс - игрок заползает за экран и там может заблудиться. Ограничим его передвижение и немножко отрефакторим код, вынеся получение состояния клавиши в отдельный метод
isMoveTo : function (dir) {
return this.libcanvas.getKey(dir);
},
checkMovement : function () {
var pos = this.shape.center;
var full = this.getFull();
if (this.isMoveTo('left') && pos.x > 0 ) pos.x -= this.speed;
if (this.isMoveTo('right') && pos.x < full.width ) pos.x += this.speed;
if (this.isMoveTo('up') && pos.y > 0 ) pos.y -= this.speed;
if (this.isMoveTo('down') && pos.y < full.height) pos.y += this.speed;
},
Также слегка изменим метод isMoveTo - чтобы можно было с легкостью изменять клавиши для управления игроком:
control : {
up : 'up',
down : 'down',
left : 'left',
right : 'right'
},
isMoveTo : function (dir) {
return this.libcanvas.getKey(this.control[dir]);
},
Вводим второго игрока
Изменяем файл ./js/start.js:
var player = new Player().setZIndex(30);
libcanvas.addElement(player);
// =>
var players = [];
(2).times(function (i) {
var player = new Player().setZIndex(30 + i);
libcanvas.addElement(player);
players.push(player);
});
// Меняем стиль и управление второго игрока
players[1].color = '#ff0';
players[1].control = {
up : 'w',
down : 's',
left : 'a',
right : 'd'
};
Содержимое таймера оборачиваем в players.each(function (player) { /* * */ });
Осталось сделать небольшие поправки: 1. Сдвинуть счет второго игрока нижу счета первого игрока 2. Раскрасить хищников разных игроков в разные цвета 3. Ради статистики ввести "Рекорд" - какой максимальный счет каким игроком был достигнут Вносим соответствующие изменения в ./js/Player.js:
var Player = new Class({
// ...
// Красим хищников в соответствующий игроку цвет:
createBarrier : function () {
// ...
barrier.color = this.barrierColor || this.color;
// ...
},
// Реализуем подсчет максимального рекорда
maxScore : 0,
die : function () {
this.maxScore = Math.max(this.maxScore, this.barriers.length);
// ...
},
index : 0,
draw : function () {
this.parent();
this.libcanvas.ctx.text({
// Выводим максимальный рекорд:
text : 'Score : ' + this.barriers.length + ' (' + this.maxScore + ')',
// Смещаем очки игрока на 20 пикселей вниз зависимо от его индекса:
to : [20, 10 + 20*this.index, 200, 40],
color : this.color
});
}
});
Вносим коррективы в ./js/start.js:
(2).times(function (i) {
var player = new Player().setZIndex(30 + i);
player.index = i;
// ...
});
players[0].color = '#09f';
players[0].barrierColor = '#069';
// Меняем стиль и управление второго игрока
players[1].color = '#ff0';
players[1].barrierColor = '#960';
players[1].control = {
up : 'w',
down : 's',
left : 'a',
right : 'd'
};
Пример работы с двумя игроками.
При желании очень просто добавить третьего и четвертого игрока:
players[2].color = '#f30';
players[2].barrierColor = '#900';
players[2].control = {
up : 'i',
down : 'k',
left : 'j',
right : 'l'
};
// players[0] uses numpad
// players[3] uses home end delete & pagedown
players[3].color = '#3f0';
players[3].barrierColor = '#090';
players[3].control = {
up : '$',
down : '#',
left : 'delete',
right : '"'
};
Пример работы для четырех игроков.
Список использованной литературы
1. JavaScript: Подробное руководство (Definitive Guide), Давид Финнерман. Спб, 2007г.
2. JavaScript. Библия пользователя, Фленов Иван, Спб, 2005г.
3. Javascript и DHTML, сборник рецептов, Д.Гудман, Спб, 2004г.
Подобные документы
Отображение графики с помощью Canvas, представляющей собой область компонента, на которой можно рисовать или отображать готовые изображения. Операторы, применяемые в программе создания аналоговых часов, ее интерфейс и алгоритм решения на языке Delphi.
курсовая работа [2,3 M], добавлен 20.01.2016Создание интерактивных веб-страниц. Что такое JavaScript. Полная интеграция с браузером. Мощные средства для создания сетевых соединений. Подключение и выполнение JavaScript. Загрузка данных без перезагрузки страницы. Объекты для работы с мультимедиа.
лекция [16,2 K], добавлен 05.02.2012Изучение создания скриптов на JavaScript. Разработка программы выдачи простого предупреждения по событию Click при выборе гипертекстовой ссылки. Применение контейнера SCRIPT для размещение JavaScript-кода. Получение типа программы просмотра HTML-страниц.
контрольная работа [21,1 K], добавлен 15.02.2010Характеристика Javascript функции с параметрами (аргументами). Возврат значений, глобальные и локальные переменные в функции. Все способы создания пользовательских функций в Javascript. Область видимости переменных. Рекурсивная функция Javascript.
лабораторная работа [75,8 K], добавлен 19.09.2019Назначение и применение JavaScript, общие сведения. Понятие объектной модели применительно к JavaScript. Размещение кода на HTML-странице. URL-схема. Вставка (контейнер SCRIPT, принудительный вызов интерпретатора). Программирование свойств окна браузера.
лекция [517,1 K], добавлен 09.03.2009Размещение кода скрипта JavaScript непосредственно на HTML-странице. Сценарий JavaScript и список основных событий. Полезные конструкции на PHP. Некоторые функции для работы с массивами. Фрагмент кода JavaScript из "Эконометрической модели России".
презентация [331,2 K], добавлен 25.09.2013Сравнительная характеристика, возможности и функции языков программирования JavaScript и PHP. Основные области их использования. Разработка интерактивного Web-приложения с применением JavaScript на примере теста по теме "Программирование на языке Delphi".
курсовая работа [19,3 K], добавлен 01.07.2014Область применения компьютерной графики. Работа с графикой в Delphi, обращение к свойству Canvas-компонентов. Холст для рисования Canvas - перевернутая система координат. Свойства и методы приложения. Простое приложение, иллюстрирующее работу с графикой.
курсовая работа [968,7 K], добавлен 23.03.2015Примеры динамического построения html-страницы при помощи JavaScript. Использование цикла For, когда заранее известно, сколько раз должны повториться циклические действия. Выполнение циклических операторов входа и выхода, прерывание текущей итерации.
лабораторная работа [52,4 K], добавлен 19.09.2019Исследование возможностей и областей использования языка программирования JavaScript. Сравнительный анализ языков программирования JavaScript и PHP. Разработка интерактивного Web-приложения на примере теста по теме "Программирование на языке Delphi".
практическая работа [26,0 K], добавлен 04.02.2015