14455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler/* 28df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler * Copyright (C) 2015 The Android Open Source Project 34455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * 44455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 54455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * you may not use this file except in compliance with the License. 64455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * You may obtain a copy of the License at 74455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * 84455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * http://www.apache.org/licenses/LICENSE-2.0 94455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * 104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * Unless required by applicable law or agreed to in writing, software 114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * distributed under the License is distributed on an "AS IS" BASIS, 124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * See the License for the specific language governing permissions and 144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler * limitations under the License. 154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler */ 164455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerpackage com.android.systemui.egg; 184455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport android.animation.LayoutTransition; 204455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.animation.TimeAnimator; 214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.content.Context; 224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.content.res.Resources; 232200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Canvas; 242200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Color; 252200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Matrix; 262200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Outline; 272200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Paint; 282200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Path; 292200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.PorterDuff; 308df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport android.graphics.PorterDuffColorFilter; 312200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.graphics.Rect; 324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.graphics.drawable.Drawable; 334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.graphics.drawable.GradientDrawable; 34195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandlerimport android.media.AudioAttributes; 35195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandlerimport android.media.AudioManager; 36195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandlerimport android.os.Vibrator; 374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.util.AttributeSet; 384455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.util.Log; 392200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.view.Gravity; 408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport android.view.InputDevice; 412200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.view.KeyEvent; 428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport android.view.LayoutInflater; 432200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.view.MotionEvent; 442200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.view.View; 458df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport android.view.ViewGroup; 462200f86f800876d005f911e6864708fa9772d03aDan Sandlerimport android.view.ViewOutlineProvider; 474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.widget.FrameLayout; 484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.widget.ImageView; 494455da985d4bc8b3dce8ae35deaef41049d121daDan Sandlerimport android.widget.TextView; 504455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport com.android.internal.logging.MetricsLogger; 528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerimport com.android.systemui.R; 538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 54c0d7058b14c24cd07912f5629c26b39b7b4673d5Winsonimport java.util.ArrayList; 55c0d7058b14c24cd07912f5629c26b39b7b4673d5Winson 568df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler// It's like LLand, but "M"ultiplayer. 578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandlerpublic class MLand extends FrameLayout { 588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final String TAG = "MLand"; 594455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 604455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 612200f86f800876d005f911e6864708fa9772d03aDan Sandler public static final boolean DEBUG_DRAW = false; // DEBUG 624455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final boolean SHOW_TOUCHES = true; 648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 65195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler public static void L(String s, Object ... objects) { 664455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (DEBUG) { 678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler Log.d(TAG, objects.length == 0 ? s : String.format(s, objects)); 684455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 694455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 704455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final float PI_2 = (float) (Math.PI/2); 728df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 734455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final boolean AUTOSTART = true; 744455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final boolean HAVE_STARS = true; 754455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final float DEBUG_SPEED_MULTIPLIER = 0.5f; // only if DEBUG 77195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler public static final boolean DEBUG_IDDQD = Log.isLoggable(TAG + ".iddqd", Log.DEBUG); 784455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final int DEFAULT_PLAYERS = 1; 808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final int MIN_PLAYERS = 1; 818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static final int MAX_PLAYERS = 6; 828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static final float CONTROLLER_VIBRATION_MULTIPLIER = 2f; 842200f86f800876d005f911e6864708fa9772d03aDan Sandler 854455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private static class Params { 864455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float TRANSLATION_PER_SEC; 874455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int OBSTACLE_SPACING, OBSTACLE_PERIOD; 884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int BOOST_DV; 894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int PLAYER_HIT_SIZE; 904455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int PLAYER_SIZE; 912200f86f800876d005f911e6864708fa9772d03aDan Sandler public int OBSTACLE_WIDTH, OBSTACLE_STEM_WIDTH; 924455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int OBSTACLE_GAP; 934455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int OBSTACLE_MIN; 944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int BUILDING_WIDTH_MIN, BUILDING_WIDTH_MAX; 954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int BUILDING_HEIGHT_MIN; 964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int CLOUD_SIZE_MIN, CLOUD_SIZE_MAX; 974455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int STAR_SIZE_MIN, STAR_SIZE_MAX; 984455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int G; 994455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int MAX_V; 1004455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float SCENERY_Z, OBSTACLE_Z, PLAYER_Z, PLAYER_Z_BOOST, HUD_Z; 1014455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Params(Resources res) { 1024455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler TRANSLATION_PER_SEC = res.getDimension(R.dimen.translation_per_sec); 1034455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler OBSTACLE_SPACING = res.getDimensionPixelSize(R.dimen.obstacle_spacing); 1044455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler OBSTACLE_PERIOD = (int) (OBSTACLE_SPACING / TRANSLATION_PER_SEC); 1054455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler BOOST_DV = res.getDimensionPixelSize(R.dimen.boost_dv); 1064455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PLAYER_HIT_SIZE = res.getDimensionPixelSize(R.dimen.player_hit_size); 1074455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PLAYER_SIZE = res.getDimensionPixelSize(R.dimen.player_size); 1084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler OBSTACLE_WIDTH = res.getDimensionPixelSize(R.dimen.obstacle_width); 1092200f86f800876d005f911e6864708fa9772d03aDan Sandler OBSTACLE_STEM_WIDTH = res.getDimensionPixelSize(R.dimen.obstacle_stem_width); 1104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler OBSTACLE_GAP = res.getDimensionPixelSize(R.dimen.obstacle_gap); 1114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler OBSTACLE_MIN = res.getDimensionPixelSize(R.dimen.obstacle_height_min); 1124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler BUILDING_HEIGHT_MIN = res.getDimensionPixelSize(R.dimen.building_height_min); 1134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler BUILDING_WIDTH_MIN = res.getDimensionPixelSize(R.dimen.building_width_min); 1144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler BUILDING_WIDTH_MAX = res.getDimensionPixelSize(R.dimen.building_width_max); 1154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler CLOUD_SIZE_MIN = res.getDimensionPixelSize(R.dimen.cloud_size_min); 1164455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler CLOUD_SIZE_MAX = res.getDimensionPixelSize(R.dimen.cloud_size_max); 1174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler STAR_SIZE_MIN = res.getDimensionPixelSize(R.dimen.star_size_min); 1184455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler STAR_SIZE_MAX = res.getDimensionPixelSize(R.dimen.star_size_max); 1194455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1204455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler G = res.getDimensionPixelSize(R.dimen.G); 1214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler MAX_V = res.getDimensionPixelSize(R.dimen.max_v); 1224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler SCENERY_Z = res.getDimensionPixelSize(R.dimen.scenery_z); 1244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler OBSTACLE_Z = res.getDimensionPixelSize(R.dimen.obstacle_z); 1254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PLAYER_Z = res.getDimensionPixelSize(R.dimen.player_z); 1264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PLAYER_Z_BOOST = res.getDimensionPixelSize(R.dimen.player_z_boost); 1274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler HUD_Z = res.getDimensionPixelSize(R.dimen.hud_z); 128195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler 129195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler // Sanity checking 130195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler if (OBSTACLE_MIN <= OBSTACLE_WIDTH / 2) { 1318df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler L("error: obstacles might be too short, adjusting"); 132195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler OBSTACLE_MIN = OBSTACLE_WIDTH / 2 + 1; 133195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler } 1344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 1354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 1364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private TimeAnimator mAnim; 138195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler private Vibrator mVibrator; 139195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler private AudioManager mAudioManager; 140195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler private final AudioAttributes mAudioAttrs = new AudioAttributes.Builder() 141195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler .setUsage(AudioAttributes.USAGE_GAME).build(); 1424455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1434455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private View mSplash; 1448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private ViewGroup mScoreFields; 1454455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private ArrayList<Player> mPlayers = new ArrayList<Player>(); 1474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private ArrayList<Obstacle> mObstaclesInPlay = new ArrayList<Obstacle>(); 1484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1494455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private float t, dt; 1504455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1514455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private float mLastPipeTime; // in sec 1528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private int mCurrentPipeId; // basically, equivalent to the current score 1534455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private int mWidth, mHeight; 1544455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private boolean mAnimating, mPlaying; 1554455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private boolean mFrozen; // after death, a short backoff 1568df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private int mCountdown = 0; 1572200f86f800876d005f911e6864708fa9772d03aDan Sandler private boolean mFlipped; 1584455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private int mTaps; 1608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 1614455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private int mTimeOfDay; 1624455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private static final int DAY = 0, NIGHT = 1, TWILIGHT = 2, SUNSET = 3; 1634455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private static final int[][] SKIES = { 1644455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler { 0xFFc0c0FF, 0xFFa0a0FF }, // DAY 1654455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler { 0xFF000010, 0xFF000000 }, // NIGHT 1664455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler { 0xFF000040, 0xFF000010 }, // TWILIGHT 1672200f86f800876d005f911e6864708fa9772d03aDan Sandler { 0xFFa08020, 0xFF204080 }, // SUNSET 1684455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler }; 1694455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private int mScene; 1718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private static final int SCENE_CITY = 0, SCENE_TX = 1, SCENE_ZRH = 2; 1728df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private static final int SCENE_COUNT = 3; 1738df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 1744455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private static Params PARAMS; 1754455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private static float dp = 1f; 1778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 1788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private Paint mTouchPaint, mPlayerTracePaint; 1798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 1808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private ArrayList<Integer> mGameControllers = new ArrayList<>(); 1818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 1828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public MLand(Context context) { 1834455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler this(context, null); 1844455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 1854455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1868df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public MLand(Context context, AttributeSet attrs) { 1874455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler this(context, attrs, 0); 1884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 1894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 1908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public MLand(Context context, AttributeSet attrs, int defStyle) { 1914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context, attrs, defStyle); 1928df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 193195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 194195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setFocusable(true); 1964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PARAMS = new Params(getResources()); 1978df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTimeOfDay = irand(0, SKIES.length - 1); 1988df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScene = irand(0, SCENE_COUNT); 1998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2008df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 2018df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchPaint.setColor(0x80FFFFFF); 2028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchPaint.setStyle(Paint.Style.FILL); 2038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2048df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlayerTracePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 2058df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlayerTracePaint.setColor(0x80FFFFFF); 2068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlayerTracePaint.setStyle(Paint.Style.STROKE); 2078df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlayerTracePaint.setStrokeWidth(2 * dp); 208f5ba6bdafa33720fa6ee692954ac9ab364fdedf5Dan Sandler 209f5ba6bdafa33720fa6ee692954ac9ab364fdedf5Dan Sandler // we assume everything will be laid out left|top 210f5ba6bdafa33720fa6ee692954ac9ab364fdedf5Dan Sandler setLayoutDirection(LAYOUT_DIRECTION_LTR); 2118df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setupPlayers(DEFAULT_PLAYERS); 2138df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MetricsLogger.count(getContext(), "egg_mland_create", 1); 2158df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2178df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler @Override 2188df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void onAttachedToWindow() { 2198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler super.onAttachedToWindow(); 2208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler dp = getResources().getDisplayMetrics().density; 2218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2228df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler reset(); 2238df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (AUTOSTART) { 2248df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler start(false); 2258df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 2284455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 2294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean willNotDraw() { 2304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return !DEBUG; 2314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 2334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int getGameWidth() { return mWidth; } 2344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int getGameHeight() { return mHeight; } 2354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float getGameTime() { return t; } 2364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float getLastTimeStep() { return dt; } 2374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 2388df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void setScoreFieldHolder(ViewGroup vg) { 2398df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreFields = vg; 2408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (vg != null) { 2418df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final LayoutTransition lt = new LayoutTransition(); 2428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler lt.setDuration(250); 2438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreFields.setLayoutTransition(lt); 2448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2458df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (Player p : mPlayers) { 2468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreFields.addView(p.mScoreField, 2478df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler new MarginLayoutParams( 2488df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MarginLayoutParams.WRAP_CONTENT, 2498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MarginLayoutParams.MATCH_PARENT)); 2504455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2514455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2524455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 2534455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void setSplash(View v) { 2544455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mSplash = v; 2554455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2564455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 2578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static boolean isGamePad(InputDevice dev) { 2588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int sources = dev.getSources(); 2598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // Verify that the device has gamepad buttons, control sticks, or both. 2618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) 2628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler || ((sources & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK)); 2638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public ArrayList getGameControllers() { 2668df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGameControllers.clear(); 2678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int[] deviceIds = InputDevice.getDeviceIds(); 2688df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int deviceId : deviceIds) { 2698df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler InputDevice dev = InputDevice.getDevice(deviceId); 2708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (isGamePad(dev)) { 2718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (!mGameControllers.contains(deviceId)) { 2728df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGameControllers.add(deviceId); 2738df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2748df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2758df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return mGameControllers; 2778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public int getControllerPlayer(int id) { 2808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int player = mGameControllers.indexOf(id); 2818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (player < 0 || player >= mPlayers.size()) return 0; 2828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return player; 2838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 2848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2854455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 2864455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler protected void onSizeChanged(int w, int h, int oldw, int oldh) { 2878df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler dp = getResources().getDisplayMetrics().density; 2888df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler stop(); 2908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler reset(); 2924455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (AUTOSTART) { 2934455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler start(false); 2944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 2964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 2978df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final static float hsv[] = {0, 0, 0}; 2988df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 2998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private static float luma(int bgcolor) { 3008df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return 0.2126f * (float) (bgcolor & 0xFF0000) / 0xFF0000 3018df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler + 0.7152f * (float) (bgcolor & 0xFF00) / 0xFF00 3028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler + 0.0722f * (float) (bgcolor & 0xFF) / 0xFF; 3038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3048df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3058df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public Player getPlayer(int i) { 3068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return i < mPlayers.size() ? mPlayers.get(i) : null; 3078df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3088df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3098df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private int addPlayerInternal(Player p) { 3108df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlayers.add(p); 3118df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler realignPlayers(); 3128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler TextView scoreField = (TextView) 3138df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler LayoutInflater.from(getContext()).inflate(R.layout.mland_scorefield, null); 3148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mScoreFields != null) { 3158df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreFields.addView(scoreField, 3168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler new MarginLayoutParams( 3178df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MarginLayoutParams.WRAP_CONTENT, 3188df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MarginLayoutParams.MATCH_PARENT)); 3198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.setScoreField(scoreField); 3218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return mPlayers.size()-1; 3228df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3238df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3248df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void removePlayerInternal(Player p) { 3258df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mPlayers.remove(p)) { 3268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler removeView(p); 3278df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreFields.removeView(p.mScoreField); 3288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler realignPlayers(); 3298df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3308df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3318df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3328df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void realignPlayers() { 3338df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int N = mPlayers.size(); 3348df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler float x = (mWidth - (N-1) * PARAMS.PLAYER_SIZE) / 2; 3358df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int i=0; i<N; i++) { 3368df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = mPlayers.get(i); 3378df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.setX(x); 3388df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler x += PARAMS.PLAYER_SIZE; 3398df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3418df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void clearPlayers() { 3438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler while (mPlayers.size() > 0) { 3448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler removePlayerInternal(mPlayers.get(0)); 3458df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3478df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3488df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void setupPlayers(int num) { 3498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler clearPlayers(); 3508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int i=0; i<num; i++) { 3518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler addPlayerInternal(Player.create(this)); 3528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3548df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3558df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void addPlayer() { 3568df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (getNumPlayers() == MAX_PLAYERS) return; 3578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler addPlayerInternal(Player.create(this)); 3588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public int getNumPlayers() { 3618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return mPlayers.size(); 3628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 3648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void removePlayer() { 3658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (getNumPlayers() == MIN_PLAYERS) return; 3668df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler removePlayerInternal(mPlayers.get(mPlayers.size() - 1)); 3678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3684455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 3698df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void thump(int playerIndex, long ms) { 370195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) { 371195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler // No interruptions. Not even game haptics. 372195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler return; 373195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler } 3748df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (playerIndex < mGameControllers.size()) { 3758df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int controllerId = mGameControllers.get(playerIndex); 3768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler InputDevice dev = InputDevice.getDevice(controllerId); 3778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (dev != null && dev.getVibrator().hasVibrator()) { 3788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler dev.getVibrator().vibrate( 3798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler (long) (ms * CONTROLLER_VIBRATION_MULTIPLIER), 3808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mAudioAttrs); 3818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return; 3828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 3848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mVibrator.vibrate(ms, mAudioAttrs); 385195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler } 386195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler 387195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler public void reset() { 3884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler L("reset"); 3894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Drawable sky = new GradientDrawable( 3904455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler GradientDrawable.Orientation.BOTTOM_TOP, 3914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler SKIES[mTimeOfDay] 3924455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler ); 3934455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sky.setDither(true); 3944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setBackground(sky); 3954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 3962200f86f800876d005f911e6864708fa9772d03aDan Sandler mFlipped = frand() > 0.5f; 3972200f86f800876d005f911e6864708fa9772d03aDan Sandler setScaleX(mFlipped ? -1 : 1); 3984455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 3994455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler int i = getChildCount(); 4004455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler while (i-->0) { 4014455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final View v = getChildAt(i); 4024455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (v instanceof GameView) { 4034455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler removeViewAt(i); 4044455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4054455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4064455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4074455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mObstaclesInPlay.clear(); 4088df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mCurrentPipeId = 0; 4094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mWidth = getWidth(); 4114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mHeight = getHeight(); 4124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler boolean showingSun = (mTimeOfDay == DAY || mTimeOfDay == SUNSET) && frand() > 0.25; 4144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (showingSun) { 4154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Star sun = new Star(getContext()); 4164455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.setBackgroundResource(R.drawable.sun); 4174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int w = getResources().getDimensionPixelSize(R.dimen.sun_size); 4184455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.setTranslationX(frand(w, mWidth-w)); 4194455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (mTimeOfDay == DAY) { 4204455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.setTranslationY(frand(w, (mHeight * 0.66f))); 4214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.getBackground().setTint(0); 4224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } else { 4234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.setTranslationY(frand(mHeight * 0.66f, mHeight - w)); 4244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.getBackground().setTintMode(PorterDuff.Mode.SRC_ATOP); 4254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sun.getBackground().setTint(0xC0FF8000); 4264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4284455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler addView(sun, new LayoutParams(w, w)); 4294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (!showingSun) { 4314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final boolean dark = mTimeOfDay == NIGHT || mTimeOfDay == TWILIGHT; 4324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final float ff = frand(); 4334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if ((dark && ff < 0.75f) || ff < 0.5f) { 4344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Star moon = new Star(getContext()); 4354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler moon.setBackgroundResource(R.drawable.moon); 4364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler moon.getBackground().setAlpha(dark ? 255 : 128); 4374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler moon.setScaleX(frand() > 0.5 ? -1 : 1); 4384455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler moon.setRotation(moon.getScaleX() * frand(5, 30)); 4394455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int w = getResources().getDimensionPixelSize(R.dimen.sun_size); 4404455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler moon.setTranslationX(frand(w, mWidth - w)); 4414455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler moon.setTranslationY(frand(w, mHeight - w)); 4424455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler addView(moon, new LayoutParams(w, w)); 4434455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4444455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4454455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4464455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int mh = mHeight / 6; 4474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final boolean cloudless = frand() < 0.25; 4484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int N = 20; 4494455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (i=0; i<N; i++) { 4504455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final float r1 = frand(); 4514455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Scenery s; 4524455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (HAVE_STARS && r1 < 0.3 && mTimeOfDay != DAY) { 4534455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler s = new Star(getContext()); 4544455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } else if (r1 < 0.6 && !cloudless) { 4554455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler s = new Cloud(getContext()); 4564455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } else { 4578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler switch (mScene) { 4588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler case SCENE_ZRH: 4598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler s = new Mountain(getContext()); 4608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler break; 4618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler case SCENE_TX: 4628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler s = new Cactus(getContext()); 4638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler break; 4648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler case SCENE_CITY: 4658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler default: 4668df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler s = new Building(getContext()); 4678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler break; 4688df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 4698df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler s.z = (float) i / N; 4708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // no more shadows for these things 4718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //s.setTranslationZ(PARAMS.SCENERY_Z * (1+s.z)); 4724455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler s.v = 0.85f * s.z; // buildings move proportional to their distance 4738df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mScene == SCENE_CITY) { 4748df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler s.setBackgroundColor(Color.GRAY); 4758df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler s.h = irand(PARAMS.BUILDING_HEIGHT_MIN, mh); 4768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 4778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int c = (int)(255f*s.z); 4788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Drawable bg = s.getBackground(); 4798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (bg != null) bg.setColorFilter(Color.rgb(c,c,c), PorterDuff.Mode.MULTIPLY); 4804455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4814455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final LayoutParams lp = new LayoutParams(s.w, s.h); 4824455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (s instanceof Building) { 4834455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler lp.gravity = Gravity.BOTTOM; 4844455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } else { 4854455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler lp.gravity = Gravity.TOP; 4864455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final float r = frand(); 4874455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (s instanceof Star) { 4884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler lp.topMargin = (int) (r * r * mHeight); 4894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } else { 4904455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler lp.topMargin = (int) (1 - r*r * mHeight/2) + mHeight/2; 4914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4924455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4934455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4948df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 4954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler addView(s, lp); 4964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler s.setTranslationX(frand(-lp.width, mWidth + lp.width)); 4974455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 4984455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 4998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (Player p : mPlayers) { 5008df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler addView(p); // put it back! 5018df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.reset(); 5028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5048df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler realignPlayers(); 5052200f86f800876d005f911e6864708fa9772d03aDan Sandler 5068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mAnim != null) { 5078df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mAnim.cancel(); 5088df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnim = new TimeAnimator(); 5104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnim.setTimeListener(new TimeAnimator.TimeListener() { 5114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 5124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void onTimeUpdate(TimeAnimator timeAnimator, long t, long dt) { 5134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler step(t, dt); 5144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 5154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler }); 5164455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 5174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 518195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler public void start(boolean startPlaying) { 5198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler L("start(startPlaying=%s)", startPlaying ? "true" : "false"); 5208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (startPlaying && mCountdown <= 0) { 5218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler showSplash(); 5224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 5238df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.findViewById(R.id.play_button).setEnabled(false); 5244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 5258df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final View playImage = mSplash.findViewById(R.id.play_button_image); 5268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final TextView playText = (TextView) mSplash.findViewById(R.id.play_button_text); 5274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 5288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler playImage.animate().alpha(0f); 5298df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler playText.animate().alpha(1f); 5304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 5318df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mCountdown = 3; 5328df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler post(new Runnable() { 5338df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler @Override 5348df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void run() { 5358df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mCountdown == 0) { 5368df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler startPlaying(); 5378df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } else { 5388df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler postDelayed(this, 500); 5398df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler playText.setText(String.valueOf(mCountdown)); 5418df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mCountdown--; 5428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler }); 5448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5458df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (Player p : mPlayers) { 5478df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.setVisibility(View.INVISIBLE); 5484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 5498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5504455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (!mAnimating) { 5514455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnim.start(); 5524455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnimating = true; 5534455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 5544455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 5554455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 5568df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void hideSplash() { 5578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mSplash != null && mSplash.getVisibility() == View.VISIBLE) { 5588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.setClickable(false); 5598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.animate().alpha(0).translationZ(0).setDuration(300).withEndAction( 5608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler new Runnable() { 5618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler @Override 5628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void run() { 5638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.setVisibility(View.GONE); 5648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5668df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler ); 5678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5688df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5698df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void showSplash() { 5718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mSplash != null && mSplash.getVisibility() != View.VISIBLE) { 5728df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.setClickable(true); 5738df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.setAlpha(0f); 5748df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.setVisibility(View.VISIBLE); 5758df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.animate().alpha(1f).setDuration(1000); 5768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.findViewById(R.id.play_button_image).setAlpha(1f); 5778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.findViewById(R.id.play_button_text).setAlpha(0f); 5788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.findViewById(R.id.play_button).setEnabled(true); 5798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mSplash.findViewById(R.id.play_button).requestFocus(); 5808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 5828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void startPlaying() { 5848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlaying = true; 5858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5868df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler t = 0; 5878df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // there's a sucker born every OBSTACLE_PERIOD 5888df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mLastPipeTime = getGameTime() - PARAMS.OBSTACLE_PERIOD; 5898df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler hideSplash(); 5918df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5928df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler realignPlayers(); 5938df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTaps = 0; 5948df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 5958df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int N = mPlayers.size(); 5968df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MetricsLogger.histogram(getContext(), "egg_mland_players", N); 5978df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int i=0; i<N; i++) { 5988df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = mPlayers.get(i); 5998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.setVisibility(View.VISIBLE); 6008df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.reset(); 6018df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.start(); 6028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.boost(-1, -1); // start you off flying! 6038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.unboost(); // not forever, though 6048df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 6058df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 6068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 607195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler public void stop() { 6084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (mAnimating) { 6094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnim.cancel(); 6104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnim = null; 6114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mAnimating = false; 6128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlaying = false; 6138df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTimeOfDay = irand(0, SKIES.length - 1); // for next reset 6148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScene = irand(0, SCENE_COUNT); 6154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mFrozen = true; 6168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (Player p : mPlayers) { 6178df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.die(); 6188df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 6194455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler postDelayed(new Runnable() { 6204455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 6214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void run() { 6224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mFrozen = false; 6234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler }, 250); 6254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6284455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final float lerp(float x, float a, float b) { 6294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return (b - a) * x + a; 6304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final float rlerp(float v, float a, float b) { 6334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return (v - a) / (b - a); 6344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final float clamp(float f) { 6374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return f < 0f ? 0f : f > 1f ? 1f : f; 6384455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6394455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6404455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final float frand() { 6414455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return (float) Math.random(); 6424455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6434455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6444455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final float frand(float a, float b) { 6454455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return lerp(frand(), a, b); 6464455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public static final int irand(int a, int b) { 6498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return Math.round(frand((float) a, (float) b)); 6508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 6518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 6528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static int pick(int[] l) { 6538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return l[irand(0, l.length-1)]; 6544455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6554455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6564455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private void step(long t_ms, long dt_ms) { 6574455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler t = t_ms / 1000f; // seconds 6584455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler dt = dt_ms / 1000f; 6594455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6604455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (DEBUG) { 6614455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler t *= DEBUG_SPEED_MULTIPLIER; 6624455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler dt *= DEBUG_SPEED_MULTIPLIER; 6634455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6644455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6654455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler // 1. Move all objects and update bounds 6664455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int N = getChildCount(); 6674455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler int i = 0; 6684455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (; i<N; i++) { 6694455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final View v = getChildAt(i); 6704455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (v instanceof GameView) { 6714455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler ((GameView) v).step(t_ms, dt_ms, t, dt); 6724455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6734455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 6744455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 6758df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mPlaying) { 6768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int livingPlayers = 0; 6778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (i = 0; i < mPlayers.size(); i++) { 6788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = getPlayer(i); 6798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 6808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (p.mAlive) { 6818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // 2. Check for altitude 6828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (p.below(mHeight)) { 6838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (DEBUG_IDDQD) { 6848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler poke(i); 6858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler unpoke(i); 6868df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } else { 6878df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler L("player %d hit the floor", i); 6888df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler thump(i, 80); 6898df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.die(); 6908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 6918df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 6928df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 6938df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // 3. Check for obstacles 6948df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int maxPassedStem = 0; 6958df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int j = mObstaclesInPlay.size(); j-- > 0; ) { 6968df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Obstacle ob = mObstaclesInPlay.get(j); 6978df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (ob.intersects(p) && !DEBUG_IDDQD) { 6988df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler L("player hit an obstacle"); 6998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler thump(i, 80); 7008df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.die(); 7018df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } else if (ob.cleared(p)) { 7028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (ob instanceof Stem) { 7038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler maxPassedStem = Math.max(maxPassedStem, ((Stem)ob).id); 7048df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7058df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7078df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 7088df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (maxPassedStem > p.mScore) { 7098df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.addScore(1); 7108df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7118df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 7138df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (p.mAlive) livingPlayers++; 7144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 7154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 7168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (livingPlayers == 0) { 7174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler stop(); 7184455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 7198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MetricsLogger.count(getContext(), "egg_mland_taps", mTaps); 7208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTaps = 0; 7218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int playerCount = mPlayers.size(); 7228df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int pi=0; pi<playerCount; pi++) { 7238df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = mPlayers.get(pi); 7248df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler MetricsLogger.histogram(getContext(), "egg_mland_score", p.getScore()); 7258df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 7274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 7284455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 7294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler // 4. Handle edge of screen 7304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler // Walk backwards to make sure removal is safe 7314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler while (i-->0) { 7324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final View v = getChildAt(i); 7334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (v instanceof Obstacle) { 7344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (v.getTranslationX() + v.getWidth() < 0) { 7354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler removeViewAt(i); 7368df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mObstaclesInPlay.remove(v); 7374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 7384455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } else if (v instanceof Scenery) { 7394455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Scenery s = (Scenery) v; 7404455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (v.getTranslationX() + s.w < 0) { 7414455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler v.setTranslationX(getWidth()); 7424455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 7434455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 7444455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 7454455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 7464455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler // 3. Time for more obstacles! 7474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (mPlaying && (t - mLastPipeTime) > PARAMS.OBSTACLE_PERIOD) { 7484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mLastPipeTime = t; 7498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mCurrentPipeId ++; 750195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler final int obstacley = 751195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler (int)(frand() * (mHeight - 2*PARAMS.OBSTACLE_MIN - PARAMS.OBSTACLE_GAP)) + 752195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler PARAMS.OBSTACLE_MIN; 7534455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 7542200f86f800876d005f911e6864708fa9772d03aDan Sandler final int inset = (PARAMS.OBSTACLE_WIDTH - PARAMS.OBSTACLE_STEM_WIDTH) / 2; 7552200f86f800876d005f911e6864708fa9772d03aDan Sandler final int yinset = PARAMS.OBSTACLE_WIDTH/2; 7562200f86f800876d005f911e6864708fa9772d03aDan Sandler 7572200f86f800876d005f911e6864708fa9772d03aDan Sandler final int d1 = irand(0,250); 7582200f86f800876d005f911e6864708fa9772d03aDan Sandler final Obstacle s1 = new Stem(getContext(), obstacley - yinset, false); 7592200f86f800876d005f911e6864708fa9772d03aDan Sandler addView(s1, new LayoutParams( 7602200f86f800876d005f911e6864708fa9772d03aDan Sandler PARAMS.OBSTACLE_STEM_WIDTH, 7612200f86f800876d005f911e6864708fa9772d03aDan Sandler (int) s1.h, 7622200f86f800876d005f911e6864708fa9772d03aDan Sandler Gravity.TOP|Gravity.LEFT)); 7632200f86f800876d005f911e6864708fa9772d03aDan Sandler s1.setTranslationX(mWidth+inset); 7642200f86f800876d005f911e6864708fa9772d03aDan Sandler s1.setTranslationY(-s1.h-yinset); 7652200f86f800876d005f911e6864708fa9772d03aDan Sandler s1.setTranslationZ(PARAMS.OBSTACLE_Z*0.75f); 7662200f86f800876d005f911e6864708fa9772d03aDan Sandler s1.animate() 7672200f86f800876d005f911e6864708fa9772d03aDan Sandler .translationY(0) 7682200f86f800876d005f911e6864708fa9772d03aDan Sandler .setStartDelay(d1) 7692200f86f800876d005f911e6864708fa9772d03aDan Sandler .setDuration(250); 7702200f86f800876d005f911e6864708fa9772d03aDan Sandler mObstaclesInPlay.add(s1); 7712200f86f800876d005f911e6864708fa9772d03aDan Sandler 7722200f86f800876d005f911e6864708fa9772d03aDan Sandler final Obstacle p1 = new Pop(getContext(), PARAMS.OBSTACLE_WIDTH); 7734455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler addView(p1, new LayoutParams( 7744455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PARAMS.OBSTACLE_WIDTH, 7752200f86f800876d005f911e6864708fa9772d03aDan Sandler PARAMS.OBSTACLE_WIDTH, 7764455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler Gravity.TOP|Gravity.LEFT)); 7774455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler p1.setTranslationX(mWidth); 7782200f86f800876d005f911e6864708fa9772d03aDan Sandler p1.setTranslationY(-PARAMS.OBSTACLE_WIDTH); 7792200f86f800876d005f911e6864708fa9772d03aDan Sandler p1.setTranslationZ(PARAMS.OBSTACLE_Z); 7802200f86f800876d005f911e6864708fa9772d03aDan Sandler p1.setScaleX(0.25f); 7818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p1.setScaleY(-0.25f); 7824455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler p1.animate() 7832200f86f800876d005f911e6864708fa9772d03aDan Sandler .translationY(s1.h-inset) 7842200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleX(1f) 7858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler .scaleY(-1f) 7862200f86f800876d005f911e6864708fa9772d03aDan Sandler .setStartDelay(d1) 7874455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler .setDuration(250); 7884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mObstaclesInPlay.add(p1); 7894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 7902200f86f800876d005f911e6864708fa9772d03aDan Sandler final int d2 = irand(0,250); 7912200f86f800876d005f911e6864708fa9772d03aDan Sandler final Obstacle s2 = new Stem(getContext(), 7922200f86f800876d005f911e6864708fa9772d03aDan Sandler mHeight - obstacley - PARAMS.OBSTACLE_GAP - yinset, 7932200f86f800876d005f911e6864708fa9772d03aDan Sandler true); 7942200f86f800876d005f911e6864708fa9772d03aDan Sandler addView(s2, new LayoutParams( 7952200f86f800876d005f911e6864708fa9772d03aDan Sandler PARAMS.OBSTACLE_STEM_WIDTH, 7962200f86f800876d005f911e6864708fa9772d03aDan Sandler (int) s2.h, 7972200f86f800876d005f911e6864708fa9772d03aDan Sandler Gravity.TOP|Gravity.LEFT)); 7982200f86f800876d005f911e6864708fa9772d03aDan Sandler s2.setTranslationX(mWidth+inset); 7992200f86f800876d005f911e6864708fa9772d03aDan Sandler s2.setTranslationY(mHeight+yinset); 8002200f86f800876d005f911e6864708fa9772d03aDan Sandler s2.setTranslationZ(PARAMS.OBSTACLE_Z*0.75f); 8012200f86f800876d005f911e6864708fa9772d03aDan Sandler s2.animate() 8022200f86f800876d005f911e6864708fa9772d03aDan Sandler .translationY(mHeight-s2.h) 8032200f86f800876d005f911e6864708fa9772d03aDan Sandler .setStartDelay(d2) 8042200f86f800876d005f911e6864708fa9772d03aDan Sandler .setDuration(400); 8052200f86f800876d005f911e6864708fa9772d03aDan Sandler mObstaclesInPlay.add(s2); 8062200f86f800876d005f911e6864708fa9772d03aDan Sandler 8072200f86f800876d005f911e6864708fa9772d03aDan Sandler final Obstacle p2 = new Pop(getContext(), PARAMS.OBSTACLE_WIDTH); 8084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler addView(p2, new LayoutParams( 8094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler PARAMS.OBSTACLE_WIDTH, 8102200f86f800876d005f911e6864708fa9772d03aDan Sandler PARAMS.OBSTACLE_WIDTH, 8114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler Gravity.TOP|Gravity.LEFT)); 8124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler p2.setTranslationX(mWidth); 8134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler p2.setTranslationY(mHeight); 8142200f86f800876d005f911e6864708fa9772d03aDan Sandler p2.setTranslationZ(PARAMS.OBSTACLE_Z); 8152200f86f800876d005f911e6864708fa9772d03aDan Sandler p2.setScaleX(0.25f); 8162200f86f800876d005f911e6864708fa9772d03aDan Sandler p2.setScaleY(0.25f); 8174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler p2.animate() 8182200f86f800876d005f911e6864708fa9772d03aDan Sandler .translationY(mHeight-s2.h-yinset) 8192200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleX(1f) 8202200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleY(1f) 8212200f86f800876d005f911e6864708fa9772d03aDan Sandler .setStartDelay(d2) 8224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler .setDuration(400); 8234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler mObstaclesInPlay.add(p2); 8244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 8268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (SHOW_TOUCHES || DEBUG_DRAW) invalidate(); 8274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 8294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 8304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean onTouchEvent(MotionEvent ev) { 831195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler L("touch: %s", ev); 8328df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int actionIndex = ev.getActionIndex(); 8338df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final float x = ev.getX(actionIndex); 8348df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final float y = ev.getY(actionIndex); 8358df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int playerIndex = (int) (getNumPlayers() * (x / getWidth())); 8368df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mFlipped) playerIndex = getNumPlayers() - 1 - playerIndex; 8378df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler switch (ev.getActionMasked()) { 8382200f86f800876d005f911e6864708fa9772d03aDan Sandler case MotionEvent.ACTION_DOWN: 8398df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler case MotionEvent.ACTION_POINTER_DOWN: 8408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler poke(playerIndex, x, y); 8412200f86f800876d005f911e6864708fa9772d03aDan Sandler return true; 8422200f86f800876d005f911e6864708fa9772d03aDan Sandler case MotionEvent.ACTION_UP: 8438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler case MotionEvent.ACTION_POINTER_UP: 8448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler unpoke(playerIndex); 8452200f86f800876d005f911e6864708fa9772d03aDan Sandler return true; 8464455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return false; 8484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8494455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 8504455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 8514455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean onTrackballEvent(MotionEvent ev) { 852195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler L("trackball: %s", ev); 8532200f86f800876d005f911e6864708fa9772d03aDan Sandler switch (ev.getAction()) { 8542200f86f800876d005f911e6864708fa9772d03aDan Sandler case MotionEvent.ACTION_DOWN: 8558df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler poke(0); 8562200f86f800876d005f911e6864708fa9772d03aDan Sandler return true; 8572200f86f800876d005f911e6864708fa9772d03aDan Sandler case MotionEvent.ACTION_UP: 8588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler unpoke(0); 8592200f86f800876d005f911e6864708fa9772d03aDan Sandler return true; 8604455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8614455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return false; 8624455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8634455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 8644455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 8654455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean onKeyDown(int keyCode, KeyEvent ev) { 866195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler L("keyDown: %d", keyCode); 8674455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler switch (keyCode) { 8684455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler case KeyEvent.KEYCODE_DPAD_CENTER: 8694455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler case KeyEvent.KEYCODE_DPAD_UP: 8704455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler case KeyEvent.KEYCODE_SPACE: 8714455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler case KeyEvent.KEYCODE_ENTER: 8724455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler case KeyEvent.KEYCODE_BUTTON_A: 8738df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int player = getControllerPlayer(ev.getDeviceId()); 8748df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler poke(player); 8754455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return true; 8764455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8774455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return false; 8784455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 8794455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 8804455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 8812200f86f800876d005f911e6864708fa9772d03aDan Sandler public boolean onKeyUp(int keyCode, KeyEvent ev) { 882195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler L("keyDown: %d", keyCode); 8832200f86f800876d005f911e6864708fa9772d03aDan Sandler switch (keyCode) { 8842200f86f800876d005f911e6864708fa9772d03aDan Sandler case KeyEvent.KEYCODE_DPAD_CENTER: 8852200f86f800876d005f911e6864708fa9772d03aDan Sandler case KeyEvent.KEYCODE_DPAD_UP: 8862200f86f800876d005f911e6864708fa9772d03aDan Sandler case KeyEvent.KEYCODE_SPACE: 8872200f86f800876d005f911e6864708fa9772d03aDan Sandler case KeyEvent.KEYCODE_ENTER: 8882200f86f800876d005f911e6864708fa9772d03aDan Sandler case KeyEvent.KEYCODE_BUTTON_A: 8898df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int player = getControllerPlayer(ev.getDeviceId()); 8908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler unpoke(player); 8912200f86f800876d005f911e6864708fa9772d03aDan Sandler return true; 8922200f86f800876d005f911e6864708fa9772d03aDan Sandler } 8932200f86f800876d005f911e6864708fa9772d03aDan Sandler return false; 8942200f86f800876d005f911e6864708fa9772d03aDan Sandler } 8952200f86f800876d005f911e6864708fa9772d03aDan Sandler 8962200f86f800876d005f911e6864708fa9772d03aDan Sandler @Override 8974455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean onGenericMotionEvent (MotionEvent ev) { 898195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler L("generic: %s", ev); 8994455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return false; 9004455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9014455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 9028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void poke(int playerIndex) { 9038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler poke(playerIndex, -1, -1); 9048df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 9058df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 9068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void poke(int playerIndex, float x, float y) { 9078df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler L("poke(%d)", playerIndex); 9084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (mFrozen) return; 9094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (!mAnimating) { 9104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler reset(); 9114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (!mPlaying) { 9138df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler start(true); 9148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } else { 9158df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = getPlayer(playerIndex); 9168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (p == null) return; // no player for this controller 9178df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.boost(x, y); 9188df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTaps++; 9198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (DEBUG) { 9208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.dv *= DEBUG_SPEED_MULTIPLIER; 9218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.animate().setDuration((long) (200 / DEBUG_SPEED_MULTIPLIER)); 9228df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 9234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 9268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void unpoke(int playerIndex) { 9278df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler L("unboost(%d)", playerIndex); 9288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mFrozen || !mAnimating || !mPlaying) return; 9298df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = getPlayer(playerIndex); 9308df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (p == null) return; // no player for this controller 9318df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.unboost(); 9322200f86f800876d005f911e6864708fa9772d03aDan Sandler } 9332200f86f800876d005f911e6864708fa9772d03aDan Sandler 9344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 9354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void onDraw(Canvas c) { 9364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super.onDraw(c); 9374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 9388df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (SHOW_TOUCHES) { 9398df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (Player p : mPlayers) { 9408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (p.mTouchX > 0) { 9418df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchPaint.setColor(0x80FFFFFF & p.color); 9428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPlayerTracePaint.setColor(0x80FFFFFF & p.color); 9438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler float x1 = p.mTouchX; 9448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler float y1 = p.mTouchY; 9458df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler c.drawCircle(x1, y1, 100, mTouchPaint); 9468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler float x2 = p.getX() + p.getPivotX(); 9478df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler float y2 = p.getY() + p.getPivotY(); 9488df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler float angle = PI_2 - (float) Math.atan2(x2-x1, y2-y1); 9498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler x1 += 100*Math.cos(angle); 9508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler y1 += 100*Math.sin(angle); 9518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler c.drawLine(x1, y1, x2, y2, mPlayerTracePaint); 9528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 9538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 9548df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 9558df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 9564455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (!DEBUG_DRAW) return; 9574455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 9584455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Paint pt = new Paint(); 9594455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler pt.setColor(0xFFFFFFFF); 9608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (Player p : mPlayers) { 9618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int L = p.corners.length; 9628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int N = L / 2; 9638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int i = 0; i < N; i++) { 9648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int x = (int) p.corners[i * 2]; 9658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int y = (int) p.corners[i * 2 + 1]; 9668df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler c.drawCircle(x, y, 4, pt); 9678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler c.drawLine(x, y, 9688df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.corners[(i * 2 + 2) % L], 9698df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.corners[(i * 2 + 3) % L], 9708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler pt); 9718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 9724455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9734455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 9742200f86f800876d005f911e6864708fa9772d03aDan Sandler pt.setStyle(Paint.Style.STROKE); 9752200f86f800876d005f911e6864708fa9772d03aDan Sandler pt.setStrokeWidth(getResources().getDisplayMetrics().density); 9762200f86f800876d005f911e6864708fa9772d03aDan Sandler 9774455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int M = getChildCount(); 9782200f86f800876d005f911e6864708fa9772d03aDan Sandler pt.setColor(0x8000FF00); 9794455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (int i=0; i<M; i++) { 9804455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final View v = getChildAt(i); 9818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (v instanceof Player) continue; 9824455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (!(v instanceof GameView)) continue; 9832200f86f800876d005f911e6864708fa9772d03aDan Sandler if (v instanceof Pop) { 9848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Pop pop = (Pop) v; 9858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler c.drawCircle(pop.cx, pop.cy, pop.r, pt); 9862200f86f800876d005f911e6864708fa9772d03aDan Sandler } else { 9872200f86f800876d005f911e6864708fa9772d03aDan Sandler final Rect r = new Rect(); 9882200f86f800876d005f911e6864708fa9772d03aDan Sandler v.getHitRect(r); 9892200f86f800876d005f911e6864708fa9772d03aDan Sandler c.drawRect(r, pt); 9902200f86f800876d005f911e6864708fa9772d03aDan Sandler } 9914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9924455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 9934455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler pt.setColor(Color.BLACK); 9944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final StringBuilder sb = new StringBuilder("obstacles: "); 9954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (Obstacle ob : mObstaclesInPlay) { 9964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sb.append(ob.hitRect.toShortString()); 9974455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler sb.append(" "); 9984455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 9994455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler pt.setTextSize(20f); 10004455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler c.drawText(sb.toString(), 20, 100, pt); 10014455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 10024455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 10034455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler static final Rect sTmpRect = new Rect(); 10044455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 10054455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private interface GameView { 10064455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void step(long t_ms, long dt_ms, float t, float dt); 10074455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 10084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 10098df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private static class Player extends ImageView implements GameView { 10104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float dv; 10118df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public int color; 10128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private MLand mLand; 10132200f86f800876d005f911e6864708fa9772d03aDan Sandler private boolean mBoosting; 10148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private float mTouchX = -1, mTouchY = -1; 10158df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private boolean mAlive; 10168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private int mScore; 10178df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private TextView mScoreField; 10182200f86f800876d005f911e6864708fa9772d03aDan Sandler 1019195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler private final int[] sColors = new int[] { 10208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //0xFF78C557, 10218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 0xFFDB4437, 10228df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 0xFF3B78E7, 10238df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 0xFFF4B400, 10248df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 0xFF0F9D58, 10258df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 0xFF7B1880, 10268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 0xFF9E9E9E, 1027195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler }; 10288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static int sNextColor = 0; 1029195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler 10304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private final float[] sHull = new float[] { 10314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.3f, 0f, // left antenna 10324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.7f, 0f, // right antenna 10334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.92f, 0.33f, // off the right shoulder of Orion 10344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.92f, 0.75f, // right hand (our right, not his right) 10354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.6f, 1f, // right foot 10364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.4f, 1f, // left foot BLUE! 10374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 0.08f, 0.75f, // sinistram 1038195c438883dfcca799aa456dfe52d24c077e40daDaniel Sandler 0.08f, 0.33f, // cold shoulder 10394455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler }; 10404455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public final float[] corners = new float[sHull.length]; 10414455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 10428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public static Player create(MLand land) { 10438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final Player p = new Player(land.getContext()); 10448df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.mLand = land; 10458df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.reset(); 10468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler p.setVisibility(View.INVISIBLE); 10478df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler land.addView(p, new LayoutParams(PARAMS.PLAYER_SIZE, PARAMS.PLAYER_SIZE)); 10488df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return p; 10498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 10518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void setScore(int score) { 10528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScore = score; 10538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mScoreField != null) { 10548df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreField.setText(DEBUG_IDDQD ? "??" : String.valueOf(score)); 10558df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10568df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 10588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public int getScore() { 10598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return mScore; 10608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 10628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private void addScore(int incr) { 10638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setScore(mScore + incr); 10648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 10668df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void setScoreField(TextView tv) { 10678df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreField = tv; 10688df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (tv != null) { 10698df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setScore(mScore); // reapply 10708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //mScoreField.setBackgroundResource(R.drawable.scorecard); 10718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreField.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP); 10728df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mScoreField.setTextColor(luma(color) > 0.7f ? 0xFF000000 : 0xFFFFFFFF); 10738df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10748df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10758df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 10768df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void reset() { 10778df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //setX(mLand.mWidth / 2); 10788df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setY(mLand.mHeight / 2 10798df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler + (int)(Math.random() * PARAMS.PLAYER_SIZE) 10808df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler - PARAMS.PLAYER_SIZE / 2); 10818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setScore(0); 10828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setScoreField(mScoreField); // refresh color 10838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mBoosting = false; 10848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler dv = 0; 10858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 10868df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 10874455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Player(Context context) { 10884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context); 10894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 10904455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setBackgroundResource(R.drawable.android); 10914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler getBackground().setTintMode(PorterDuff.Mode.SRC_ATOP); 10928df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler color = sColors[(sNextColor++%sColors.length)]; 10938df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler getBackground().setTint(color); 10944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setOutlineProvider(new ViewOutlineProvider() { 10954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 10964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void getOutline(View view, Outline outline) { 10974455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int w = view.getWidth(); 10984455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int h = view.getHeight(); 10994455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int ix = (int) (w * 0.3f); 11004455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int iy = (int) (h * 0.2f); 11014455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler outline.setRect(ix, iy, w - ix, h - iy); 11024455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11034455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler }); 11044455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11054455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11064455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void prepareCheckIntersections() { 11074455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int inset = (PARAMS.PLAYER_SIZE - PARAMS.PLAYER_HIT_SIZE)/2; 11084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int scale = PARAMS.PLAYER_HIT_SIZE; 11094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int N = sHull.length/2; 11104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (int i=0; i<N; i++) { 11114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler corners[i*2] = scale * sHull[i*2] + inset; 11124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler corners[i*2+1] = scale * sHull[i*2+1] + inset; 11134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final Matrix m = getMatrix(); 11154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler m.mapPoints(corners); 11164455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11184455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean below(int h) { 11194455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int N = corners.length/2; 11204455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (int i=0; i<N; i++) { 11214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int y = (int) corners[i*2+1]; 11224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (y >= h) return true; 11234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return false; 11254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void step(long t_ms, long dt_ms, float t, float dt) { 11288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (!mAlive) { 11298df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // float away with the garbage 11308df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setTranslationX(getTranslationX()-PARAMS.TRANSLATION_PER_SEC*dt); 11318df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler return; 11328df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 11334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11342200f86f800876d005f911e6864708fa9772d03aDan Sandler if (mBoosting) { 11352200f86f800876d005f911e6864708fa9772d03aDan Sandler dv = -PARAMS.BOOST_DV; 11362200f86f800876d005f911e6864708fa9772d03aDan Sandler } else { 11372200f86f800876d005f911e6864708fa9772d03aDan Sandler dv += PARAMS.G; 11382200f86f800876d005f911e6864708fa9772d03aDan Sandler } 11394455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (dv < -PARAMS.MAX_V) dv = -PARAMS.MAX_V; 11404455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler else if (dv > PARAMS.MAX_V) dv = PARAMS.MAX_V; 11414455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11424455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final float y = getTranslationY() + dv * dt; 11434455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setTranslationY(y < 0 ? 0 : y); 11444455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setRotation( 11454455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 90 + lerp(clamp(rlerp(dv, PARAMS.MAX_V, -1 * PARAMS.MAX_V)), 90, -90)); 11464455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11474455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler prepareCheckIntersections(); 11484455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11494455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void boost(float x, float y) { 11518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchX = x; 11528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchY = y; 11538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler boost(); 11548df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 11558df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 11564455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void boost() { 11572200f86f800876d005f911e6864708fa9772d03aDan Sandler mBoosting = true; 11584455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler dv = -PARAMS.BOOST_DV; 11592200f86f800876d005f911e6864708fa9772d03aDan Sandler 11602200f86f800876d005f911e6864708fa9772d03aDan Sandler animate().cancel(); 11612200f86f800876d005f911e6864708fa9772d03aDan Sandler animate() 11622200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleX(1.25f) 11632200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleY(1.25f) 11642200f86f800876d005f911e6864708fa9772d03aDan Sandler .translationZ(PARAMS.PLAYER_Z_BOOST) 11652200f86f800876d005f911e6864708fa9772d03aDan Sandler .setDuration(100); 11664455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setScaleX(1.25f); 11674455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setScaleY(1.25f); 11682200f86f800876d005f911e6864708fa9772d03aDan Sandler } 11692200f86f800876d005f911e6864708fa9772d03aDan Sandler 11702200f86f800876d005f911e6864708fa9772d03aDan Sandler public void unboost() { 11712200f86f800876d005f911e6864708fa9772d03aDan Sandler mBoosting = false; 11728df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mTouchX = mTouchY = -1; 11732200f86f800876d005f911e6864708fa9772d03aDan Sandler 11742200f86f800876d005f911e6864708fa9772d03aDan Sandler animate().cancel(); 11754455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler animate() 11762200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleX(1f) 11772200f86f800876d005f911e6864708fa9772d03aDan Sandler .scaleY(1f) 11782200f86f800876d005f911e6864708fa9772d03aDan Sandler .translationZ(PARAMS.PLAYER_Z) 11792200f86f800876d005f911e6864708fa9772d03aDan Sandler .setDuration(200); 11804455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11818df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 11828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void die() { 11838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mAlive = false; 11848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mScoreField != null) { 11858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //mScoreField.setTextColor(0xFFFFFFFF); 11868df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //mScoreField.getBackground().setColorFilter(0xFF666666, PorterDuff.Mode.SRC_ATOP); 11878df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //mScoreField.setBackgroundResource(R.drawable.scorecard_gameover); 11888df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 11898df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 11908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 11918df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void start() { 11928df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mAlive = true; 11938df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 11944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 11954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private class Obstacle extends View implements GameView { 11974455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float h; 11984455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 11994455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public final Rect hitRect = new Rect(); 12004455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 12014455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Obstacle(Context context, float h) { 12024455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context); 12032200f86f800876d005f911e6864708fa9772d03aDan Sandler setBackgroundColor(0xFFFF0000); 12044455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler this.h = h; 12054455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12064455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 12074455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean intersects(Player p) { 12084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int N = p.corners.length/2; 12094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (int i=0; i<N; i++) { 12104455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int x = (int) p.corners[i*2]; 12114455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int y = (int) p.corners[i*2+1]; 12124455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (hitRect.contains(x, y)) return true; 12134455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12144455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return false; 12154455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12164455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 12174455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public boolean cleared(Player p) { 12184455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int N = p.corners.length/2; 12194455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler for (int i=0; i<N; i++) { 12204455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler final int x = (int) p.corners[i*2]; 12214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler if (hitRect.right >= x) return false; 12224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler return true; 12244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 12264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 12274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void step(long t_ms, long dt_ms, float t, float dt) { 12284455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setTranslationX(getTranslationX()-PARAMS.TRANSLATION_PER_SEC*dt); 12294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler getHitRect(hitRect); 12304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 12324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 12338df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static final int[] ANTENNAE = new int[] {R.drawable.mm_antennae, R.drawable.mm_antennae2}; 12348df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static final int[] EYES = new int[] {R.drawable.mm_eyes, R.drawable.mm_eyes2}; 12358df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static final int[] MOUTHS = new int[] {R.drawable.mm_mouth1, R.drawable.mm_mouth2, 12368df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler R.drawable.mm_mouth3, R.drawable.mm_mouth4}; 12372200f86f800876d005f911e6864708fa9772d03aDan Sandler private class Pop extends Obstacle { 12382200f86f800876d005f911e6864708fa9772d03aDan Sandler int mRotate; 12392200f86f800876d005f911e6864708fa9772d03aDan Sandler int cx, cy, r; 12408df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler // The marshmallow illustration and hitbox is 2/3 the size of its container. 12418df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler Drawable antenna, eyes, mouth; 12428df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 12438df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 12442200f86f800876d005f911e6864708fa9772d03aDan Sandler public Pop(Context context, float h) { 12452200f86f800876d005f911e6864708fa9772d03aDan Sandler super(context, h); 12468df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setBackgroundResource(R.drawable.mm_head); 12478df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler antenna = context.getDrawable(pick(ANTENNAE)); 12488df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (frand() > 0.5f) { 12498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler eyes = context.getDrawable(pick(EYES)); 12508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (frand() > 0.8f) { 12518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mouth = context.getDrawable(pick(MOUTHS)); 12528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 12538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 12542200f86f800876d005f911e6864708fa9772d03aDan Sandler setOutlineProvider(new ViewOutlineProvider() { 12552200f86f800876d005f911e6864708fa9772d03aDan Sandler @Override 12562200f86f800876d005f911e6864708fa9772d03aDan Sandler public void getOutline(View view, Outline outline) { 12578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler final int pad = (int) (getWidth() * 1f/6); 12582200f86f800876d005f911e6864708fa9772d03aDan Sandler outline.setOval(pad, pad, getWidth()-pad, getHeight()-pad); 12592200f86f800876d005f911e6864708fa9772d03aDan Sandler } 12602200f86f800876d005f911e6864708fa9772d03aDan Sandler }); 12612200f86f800876d005f911e6864708fa9772d03aDan Sandler } 12622200f86f800876d005f911e6864708fa9772d03aDan Sandler 12632200f86f800876d005f911e6864708fa9772d03aDan Sandler public boolean intersects(Player p) { 12642200f86f800876d005f911e6864708fa9772d03aDan Sandler final int N = p.corners.length/2; 12652200f86f800876d005f911e6864708fa9772d03aDan Sandler for (int i=0; i<N; i++) { 12662200f86f800876d005f911e6864708fa9772d03aDan Sandler final int x = (int) p.corners[i*2]; 12672200f86f800876d005f911e6864708fa9772d03aDan Sandler final int y = (int) p.corners[i*2+1]; 12682200f86f800876d005f911e6864708fa9772d03aDan Sandler if (Math.hypot(x-cx, y-cy) <= r) return true; 12692200f86f800876d005f911e6864708fa9772d03aDan Sandler } 12702200f86f800876d005f911e6864708fa9772d03aDan Sandler return false; 12712200f86f800876d005f911e6864708fa9772d03aDan Sandler } 12722200f86f800876d005f911e6864708fa9772d03aDan Sandler 12732200f86f800876d005f911e6864708fa9772d03aDan Sandler @Override 12742200f86f800876d005f911e6864708fa9772d03aDan Sandler public void step(long t_ms, long dt_ms, float t, float dt) { 12752200f86f800876d005f911e6864708fa9772d03aDan Sandler super.step(t_ms, dt_ms, t, dt); 12762200f86f800876d005f911e6864708fa9772d03aDan Sandler if (mRotate != 0) { 12772200f86f800876d005f911e6864708fa9772d03aDan Sandler setRotation(getRotation() + dt * 45 * mRotate); 12782200f86f800876d005f911e6864708fa9772d03aDan Sandler } 12792200f86f800876d005f911e6864708fa9772d03aDan Sandler 12802200f86f800876d005f911e6864708fa9772d03aDan Sandler cx = (hitRect.left + hitRect.right)/2; 12812200f86f800876d005f911e6864708fa9772d03aDan Sandler cy = (hitRect.top + hitRect.bottom)/2; 12828df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler r = getWidth() / 3; // see above re 2/3 container size 12838df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 12848df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 12858df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler @Override 12868df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public void onDraw(Canvas c) { 12878df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler super.onDraw(c); 12888df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (antenna != null) { 12898df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler antenna.setBounds(0, 0, c.getWidth(), c.getHeight()); 12908df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler antenna.draw(c); 12918df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 12928df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (eyes != null) { 12938df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler eyes.setBounds(0, 0, c.getWidth(), c.getHeight()); 12948df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler eyes.draw(c); 12958df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 12968df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mouth != null) { 12978df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mouth.setBounds(0, 0, c.getWidth(), c.getHeight()); 12988df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mouth.draw(c); 12998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 13002200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13012200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13022200f86f800876d005f911e6864708fa9772d03aDan Sandler 13032200f86f800876d005f911e6864708fa9772d03aDan Sandler private class Stem extends Obstacle { 13042200f86f800876d005f911e6864708fa9772d03aDan Sandler Paint mPaint = new Paint(); 13052200f86f800876d005f911e6864708fa9772d03aDan Sandler Path mShadow = new Path(); 13068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler GradientDrawable mGradient = new GradientDrawable(); 13072200f86f800876d005f911e6864708fa9772d03aDan Sandler boolean mDrawShadow; 13088df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler Path mJandystripe; 13098df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler Paint mPaint2; 13108df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler int id; // use this to track which pipes have been cleared 13112200f86f800876d005f911e6864708fa9772d03aDan Sandler 13122200f86f800876d005f911e6864708fa9772d03aDan Sandler public Stem(Context context, float h, boolean drawShadow) { 13132200f86f800876d005f911e6864708fa9772d03aDan Sandler super(context, h); 13148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler id = mCurrentPipeId; 13158df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 13162200f86f800876d005f911e6864708fa9772d03aDan Sandler mDrawShadow = drawShadow; 13172200f86f800876d005f911e6864708fa9772d03aDan Sandler setBackground(null); 13188df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGradient.setOrientation(GradientDrawable.Orientation.LEFT_RIGHT); 13198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPaint.setColor(0xFF000000); 13208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPaint.setColorFilter(new PorterDuffColorFilter(0x22000000, PorterDuff.Mode.MULTIPLY)); 13218df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 13228df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (frand() < 0.01f) { 13238df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGradient.setColors(new int[]{0xFFFFFFFF, 0xFFDDDDDD}); 13248df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe = new Path(); 13258df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPaint2 = new Paint(); 13268df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPaint2.setColor(0xFFFF0000); 13278df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mPaint2.setColorFilter(new PorterDuffColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY)); 13288df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } else { 13298df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler //mPaint.setColor(0xFFA1887F); 13308df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGradient.setColors(new int[]{0xFFBCAAA4, 0xFFA1887F}); 13318df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 13322200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13332200f86f800876d005f911e6864708fa9772d03aDan Sandler 13342200f86f800876d005f911e6864708fa9772d03aDan Sandler @Override 13352200f86f800876d005f911e6864708fa9772d03aDan Sandler public void onAttachedToWindow() { 13362200f86f800876d005f911e6864708fa9772d03aDan Sandler super.onAttachedToWindow(); 13372200f86f800876d005f911e6864708fa9772d03aDan Sandler setWillNotDraw(false); 13382200f86f800876d005f911e6864708fa9772d03aDan Sandler setOutlineProvider(new ViewOutlineProvider() { 13392200f86f800876d005f911e6864708fa9772d03aDan Sandler @Override 13402200f86f800876d005f911e6864708fa9772d03aDan Sandler public void getOutline(View view, Outline outline) { 13412200f86f800876d005f911e6864708fa9772d03aDan Sandler outline.setRect(0, 0, getWidth(), getHeight()); 13422200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13432200f86f800876d005f911e6864708fa9772d03aDan Sandler }); 13442200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13452200f86f800876d005f911e6864708fa9772d03aDan Sandler @Override 13462200f86f800876d005f911e6864708fa9772d03aDan Sandler public void onDraw(Canvas c) { 13472200f86f800876d005f911e6864708fa9772d03aDan Sandler final int w = c.getWidth(); 13482200f86f800876d005f911e6864708fa9772d03aDan Sandler final int h = c.getHeight(); 13498df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGradient.setGradientCenter(w * 0.75f, 0); 13508df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGradient.setBounds(0, 0, w, h); 13518df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mGradient.draw(c); 13528df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 13538df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler if (mJandystripe != null) { 13548df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.reset(); 13558df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.moveTo(0, w); 13568df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.lineTo(w, 0); 13578df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.lineTo(w, 2 * w); 13588df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.lineTo(0, 3 * w); 13598df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.close(); 13608df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler for (int y=0; y<h; y+=4*w) { 13618df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler c.drawPath(mJandystripe, mPaint2); 13628df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mJandystripe.offset(0, 4 * w); 13638df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 13648df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 13658df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 13662200f86f800876d005f911e6864708fa9772d03aDan Sandler if (!mDrawShadow) return; 13672200f86f800876d005f911e6864708fa9772d03aDan Sandler mShadow.reset(); 13688df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mShadow.moveTo(0, 0); 13692200f86f800876d005f911e6864708fa9772d03aDan Sandler mShadow.lineTo(w, 0); 13708df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mShadow.lineTo(w, PARAMS.OBSTACLE_WIDTH * 0.4f + w*1.5f); 13718df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler mShadow.lineTo(0, PARAMS.OBSTACLE_WIDTH * 0.4f); 13722200f86f800876d005f911e6864708fa9772d03aDan Sandler mShadow.close(); 13732200f86f800876d005f911e6864708fa9772d03aDan Sandler c.drawPath(mShadow, mPaint); 13742200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13752200f86f800876d005f911e6864708fa9772d03aDan Sandler } 13762200f86f800876d005f911e6864708fa9772d03aDan Sandler 13774455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private class Scenery extends FrameLayout implements GameView { 13784455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float z; 13794455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public float v; 13804455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public int h, w; 13814455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Scenery(Context context) { 13824455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context); 13834455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 13844455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 13854455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler @Override 13864455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public void step(long t_ms, long dt_ms, float t, float dt) { 13874455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setTranslationX(getTranslationX() - PARAMS.TRANSLATION_PER_SEC * dt * v); 13884455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 13894455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 13904455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 13914455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private class Building extends Scenery { 13924455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Building(Context context) { 13934455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context); 13944455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 13954455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler w = irand(PARAMS.BUILDING_WIDTH_MIN, PARAMS.BUILDING_WIDTH_MAX); 13964455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler h = 0; // will be setup later, along with z 13978df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 13988df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 13998df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 14008df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static final int[] CACTI = { R.drawable.cactus1, R.drawable.cactus2, R.drawable.cactus3 }; 14018df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private class Cactus extends Building { 14028df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public Cactus(Context context) { 14038df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler super(context); 14044455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 14058df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setBackgroundResource(pick(CACTI)); 14068df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler w = h = irand(PARAMS.BUILDING_WIDTH_MAX / 4, PARAMS.BUILDING_WIDTH_MAX / 2); 14074455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 14084455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 14094455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 14108df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler static final int[] MOUNTAINS = { 14118df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler R.drawable.mountain1, R.drawable.mountain2, R.drawable.mountain3 }; 14128df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler private class Mountain extends Building { 14138df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler public Mountain(Context context) { 14148df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler super(context); 14158df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler 14168df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler setBackgroundResource(pick(MOUNTAINS)); 14178df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler w = h = irand(PARAMS.BUILDING_WIDTH_MAX / 2, PARAMS.BUILDING_WIDTH_MAX); 14188df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler z = 0; 14198df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 14208df3cfe6b8e6a871bcc69efdd19a632229b50384Dan Sandler } 14214455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private class Cloud extends Scenery { 14224455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Cloud(Context context) { 14234455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context); 14244455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setBackgroundResource(frand() < 0.01f ? R.drawable.cloud_off : R.drawable.cloud); 14254455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler getBackground().setAlpha(0x40); 14264455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler w = h = irand(PARAMS.CLOUD_SIZE_MIN, PARAMS.CLOUD_SIZE_MAX); 14274455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler z = 0; 14284455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler v = frand(0.15f,0.5f); 14294455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 14304455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 14314455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler 14324455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler private class Star extends Scenery { 14334455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler public Star(Context context) { 14344455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler super(context); 14354455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler setBackgroundResource(R.drawable.star); 14364455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler w = h = irand(PARAMS.STAR_SIZE_MIN, PARAMS.STAR_SIZE_MAX); 14374455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler v = z = 0; 14384455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 14394455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler } 14404455da985d4bc8b3dce8ae35deaef41049d121daDan Sandler} 1441