Java/Игра змейка

Материал из Викиучебника — открытых книг для открытого мира

Если не терпится написать что-нибудь интересное, например игру - вы находитесь на правильной странице! Данная игра не является законченным продуктом, в ней почти нет коментариев, зато она работает и в ней есть несколько ключевых элементов с помощью которых можно написать свою собственную игру. В общем, берем исходники и доделываем/переделываем игру сами!

Дизайн программы[править]

На графическом поле со стенами ползает змейка, которой игрок управляет стрелками, собирая апельсины.

Функциональность[править]

//**//Для начала в объекта actions установим голову змейки в центр поля. Потом создаем 2 массива в которых будут храниться координаты //**//сегментов змейки. 

//**// Действия которые выполняются при загрузке объекта
onClipEvent (load) {
//**//Переменная в которой хранится количество сегментов тела змейки
body_count = 0;
//**//Переменная необходимая для паузы в движении змейки
move_timer=getTimer();
//**//Переменная необходимая для паузы при создании бонусов
bonus_timer=getTimer();
//**//Переменная которая указывает создан ли бонус или нет.
bonus_exist = 0;
//**//Устанавливаем голову змейки в центр игрового поля
_root.snake_head._x = 290;
_root.snake_head._y = 250;
//**//Создаем массивы в которых будем хранить координаты тела змейки
var cell_x:Array = new Array();
var cell_y:Array = new Array(); 

//**// Затем методом дубликации создадим начальный хвост для змейки, и вписываем координаты каждого сегмента в массивы.

//**//Создание хвоста змейки циклом от 1 до 7
for (i=1; i<7; i++) {
duplicateMovieClip(_root.snake_body, 'snake_body'+i, i);
//**//Расстановка сегментов хвоста на поле, снизу головы змейки
_root['snake_body'+i]._x = _root.snake_head._x;
_root['snake_body'+i]._y = _root.snake_head._y+(i*20);
//**//Вписываем в массив новые переменные
cell_x[i+1] = _root['snake_body'+i]._x;
cell_y[i+1] = _root['snake_body'+i]._y;
//**//Записываем в переменной количество сегментов тела
body_count++;
}}

//**//Затем добавим код, который будет управлять движением змейки, он очень прост, при нажатии на кнопку управления - голова змейки //**//меняет свое направление.

//**//Блок управления движением змейки при нажатии кнопки - змейка меняет направление
on (keyPress "<Left>") {
_root.snake_head._rotation = -90;
}
on (keyPress "<Right>") {
_root.snake_head._rotation = 90;
}
on (keyPress "<Up>") {
_root.snake_head._rotation = 0;
}
on (keyPress "<Down>") {
_root.snake_head._rotation = 180;
}

//**//Для движения змейки, появления бонусов, проверки столкновений, испольуем событие которое будет проверяться каждый кадр //**//мувика(onClipEvent (enterFrame)). Напишем код который будет дублировать мувик бонуса и размещать его в случайном месте на сцене, //**//перед дубликацией мувика проверяется тайме и переменная которая указывает создан бонус или нет, это нужно для того чтобы на //**//сцене размещался только 1 бонус.

