Java Gnome FAQ Nibbles

Материал из Wiki.crossplatform.ru

(Различия между версиями)
Перейти к: навигация, поиск
(нарушало авторские права)
 
Строка 1: Строка 1:
-
In this part of the Java Gnome programming tutorial, we will create a Nibbles game clone.
 
-
__TOC__
 
-
 
-
== Nibbles ==
 
-
 
-
<b>Nibbles</b> is an older classic video game. It was first created in late 70s.
 
-
Later it was brought to PCs. In this game the player controls a snake. The objective is to eat as many apples as possible.
 
-
Each time the snake eats an apple, its body grows. The snake must avoid the  walls and its own body.
 
-
 
-
== Development ==
 
-
 
-
The size of each of the joints of a snake is 10px. The snake is controlled  with the cursor keys. Initially, the snake has three joints. The game starts immediately. When the game is finished, we display "Game Over" message in the statusbar widget.
 
-
 
-
<source lang="java">
 
-
package com.zetcode;
 
-
 
-
import java.io.FileNotFoundException;
 
-
 
-
import java.util.Timer;
 
-
import java.util.TimerTask;
 
-
 
-
import org.freedesktop.cairo.Context;
 
-
 
-
import org.gnome.gdk.Color;
 
-
import org.gnome.gdk.EventExpose;
 
-
import org.gnome.gdk.EventKey;
 
-
import org.gnome.gdk.Keyval;
 
-
import org.gnome.gdk.ModifierType;
 
-
import org.gnome.gdk.Pixbuf;
 
-
import org.gnome.gtk.DrawingArea;
 
-
import org.gnome.gtk.Justification;
 
-
import org.gnome.gtk.Label;
 
-
import org.gnome.gtk.StateType;
 
-
import org.gnome.gtk.Widget;
 
-
 
-
 
-
public class Board extends DrawingArea implements Widget.ExposeEvent {
 
-
 
-
    private final int WIDTH = 300;
 
-
    private final int HEIGHT = 300;
 
-
    private final int DOT_SIZE = 10;
 
-
    private final int ALL_DOTS = 900;
 
-
    private final int RAND_POS = 29;
 
-
    private final int DELAY = 140;
 
-
    private final int PERIOD = 80;
 
-
 
-
    private int x[] = new int[ALL_DOTS];
 
-
    private int y[] = new int[ALL_DOTS];
 
-
 
-
    private int dots;
 
-
    private int apple_x;
 
-
    private int apple_y;
 
-
 
-
    private boolean left = false;
 
-
    private boolean right = true;
 
-
    private boolean up = false;
 
-
    private boolean down = false;
 
-
    private boolean inGame = true;
 
-
 
-
    private Timer timer;
 
-
 
-
    private Pixbuf dot;
 
-
    private Pixbuf apple;
 
-
    private Pixbuf head;
 
-
   
 
-
    private Label statusbar;
 
-
 
-
    public Board(Label statusbar) {
 
-
       
 
-
        this.statusbar = statusbar;
 
-
 
-
        connect(new SnakeKeyListener());
 
-
 
-
        modifyBackground(StateType.NORMAL, Color.BLACK);
 
-
 
-
        try {
 
-
            dot = new Pixbuf("dot.png");
 
-
            apple = new Pixbuf("apple.png");
 
-
            head = new Pixbuf("head.png");
 
-
 
-
        } catch (FileNotFoundException e) {
 
-
            e.printStackTrace();
 
-
        }
 
-
 
-
        connect(this);
 
-
        setCanFocus(true);
 
-
 
-
        initGame();
 
-
    }
 
-
   
 
-
   
 
-
    public Timer getTimer() { return timer; }
 
-
 
-
 
-
    public void initGame() {
 
-
 
-
        dots = 3;
 
-
 
-
        for (int z = 0; z < dots; z++) {
 
-
            x[z] = 50 - z * 10;
 
-
            y[z] = 50;
 
-
        }
 
-
 
-
        locateApple();
 
-
 
-
        timer = new Timer();
 
-
        timer.scheduleAtFixedRate(new ScheduleTask(), DELAY, PERIOD);
 
-
 
-
    }
 
-
 
-
 
-
    public void drawObjects(Context cr) {
 
-
 
-
 
-
        if (inGame) {
 
-
 
-
            cr.setSource(apple, apple_x, apple_y);
 
-
            cr.paint();
 
-
 
-
            for (int z = 0; z < dots; z++) {
 
-
                if (z == 0) {
 
-
                    cr.setSource(head, x[z], y[z]);
 
-
                    cr.paint();
 
-
                } else {
 
-
                    cr.setSource(dot, x[z], y[z]);
 
-
                    cr.paint();
 
-
                }
 
-
            }
 
-
 
-
        } else {
 
-
            gameOver();
 
-
        }
 
-
    }
 
-
 
-
 
-
    public void gameOver() {
 
-
       
 
-
        timer.cancel();
 
-
 
-
        statusbar.setJustify(Justification.LEFT);
 
-
        statusbar.setAlignment(0f, 0.5f);
 
-
        statusbar.setLabel("Game Over");
 
-
    }
 
-
 
-
 
-
    public void checkApple() {
 
-
 
-
        if ((x[0] == apple_x) && (y[0] == apple_y)) {
 
-
            dots++;
 
-
            locateApple();
 
-
        }
 
-
    }
 
-
 
-
    public void move() {
 
-
 
-
        for (int z = dots; z > 0; z--) {
 
-
            x[z] = x[(z - 1)];
 
-
            y[z] = y[(z - 1)];
 
-
        }
 
-
 
-
        if (left) {
 
-
            x[0] -= DOT_SIZE;
 
-
        }
 
-
 
-
        if (right) {
 
-
            x[0] += DOT_SIZE;
 
-
        }
 
-
 
-
        if (up) {
 
-
            y[0] -= DOT_SIZE;
 
-
        }
 
-
 
-
        if (down) {
 
-
            y[0] += DOT_SIZE;
 
-
        }
 
-
    }
 
-
 
-
    public void checkCollision() {
 
-
 
-
        for (int z = dots; z > 0; z--) {
 
-
 
-
            if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
 
-
                inGame = false;
 
-
            }
 
-
        }
 
-
 
-
        if (y[0] > HEIGHT) {
 
-
            inGame = false;
 
-
        }
 
-
 
-
        if (y[0] < 0) {
 
-
            inGame = false;
 
-
        }
 
-
 
-
        if (x[0] > WIDTH) {
 
-
            inGame = false;
 
-
        }
 
-
 
-
        if (x[0] < 0) {
 
-
            inGame = false;
 
-
        }
 
-
    }
 
