Catatan Sang Pembelajar

Share Your Thought !

Membuat Game FPS-Duck — October 2, 2014

Membuat Game FPS-Duck

Bicara tentang Game, mungkin gak ada habisnya. Kali ini saya mencoba membuat tutorial Game 2D sederhana menggunakan Java. Game ini saya namakan FPS-Duck atau tembak-tembakan bebek!! Haha.

Pertama saya akan memperkenalkan Basic Game Flow di dalam game seperti gambar berikut:

Basic-game-flow-diagram

Penjelasan :

Dalam “Launch Game”, pertama Window dibuat dilanjutkan dengan panel di dalamnya. Pada state ini semua file dimuat (gambar, suara dll). Ketika state “Launch Game” selesai maka dilanjutkan dengan state “Main Menu”. Pada state “Main Menu” user diberi pilihan apakah ingin keluar game atau ingin memulai permainan.

Gak usah terlalu banyak penjelasan, mari langsung saja kita ke intinya!!

Kebutuhan

  • Pastikan JDK sudah terinstall dengan benar
  • Gunakan IDE yang Anda sukai (Netbeans, Eclipse, Intellij IDEA)

Langkah-langkah

  • Klik menu New Project -> Java Application
  • Buat 2 buah direktori (main dan resources). main untuk menyimpan Class, sedangkan resources untuk menyimpan file (gambar, suara dll).
  • Buat Class Duck.java
package com.company;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

/**
 * The duck class.
 * 
 * @author thinksmart
 */

public class Duck {
 
 /**
 * How much time must pass in order to create a new duck?
 */
 public static long timeBetweenDucks = Framework.secInNanosec / 2;
 /**
 * Last time when the duck was created.
 */
 public static long lastDuckTime = 0;
 
 /**
 * Duck lines.
 * Where is starting location for the duck?
 * Speed of the duck?
 * How many points is a duck worth?
 */
 public static int[][] duckLines = {
 {Framework.frameWidth, (int)(Framework.frameHeight * 0.60), -2, 20},
 {Framework.frameWidth, (int)(Framework.frameHeight * 0.65), -3, 30},
 {Framework.frameWidth, (int)(Framework.frameHeight * 0.70), -4, 40},
 {Framework.frameWidth, (int)(Framework.frameHeight * 0.78), -5, 50}
 };
 /**
 * Indicate which is next duck line.
 */
 public static int nextDuckLines = 0;
 
 
 /**
 * X coordinate of the duck.
 */
 public int x;
 /**
 * Y coordinate of the duck.
 */
 public int y;
 
 /**
 * How fast the duck should move? And to which direction?
 */
 private int speed;
 
 /**
 * How many points this duck is worth?
 */
 public int score;
 
 /**
 * Duck image.
 */
 private BufferedImage duckImg;
 
 
 /**
 * Creates new duck.
 * 
 * @param x Starting x coordinate.
 * @param y Starting y coordinate.
 * @param speed The speed of this duck.
 * @param score How many points this duck is worth?
 * @param duckImg Image of the duck.
 */
 public Duck(int x, int y, int speed, int score, BufferedImage duckImg)
 {
 this.x = x;
 this.y = y;
 
 this.speed = speed;
 
 this.score = score;
 
 this.duckImg = duckImg; 
 }
 
 
 /**
 * Move the duck.
 */
 public void Update()
 {
 x += speed;
 }
 
 /**
 * Draw the duck to the screen.
 * @param g2d Graphics2D
 */
 public void Draw(Graphics2D g2d)
 {
 g2d.drawImage(duckImg, x, y, null);
 }
}
  • Buat Class Window.java, Class ini berisi method main yang digunakan untuk menjalankan game. 
package com.company;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 * Creates frame and set its properties.
 * 
 * @author thinksmart
 */

public class Window extends JFrame{
 
 private Window()
 {
 // Sets the title for this frame.
 this.setTitle("Shoot the duck");
 
 // Sets size of the frame.
 if(true) // Full screen mode
 {
 // Disables decorations for this frame.
 this.setUndecorated(true);
 // Puts the frame to full screen.
 this.setExtendedState(this.MAXIMIZED_BOTH);
 }
 else // Window mode
 {
 // Size of the frame.
 this.setSize(800, 600);
 // Puts frame to center of the screen.
 this.setLocationRelativeTo(null);
 // So that frame cannot be resizable by the user.
 this.setResizable(false);
 }
 
 // Exit the application when user close frame.
 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
 this.setContentPane(new Framework());
 
 this.setVisible(true);
 }

