- •Занятие 1. "Постановка задания для разработки игры Змейка. Работа с двумерным массивом"
- •Правила самостоятельной разработки игр данного курса
- •Работа с двумерным массивом в Java
- •Применение двумерного массива при создании игр
- •Постановка задания по созданию игры Змейка
- •Разделение задания для трех уровней сложности
- •План разработки проекта
- •Алгоритм для реализации игры Змейка
- •Перемещать голову змейки в нужном направлении.
- •Удалять хвост змейки. Удаление хвоста равносильно записи нулевого значения в элемент массива, где находилось число, отвечающее за хвост змейки.
- •Итог занятия
- •Занятие 2. "Постановка задания для разработки игры Морской бой"
- •Постановка задания по созданию игры Морской бой
- •Разделение задания для трех уровней сложности
- •Рекомендации для реализации игровых полей игры Морской бой
- •Алгоритм для реализации игры "Морской бой"
- •Генерация кораблей на игровом поле
- •Итог занятия
- •Занятие 3. "Постановка задания для разработки игры Пасьянс-Косынка"
- •Правила игры Пасьянс-Косынка
- •Упаковка файлов изображений внутрьJar-архива
- •Работа со списком в Java
- •Import java.Util.ArrayList;
- •Постановка задания по созданию игры Пасьянс-Косынка
- •Разделение задания для трех уровней сложности
- •Алгоритм перемешивания карт в колоде
- •Создание массива списков значений
- •Итог занятия
- •Заключение
- •Занятие 1. "Разработка игры Змейка. Первый и второй уровень сложности"
- •Рекомендации для изучения программного кода игр
- •Изучаемый программный код необходимо самостоятельно вводить с клавиатуры в среде разработки, глядя на образец в печатном издании.
- •Каждую строчку, каждый фрагмент программного кода стараться максимально разобрать и понять смысл. Не следует бездумно переписывать программный код и запускать!
- •Моменты, которые вызывают особые сложности в понимании, стараться нарисовать на бумаге или пройти пошагово.Например, цикл, который использует формулу с изменяющимися переменными в цикле.
- •Старайтесь больше экспериментировать с записанным программным кодом. Изменяйте значение кого-нибудь параметра и запускайте программу. Смотрите на изменения.
- •После разбора фрагмента программного кода –закрывайте книгу и начинайте пытаться записать свой программный код,который выполняет тоже самое, при этом, не заглядывая в книгу - с чистого листа.
- •Реализация первого уровня сложности игры Змейка Подготовка изображений для игры Змейка
- •Создание проекта и файлов классов игры Змейка
- •Реализация второго уровня сложности игры Змейка(начало)
- •Итог занятия
- •Занятие 2. "Разработка игры Змейка. Второй и третий уровень сложности"
- •Реализация второго уровня сложности игры Змейка(завершение)
- •Реализация третьего уровня сложности игры Змейка
- •Механизм перемещения змейки
- •Итог занятия
- •Занятие 3. "Разработка игры Морской бой. Первый уровень сложности"
- •Создание проекта и файлов классов игры Морской бой
- •Итог занятия
- •Занятие 4. "Разработка игры Морской бой. Второй уровень сложности"
- •Реализация второго уровня сложности игры Морской бой
- •Обозначения состояния ячейки игрового поля
- •Отрисовка игрового поля на основании двумерного массива
- •Ситуация выхода за пределы массива
- •Генерация однопалубных кораблей
- •Генерация четырехпалубного корабля
- •Итог занятия
- •Занятие 5. "Разработка игры Морской бой. Третий уровень сложности"
- •Реализация третьего уровня сложности игры Морской бой
- •Выполнение ходов игроком и компьютером
- •Стратегия ходов компьютера
- •Итог занятия
- •Занятие 6. "Разработка игры Пасьянс-Косынка. Начало первого уровня сложности"
- •Подготовка изображений для игры
- •Создание проекта и файлов классов игры Пасьянса-Косынка
- •Реализация класса kosinka
- •Реализация класса okno
- •Import javax.Swing.*;
- •Import java.Awt.*;
- •Реализация класса pole
- •Реализация класса karta
- •Import javax.Imageio.*;
- •Import java.Awt.*;
- •Import java.Io.*;
- •Итог занятия
- •Занятие 7. "Разработка игры Пасьянс-Косынка. Завершение первого уровня сложности"
- •Реализация класса stopka
- •Import java.Util.ArrayList;
- •Начало реализации класса game
- •Реализация класса pole
- •Завершение реализации класса game для первого уровня сложности
- •Vidacha();
- •Итог занятия
- •Занятие 8. "Разработка игры Пасьянс-Косынка. Второй уровень сложности"
- •Перерисовка всех стопок карт
- •Stopki[I].Get(stopki[I].Size()-2).Draw(gr);
- •Раздача карт в нижние семь стопок
- •Начало реализации третьего уровня сложности
- •Итог занятия
- •Занятие 9. "Разработка игры Пасьянс-Косынка. Третий уровень сложности"
- •// Получаем номер верхней карты
- •Тестирование переноса
- •Vidacha();
- •Заключение
- •Итог занятия
Реализация класса pole
Перейдем в файл pole.java. В классе poleмы уже добавили необходимые библиотеки. Этот класс наследуется от класса JPanel. Это наше игровое поле. Реализация этого класса будет во многом похожа на реализацию его в игре"Морской бой". В этом классе будет производиться загрузка изображений, настройка таймера отрисовки игрового поля, подключение обработчиков событий для мыши и сам процесс перерисовки игрового поля. В самом верху класса добавим свойства класса pole:
// Для работы с событиями (мышь, таймер)
import java.awt.event.*;
// Для работы с окнами и кнопками
import javax.swing.*;
// Для работы с графикой
import java.awt.*;
// Для работы с картинками
import javax.imageio.*;
// Для работы с файлами
import java.io.*;
// Класс игрового поля наследуется от JPanel
public class pole extends JPanel
{
// Таймер для отрисовки игрового поля
private Timer tmDraw;
// Две кнопки: Новая игра,Выход
private JButton btn1,btn2;
// Изображение фона
private Image fon;
// Переменная для реализации игры
private game newGame;
}
Это таймер для перерисовки игрового поля, две кнопки, фон игрового поля и переменная для реализации логики игры.
Под переменными класса,внутри класса poleдобавим уже знакомые нам два класса для обработки событий от мыши:
public class myMouse1 implements MouseListener {
public void mouseClicked(MouseEvent e) {}
// При нажатии кнопки мыши
public void mousePressed(MouseEvent e) {
//Если еще не конец игры
if (newGame.endGame==false)
{
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
// Если нажата левая клавиша мыши один раз
if ((e.getButton()==1)&&(e.getClickCount()==1))
{
// Вызываем метод из класса game
newGame.mousePressed(mX, mY);
}
// Если двойной щелчок левой клавиши мыши
else if ((e.getButton()==1)&&(e.getClickCount()==2))
{
// Вызываем метод из класса game
newGame.mouseDoublePressed(mX, mY);
}
}
}
// При отпускании кнопки мыши
public void mouseReleased(MouseEvent e)
{
//Если еще не конец игры
if (newGame.endGame==false)
{
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
// Если нажата левая клавиша мыши
if (e.getButton()==1)
{
// Вызываем метод из класса game
newGame.mouseReleased(mX, mY);
}
}
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
}
public class myMouse2 implements MouseMotionListener {
// При перетаскивании (захвате мышью)
public void mouseDragged(MouseEvent e)
{
// Если еще не конец игры
if (newGame.endGame==false)
{
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
// Вызываем метод из класса game
newGame.mouseDragged(mX, mY);
}
}
public void mouseMoved(MouseEvent e) {}
}
При создании игры"Пасьянс-Косынка"нам интересны три события связанных с мышью: нажатие клавиши мыши mousePressed(), отпускание клавиши мыши mouseReleased(), перенос мышью (захват) mouseDragged().
Во всех этих трех методах проверяем, что еще не конец игры:
// Если еще не конец игры
if (newGame.endGame==false)
{
Если еще не конец игры,то получаем текущие координаты курсора мыши:
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
Обработку действий пользователя, контроль над правильностью действий мы будем реализовывать в классеgame. В классеgame у нас созданы для этого четыре метода, их названия начинаются со слова mouse. Внутри класса poleмы будем лишь определять координаты курсора, и вызывать методы класса game. При помощи дополнительных проверок, таких как:
if ((e.getButton()==1)&&(e.getClickCount()==1))
мы проверяем, что пользователь использовал именно левую клавишу мыши и определяем количество нажатий (обычное нажатие или двойной щелчок).
При двойном щелчке мыши должно происходить действие автоматического переноса карты в домашнюю стопку (см. рис. 7) –если это возможно сделать. Для первого уровня сложности двойной щелчок мыши не нужно обрабатывать, но мы сразу создадим класс pole для всех уровней сложности, чтобы больше к нему не возвращаться.
Рис. 7
Под двумя классами для работы с мышью создадим конструктор класса pole:
// Конструктор класса pole
public pole()
{
// Подключаем обработчики событий для мыши
addMouseListener(new myMouse1());
addMouseMotionListener(new myMouse2());
// Создаем объект на основании классаgame
newGame = new game();
//Загружаем фоновое изображение
try
{
fon = ImageIO.read(new File("c:\\karta\\fon.png"));
}
catch (Exception ex) {}
// Включаем возможность произвольного
// размещения элементов формы
setLayout(null);
// Создаем первую кнопку Новая игра
btn1 = new JButton();
btn1.setText("Новая игра");
btn1.setForeground(Color.BLUE);
btn1.setFont(new Font("serif",0,20));
btn1.setBounds(820, 50, 150, 50);
btn1.addActionListener(new ActionListener() {
// При нажатии на кнопку
public void actionPerformed(ActionEvent arg0) {
// Старт игры (Запуск игры)
newGame.start();
}
});
add(btn1);
// Создаем вторую кнопку Выход
btn2 = new JButton();
btn2.setText("Выход");
btn2.setForeground(Color.RED);
btn2.setFont(new Font("serif",0,20));
btn2.setBounds(820, 150, 150, 50);
btn2.addActionListener(new ActionListener() {
// При нажатии на кнопку
public void actionPerformed(ActionEvent arg0) {
// Завершение работы приложения
System.exit(0);
}
});
add(btn2);
// Создаем, настраиваем и запускаем таймер отрисовки
tmDraw = new Timer(20,new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// Перерисовка игрового поля
repaint();
}
});
tmDraw.start();
}
Данный конструктор практически не отличается от конструктора того же класса для игры "Морской бой". Сначала подключаются обработчики событий для мыши.Потом создается объект на основании классаgame. Загружается фоновое изображение. Создаются две кнопки и таймер для перерисовки игрового поля.Выполним запуск проекта. Должны появиться две кнопки (см. рис. 8). При нажатии на кнопку Выход, приложение должно закрываться.
В классе poleосталось добавить только метод paintComponent(), который вызывается в таймере для перерисовки игрового поля. В методе paintComponent() мы сначала очищаем игровое поле, затем выводим фоновое изображение. Далее рисуем шесть верхних белых прямоугольников и семь нижних белых прямоугольников.
Рис. 8
Прямоугольники выводим без заливки, только контуры.Прямоугольники выводятся в местах расположения стопок карт. Всего стопок будет тринадцать. В самом конце вызываем метод выведения всех стопок карт:
// Метод отрисовки игрового поля
public void paintComponent(Graphics gr)
{
//Очищение игрового поля
super.paintComponent(gr);
//Выведение фонового изображения
gr.drawImage(fon,0,0,1000,700,null);
//Рисование верхних белых шести прямоугольников
gr.setColor(Color.WHITE);
for (int i=0;i<7;i++)
{
if (i!=2) gr.drawRect(30+i*110, 15, 72, 97);
}
//Рисование верхних белых шести прямоугольников
for (int i=0;i<7;i++)
{
gr.drawRect(30+i*110, 130, 72, 97);
}
//Метод отрисовки всех стопок карт
newGame.drawKoloda(gr);
}
Запустим проект. В дополнение к кнопкам должно появиться фоновое изображение и тринадцать белых контуров прямоугольников (см.рис. 9).
Рис. 9
На этом реализация класса pole является полностью законченной для всех уровней сложности. Больше к этому классу мы возвращаться не будем. Можно закрыть закладку pole.java (см.рис. 10).
Рис. 10
Полный программный код класса poleвыглядит так:
// Для работы с событиями (мышь, таймер)
import java.awt.event.*;
// Для работы с окнами и кнопками
import javax.swing.*;
// Для работы с графикой
import java.awt.*;
// Для работы с картинками
import javax.imageio.*;
// Для работы с файлами
import java.io.*;
// Класс игрового поля наследуется от JPanel
public class pole extends JPanel
{
// Таймер для отрисовки игрового поля
private Timer tmDraw;
// Две кнопки: Новая игра,Выход
private JButton btn1,btn2;
// Изображение фона
private Image fon;
// Переменная для реализации игры
private game newGame;
public class myMouse1 implements MouseListener {
public void mouseClicked(MouseEvent e) {}
// При нажатии кнопки мыши
public void mousePressed(MouseEvent e) {
// Если еще не конец игры
if (newGame.endGame==false)
{
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
// Если нажата левая клавиша мыши один раз
if ((e.getButton()==1)&&(e.getClickCount()==1))
{
// Вызываем метод из класса game
newGame.mousePressed(mX, mY);
}
// Если двойной щелчок левой клавиши мыши
else if ((e.getButton()==1)&&(e.getClickCount()==2))
{
// Вызываем метод из класса game
newGame.mouseDoublePressed(mX, mY);
}
}
}
// При отпускании кнопки мыши
public void mouseReleased(MouseEvent e)
{
//Если еще не конец игры
if (newGame.endGame==false)
{
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
// Если нажата левая клавиша мыши
if (e.getButton()==1)
{
// Вызываем метод из класса game
newGame.mouseReleased(mX, mY);
}
}
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
}
public class myMouse2 implements MouseMotionListener {
// При перетаскивании (захвате мышью)
public void mouseDragged(MouseEvent e)
{
// Если еще не конец игры
if (newGame.endGame==false)
{
// Получаем координаты курсора мыши
int mX = e.getX();
int mY = e.getY();
//Вызываем метод из класса game
newGame.mouseDragged(mX, mY);
}
}
public void mouseMoved(MouseEvent e) {}
}
// Конструктор класса pole
public pole()
{
// Подключаем обработчики событий для мыши
addMouseListener(new myMouse1());
addMouseMotionListener(new myMouse2());
// Создаем объект на основании классаgame
newGame = new game();
// Загружаем фоновое изображение
try
{
fon = ImageIO.read(new File("c:\\karta\\fon.png"));
}
catch (Exception ex) {}
// Включаем возможность произвольного
// размещения элементов формы
setLayout(null);
// Создаем первую кнопку Новая игра
btn1 = new JButton();
btn1.setText("Новая игра");
btn1.setForeground(Color.BLUE);
btn1.setFont(new Font("serif",0,20));
btn1.setBounds(820, 50, 150, 50);
btn1.addActionListener(new ActionListener() {
// При нажатии на кнопку
public void actionPerformed(ActionEvent arg0) {
// Старт игры (Запуск игры)
newGame.start();
}
});
add(btn1);
// Создаем вторую кнопку Выход
btn2 = new JButton();
btn2.setText("Выход");
btn2.setForeground(Color.RED);
btn2.setFont(new Font("serif",0,20));
btn2.setBounds(820, 150, 150, 50);
btn2.addActionListener(new ActionListener() {
// При нажатии на кнопку
public void actionPerformed(ActionEvent arg0) {
// Завершение приложения
System.exit(0);
}
});
add(btn2);
// Создаем, настраиваем и запускаем таймер отрисовки
tmDraw = new Timer(20,new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// Перерисовка игрового поля
repaint();
}
});
tmDraw.start();
}
// Метод отрисовки игрового поля
public void paintComponent(Graphics gr)
{
//Очищение игрового поля
super.paintComponent(gr);
//Выведение фонового изображения
gr.drawImage(fon,0,0,1000,700,null);
//Рисование верхних белых шести прямоугольников
gr.setColor(Color.WHITE);
for (int i=0;i<7;i++)
{
if (i!=2) gr.drawRect(30+i*110, 15, 72, 97);
}
//Рисование верхних белых шести прямоугольников
for (int i=0;i<7;i++)
{
gr.drawRect(30+i*110, 130, 72, 97);
}
//Метод отрисовки всех стопок карт
newGame.drawKoloda(gr);
}
}
