source: advance-wars/src/com/medievaltech/advancewars/GameView.java@ 511177b

Last change on this file since 511177b was c3ad11c, checked in by dportnoy <devnull@…>, 13 years ago

Units are now colored based on the player that controls them. The controlling player is specified in the unit's constructor.

  • Property mode set to 100644
File size: 14.5 KB
Line 
1package com.medievaltech.advancewars;
2
3import java.io.*;
4import java.util.*;
5
6import com.medievaltech.advancewars.Enum.*;
7import com.medievaltech.unit.*;
8import com.medievaltech.gui.*;
9
10import android.content.Context;
11import android.graphics.*;
12import android.os.*;
13import android.view.*;
14import android.util.AttributeSet;
15import android.util.Log;
16import android.widget.TextView;
17
18class GameView extends SurfaceView implements SurfaceHolder.Callback {
19
20 class DrawingThread extends Thread {
21 public GameState mGameState;
22
23 //maybe make this private and make an accessor for it
24 public Map mMap;
25
26 public Tile grassTile, oceanTile;
27
28 public Turn mTurn;
29
30 public Player enemy;
31 private Unit selectedUnit;
32
33 private int mCanvasHeight = 1;
34 private int mCanvasWidth = 1;
35
36 private Paint mLinePaint, mTextPaint, mButtonPaint, mTilePaint1,
37 mTilePaint2, mSelectionPaint, mUnitPaint1, mUnitPaint2;
38
39 /** Indicate whether the surface has been created & is ready to draw */
40 private boolean mRun = false;
41
42 /** Handle to the surface manager object we interact with */
43 private SurfaceHolder mSurfaceHolder;
44
45 private com.medievaltech.gui.Window wndMainMenu;
46
47 public DrawingThread(SurfaceHolder surfaceHolder, Context context, Handler handler) {
48 mSurfaceHolder = surfaceHolder;
49
50 mLinePaint = new Paint();
51 mLinePaint.setAntiAlias(true);
52 mLinePaint.setARGB(255, 0, 255, 0);
53
54 mTextPaint = new Paint();
55 mTextPaint.setAntiAlias(true);
56 mTextPaint.setARGB(255, 255, 255, 255);
57 mTextPaint.setTextSize(12);
58 mTextPaint.setTextAlign(Paint.Align.CENTER);
59
60 mButtonPaint = new Paint();
61 mButtonPaint.setAntiAlias(true);
62 mButtonPaint.setARGB(255, 0, 0, 0);
63 mButtonPaint.setTextSize(20);
64 mButtonPaint.setTextAlign(Paint.Align.CENTER);
65
66 mTilePaint1 = new Paint();
67 mTilePaint1.setAntiAlias(true);
68 mTilePaint1.setARGB(255, 0, 255, 0);
69
70 mTilePaint2 = new Paint();
71 mTilePaint2.setAntiAlias(true);
72 mTilePaint2.setARGB(255, 0, 0, 255);
73
74 mUnitPaint1 = new Paint();
75 mUnitPaint1.setAntiAlias(true);
76 mUnitPaint1.setARGB(255, 255, 0, 0);
77
78 mUnitPaint2 = new Paint();
79 mUnitPaint2.setAntiAlias(true);
80 mUnitPaint2.setARGB(255, 160, 160, 255);
81
82 mSelectionPaint = new Paint();
83 mSelectionPaint.setAntiAlias(true);
84 mSelectionPaint.setARGB(255, 255, 127, 0);
85
86 wndMainMenu = new com.medievaltech.gui.Window(0, 0, 320, 450);;
87 wndMainMenu.addGUIObject("txtTitle", new Text("Main Menu", 100, 30, 120, 20, mTextPaint));
88 wndMainMenu.addGUIObject("btnNewGame", new Button("New Game", 100, 90, 120, 20, mLinePaint, mButtonPaint));
89 wndMainMenu.addGUIObject("btnLoadGame", new Button("Load Game", 100, 125, 120, 20, mLinePaint, mButtonPaint));
90 wndMainMenu.addGUIObject("btnMapEditor", new Button("Map Editor", 100, 160, 120, 20, mLinePaint, mButtonPaint));
91 wndMainMenu.addGUIObject("btnQuit", new Button("Quit", 100, 195, 120, 20, mLinePaint, mButtonPaint));
92
93 grassTile = new Tile(mTilePaint1, TerrainType.LAND);
94 oceanTile = new Tile(mTilePaint2, TerrainType.SEA);
95
96 mMap = new Map(grassTile, 6, 8, new Point(10, 25));
97
98 boolean land = true;
99
100 for(int x=0; x<mMap.getWidth(); x++) {
101 for(int y=0; y<mMap.getHeight(); y++) {
102 if(land)
103 mMap.setTile(x, y, new Tile(grassTile, new Point(x, y)));
104 else
105 mMap.setTile(x, y, new Tile(oceanTile, new Point(x, y)));
106 land = !land;
107 }
108 land = !land;
109 }
110
111 Player humanPlayer = new Player("Human", mUnitPaint1);
112 enemy = new Player("Comp", mUnitPaint2);
113
114 mMap.getTile(0, 0).addUnit(new Soldier(enemy));
115 mMap.getTile(2, 3).addUnit(new Soldier(humanPlayer));
116 mMap.getTile(5, 6).addUnit(new Soldier(humanPlayer));
117
118 mTurn = Turn.YOUR_TURN;
119
120 mGameState = GameState.MAIN_MENU;
121 }
122
123 /**
124 * Starts the game, setting parameters for the current difficulty.
125 */
126 // I don't think this gets called now. maybe we should call it in the thread constructor
127 public void doStart() {
128 synchronized (mSurfaceHolder) {
129 Log.i("AdvanceWars", "Player's turn starting now");
130 mGameState = GameState.MAIN_MENU;
131 }
132 }
133
134 @Override
135 public void run() {
136 while (mRun) {
137 Canvas c = null;
138 try {
139 c = mSurfaceHolder.lockCanvas(null);
140 synchronized(mSurfaceHolder) {
141 doLogic();
142 doDraw(c);
143 }
144 } finally {
145 // do this in a finally so that if an exception is thrown
146 // during the above, we don't leave the Surface in an
147 // inconsistent state
148 if (c != null) {
149 mSurfaceHolder.unlockCanvasAndPost(c);
150 }
151 }
152 }
153 }
154
155 /**
156 * Used to signal the thread whether it should be running or not.
157 * Passing true allows the thread to run; passing false will shut it
158 * down if it's already running. Calling start() after this was most
159 * recently called with false will result in an immediate shutdown.
160 *
161 * @param b true to run, false to shut down
162 */
163 public void setRunning(boolean b) {
164 mRun = b;
165 }
166
167 public void setGameState(GameState state) {
168 synchronized (mSurfaceHolder) {
169 mGameState = state;
170 }
171 }
172
173 /* Callback invoked when the surface dimensions change. */
174 public void setSurfaceSize(int width, int height) {
175 // synchronized to make sure these all change atomically
176 synchronized (mSurfaceHolder) {
177 mCanvasWidth = width;
178 mCanvasHeight = height;
179
180 Log.i("AdvanceWars", "width: "+mCanvasWidth+", height: "+mCanvasHeight);
181 }
182 }
183
184 private void doLogic() {
185 if(mTurn == Turn.YOUR_TURN)
186 return;
187
188 switch(mGameState) {
189 case BATTLE_MAP:
190 Iterator<Unit> iter = enemy.getControlledUnits().iterator();
191 Unit cur;
192 int x, y;
193
194 Log.i("AdvanceWars", "starting to move enemy units");
195 while(iter.hasNext()) {
196 cur = iter.next();
197 x = cur.location.x;
198 y = cur.location.y;
199
200 Log.i("AdvanceWars", "moving enemy unit");
201
202 //any unit that's in the way is removed (needs to be changed eventuallyy)
203 thread.mMap.getTile(x, y).removeUnit();
204 thread.mMap.getTile(x, y+1).addUnit(cur);
205 }
206 Log.i("AdvanceWars", "finished moving enemy units");
207
208
209 mTurn = Turn.YOUR_TURN;
210 break;
211 }
212 }
213
214 /**
215 * Draws the ship, fuel/speed bars, and background to the provided
216 * Canvas.
217 */
218 private void doDraw(Canvas canvas) {
219 canvas.drawColor(Color.BLACK);
220
221 switch(mGameState) {
222 case MAIN_MENU:
223 wndMainMenu.draw(canvas);
224 break;
225 case BATTLE_MAP:
226 mTextPaint.setTextSize(12);
227
228 mMap.draw(canvas);
229
230 if(selectedUnit != null) {
231 for(Point p : selectedUnit.getMovementRange()) {
232 canvas.drawRect(p.x*50+10, p.y*50+25, p.x*50+50+10, p.y*50+50+25, mSelectionPaint);
233 }
234 }
235
236 mMap.drawUnits(canvas);
237
238 break;
239 }
240 }
241 }
242
243 /** Pointer to the text view to display "Paused.." etc. */
244 private TextView mStatusText;
245
246 /** The thread that actually draws the animation */
247 private DrawingThread thread;
248
249 public Game mGame;
250
251 public GameView(Context context, AttributeSet attrs) {
252 super(context, attrs);
253
254 // register our interest in hearing about changes to our surface
255 SurfaceHolder holder = getHolder();
256 holder.addCallback(this);
257
258 // create thread only; it's started in surfaceCreated()
259 thread = new DrawingThread(holder, context, new Handler() {
260 @Override
261 public void handleMessage(Message m) {
262 mStatusText.setVisibility(m.getData().getInt("viz"));
263 mStatusText.setText(m.getData().getString("text"));
264 }
265 });
266
267 setFocusable(true); // make sure we get key events
268 }
269
270 @Override public boolean onTouchEvent(MotionEvent event) {
271 Log.i("AdvanceWars", "Detected touch event");
272
273 if(event.getAction() == MotionEvent.ACTION_UP) {
274 Log.i("AdvanceWars", "Detected UP touch action");
275 switch(thread.mGameState) {
276 case MAIN_MENU:
277 Log.i("AdvanceWars", "Switching to battle map");
278 if(thread.wndMainMenu.getGUIObject("btnNewGame").isClicked(event.getX(), event.getY())) {
279 thread.mGameState = GameState.BATTLE_MAP;
280 }else if(thread.wndMainMenu.getGUIObject("btnLoadGame").isClicked(event.getX(), event.getY())) {
281 BufferedReader b;
282 try {
283 b = new BufferedReader(new FileReader(android.os.Environment.getExternalStorageDirectory()+"/save.txt"));
284
285 int width = Integer.parseInt(b.readLine());
286 int height = Integer.parseInt(b.readLine());
287
288 String offset = b.readLine();
289 Log.i("GameSave", offset);
290 int offsetX = Integer.parseInt(offset.substring(0, offset.indexOf("x")));
291 int offsetY = Integer.parseInt(offset.substring(offset.indexOf("x")+1));
292
293 thread.mMap = new Map(thread.grassTile, width, height, new Point(offsetX, offsetY));
294
295 Log.i("GameSave", "Created the map");
296
297 for(int x=0; x<width; x++) {
298 String line = b.readLine();
299 Log.i("GameSave", line);
300 String[] arr = line.split(",");
301 for(int y=0; y<arr.length; y++) {
302 TerrainType type = TerrainType.values()[Integer.parseInt(arr[y])];
303 if(type.equals(TerrainType.LAND))
304 thread.mMap.setTile(x, y, new Tile(thread.grassTile, new Point(10, 25)));
305 else
306 thread.mMap.setTile(x, y, new Tile(thread.oceanTile, new Point(10, 25)));
307 }
308 }
309
310 while(b.ready()) {
311 String unit = b.readLine();
312 Log.i("GameSave", unit);
313 int x = Integer.parseInt(unit.substring(0, unit.indexOf(",")));
314 int y = Integer.parseInt(unit.substring(unit.indexOf(",")+1));
315
316 Player humanPlayer = new Player("Human", mGame.mThread.mUnitPaint1);
317
318 mGame.mThread.mMap.getTile(x, y).addUnit(new Soldier(humanPlayer));
319 }
320
321 b.close();
322 }catch(IOException ioe) {
323 ioe.printStackTrace();
324 }
325 thread.mGameState = GameState.BATTLE_MAP;
326 }else if(thread.wndMainMenu.getGUIObject("btnQuit").isClicked(event.getX(), event.getY())) {
327 mGame.finish();
328 }
329 break;
330 case BATTLE_MAP:
331 Log.i("AdvanceWars", "Touch event detected on battle map");
332
333 if(event.getX() >= thread.mMap.offset.x && event.getY() >= thread.mMap.offset.y) {
334 int x = ((int)event.getX() - thread.mMap.offset.x) / 50;
335 int y = ((int)event.getY() - thread.mMap.offset.y) / 50;
336
337 Unit target = thread.mMap.getTile(x, y).currentUnit;
338
339 if(thread.selectedUnit != null && thread.selectedUnit.getMovementRange().contains(new Point(x, y))) {
340 if(target == null || target == thread.selectedUnit) {
341 thread.mMap.getTile(thread.selectedUnit.location.x, thread.selectedUnit.location.y).removeUnit();
342 thread.mMap.getTile(x, y).addUnit(thread.selectedUnit);
343 }else {
344 // the target contains another unit. If the unit is enemy-controlled, attack it
345 }
346 thread.selectedUnit = null;
347 }else
348 thread.selectedUnit = target;
349 }
350
351 Log.i("AdvanceWars", "Touch event handling finished");
352
353 break;
354 }
355 }else if(event.getAction() == MotionEvent.ACTION_DOWN) {
356
357 }
358
359 return true;
360 }
361
362 /**
363 * Fetches the animation thread corresponding to this LunarView.
364 *
365 * @return the animation thread
366 */
367 public DrawingThread getThread() {
368 return thread;
369 }
370
371 /**
372 * Installs a pointer to the text view used for messages.
373 */
374 public void setTextView(TextView textView) {
375 mStatusText = textView;
376 }
377
378 /* Callback invoked when the surface dimensions change. */
379 public void surfaceChanged(SurfaceHolder holder, int format, int width,
380 int height) {
381 thread.setSurfaceSize(width, height);
382 }
383
384 /*
385 * Callback invoked when the Surface has been created and is ready to be
386 * used.
387 */
388 public void surfaceCreated(SurfaceHolder holder) {
389 thread.setRunning(true);
390 thread.start();
391 }
392
393 /*
394 * Callback invoked when the Surface has been destroyed and must no longer
395 * be touched. WARNING: after this method returns, the Surface/Canvas must
396 * never be touched again!
397 */
398 public void surfaceDestroyed(SurfaceHolder holder) {
399 // we have to tell thread to shut down & wait for it to finish, or else
400 // it might touch the Surface after we return and explode
401 boolean retry = true;
402 thread.setRunning(false);
403 while (retry) {
404 try {
405 thread.join();
406 retry = false;
407 } catch (InterruptedException e) {
408 }
409 }
410 }
411}
Note: See TracBrowser for help on using the repository browser.