 public static void main(String[] args)
 {
 // Use the event dispatch thread to build the UI for thread-safety.
 SwingUtilities.invokeLater(new Runnable() {
 @Override
 public void run() {
 new Window();
 }
 });
 }
}
  • Buat Class Canvas.java. 
package com.company;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

/**
 * Create a JPanel on which we draw and listen for keyboard and mouse events.
 * 
 * @author thinksmart
 */

public abstract class Canvas extends JPanel implements KeyListener, MouseListener {
 
 // Keyboard states - Here are stored states for keyboard keys - is it down or not.
 private static boolean[] keyboardState = new boolean[525];
 
 // Mouse states - Here are stored states for mouse keys - is it down or not.
 private static boolean[] mouseState = new boolean[3];
 
 
 public Canvas()
 {
 // We use double buffer to draw on the screen.
 this.setDoubleBuffered(true);
 this.setFocusable(true);
 this.setBackground(Color.black);
 
 // If you will draw your own mouse cursor or if you just want that mouse cursor disapear, 
 // insert "true" into if condition and mouse cursor will be removed.
 if(true)
 {
 BufferedImage blankCursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
 Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(blankCursorImg, new Point(0, 0), null);
 this.setCursor(blankCursor);
 }
 
 // Adds the keyboard listener to JPanel to receive key events from this component.
 this.addKeyListener(this);
 // Adds the mouse listener to JPanel to receive mouse events from this component.
 this.addMouseListener(this);
 }
 
 
 // This method is overridden in Framework.java and is used for drawing to the screen.
 public abstract void Draw(Graphics2D g2d);
 
 @Override
 public void paintComponent(Graphics g)
 {
 Graphics2D g2d = (Graphics2D)g; 
 super.paintComponent(g2d); 
 Draw(g2d);
 }
 
 
 // Keyboard
 /**
 * Is keyboard key "key" down?
 * 
 * @param key Number of key for which you want to check the state.
 * @return true if the key is down, false if the key is not down.
 */
 public static boolean keyboardKeyState(int key)
 {
 return keyboardState[key];
 }
 
 // Methods of the keyboard listener.
 @Override
 public void keyPressed(KeyEvent e) 
 {
 keyboardState[e.getKeyCode()] = true;
 }
 
 @Override
 public void keyReleased(KeyEvent e)
 {
 keyboardState[e.getKeyCode()] = false;
 keyReleasedFramework(e);
 }
 
 @Override
 public void keyTyped(KeyEvent e) { }
 
 public abstract void keyReleasedFramework(KeyEvent e);
 
 
 // Mouse
 /**
 * Is mouse button "button" down?
 * Parameter "button" can be "MouseEvent.BUTTON1" - Indicates mouse button #1
 * or "MouseEvent.BUTTON2" - Indicates mouse button #2 ...
 * 
 * @param button Number of mouse button for which you want to check the state.
 * @return true if the button is down, false if the button is not down.
 */
 public static boolean mouseButtonState(int button)
 {
 return mouseState[button - 1];
 }
 
 // Sets mouse key status.
 private void mouseKeyStatus(MouseEvent e, boolean status)
 {
 if(e.getButton() == MouseEvent.BUTTON1)
 mouseState[0] = status;
 else if(e.getButton() == MouseEvent.BUTTON2)
 mouseState[1] = status;
 else if(e.getButton() == MouseEvent.BUTTON3)
 mouseState[2] = status;
 }
 
 // Methods of the mouse listener.
 @Override
 public void mousePressed(MouseEvent e)
 {
 mouseKeyStatus(e, true);
 }
 
 @Override
 public void mouseReleased(MouseEvent e)
 {
 mouseKeyStatus(e, false);
 }
 
 @Override
 public void mouseClicked(MouseEvent e) { }
 
 @Override
 public void mouseEntered(MouseEvent e) { }
 
 @Override
 public void mouseExited(MouseEvent e) { }
 
}
  • Buat Class Framework.java. 
