дизайн

раскрутка

web-прог.

развлечения

статейки

софт

игры

на главную

гостевая

заказать сайт

сочинения

мои друзья

Hosted by uCoz


1. Что такое HTML.

2. Основа HTML.

3. Таблици и формы.

4. Фреймы.

5. Java.

6. JavaScript.—>>


Рейтинг@Mail.ru

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

JavaScript

Дарова, перец! Ну как, черпаешь инфу из нашего Х? То-то же. Ну, предположим, изваял ты себе крутую пагу с клевым дизигном, сидишь и думаешь: чего б такого туда еще запихнуть-то?.. Чтоб оно и процесс загрузки паги не тормозило, и прикольно было. Я вот решил тебе мазу подкинуть: а почему бы тебе не написать гаму на Яве? Простую, конечно, но настоящую? Что, интересно? Тогда мотай на ус.
Давай изваяем следующую фишку: в игровом поле будет летать и отражаться от стенок импровизированный "мячик", а от нижней границы его надо отбить, перемещая ракетку с помощью мыши или клавиатуры. И чтобы жизнь малиной не казалась, после каждых пяти "возвратов" скорость мяча будет возрастать. По-русски это, по-моему, называлось "Арканоид" и было на писюках лет десять назад. Поверь мне, пельмень, это было супер-круто и не растеряло своей крутизны даже сейчас. Посмотрим теперь, как это работает на JavaScript.

Ява наносит ответный удар

В начале определимся со средством вывода на экран. Ясно, что с помощью кучи разных переменных можно описать процесс любой, на фиг, сложности. Но как увидеть результат всего этого ведь JavaScript-то, козлина эдакая, не располагает средствами графического вывода на экран? Обойти этот подводный камень можно посредством использования формы и текстового поля для ввода (под этим громоздким названием я имею в виду тэг <TEXTAREA>). Самое важное при этом то, что текстовое поле (получая значение как показано ниже) само форматит полученную строку. Зырь, короче, на следующий пример:

Пример1: Использование <TEXTAREA> для вывода:
<HTML>
<HEAD>
<title>Пример1</title>
</HEAD>
<BODY>
<FORM name =TestForm1>
<TEXTAREA cols = 15 name = TestArea1 rows = 10>
</TEXTAREA>
</FORM>
</BODY>
<SCRIPT LANGUAGE=JavaScript>
<!-var string ="Это длинная строка. При выводе она будет автоматически перенесена";
// Объявляем тестовую переменную
TestForm1.TestArea1.value=string;
// Выводим в поле TestArea1 переменную string
//->
</SCRIPT>
</html>

Объявляя в этом примере форму и текстовое поле, мы с тобой, доктор Перец, задаем параметр name (для FORM это TestForm1, для TEXTAREA - TestArea1). Посредством этого имени мы затем обращаемся к самому элементу TestForm1.TestArea1.value=string. Заметь, что поле для ввода само выполняет перенос. То есть, если мы в поле размером 30х20 запишем строку размером в 600 символов, то поле само разобьет ее на 20 строк по 30 символов в каждой. Таким образом, вывод нашей программы сводится к формированию одной длинной строки игрового поля, которая будет затем записана в TEXTAREA.
Теперь нам осталось только создать тот механизм, который позволит изменять данную строку так, чтобы все выглядело как настоящая игра. Что ж, приступим. Вначале создай 13 переменных (конечно, уже внутри тэга <SCRIPT language = JavaScript>), которые и будут отвечать за все внутренности игры:

Шаг 1: Инициализация переменных:
var fieldx= 1; // Х-координата игрового поля
var fieldy= 1; // Y-координата игрового поля
var objectx=2; // Х-координата мячика
var objectdx= 1; // Смещение мячика по оси Х
var objecty=2; // Y-координата мячика
var objectdy= 1; // Смещение мячика по оси Y
var racketpos=7; // Положение ракетки
var errorflag=0; // Если 0, то мяч отбит. Если единица, то мяч вовремя не отбит.
var score=0; // Набранные очки
var deltascore=1; // Количество отскоков
var waitdelay=200; // Задержка в миллисекундах между движениями мячика (скорость игры)
var onflag=0; // Если 0, то игра не начата. Единица, если уже идет.
var printscreen; // Главная переменная вывода

Теперь давай напишем вспомогательную функцию newgame, которая будет вызываться при нажатии кнопки "Start Game". Ее основная работа - проверка, не начата ли новая игра (т.е. удостовериться в том, что onflag равен 0), и в инициализации переменных для новой игры:

Шаг 2: Функция newgame:
function newgame(){ // Объявляем функцию newgame без аргументов
if(onflag==0){ // Т.е. если игра не начата, то..
errorflag=0; // Сбрасываем в значение по умолчанию
score=0; // Очевидно, что очков пока нет
objectx=objecty=2; // Задаем начальные координаты для мяча
fieldx=fieldy=1; // Задаем начальные координаты для поля
waitdelay=200; // Присваиваем значение по умолчанию
deltascore=0; // Нет игры - нет и отскоков
scoreboard.value="Score: "+score; //Записываем ноль в табло
main(); // Вызываем основную функцию
} //Конец блока if
} // Конец тела функции newgame

