Dalam hal ini bagian dari permainan tutorial Java 2D, kita akan membuat game clone Java Sokoban.
Sokoban adalah permainan lain komputer klasik. Buku itu diciptakan pada tahun 1980 oleh Hiroyuki Imabayashi. Sokoban berarti penjaga gudang di Jepang. Pemain mendorong kotak sekitar labirin. Tujuannya adalah untuk menempatkan semua kotak di lokasi yang ditunjuk.
Development
Kami mengontrol objek sokoban dengan tombol kursor. Kami juga dapat menekan tombol R untuk me-restart tingkat. Ketika semua tas ditempatkan pada daerah tujuan, permainan selesai. Kami menggambar "Selesai" string di sudut kiri jendela.
Yang pertama anda lakukan adalah membuat class baru dengan nama
Board.java
package sokoban;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Board extends JPanel {
private final int OFFSET = 30;
private final int SPACE = 20;
private final int LEFT_COLLISION = 1;
private final int RIGHT_COLLISION = 2;
private final int TOP_COLLISION = 3;
private final int BOTTOM_COLLISION = 4;
private ArrayList walls = new ArrayList();
private ArrayList baggs = new ArrayList();
private ArrayList areas = new ArrayList();
private Player soko;
private int w = 0;
private int h = 0;
private boolean completed = false;
private String level =
" ######\n"
+ " ## #\n"
+ " ##$ #\n"
+ " #### $##\n"
+ " ## $ $ #\n"
+ "#### # ## # ######\n"
+ "## # ## ##### ..#\n"
+ "## $ $ ..#\n"
+ "###### ### #@## ..#\n"
+ " ## #########\n"
+ " ########\n";
public Board() {
addKeyListener(new TAdapter());
setFocusable(true);
initWorld();
}
public int getBoardWidth() {
return this.w;
}
public int getBoardHeight() {
return this.h;
}
public final void initWorld() {
int x = OFFSET;
int y = OFFSET;
Wall wall;
Baggage b;
Area a;
for (int i = 0; i < level.length(); i++) {
char item = level.charAt(i);
if (item == '\n') {
y += SPACE;
if (this.w < x) {
this.w = x;
}
x = OFFSET;
} else if (item == '#') {
wall = new Wall(x, y);
walls.add(wall);
x += SPACE;
} else if (item == '$') {
b = new Baggage(x, y);
baggs.add(b);
x += SPACE;
} else if (item == '.') {
a = new Area(x, y);
areas.add(a);
x += SPACE;
} else if (item == '@') {
soko = new Player(x, y);
x += SPACE;
} else if (item == ' ') {
x += SPACE;
}
h = y;
}
}
public void buildWorld(Graphics g) {
g.setColor(new Color(250, 240, 170));
g.fillRect(0, 0, this.getWidth(), this.getHeight());
ArrayList world = new ArrayList();
world.addAll(walls);
world.addAll(areas);
world.addAll(baggs);
world.add(soko);
for (int i = 0; i < world.size(); i++) {
Actor item = (Actor) world.get(i);
if ((item instanceof Player)
|| (item instanceof Baggage)) {
g.drawImage(item.getImage(), item.x() + 2, item.y() + 2, this);
} else {
g.drawImage(item.getImage(), item.x(), item.y(), this);
}
if (completed) {
g.setColor(new Color(0, 0, 0));
g.drawString("Completed", 25, 20);
}
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
buildWorld(g);
}
class TAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
if (completed) {
return;
}
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
if (checkWallCollision(soko,
LEFT_COLLISION)) {
return;
}
if (checkBagCollision(LEFT_COLLISION)) {
return;
}
soko.move(-SPACE, 0);
} else if (key == KeyEvent.VK_RIGHT) {
if (checkWallCollision(soko,
RIGHT_COLLISION)) {
return;
}
if (checkBagCollision(RIGHT_COLLISION)) {
return;
}
soko.move(SPACE, 0);
} else if (key == KeyEvent.VK_UP) {
if (checkWallCollision(soko,
TOP_COLLISION)) {
return;
}
if (checkBagCollision(TOP_COLLISION)) {
return;
}
soko.move(0, -SPACE);
} else if (key == KeyEvent.VK_DOWN) {
if (checkWallCollision(soko,
BOTTOM_COLLISION)) {
return;
}
if (checkBagCollision(BOTTOM_COLLISION)) {
return;
}
soko.move(0, SPACE);
} else if (key == KeyEvent.VK_R) {
restartLevel();
}
repaint();
}
}
private boolean checkWallCollision(Actor actor, int type) {
if (type == LEFT_COLLISION) {
for (int i = 0; i < walls.size(); i++) {
Wall wall = (Wall) walls.get(i);
if (actor.isLeftCollision(wall)) {
return true;
}
}
return false;
} else if (type == RIGHT_COLLISION) {
for (int i = 0; i < walls.size(); i++) {
Wall wall = (Wall) walls.get(i);
if (actor.isRightCollision(wall)) {
return true;
}
}
return false;
} else if (type == TOP_COLLISION) {
for (int i = 0; i < walls.size(); i++) {
Wall wall = (Wall) walls.get(i);
if (actor.isTopCollision(wall)) {
return true;
}
}
return false;
} else if (type == BOTTOM_COLLISION) {
for (int i = 0; i < walls.size(); i++) {
Wall wall = (Wall) walls.get(i);
if (actor.isBottomCollision(wall)) {
return true;
}
}
return false;
}
return false;
}
private boolean checkBagCollision(int type) {
if (type == LEFT_COLLISION) {
for (int i = 0; i < baggs.size(); i++) {
Baggage bag = (Baggage) baggs.get(i);
if (soko.isLeftCollision(bag)) {
for (int j=0; j < baggs.size(); j++) {
Baggage item = (Baggage) baggs.get(j);
if (!bag.equals(item)) {
if (bag.isLeftCollision(item)) {
return true;
}
}
if (checkWallCollision(bag,
LEFT_COLLISION)) {
return true;
}
}
bag.move(-SPACE, 0);
isCompleted();
}
}
return false;
} else if (type == RIGHT_COLLISION) {
for (int i = 0; i < baggs.size(); i++) {
Baggage bag = (Baggage) baggs.get(i);
if (soko.isRightCollision(bag)) {
for (int j=0; j < baggs.size(); j++) {
Baggage item = (Baggage) baggs.get(j);
if (!bag.equals(item)) {
if (bag.isRightCollision(item)) {
return true;
}
}
if (checkWallCollision(bag,
RIGHT_COLLISION)) {
return true;
}
}
bag.move(SPACE, 0);
isCompleted();
}
}
return false;
} else if (type == TOP_COLLISION) {
for (int i = 0; i < baggs.size(); i++) {
Baggage bag = (Baggage) baggs.get(i);
if (soko.isTopCollision(bag)) {
for (int j = 0; j < baggs.size(); j++) {
Baggage item = (Baggage) baggs.get(j);
if (!bag.equals(item)) {
if (bag.isTopCollision(item)) {
return true;
}
}
if (checkWallCollision(bag,
TOP_COLLISION)) {
return true;
}
}
bag.move(0, -SPACE);
isCompleted();
}
}
return false;
} else if (type == BOTTOM_COLLISION) {
for (int i = 0; i < baggs.size(); i++) {
Baggage bag = (Baggage) baggs.get(i);
if (soko.isBottomCollision(bag)) {
for (int j = 0; j < baggs.size(); j++) {
Baggage item = (Baggage) baggs.get(j);
if (!bag.equals(item)) {
if (bag.isBottomCollision(item)) {
return true;
}
}
if (checkWallCollision(bag,
BOTTOM_COLLISION)) {
return true;
}
}
bag.move(0, SPACE);
isCompleted();
}
}
}
return false;
}
public void isCompleted() {
int num = baggs.size();
int compl = 0;
for (int i = 0; i < num; i++) {
Baggage bag = (Baggage) baggs.get(i);
for (int j = 0; j < num; j++) {
Area area = (Area) areas.get(j);
if (bag.x() == area.x()
&& bag.y() == area.y()) {
compl += 1;
}
}
}
if (compl == num) {
completed = true;
repaint();
}
}
public void restartLevel() {
areas.clear();
baggs.clear();
walls.clear();
initWorld();
if (completed) {
completed = false;
}
}
}
Permainan ini sangat sederhana. Ini hanya menyediakan fungsi dasar. Kode ini lebih mudah dimengerti. Permainan memiliki satu tingkat.
private final int OFFSET = 30; private final int SPACE = 20; private final int LEFT_COLLISION = 1; private final int RIGHT_COLLISION = 2; private final int TOP_COLLISION = 3; private final int BOTTOM_COLLISION = 4;
Ukuran gambar dinding 20x20px. Ini mencerminkan konstan SPACE. The OFFSET adalah jarak antara perbatasan jendela dan dunia game. Ada empat jenis tabrakan. Masing-masing diwakili oleh konstanta numerik.
private ArrayList walls = new ArrayList(); private ArrayList baggs = new ArrayList(); private ArrayList areas = new ArrayList();
Dinding, Baggs dan daerah adalah area khusus, yang akan menampung semua dinding, Baggs dan bidang permainan.
private String level =
" ######\n"
+ " ## #\n"
+ " ##$ #\n"
+ " #### $##\n"
+ " ## $ $ #\n"
+ "#### # ## # ######\n"
+ "## # ## ##### ..#\n"
+ "## $ $ ..#\n"
+ "###### ### #@## ..#\n"
+ " ## #########\n"
+ " ########\n";
Ini adalah tingkat permainan. Kecuali untuk ruang, ada lima karakter. The hash (#) singkatan dari dinding. Dolar ($) merupakan kotak untuk bergerak. Titik (.) Karakter merupakan tempat di mana kita harus memindahkan kotak. Pada karakter (@) adalah sokoban tersebut. Dan akhirnya karakter baris baru (\ n) memulai baris baru di dunia.
public final void initWorld() {
int x = OFFSET;
int y = OFFSET;
...
The initWorld () metode memulai dunia game. Ini berjalan melalui string tingkat dan mengisi daftar yang disebutkan di atas.
} else if (item == '$') {
b = new Baggage(x, y);
baggs.add(b);
x += SPACE;
Dalam kasus karakter dollar, kita membuat objek Bagasi. Tujuannya ditambahkan ke daftar Baggs. variabel x meningkat sesuai.
public void buildWorld(Graphics g) {
...
The buildworld () method memanggil semua class game pada satu windows.
ArrayList world = new ArrayList(); world.addAll(walls); world.addAll(areas); world.addAll(baggs); world.add(soko);
Kami membuat daftar class yang meliputi semua objek dari permainan.
for (int i = 0; i < world.size(); i++) {
Actor item = (Actor) world.get(i);
if ((item instanceof Player)
|| (item instanceof Baggage)) {
g.drawImage(item.getImage(), item.x() + 2, item.y() + 2, this);
} else {
g.drawImage(item.getImage(), item.x(), item.y(), this);
}
...
Kami melek melalui wadah dunia dan menggambar obyek. Pemain dan gambar bagasi sedikit lebih kecil. Kami menambahkan 2px ke koordinat mereka ke pusat mereka.
if (completed) {
g.setColor(new Color(0, 0, 0));
g.drawString("Completed", 25, 20);
}
Jika level ini selesai, kita menarik "Selesai" di sudut kiri atas jendela
if (key == KeyEvent.VK_LEFT) {
if (checkWallCollision(soko,
LEFT_COLLISION)) {
return;
}
if (checkBagCollision(LEFT_COLLISION)) {
return;
}
soko.move(-SPACE, 0);
...
Di dalam method keyPressed (), kita cek tombol apa yang ditekan. Kami mengontrol objek sokoban dengan tombol kursor. Jika kita tekan tombol kursor kiri, kita memeriksa apakah bertabrakan sokoban dengan dinding atau dengan bagasi a. Jika tidak, kita bergerak sokoban ke kiri.
} else if (key == KeyEvent.VK_R) {
restartLevel();
}
Kami me-restart tingkat, jika kita tekan tombol R.
if (type == LEFT_COLLISION) {
for (int i = 0; i < walls.size(); i++) {
Wall wall = (Wall) walls.get(i);
if (actor.isLeftCollision(wall)) {
return true;
}
}
return false;
...
Method checkWallCollision() method diciptakan untuk memastikan, bahwa sokoban atau bagasi yang tidak lulus dinding. Ada empat jenis tabrakan. Baris di atas memeriksa tabrakan kiri.
private boolean checkBagCollision(int type) {
}
Method Checkbagcollision() adalah lebih sedikit dilibatkan. Suatu bagasi dapat menabrak dengan suatu dinding, dengan suatu sokoban menolak atau dengan bagasi yang lain . Bagasi dapat dipindahkan hanya jika [itu] menabrak dengan suatu sokoban dan tidak menabrak dengan bagasi yang lain atau suatu dinding. Ketika bagasi dipindahkan, adalah waktu untuk memeriksa, jika tingkatan diselesaikan dengan pemanggilan yang isCompleted() method.
Yang isCompleted() method untuk mengeshock, jika tingkatan diselesaikan. Kita mendapat/kan banyaknya kantong. Kita bandingkan x, y mengkoordinir dari semua kantong dan area tujuan.
for (int i = 0; i < num; i++) {
Baggage bag = (Baggage) baggs.get(i);
for (int j = 0; j < num; j++) {
Area area = (Area) areas.get(j);
if (bag.x() == area.x()
&& bag.y() == area.y()) {
compl += 1;
}
}
}
Yang isCompleted() method untuk mengeshock, jika tingkatan diselesaikan. Kita mendapat/kan banyaknya kantong. Kita bandingkan x, y mengkoordinir dari semua kantong dan area tujuan.
if (compl == num) {
completed = true;
repaint();
}
Game sudah selesai, ketika variabel yang diselesaikan yang sama banyaknya kantong di (dalam) game itu.public void restartLevel() {
areas.clear();
baggs.clear();
walls.clear();
initWorld();
if (completed) {
completed = false;
}
}
Jika kita lakukan beberapa gerak tidak baik, kita dapat start kembali tingkatan [itu]. Kita menghapus semua object dari daftar yang penting dan memulai dunia lagi. variabel Yang diselesaikan adalah mulai sumbang/palsu.
buatlah sebuah class dengan nama
Actor.java
package sokoban;
import java.awt.Image;
public class Actor {
private final int SPACE = 20;
private int x;
private int y;
private Image image;
public Actor(int x, int y) {
this.x = x;
this.y = y;
}
public Image getImage() {
return this.image;
}
public void setImage(Image img) {
image = img;
}
public int x() {
return this.x;
}
public int y() {
return this.y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public boolean isLeftCollision(Actor actor) {
if (((this.x() - SPACE) == actor.x()) &&
(this.y() == actor.y())) {
return true;
} else {
return false;
}
}
public boolean isRightCollision(Actor actor) {
if (((this.x() + SPACE) == actor.x())
&& (this.y() == actor.y())) {
return true;
} else {
return false;
}
}
public boolean isTopCollision(Actor actor) {
if (((this.y() - SPACE) == actor.y()) &&
(this.x() == actor.x())) {
return true;
} else {
return false;
}
}
public boolean isBottomCollision(Actor actor) {
if (((this.y() + SPACE) == actor.y())
&& (this.x() == actor.x())) {
return true;
} else {
return false;
}
}
}
kita lakukan beberapa gerak tidak baik, kita dapat start kembali tingkatan [itu]. Kita Ini menjadi aktor Kelas. Kelas adalah suatu kelas dasar untuk para aktor [yang] lain di (dalam) game [itu]. [Itu] encapsulates kemampuan dasar suatu obyek di (dalam) Sokoban game.
public boolean isLeftCollision(Actor actor) {
if (((this.x() - SPACE) == actor.x()) &&
(this.y() == actor.y())) {
return true;
} else {
return false;
}
}
metoda ini Cek, jika aktor menabrak dengan cek metoda Ini yang lain , jika aktor menabrak dengan aktor yang lain ( dinding, bagasi, sokoban) kepada [yang] yang ditinggalkan [itu].
membuat class baru dengan Nama
Wall.java
package sokoban;
import java.awt.Image;
import java.net.URL;
import javax.swing.ImageIcon;
public class Wall extends Actor {
private Image image;
public Wall(int x, int y) {
super(x, y);
URL loc = this.getClass().getResource("wall.png");
ImageIcon iia = new ImageIcon(loc);
image = iia.getImage();
this.setImage(image);
}
}
Ini adalah kelas Dinding. Ini mewarisi dari kelas Aktor. Setelah konstruksi, itu beban gambar dinding dari filesystem.
Buat class baru dengan nama
Player.java
package sokoban;
import java.awt.Image;
import java.net.URL;
import javax.swing.ImageIcon;
public class Player extends Actor {
public Player(int x, int y) {
super(x, y);
URL loc = this.getClass().getResource("sokoban.png");
ImageIcon iia = new ImageIcon(loc);
Image image = iia.getImage();
this.setImage(image);
}
public void move(int x, int y) {
int nx = this.x() + x;
int ny = this.y() + y;
this.setX(nx);
this.setY(ny);
}
}
Ini adalah kelas Player. Ini adalah kelas untuk membuat objek sokoban.
public void move(int x, int y) {
int nx = this.x() + x;
int ny = this.y() + y;
this.setX(nx);
this.setY(ny);
}
Kelas ini memiliki mengerakan (metode), yang bergerak objek di dalam frame.
Baggage.java
package sokoban;
import java.awt.Image;
import java.net.URL;
import javax.swing.ImageIcon;
public class Baggage extends Actor {
public Baggage(int x, int y) {
super(x, y);
URL loc = this.getClass().getResource("baggage.png");
ImageIcon iia = new ImageIcon(loc);
Image image = iia.getImage();
this.setImage(image);
}
public void move(int x, int y) {
int nx = this.x() + x;
int ny = this.y() + y;
this.setX(nx);
this.setY(ny);
}
}
Ini adalah kelas untuk objek Bagasi. Objek ini bergerak, sehingga memiliki langkah () metode juga.Area.java
package sokoban;
import java.awt.Image;
import java.net.URL;
import javax.swing.ImageIcon;
public class Area extends Actor {
public Area(int x, int y) {
super(x, y);
URL loc = this.getClass().getResource("area.png");
ImageIcon iia = new ImageIcon(loc);
Image image = iia.getImage();
this.setImage(image);
}
}
Kelas area. Ini adalah obyek, di mana kami mencoba untuk menempatkan baggages.
dan sekian postingan ini semoga bermanfaat.
sumber : http://zetcode.com
Sokoban.java
package sokoban;
import javax.swing.JFrame;
public final class Sokoban extends JFrame {
private final int OFFSET = 30;
public Sokoban() {
InitUI();
}
public void InitUI() {
Board board = new Board();
add(board);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(board.getBoardWidth() + OFFSET,
board.getBoardHeight() + 2*OFFSET);
setLocationRelativeTo(null);
setTitle("Sokoban");
}
public static void main(String[] args) {
Sokoban sokoban = new Sokoban();
sokoban.setVisible(true);
}
}
Ok.dan sekian postingan ini semoga bermanfaat.
sumber : http://zetcode.com
1 Komentar untuk "Source Code Game Sokoban dengan Java"
eror gan,
ni pesan erornya :
Exception in thread "main" java.lang.NullPointerException
at javax.swing.ImageIcon.(ImageIcon.java:205)
at sokoban.Wall.(Wall.java:19)
at sokoban.Board.initWorld(Board.java:81)
at sokoban.Board.(Board.java:48)
at sokoban.Sokoban.InitUI(Sokoban.java:14)
at sokoban.Sokoban.(Sokoban.java:10)
at sokoban.Sokoban.main(Sokoban.java:24)
Java Result: 1
mohon bantuannya..
terima kasih