package com.company;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 * Framework that controls the game (Game.java) that created it, update it and draw it on the screen.
 * 
 * @author thinksmart
 */

public class Framework extends Canvas {
 
 /**
 * Width of the frame.
 */
 public static int frameWidth;
 /**
 * Height of the frame.
 */
 public static int frameHeight;

 /**
 * Time of one second in nanoseconds.
 * 1 second = 1 000 000 000 nanoseconds
 */
 public static final long secInNanosec = 1000000000L;
 
 /**
 * Time of one millisecond in nanoseconds.
 * 1 millisecond = 1 000 000 nanoseconds
 */
 public static final long milisecInNanosec = 1000000L;
 
 /**
 * FPS - Frames per second
 * How many times per second the game should update?
 */
 private final int GAME_FPS = 60;
 /**
 * Pause between updates. It is in nanoseconds.
 */
 private final long GAME_UPDATE_PERIOD = secInNanosec / GAME_FPS;
 
 /**
 * Possible states of the game
 */
 public static enum GameState{STARTING, VISUALIZING, GAME_CONTENT_LOADING, MAIN_MENU, OPTIONS, PLAYING, GAMEOVER, DESTROYED}
 /**
 * Current state of the game
 */
 public static GameState gameState;
 
 /**
 * Elapsed game time in nanoseconds.
 */
 private long gameTime;
 // It is used for calculating elapsed time.
 private long lastTime;
 