Теперь самое время определить функцию main. Это основная функция всей программы. Она проверяет, был ли правильно отбит мячик (т е значение errorflag), и если все в порядке, вызывает функции definefield (она наполняет главную переменную printscreen и выводит ее в текстовое поле) и definemovement (результатом работы которой является обсчет движения объектов - мячика и ракетки). Однако главное в main - рекурсивный вызов самой функции main через некоторый таймаут. Таким образом, весь процесс замыкается, и вся игра продолжается. До момента ошибки игрока. Вот, короче, сама функция main.

Шаг 3: Функция main:
function main(){ // Объявляем функцию main без аргументов
if (errorflag!=1){ //Если ошибки нет, т.е. если мяч успешно отбит...
definefield(); // Вызываем функцию, отвечающую за прорисовку поля
definemovement(); // Вызываем функцию, отвечающую за движение объектов
onflag= 1; // Обозначаем, что игра уже идет
setTimeout("main()",waitdelay); // Вызываем main через waitdelay миллисекунд
} //Конец блока if
else { //Фак! Мяч не был отбит!
printscreen="Косая козлина! Руки из задницы растут!!!!!!"; // Формируем строку сообщения
battleForm.battleTA.value=printscreen; // Выводим сообщение
onflag=0; //Устанавливаем в состояние "игры нет"
} // Конец блока else
} // Конец тела функции main

Перед описанием функций, выполняющих основную работу (definemovement и definefield), давай напишем еще пару вспомогательных для определения браузера и обработки клавиатуры:

Шаг 4: Вспомогательные функции:
function testbrowser(){ // Объявляем функцию testbrowser без аргументов
if (window.navigator.userAgent.indexOf("MSIE")== -1) // Если в объекте информации о браузере userAgent нет строки MSIE, то это - не Internet Explorer!
alert ("Please use IE for this page!"); // Используем метод alert для предупреждения
} //Конец тела функции testbrowser

Реально эта функция запрашивает строку userAgent, возвращаемую браузером, и, если значение "MSIE* не найдено, выдается предупреждающее сообщение. Вызывается при загрузке страницы в теге <BODY onload = testbrowser()>
Теперь разберемся с клавиатурой - ведь нужно, чтобы можно было управлять ракеткой с помощью стрелок влево-вправо (в следующем номере Х расскажу, как подключить к игре джойстик с Форс-Фидбэком). :)

function keyboard(){ // Объявляем функцию keyboard без аргументов
if (window.event.keyCode==37 && racketpos>1) racketpos-; // Если нажата кнопка влево, и ракетка не у левого края, двигаем ее влево
if (window.event.keyCode==39 && racketpos<15) racketpos++; // Аналогично: нажата кнопка вправо, и ракетка не у самого края, двигаем ее вправо
} // Конец тела функции keyboard

Здесь мы запрашиваем код события (т.е. нажатой кнопки) в формате Unicode. В этом формате 37 соответствует "стрелке влево", а 39 -"стрелке вправо". Логическое И (&&) позволяет сдвигать ракетку (т.е. увеличивать или уменьшать на единицу ее координату), только если она не находится на краю поля. Так как ракетка занимает две позиции на поле (==), всего возможно только 15 ее положений (ширина поля равна 30).
Функция keyboard будет вызываться при каждом нажатии клавиши (<BODY onkeydown=keyboard()>).
Теперь, засучив рукава и приспустив штаны, приступим к основным функциям, первая из которых - definefield. Сначала давай прикинем, как она должна выглядеть в общих чертах. Результатом ее работы будет строка длинною в 600 символов (TEXTAREA я предлагаю задать 30х20), которая затем будет записана в наше основное текстовое поле. Поскольку последняя строка, содержащая "ракетку", не вполне обычна, логичным решением будет разбить функцию на два блока: первый отвечает за наполнение первых 570 значений (19 строк), а второй - только за последнюю строку. Таким образом, для первых 19 строк если значения переменных "мячика" и поля по Х и Y совпадают, то пишем "о" (это наш мячик), иначе - "." (точку, т.е. ничего нет) Для последней строки если совпали координата Х строки и переменная положения ракетки racketpos, то пишем "==" (ракетку), иначе - ".." (две точки - наш стандартный наполнитель поля). В конце функции необходимо осуществить вывод нашей переменной printscreen.
Вот как все это реализуется на практике:

