|
||||||||||||||||||||||||||||
Зміст
АнотаціяГра «Змійка» - це гра, в якій уявна змійка рухається по ігровому полю оминаючи перепони і їй потрібно влучити в ціль. Програма є нескладною і доступна для виконання на багатьох ЕОМ в різних операційних системах з встановленою Virtual Java Machine. Вона розрахована на широке коло користувачів завдяки своїй простоті.Завдання:Провести аналіз, розробити проект, скласти опис і специфікацію, провести кодування програми-гри «Змійка» використовуючи методи об'єктно-орієнтованого програмування.1. Аналіз предметної області, постановка задачі1.1. Формулювання проблемиКомп'ютерні ігри для людини - це не лише засіб розважитись. Вони допомагають розвинути людську реакцію, інтелект, знання в певних галузях і областях. Гра змійка - одна з таких ігор. Рівень, до якого дійде гравець, залежить лише від швидкості його реакції на поточні обставини гри, які динамічно змінюватимуться в сторону збільшення з кожним новим раундом, що також сприятиме збільшенню реакції. Провівши частину вільного часу за грою, можна отримати задоволення від набраних очок і пройдених рівнів. Якщо людина ніколи не працювала з комп'ютером, то гра допоможе набути мінімальних навиків з клавіатурою без необхідності розбиратись з складними правилами великих ігор та програм.Правила гри такі: на прямокутному ігровому полі створюється змійка, яка має декілька життів і складається з кількох частин. На полі також знаходяться клітки-перепони та ціль, в яку змійка має влучити. Змійка починає рухатися в довільному напрямку на найнижчій швидкості, яка відповідає першому рівню гри. Коли гравець натискатиме клавіші курсору, то напрям руху першої частини змійки - «голови» змінюватиметься відповідно до натиснутої клавіші. Коли голова змійки вийде за межі ігрового поля чи влучить в одну з перепон, то в залежності від того, залишились чи ні життя, в змійки або ж буде відняте одне життя, або ж гру буде припинено. Коли голова змійки «врізається» в ціль, то вона стане новою головою і рух змійки продовжиться. Коли довжина змійки перевищує максимально можливу, то даний рівень буде пройдено і гра перейде на наступний. В наступному рівні швидкість руху збільшується.1.2. Аналіз предметної областіГру «змійка» можна було б реалізувати в текстовому режимі, зображуючи всі об'єкти різними текстовими символами, наприклад, границі - підкреслюванням «_ і |», перепони хрестиками «Х», змійку прямокутниками.Але в іграх, що вже існують і подібні до даної, використовуються побудови в графічному режимі, хоч і максимально прості. Проте поряд з простотою в них застосовуються анімації для зображення руху, наприклад у грі в танки, ці танки рухаються по екрану, імітуючи рух справжнього танку.У грі для створення інтерфейсу користувача - виводу вікна гри, ігрових меню та кнопок, можна використати стандартні засоби мови JAVA - компоненти бібліотек AWT (застаріла) чи Swing (більш нова, що є частиною API - Java Foundation Classes), і тому її використання цієї бібліотеки дає більше можливостей для графічного оформлення гри - побудова найпростіших геометричних фігур, розфарбовування областей екрану та інше.1.3. Постановка задачіРозробити проект гри, з допомогою який можна програмно реалізувати, провівши кодування на об'єктно-орієнтованій мові програмування, скласти специфікацію.2. Проект програми2.1. Ієрархія об'єктівНа основі того, що необхідно розробити гру змійка, можна виділити головний об'єкт ієрархії - «Гра Змійка». Вона складається з «ігрового поля» та «меню». Об'єкти-пункти меню: «Гра» з вкладеними підпунктами «нова гра» - розпочинає нову гру, «пауза» - тимчасово припиняє гру, «зупинити гру» - зупиняє поточну гру, «вихід» - дозволяє вийти з програми. Підменю «швидкість гри» з меню «Настроювання» дозволяє змінити швидкість руху змійки. Об'єкт «ігрове поле» складається з об'єктів «ціль», «змійка», «перепона», «межі», «поле інформації» та «повідомлення». «Ціль» це клітка на ігровому полі, у яку має влучити змійка. «Змійка» складається з «частин» і згідно описаних вище правил рухається по ігровому полі. «Перепони» - це клітки на ігровому полі, які змійка має оминати. «Межі» ігрового поля встановлюють границі, за які змійка не може вийти. Влучання змійки в перепони чи вихід за ігрове поле зменшують її кількість гравців. «Поле інформації» інформуватиме гравця про стан гри: «Повідомлення» - якій будуть видаватися різноманітні текстові повідомлення про події в грі та вказівки гравцю (наприклад, повідомлення про те, що гру закінчено, про перехід в наступний тур або виграш у грі). «Індикатор життів» - об'єкт, який показуватиме про кількість життів змійки. «Індикатор рівня» буде показувати номер рівня, на якому знаходиться гра. «Індикатор довжини» відображатиме довжину змійки, щоб гравець орієнтувався, скільки цілей поцілено - згідно вказаних правил для переходу на наступний рівень, потрібно поцілити в певну кількість цілей. Рисунок 1 - ієрархія об'єктів гри Змійка 2.2. Ієрархія наслідуванняРисунок 2 - Ієрархія класів 2.3. Діаграма станів гриРисунок 3 - Діаграма станів гри 2.4. СпецифікаціяКлас public class Game - головний клас проекту необхідний для запуску гри Метод public static void main(String[] args) - з нього починається виконання програми Клас public class GameFrame реалізує вікно для відображення ігрового поля та даних гри Метод public GameFrame() - конструктор вікна гри в якому встановлюються його параметри. Метод public void newGame() - метод запускає новий сеанс гри Метод public void pauseGame() - метод створює паузу Метод public void stopGame() - метод зупиняє гру Клас public class GameField - ігрове поле Змінні: Snake snake - змійк GameFrame frame - змінна для доступу до вікна гри InformPanel informPanel - інформаційна панель protected boolean isGameRun = істина, якщо йде гра protected boolean isGamePause - істина під час паузи int gameSpeed - швидкість гри protected int colObstacles - Кількість перепон protected int delay - Затримка при русі змійки final int w = 35, h = 25 - розміри ігрового поля protected GameSquare square[][] - ігрові клітки boolean keyBlocked - істина, коли заблокована клавіатура Методи public GameField(GameFrame owner) - конструктор public void setDefault() - встановлення в початковий стан public void clearSquares()- відмічення всіх кліток вільними protected void createSnake() - створення змійки protected void createBorders() - Створює межі поля protected void createObstacles(int col) - створює col перепон на ігровому полі protected void createTarget() - створення мішені для змійки public void paintComponent(Graphics g) - малювання компонентів поля public void run () - обробка подій гри public void cheeckWin() - перевірка перемоги в грі public void processCrash() - перевірка влучання в перепону public void newGame() - Запуск нової гри public void pauseGame() - пауза в грі public void stopGame( ) - зупинка гри public void setGameSpeed(int s) - задання швидкості гри Клас public class InformPanel Змінні: protected int lives, len, speed, obstacles - кількість життів, довжина змійки, швидкість змійки, кількість перепон; Методи public InformPanel(final GameField field) - Конструктор public void updateInfo(int lives, int len, int speed, int obstacles) Зміна поточних даних новими public void paintComponent(Graphics g) - малювання панелі Клас class Snake - змійка Змінні: int colElements - кількість елементів final int maxLen - максимально можлива довжина SnakeElement elem[] - масив частин змійки int xNextSpeed, yNextSpeed - напрям руху на наступному кроці final int startLives - початкова кількість життів private static int lives - зберігає кількість життів змійки Методи public Snake(int c, int xPos, int yPos) - створення змійки довжини с з заданими координатами public void increment(SnakeElement lastElem) додавання до змійки нового елемента public boolean isMaxLong() - перевірка досягнення змійкою максимальної довжини public boolean isKilled() - перевірка, чи «жива» змійка public void decrementLive() - забирає життя в змійки Клас class SnakeElement - елемент змійки Змінні: int xSpeed - швидкість елемента змійки по горизонталі int ySpeed - швидкість елемента змійки по вертикалі int xPos - позиція елемента змійки по горизонталі int yPos - позиція елемента змійки по вертикалі public SnakeElement(int xPos, int yPos) - конструктор задає координати елемента public void move() - рухає елемент public void setSpeed(int x, int y) - встановлення швидкості елемента Клас class GameSquare - клітка ігрового поля Змінні: int w, h - розміри boolean used - використання boolean isBorder - перепона
Методи public void setSize(int w, int h) - встановлює розміри public void setBorder(boolean b) - робить клітинку перепоною public void setUsed(boolean b) - робить клітинкою зайнятою/незайнятою public void paintComponent(Graphics g) - малювання клітинки Клас public class MenuString - строка меню Змінні: - пункти меню і підменю JMenu Game; JMenuItem mi_NewGame, mi_PauseGame, mi_StopGame, mi_ExitGame; JMenu Options, Speed; JMenuItem mi_S1, mi_S2, mi_S3; JMenu Help; JMenuItem mi_About; 2.5. КодуванняКодування проведено згідно викладеного проекту на об'єктно орієнтованій мові Java.Мова Java є об'єктно-орієнтовнованою дозволяє реалізувати запроектовані класи, їх взаємодію та сприяє написанню надійних програм і спрощує їх реалізацію. Існує багато інших мов підтримуючих ООП технологію програмування. Це такі мови програмування, як С++, Object Pascal, Python та ін. Мова Java завдяки широким можливостям та бібліотекам класів має велику гнучкість і забезпечує можливість реалізації дуже великих проектів за мінімальний час,Тому для даної роботи було обрано мову Java, як найбільш ефективну та багато платформну.2.6. ВисновокВраховуючи аналіз предметної області і проект програми, можливо зробити висновок, що розроблена гра „Змійка” розрахована на широке коло користувачів завдяки своїй простоті. Модель програми дозволяє легко та зручно її модернізувати: додати нові команди; зробити сприйнятливий для користувача інтерфейс.3. Додаток3.1. Тексти файлів проекту3.1.1. Файл GameSnake.javapublic class GameSnake {
public static void main(String[] args) { GameFrame window = new GameFrame(); } } 3.1.2. Файл GameFrame.javaimport javax.swing.*; import java.awt.*; import java.awt.event.*; public class GameFrame extends JFrame{ GameField field; MenuString menu; boolean running = false; public GameFrame() { setDefaultLookAndFeelDecorated(true); setSize(400, 300); setTitle("Гра Змійка"); menu = new MenuString(this); field = new GameField(this); getContentPane().add(field); setJMenuBar(menu); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); addKeyListener(field); setVisible(true); } public void newGame(){ field.newGame(); } public void pauseGame(){ field.pauseGame(); } public void stopGame(){ field.stopGame(); } } 3.1.3. Файл GameField.javaimport java.awt.*; import javax.swing.*; import java.util.*; import java.awt.event.*; public class GameField extends JPanel implements Runnable, KeyListener{ Snake snake; GameFrame frame; SnakeElement targetElem; InformPanel informPanel; protected boolean isGameRun; protected boolean isGamePause = false; int gameSpeed = 2; protected int colObstacles = 12;//Кількість перепон protected int delay;//Затримка при русі змійки final int w = 35, h = 25; protected Thread th; protected GameSquare square[][]; boolean keyBlocked = false; boolean crash = false; boolean target = false; public GameField(GameFrame owner) { super(); frame = owner; this.setLayout(null); Random rnd = new Random(); square = new GameSquare[w][h]; for(int x = 0; x<w; x++){ for(int y = 0; y<h; y++){ square[x][y] = new GameSquare(); add(square[x][y]); } } informPanel = new InformPanel(this); frame.getContentPane().add(informPanel, BorderLayout.EAST); clearSquares(); createSnake(); createBorders(); start(); } public void setDefault(){ clearSquares(); createSnake(); createBorders(); createObstacles(colObstacles); createTarget(); informPanel.updateInfo(snake.getLives(), snake.colElements, gameSpeed, colObstacles); } public void clearSquares(){ for(int x = 0; x<w; x++){ for(int y = 0; y<h; y++){ square[x][y].setBorder(false); square[x][y].setUsed(false); } } } protected void createSnake(){ snake = new Snake(5, w/2, h-2); for (int i = 0; i<snake.colElements; i++){ square[snake.elem[i].xPos][snake.elem[i].yPos].setUsed(true); square[snake.elem[i].xPos][snake.elem[i].yPos].setBorder(true); square[snake.elem[i].xPos][snake.elem[i].yPos].n = i; } } protected void createBorders(){ for (int i = 0; i<w; i++){ square[i][0].setBorder(true); square[i][h-1].setBorder(true); } for (int i = 0; i<h; i++){ square[0] [i].setBorder(true); square[w-1][i].setBorder(true); } } protected void createObstacles(int col){//створює n ререпон на ігровому полі Random rnd = new Random(); int x, y; for (int i = 0; i<col; i++){ do{ x = Math.abs(rnd.nextInt(w)); y = Math.abs(rnd.nextInt(h)); } while (square[x][y].isBorder); square[x][y].setBorder(true); } } protected void createTarget(){//Мішень для змійки Random rnd = new Random(); int x, y; targetElem = new SnakeElement(0, 0); do{ x = Math.abs(rnd.nextInt(w)); y = Math.abs(rnd.nextInt(h)); } while (square[x][y].isBorder); targetElem.setSpeed(0, 0); targetElem.xPos = x; targetElem.yPos = y; square[x][y].setUsed(true); } public void paintComponent(Graphics g){ super.paintComponent(g); int squareW = (getWidth())/w; int squareH = (getHeight())/h; for(int x = 0; x<w; x++){ for(int y = 0; y<h; y++){ square[x][y].setSize(squareW, squareH); square[x][y].setLocation(x*squareW, y*squareH); } } g.setColor(Color.BLUE); g.setFont( new Font("1", Font.BOLD, 20) ); if ( !isGameRun ){ g.drawString("Розпочніть нову гру", 40, 100); } else { if (isGamePause){ g.drawString("ПАУЗА", 100, 100); } } } public void run (){ while (true){ if (isGameRun && !isGamePause){ keyBlocked = true; int n = snake.colElements-1; SnakeElement lastElem = new SnakeElement(snake.elem[n].xPos, snake.elem[n].yPos); lastElem.setSpeed(snake.elem[n].xSpeed, snake.elem[n].ySpeed); square[lastElem.xPos][lastElem.yPos].setUsed(false); square[lastElem.xPos][lastElem.yPos].setBorder(false); snake.move(); crash = square[snake.elem[0].xPos][snake.elem[0].yPos].isBorder; target = !crash && square[snake.elem[0].xPos][snake.elem[0].yPos].used; if (target){ snake.increment(lastElem); createTarget(); cheeckWin(); } keyBlocked = false; for (int i = 0; i<snake.colElements; i++){ square[snake.elem[i].xPos][snake.elem[i].yPos].setUsed(true); square[snake.elem[i].xPos][snake.elem[i].yPos].setBorder(true); square[snake.elem[i].xPos][snake.elem[i].yPos].n = i; } if (crash) { processCrash(); } repaint(); informPanel.updateInfo(snake.getLives(), snake.colElements, gameSpeed, colObstacles); informPanel.repaint(); try { Thread.sleep (delay); } catch ( InterruptedException ex){ } } } } public void cheeckWin(){ if (snake.isMaxLong()) { JOptionPane.showMessageDialog(frame, "Ви перемогли!\nНа швидкості "+gameSpeed, "Ігрова інформація", JOptionPane.INFORMATION_MESSAGE); stopGame(); try { Thread.sleep (delay*2); } catch ( InterruptedException ex){ } setDefault(); } } public void processCrash(){ snake.decrementLive(); if (snake.isKilled()) { JOptionPane.showMessageDialog(frame, "Гру завершено!", "Ігрова інформація", JOptionPane.INFORMATION_MESSAGE); stopGame(); } try { Thread.sleep (delay*2); } catch ( InterruptedException ex){ } setDefault(); } public void newGame(){ if (isGameRun) stopGame(); setDefault(); snake.resetLives(); isGameRun = true; isGamePause = false; } public void pauseGame(){ isGamePause = !isGamePause; if (isGamePause){ keyBlocked = true; repaint(); } else{ keyBlocked = false; } } public void stopGame( ){ isGameRun = false; repaint(); } public void setGameSpeed(int s){ gameSpeed = s; switch (gameSpeed){ case 1: delay = 400; break; case 2: delay = 200; break; case 3: delay = 100; break; } informPanel.updateInfo(snake.getLives(), snake.colElements, gameSpeed, colObstacles); } public void start(){ isGameRun = false; setGameSpeed(2); th = new Thread(this); th.start(); } public void stop(){} public void keyPressed (KeyEvent e){ switch (e.getKeyCode()) { // Яку клавішу натиснули. case KeyEvent.VK_LEFT : if (!snake.elem[0].isMovingRight() && !keyBlocked){ snake.setMoveLeft(); keyBlocked = true; } break; case KeyEvent.VK_RIGHT : if (!snake.elem[0].isMovingLeft() && !keyBlocked){ snake.setMoveRight(); keyBlocked = true; } break; case KeyEvent.VK_UP : if (!snake.elem[0].isMovingDown() && !keyBlocked){ snake.setMoveUp(); keyBlocked = true; } break; case KeyEvent.VK_DOWN : if (!snake.elem[0].isMovingUp() && !keyBlocked){ snake.setMoveDown(); keyBlocked = true; } break; case KeyEvent.VK_SPACE : newGame(); break; case KeyEvent.VK_P : pauseGame(); break; } } public void keyTyped(KeyEvent e){} public void keyReleased(KeyEvent e){} } 3.1.4. Файл InformPanel.javaimport javax.swing.*; import java.awt.*; import java.awt.event.*; public class InformPanel extends JPanel{ JLabel label; boolean rn = true; protected int lives, len, speed, obstacles; public InformPanel(final GameField field) { label = new JLabel("Інформація гри"); add(label); setDefault(); } public void setDefault(){ updateInfo(0, 0, 0, 0); } public void updateInfo(int lives, int len, int speed, int obstacles){ this.lives = lives; this.len = len; this.speed = speed; this.obstacles = obstacles; repaint(); } public void paintComponent(Graphics g){ int h = 100; super.paintComponent(g); g.drawString(" Життя: " + lives, 1, h += 30); g.drawString("Елементів: " + len, 1, h += 30); g.drawString("Швидкість: " + speed, 1, h += 30); g.drawString(" Перепони: " + obstacles, 1, h += 30); } } 3.1.5. Файл Snake.javaclass Snake { int colElements; final int maxLen = 16; SnakeElement elem[]; int xNextSpeed, yNextSpeed; final int startLives = 3; private static int lives; public Snake(int c, int xPos, int yPos){ colElements = c; elem = new SnakeElement[colElements]; for (int i = 0; i<colElements; i++) { elem[i] = new SnakeElement(xPos-i,yPos); elem[i].setMoveRight(); } setMoveRight(); } public void resetLives(){ lives = startLives; } public void increment(SnakeElement lastElem) { SnakeElement temp[]; temp = new SnakeElement[colElements]; for (int i = 0; i<colElements; i++) { temp[i] = new SnakeElement(0,0); temp[i] = elem[i]; } colElements++; elem = new SnakeElement[colElements]; for (int i = 0; i<colElements-1; i++) { elem[i] = new SnakeElement(0,0); elem[i] = temp[i]; } elem[colElements-1] = new SnakeElement(0,0); elem[colElements-1] = lastElem; elem[colElements-1].xSpeed = lastElem.xSpeed; elem[colElements-1].ySpeed = lastElem.ySpeed; } public void move(){ for (int i = colElements-1; i>0; i--){ elem[i].setSpeed(elem[i-1].xSpeed, elem[i-1].ySpeed); elem[i].move(); } elem[0].xSpeed = xNextSpeed; elem[0].ySpeed = yNextSpeed; elem[0].move(); } public void setMoveUp(){ xNextSpeed = 0; yNextSpeed = -1; }; public void setMoveDown(){ xNextSpeed = 0; yNextSpeed = 1; }; public void setMoveLeft(){ xNextSpeed = -1; yNextSpeed = 0; }; public void setMoveRight(){ xNextSpeed = 1; yNextSpeed = 0; }; public boolean isMaxLong(){return (colElements == maxLen);} public boolean isKilled(){return (lives<0);} public void decrementLive(){lives -=1;} public int getLives(){ return lives;} } 3.1.6. Файл SnakeElement.javaclass SnakeElement { int xSpeed=1; int ySpeed=1; int xPos=1; int yPos=1; public SnakeElement(int xPos, int yPos){ this.xPos = xPos; this.yPos = yPos; } public void move(){ xPos += xSpeed; yPos += ySpeed; } public void setSpeed(int x, int y){ xSpeed = x; ySpeed = y; } public void setMoveUp() { xSpeed = 0; ySpeed = -1;} public void setMoveDown() { xSpeed = 0; ySpeed = 1;} public void setMoveLeft() { xSpeed = -1; ySpeed = 0;} public void setMoveRight(){ xSpeed = 1; ySpeed = 0;} public boolean isMovingUp() { return ySpeed == -1;} public boolean isMovingDown(){ return ySpeed == 1;} public boolean isMovingLeft(){ return xSpeed == -1;} public boolean isMovingRight(){ return xSpeed == 1;} } 3.1.7. Файл GameSquare.javaimport java.awt.*; import javax.swing.*; class GameSquare extends JPanel{ int w, h; boolean used = false; boolean isBorder = false; int n; public void setSize(int w, int h){ super.setSize(w, h); this.w = w; this.h = h; } public void setBorder(boolean b){isBorder = b;} public void setUsed(boolean b){used = b;} public void paintComponent(Graphics g){ if (isBorder && !used){ g.setColor(Color.ORANGE); g.fillRect(0,0,w-1,h-1); g.setColor(Color.RED); g.drawRect(0,0,w-1,h-1); } if (used) { g.setColor(Color.BLUE); g.fillOval(-1, -1, w+2, h+2); } } } 3.1.8. Файл MenuString.javaimport javax.swing.*; import java.awt.*; import java.awt.event.*; public class MenuString extends JMenuBar { JMenu Game; JMenuItem mi_NewGame, mi_PauseGame, mi_StopGame, mi_ExitGame; JMenu Options, Speed; JMenuItem mi_S1, mi_S2, mi_S3; JMenu Help; JMenuItem mi_About; public MenuString(final GameFrame owner) { super(); Game = new JMenu("Гра"); mi_NewGame = new JMenuItem("Нова гра"); mi_NewGame.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { owner.newGame(); } }); mi_PauseGame = new JMenuItem("Пауза"); mi_PauseGame.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { owner.pauseGame(); } }); mi_StopGame = new JMenuItem("Зупинити гру"); mi_StopGame.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { owner.stopGame(); } }); mi_ExitGame = new JMenuItem("Вихiд"); mi_ExitGame.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //Вихід з гри System.exit(0); } }); Game.add(mi_NewGame); Game.add(mi_PauseGame); Game.add(mi_StopGame); Game.add(mi_ExitGame); add(Game); Options = new JMenu("Настроювання"); Speed = new JMenu("Швидкість гри"); Options.add(Speed); mi_S1 = new JMenuItem("Новичок"); mi_S1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { owner.field.setGameSpeed(1); } }); mi_S2 = new JMenuItem("Середня"); mi_S2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { owner.field.setGameSpeed(2); } }); mi_S3 = new JMenuItem("Професіонал"); mi_S3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { owner.field.setGameSpeed(3); } }); Speed.add(mi_S1); Speed.add(mi_S2); Speed.add(mi_S3); add(Options); Help = new JMenu("Допомога"); mi_About = new JMenuItem("Про гру"); mi_About.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //Інформаційне вікно JOptionPane.showMessageDialog(owner, "Гра Змійка\nАвтор: Гребенюк Віктор\n2005 рік", "Про гру", JOptionPane.INFORMATION_MESSAGE); } }); Help.add(mi_About); add(Help); } } 3.2. Знімок вікна програми:
4. Література4.1. JAVA - Издательство Питер. Секреты программирования для Internet на Java 4.2. Картузов А.В. Язык JAVA |
|