-
 
-
    public void locateApple() {
 
-
        int r = (int) (Math.random() * RAND_POS);
 
-
        apple_x = ((r * DOT_SIZE));
 
-
        r = (int) (Math.random() * RAND_POS);
 
-
        apple_y = ((r * DOT_SIZE));
 
-
    }
 
-
 
-
    public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
 
-
   
 
-
        Context cr = new Context(widget.getWindow());
 
-
        drawObjects(cr);
 
-
       
 
-
        return false;
 
-
    }
 
-
 
-
 
-
    class ScheduleTask extends TimerTask {
 
-
 
-
        public void run() {
 
-
 
-
            if (inGame) {
 
-
                checkApple();
 
-
                checkCollision();
 
-
                move();
 
-
            }
 
-
            queueDraw();
 
-
        }
 
-
    }
 
-
 
-
    class SnakeKeyListener implements Widget.KeyPressEvent {
 
-
 
-
        public boolean onKeyPressEvent(Widget widget, EventKey eventKey) {
 
-
           
 
-
            final Keyval key;
 
-
            final ModifierType mod;
 
-
           
 
-
            key = eventKey.getKeyval();
 
-
            mod = eventKey.getState();
 
-
 
-
            if ((key == key.Left) && (!right)) {
 
-
                left = true;
 
-
                up = false;
 
-
                down = false;
 
-
            }
 
-
 
-
            if ((key == key.Right) && (!left)) {
 
-
                right = true;
 
-
                up = false;
 
-
                down = false;
 
-
            }
 
-
 
-
            if ((key == key.Up) && (!down)) {
 
-
                up = true;
 
-
                right = false;
 
-
                left = false;
 
-
            }
 
-
 
-
            if ((key == key.Down) && (!up)) {
 
-
                down = true;
 
-
                right = false;
 
-
                left = false;
 
-
            }
 
-
           
 
-
            return false;
 
-
        }
 
-
    }
 
-
}
 
-
 
-
</source>
 
-
 
-
First we will define some globals used in our game.
 
-
 
-
The <b>HEIGHT</b> constants determine the size of the Board. The <b>DOT_SIZE</b> is the size of the apple and the dot of the snake. The <b>ALL_DOTS</b> constant defines the maximum number of possible dots on the Board.
 
-
The <b>RAND_POS</b> constant is used to calculate a random position of an apple.
 
-
The <b>DELAY</b> constant determines the speed of the game.
 
-
 
-
<source lang="java">
 
-
private int x[] = new int[ALL_DOTS];
 
-
private int y[] = new int[ALL_DOTS];
 
-
</source>
 
-
 
-
These two arrays store x, y coordinates of all possible joints of a snake.
 
-
 
-
The <b>initGame()</b> method initializes variables, loads images and starts a timeout function.
 
-
 
-
In the <b>move()</b> method we have the key algorithm of the game.
 
-
To understand it, look at how the snake is moving. You control the head of the snake.
 
-
You can change its direction with the cursor keys. The rest of the joints move one position up the chain. The second joint moves where the first was, the third joint where the second was etc.
 
