From 79c99bc166e80dde03b1086673bb04451af15657 Mon Sep 17 00:00:00 2001 From: forteri76 Date: Thu, 5 Jun 2014 05:15:55 +0000 Subject: [PATCH] Added arcade game mode. Bubbles will scroll continuously from the top of the screen, forever. The high score screen will always be displayed after the player dies, and funcitons like the multiplayer high score screen. --- AndroidManifest.xml | 4 +- jni/load_abc.cpp | 2 +- jni/load_it.cpp | 2 +- .../frozenbubble/HighscoreManager.java | 1 + src/com/efortin/frozenbubble/HomeScreen.java | 167 +++++++++----- src/org/jfedor/frozenbubble/BubbleSprite.java | 31 ++- src/org/jfedor/frozenbubble/Compressor.java | 33 ++- src/org/jfedor/frozenbubble/FrozenBubble.java | 32 ++- src/org/jfedor/frozenbubble/FrozenGame.java | 214 +++++++++++++++--- src/org/jfedor/frozenbubble/GameView.java | 116 ++++++---- src/org/jfedor/frozenbubble/LevelManager.java | 39 +++- 11 files changed, 481 insertions(+), 160 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a7d22b9..2ef3c3c 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="33" + android:versionName="3.0"> nLen-nPos-8) break;; + if (nPluginSize > nLen-nPos-8) break; if ((bswapLE32(*(DWORD *)(p+nPos))) == 0x58464843) { for (UINT ch=0; ch<64; ch++) if (ch*4 < nPluginSize) diff --git a/src/com/efortin/frozenbubble/HighscoreManager.java b/src/com/efortin/frozenbubble/HighscoreManager.java index 981b666..c104816 100644 --- a/src/com/efortin/frozenbubble/HighscoreManager.java +++ b/src/com/efortin/frozenbubble/HighscoreManager.java @@ -68,6 +68,7 @@ public class HighscoreManager { public static final String PUZZLE_DATABASE_NAME = "frozenbubble"; public static final String MULTIPLAYER_DATABASE_NAME = "multiplayer"; + public static final String ARCADE_DATABASE_NAME = "arcade"; private boolean isPaused = true; private int currentLevel = 0; diff --git a/src/com/efortin/frozenbubble/HomeScreen.java b/src/com/efortin/frozenbubble/HomeScreen.java index 04c0109..00f8b52 100644 --- a/src/com/efortin/frozenbubble/HomeScreen.java +++ b/src/com/efortin/frozenbubble/HomeScreen.java @@ -93,11 +93,12 @@ public class HomeScreen extends Activity { private final static int BTN6_ID = 107; private final static int BTN7_ID = 108; private final static int BTN8_ID = 109; + private final static int BTN9_ID = 110; private static int buttonSelected = BTN1_ID; private static int buttonSelPage1 = BTN1_ID; - private static int buttonSelPage2 = BTN4_ID; - private static int buttonSelPage3 = BTN7_ID; + private static int buttonSelPage2 = BTN5_ID; + private static int buttonSelPage3 = BTN8_ID; private boolean finished = false; private boolean homeShown = false; @@ -172,8 +173,8 @@ private void addHomeButtons() { Button start2pGameButton = new Button(this); start2pGameButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN2_ID; - buttonSelPage1 = BTN2_ID; + buttonSelected = BTN3_ID; + buttonSelPage1 = BTN3_ID; /* * Display the 2 player mode buttons page. */ @@ -194,7 +195,7 @@ public boolean onTouch(View v, MotionEvent event){ start2pGameButton.setHorizontalFadingEdgeEnabled(true); start2pGameButton.setFadingEdgeLength(5); start2pGameButton.setShadowLayer(5, 5, 5, R.color.black); - start2pGameButton.setId(BTN2_ID); + start2pGameButton.setId(BTN3_ID); start2pGameButton.setFocusable(true); start2pGameButton.setFocusableInTouchMode(true); LayoutParams myParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -212,14 +213,14 @@ public boolean onTouch(View v, MotionEvent event){ Button start1pGameButton = new Button(this); start1pGameButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN1_ID; - buttonSelPage1 = BTN1_ID; + buttonSelected = BTN2_ID; + buttonSelPage1 = BTN2_ID; /* * Process the button tap and start/resume a 1 player game. */ startFrozenBubble(VirtualInput.PLAYER1, 1, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL); + FrozenBubble.LOCALE_LOCAL, false); } }); start1pGameButton.setOnTouchListener(new Button.OnTouchListener(){ @@ -236,7 +237,7 @@ public boolean onTouch(View v, MotionEvent event){ start1pGameButton.setHorizontalFadingEdgeEnabled(true); start1pGameButton.setFadingEdgeLength(5); start1pGameButton.setShadowLayer(5, 5, 5, R.color.black); - start1pGameButton.setId(BTN1_ID); + start1pGameButton.setId(BTN2_ID); start1pGameButton.setFocusable(true); start1pGameButton.setFocusableInTouchMode(true); LayoutParams myParams2 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -249,14 +250,58 @@ public boolean onTouch(View v, MotionEvent event){ * Add view to layout. */ myLayout.addView(start1pGameButton, myParams2); + /* + * Construct the 1 player arcade game button. + */ + Button startArcadeGameButton = new Button(this); + startArcadeGameButton.setOnClickListener(new Button.OnClickListener(){ + public void onClick(View v){ + buttonSelected = BTN1_ID; + buttonSelPage1 = BTN1_ID; + /* + * Process the button tap and start/resume a 1 player arcade + * game. + */ + startFrozenBubble(VirtualInput.PLAYER1, 1, + FrozenBubble.HUMAN, + FrozenBubble.LOCALE_LOCAL, true); + } + }); + startArcadeGameButton.setOnTouchListener(new Button.OnTouchListener(){ + public boolean onTouch(View v, MotionEvent event){ + if (event.getAction() == MotionEvent.ACTION_DOWN) + v.requestFocus(); + return false; + } + }); + startArcadeGameButton.setText("Arcade"); + startArcadeGameButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + startArcadeGameButton.setWidth((int) (startArcadeGameButton.getTextSize() * 9)); + startArcadeGameButton.setTypeface(null, Typeface.BOLD); + startArcadeGameButton.setHorizontalFadingEdgeEnabled(true); + startArcadeGameButton.setFadingEdgeLength(5); + startArcadeGameButton.setShadowLayer(5, 5, 5, R.color.black); + startArcadeGameButton.setId(BTN1_ID); + startArcadeGameButton.setFocusable(true); + startArcadeGameButton.setFocusableInTouchMode(true); + LayoutParams myParams3 = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + myParams3.addRule(RelativeLayout.CENTER_IN_PARENT); + myParams3.addRule(RelativeLayout.ABOVE, start1pGameButton.getId()); + myParams3.topMargin = 15; + myParams3.bottomMargin = 15; + /* + * Add view to layout. + */ + myLayout.addView(startArcadeGameButton, myParams3); /* * Construct the options button. */ Button optionsButton = new Button(this); optionsButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN3_ID; - buttonSelPage1 = BTN3_ID; + buttonSelected = BTN4_ID; + buttonSelPage1 = BTN4_ID; /* * Process the button tap and start the preferences activity. */ @@ -277,19 +322,19 @@ public boolean onTouch(View v, MotionEvent event){ optionsButton.setHorizontalFadingEdgeEnabled(true); optionsButton.setFadingEdgeLength(5); optionsButton.setShadowLayer(5, 5, 5, R.color.black); - optionsButton.setId(BTN3_ID); + optionsButton.setId(BTN4_ID); optionsButton.setFocusable(true); optionsButton.setFocusableInTouchMode(true); - LayoutParams myParams3 = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams myParams4 = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - myParams3.addRule(RelativeLayout.CENTER_IN_PARENT); - myParams3.addRule(RelativeLayout.BELOW, start2pGameButton.getId()); - myParams3.topMargin = 15; - myParams3.bottomMargin = 15; + myParams4.addRule(RelativeLayout.CENTER_IN_PARENT); + myParams4.addRule(RelativeLayout.BELOW, start2pGameButton.getId()); + myParams4.topMargin = 15; + myParams4.bottomMargin = 15; /* * Add view to layout. */ - myLayout.addView(optionsButton, myParams3); + myLayout.addView(optionsButton, myParams4); } /** @@ -308,8 +353,8 @@ private void addMultiplayerButtons() { Button startLanGameButton = new Button(this); startLanGameButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN5_ID; - buttonSelPage2 = BTN5_ID; + buttonSelected = BTN6_ID; + buttonSelPage2 = BTN6_ID; /* * Display the player ID buttons page. */ @@ -330,7 +375,7 @@ public boolean onTouch(View v, MotionEvent event){ startLanGameButton.setHorizontalFadingEdgeEnabled(true); startLanGameButton.setFadingEdgeLength(5); startLanGameButton.setShadowLayer(5, 5, 5, R.color.black); - startLanGameButton.setId(BTN5_ID); + startLanGameButton.setId(BTN6_ID); startLanGameButton.setFocusable(true); startLanGameButton.setFocusableInTouchMode(true); LayoutParams myParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -348,14 +393,14 @@ public boolean onTouch(View v, MotionEvent event){ Button startCPUGameButton = new Button(this); startCPUGameButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN4_ID; - buttonSelPage2 = BTN4_ID; + buttonSelected = BTN5_ID; + buttonSelPage2 = BTN5_ID; /* * Process the button tap and start a 2 player game. */ startFrozenBubble(VirtualInput.PLAYER1, 2, FrozenBubble.CPU, - FrozenBubble.LOCALE_LOCAL); + FrozenBubble.LOCALE_LOCAL, false); } }); startCPUGameButton.setOnTouchListener(new Button.OnTouchListener(){ @@ -372,7 +417,7 @@ public boolean onTouch(View v, MotionEvent event){ startCPUGameButton.setHorizontalFadingEdgeEnabled(true); startCPUGameButton.setFadingEdgeLength(5); startCPUGameButton.setShadowLayer(5, 5, 5, R.color.black); - startCPUGameButton.setId(BTN4_ID); + startCPUGameButton.setId(BTN5_ID); startCPUGameButton.setFocusable(true); startCPUGameButton.setFocusableInTouchMode(true); LayoutParams myParams2 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -391,8 +436,8 @@ public boolean onTouch(View v, MotionEvent event){ Button startIPGameButton = new Button(this); startIPGameButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN6_ID; - buttonSelPage2 = BTN6_ID; + buttonSelected = BTN7_ID; + buttonSelPage2 = BTN7_ID; /* * Display the player ID buttons page. */ @@ -413,7 +458,7 @@ public boolean onTouch(View v, MotionEvent event){ startIPGameButton.setHorizontalFadingEdgeEnabled(true); startIPGameButton.setFadingEdgeLength(5); startIPGameButton.setShadowLayer(5, 5, 5, R.color.black); - startIPGameButton.setId(BTN6_ID); + startIPGameButton.setId(BTN7_ID); startIPGameButton.setFocusable(true); startIPGameButton.setFocusableInTouchMode(true); LayoutParams myParams3 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -444,20 +489,20 @@ private void addPlayerSelectButtons() { Button player2Button = new Button(this); player2Button.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN8_ID; - buttonSelPage3 = BTN8_ID; + buttonSelected = BTN9_ID; + buttonSelPage3 = BTN9_ID; /* * Process the button tap and start a 2 player game. */ - if (buttonSelPage2 == BTN6_ID) { + if (buttonSelPage2 == BTN7_ID) { startFrozenBubble(VirtualInput.PLAYER2, 2, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_INTERNET); + FrozenBubble.LOCALE_INTERNET, false); } else { startFrozenBubble(VirtualInput.PLAYER2, 2, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LAN); + FrozenBubble.LOCALE_LAN, false); } } }); @@ -475,7 +520,7 @@ public boolean onTouch(View v, MotionEvent event){ player2Button.setHorizontalFadingEdgeEnabled(true); player2Button.setFadingEdgeLength(5); player2Button.setShadowLayer(5, 5, 5, R.color.black); - player2Button.setId(BTN8_ID); + player2Button.setId(BTN9_ID); player2Button.setFocusable(true); player2Button.setFocusableInTouchMode(true); LayoutParams myParams1 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -493,20 +538,20 @@ public boolean onTouch(View v, MotionEvent event){ Button player1Button = new Button(this); player1Button.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ - buttonSelected = BTN7_ID; - buttonSelPage3 = BTN7_ID; + buttonSelected = BTN8_ID; + buttonSelPage3 = BTN8_ID; /* * Process the button tap and start a 2 player game. */ - if (buttonSelPage2 == BTN6_ID) { + if (buttonSelPage2 == BTN7_ID) { startFrozenBubble(VirtualInput.PLAYER1, 2, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_INTERNET); + FrozenBubble.LOCALE_INTERNET, false); } else { startFrozenBubble(VirtualInput.PLAYER1, 2, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LAN); + FrozenBubble.LOCALE_LAN, false); } } }); @@ -524,7 +569,7 @@ public boolean onTouch(View v, MotionEvent event){ player1Button.setHorizontalFadingEdgeEnabled(true); player1Button.setFadingEdgeLength(5); player1Button.setShadowLayer(5, 5, 5, R.color.black); - player1Button.setId(BTN7_ID); + player1Button.setId(BTN8_ID); player1Button.setFocusable(true); player1Button.setFocusableInTouchMode(true); LayoutParams myParams2 = new LayoutParams(LayoutParams.WRAP_CONTENT, @@ -549,13 +594,13 @@ private void backKeyPress() { * Otherwise if one of the base level buttons was selected, then * terminate the home screen activity. */ - if ((buttonSelected == BTN4_ID) || - (buttonSelected == BTN5_ID) || - (buttonSelected == BTN6_ID)) { + if ((buttonSelected == BTN5_ID) || + (buttonSelected == BTN6_ID) || + (buttonSelected == BTN7_ID)) { displayButtonPage(1); } - else if ((buttonSelected == BTN7_ID) || - (buttonSelected == BTN8_ID)) { + else if ((buttonSelected == BTN8_ID) || + (buttonSelected == BTN9_ID)) { displayButtonPage(2); } else { @@ -595,11 +640,11 @@ private void cleanUp() { private void displayButtonPage(int pageID) { if (pageID == 1) { buttonSelected = buttonSelPage1; - removeViewByID(BTN4_ID); removeViewByID(BTN5_ID); removeViewByID(BTN6_ID); removeViewByID(BTN7_ID); removeViewByID(BTN8_ID); + removeViewByID(BTN9_ID); addHomeButtons(); selectInitialButton(); } @@ -608,8 +653,9 @@ else if (pageID == 2) { removeViewByID(BTN1_ID); removeViewByID(BTN2_ID); removeViewByID(BTN3_ID); - removeViewByID(BTN7_ID); + removeViewByID(BTN4_ID); removeViewByID(BTN8_ID); + removeViewByID(BTN9_ID); addMultiplayerButtons(); selectInitialButton(); } @@ -621,6 +667,7 @@ else if (pageID == 3) { removeViewByID(BTN4_ID); removeViewByID(BTN5_ID); removeViewByID(BTN6_ID); + removeViewByID(BTN7_ID); addPlayerSelectButtons(); selectInitialButton(); } @@ -659,7 +706,8 @@ public void onCreate(Bundle savedInstanceState) { startFrozenBubble(FrozenBubble.myPlayerId, FrozenBubble.numPlayers, FrozenBubble.opponentId, - FrozenBubble.gameLocale); + FrozenBubble.gameLocale, + FrozenBubble.arcadeGame); else if (getIntent().hasExtra("startHomeScreen")) { setBackgroundImage(R.drawable.home_screen); setContentView(myLayout); @@ -815,11 +863,13 @@ private void setWindowLayout() { * will be played by the CPU. A LAN opponent will be played over the * network using multicasting, and an internet opponent will be played * using TCP. + * @param arcadeGame - endless arcade game that scrolls new bubbles. */ private void startFrozenBubble(int myPlayerId, int numPlayers, int opponentId, - int gameLocale) { + int gameLocale, + boolean arcadeGame) { finished = true; /* * Since the default game activity creates its own player, @@ -830,10 +880,12 @@ private void startFrozenBubble(int myPlayerId, * Create an intent to launch the activity to play the game. */ Intent intent = new Intent(this, FrozenBubble.class); - intent.putExtra("myPlayerId", (int)myPlayerId); - intent.putExtra("numPlayers", (int)numPlayers); - intent.putExtra("opponentId", (int)opponentId); - intent.putExtra("gameLocale", (int)gameLocale); + intent.putExtra("myPlayerId", (int) myPlayerId); + intent.putExtra("numPlayers", (int) numPlayers); + intent.putExtra("opponentId", (int) opponentId); + intent.putExtra("gameLocale", (int) gameLocale); + intent.putExtra("arcadeGame", (boolean) arcadeGame); + startActivity(intent); /* * Terminate the splash screen activity. @@ -848,11 +900,12 @@ private void startHomeScreen() { addBackButton(); if ((buttonSelected == BTN1_ID) || (buttonSelected == BTN2_ID) || - (buttonSelected == BTN3_ID)) + (buttonSelected == BTN3_ID) || + (buttonSelected == BTN4_ID)) addHomeButtons(); - else if ((buttonSelected == BTN4_ID) || - (buttonSelected == BTN5_ID) || - (buttonSelected == BTN6_ID)) + else if ((buttonSelected == BTN5_ID) || + (buttonSelected == BTN6_ID) || + (buttonSelected == BTN7_ID)) addMultiplayerButtons(); else addPlayerSelectButtons(); diff --git a/src/org/jfedor/frozenbubble/BubbleSprite.java b/src/org/jfedor/frozenbubble/BubbleSprite.java index 928b18c..03d27ca 100644 --- a/src/org/jfedor/frozenbubble/BubbleSprite.java +++ b/src/org/jfedor/frozenbubble/BubbleSprite.java @@ -94,8 +94,8 @@ public class BubbleSprite extends Sprite { public BubbleSprite(Rect area, int color, double moveX, double moveY, double realX, double realY, boolean fixed, boolean blink, boolean released, boolean checkJump, boolean checkFall, - int fixedAnim, BmpWrap bubbleFace, - Point lastOpenPosition, + int fixedAnim, int scroll, int scrollMax, + BmpWrap bubbleFace, Point lastOpenPosition, BmpWrap bubbleBlindFace, BmpWrap frozenFace, BmpWrap[] bubbleFixed, BmpWrap bubbleBlink, BubbleManager bubbleManager, SoundManager soundManager, @@ -149,7 +149,7 @@ public BubbleSprite(Rect area, double direction, int color, BmpWrap bubbleFace, this.realY = area.top; this.lastOpenPosition = currentPosition(); - fixed = false; + fixed = false; fixedAnim = -1; } @@ -174,7 +174,7 @@ public BubbleSprite(Rect area, int color, BmpWrap bubbleFace, this.realY = area.top; this.lastOpenPosition = currentPosition(); - fixed = true; + fixed = true; fixedAnim = -1; addToManager(); } @@ -221,7 +221,7 @@ public void checkFall() { } checkFall = true; - Vector v = this.getNeighbors(this.lastOpenPosition); + Vector v = this.getNeighbors(this.currentPosition()); for (int i=0 ; i jump, BmpWrap compare) { checkJump = true; if (this.bubbleFace == compare) { - checkJump(jump, this.getNeighbors(this.lastOpenPosition)); + checkJump(jump, this.getNeighbors(this.currentPosition())); } } @@ -257,8 +257,9 @@ void checkJump(Vector jump, Vector neighbors) { } Point currentPosition() { + int rowOffset = frozen.getRowOffset(); int posY = (int)Math.floor((realY-28.-frozen.getMoveDown())/28.); - int posX = (int)Math.floor((realX-174.)/32. + 0.5*(posY%2)); + int posX = (int)Math.floor((realX-174.)/32. + 0.5*((posY+rowOffset)%2)); if (posX > (LevelManager.NUM_COLS - 1)) { posX = LevelManager.NUM_COLS - 1; @@ -268,6 +269,10 @@ Point currentPosition() { posX = 0; } + if (posY > (LevelManager.NUM_ROWS - 1)) { + posY = LevelManager.NUM_ROWS - 1; + } + if (posY < 0) { posY = 0; } @@ -293,7 +298,8 @@ Vector getNeighbors(Point p) { BubbleSprite[][] grid = frozen.getGrid(); Vector list = new Vector(); - if ((p.y % 2) == 0) { + int rowOffset = frozen.getRowOffset(); + if (((p.y + rowOffset) % 2) == 0) { if (p.x > 0) { list.addElement(grid[p.x-1][p.y]); } @@ -470,7 +476,8 @@ else if (realX<=190.) { Vector neighbors = getNeighbors(lastOpenPosition); if (checkCollision(neighbors) || realY < 44.+frozen.getMoveDown()) { - realX = 190.+lastOpenPosition.x*32-(lastOpenPosition.y%2)*16; + int rowOffset = frozen.getRowOffset(); + realX = 190.+lastOpenPosition.x*32-((lastOpenPosition.y+rowOffset)%2)*16; realY = 44.+lastOpenPosition.y*28+frozen.getMoveDown(); fixed = true; @@ -489,6 +496,7 @@ else if (realX<=190.) { if (i>0) { current.removeFromManager(); } + grid[currentPoint.x][currentPoint.y] = null; } @@ -622,6 +630,11 @@ public void saveState(Bundle map, Vector savedSprites, int id) { lastOpenPosition.y); } + public void scroll(int moveDown) { + realY += 1.; + super.absoluteMove(new Point((int)realX, (int)realY)); + } + public static void setCollisionThreshold(int collision) { minDistance = collision * collision; } diff --git a/src/org/jfedor/frozenbubble/Compressor.java b/src/org/jfedor/frozenbubble/Compressor.java index 26f34eb..3241679 100644 --- a/src/org/jfedor/frozenbubble/Compressor.java +++ b/src/org/jfedor/frozenbubble/Compressor.java @@ -56,17 +56,29 @@ import android.os.Bundle; public class Compressor { + private static final int SCROLL_START = 6; + private BmpWrap compressorHead; private BmpWrap compressor; private double moveDown; + private int scroll; + private int scrollMax; private int steps; public Compressor(BmpWrap compressorHead, BmpWrap compressor) { this.compressorHead = compressorHead; - this.compressor = compressor; + this.compressor = compressor; init(); } + public boolean checkScroll() { + if (scroll++ > scrollMax) { + scroll = 0; + moveDown += 1.; + } + return scroll == 0; + } + public double getMoveDown() { return moveDown; } @@ -76,8 +88,10 @@ public int getSteps() { } public void init() { - moveDown = 0.; - steps = 0; + moveDown = 0.; + scroll = 0; + scrollMax = SCROLL_START; + steps = 0; } public void moveDown() { @@ -85,6 +99,10 @@ public void moveDown() { steps++; } + public void moveDownSubtract(double subtract) { + moveDown -= subtract; + } + public void paint(Canvas c, double scale, int dx, int dy) { for (int i = 0; i < steps; i++) { c.drawBitmap(compressor.bmp, @@ -100,12 +118,17 @@ public void paint(Canvas c, double scale, int dx, int dy) { } public void restoreState(Bundle map, int id) { - moveDown = map.getDouble(String.format("%d-compressor-moveDown", id)); - steps = map.getInt(String.format("%d-compressor-steps", id)); + moveDown = map.getDouble(String.format("%d-compressor-moveDown", id)); + scroll = map.getInt(String.format("%d-compressor-scroll", id)); + scrollMax = map.getInt(String.format("%d-compressor-scrollMax", id)); + steps = map.getInt(String.format("%d-compressor-steps", id)); } public void saveState(Bundle map, int id) { map.putDouble(String.format("%d-compressor-moveDown", id), moveDown); + map.putInt(String.format("%d-compressor-scroll", id), scroll); + map.putInt(String.format("%d-compressor-scrollMax", id), scrollMax); + map.putInt(String.format("%d-compressor-steps", id), steps); map.putInt(String.format("%d-compressor-steps", id), steps); } }; diff --git a/src/org/jfedor/frozenbubble/FrozenBubble.java b/src/org/jfedor/frozenbubble/FrozenBubble.java index a0e3b65..1f4377a 100644 --- a/src/org/jfedor/frozenbubble/FrozenBubble.java +++ b/src/org/jfedor/frozenbubble/FrozenBubble.java @@ -158,10 +158,11 @@ public class FrozenBubble extends Activity public final static int CPU = 0; public final static int HUMAN = 1; - public static int gameLocale = LOCALE_LOCAL; - public static int myPlayerId = VirtualInput.PLAYER1; - public static int numPlayers = 0; - public static int opponentId = CPU; + public static boolean arcadeGame = false; + public static int gameLocale = LOCALE_LOCAL; + public static int myPlayerId = VirtualInput.PLAYER1; + public static int numPlayers = 0; + public static int opponentId = CPU; private static boolean adsOn = true; private static int collision = BubbleSprite.MIN_PIX; @@ -559,6 +560,7 @@ public void cleanUp() { * The current game is being destroyed, so reset the static game * state variables. */ + arcadeGame = false; gameLocale = LOCALE_LOCAL; myPlayerId = VirtualInput.PLAYER1; numPlayers = 0; @@ -763,7 +765,7 @@ else if (allowUnpause) break; case LEVEL_START: - if ((mGameView != null) && (mGameThread != null) && + if (!arcadeGame && (mGameView != null) && (mGameThread != null) && (numPlayers == 1)) { if (mGameThread.getCurrentLevelIndex() == 0) { /* @@ -828,10 +830,11 @@ private void playMusic(boolean startPlaying) int modNow; /* * Ascertain which song to play. For a single player game, the song - * is based on the current level. For a two player game, or if the - * game thread has been destroyed, the song is selected at random. + * is based on the current level. For an arcade game, a two player + * game, or if the game thread has been destroyed, the song is + * selected at random. */ - if ((mGameThread != null) && (numPlayers == 1)) { + if (!arcadeGame && (mGameThread != null) && (numPlayers == 1)) { modNow = mGameThread.getCurrentLevelIndex() % MODlist.length; } else @@ -881,7 +884,7 @@ private void restoreGamePrefs() { * Save critically important game information. */ public void saveState() { - if ((mGameThread != null) && (numPlayers == 1)) { + if (!arcadeGame && (mGameThread != null) && (numPlayers == 1)) { /* * Allow level editor functionalities. */ @@ -1055,6 +1058,7 @@ private void startDefaultGame(Intent intent, Bundle savedInstanceState) { /* * Check if this is a single player or multiplayer game. */ + arcadeGame = false; gameLocale = LOCALE_LOCAL; myPlayerId = VirtualInput.PLAYER1; numPlayers = 1; @@ -1068,6 +1072,8 @@ private void startDefaultGame(Intent intent, Bundle savedInstanceState) { opponentId = intent.getIntExtra("opponentId", CPU); if (intent.hasExtra("gameLocale")) gameLocale = intent.getIntExtra("gameLocale", LOCALE_LOCAL); + if (intent.hasExtra("arcadeGame")) + arcadeGame = intent.getBooleanExtra("arcadeGame", false); } initGameOptions(); /* @@ -1075,8 +1081,12 @@ private void startDefaultGame(Intent intent, Bundle savedInstanceState) { * Otherwise start a single player game. */ if (numPlayers > 1) { - mGameView = - new GameView(this, numPlayers, myPlayerId, opponentId, gameLocale); + mGameView = new GameView(this, + numPlayers, + myPlayerId, + opponentId, + gameLocale, + arcadeGame); setContentView(mGameView); mGameView.setGameListener(this); mGameThread = mGameView.getThread(); diff --git a/src/org/jfedor/frozenbubble/FrozenGame.java b/src/org/jfedor/frozenbubble/FrozenGame.java index c7b7cc7..379ed15 100644 --- a/src/org/jfedor/frozenbubble/FrozenGame.java +++ b/src/org/jfedor/frozenbubble/FrozenGame.java @@ -70,9 +70,9 @@ import com.efortin.frozenbubble.VirtualInput; public class FrozenGame extends GameScreen { - private final int[] columnX = { 190, 206, 222, 238, 254, - 270, 286, 302, 318, 334, - 350, 366, 382, 398, 414 }; + private final int[] columnX = {190, 206, 222, 238, 254, + 270, 286, 302, 318, 334, + 350, 366, 382, 398, 414}; public final static int HORIZONTAL_MOVE = 0; public final static int FIRE = 1; @@ -117,6 +117,7 @@ public class FrozenGame extends GameScreen { Vector jumping; BubbleSprite[][] bubblePlay; + BubbleSprite[] scrolling; BmpWrap gameWon, gameLost; @@ -134,6 +135,7 @@ public class FrozenGame extends GameScreen { boolean endOfGame; boolean frozenify; + boolean isArcade; boolean isRemote; boolean readyToFire; boolean swapPressed; @@ -203,6 +205,8 @@ public FrozenGame(BmpWrap background_arg, isRemote = false; } + isArcade = FrozenBubble.arcadeGame; + /* * Create objects for all the game graphics. */ @@ -236,6 +240,7 @@ public FrozenGame(BmpWrap background_arg, bubblePlay = new BubbleSprite[LevelManager.NUM_COLS] [LevelManager.NUM_ROWS]; + scrolling = new BubbleSprite[LevelManager.NUM_COLS]; bubbleManager = new BubbleManager(bubbles); /* @@ -262,6 +267,10 @@ public FrozenGame(BmpWrap background_arg, } } + if (isArcade) { + addScrollRow(); + } + /* * Initialize the launch bubbles. */ @@ -331,6 +340,28 @@ public void addJumpingBubble(BubbleSprite sprite) { jumping.addElement(sprite); } + private void addScrollRow() { + byte[] newRow = levelManager.getNewRow(bubblePlay); + int colIdx = (levelManager.getRowOffset() + 1) % 2; + int rowMove = (int) compressor.getMoveDown(); + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + scrolling[column] = null; + } + for (int column = colIdx; column < LevelManager.NUM_COLS; column++) { + if (newRow[column] != -1) { + int color = newRow[column]; + BubbleSprite tempBubble = new BubbleSprite( + new Rect(columnX[colIdx], 44 - 28 + rowMove, 32, 32), + color, bubbles[color], bubblesBlind[color], frozenBubbles[color], + bubbleBlink, bubbleManager, soundManager, this); + scrolling[column] = tempBubble; + this.addSprite(tempBubble); + this.spriteToBack(tempBubble); + } + colIdx += 2; + } + } + private void blinkLine(int number) { int move = number%2; int column = (number+1) >> 1; @@ -378,8 +409,14 @@ private boolean checkLost() { if (lost) { penguin.updateState(PenguinSprite.STATE_GAME_LOST); - if (highscoreManager != null) - highscoreManager.lostLevel(); + if (highscoreManager != null) { + if (isArcade) { + highscoreManager.endLevel(nbBubbles); + } + else { + highscoreManager.lostLevel(); + } + } playResult = gameEnum.LOST; endOfGame = true; initFrozenify(); @@ -420,6 +457,21 @@ public void deleteJumpingBubble(BubbleSprite sprite) { jumping.removeElement(sprite); } + private void finishFrozenify() { + if (isArcade) { + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + if (scrolling[column] != null) { + this.spriteToBack(scrolling[column]); + scrolling[column].frozenify(); + } + } + } + frozenify = false; + this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), + gameLost)); + soundManager.playSound(FrozenBubble.SOUND_NOH); + } + private void frozenify() { frozenifyX--; if (frozenifyX < 0) { @@ -427,10 +479,7 @@ private void frozenify() { frozenifyY--; if (frozenifyY < 0) { - frozenify = false; - this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), - gameLost)); - soundManager.playSound(FrozenBubble.SOUND_NOH); + finishFrozenify(); return; } } @@ -442,10 +491,7 @@ private void frozenify() { frozenifyY--; if (frozenifyY < 0) { - frozenify = false; - this.addSprite(new ImageSprite(new Rect(152, 190, 337, 116), - gameLost)); - soundManager.playSound(FrozenBubble.SOUND_NOH); + finishFrozenify(); return; } } @@ -511,6 +557,10 @@ public Random getRandom() { return random; } + public int getRowOffset() { + return levelManager.getRowOffset(); + } + /** * Obtain this player's sendToOpponent value, which is * the number of attack bubbles to add to the opponent's attack bar. @@ -542,6 +592,10 @@ private void initFrozenify() { public void lowerCompressor(boolean playSound) { fixedBubbles = 0; + if (isArcade) { + return; + } + if (playSound) { soundManager.playSound(FrozenBubble.SOUND_NEWROOT); } @@ -558,9 +612,7 @@ public void lowerCompressor(boolean playSound) { playResult = gameEnum.LOST; endOfGame = true; initFrozenify(); - if (playSound) { - soundManager.playSound(FrozenBubble.SOUND_LOST); - } + soundManager.playSound(FrozenBubble.SOUND_LOST); } } } @@ -579,7 +631,7 @@ public boolean manageMovingBubble() { if (movingBubble != null) { movingBubble.move(); if (movingBubble.fixed()) { - if (!checkLost()) { + if (!checkLost() && !isArcade) { /* * If there are no bubbles in the bubble manager, then the * player has won the game. The bubble manager counts bubbles @@ -617,7 +669,6 @@ else if ((malusBar == null) || FrozenBubble.getCompressor()) { } public void paint(Canvas c, double scale, int dx, int dy) { - compressor.paint(c, scale, dx, dy); if (FrozenBubble.getMode() == FrozenBubble.GAME_NORMAL) { nextBubble.changeImage(bubbles[nextColor]); } @@ -625,6 +676,7 @@ public void paint(Canvas c, double scale, int dx, int dy) { nextBubble.changeImage(bubblesBlind[nextColor]); } super.paint(c, scale, dx, dy); + compressor.paint(c, scale, dx, dy); } public void pause() { @@ -850,7 +902,7 @@ else if (hurryTime%40 == 35) { } } - if ((malusBar == null) || FrozenBubble.getCompressor()) { + if (!isArcade && ((malusBar == null) || FrozenBubble.getCompressor())) { if (fixedBubbles == 6) { if (blinkDelay < 15) { blinkLine(blinkDelay); @@ -871,6 +923,10 @@ else if (fixedBubbles == 7) { } } + if (!endOfGame && isArcade) { + scrollBubbles(); + } + for (int i = 0; i < falling.size(); i++) { ((BubbleSprite)falling.elementAt(i)).fall(); } @@ -884,17 +940,19 @@ else if (fixedBubbles == 7) { } /* - * In a multiplayer game, check if the player lost due to attack - * bubbles overflowing the play area. + * Perform game synchronization tasks. */ - if (malusBar != null) { - checkLost(); + if (!endOfGame && movingBubble == null) { + synchronizeBubbleManager(); } /* - * Perform game synchronization tasks. + * In an arcade or multiplayer game, check if the player lost due to + * scrolling or attack bubbles overflowing the play area. */ - synchronizeBubbleManager(); + if ((malusBar != null) || isArcade) { + checkLost(); + } /* * If this player is the local player and is participating in a @@ -1033,10 +1091,12 @@ private Sprite restoreSprite(Bundle map, Vector imageList, int i) { Point lastOpenPosition = new Point( map.getInt(String.format("%d-%d-lastOpenPosition.x", player, i)), map.getInt(String.format("%d-%d-lastOpenPosition.y", player, i))); + int scroll = map.getInt(String.format("%d-%d-scroll", player, i)); + int scrollMax = map.getInt(String.format("%d-%d-scrollMax", player, i)); return new BubbleSprite(new Rect(left, top, right, bottom), color, moveX, moveY, realX, realY, fixed, blink, released, checkJump, checkFall, - fixedAnim, + fixedAnim, scroll, scrollMax, (frozen ? frozenBubbles[color] : bubbles[color]), lastOpenPosition, bubblesBlind[color], @@ -1086,29 +1146,37 @@ public void restoreState(Bundle map, Vector imageList) { restoreSprites(map, savedSprites, player); - jumping = new Vector(); + if (jumping == null) { + jumping = new Vector(); + } int numJumpingSprites = map.getInt(String.format("%d-numJumpingSprites", player)); for (int i = 0; i < numJumpingSprites; i++) { int spriteIdx = map.getInt(String.format("%d-jumping-%d", player, i)); jumping.addElement(savedSprites.elementAt(spriteIdx)); } - goingUp = new Vector(); + if (goingUp == null) { + goingUp = new Vector(); + } int numGoingUpSprites = map.getInt(String.format("%d-numGoingUpSprites", player)); for (int i = 0; i < numGoingUpSprites; i++) { int spriteIdx = map.getInt(String.format("%d-goingUp-%d", player, i)); goingUp.addElement(savedSprites.elementAt(spriteIdx)); } - falling = new Vector(); + if (falling == null) { + falling = new Vector(); + } int numFallingSprites = map.getInt(String.format("%d-numFallingSprites", player)); for (int i = 0; i < numFallingSprites; i++) { int spriteIdx = map.getInt(String.format("%d-falling-%d", player, i)); falling.addElement(savedSprites.elementAt(spriteIdx)); } - bubblePlay = new BubbleSprite[LevelManager.NUM_COLS] - [LevelManager.NUM_ROWS]; + if (bubblePlay == null) { + bubblePlay = new BubbleSprite[LevelManager.NUM_COLS] + [LevelManager.NUM_ROWS]; + } for (int i = 0; i < LevelManager.NUM_COLS; i++) { for (int j = 0; j < LevelManager.NUM_ROWS; j++) { int spriteIdx = @@ -1121,6 +1189,21 @@ public void restoreState(Bundle map, Vector imageList) { } } } + if (isArcade) { + if (scrolling == null) { + scrolling = new BubbleSprite[LevelManager.NUM_COLS]; + } + for (int i = 0; i < LevelManager.NUM_COLS; i++) { + int spriteIdx = + map.getInt(String.format("%d-scrolling-%d", player, i)); + if (spriteIdx != -1) { + scrolling[i] = (BubbleSprite)savedSprites.elementAt(spriteIdx); + } + else { + scrolling[i] = null; + } + } + } int launchBubbleId = map.getInt(String.format("%d-launchBubbleId", player)); launchBubble = (LaunchBubbleSprite)savedSprites.elementAt(launchBubbleId); @@ -1201,6 +1284,18 @@ public void saveState(Bundle map) { } } } + if (isArcade) { + for (int i = 0; i < LevelManager.NUM_COLS; i++) { + if (scrolling[i] != null) { + scrolling[i].saveState(map, savedSprites, player); + map.putInt(String.format("%d-scrolling-%d", player, i), + scrolling[i].getSavedId()); + } + else { + map.putInt(String.format("%d-scrolling-%d", player, i), -1); + } + } + } launchBubble.saveState(map, savedSprites, player); map.putInt(String.format("%d-launchBubbleId", player), launchBubble.getSavedId()); @@ -1247,6 +1342,48 @@ public void saveState(Bundle map) { } } + void scrollBubbles() { + boolean scroll = compressor.checkScroll(); + int moveDown = (int) compressor.getMoveDown(); + if (scroll) { + for (int row = LevelManager.NUM_ROWS - 1; row >= 0; row--) { + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + if (bubblePlay[column][row] != null) { + bubblePlay[column][row].scroll(moveDown); + } + } + } + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + if (scrolling[column] != null) { + scrolling[column].scroll(moveDown); + } + } + } + if ((movingBubble == null) && (moveDown >= 28.)) { + bubbleManager.initialize(); + compressor.moveDownSubtract(28.); + for (int row = LevelManager.NUM_ROWS - 1; row > 0; row--) { + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + bubblePlay[column][row ] = bubblePlay[column][row - 1]; + bubblePlay[column][row - 1] = null; + if (bubblePlay[column][row] != null) { + } + } + } + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + bubblePlay[column][0] = scrolling[column]; + } + addScrollRow(); + for (int row = 0; row < LevelManager.NUM_ROWS; row++) { + for (int column = 0; column < LevelManager.NUM_COLS; column++) { + if (bubblePlay[column][row] != null) { + bubblePlay[column][row].addToManager(); + } + } + } + } + } + /** * Set the game result associated with this player. * @param result - GAME_WON if this player won the game, GAME_LOST if @@ -1377,6 +1514,13 @@ public void synchronizeBubbleManager() { } } } + if (isArcade) { + for (int i = 0; i < LevelManager.NUM_COLS; i++) { + if (scrolling[i] != null) { + numBubblesPlay++; + } + } + } /* * If the number of bubble sprite grid entries does not match the * number of bubbles in the bubble manager, then we need to re- @@ -1397,6 +1541,14 @@ public void synchronizeBubbleManager() { } } } + if (isArcade) { + for (int i = 0; i < LevelManager.NUM_COLS; i++) { + if (scrolling[i] != null) { + scrolling[i].addToManager(); + this.addSprite(scrolling[i]); + } + } + } for (int i = 0; i < falling.size(); i++) { this.addSprite(falling.elementAt(i)); } diff --git a/src/org/jfedor/frozenbubble/GameView.java b/src/org/jfedor/frozenbubble/GameView.java index 98aac80..fe3da58 100644 --- a/src/org/jfedor/frozenbubble/GameView.java +++ b/src/org/jfedor/frozenbubble/GameView.java @@ -795,7 +795,7 @@ public GameThread(SurfaceHolder surfaceHolder) { } public GameThread(SurfaceHolder surfaceHolder, byte[] customLevels, - int startingLevel) { + int startingLevel, boolean arcadeGame) { //Log.i("frozen-bubble", "GameThread()"); mSurfaceHolder = surfaceHolder; Resources res = mContext.getResources(); @@ -945,34 +945,43 @@ public GameThread(SurfaceHolder surfaceHolder, byte[] customLevels, mFont = new BubbleFont(mFontImage); mLauncher = res.getDrawable(R.drawable.launcher); mSoundManager = new SoundManager(mContext); - mHighScoreManager = - new HighscoreManager(getContext(), - HighscoreManager.PUZZLE_DATABASE_NAME); - if (null == customLevels) { - try { - InputStream is = mContext.getAssets().open("levels.txt"); - int size = is.available(); - byte[] levels = new byte[size]; - is.read(levels); - is.close(); - SharedPreferences sp = mContext.getSharedPreferences( - FrozenBubble.PREFS_NAME, Context.MODE_PRIVATE); - startingLevel = sp.getInt("level", 0); - mLevelManager = new LevelManager(levels, startingLevel); - } catch (IOException e) { + if (arcadeGame) { + mHighScoreManager = + new HighscoreManager(getContext(), + HighscoreManager.ARCADE_DATABASE_NAME); + mLevelManager = new LevelManager(System.currentTimeMillis(), + FrozenBubble.getDifficulty()); + } + else { + mHighScoreManager = + new HighscoreManager(getContext(), + HighscoreManager.PUZZLE_DATABASE_NAME); + if (null == customLevels) { + try { + InputStream is = mContext.getAssets().open("levels.txt"); + int size = is.available(); + byte[] levels = new byte[size]; + is.read(levels); + is.close(); + SharedPreferences sp = mContext.getSharedPreferences( + FrozenBubble.PREFS_NAME, Context.MODE_PRIVATE); + startingLevel = sp.getInt("level", 0); + mLevelManager = new LevelManager(levels, startingLevel); + } catch (IOException e) { + /* + * Should never happen. + */ + throw new RuntimeException(e); + } + } + else { /* - * Should never happen. + * We were launched by the level editor. */ - throw new RuntimeException(e); + mLevelManager = new LevelManager(customLevels, startingLevel); } } - else { - /* - * We were launched by the level editor. - */ - mLevelManager = new LevelManager(customLevels, startingLevel); - } newGame(false); } @@ -1192,7 +1201,10 @@ private void doDraw(Canvas canvas) { if (mFrozenGame1 != null) { mFrozenGame1.paint(canvas, mDisplayScale, mPlayer1DX, mDisplayDY); } - if (numPlayers > 1) { + if (FrozenBubble.arcadeGame) { + drawDifficulty(canvas); + } + else if (numPlayers > 1) { if (mFrozenGame2 != null) { mFrozenGame2.paint(canvas, mDisplayScale, mPlayer2DX, mDisplayDY); } @@ -1394,6 +1406,14 @@ private void drawBackground(Canvas c) { mDisplayDX, mDisplayDY); } + private void drawDifficulty(Canvas canvas) { + int y = 433; + int x = 159; + int level = mLevelManager.getLevelIndex(); + mFont.print(LevelManager.DifficultyStrings[level], x, y, canvas, + mDisplayScale, mDisplayDX, mDisplayDY); + } + /** * Draw the high score screen for puzzle game mode. *

The objective of puzzle game mode is efficiency - fire as few @@ -1474,10 +1494,11 @@ else if (level < 100) { } /** - * Draw the low score screen for multiplayer game mode. - *

The objective of multiplayer game mode is endurance - fire as - * many bubbles as possible for as long as possible. Thus the low - * score will exhibit the most shots fired during the longest game. + * Draw the low score screen for arcade and multiplayer game modes. + *

The objective of arcade and multiplayer games is endurance - + * fire as many bubbles as possible for as long as possible. Thus + * the low score will exhibit the most shots fired during the + * longest game. * @param canvas - the drawing canvas to display the scores on. * @param level - the level difficulty index. */ @@ -1492,12 +1513,15 @@ private void drawLowScoreScreen(Canvas canvas, int level) { int y = 20; int ysp = 26; int indent = 10; - int orientation = getScreenOrientation(); - if (orientation == FrozenBubble.SCREEN_ORIENTATION_REVERSE_PORTRAIT) - x += GAMEFIELD_WIDTH/2; - else if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) - x -= GAMEFIELD_WIDTH/2; + if (!FrozenBubble.arcadeGame) { + int orientation = getScreenOrientation(); + + if (orientation == FrozenBubble.SCREEN_ORIENTATION_REVERSE_PORTRAIT) + x += GAMEFIELD_WIDTH/2; + else if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) + x -= GAMEFIELD_WIDTH/2; + } mFont.print("highscore for " + LevelManager.DifficultyStrings[mHighScoreManager.getLevel()], @@ -1916,7 +1940,7 @@ else if (mMode == stateEnum.PAUSED) { } } else if ((mHighScoreManager != null) && mShowScores) { - if (numPlayers > 1) { + if (FrozenBubble.arcadeGame || (numPlayers > 1)) { drawLowScoreScreen(c, mHighScoreManager.getLevel()); } else { @@ -2479,7 +2503,12 @@ else if (game2Result != gameEnum.PLAYING) { } else if ((game1State == gameEnum.NEXT_LOST) || (game1State == gameEnum.NEXT_WON )) { - if (game1State == gameEnum.NEXT_WON) { + if (FrozenBubble.arcadeGame) { + game1Status = gameEnum.WON; + mShowScores = true; + pause(); + } + else if (game1State == gameEnum.NEXT_WON) { game1Status = gameEnum.WON; mShowScores = true; pause(); @@ -2530,7 +2559,7 @@ public GameView(Context context, AttributeSet attrs) { super(context, attrs); //Log.i("frozen-bubble", "GameView constructor"); init(context, 1, (int) VirtualInput.PLAYER1, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL, null, 0); + FrozenBubble.LOCALE_LOCAL, FrozenBubble.arcadeGame, null, 0); } /** @@ -2543,7 +2572,8 @@ public GameView(Context context, byte[] levels, int startingLevel) { super(context); //Log.i("frozen-bubble", "GameView constructor"); init(context, 1, (int) VirtualInput.PLAYER1, FrozenBubble.HUMAN, - FrozenBubble.LOCALE_LOCAL, levels, startingLevel); + FrozenBubble.LOCALE_LOCAL, FrozenBubble.arcadeGame, levels, + startingLevel); } /** @@ -2554,15 +2584,17 @@ public GameView(Context context, byte[] levels, int startingLevel) { * @param opponentId - the opponent type ID, human or CPU. * @param gameLocale - the game topology, which can be either local, * or distributed over various network types. + * @param arcadeGame - arcade game mode flag. */ public GameView(Context context, int numPlayers, int myPlayerId, int opponentId, - int gameLocale) { + int gameLocale, + boolean arcadeGame) { super(context); //Log.i("frozen-bubble", "GameView constructor"); - init(context, numPlayers, myPlayerId, opponentId, gameLocale, null, 0); + init(context, numPlayers, myPlayerId, opponentId, gameLocale, arcadeGame, null, 0); } private boolean checkImmediateAction() { @@ -2633,6 +2665,7 @@ public void clearGameScreen(boolean clearScreen, int wait) { * @param opponentId - the opponent type ID, human or CPU. * @param gameLocale - the game topology, which can be either local, * or distributed over various network types. + * @param arcadeGame - arcade game mode flag. * @param levels - the single player game levels (can be null). * @param startingLevel - the single player game starting level. */ @@ -2641,6 +2674,7 @@ private void init(Context context, int myPlayerId, int opponentId, int gameLocale, + boolean arcadeGame, byte[] levels, int startingLevel) { mContext = context; @@ -2702,7 +2736,7 @@ private void init(Context context, mGameThread = new GameThread(holder); } else { - mGameThread = new GameThread(holder, levels, startingLevel); + mGameThread = new GameThread(holder, levels, startingLevel, arcadeGame); } mGameThread.setRunning(true); mGameThread.start(); diff --git a/src/org/jfedor/frozenbubble/LevelManager.java b/src/org/jfedor/frozenbubble/LevelManager.java index 4ddcbfa..cf931b9 100644 --- a/src/org/jfedor/frozenbubble/LevelManager.java +++ b/src/org/jfedor/frozenbubble/LevelManager.java @@ -84,22 +84,25 @@ public class LevelManager { "frozen bubble", "easy", "normal", - "moderate", + "medium", "hard", "insane" }; private boolean randomMode; private long randomSeed; - private int currentLevel; + private int currentLevel; + private int rowOffset; private Vector levelList; public void saveState(Bundle map) { map.putInt("LevelManager-currentLevel", currentLevel); + map.putInt("LevelManager-rowOffset", rowOffset); } public void restoreState(Bundle map) { currentLevel = map.getInt("LevelManager-currentLevel"); + rowOffset = map.getInt("LevelManager-rowOffset"); } /** @@ -114,6 +117,12 @@ public LevelManager(long seed, int difficulty) { randomMode = true; randomSeed = seed; currentLevel = difficulty; + if (FrozenBubble.arcadeGame) { + rowOffset = 1; + } + else { + rowOffset = 0; + } if (currentLevel < EASY) currentLevel = EASY; else if (currentLevel > INSANE) { @@ -133,6 +142,7 @@ public LevelManager(byte[] levels, int startingLevel) { randomSeed = 0; String allLevels = new String(levels); currentLevel = startingLevel; + rowOffset = 0; levelList = new Vector(); int nextLevel = allLevels.indexOf("\n\n"); @@ -202,12 +212,34 @@ else if (data.charAt(i) == 45) { for (int i = 0; i < NUM_COLS; i++) { temp[i][j] = (byte)rand.nextInt(currentLevel); } + if (FrozenBubble.arcadeGame) { + rowOffset = (rowOffset + 1) % 2; + } } randomSeed = rand.nextInt(); } return temp; } + public byte[] getNewRow(BubbleSprite[][] grid) { + byte[] tempRow = new byte[NUM_COLS]; + Random rand = new Random(randomSeed); + + for (int column = 0; column < NUM_COLS; column++) { + tempRow[column] = (byte)rand.nextInt(currentLevel); + } + + if (FrozenBubble.arcadeGame) { + rowOffset = (rowOffset + 1) % 2; + } + randomSeed = rand.nextInt(); + return tempRow; + } + + public int getRowOffset() { + return rowOffset; + } + public byte[][] getCurrentLevel() { if (!randomMode) { if (currentLevel < levelList.size()) { @@ -215,6 +247,9 @@ public byte[][] getCurrentLevel() { } } else { + if (FrozenBubble.arcadeGame) { + rowOffset = VS_ROWS % 2; + } return (byte[][])levelList.elementAt(0); } return null;