 // The actual game
 private Game game;
 
 
 /**
 * Image for menu.
 */
 private BufferedImage shootTheDuckMenuImg; 
 
 
 public Framework ()
 {
 super();
 
 gameState = GameState.VISUALIZING;
 
 //We start game in new thread.
 Thread gameThread = new Thread() {
 @Override
 public void run(){
 try {
 GameLoop();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 };
 gameThread.start();
 }
 
 
 /**
 * Set variables and objects.
 * This method is intended to set the variables and objects for this class, variables and objects for the actual game can be set in Game.java.
 */
 private void Initialize()
 {

 }
 
 /**
 * Load files - images, sounds, ...
 * This method is intended to load files for this class, files for the actual game can be loaded in Game.java.
 */
 private void LoadContent() throws IOException {
 URL shootTheDuckMenuImgUrl = this.getClass().getResource("/resources/menu.jpg");
 shootTheDuckMenuImg = ImageIO.read(shootTheDuckMenuImgUrl);
 }
 
 /**
 * In specific intervals of time (GAME_UPDATE_PERIOD) the game/logic is updated and then the game is drawn on the screen.
 */
 private void GameLoop() throws IOException {
 // This two variables are used in VISUALIZING state of the game. We used them to wait some time so that we get correct frame/window resolution.
 long visualizingTime = 0, lastVisualizingTime = System.nanoTime();
 
 // This variables are used for calculating the time that defines for how long we should put threat to sleep to meet the GAME_FPS.
 long beginTime, timeTaken, timeLeft;
 
 while(true)
 {
 beginTime = System.nanoTime();
 
 switch (gameState)
 {
 case PLAYING:
 gameTime += System.nanoTime() - lastTime;
 
 game.UpdateGame(gameTime, mousePosition());
 
 lastTime = System.nanoTime();
 break;
 case GAMEOVER:
 //...
 break;
 case MAIN_MENU:
 //...
 break;
 case OPTIONS:
 //...
 break;
 case GAME_CONTENT_LOADING:
 //...
 break;
 case STARTING:
 // Sets variables and objects.
 Initialize();
 // Load files - images, sounds, ...
 LoadContent();

 // When all things that are called above finished, we change game status to main menu.
 gameState = GameState.MAIN_MENU;
 break;
 case VISUALIZING:
 // On Ubuntu OS (when I tested on my old computer) this.getWidth() method doesn't return the correct value immediately (eg. for frame that should be 800px width, returns 0 than 790 and at last 798px). 
 // So we wait one second for the window/frame to be set to its correct size. Just in case we
 // also insert 'this.getWidth() > 1' condition in case when the window/frame size wasn't set in time,
 // so that we although get approximately size.
 if(this.getWidth() > 1 && visualizingTime > secInNanosec)
 {
 frameWidth = this.getWidth();
 frameHeight = this.getHeight();

 // When we get size of frame we change status.
 gameState = GameState.STARTING;
 }
 else
 {
 visualizingTime += System.nanoTime() - lastVisualizingTime;
 lastVisualizingTime = System.nanoTime();
 }
 break;
 }
 
 // Repaint the screen.
 repaint();
 
 // Here we calculate the time that defines for how long we should put threat to sleep to meet the GAME_FPS.
 timeTaken = System.nanoTime() - beginTime;
 timeLeft = (GAME_UPDATE_PERIOD - timeTaken) / milisecInNanosec; // In milliseconds
 // If the time is less than 10 milliseconds, then we will put thread to sleep for 10 millisecond so that some other thread can do some work.
 if (timeLeft < 10) 
 timeLeft = 10; //set a minimum
 try {
 //Provides the necessary delay and also yields control so that other thread can do work.
 Thread.sleep(timeLeft);
 } catch (InterruptedException ex) { }
 }
 }
 
 /**
 * Draw the game to the screen. It is called through repaint() method in GameLoop() method.
 */
 @Override
 public void Draw(Graphics2D g2d)
 {
 switch (gameState)
 {
 case PLAYING:
 game.Draw(g2d, mousePosition());
 break;
 case GAMEOVER:
 game.DrawGameOver(g2d, mousePosition());
 break;
 case MAIN_MENU:
 g2d.drawImage(shootTheDuckMenuImg, 0, 0, frameWidth, frameHeight, null);
 g2d.drawString("Use left mouse button to shot the duck.", frameWidth / 2 - 83, (int)(frameHeight * 0.65)); 
 g2d.drawString("Click with left mouse button to start the game.", frameWidth / 2 - 100, (int)(frameHeight * 0.67)); 
 g2d.drawString("Press ESC any time to exit the game.", frameWidth / 2 - 75, (int)(frameHeight * 0.70));
 g2d.setColor(Color.white);
 g2d.drawString("WWW.GAMETUTORIAL.NET", 7, frameHeight - 5);
 break;
 case OPTIONS:
 //...
 break;
 case GAME_CONTENT_LOADING:
 g2d.setColor(Color.white);
 g2d.drawString("GAME is LOADING", frameWidth / 2 - 50, frameHeight / 2);
 break;
 }
 }
 
 /**
 * Starts new game.
 */
 private void newGame()
 {
 // We set gameTime to zero and lastTime to current time for later calculations.
 gameTime = 0;
 lastTime = System.nanoTime();
 
 game = new Game();
 }
 
 /**
 * Restart game - reset game time and call RestartGame() method of game object so that reset some variables.
 */
 private void restartGame()
 {
 // We set gameTime to zero and lastTime to current time for later calculations.
 gameTime = 0;
 lastTime = System.nanoTime();
 
 game.RestartGame();
 
 // We change game status so that the game can start.
 gameState = GameState.PLAYING;
 }
 
 /**
 * Returns the position of the mouse pointer in game frame/window.
 * If mouse position is null than this method return 0,0 coordinate.
 * 
 * @return Point of mouse coordinates.
 */
 private Point mousePosition()
 {
 try
 {
 Point mp = this.getMousePosition();
 
 if(mp != null)
 return this.getMousePosition();
 else
 return new Point(0, 0);
 }
 catch (Exception e)
 {
 return new Point(0, 0);
 }
 }
 
 /**
 * This method is called when keyboard key is released.
 * 
 * @param e KeyEvent
 */
 @Override
 public void keyReleasedFramework(KeyEvent e)
 {
 switch (gameState)
 {
 case GAMEOVER:
 if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
 System.exit(0);
 else if(e.getKeyCode() == KeyEvent.VK_SPACE || e.getKeyCode() == KeyEvent.VK_ENTER)
 restartGame();
 break;
 case PLAYING:
 case MAIN_MENU:
 if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
 System.exit(0);
 break;
 }
 }
 
 /**
 * This method is called when mouse button is clicked.
 * 
 * @param e MouseEvent
 */
 @Override
 public void mouseClicked(MouseEvent e)
 {
 switch (gameState)
 {
 case MAIN_MENU:
 if(e.getButton() == MouseEvent.BUTTON1)
 newGame();
 break;
 }
 }
}
  • Buat Class Game.java. 
package com.company;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 * Actual game.
 * 
 * @author thinksmart
 */

public class Game {
 
 /**
 * We use this to generate a random number.
 */
 private Random random;
 
 /**
 * Font that we will use to write statistic to the screen.
 */
 private Font font;
 
 /**
 * Array list of the ducks.
 */
 private ArrayList<Duck> ducks;
 
 /**
 * How many ducks leave the screen alive?
 */
 private int runawayDucks;
 
 /**
 * How many ducks the player killed?
 */
 private int killedDucks;
 
 /**
 * For each killed duck, the player gets points.
 */
 private int score;
 
 /**
 * How many times a player is shot?
 */
 private int shoots;
 
 /**
 * Last time of the shoot.
 */
 private long lastTimeShoot; 
 /**
 * The time which must elapse between shots.
 */
 private long timeBetweenShots;

 /**
 * Game background image.
 */
 private BufferedImage backgroundImg;
 
 /**
 * Bottom grass.
 */
 private BufferedImage grassImg;
 
 /**
 * Duck image.
 */
 private BufferedImage duckImg;
 
 /**
 * Shotgun sight image.
 */
 private BufferedImage sightImg;
 
 /**
 * Middle width of the sight image.
 */
 private int sightImgMiddleWidth;
 /**
 * Middle height of the sight image.
 */
 private int sightImgMiddleHeight;
 

 public Game()
 {
 Framework.gameState = Framework.GameState.GAME_CONTENT_LOADING;
 
 Thread threadForInitGame = new Thread() {
 @Override
 public void run(){
 // Sets variables and objects for the game.
 Initialize();
 // Load game files (images, sounds, ...)
 LoadContent();
 
 Framework.gameState = Framework.GameState.PLAYING;
 }
 };
 threadForInitGame.start();
 }
 
 
 /**
 * Set variables and objects for the game.
 */
 private void Initialize()
 {
 random = new Random(); 
 font = new Font("monospaced", Font.BOLD, 18);
 
 ducks = new ArrayList<Duck>();
 
 runawayDucks = 0;
 killedDucks = 0;
 score = 0;
 shoots = 0;
 
 lastTimeShoot = 0;
 timeBetweenShots = Framework.secInNanosec / 3;
 }
 
 /**
 * Load game files - images, sounds, ...
 */
 private void LoadContent()
 {
 try
 {
 URL backgroundImgUrl = this.getClass().getResource("/resources/background.jpg");
 backgroundImg = ImageIO.read(backgroundImgUrl);
 
 URL grassImgUrl = this.getClass().getResource("/resources/grass.png");
 grassImg = ImageIO.read(grassImgUrl);
 
 URL duckImgUrl = this.getClass().getResource("/resources/duck.png");
 duckImg = ImageIO.read(duckImgUrl);
 
 URL sightImgUrl = this.getClass().getResource("/resources/sight.png");
 sightImg = ImageIO.read(sightImgUrl);
 sightImgMiddleWidth = sightImg.getWidth() / 2;
 sightImgMiddleHeight = sightImg.getHeight() / 2;
 }
 catch (IOException ex) {
 Logger.getLogger(Game.class.getName()).log(Level.SEVERE, null, ex);
 }
 }
 
 
 /**
 * Restart game - reset some variables.
 */
 public void RestartGame()
 {
 // Removes all of the ducks from this list.
 ducks.clear();
 
 // We set last duckt time to zero.
 Duck.lastDuckTime = 0;
 
 runawayDucks = 0;
 killedDucks = 0;
 score = 0;
 shoots = 0;
 
 lastTimeShoot = 0;
 }
 
 
 /**
 * Update game logic.
 * 
 * @param gameTime gameTime of the game.
 * @param mousePosition current mouse position.
 */
 public void UpdateGame(long gameTime, Point mousePosition)
 {
 // Creates a new duck, if it's the time, and add it to the array list.
 if(System.nanoTime() - Duck.lastDuckTime >= Duck.timeBetweenDucks)
 {
 // Here we create new duck and add it to the array list.
 ducks.add(new Duck(Duck.duckLines[Duck.nextDuckLines][0] + random.nextInt(200), Duck.duckLines[Duck.nextDuckLines][1], Duck.duckLines[Duck.nextDuckLines][2], Duck.duckLines[Duck.nextDuckLines][3], duckImg));
 
 // Here we increase nextDuckLines so that next duck will be created in next line.
 Duck.nextDuckLines++;
 if(Duck.nextDuckLines >= Duck.duckLines.length)
 Duck.nextDuckLines = 0;
 
 Duck.lastDuckTime = System.nanoTime();
 }
 
 // Update all of the ducks.
 for(int i = 0; i < ducks.size(); i++)
 {
 // Move the duck.
 ducks.get(i).Update();
 
 // Checks if the duck leaves the screen and remove it if it does.
 if(ducks.get(i).x < 0 - duckImg.getWidth())
 {
 ducks.remove(i);
 runawayDucks++;
 }
 }
 
 // Does player shoots?
 if(Canvas.mouseButtonState(MouseEvent.BUTTON1))
 {
 // Checks if it can shoot again.
 if(System.nanoTime() - lastTimeShoot >= timeBetweenShots)
 {
 shoots++;
 
 // We go over all the ducks and we look if any of them was shoot.
 for(int i = 0; i < ducks.size(); i++)
 {
 // We check, if the mouse was over ducks head or body, when player has shot.
 if(new Rectangle(ducks.get(i).x + 18, ducks.get(i).y , 27, 30).contains(mousePosition) ||
 new Rectangle(ducks.get(i).x + 30, ducks.get(i).y + 30, 88, 25).contains(mousePosition))
 {
 killedDucks++;
 score += ducks.get(i).score;
 
 // Remove the duck from the array list.
 ducks.remove(i);
 
 // We found the duck that player shoot so we can leave the for loop.
 break;
 }
 }
 
 lastTimeShoot = System.nanoTime();
 }
 }
 
 // When 200 ducks runaway, the game ends.
 if(runawayDucks >= 200)
 Framework.gameState = Framework.GameState.GAMEOVER;
 }
 
 /**
 * Draw the game to the screen.
 * 
 * @param g2d Graphics2D
 * @param mousePosition current mouse position.
 */
 public void Draw(Graphics2D g2d, Point mousePosition)
 {
 g2d.drawImage(backgroundImg, 0, 0, Framework.frameWidth, Framework.frameHeight, null);
 
 // Here we draw all the ducks.
 for(int i = 0; i < ducks.size(); i++)
 {
 ducks.get(i).Draw(g2d);
 }
 
 g2d.drawImage(grassImg, 0, Framework.frameHeight - grassImg.getHeight(), Framework.frameWidth, grassImg.getHeight(), null);
 
 g2d.drawImage(sightImg, mousePosition.x - sightImgMiddleWidth, mousePosition.y - sightImgMiddleHeight, null);
 
 g2d.setFont(font);
 g2d.setColor(Color.darkGray);
 
 g2d.drawString("RUNAWAY: " + runawayDucks, 10, 21);
 g2d.drawString("KILLS: " + killedDucks, 160, 21);
 g2d.drawString("SHOOTS: " + shoots, 299, 21);
 g2d.drawString("SCORE: " + score, 440, 21);
 }
 
 
 /**
 * Draw the game over screen.
 * 
 * @param g2d Graphics2D
 * @param mousePosition Current mouse position.
 */
 public void DrawGameOver(Graphics2D g2d, Point mousePosition)
 {
 Draw(g2d, mousePosition);
 
 // The first text is used for shade.
 g2d.setColor(Color.black);
 g2d.drawString("Game Over", Framework.frameWidth / 2 - 39, (int)(Framework.frameHeight * 0.65) + 1);
 g2d.drawString("Press space or enter to restart.", Framework.frameWidth / 2 - 149, (int)(Framework.frameHeight * 0.70) + 1);
 g2d.setColor(Color.red);
 g2d.drawString("Game Over", Framework.frameWidth / 2 - 40, (int)(Framework.frameHeight * 0.65));
 g2d.drawString("Press space or enter to restart.", Framework.frameWidth / 2 - 150, (int)(Framework.frameHeight * 0.70));
 }
}
  • Untuk menjalankan Game buka  Class Window.java -> Klik kanan -> Run As Main Application. 

Screenshot from 2014-10-02 23:04:24

Keep Learn, Have fun Coding!!

Advertisements