-
 
-
<source lang="java">
 
-
for (int z = dots; z > 0; z--) {
 
-
    x[z] = x[(z - 1)];
 
-
    y[z] = y[(z - 1)];
 
-
}
 
-
</source>
 
-
 
-
This code moves the joints up the chain.
 
-
 
-
<source lang="java">
 
-
if (left) {
 
-
    x[0] -= DOT_SIZE;
 
-
}
 
-
</source>
 
-
 
-
Move the head to the left.
 
-
 
-
In the <b>checkCollision()</b> method, we determine if the snake has hit itself or one of the walls.
 
-
 
-
<source lang="java">
 
-
 
-
for (int z = dots; z > 0; z--) {
 
-
    if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
 
-
        inGame = false;
 
-
    }
 
-
}
 
-
</source>
 
-
 
-
Finish the game, if the snake hits one of its joints with the head.
 
-
 
-
<source lang="java">
 
-
if (y[0] > HEIGHT) {
 
-
    inGame = false;
 
-
}
 
-
</source>
 
-
 
-
Finish the game, if the snake hits the bottom of the Board.
 
-
 
-
The <b>locateApple()</b> method locates an apple randomly on the form.
 
-
 
-
<source lang="java">
 
-
int r = (int) (Math.random() * RAND_POS);
 
-
</source>
 
-
 
-
We get a random number from 0 to RAND_POS - 1.
 
-
 
-
<source lang="java">
 
-
apple_x = ((r * DOT_SIZE));
 
-
...
 
-
apple_y = ((r * DOT_SIZE));
 
-
</source>
 
-
 
-
These line set the x, y coordinates of the apple object.
 
-
 
-
In the <b>onKeyPressEvent()</b> method of the Board class, we  deternime which keys the player hit.
 
-
 
-
<source lang="java">
 
-
if ((key == key.Left) && (!right)) {
 
-
    left = true;
 
-
    up = false;
 
-
    down = false;
 
-
}
 
-
</source>
 
-
 
-
If we hit the left cursor key, we set <b>left</b> variable to  true. This variable is used in the <b>move()</b> method to change coordinates of the snake object. Notice also, that when the snake is heading to the right, we cannot turn immediately to the left.
 
-
 
-
<source lang="java">
 
-
package com.zetcode;
 
-
 
-
import java.util.Timer;
 
-
 
-
import org.gnome.gdk.Event;
 
-
import org.gnome.gtk.Gtk;
 
-
import org.gnome.gtk.Label;
 
-
import org.gnome.gtk.VBox;
 
-
import org.gnome.gtk.Widget;
 
-
import org.gnome.gtk.Window;
 
-
import org.gnome.gtk.WindowPosition;
 
-
 
-
 
-
/**
 
-
* ZetCode Java Gnome tutorial
 
-
*
 
-
* This program creates a Nibbles game clone.
 
-
*
 
-
* @author jan bodnar
 
-
* website zetcode.com
 
-
* last modified March 2009
 
-
*/
 
-
 
-
public class GNibbles extends Window {
 
-
 
-
    Board board;
 
-
    Label statusbar;
 
-
 
-
    public GNibbles() {
 
-
   
 
-
        setTitle("Nibbles");
 
-
       
 
-
        initUI();
 
-
       
 
-
        setDefaultSize(320, 320);
 
-
        setPosition(WindowPosition.CENTER);
 
-
       
 
-
        showAll();
 
-
    }
 
-
   
 
-
    public void initUI() {
 
-
   
 
-
        VBox vbox = new VBox(false, 0);
 
-
   
 
-
        statusbar = new Label("");
 
-
        board = new Board(statusbar);
 
-
       
 
-
        vbox.packStart(board);
 
-
        vbox.packStart(statusbar, false, false, 0);
 
-
       
 
-
        add(vbox);
 
-
       
 
-
        connect(new Window.DeleteEvent() {
 
-
            public boolean onDeleteEvent(Widget source, Event event) {
 
-
                Timer timer = board.getTimer();
 
-
                timer.cancel();
 
-
                Gtk.mainQuit();
 
-
                return false;
 
-
            }
 
-
        });
 
-
    }
 
-
 
-
    public static void main(String[] args)  {
 
-
        Gtk.init(args);
 
-
        new GNibbles();       
 
-
        Gtk.main();
 
-
    }
 
-
}
 
-
</source>
 
-
 
-
In this class, we set up the Nibbles game. Notice that we get the timer object from the board. This is to perform a clean exit.
 
-
 
-
[[image: Java_Gnome_faq_nibbles.png| center]]
 
-
 
-
This was the Nibbles computer game programmed using the Java Gnome programming library.
 
-
 
-
[[Категория:GTK+]]
 
-
[[Категория:Java]]
 

Текущая версия на 11:23, 7 апреля 2009