Home | History | Annotate | Download | only in replicaisland
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.replica.replicaisland;
     18 
     19 import android.content.res.AssetManager;
     20 
     21 import java.io.IOException;
     22 import java.io.InputStream;
     23 
     24 /**
     25  * Manages information about the current level, including setup, deserialization, and tear-down.
     26  */
     27 public class LevelSystem extends BaseObject {
     28 
     29     public int mWidthInTiles;
     30     public int mHeightInTiles;
     31     public int mTileWidth;
     32     public int mTileHeight;
     33     public GameObject mBackgroundObject;
     34     public ObjectManager mRoot;
     35     private byte[] mWorkspaceBytes;
     36     private TiledWorld mSpawnLocations;
     37     private GameFlowEvent mGameFlowEvent;
     38     private int mAttempts;
     39     private LevelTree.Level mCurrentLevel;
     40 
     41     public LevelSystem() {
     42         super();
     43         mWorkspaceBytes = new byte[4];
     44         mGameFlowEvent = new GameFlowEvent();
     45         reset();
     46     }
     47 
     48     @Override
     49     public void reset() {
     50         if (mBackgroundObject != null && mRoot != null) {
     51             mBackgroundObject.removeAll();
     52             mBackgroundObject.commitUpdates();
     53             mRoot.remove(mBackgroundObject);
     54             mBackgroundObject = null;
     55             mRoot = null;
     56         }
     57         mSpawnLocations = null;
     58         mAttempts = 0;
     59         mCurrentLevel = null;
     60     }
     61 
     62     public float getLevelWidth() {
     63         return mWidthInTiles * mTileWidth;
     64     }
     65 
     66     public float getLevelHeight() {
     67         return mHeightInTiles * mTileHeight;
     68     }
     69 
     70     public void sendRestartEvent() {
     71         mGameFlowEvent.post(GameFlowEvent.EVENT_RESTART_LEVEL, 0,
     72                 sSystemRegistry.contextParameters.context);
     73     }
     74 
     75     public void sendNextLevelEvent() {
     76         mGameFlowEvent.post(GameFlowEvent.EVENT_GO_TO_NEXT_LEVEL, 0,
     77                 sSystemRegistry.contextParameters.context);
     78     }
     79 
     80     public void sendGameEvent(int type, int index, boolean immediate) {
     81         if (immediate) {
     82         	mGameFlowEvent.postImmediate(type, index,
     83                 sSystemRegistry.contextParameters.context);
     84         } else {
     85         	mGameFlowEvent.post(type, index,
     86                     sSystemRegistry.contextParameters.context);
     87         }
     88     }
     89 
     90     /**
     91      * Loads a level from a binary file.  The file consists of several layers, including background
     92      * tile layers and at most one collision layer.  Each layer is used to bootstrap related systems
     93      * and provide them with layer data.
     94      * @param stream  The input stream for the level file resource.
     95      * @param tiles   A tile library to use when constructing tiled background layers.
     96      * @param background  An object to assign background layer rendering components to.
     97      * @return
     98      */
     99     public boolean loadLevel(LevelTree.Level level, InputStream stream, ObjectManager root) {
    100         boolean success = false;
    101         mCurrentLevel = level;
    102         AssetManager.AssetInputStream byteStream = (AssetManager.AssetInputStream) stream;
    103         int signature;
    104         try {
    105             signature = (byte)byteStream.read();
    106             if (signature == 96) {
    107                 final int layerCount = (byte)byteStream.read();
    108                 final int backgroundIndex = (byte)byteStream.read();
    109 
    110                 mRoot = root;
    111                 mTileWidth = 32;
    112                 mTileHeight = 32;
    113 
    114                 ContextParameters params = sSystemRegistry.contextParameters;
    115                 int currentPriority = SortConstants.BACKGROUND_START + 1;
    116                 for (int x = 0; x < layerCount; x++) {
    117                     final int type = (byte)byteStream.read();
    118                     final int tileIndex = (byte)byteStream.read();
    119                     byteStream.read(mWorkspaceBytes, 0, 4);
    120                     final float scrollSpeed = Utils.byteArrayToFloat(mWorkspaceBytes);
    121 
    122                     // TODO: use a pool here?  Seems pointless.
    123                     TiledWorld world = new TiledWorld(byteStream);
    124 
    125                     if (type == 0) { // it's a background layer
    126                         assert mWidthInTiles != 0;
    127                         assert mTileWidth != 0;
    128 
    129                         // We require a collision layer to set up the tile sizes before we load.
    130                         // TODO: this really sucks.  there's no reason each layer can't have its
    131                         // own tile widths and heights.  Refactor this crap.
    132                         if (mWidthInTiles > 0 && mTileWidth > 0) {
    133 
    134                             LevelBuilder builder = sSystemRegistry.levelBuilder;
    135 
    136                             if (mBackgroundObject == null) {
    137                                 mBackgroundObject =
    138                                     builder.buildBackground(
    139                                     		backgroundIndex,
    140                                     		mWidthInTiles * mTileWidth,
    141                                     		mHeightInTiles * mTileHeight);
    142                                 root.add(mBackgroundObject);
    143                             }
    144 
    145 
    146                             builder.addTileMapLayer(mBackgroundObject, currentPriority,
    147                                     scrollSpeed, params.gameWidth, params.gameHeight,
    148                                     mTileWidth, mTileHeight, world, tileIndex);
    149 
    150 
    151                             currentPriority++;
    152                         }
    153 
    154                     } else if (type == 1) { // collision
    155                         // Collision always defines the world boundaries.
    156                         mWidthInTiles = world.getWidth();
    157                         mHeightInTiles = world.getHeight();
    158 
    159 
    160                         CollisionSystem collision = sSystemRegistry.collisionSystem;
    161                         if (collision != null) {
    162                             collision.initialize(world, mTileWidth, mTileHeight);
    163                         }
    164                     } else if (type == 2) { // objects
    165                         mSpawnLocations = world;
    166                         spawnObjects();
    167                     } else if (type == 3) { // hot spots
    168                         HotSpotSystem hotSpots = sSystemRegistry.hotSpotSystem;
    169                         if (hotSpots != null) {
    170                             hotSpots.setWorld(world);
    171                         }
    172 
    173                     }
    174                 }
    175 
    176                 // hack!
    177                 sSystemRegistry.levelBuilder.promoteForegroundLayer(mBackgroundObject);
    178 
    179             }
    180 
    181         } catch (IOException e) {
    182             //TODO: figure out the best way to deal with this.  Assert?
    183         }
    184 
    185         return success;
    186     }
    187 
    188     public void spawnObjects() {
    189         GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
    190         if (factory != null && mSpawnLocations != null) {
    191             DebugLog.d("LevelSystem", "Spawning Objects!");
    192 
    193             factory.spawnFromWorld(mSpawnLocations, mTileWidth, mTileHeight);
    194         }
    195     }
    196 
    197     public void incrementAttemptsCount() {
    198         mAttempts++;
    199     }
    200 
    201     public int getAttemptsCount() {
    202         return mAttempts;
    203     }
    204 
    205     public LevelTree.Level getCurrentLevel() {
    206     	return mCurrentLevel;
    207     }
    208 }
    209