楽しそうなネタなのですが、コードでフォローするにはちょっと時間がありません。
いくつかアドバイスだけします。
- わにの出現位置を固定化したいなら、すべての出現位置をデータとして管理し、ランダム判定で次の出現位置を決定するようにします。
- 出現する画像を、わにかボムか決めるのもランダム判定で決めます。
- swingはスレッドセーフではないので、Threadクラスは使わず、javax.swing.Timerクラスを使いましょう。
- 1分間を計るには、ゲームスタート時にシステム時間を保存し、Timerで呼ばれる処理で、1分経過したか、毎回判定します。
- ゲームの状態を管理するには、「開始待ち」「ゲーム中」「結果表示中」など、自分のゲームに合わせたステートの管理が重要です。ステートによって、どういう画面を判断します。
- ゲームの開始は、ボタンではなく、タイトル画面クリックにしてはどうでしょう。
楽しいゲームを作ってくださいね。
我慢できず作ってみました。コメントも少し入れました。
調整不十分ですけど、だいたいこんな感じでいかがですか。
あとは適当にいじり倒してください。
java
1import java.awt.Dimension;
2import java.awt.Graphics;
3import java.awt.Image;
4import java.awt.Point;
5import java.awt.Rectangle;
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.awt.event.MouseAdapter;
9import java.awt.event.MouseEvent;
10import java.io.FileInputStream;
11import java.io.IOException;
12import java.util.ArrayList;
13import java.util.Random;
14
15import javax.imageio.ImageIO;
16import javax.swing.JFrame;
17import javax.swing.JPanel;
18import javax.swing.Timer;
19
20public class WaniWaniPanic extends JFrame {
21 public WaniWaniPanic() {
22 super("わにわにパニック");
23 setContentPane(new WaniPaniCanvas());
24 pack();
25 setDefaultCloseOperation(EXIT_ON_CLOSE);
26 setResizable(false);
27 setVisible(true);
28 }
29
30 public static void main(String[] args) {
31 new WaniWaniPanic();
32 }
33}
34
35class WaniPaniCanvas extends JPanel {
36
37 private static final long serialVersionUID = 1L;
38
39 static final int START_WAITING = 0;
40 static final int PLAYING = 1;
41 static final int ENDING = 2;
42
43 static final int IMG_TITLE = 0;
44 static final int IMG_WANI_NORMAL = 1;
45 static final int IMG_WANI_DAMAGED = 2;
46 static final int IMG_BOMB_NORMAL = 3;
47 static final int IMG_BOMB_BOMB = 4;
48 static final int IMG_ENDING = 5;
49
50 static final int WANI_SELECTED = 0;
51 static final int BOMB_SELECTED = 1;
52
53 static final int SPEED_LOW = 3;
54 static final int SPEED_MIDDLE = 2;
55 static final int SPEED_HIGH = 1;
56
57 static final String IMG_NAMES[] = { // 適当に画像作ってください。
58 "title.png", //640 x 480
59 "wani_normal.png", //70 x 70
60 "wani_damaged.png", //70 x 70
61 "bomb_normal.png", //70 x 70
62 "bomb_bomb.png", //70 x 70
63 "ending.png" //640 x 480
64 };
65
66 static final int TIMER_INTERVAL = 400; //タイマー処理の間隔 0.4秒
67 static final int TIMEUP = 60000; //タイムアップまでの時間 60秒
68
69 static final int CANVAS_WIDTH = 640;
70 static final int CANVAS_HEIGHT = 480;
71
72 static final int OBJECT_WIDTH = 70; // ワニやボム画像の幅
73 static final int OBJECT_HEIGHT = 70; // ワニやボム画像の高さ
74
75 static final Point LOCATION[] = { // 出現位置
76 new Point( 50, 150),
77 new Point(150, 150),
78 new Point(250, 150),
79 new Point(350, 150),
80 new Point(450, 150),
81 new Point(550, 150)
82 };
83
84 static final ArrayList<Image> images = new ArrayList<Image>();
85
86 static {
87 loadGameImages();
88 }
89
90 static void loadGameImages() {
91 for (String name : IMG_NAMES) {
92 try {
93 FileInputStream in = new FileInputStream(name);
94 Image img = ImageIO.read(in);
95 images.add(img);
96 in.close();
97 } catch (IOException ex) {
98 System.err.println("画像ファイル " + name + " が存在しません。");
99 System.exit(1);
100 }
101 }
102 }
103
104 final GameState gameStates[] = {
105 new StartWaiting(),
106 new Playing(),
107 new Ending()
108 };
109
110 private int currentState = START_WAITING;
111 private int bestScore = 0;
112 private int score = 0;
113 private boolean overBest = false; // ハイスコアをとったらtrue
114 private long startTime = 0L;
115 private int selectedLocation = 0; // ランダムで選択した出現位置
116 private int selectedObject = 0; // ランダムで選択した出現オブジェクト
117 private int callCounter = 0;
118 private boolean hitObject = false;
119
120 private Random random = new Random(System.currentTimeMillis());
121
122 private Timer timer = new Timer(TIMER_INTERVAL, new ActionListener() {
123 @Override
124 public void actionPerformed(ActionEvent e) {
125 callCounter++;
126 if (hitObject) hitObject = false;
127 long pastTime = System.currentTimeMillis() - startTime;
128 if (pastTime >= TIMEUP) {
129 timer.stop();
130 currentState = ENDING;
131 if (score > bestScore) {
132 bestScore = score;
133 overBest = true;
134 }
135 } else if (pastTime <= TIMEUP * 0.2) {
136 if (callCounter % SPEED_LOW != 0) return;
137 } else if (pastTime <= TIMEUP * 0.85) {
138 if (callCounter % SPEED_MIDDLE != 0) return;
139 }
140
141 int loc = 0;
142 while ((loc = selectLocation()) == selectedLocation);
143
144 selectedLocation = loc;
145 selectedObject = selectObject();
146
147 WaniPaniCanvas.this.repaint();
148 }
149
150 private int selectLocation() {
151 return Math.abs(random.nextInt()) % LOCATION.length;
152 }
153
154 private int selectObject() {
155 int n = Math.abs(random.nextInt()) % 10;
156 if (n == 0) return BOMB_SELECTED;
157 else return WANI_SELECTED;
158 }
159 });
160
161 public WaniPaniCanvas() {
162 setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
163 addMouseListener(new MouseAdapter() {
164 @Override
165 public void mouseClicked(MouseEvent e) {
166 gameStates[currentState].mouseClicked(e);
167 }
168 });
169 }
170
171 public void paint(Graphics g) {
172 gameStates[currentState].paint(g);
173 }
174
175 interface GameState {
176 public void paint(Graphics g);
177 public void mouseClicked(MouseEvent e);
178 }
179
180 class StartWaiting implements GameState {
181 public void paint(Graphics g) {
182 g.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
183 Image img = images.get(IMG_TITLE);
184 g.drawImage(img, 0, 0, WaniPaniCanvas.this);
185 }
186
187 public void mouseClicked(MouseEvent e) {
188 // タイトル画面をクリックしたらゲームスタート
189 score = 0;
190 overBest = false;
191 selectedLocation = 0;
192 selectedObject = 0;
193 callCounter = 0;
194 hitObject = false;
195 startTime = System.currentTimeMillis();
196 currentState = PLAYING;
197 timer.start();
198 WaniPaniCanvas.this.repaint();
199 }
200 }
201
202 class Playing implements GameState {
203 public void paint(Graphics g) {
204 g.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
205 int index = IMG_WANI_NORMAL;
206 if (selectedObject == WANI_SELECTED && hitObject) {
207 index = IMG_WANI_DAMAGED;
208 } else if (selectedObject == BOMB_SELECTED) {
209 if (hitObject) index = IMG_BOMB_BOMB;
210 else index = IMG_BOMB_NORMAL;
211 }
212 Image img = images.get(index);
213 int x = LOCATION[selectedLocation].x;
214 int y = LOCATION[selectedLocation].y;
215 g.drawImage(img, x, y, WaniPaniCanvas.this);
216 g.drawString("得点: " + score, 10, 10);
217 }
218
219 public void mouseClicked(MouseEvent e) {
220 // 当たり判定
221 int x = LOCATION[selectedLocation].x;
222 int y = LOCATION[selectedLocation].y;
223 Rectangle rect = new Rectangle(x, y, OBJECT_WIDTH, OBJECT_HEIGHT);
224 if (rect.contains(e.getPoint())) score += 100;
225 WaniPaniCanvas.this.repaint();
226 }
227 }
228
229 class Ending implements GameState {
230 public void paint(Graphics g) {
231 g.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
232 Image img = images.get(IMG_ENDING);
233 g.drawImage(img, 0, 0, WaniPaniCanvas.this);
234 g.drawString("現在の最高得点: " + bestScore, 200, 200);
235 g.drawString("今回の得点: " + score, 200, 230);
236 if (overBest) g.drawString("ハイスコアです。おめでとう", 200, 260);
237 }
238
239 public void mouseClicked(MouseEvent e) {
240 currentState = START_WAITING;
241 WaniPaniCanvas.this.repaint();
242 }
243 }
244}
245