Changes in / [17dfb52:0986844] in galcon-client
- Files:
-
- 4 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/com/example/helloandroid/Fleet.java
r17dfb52 r0986844 4 4 5 5 import android.graphics.Canvas; 6 import android.graphics.Color;7 6 import android.graphics.Paint; 8 7 import android.graphics.Path; … … 24 23 /* Optimising: pre-calculate paths */ 25 24 public Fleet(Planet source, Planet destination, int numShips, int faction) { 26 source.setNumShips(source.getNumShips()-numShips);27 28 25 //Calculate initial coordinates and direction 29 26 if((destination.getX() - source.getX()) != 0){ … … 137 134 } 138 135 139 public void draw(Canvas canvas, Paint linePaint) { 136 public void draw(Canvas canvas, Paint linePaint) { 137 //Log.i("Gencon", "direction: "+direction); 138 canvas.drawLine((float)x, (float)y, (float)(x+10*Math.cos(direction)), (float)(y+10*Math.sin(direction)), linePaint); 139 140 140 Path p = new Path(); 141 141 … … 145 145 p.lineTo((float)(x+5*Math.cos(direction+Math.PI/2)), (float)(y+5*Math.sin(direction+Math.PI/2))); 146 146 147 int c, prevC = linePaint.getColor();148 149 switch(faction) {150 case 0:151 c = Color.argb(255, 100, 100, 100);152 break;153 case 1:154 c = Color.argb(255, 255, 0, 0);155 break;156 case 2:157 c = Color.argb(255, 0, 180, 0);158 break;159 case 3:160 c = Color.argb(255, 0, 0, 255);161 break;162 case 4:163 c = Color.argb(255, 150, 150, 0);164 break;165 default:166 c = prevC;167 }168 169 linePaint.setColor(c);170 147 171 148 canvas.drawPath(p, linePaint); 172 173 linePaint.setColor(prevC);174 149 } 175 150 -
src/com/example/helloandroid/Game.java
r17dfb52 r0986844 75 75 mThread.unpause(); 76 76 return true; 77 case MENU_EASY: 78 mThread.setDifficulty(DrawingThread.DIFFICULTY_EASY); 79 return true; 80 case MENU_MEDIUM: 81 mThread.setDifficulty(DrawingThread.DIFFICULTY_MEDIUM); 82 return true; 83 case MENU_HARD: 84 mThread.setDifficulty(DrawingThread.DIFFICULTY_HARD); 85 return true; 77 86 } 78 87 … … 104 113 // we were just launched: set up a new game 105 114 mThread.setState(DrawingThread.STATE_RUNNING); 106 Log.w( "Galcon", "SIS is null");115 Log.w(this.getClass().getName(), "SIS is null"); 107 116 } else { 108 Log.w("Galcon", "SIS is nonnull"); 117 // we are being restored: resume a previous game 118 mThread.restoreState(savedInstanceState); 119 Log.w(this.getClass().getName(), "SIS is nonnull"); 109 120 } 110 121 } … … 129 140 // just have the View's thread save its state into our Bundle 130 141 super.onSaveInstanceState(outState); 131 Log.w("Galcon", "SIS called"); 142 mThread.saveState(outState); 143 Log.w(this.getClass().getName(), "SIS called"); 132 144 } 133 145 } -
src/com/example/helloandroid/GameView.java
r17dfb52 r0986844 6 6 import android.content.Context; 7 7 import android.content.res.Resources; 8 import android.graphics.Bitmap; 9 import android.graphics.BitmapFactory; 8 10 import android.graphics.Canvas; 9 import android.graphics.Color;10 11 import android.graphics.Paint; 12 import android.graphics.drawable.Drawable; 11 13 import android.os.Bundle; 12 14 import android.os.Handler; … … 32 34 class DrawingThread extends Thread { 33 35 /* 36 * Difficulty setting constants 37 */ 38 public static final int DIFFICULTY_EASY = 0; 39 public static final int DIFFICULTY_HARD = 1; 40 public static final int DIFFICULTY_MEDIUM = 2; 41 /* 42 * Physics constants 43 */ 44 public static final int PHYS_DOWN_ACCEL_SEC = 35; 45 public static final int PHYS_FIRE_ACCEL_SEC = 80; 46 public static final int PHYS_FUEL_INIT = 60; 47 public static final int PHYS_FUEL_MAX = 100; 48 public static final int PHYS_FUEL_SEC = 10; 49 public static final int PHYS_SLEW_SEC = 120; // degrees/second rotate 50 public static final int PHYS_SPEED_HYPERSPACE = 180; 51 public static final int PHYS_SPEED_INIT = 30; 52 public static final int PHYS_SPEED_MAX = 120; 53 /* 34 54 * State-tracking constants 35 55 */ … … 41 61 42 62 /* 63 * Goal condition constants 64 */ 65 public static final int TARGET_ANGLE = 18; // > this angle means crash 66 public static final int TARGET_BOTTOM_PADDING = 17; // px below gear 67 public static final int TARGET_PAD_HEIGHT = 8; // how high above ground 68 public static final int TARGET_SPEED = 28; // > this speed means crash 69 public static final double TARGET_WIDTH = 1.6; // width of target 70 /* 43 71 * UI constants (i.e. the speed & fuel bars) 44 72 */ 45 73 public static final int UI_BAR = 100; // width of the bar(s) 46 74 public static final int UI_BAR_HEIGHT = 10; // height of the bar(s) 75 private static final String KEY_DIFFICULTY = "mDifficulty"; 76 private static final String KEY_DX = "mDX"; 77 78 private static final String KEY_DY = "mDY"; 79 private static final String KEY_FUEL = "mFuel"; 80 private static final String KEY_GOAL_ANGLE = "mGoalAngle"; 81 private static final String KEY_GOAL_SPEED = "mGoalSpeed"; 82 private static final String KEY_GOAL_WIDTH = "mGoalWidth"; 83 84 private static final String KEY_GOAL_X = "mGoalX"; 85 private static final String KEY_HEADING = "mHeading"; 86 private static final String KEY_LANDER_HEIGHT = "mLanderHeight"; 87 private static final String KEY_LANDER_WIDTH = "mLanderWidth"; 88 private static final String KEY_WINS = "mWinsInARow"; 89 90 private static final String KEY_X = "mX"; 91 private static final String KEY_Y = "mY"; 47 92 48 93 /* 49 94 * Member (state) fields 50 95 */ 96 /** The drawable to use as the background of the animation canvas */ 97 private Bitmap mBackgroundImage; 51 98 52 99 private int mCanvasHeight = 1; 53 100 private int mCanvasWidth = 1; 54 101 102 /** Default is MEDIUM. */ 103 private int mDifficulty; 104 105 /** Velocity */ 106 private double mDX; 107 private double mDY; 108 109 /** Is the engine burning? */ 110 private boolean mEngineFiring; 111 112 /** Fuel remaining */ 113 private double mFuel; 114 115 /** Allowed angle. */ 116 private int mGoalAngle; 117 118 /** Allowed speed. */ 119 private int mGoalSpeed; 120 121 /** Width of the landing pad. */ 122 private int mGoalWidth; 123 124 /** X of the landing pad. */ 125 private int mGoalX; 126 55 127 /** Message handler used by thread to interact with TextView */ 56 128 private Handler mHandler; 57 129 130 /** 131 * Lander heading in degrees, with 0 up, 90 right. Kept in the range 132 * 0..360. 133 */ 134 private double mHeading; 135 136 /** Pixel height of lander image. */ 137 private int mLanderHeight; 138 139 /** What to draw for the Lander in its normal state */ 140 private Drawable mLanderImage; 141 142 /** Pixel width of lander image. */ 143 private int mLanderWidth; 144 58 145 /** Used to figure out elapsed time between frames */ 59 146 private long mLastTime; … … 62 149 private Paint mLinePaint, mTextPaint; 63 150 151 /** "Bad" speed-too-high variant of the line color. */ 152 private Paint mLinePaintBad; 153 64 154 /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */ 65 155 private int mMode; 66 156 157 /** Currently rotating, -1 left, 0 none, 1 right. */ 158 private int mRotating; 159 67 160 /** Indicate whether the surface has been created & is ready to draw */ 68 161 private boolean mRun = false; … … 70 163 /** Handle to the surface manager object we interact with */ 71 164 private SurfaceHolder mSurfaceHolder; 165 166 /** Number of wins in a row. */ 167 private int mWinsInARow; 168 169 /** lander center. */ 170 private double mX; 171 private double mY; 72 172 73 173 public Object planetsLock, fleetsLock; … … 84 184 mContext = context; 85 185 186 Resources res = context.getResources(); 187 // cache handles to our key sprites & other drawables 188 mLanderImage = context.getResources().getDrawable(R.drawable.lander_plain); 189 190 // load background image as a Bitmap instead of a Drawable b/c 191 // we don't need to transform it and it's faster to draw this way 192 mBackgroundImage = BitmapFactory.decodeResource(res, R.drawable.earthrise); 193 194 // Use the regular lander image as the model size for all sprites 195 mLanderWidth = mLanderImage.getIntrinsicWidth(); 196 mLanderHeight = mLanderImage.getIntrinsicHeight(); 197 86 198 // Initialize paints for speedometer 87 199 mLinePaint = new Paint(); … … 89 201 mLinePaint.setARGB(255, 0, 255, 0); 90 202 203 mLinePaintBad = new Paint(); 204 mLinePaintBad.setAntiAlias(true); 205 mLinePaintBad.setARGB(255, 120, 180, 0); 206 91 207 mTextPaint = new Paint(); 92 208 mTextPaint.setAntiAlias(true); 93 209 mTextPaint.setARGB(255, 255, 255, 255); 210 211 mWinsInARow = 0; 212 mDifficulty = DIFFICULTY_MEDIUM; 213 214 // initial show-up of lander (not yet playing) 215 mX = mLanderWidth; 216 mY = mLanderHeight * 2; 217 mFuel = PHYS_FUEL_INIT; 218 mDX = 0; 219 mDY = 0; 220 mHeading = 0; 221 mEngineFiring = true; 94 222 95 223 planetsLock = new Object(); … … 107 235 public void doStart() { 108 236 synchronized (mSurfaceHolder) { 237 // First set the game for Medium difficulty 238 mFuel = PHYS_FUEL_INIT; 239 mEngineFiring = false; 240 mGoalWidth = (int) (mLanderWidth * TARGET_WIDTH); 241 mGoalSpeed = TARGET_SPEED; 242 mGoalAngle = TARGET_ANGLE; 243 int speedInit = PHYS_SPEED_INIT; 244 245 // Adjust difficulty params for EASY/HARD 246 if (mDifficulty == DIFFICULTY_EASY) { 247 mFuel = mFuel * 3 / 2; 248 mGoalWidth = mGoalWidth * 4 / 3; 249 mGoalSpeed = mGoalSpeed * 3 / 2; 250 mGoalAngle = mGoalAngle * 4 / 3; 251 speedInit = speedInit * 3 / 4; 252 } else if (mDifficulty == DIFFICULTY_HARD) { 253 mFuel = mFuel * 7 / 8; 254 mGoalWidth = mGoalWidth * 3 / 4; 255 mGoalSpeed = mGoalSpeed * 7 / 8; 256 speedInit = speedInit * 4 / 3; 257 } 258 259 // pick a convenient initial location for the lander sprite 260 mX = mCanvasWidth / 2; 261 mY = mCanvasHeight - mLanderHeight / 2; 262 263 // start with a little random motion 264 mDY = Math.random() * -speedInit; 265 mDX = Math.random() * 2 * speedInit - speedInit; 266 mHeading = 0; 267 268 // Figure initial spot for landing, not too near center 269 while (true) { 270 mGoalX = (int) (Math.random() * (mCanvasWidth - mGoalWidth)); 271 if (Math.abs(mGoalX - (mX - mLanderWidth / 2)) > mCanvasHeight / 6) 272 break; 273 } 274 109 275 mLastTime = System.currentTimeMillis() + 100; 110 276 setState(STATE_RUNNING); … … 118 284 synchronized (mSurfaceHolder) { 119 285 if (mMode == STATE_RUNNING) setState(STATE_PAUSE); 286 } 287 } 288 289 /** 290 * Restores game state from the indicated Bundle. Typically called when 291 * the Activity is being restored after having been previously 292 * destroyed. 293 * 294 * @param savedState Bundle containing the game state 295 */ 296 public synchronized void restoreState(Bundle savedState) { 297 synchronized (mSurfaceHolder) { 298 setState(STATE_PAUSE); 299 mRotating = 0; 300 mEngineFiring = false; 301 302 mDifficulty = savedState.getInt(KEY_DIFFICULTY); 303 mX = savedState.getDouble(KEY_X); 304 mY = savedState.getDouble(KEY_Y); 305 mDX = savedState.getDouble(KEY_DX); 306 mDY = savedState.getDouble(KEY_DY); 307 mHeading = savedState.getDouble(KEY_HEADING); 308 309 mLanderWidth = savedState.getInt(KEY_LANDER_WIDTH); 310 mLanderHeight = savedState.getInt(KEY_LANDER_HEIGHT); 311 mGoalX = savedState.getInt(KEY_GOAL_X); 312 mGoalSpeed = savedState.getInt(KEY_GOAL_SPEED); 313 mGoalAngle = savedState.getInt(KEY_GOAL_ANGLE); 314 mGoalWidth = savedState.getInt(KEY_GOAL_WIDTH); 315 mWinsInARow = savedState.getInt(KEY_WINS); 316 mFuel = savedState.getDouble(KEY_FUEL); 120 317 } 121 318 } … … 147 344 148 345 /** 346 * Dump game state to the provided Bundle. Typically called when the 347 * Activity is being suspended. 348 * 349 * @return Bundle with this view's state 350 */ 351 public Bundle saveState(Bundle map) { 352 synchronized (mSurfaceHolder) { 353 if (map != null) { 354 map.putInt(KEY_DIFFICULTY, Integer.valueOf(mDifficulty)); 355 map.putDouble(KEY_X, Double.valueOf(mX)); 356 map.putDouble(KEY_Y, Double.valueOf(mY)); 357 map.putDouble(KEY_DX, Double.valueOf(mDX)); 358 map.putDouble(KEY_DY, Double.valueOf(mDY)); 359 map.putDouble(KEY_HEADING, Double.valueOf(mHeading)); 360 map.putInt(KEY_LANDER_WIDTH, Integer.valueOf(mLanderWidth)); 361 map.putInt(KEY_LANDER_HEIGHT, Integer 362 .valueOf(mLanderHeight)); 363 map.putInt(KEY_GOAL_X, Integer.valueOf(mGoalX)); 364 map.putInt(KEY_GOAL_SPEED, Integer.valueOf(mGoalSpeed)); 365 map.putInt(KEY_GOAL_ANGLE, Integer.valueOf(mGoalAngle)); 366 map.putInt(KEY_GOAL_WIDTH, Integer.valueOf(mGoalWidth)); 367 map.putInt(KEY_WINS, Integer.valueOf(mWinsInARow)); 368 map.putDouble(KEY_FUEL, Double.valueOf(mFuel)); 369 } 370 } 371 return map; 372 } 373 374 /** 375 * Sets the current difficulty. 376 * 377 * @param difficulty 378 */ 379 public void setDifficulty(int difficulty) { 380 synchronized (mSurfaceHolder) { 381 mDifficulty = difficulty; 382 } 383 } 384 385 /** 386 * Sets if the engine is currently firing. 387 */ 388 public void setFiring(boolean firing) { 389 synchronized (mSurfaceHolder) { 390 mEngineFiring = firing; 391 } 392 } 393 394 /** 149 395 * Used to signal the thread whether it should be running or not. 150 396 * Passing true allows the thread to run; passing false will shut it … … 198 444 mHandler.sendMessage(msg); 199 445 } else { 446 mRotating = 0; 447 mEngineFiring = false; 200 448 Resources res = mContext.getResources(); 201 449 CharSequence str = ""; … … 206 454 else if (mMode == STATE_LOSE) 207 455 str = res.getText(R.string.mode_lose); 456 else if (mMode == STATE_WIN) 457 str = res.getString(R.string.mode_win_prefix) 458 + mWinsInARow + " " 459 + res.getString(R.string.mode_win_suffix); 208 460 209 461 if (message != null) { 210 462 str = message + "\n" + str; 211 463 } 464 465 if (mMode == STATE_LOSE) mWinsInARow = 0; 212 466 213 467 Message msg = mHandler.obtainMessage(); … … 248 502 } 249 503 } 504 505 // don't forget to resize the background image 506 mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true); 250 507 } 251 508 } … … 325 582 */ 326 583 private void doDraw(Canvas canvas) { 327 canvas.drawColor(Color.BLACK); 328 584 canvas.drawBitmap(mBackgroundImage, 0, 0, null); 329 585 synchronized(planetsLock) { 330 586 for(Planet p : planets) { … … 342 598 } 343 599 } 600 601 int yTop = mCanvasHeight - ((int) mY + mLanderHeight / 2); 602 int xLeft = (int) mX - mLanderWidth / 2; 603 604 // Draw the ship with its current rotation 605 canvas.save(); 606 canvas.rotate((float)mHeading, (float)mX, mCanvasHeight - (float)mY); 607 608 mLanderImage.setBounds(xLeft, yTop, xLeft + mLanderWidth, yTop + mLanderHeight); 609 mLanderImage.draw(canvas); 610 611 canvas.restore(); 344 612 } 345 613 … … 358 626 // by 100ms or whatever. 359 627 if (mLastTime > now) return; 628 629 double elapsed = (now - mLastTime) / 1000.0; 630 631 // mRotating -- update heading 632 if (mRotating != 0) { 633 mHeading += mRotating * (PHYS_SLEW_SEC * elapsed); 634 635 // Bring things back into the range 0..360 636 if (mHeading < 0) 637 mHeading += 360; 638 else if (mHeading >= 360) mHeading -= 360; 639 } 640 641 // Base accelerations -- 0 for x, gravity for y 642 double ddx = 0.0; 643 double ddy = -PHYS_DOWN_ACCEL_SEC * elapsed; 644 645 if (mEngineFiring) { 646 // taking 0 as up, 90 as to the right 647 // cos(deg) is ddy component, sin(deg) is ddx component 648 double elapsedFiring = elapsed; 649 double fuelUsed = elapsedFiring * PHYS_FUEL_SEC; 650 651 // tricky case where we run out of fuel partway through the 652 // elapsed 653 if (fuelUsed > mFuel) { 654 elapsedFiring = mFuel / fuelUsed * elapsed; 655 fuelUsed = mFuel; 656 657 // Oddball case where we adjust the "control" from here 658 mEngineFiring = false; 659 } 660 661 mFuel -= fuelUsed; 662 663 // have this much acceleration from the engine 664 double accel = PHYS_FIRE_ACCEL_SEC * elapsedFiring; 665 666 double radians = 2 * Math.PI * mHeading / 360; 667 ddx = Math.sin(radians) * accel; 668 ddy += Math.cos(radians) * accel; 669 } 360 670 361 671 synchronized(planetsLock) { … … 370 680 } 371 681 } 682 683 double dxOld = mDX; 684 double dyOld = mDY; 685 686 // figure speeds for the end of the period 687 mDX += ddx; 688 mDY += ddy; 689 690 // figure position based on average speed during the period 691 mX += elapsed * (mDX + dxOld) / 2; 692 mY += elapsed * (mDY + dyOld) / 2; 372 693 373 694 mLastTime = now; 695 696 // Evaluate if we have landed ... stop the game 697 double yLowerBound = TARGET_PAD_HEIGHT + mLanderHeight / 2 698 - TARGET_BOTTOM_PADDING; 699 if (mY <= yLowerBound) { 700 mY = yLowerBound; 701 702 double speed = Math.sqrt(mDX * mDX + mDY * mDY); 703 boolean onGoal = (mGoalX <= mX - mLanderWidth / 2 && mX 704 + mLanderWidth / 2 <= mGoalX + mGoalWidth); 705 706 // "Hyperspace" win -- upside down, going fast, 707 // puts you back at the top. 708 if (onGoal && Math.abs(mHeading - 180) < mGoalAngle 709 && speed > PHYS_SPEED_HYPERSPACE) { 710 mWinsInARow++; 711 doStart(); 712 713 return; 714 // Oddball case: this case does a return, all other cases 715 // fall through to setMode() below. 716 } 717 } 374 718 } 375 719 } … … 420 764 } 421 765 422 if(target != null && thread.planetSelected.getFaction() != 0) {766 if(target != null) { 423 767 synchronized(thread.fleetsLock) { 424 768 Fleet f = new Fleet(thread.planetSelected, target, 1, 1); 425 f.setFaction(thread.planetSelected.getFaction());426 769 thread.fleets.add(f); 427 770 } -
src/com/example/helloandroid/Planet.java
r17dfb52 r0986844 62 62 public int getRadius() { 63 63 return radius; 64 }65 66 public int getFaction() {67 return faction;68 64 } 69 65 … … 132 128 133 129 public void update() { 134 //if(faction != 0)135 //numShips++;130 if(faction != 0) 131 numShips++; 136 132 137 133 }
Note:
See TracChangeset
for help on using the changeset viewer.