package org.andengine.examples.game.snake; import java.io.IOException; import org.andengine.audio.sound.Sound; import org.andengine.audio.sound.SoundFactory; import org.andengine.engine.camera.Camera; import org.andengine.engine.camera.hud.controls.BaseOnScreenControl; import org.andengine.engine.camera.hud.controls.BaseOnScreenControl.IOnScreenControlListener; import org.andengine.engine.camera.hud.controls.DigitalOnScreenControl; import org.andengine.engine.handler.timer.ITimerCallback; import org.andengine.engine.handler.timer.TimerHandler; import org.andengine.engine.options.EngineOptions; import org.andengine.engine.options.ScreenOrientation; import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy; import org.andengine.entity.Entity; import org.andengine.entity.modifier.RotationModifier; import org.andengine.entity.modifier.ScaleModifier; import org.andengine.entity.scene.Scene; import org.andengine.entity.sprite.Sprite; import org.andengine.entity.text.Text; import org.andengine.entity.text.TextOptions; import org.andengine.entity.util.FPSLogger; import org.andengine.examples.game.snake.adt.Direction; import org.andengine.examples.game.snake.adt.SnakeSuicideException; import org.andengine.examples.game.snake.entity.Frog; import org.andengine.examples.game.snake.entity.Snake; import org.andengine.examples.game.snake.entity.SnakeHead; import org.andengine.examples.game.snake.util.constants.SnakeConstants; import org.andengine.opengl.font.Font; import org.andengine.opengl.font.FontFactory; import org.andengine.opengl.texture.TextureOptions; import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas; import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory; import org.andengine.opengl.texture.region.ITextureRegion; import org.andengine.opengl.texture.region.TiledTextureRegion; import org.andengine.ui.activity.SimpleBaseGameActivity; import org.andengine.util.HorizontalAlign; import org.andengine.util.debug.Debug; import org.andengine.util.math.MathUtils; import android.graphics.Color; import android.opengl.GLES20; /** * (c) 2010 Nicolas Gramlich * (c) 2011 Zynga * * @author Nicolas Gramlich * @since 02:26:05 - 08.07.2010 */ public class SnakeGameActivity extends SimpleBaseGameActivity implements SnakeConstants { // =========================================================== // Constants // =========================================================== private static final int CAMERA_WIDTH = CELLS_HORIZONTAL * CELL_WIDTH; // 640 private static final int CAMERA_HEIGHT = CELLS_VERTICAL * CELL_HEIGHT; // 480 private static final int LAYER_COUNT = 4; private static final int LAYER_BACKGROUND = 0; private static final int LAYER_FOOD = LAYER_BACKGROUND + 1; private static final int LAYER_SNAKE = LAYER_FOOD + 1; private static final int LAYER_SCORE = LAYER_SNAKE + 1; // =========================================================== // Fields // =========================================================== private Camera mCamera; private DigitalOnScreenControl mDigitalOnScreenControl; private Font mFont; private BitmapTextureAtlas mBitmapTextureAtlas; private ITextureRegion mTailPartTextureRegion; private TiledTextureRegion mHeadTextureRegion; private TiledTextureRegion mFrogTextureRegion; private BitmapTextureAtlas mBackgroundTexture; private ITextureRegion mBackgroundTextureRegion; private BitmapTextureAtlas mOnScreenControlTexture; private ITextureRegion mOnScreenControlBaseTextureRegion; private ITextureRegion mOnScreenControlKnobTextureRegion; private Scene mScene; private Snake mSnake; private Frog mFrog; private int mScore = 0; private Text mScoreText; private Sound mGameOverSound; private Sound mMunchSound; protected boolean mGameRunning; private Text mGameOverText; // =========================================================== // Constructors // =========================================================== // =========================================================== // Getter & Setter // =========================================================== // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override public EngineOptions onCreateEngineOptions() { this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT); final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), this.mCamera); engineOptions.getAudioOptions().setNeedsSound(true); return engineOptions; } @Override public void onCreateResources() { /* Load the font we are going to use. */ FontFactory.setAssetBasePath("font/"); this.mFont = FontFactory.createFromAsset(this.getFontManager(), this.getTextureManager(), 512, 512, TextureOptions.BILINEAR, this.getAssets(), "Plok.ttf", 32, true, Color.WHITE); this.mFont.load(); BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/"); /* Load all the textures this game needs. */ this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 128, 128); this.mHeadTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "snake_head.png", 0, 0, 3, 1); this.mTailPartTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this, "snake_tailpart.png", 96, 0); this.mFrogTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "frog.png", 0, 64, 3, 1); this.mBitmapTextureAtlas.load(); this.mBackgroundTexture = new BitmapTextureAtlas(this.getTextureManager(), 1024, 512); this.mBackgroundTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBackgroundTexture, this, "snake_background.png", 0, 0); this.mBackgroundTexture.load(); this.mOnScreenControlTexture = new BitmapTextureAtlas(this.getTextureManager(), 256, 128, TextureOptions.BILINEAR); this.mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_base.png", 0, 0); this.mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, this, "onscreen_control_knob.png", 128, 0); this.mOnScreenControlTexture.load(); /* Load all the sounds this game needs. */ try { SoundFactory.setAssetBasePath("mfx/"); this.mGameOverSound = SoundFactory.createSoundFromAsset(this.getSoundManager(), this, "game_over.ogg"); this.mMunchSound = SoundFactory.createSoundFromAsset(this.getSoundManager(), this, "munch.ogg"); } catch (final IOException e) { Debug.e(e); } } @Override public Scene onCreateScene() { this.mEngine.registerUpdateHandler(new FPSLogger()); this.mScene = new Scene(); for(int i = 0; i < LAYER_COUNT; i++) { this.mScene.attachChild(new Entity()); } /* No background color needed as we have a fullscreen background sprite. */ this.mScene.setBackgroundEnabled(false); this.mScene.getChildByIndex(LAYER_BACKGROUND).attachChild(new Sprite(0, 0, this.mBackgroundTextureRegion, this.getVertexBufferObjectManager())); /* The ScoreText showing how many points the pEntity scored. */ this.mScoreText = new Text(5, 5, this.mFont, "Score: 0", "Score: XXXX".length(), this.getVertexBufferObjectManager()); this.mScoreText.setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); this.mScoreText.setAlpha(0.5f); this.mScene.getChildByIndex(LAYER_SCORE).attachChild(this.mScoreText); /* The Snake. */ this.mSnake = new Snake(Direction.RIGHT, 0, CELLS_VERTICAL / 2, this.mHeadTextureRegion, this.mTailPartTextureRegion, this.getVertexBufferObjectManager()); this.mSnake.getHead().animate(200); /* Snake starts with one tail. */ this.mSnake.grow(); this.mScene.getChildByIndex(LAYER_SNAKE).attachChild(this.mSnake); /* A frog to approach and eat. */ this.mFrog = new Frog(0, 0, this.mFrogTextureRegion, this.getVertexBufferObjectManager()); this.mFrog.animate(1000); this.setFrogToRandomCell(); this.mScene.getChildByIndex(LAYER_FOOD).attachChild(this.mFrog); /* The On-Screen Controls to control the direction of the snake. */ this.mDigitalOnScreenControl = new DigitalOnScreenControl(0, CAMERA_HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight(), this.mCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, this.getVertexBufferObjectManager(), new IOnScreenControlListener() { @Override public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) { if(pValueX == 1) { SnakeGameActivity.this.mSnake.setDirection(Direction.RIGHT); } else if(pValueX == -1) { SnakeGameActivity.this.mSnake.setDirection(Direction.LEFT); } else if(pValueY == 1) { SnakeGameActivity.this.mSnake.setDirection(Direction.DOWN); } else if(pValueY == -1) { SnakeGameActivity.this.mSnake.setDirection(Direction.UP); } } }); /* Make the controls semi-transparent. */ this.mDigitalOnScreenControl.getControlBase().setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); this.mDigitalOnScreenControl.getControlBase().setAlpha(0.5f); this.mScene.setChildScene(this.mDigitalOnScreenControl); /* Make the Snake move every 0.5 seconds. */ this.mScene.registerUpdateHandler(new TimerHandler(0.5f, true, new ITimerCallback() { @Override public void onTimePassed(final TimerHandler pTimerHandler) { if(SnakeGameActivity.this.mGameRunning) { try { SnakeGameActivity.this.mSnake.move(); } catch (final SnakeSuicideException e) { SnakeGameActivity.this.onGameOver(); } SnakeGameActivity.this.handleNewSnakePosition(); } } })); /* The title-text. */ final Text titleText = new Text(0, 0, this.mFont, "Snake\non a Phone!", new TextOptions(HorizontalAlign.CENTER), this.getVertexBufferObjectManager()); titleText.setPosition((CAMERA_WIDTH - titleText.getWidth()) * 0.5f, (CAMERA_HEIGHT - titleText.getHeight()) * 0.5f); titleText.setScale(0.0f); titleText.registerEntityModifier(new ScaleModifier(2, 0.0f, 1.0f)); this.mScene.getChildByIndex(LAYER_SCORE).attachChild(titleText); /* The handler that removes the title-text and starts the game. */ this.mScene.registerUpdateHandler(new TimerHandler(3.0f, new ITimerCallback() { @Override public void onTimePassed(final TimerHandler pTimerHandler) { SnakeGameActivity.this.mScene.unregisterUpdateHandler(pTimerHandler); SnakeGameActivity.this.mScene.getChildByIndex(LAYER_SCORE).detachChild(titleText); SnakeGameActivity.this.mGameRunning = true; } })); /* The game-over text. */ this.mGameOverText = new Text(0, 0, this.mFont, "Game\nOver", new TextOptions(HorizontalAlign.CENTER), this.getVertexBufferObjectManager()); this.mGameOverText.setPosition((CAMERA_WIDTH - this.mGameOverText.getWidth()) * 0.5f, (CAMERA_HEIGHT - this.mGameOverText.getHeight()) * 0.5f); this.mGameOverText.registerEntityModifier(new ScaleModifier(3, 0.1f, 2.0f)); this.mGameOverText.registerEntityModifier(new RotationModifier(3, 0, 720)); return this.mScene; } @Override public void onGameCreated() { } // =========================================================== // Methods // =========================================================== private void setFrogToRandomCell() { this.mFrog.setCell(MathUtils.random(1, CELLS_HORIZONTAL - 2), MathUtils.random(1, CELLS_VERTICAL - 2)); } private void handleNewSnakePosition() { final SnakeHead snakeHead = this.mSnake.getHead(); if(snakeHead.getCellX() < 0 || snakeHead.getCellX() >= CELLS_HORIZONTAL || snakeHead.getCellY() < 0 || snakeHead.getCellY() >= CELLS_VERTICAL) { this.onGameOver(); } else if(snakeHead.isInSameCell(this.mFrog)) { this.mScore += 50; this.mScoreText.setText("Score: " + this.mScore); this.mSnake.grow(); this.mMunchSound.play(); this.setFrogToRandomCell(); } } private void onGameOver() { this.mGameOverSound.play(); this.mScene.getChildByIndex(LAYER_SCORE).attachChild(this.mGameOverText); this.mGameRunning = false; } // =========================================================== // Inner and Anonymous Classes // =========================================================== }