source: advance-wars/src/com/medievaltech/advancewars/GameView.java@ 99433bb

Last change on this file since 99433bb was fea4b77, checked in by dportnoy <devnull@…>, 13 years ago

Implemented turn and support for computer-controller movement of units. Right now, the computer moves a specific unit down one square when its his turn.

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