blob: 3b76ecda2087af12b4ec527b611f25bd1cbe81c8 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.replica.replicaisland;
import android.content.res.AssetManager;
import java.io.IOException;
import java.io.InputStream;
/**
* Manages information about the current level, including setup, deserialization, and tear-down.
*/
public class LevelSystem extends BaseObject {
public int mWidthInTiles;
public int mHeightInTiles;
public int mTileWidth;
public int mTileHeight;
public GameObject mBackgroundObject;
public ObjectManager mRoot;
private byte[] mWorkspaceBytes;
private TiledWorld mSpawnLocations;
private GameFlowEvent mGameFlowEvent;
private int mAttempts;
private LevelTree.Level mCurrentLevel;
public LevelSystem() {
super();
mWorkspaceBytes = new byte[4];
mGameFlowEvent = new GameFlowEvent();
reset();
}
@Override
public void reset() {
if (mBackgroundObject != null && mRoot != null) {
mBackgroundObject.removeAll();
mBackgroundObject.commitUpdates();
mRoot.remove(mBackgroundObject);
mBackgroundObject = null;
mRoot = null;
}
mSpawnLocations = null;
mAttempts = 0;
mCurrentLevel = null;
}
public float getLevelWidth() {
return mWidthInTiles * mTileWidth;
}
public float getLevelHeight() {
return mHeightInTiles * mTileHeight;
}
public void sendRestartEvent() {
mGameFlowEvent.post(GameFlowEvent.EVENT_RESTART_LEVEL, 0,
sSystemRegistry.contextParameters.context);
}
public void sendNextLevelEvent() {
mGameFlowEvent.post(GameFlowEvent.EVENT_GO_TO_NEXT_LEVEL, 0,
sSystemRegistry.contextParameters.context);
}
public void sendGameEvent(int type, int index, boolean immediate) {
if (immediate) {
mGameFlowEvent.postImmediate(type, index,
sSystemRegistry.contextParameters.context);
} else {
mGameFlowEvent.post(type, index,
sSystemRegistry.contextParameters.context);
}
}
/**
* Loads a level from a binary file. The file consists of several layers, including background
* tile layers and at most one collision layer. Each layer is used to bootstrap related systems
* and provide them with layer data.
* @param stream The input stream for the level file resource.
* @param tiles A tile library to use when constructing tiled background layers.
* @param background An object to assign background layer rendering components to.
* @return
*/
public boolean loadLevel(LevelTree.Level level, InputStream stream, ObjectManager root) {
boolean success = false;
mCurrentLevel = level;
AssetManager.AssetInputStream byteStream = (AssetManager.AssetInputStream) stream;
int signature;
try {
signature = (byte)byteStream.read();
if (signature == 96) {
final int layerCount = (byte)byteStream.read();
final int backgroundIndex = (byte)byteStream.read();
mRoot = root;
mTileWidth = 32;
mTileHeight = 32;
ContextParameters params = sSystemRegistry.contextParameters;
int currentPriority = SortConstants.BACKGROUND_START + 1;
for (int x = 0; x < layerCount; x++) {
final int type = (byte)byteStream.read();
final int tileIndex = (byte)byteStream.read();
byteStream.read(mWorkspaceBytes, 0, 4);
final float scrollSpeed = Utils.byteArrayToFloat(mWorkspaceBytes);
// TODO: use a pool here? Seems pointless.
TiledWorld world = new TiledWorld(byteStream);
if (type == 0) { // it's a background layer
assert mWidthInTiles != 0;
assert mTileWidth != 0;
// We require a collision layer to set up the tile sizes before we load.
// TODO: this really sucks. there's no reason each layer can't have its
// own tile widths and heights. Refactor this crap.
if (mWidthInTiles > 0 && mTileWidth > 0) {
LevelBuilder builder = sSystemRegistry.levelBuilder;
if (mBackgroundObject == null) {
mBackgroundObject =
builder.buildBackground(
backgroundIndex,
mWidthInTiles * mTileWidth,
mHeightInTiles * mTileHeight);
root.add(mBackgroundObject);
}
builder.addTileMapLayer(mBackgroundObject, currentPriority,
scrollSpeed, params.gameWidth, params.gameHeight,
mTileWidth, mTileHeight, world, tileIndex);
currentPriority++;
}
} else if (type == 1) { // collision
// Collision always defines the world boundaries.
mWidthInTiles = world.getWidth();
mHeightInTiles = world.getHeight();
CollisionSystem collision = sSystemRegistry.collisionSystem;
if (collision != null) {
collision.initialize(world, mTileWidth, mTileHeight);
}
} else if (type == 2) { // objects
mSpawnLocations = world;
spawnObjects();
} else if (type == 3) { // hot spots
HotSpotSystem hotSpots = sSystemRegistry.hotSpotSystem;
if (hotSpots != null) {
hotSpots.setWorld(world);
}
}
}
// hack!
sSystemRegistry.levelBuilder.promoteForegroundLayer(mBackgroundObject);
}
} catch (IOException e) {
//TODO: figure out the best way to deal with this. Assert?
}
return success;
}
public void spawnObjects() {
GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
if (factory != null && mSpawnLocations != null) {
DebugLog.d("LevelSystem", "Spawning Objects!");
factory.spawnFromWorld(mSpawnLocations, mTileWidth, mTileHeight);
}
}
public void incrementAttemptsCount() {
mAttempts++;
}
public int getAttemptsCount() {
return mAttempts;
}
public LevelTree.Level getCurrentLevel() {
return mCurrentLevel;
}
}