Шаг 5: Функция definefield:
function definefield(){ // Объявляем саму функцию и в который раз без аргументов
printscreen=""; // Обнуляем переменную, отвечающую за прорисовку поля
fieldx=fieldy=1; // Начинаем поиск мячика с левого верхнего угла поля
//Блок1:
while (fieldy<20){ //Для каждой строки по 19-ю включительно:
for (fieldx=1; fieldx<31; fieldx++){ // Для каждого элемента строки сравниваем:
if (objectx==fieldx && objecty==fieldy) printscreen+="o";// Если совпали координаты, то на этом месте - мячик
else printscreen+="."; // Иначе - пусто
} // Конец цикла for - вся строка просмотрена в поисках мячика
fieldy++; // Берем следующую строку и все сначала, пока не исчерпаем все 19 cтрок
} //Конец цикла while - все 19 строк пройдены
// Блок 2 для последней 20-ой строки:
for (fieldx=1; fieldx<16; fieldx++){ //Для каждого второго элемента (Всего 15 позиций!)
if (racketpos==fieldx) printscreen+="=="; // Если совпали, значит рисуем ракетку
else printscreen+=".."; //Иначе-пусто
} // Конец цикла for - где-то нарисовали ракетку
battleForm.battleTA.value=printscreen; //Рисуем наше поле в TEXTAREA
} // Конец функции definefield

Теперь осталось рассмотреть последнюю функцию definemovement, которая отвечает за избиение состояния всех объектов, т.е. их движение. Каждый раз, когда мы обращаемся к той функции, мячик, ясный пень, должен двигаться. Иными словами, координата мячика изменяется по Х и Y. Если, например, он движется вниз и вправо, то обе координаты возрастают. Если вверх и влево - убывают. Ясно, что возможны и два комбинированных случая (вправо вверх и влево вниз).
Таким образом, чтобы задать передвижение мяча, необходимо изменить на противоположное направление его приращения в четырех пиковых границах - вблизи стен нашей коробки. С тремя стенками все просто - только и дела что проверить координату мяча и изменить знак у objectdx или objectdy. Четвертый случай (когда необходимо отслеживать и позицию ракетки) более сложен:
Ракетка занимает два элемента поля и, следовательно, имеет 15 возможных положений на нем. Будем считать, что ракетка может отражать мяч своими "углами". Допустим, что положение ракетки сейчас равно 7. Тогда занимаемые ею поля, как ты шаришь, 13 и 14. Теперь займемся отражением "углами". Если мяч падает на ракетку слева, то он должен отражаться и в колонке 12 (это и будет похоже на то, что ракетка отразила мяч своим левым углом). Соответственно, если он падает справа, то правый угол будет в колонке 15. Следовательно, условие отражения мяча может быть задано нами в виде: если мяч движется вправо и Х-координата мяча равна позиции ракетки, умноженной на два, или позиции ракетки, умноженной на два - 1, или позиции ракетки, умноженной на два - 2, то мяч надо отразить. Используя логическое ИЛИ ( оператор || ) получаем: if (objectdx > 0 && (racketpos*2-2 == objectx || racketpos*2 - 1 == objectx || racketpos*2 == objectx )) objectdy = -objectdy. Теперь направление изменено и мяч отразился. Вариант для движения мяча влево и остальной необходимый код приведен уже в самой функции:

Шаг 6: Функция definemovement:
function definemovement(){ // Объявляем функцию без аргументов
// Сразу самый сложный случай: мяч на предпоследней горизонтали
if(objecty>18){ //Внимание!
if (objectdx>0 && (racketpos*2-2==objectx || racketpos*2==objectx || racketpos*2-1==objectx))
// Если мяч движется вправо и находится в зоне ракетки
{ objectdy=-objectdy; // Мяч отражается
score++; // Очки возрастают
}
if (objectdx<0 && (racketpos*2-1==objectx || racketpos*2==objectx ||racketpos*2+1==objectx))
// Аналогично: если мяч движется влево и находится в зоне ракетки
{ objectdy=-objectdy; // Мяч отражается
score++;// Очки возрастают
}
deltascore++; // Количество отскоков увеличилось на единицу
if (deltascore==5){ // Если мяч отскочил уже 5 раз, ускорим игру!
deltascore=0; // Сбросили счетчик отскоков на ноль
waitdelay=waitdelay*0.75; //Уменьшили задержку, т.е. ускорили на 25%
}
if (errorflag!=1 )scoreboard.value="Score: "+score; //Вывели очки в табло, если все ОК
} // Конец блока if, проверявшего, находится ли мяч на последней горизонтали
// Теперь три легких случая - мяч у трех стенок:
if (objecty<2) objectdy=-objectdy; // Мяч у верхней стенки, меняем направление
if(objectx>29)objectdx=-objectdx; // Мяч у правой стенки, меняем направление
if (objectx<2) objectdx=-objectdx; // Мяч у левой стенки, меняем направление
// Осуществляем движение:
objectx+=objectdx; //Двигаем объект по Х
objecty+=objectdy; // Двигаем объект по Y
if (objecty>19) errorflag=1; // Ошибка! Мяч не был вовремя отражен!
} // Конец тела функции

Вот, собственно, и все! Теперь тебе остается cо спокойным сердцем закрыть тэг <SCRIPT> и создать внутри <BODY> с помощью стандартных тэгов кнопочку Start Game (onclick= newgame()), форму (name=battleForm) и внутри ее TEXTAREA размером 30 на 20 (name=battleTA cols=30 rows=20). He забудь про табло <INPUT name=scoreboard>, и твоя первая игра полностью готова!

дизайн

раскрутка

web-прог.

развлечения

статейки

софт

игры

на главную

гостевая

заказать сайт

сочинения

мои друзья