Java 2D Game 2019/4/25 Java 2D Game Tutorial - - PowerPoint PPT Presentation

java 2d game
SMART_READER_LITE
LIVE PREVIEW

Java 2D Game 2019/4/25 Java 2D Game Tutorial - - PowerPoint PPT Presentation

Poly- mor- phism Abstra ction Class OOP Inheri -tance En- capsu- lation Kuan-Ting Lai Java 2D Game 2019/4/25 Java 2D Game Tutorial http://zetcode.com/tutorials/javagamestutorial/ 2 Running Examples from Zetcode Download


slide-1
SLIDE 1

Java 2D Game

Kuan-Ting Lai 2019/4/25

OOP

Class Abstra ction Inheri

  • tance

En- capsu- lation Poly- mor- phism

slide-2
SLIDE 2

Java 2D Game Tutorial

  • http://zetcode.com/tutorials/javagamestutorial/

2

slide-3
SLIDE 3

Running Examples from Zetcode

  • Download images

− http://zetcode.com/img/gfx/javagames/images.zip

  • The example codes are packaged by the command

− package com.zetcode;

  • To compile and run the code, you need to
  • 1. Build folder “com/zetcode”
  • 2. Put the source codes in the folder above
  • 3. javac com/zetcode/*.java
  • 4. java com.zetcode.ImageExample

3

slide-4
SLIDE 4

Using JPanel to Display Screen

  • Create class Board, which inherits from JPanel

4

import import javax.swing.JPanel; public public class class Board extends extends JPanel { public public Board() {} }

slide-5
SLIDE 5

Creating main()

  • Using EventQueue
  • Swing processing is done in a

thread called EDT (Event Dispatching Thread)

  • EventQueue.invokeLater()

posts an event (your Runnable) at the end of Swings event list and is processed after all previous GUI events are processed.

5

import import java.awt.EventQueue; import import javax.swing.JFrame; public class public class Application extends extends JFrame { public public Application() { add(new new Board()); setSize(250, 200); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE EXIT_ON_CLOSE); setLocationRelativeTo(null null); } public static void public static void main(String[] args) { EventQueue.invokeLater(() -> { Application ex = new new Application(); ex.setVisible(true true); }); } } https://stackoverflow.com/questions/22534356/java-awt-eventqueue-invokelater-explained

slide-6
SLIDE 6

Drawing a Donut

6

slide-7
SLIDE 7

Updating Board.java

  • Override paintComponent(Graphics g)

7

import import java.awt.BasicStroke; import import java.awt.Color; import import java.awt.Dimension; import import java.awt.Graphics; import import java.awt.Graphics2D; import import java.awt.RenderingHints; import import java.awt.geom.AffineTransform; import import java.awt.geom.Ellipse2D; import import javax.swing.JPanel; public class public class Board extends extends JPanel { @Override public void public void paintComponent(Graphics g) { super super.paintComponent(g); drawDonut(g); } private void private void drawDonut(Graphics g) {…} }

slide-8
SLIDE 8

drawDonut(Graphics g)

8

privat private void e void drawDonut(Graphics g) { Graphics2D g2d = (Graphics2D) g; Dimension size = getSize(); double double w = size.getWidth(); double double h = size.getHeight(); Ellipse2D e = new new Ellipse2D.Double(0, 0, 80, 130); g2d.setStroke(new new BasicStroke(1)); g2d.setColor(Color.gray gray); for for (dou double ble deg = 0; deg < 360; deg += 5) { AffineTransform at = AffineTransform.getTranslateInstance(w/2, h/2); at.rotate(Math.toRadians(deg)); g2d.draw(at.createTransformedShape(e)); } }

slide-9
SLIDE 9

Drawing an Image

9

slide-10
SLIDE 10

10

import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import javax.swing.ImageIcon; import javax.swing.JPanel; public class Board extends JPanel { private Image bardejov; public Board() { initBoard(); } private void initBoard() { loadImage(); int int w = bardejov.getWidth(this); int int h = bardejov.getHeight(this this); setPreferredSize(new Dimension(w, h)); } private void loadImage() { ImageIcon ii = new new ImageIcon("src/resources/beach-walking-family.jpg"); bardejov = ii.getImage(); } @Override public void paintComponent(Graphics g) { g.drawImage(bardejov, 0, 0, null null); } }

slide-11
SLIDE 11

Animation

  • http://zetcode.com/tutorials/javagamestutorial/animation/
  • Showing a moving star

11

slide-12
SLIDE 12

Board.java (2-1)

  • implements ActionListener
  • Create a timer
  • @Override

void actionPerformed(ActionEvent e)

12

public class Board extends JPanel implements ActionListener { private final int B_WIDTH = 350; private final int B_HEIGHT = 350; private final int INITIAL_X = -40; private final int INITIAL_Y = -40; private final int DELAY = 25; private Image star; private Timer timer; private int x, y; public Board() { initBoard(); } private void loadImage() { ImageIcon ii = new ImageIcon("src/resources/star.png"); star = ii.getImage(); } private void initBoard() {…} @Override public void paintComponent(Graphics g) { super.paintComponent(g); drawStar(g); } private void drawStar(Graphics g) {…} @Override public void actionPerformed(ActionEvent e) {…} }

slide-13
SLIDE 13

Board.java (2-2)

  • Call drawStar(…) in

paintComponent(…)

  • Call repaint() to refresh the display

13

public class Board extends JPanel implements ActionListener { …… public Board() {…} private void loadImage() {…} private void initBoard() { setBackground(Color.BLACK); setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT)); loadImage(); x = INITIAL_X; y = INITIAL_Y; timer = new Timer(DELAY, this); timer.start(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(star, x, y, this); } @Override public void actionPerformed(ActionEvent e) { x += 1; y += 1; if (y > B_HEIGHT) { y = INITIAL_Y; x = INITIAL_X; } repaint(); } }

slide-14
SLIDE 14

Moving Sprites

14

slide-15
SLIDE 15

Moving Sprites

15

slide-16
SLIDE 16

Moving Sprite Example

  • http://zetcode.com/tutorials/javagamestutorial/movingsprites/

16

slide-17
SLIDE 17

SpaceShip

  • Three important functions

− move() − keyPressed(KeyEvent e) − keyReleased(KeyEvent e)

17 import ... public class SpaceShip { public int x = 40; public int y = 60; public int w; public int h; private int dx; private int dy; private Image image; public SpaceShip() { loadImage();} private void loadImage() {…} public Image getImage() { return image;} public void move() { x += dx; y += dy; } public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_LEFT: dx = -2; break; case KeyEvent.VK_RIGHT: dx = 2; break; case KeyEvent.VK_UP: dy = -2; break; case KeyEvent.VK_DOWN: dy = 2; break; } } public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_LEFT: dx = 0; break; case KeyEvent.VK_RIGHT: dx = 0; break; case KeyEvent.VK_UP: dy = 0; break; case KeyEvent.VK_DOWN: dy = 0; break; } } }

slide-18
SLIDE 18

Inheriting KeyAdapter

  • Create a new private class TAdapter, which extends KeyAdaptor to
  • vewrite keyReleased and keyPressed events

18

private class TAdapter extends KeyAdapter { @Override public void keyReleased(KeyEvent e) { spaceShip.keyReleased(e); } @Override public void keyPressed(KeyEvent e) { spaceShip.keyPressed(e); } }

slide-19
SLIDE 19

public class Board extends JPanel implements ActionListener { private Timer timer; private SpaceShip spaceShip; private final int DELAY = 10; public Board() { addKeyListener(new TAdapter()); setBackground(Color.black); setFocusable(true); spaceShip = new SpaceShip(); timer = new Timer(DELAY, this); timer.start(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.drawImage(spaceShip.getImage(), spaceShip.x, spaceShip.y, this); } @Override public void actionPerformed(ActionEvent e) { step(); } private void step() { spaceShip.move(); repaint(spaceShip.x-1, spaceShip.y-1, spaceShip.w+2, spaceShip.h+2); } private class TAdapter extends KeyAdapter {……} }

Board.java

19

slide-20
SLIDE 20

MovingSpriteEx

20

public class MovingSpriteEx extends JFrame { public MovingSpriteEx() { initUI(); } private void initUI() { add(new Board()); setTitle("Moving sprite"); setSize(800, 600); setLocationRelativeTo(null); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public static void main(String[] args) { EventQueue.invokeLater(() -> { MovingSpriteEx ex = new MovingSpriteEx(); ex.setVisible(true); }); } }

slide-21
SLIDE 21

Collision Detection

21

slide-22
SLIDE 22

SpaceShip, Alien, Missile

22

Sprite

# x: int # y: int # width: int # height: int # visible: boolean # image: Image # loadImage(imageName: String) # getImageDimensions() + isVisible() : boolean + setVisible(visible: boolean) + getBounds(): Rectangle

SpaceShip

  • dx: int
  • dy: int
  • missiles: List<Missile>

+ move() + fire() + getMissiles() : List<Missile> + keyPressed(KeyEvent e) + keyReleased(KeyEvent e)

Missile

  • BOARD_WIDTH: int
  • MISSILE_SPEED: int

+ move()

Alien

  • INITIAL_X: int

+ Alien(x: int, y: int)

  • initAlien()

+ move()

slide-23
SLIDE 23

SpaceShip

  • Add list of missiles

− List<Missile> missiles

  • Fire missiles

− missiles missiles.add(new new Missile(x x + width width, y y + height height / 2));

23

import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.List; public class SpaceShip extends Sprite { private int dx dx; private int dy dy; private List<Missile> missiles; public SpaceShip(int x, int y) { super(x, y); initCraft(); } private void initCraft() { missiles = new ArrayList<>(); loadImage("src/resources/craft.png"); getImageDimensions(); } public List<Missile> getMissiles() { return missiles; } public void fire() { missiles.add(new Missile(x x + width, y y + height / 2)); } public void move() {...} public void keyPressed(KeyEvent e) {...} public void keyReleased(KeyEvent e) {...} }

slide-24
SLIDE 24

Missile

  • Set default speed

− MISSILE_SPEED = 2

  • Move the missile

24

public class public class Missile extends extends Sprite { private final int private final int BOARD_WIDTH BOARD_WIDTH = 390; private final int private final int MISSILE_SPEED MISSILE_SPEED = 2; public public Missile(int int x, int int y) { super super(x, y); initMissile(); } private void private void initMissile() { loadImage("src src/resources/missile.png" /resources/missile.png"); getImageDimensions(); } public void public void move() { x x += MISSILE_SPEED MISSILE_SPEED; if if (x x > BOARD_WIDTH BOARD_WIDTH) visible visible = false false; } }

slide-25
SLIDE 25

Alien

  • Moving toward left constantly

25

public class public class Alien extends extends Sprite { private final int private final int INITIAL_X INITIAL_X = 400; public public Alien(int int x, int int y) { super super(x, y); initAlien(); } private void private void initAlien() { loadImage("src src/resources/alien.png" /resources/alien.png"); getImageDimensions(); } public void public void move() { if if (x x < 0) { x x = INITIAL_X INITIAL_X; } x x -= 1; } }

slide-26
SLIDE 26

Board

  • Initialize SpaceShip, Aliens
  • Draw objects

− updateShip() − updateMissiles() − updateAliens() − drawObjects()

  • Check collisions

− checkCollisions()

  • Check gameover

− inGame() − drawGameOver

26

Board

  • timer: Timer
  • spaceship: SpaceShip
  • ingame: Boolean
  • ICRAFT_X: int
  • ICRAFT_Y: int
  • DELAY: int
  • alien_pos: int[][]
  • TAdaptor: KeyAdaptor

+ Board() + initAlients() + paintComponent(Graphics g) + drawObjects(Graphics g) + drawGameOver(Graphics g) + actionPerformed(Action e) + inGame() + updateShip() + updateMissiles() + updateAliens() + checkCollisions

slide-27
SLIDE 27

Initializing Parameters

  • Assign aliens’ positions

− int[][] pos

27

public class Board extends JPanel implements ActionListener { private Timer timer; private SpaceShip spaceship; private List<Alien> aliens; private boolean ingame; private final int ICRAFT_X = 40; private final int ICRAFT_Y = 60; private final int B_WIDTH = 400; private final int B_HEIGHT = 300; private final int DELAY = 15; private final int[][] pos = { {2380, 29}, {2500, 59}, {1380, 89}, {780, 109}, {580, 139}, {680, 239}, {790, 259}, {760, 50}, {790, 150}, {980, 209}, {560, 45}, {510, 70}, {930, 159}, {590, 80}, {530, 60}, {940, 59}, {990, 30}, {920, 200}, {900, 259}, {660, 50}, {540, 90}, {810, 220}, {860, 20}, {740, 180}, {820, 128}, {490, 170}, {700, 30} }; … … }

slide-28
SLIDE 28

Board Initialization

  • Create Timer
  • Create SpaceShip and Aliens

28

…… public Board() { initBoard(); } private void initBoard() { addKeyListener(new TAdapter()); setFocusable(true true); setBackground(Color.BLACK); ingame = true; setPreferredSize(new new Dimension(B_WIDTH, B_HEIGHT)); spaceship = new new SpaceShip(ICRAFT_X, ICRAFT_Y); initAliens(); timer = new Timer(DELAY, this this); timer.start(); } public void initAliens() { aliens = new ArrayList<>(); for (int int[] p : pos pos) { aliens.add(new Alien(p[0], p[1])); } } ……

slide-29
SLIDE 29

29

…… @Override public void paintComponent(Graphics g) { super.paintComponent(g); if (ingame) { drawObjects(g); } else { drawGameOver(g); } Toolkit.getDefaultToolkit().sync(); } private void drawObjects(Graphics g) { if (spaceship.isVisible()) { g.drawImage(spaceship.getImage(), spaceship.getX(), spaceship.getY(), this); } List<Missile> ms = spaceship.getMissiles(); for (Missile missile : ms) { if (missile.isVisible()) { g.drawImage(missile.getImage(), missile.getX(), missile.getY(), this); } } for (Alien alien : aliens) { if (alien.isVisible()) { g.drawImage(alien.getImage(), alien.getX(), alien.getY(), this); } } g.setColor(Color.WHITE); g.drawString("Aliens left: " + aliens.size(), 5, 15); } ……

Drawing

slide-30
SLIDE 30

Drawing Game Over

30

private void private void drawGameOver(Graphics g) { String msg = "Game Over" "Game Over"; Font small = new new Font("Helvetica" "Helvetica", Font.BOLD BOLD, 14); FontMetrics fm = getFontMetrics(small); g.setColor(Color.white white); g.setFont(small); g.drawString(msg, (B_WIDTH B_WIDTH - fm.stringWidth(msg)) / 2, B_HEIGHT B_HEIGHT / 2); }

slide-31
SLIDE 31

Processing Timer Events

31

@Override public void public void actionPerformed(ActionEvent e) { inGame(); updateShip(); updateMissiles(); updateAliens(); checkCollisions(); repaint(); }

slide-32
SLIDE 32

Updating Objects

  • Update game status, ship, aliens,

and missiles

32 private void private void inGame() { if if (!ingame ingame) { timer timer.stop(); } } private void private void updateShip() { if if (spaceship spaceship.isVisible()) { spaceship spaceship.move(); } } private void private void updateMissiles() { List<Missile> ms = spaceship spaceship.getMissiles(); for for (int int i = 0; i < ms.size(); i++) { Missile m = ms.get(i); if if (m.isVisible()) { m.move(); } else else { ms.remove(i); } } } private void private void updateAliens() { if if (aliens aliens.isEmpty()) { ingame ingame = false false; return return; } for for (int int i = 0; i < aliens aliens.size(); i++) { Alien a = aliens aliens.get(i); if if (a.isVisible()) { a.move(); } else else { aliens aliens.remove(i); } } }

slide-33
SLIDE 33

Check Collisions

  • Check ship-alien collision
  • Check missile-alien collision

33

public void public void checkCollisions() { Rectangle r3 = spaceship spaceship.getBounds(); for for (Alien alien : aliens aliens) { Rectangle r2 = alien.getBounds(); if if (r3.intersects(r2)) { spaceship spaceship.setVisible(false false); alien.setVisible(false false); ingame ingame = false false; } } List<Missile> ms = spaceship spaceship.getMissiles(); for for (Missile m : ms) { Rectangle r1 = m.getBounds(); for for (Alien alien : aliens aliens) { Rectangle r2 = alien.getBounds(); if if (r1.intersects(r2)) { m.setVisible(false false); alien.setVisible(false false); } } } }

slide-34
SLIDE 34

Keyboard Events

34

private class private class TAdapter extends extends KeyAdapter { @Override public void public void keyReleased(KeyEvent e) { spaceship spaceship.keyReleased(e); } @Override public void public void keyPressed(KeyEvent e) { spaceship spaceship.keyPressed(e); } }

slide-35
SLIDE 35

Reference

  • http://zetcode.com/tutorials/javagamestutorial/

35