Создание игры на 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

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.