onClipEvent (enterFrame) {
//**//Создание бонусов.
//**//Проверяем, если таймер меньше и переменная указывает что бонуса не создано - создаем бонус.
if (getTimer()-bonus_timer>500 && !bonus_exist) {
//**//Дублируем клип, присваиваем ему имя
duplicateMovieClip(_root.bonus, 'bonus_real', 1000);
//**//Устанавливаем случайные координаты для дублированного бонуса
_root.bonus_real._x = random(30)*20+10;
_root.bonus_real._y = random(25)*20+10;
//**//Ставим в переменной что бонус создан.
bonus_exist = 1;
}

//**//Движение тела змейки по клеткам с проверкой таймера, для создания задержки и вписывание новых данных в массивы


//**//Движение змейки 
//**//Проверяем таймер, для движения с задержкой.
if (getTimer()-move_timer>170) {
//**//Обновление таймера движения.
move_timer = getTimer();
//**//вписываем в массив координаты головы змейки
cell_x[1] = _root.snake_head._x;
cell_y[1] = _root.snake_head._y;
//**//Движение головы змейки в клетку по направлению(_rotation)
_root.snake_head._x += 20*Math.sin(_root.snake_head._rotation*(Math.PI/180));
_root.snake_head._y -= 20*Math.cos(_root.snake_head._rotation*(Math.PI/180));
//**//Запись циклом сегментов тела змейки в массивы
for (i=1; i<body_count+1; i++) {
_root['snake_body'+i]._x = cell_x[i];
_root['snake_body'+i]._y = cell_y[i];
}
//**//Передвижение циклом всех сегментов тела змейки в вышестоящую ячейку массива.
for (i=1; i<body_count+1; i++) {
cell_x[i+1] = _root['snake_body'+i]._x;
cell_y[i+1] = _root['snake_body'+i]._y;
}

//**//Проверку столкновения головы змейки с бонусом, осуществяется встроенной функцией Flash - hitTest(), если столкновение произошло //**//- дублируем для тела змейки новые сегменты и устанавливаем им позицию в хвосте змейки на место последнего сегмента, при //**//последующем движении змейки - они будут следовать за ней, и вписывать свои координаты в массивы.


//**//Проверка столкновения головы змейки с бонусом методом HitTest`а и добавление новых сегментов к телу змейки 
if (_root.snake_head.hitTest(_root.bonus_real._x, _root.bonus_real._y)) {
trace('Bonus eat, you grow!');
removeMovieClip(_root.bonus_real);
//**//Устанавливаем переменную, что бонус съеден и обновляем таймер для создания нового бонуса
bonus_exist = 0;
bonus_timer = getTimer();
//**//Добавляем циклом новые сегменты тела к змейке на последний сегмент тела и увеличиваем переменную отвечающую за длину тела. 
for (i=0; i<4; i++) {
duplicateMovieClip(_root.snake_body, 'snake_body'+body_count, body_count);
body_count++;
_root['snake_body'+body_count]._x = _root['snake_body'+(body_count-1)]._x;
_root['snake_body'+body_count]._y = _root['snake_body'+(body_count-1)]._y;
cell_x[body_count] = _root['snake_body'+body_count]._x;
cell_y[body_count] = _root['snake_body'+body_count]._y;
}
}

//**//Проверка столкновения головы змейки с телом осуществляется циклом с функцией hitTest(), циклом проверяются все сегменты змейки //**//на столкновение с головой. Если столкновение произошло - функцией fscommand осуществляется закрытие мувика.

//Проверка столкновения головы с сегментами тела HitTest`ом 
for (i=0; i<body_count+1; i++) {
//**//Если столкновение произошло - выводим сообщение и закрываем мувик.
if (_root.snake_head.hitTest(_root['snake_body'+i]._x, _root['snake_body'+i]._y, 0)) {
trace('You eat your body. Cannibal !');
fscommand('quit', true);
}
}
}
}

Классы[править]

  • SnakeApp - Окно игры. Окно игры содержит игру, слушает клавиатуру и пересылает команды
  • SnakeGame - Главный класс игры. В сущности вся игра тут
  • Snake - класс змейки. Змейка вынесена в отдельный класс, чтобы в будущем была возможность создания нескольких экземпляров одновременно

Отладка[править]

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

  1. Нет проверок на самосъедание
  2. После аварии змейка может продолжить движение (уйти в бесконечность)
  3. Нет возможности перезапустить игру не закрывая окна

Исходники[править]

  • SnakeApp.java - Окно игры
  • SnakeGame.java - Главный класс игры
  • Snake.java - класс змейки
  • sn1.dat - текстовый файл с данными о стенках (поместите его в C:\ или измените путь в классе SnakeGame или в папке NetBeans scr....)