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 
LevelSystem()41     public LevelSystem() {
42         super();
43         mWorkspaceBytes = new byte[4];
44         mGameFlowEvent = new GameFlowEvent();
45         reset();
46     }
47 
48     @Override
reset()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 
getLevelWidth()62     public float getLevelWidth() {
63         return mWidthInTiles * mTileWidth;
64     }
65 
getLevelHeight()66     public float getLevelHeight() {
67         return mHeightInTiles * mTileHeight;
68     }
69 
sendRestartEvent()70     public void sendRestartEvent() {
71         mGameFlowEvent.post(GameFlowEvent.EVENT_RESTART_LEVEL, 0,
72                 sSystemRegistry.contextParameters.context);
73     }
74 
sendNextLevelEvent()75     public void sendNextLevelEvent() {
76         mGameFlowEvent.post(GameFlowEvent.EVENT_GO_TO_NEXT_LEVEL, 0,
77                 sSystemRegistry.contextParameters.context);
78     }
79 
sendGameEvent(int type, int index, boolean immediate)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      */
loadLevel(LevelTree.Level level, InputStream stream, ObjectManager root)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 
spawnObjects()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 
incrementAttemptsCount()197     public void incrementAttemptsCount() {
198         mAttempts++;
199     }
200 
getAttemptsCount()201     public int getAttemptsCount() {
202         return mAttempts;
203     }
204 
getCurrentLevel()205     public LevelTree.Level getCurrentLevel() {
206     	return mCurrentLevel;
207     }
208 }
209