1 // MicroNibbles - Nibbles in 150 Zeilen - (C)2002 Jörg Mensmann
2 import java.awt.*;
3 import java.awt.event.*;
4 import java.awt.image.PixelGrabber;
5 public class MicroNibbles extends java.applet.Applet implements Runnable, KeyListener {
6 Thread thread = null; // Timer-Thread
7 Image offscreen, backgroundimg; // Bitmaps
8 Graphics offgraphics; // Backbuffer-Graphic
9 Font bigFont, mediumFont, smallFont; // Schriftarten
10 int direction, snake_len, snake_num, counter = 0, level = 1;
11 boolean inGame, showCrash, hasWon, gameOver; // Spiellogik
12 int[] snake_x, snake_y; // Positionen der Einzelteile der Schlange
13 int[][] field; // Spielfeld
14 final int FeldX = 64, FeldY = 40, // Größe der Spielfeldes
15 EMPTY = 0, OBSTACLE = 1, SNAKE = 2, NUMBER = 3, // für Spielfeld
16 NORTH = 0, EAST = 1, SOUTH = 2, WEST = 3; // Richtungen
17 public void init() {
18 backgroundimg = getImage(getDocumentBase(), getParameter("bg"));
19 bigFont = new Font("TimesRoman,Times", Font.BOLD, 30);
20 mediumFont = new Font("TimesRoman,Times", 0, 20);
21 smallFont = new Font("Courier New,Courier,Helvetica", 0, 15);
22 snake_x = new int[70];
23 snake_y = new int[70];
24 field = new int[FeldX + 1][FeldY + 1];
25 addKeyListener(this);
26 }
27 public void start() {
28 if (thread == null) {
29 thread = new Thread(this);
30 thread.start();
31 }
32 }
33 public void stop() { thread = null; }
34 public void run() { // Run-Methode des Thread
35 while (thread != null) {
36 try { Thread.sleep(80); } catch (InterruptedException e){}
37 counter++;
38 if (inGame) moveSnake();
39 repaint();
40 }
41 thread = null;
42 }
43 void newNumber() { // Zahl irgendwo auf dem Spielfeld einfügen
44 int x, y;
45 do {
46 x = (int)(Math.random() * (FeldX - 2)) + 1;
47 y = (int)(Math.random() * (FeldY - 2)) + 1;
48 } while (GetField(x, y) != EMPTY); // Leeres Feld suchen
49 SetField(x, y, NUMBER);
50 }
51 int GetField(int x, int y) { return field[x][y]; }
52 void SetField(int x, int y, int w) { field[x][y] = w; }
53 void moveSnake() {
54 SetField(snake_x[snake_len], snake_y[snake_len], EMPTY); // Ende der Schlange entfernen
55 for (int i=snake_len; i >= 2; i--) { // Positionen weitersetzen
56 snake_x[i] = snake_x[i - 1];
57 snake_y[i] = snake_y[i - 1];
58 }
59 switch (direction) { // Kopf neu setzen bzw. Crash
60 case NORTH: if (snake_y[1] > 0) snake_y[1]--; else crash(); break;
61 case EAST: if (snake_x[1] < FeldX - 1) snake_x[1]++; else crash(); break;
62 case SOUTH: if (snake_y[1] < FeldY - 1) snake_y[1]++; else crash(); break;
63 case WEST: if (snake_x[1] > 0) snake_x[1]--; else crash(); break;
64 }
65 if (GetField(snake_x[1], snake_y[1]) == NUMBER) { // Nummer?
66 if (--snake_num < 1) { // Level gewonnen?
67 inGame = !(hasWon = true);
68 gameOver = (getParameter("level" + (++level)) == null);
69 if (gameOver) level = 1;
70 } else {
71 newNumber(); // Neue Nummer und Länge der Schlange erhöhen
72 for (int i=snake_len + 1; i <= (snake_len + 10 - snake_num); i++) {
73 snake_x[i] = snake_x[snake_len];
74 snake_y[i] = snake_y[snake_len];
75 }
76 snake_len += 10 - snake_num;
77 }
78 }
79 if ((GetField(snake_x[1], snake_y[1]) != EMPTY) && (GetField(snake_x[1], snake_y[1]) != NUMBER)) crash();
80 else SetField(snake_x[1], snake_y[1], SNAKE);
81 }
82 void crash () { showCrash = true; inGame = false; }
83 public synchronized void update(Graphics g) {
84 if (offscreen == null) { // Erster Durchlauf -> Backbuffer erzeugen
85 offscreen = createImage(getSize().width, getSize().height);
86 offgraphics = offscreen.getGraphics();
87 }
88 offgraphics.drawImage(backgroundimg, 0, 0, null); // Hintergrund
89 if ((inGame) || (showCrash)) {
90 offgraphics.setColor(Color.red);
91 for (int x=0; x <= FeldX; x++) // Hindernisse
92 for (int y=0; y <= FeldY; y++)
93 if (GetField(x, y) == OBSTACLE) offgraphics.fillRect(x*10, y*10, 10, 10);
94 if (!showCrash || counter % 2 == 0) { // Wenn gecrashed dann blinkend darstellen
95 offgraphics.setColor(Color.green);
96 for (int x=0; x <= FeldX; x++) // Schlange
97 for (int y=0; y <= FeldY; y++)
98 if (GetField(x, y) == SNAKE) offgraphics.fillRect(x*10, y*10, 10, 10);
99 }
100 offgraphics.setFont(smallFont);
101 offgraphics.setColor(Color.white);
102 for (int x=0; x <= FeldX; x++) // Zahl
103 for (int y=0; y <= FeldY; y++)
104 if (GetField(x, y) == NUMBER) offgraphics.drawString("" + snake_num, x*10, y*10 + 10);
105 }
106 if (!inGame) { // Nicht im Spiel -> Text anzeigen
107 offgraphics.setColor(Color.black);
108 offgraphics.setFont(bigFont);
109 offgraphics.drawString("MicroNibbles", 10, 35);
110 offgraphics.setColor(Color.blue);
111 offgraphics.setFont(bigFont);
112 if (counter % 2 == 0 && showCrash) offgraphics.drawString("Crash!", 10, 75);
113 else if ((counter / 7) % 2 == 0 && hasWon)
114 offgraphics.drawString(gameOver ? "You win! - Game Over" : "Level complete!", 10, 75);
115 offgraphics.setFont(mediumFont);
116 offgraphics.drawString("Press SPACE to begin!", 10, 120);
117 }
118 g.drawImage(offscreen, 0, 0, null); // Backbuffer auf den Screen
119 }
120 public void keyPressed(KeyEvent e) {
121 if (!inGame) {
122 if (e.getKeyCode() == KeyEvent.VK_SPACE) initGame();
123 } else
124 switch (e.getKeyCode()) {
125 case KeyEvent.VK_UP: if (direction != SOUTH) direction = NORTH; break;
126 case KeyEvent.VK_DOWN: if (direction != NORTH) direction = SOUTH; break;
127 case KeyEvent.VK_RIGHT: if (direction != WEST) direction = EAST; break;
128 case KeyEvent.VK_LEFT: if (direction != EAST) direction = WEST; break;
129 }
130 }
131 public void keyTyped(KeyEvent e) { }
132 public void keyReleased(KeyEvent e) { }
133 void initGame() {
134 int[] pixels = new int[FeldX * FeldY];
135 Image levelimg = getImage(getDocumentBase(), getParameter("level" + level));
136 PixelGrabber pg = new PixelGrabber(levelimg, 0, 0, FeldX, FeldY, pixels, 0, FeldX);
137 try { pg.grabPixels(); } catch (InterruptedException e) { }
138 for (int x=0; x < FeldX; x++) // Level wird abhängig von
139 for (int y=0; y < FeldY; y++) // der Level-Grafik aufgebaut
140 SetField(x, y, (pixels[x + y*FeldX] != pixels[0]) ? OBSTACLE : EMPTY);
141 direction = 1; snake_num = 9; snake_len = 6;
142 for (int i=1; i <= snake_len; i++) {
143 snake_x[i] = 20 - i;
144 snake_y[i] = 4;
145 SetField(20 - i, 4, SNAKE);
146 }
147 newNumber();
148 inGame = !(showCrash = hasWon = gameOver = false);
149 }
150 }
syntax highlighted by Code2HTML, v. 0.9.1