Changes in / [17dfb52:0986844] in galcon-client


Ignore:
Files:
4 added
4 edited

Legend:

Unmodified
Added
Removed
  • src/com/example/helloandroid/Fleet.java

    r17dfb52 r0986844  
    44
    55import android.graphics.Canvas;
    6 import android.graphics.Color;
    76import android.graphics.Paint;
    87import android.graphics.Path;
     
    2423        /* Optimising: pre-calculate paths */
    2524        public Fleet(Planet source, Planet destination, int numShips, int faction) {
    26                 source.setNumShips(source.getNumShips()-numShips);
    27                
    2825                //Calculate initial coordinates and direction
    2926                if((destination.getX() - source.getX()) != 0){
     
    137134        }
    138135
    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               
    140140                Path p = new Path();
    141141               
     
    145145                p.lineTo((float)(x+5*Math.cos(direction+Math.PI/2)), (float)(y+5*Math.sin(direction+Math.PI/2)));
    146146               
    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);
    170147               
    171148                canvas.drawPath(p, linePaint);
    172                
    173                 linePaint.setColor(prevC);
    174149        }
    175150
  • src/com/example/helloandroid/Game.java

    r17dfb52 r0986844  
    7575                mThread.unpause();
    7676                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;
    7786        }
    7887
     
    104113            // we were just launched: set up a new game
    105114                mThread.setState(DrawingThread.STATE_RUNNING);
    106             Log.w("Galcon", "SIS is null");
     115            Log.w(this.getClass().getName(), "SIS is null");
    107116        } 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");
    109120        }
    110121    }
     
    129140        // just have the View's thread save its state into our Bundle
    130141        super.onSaveInstanceState(outState);
    131         Log.w("Galcon", "SIS called");
     142        mThread.saveState(outState);
     143        Log.w(this.getClass().getName(), "SIS called");
    132144    }
    133145}
  • src/com/example/helloandroid/GameView.java

    r17dfb52 r0986844  
    66import android.content.Context;
    77import android.content.res.Resources;
     8import android.graphics.Bitmap;
     9import android.graphics.BitmapFactory;
    810import android.graphics.Canvas;
    9 import android.graphics.Color;
    1011import android.graphics.Paint;
     12import android.graphics.drawable.Drawable;
    1113import android.os.Bundle;
    1214import android.os.Handler;
     
    3234    class DrawingThread extends Thread {
    3335        /*
     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        /*
    3454         * State-tracking constants
    3555         */
     
    4161
    4262        /*
     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        /*
    4371         * UI constants (i.e. the speed & fuel bars)
    4472         */
    4573        public static final int UI_BAR = 100; // width of the bar(s)
    4674        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";
    4792
    4893        /*
    4994         * Member (state) fields
    5095         */
     96        /** The drawable to use as the background of the animation canvas */
     97        private Bitmap mBackgroundImage;
    5198
    5299        private int mCanvasHeight = 1;
    53100        private int mCanvasWidth = 1;
    54101
     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
    55127        /** Message handler used by thread to interact with TextView */
    56128        private Handler mHandler;
    57129
     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
    58145        /** Used to figure out elapsed time between frames */
    59146        private long mLastTime;
     
    62149        private Paint mLinePaint, mTextPaint;
    63150
     151        /** "Bad" speed-too-high variant of the line color. */
     152        private Paint mLinePaintBad;
     153
    64154        /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */
    65155        private int mMode;
    66156
     157        /** Currently rotating, -1 left, 0 none, 1 right. */
     158        private int mRotating;
     159
    67160        /** Indicate whether the surface has been created & is ready to draw */
    68161        private boolean mRun = false;
     
    70163        /** Handle to the surface manager object we interact with */
    71164        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;
    72172       
    73173        public Object planetsLock, fleetsLock;
     
    84184            mContext = context;
    85185
     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
    86198            // Initialize paints for speedometer
    87199            mLinePaint = new Paint();
     
    89201            mLinePaint.setARGB(255, 0, 255, 0);
    90202
     203            mLinePaintBad = new Paint();
     204            mLinePaintBad.setAntiAlias(true);
     205            mLinePaintBad.setARGB(255, 120, 180, 0);
     206           
    91207            mTextPaint = new Paint();
    92208            mTextPaint.setAntiAlias(true);
    93209            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;
    94222       
    95223            planetsLock = new Object();
     
    107235        public void doStart() {
    108236            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
    109275                mLastTime = System.currentTimeMillis() + 100;
    110276                setState(STATE_RUNNING);
     
    118284            synchronized (mSurfaceHolder) {
    119285                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);
    120317            }
    121318        }
     
    147344
    148345        /**
     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        /**
    149395         * Used to signal the thread whether it should be running or not.
    150396         * Passing true allows the thread to run; passing false will shut it
     
    198444                    mHandler.sendMessage(msg);
    199445                } else {
     446                    mRotating = 0;
     447                    mEngineFiring = false;
    200448                    Resources res = mContext.getResources();
    201449                    CharSequence str = "";
     
    206454                    else if (mMode == STATE_LOSE)
    207455                        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);
    208460
    209461                    if (message != null) {
    210462                        str = message + "\n" + str;
    211463                    }
     464
     465                    if (mMode == STATE_LOSE) mWinsInARow = 0;
    212466
    213467                    Message msg = mHandler.obtainMessage();
     
    248502                        }
    249503                }
     504                       
     505                // don't forget to resize the background image
     506                mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true);
    250507            }
    251508        }
     
    325582         */
    326583        private void doDraw(Canvas canvas) {
    327                 canvas.drawColor(Color.BLACK);
    328                
     584                canvas.drawBitmap(mBackgroundImage, 0, 0, null);
    329585                synchronized(planetsLock) {
    330586                        for(Planet p : planets) {
     
    342598                }
    343599                }
     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();
    344612        }
    345613
     
    358626            // by 100ms or whatever.
    359627            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            }
    360670
    361671            synchronized(planetsLock) {
     
    370680                }
    371681            }
     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;
    372693
    373694            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            }
    374718        }
    375719    }
     
    420764                        }
    421765                       
    422                         if(target != null && thread.planetSelected.getFaction() != 0) {
     766                        if(target != null) {
    423767                                synchronized(thread.fleetsLock) {
    424768                                Fleet f = new Fleet(thread.planetSelected, target, 1, 1);
    425                                 f.setFaction(thread.planetSelected.getFaction());
    426769                                thread.fleets.add(f);
    427770                    }
  • src/com/example/helloandroid/Planet.java

    r17dfb52 r0986844  
    6262        public int getRadius() {
    6363                return radius;
    64         }
    65        
    66         public int getFaction() {
    67                 return faction;
    6864        }
    6965       
     
    132128       
    133129        public void update() {
    134                 //if(faction != 0)
    135                         //numShips++;
     130                if(faction != 0)
     131                        numShips++;
    136132               
    137133        }
Note: See TracChangeset for help on using the changeset viewer.