- Timestamp:
- Jun 5, 2010, 7:01:47 PM (14 years ago)
- Branches:
- master
- Children:
- c65ef39
- Parents:
- 61c4fbc
- Location:
- src/com/example/helloandroid
- Files:
-
- 2 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/com/example/helloandroid/Fleet.java
r61c4fbc r95509e1 4 4 5 5 import android.graphics.Canvas; 6 import android.graphics.Color; 6 7 import android.graphics.Paint; 7 8 import android.graphics.Path; … … 23 24 /* Optimising: pre-calculate paths */ 24 25 public Fleet(Planet source, Planet destination, int numShips, int faction) { 26 source.setNumShips(source.getNumShips()-numShips); 27 25 28 //Calculate initial coordinates and direction 26 29 if((destination.getX() - source.getX()) != 0){ … … 133 136 } 134 137 135 public void draw(Canvas canvas, Paint linePaint) { 136 //Log.i("Gencon", "direction: "+direction); 137 canvas.drawLine((float)x, (float)y, (float)(x+10*Math.cos(direction)), (float)(y+10*Math.sin(direction)), linePaint); 138 138 public void draw(Canvas canvas, Paint linePaint) { 139 139 Path p = new Path(); 140 140 … … 144 144 p.lineTo((float)(x+5*Math.cos(direction+Math.PI/2)), (float)(y+5*Math.sin(direction+Math.PI/2))); 145 145 146 int c, prevC = linePaint.getColor(); 147 148 switch(faction) { 149 case 0: 150 c = Color.argb(255, 100, 100, 100); 151 break; 152 case 1: 153 c = Color.argb(255, 255, 0, 0); 154 break; 155 case 2: 156 c = Color.argb(255, 0, 180, 0); 157 break; 158 case 3: 159 c = Color.argb(255, 0, 0, 255); 160 break; 161 case 4: 162 c = Color.argb(255, 150, 150, 0); 163 break; 164 default: 165 c = prevC; 166 } 167 168 linePaint.setColor(c); 169 146 170 canvas.drawPath(p, linePaint); 171 172 linePaint.setColor(prevC); 147 173 } 148 174 -
src/com/example/helloandroid/Game.java
r61c4fbc r95509e1 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;86 77 } 87 78 … … 113 104 // we were just launched: set up a new game 114 105 mThread.setState(DrawingThread.STATE_RUNNING); 115 Log.w( this.getClass().getName(), "SIS is null");106 Log.w("Galcon", "SIS is null"); 116 107 } else { 117 // we are being restored: resume a previous game 118 mThread.restoreState(savedInstanceState); 119 Log.w(this.getClass().getName(), "SIS is nonnull"); 108 Log.w("Galcon", "SIS is nonnull"); 120 109 } 121 110 } … … 140 129 // just have the View's thread save its state into our Bundle 141 130 super.onSaveInstanceState(outState); 142 mThread.saveState(outState); 143 Log.w(this.getClass().getName(), "SIS called"); 131 Log.w("Galcon", "SIS called"); 144 132 } 145 133 } -
src/com/example/helloandroid/GameView.java
r61c4fbc r95509e1 6 6 import android.content.Context; 7 7 import android.content.res.Resources; 8 import android.graphics.Bitmap;9 import android.graphics.BitmapFactory;10 8 import android.graphics.Canvas; 9 import android.graphics.Color; 11 10 import android.graphics.Paint; 12 11 import android.graphics.drawable.Drawable; … … 34 33 class DrawingThread extends Thread { 35 34 /* 36 * Difficulty setting constants37 */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 constants43 */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 rotate50 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 /*54 35 * State-tracking constants 55 36 */ … … 61 42 62 43 /* 63 * Goal condition constants64 */65 public static final int TARGET_ANGLE = 18; // > this angle means crash66 public static final int TARGET_BOTTOM_PADDING = 17; // px below gear67 public static final int TARGET_PAD_HEIGHT = 8; // how high above ground68 public static final int TARGET_SPEED = 28; // > this speed means crash69 public static final double TARGET_WIDTH = 1.6; // width of target70 /*71 44 * UI constants (i.e. the speed & fuel bars) 72 45 */ 73 46 public static final int UI_BAR = 100; // width of the bar(s) 74 47 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";92 48 93 49 /* 94 50 * Member (state) fields 95 51 */ 96 /** The drawable to use as the background of the animation canvas */97 private Bitmap mBackgroundImage;98 52 99 53 private int mCanvasHeight = 1; 100 54 private int mCanvasWidth = 1; 101 55 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 127 56 /** Message handler used by thread to interact with TextView */ 128 57 private Handler mHandler; 129 58 130 /**131 * Lander heading in degrees, with 0 up, 90 right. Kept in the range132 * 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 145 59 /** Used to figure out elapsed time between frames */ 146 60 private long mLastTime; … … 149 63 private Paint mLinePaint, mTextPaint; 150 64 151 /** "Bad" speed-too-high variant of the line color. */152 private Paint mLinePaintBad;153 154 65 /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */ 155 66 private int mMode; 156 67 157 /** Currently rotating, -1 left, 0 none, 1 right. */158 private int mRotating;159 160 68 /** Indicate whether the surface has been created & is ready to draw */ 161 69 private boolean mRun = false; … … 163 71 /** Handle to the surface manager object we interact with */ 164 72 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;172 73 173 74 public Object planetsLock, fleetsLock; … … 184 85 mContext = context; 185 86 186 Resources res = context.getResources();187 // cache handles to our key sprites & other drawables188 mLanderImage = context.getResources().getDrawable(R.drawable.lander_plain);189 190 // load background image as a Bitmap instead of a Drawable b/c191 // we don't need to transform it and it's faster to draw this way192 mBackgroundImage = BitmapFactory.decodeResource(res, R.drawable.earthrise);193 194 // Use the regular lander image as the model size for all sprites195 mLanderWidth = mLanderImage.getIntrinsicWidth();196 mLanderHeight = mLanderImage.getIntrinsicHeight();197 198 87 // Initialize paints for speedometer 199 88 mLinePaint = new Paint(); … … 201 90 mLinePaint.setARGB(255, 0, 255, 0); 202 91 203 mLinePaintBad = new Paint();204 mLinePaintBad.setAntiAlias(true);205 mLinePaintBad.setARGB(255, 120, 180, 0);206 207 92 mTextPaint = new Paint(); 208 93 mTextPaint.setAntiAlias(true); 209 94 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;222 95 223 96 planetsLock = new Object(); … … 235 108 public void doStart() { 236 109 synchronized (mSurfaceHolder) { 237 // First set the game for Medium difficulty238 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/HARD246 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 sprite260 mX = mCanvasWidth / 2;261 mY = mCanvasHeight - mLanderHeight / 2;262 263 // start with a little random motion264 mDY = Math.random() * -speedInit;265 mDX = Math.random() * 2 * speedInit - speedInit;266 mHeading = 0;267 268 // Figure initial spot for landing, not too near center269 while (true) {270 mGoalX = (int) (Math.random() * (mCanvasWidth - mGoalWidth));271 if (Math.abs(mGoalX - (mX - mLanderWidth / 2)) > mCanvasHeight / 6)272 break;273 }274 275 110 mLastTime = System.currentTimeMillis() + 100; 276 111 setState(STATE_RUNNING); … … 284 119 synchronized (mSurfaceHolder) { 285 120 if (mMode == STATE_RUNNING) setState(STATE_PAUSE); 286 }287 }288 289 /**290 * Restores game state from the indicated Bundle. Typically called when291 * the Activity is being restored after having been previously292 * destroyed.293 *294 * @param savedState Bundle containing the game state295 */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);317 121 } 318 122 } … … 344 148 345 149 /** 346 * Dump game state to the provided Bundle. Typically called when the347 * Activity is being suspended.348 *349 * @return Bundle with this view's state350 */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, Integer362 .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 difficulty378 */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 /**395 150 * Used to signal the thread whether it should be running or not. 396 151 * Passing true allows the thread to run; passing false will shut it … … 444 199 mHandler.sendMessage(msg); 445 200 } else { 446 mRotating = 0;447 mEngineFiring = false;448 201 Resources res = mContext.getResources(); 449 202 CharSequence str = ""; … … 454 207 else if (mMode == STATE_LOSE) 455 208 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);460 209 461 210 if (message != null) { 462 211 str = message + "\n" + str; 463 212 } 464 465 if (mMode == STATE_LOSE) mWinsInARow = 0;466 213 467 214 Message msg = mHandler.obtainMessage(); … … 502 249 } 503 250 } 504 505 // don't forget to resize the background image506 mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true);507 251 } 508 252 } … … 582 326 */ 583 327 private void doDraw(Canvas canvas) { 584 canvas.drawBitmap(mBackgroundImage, 0, 0, null); 328 canvas.drawColor(Color.BLACK); 329 585 330 synchronized(planetsLock) { 586 331 for(Planet p : planets) { … … 598 343 } 599 344 } 600 601 int yTop = mCanvasHeight - ((int) mY + mLanderHeight / 2);602 int xLeft = (int) mX - mLanderWidth / 2;603 604 // Draw the ship with its current rotation605 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();612 345 } 613 346 … … 626 359 // by 100ms or whatever. 627 360 if (mLastTime > now) return; 628 629 double elapsed = (now - mLastTime) / 1000.0;630 631 // mRotating -- update heading632 if (mRotating != 0) {633 mHeading += mRotating * (PHYS_SLEW_SEC * elapsed);634 635 // Bring things back into the range 0..360636 if (mHeading < 0)637 mHeading += 360;638 else if (mHeading >= 360) mHeading -= 360;639 }640 641 // Base accelerations -- 0 for x, gravity for y642 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 right647 // cos(deg) is ddy component, sin(deg) is ddx component648 double elapsedFiring = elapsed;649 double fuelUsed = elapsedFiring * PHYS_FUEL_SEC;650 651 // tricky case where we run out of fuel partway through the652 // elapsed653 if (fuelUsed > mFuel) {654 elapsedFiring = mFuel / fuelUsed * elapsed;655 fuelUsed = mFuel;656 657 // Oddball case where we adjust the "control" from here658 mEngineFiring = false;659 }660 661 mFuel -= fuelUsed;662 663 // have this much acceleration from the engine664 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 }670 361 671 362 synchronized(planetsLock) { … … 680 371 } 681 372 } 682 683 double dxOld = mDX;684 double dyOld = mDY;685 686 // figure speeds for the end of the period687 mDX += ddx;688 mDY += ddy;689 690 // figure position based on average speed during the period691 mX += elapsed * (mDX + dxOld) / 2;692 mY += elapsed * (mDY + dyOld) / 2;693 373 694 374 mLastTime = now; 695 696 // Evaluate if we have landed ... stop the game697 double yLowerBound = TARGET_PAD_HEIGHT + mLanderHeight / 2698 - 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 && mX704 + 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) < mGoalAngle709 && speed > PHYS_SPEED_HYPERSPACE) {710 mWinsInARow++;711 doStart();712 713 return;714 // Oddball case: this case does a return, all other cases715 // fall through to setMode() below.716 }717 }718 375 } 719 376 } … … 764 421 } 765 422 766 if(target != null ) {423 if(target != null && thread.planetSelected.getFaction() != 0) { 767 424 synchronized(thread.fleetsLock) { 768 425 Fleet f = new Fleet(thread.planetSelected, target, 1, 1); 426 f.setFaction(thread.planetSelected.getFaction()); 769 427 thread.fleets.add(f); 770 428 } -
src/com/example/helloandroid/Planet.java
r61c4fbc r95509e1 62 62 public int getRadius() { 63 63 return radius; 64 } 65 66 public int getFaction() { 67 return faction; 64 68 } 65 69 … … 128 132 129 133 public void update() { 130 if(faction != 0)131 numShips++;134 //if(faction != 0) 135 //numShips++; 132 136 133 137 }
Note:
See TracChangeset
for help on using the changeset viewer.