Magic_Ling_Pixel_Dungeon/src/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java

658 lines
17 KiB
Java
Raw Normal View History

2014-07-27 13:39:07 +00:00
/*
* Pixel Dungeon
* Copyright (C) 2012-2014 Oleg Dolya
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.scenes;
2014-07-27 13:39:07 +00:00
import java.io.IOException;
import com.shatteredpixel.shatteredpixeldungeon.*;
import com.shatteredpixel.shatteredpixeldungeon.ui.LootIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.ResumeIndicator;
2014-07-27 13:39:07 +00:00
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.SkinnedBlock;
import com.watabou.noosa.Visual;
import com.watabou.noosa.audio.Music;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.particles.Emitter;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.EmoIcon;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
import com.shatteredpixel.shatteredpixeldungeon.effects.FloatingText;
import com.shatteredpixel.shatteredpixeldungeon.effects.Ripple;
import com.shatteredpixel.shatteredpixeldungeon.effects.SpellSprite;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.DiscardedItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.PlantSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.Banner;
import com.shatteredpixel.shatteredpixeldungeon.ui.BusyIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.GameLog;
import com.shatteredpixel.shatteredpixeldungeon.ui.HealthIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.Toast;
import com.shatteredpixel.shatteredpixeldungeon.ui.Toolbar;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag.Mode;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndGame;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory;
2014-07-27 13:39:07 +00:00
import com.watabou.utils.Random;
public class GameScene extends PixelScene {
private static final String TXT_WELCOME = "Welcome to the level %d of Pixel Dungeon!";
private static final String TXT_WELCOME_BACK = "Welcome back to the level %d of Pixel Dungeon!";
2014-07-27 13:39:07 +00:00
private static final String TXT_CHASM = "Your steps echo across the dungeon.";
private static final String TXT_WATER = "You hear water splashing around you.";
2014-07-27 13:39:07 +00:00
private static final String TXT_GRASS = "The smell of vegetation is thick in the air.";
private static final String TXT_DARK = "You can hear enemies moving in the darkness...";
2014-07-27 13:39:07 +00:00
private static final String TXT_SECRETS = "The atmosphere hints that this floor hides many secrets.";
static GameScene scene;
2014-07-27 13:39:07 +00:00
private SkinnedBlock water;
private DungeonTilemap tiles;
private FogOfWar fog;
private HeroSprite hero;
private GameLog log;
private BusyIndicator busy;
private static CellSelector cellSelector;
private Group terrain;
private Group ripples;
private Group plants;
private Group heaps;
private Group mobs;
private Group emitters;
private Group effects;
private Group gases;
private Group spells;
private Group statuses;
private Group emoicons;
private Toolbar toolbar;
private Toast prompt;
private AttackIndicator attack;
private LootIndicator loot;
private ResumeIndicator resume;
2014-07-27 13:39:07 +00:00
@Override
public void create() {
Music.INSTANCE.play( Assets.TUNE, true );
Music.INSTANCE.volume( 1f );
ShatteredPixelDungeon.lastClass(Dungeon.hero.heroClass.ordinal());
2014-07-27 13:39:07 +00:00
super.create();
Camera.main.zoom( defaultZoom + ShatteredPixelDungeon.zoom() );
2014-07-27 13:39:07 +00:00
scene = this;
terrain = new Group();
add( terrain );
water = new SkinnedBlock(
Level.WIDTH * DungeonTilemap.SIZE,
Level.HEIGHT * DungeonTilemap.SIZE,
Dungeon.level.waterTex() );
terrain.add( water );
ripples = new Group();
terrain.add( ripples );
tiles = new DungeonTilemap();
terrain.add( tiles );
Dungeon.level.addVisuals( this );
plants = new Group();
add( plants );
int size = Dungeon.level.plants.size();
for (int i=0; i < size; i++) {
addPlantSprite( Dungeon.level.plants.valueAt( i ) );
}
heaps = new Group();
add( heaps );
size = Dungeon.level.heaps.size();
for (int i=0; i < size; i++) {
addHeapSprite( Dungeon.level.heaps.valueAt( i ) );
}
emitters = new Group();
effects = new Group();
emoicons = new Group();
mobs = new Group();
add( mobs );
for (Mob mob : Dungeon.level.mobs) {
addMobSprite( mob );
if (Statistics.amuletObtained) {
mob.beckon( Dungeon.hero.pos );
}
}
add( emitters );
add( effects );
gases = new Group();
add( gases );
for (Blob blob : Dungeon.level.blobs.values()) {
blob.emitter = null;
addBlobSprite( blob );
}
fog = new FogOfWar( Level.WIDTH, Level.HEIGHT );
fog.updateVisibility( Dungeon.visible, Dungeon.level.visited, Dungeon.level.mapped );
add( fog );
brightness( ShatteredPixelDungeon.brightness() );
2014-07-27 13:39:07 +00:00
spells = new Group();
add( spells );
statuses = new Group();
add( statuses );
add( emoicons );
hero = new HeroSprite();
hero.place( Dungeon.hero.pos );
hero.updateArmor();
mobs.add( hero );
add( new HealthIndicator() );
add( cellSelector = new CellSelector( tiles ) );
StatusPane sb = new StatusPane();
sb.camera = uiCamera;
sb.setSize( uiCamera.width, 0 );
add( sb );
toolbar = new Toolbar();
toolbar.camera = uiCamera;
toolbar.setRect( 0,uiCamera.height - toolbar.height(), uiCamera.width, toolbar.height() );
add( toolbar );
attack = new AttackIndicator();
2014-07-27 13:39:07 +00:00
attack.camera = uiCamera;
attack.setPos(
uiCamera.width - attack.width(),
2014-07-27 13:39:07 +00:00
toolbar.top() - attack.height() );
add( attack );
loot = new LootIndicator();
loot.camera = uiCamera;
add( loot );
resume = new ResumeIndicator();
resume.camera = uiCamera;
add( resume );
layoutTags();
2014-07-27 13:39:07 +00:00
log = new GameLog();
log.camera = uiCamera;
log.setRect( 0, toolbar.top(), attack.left(), 0 );
add( log );
if (Dungeon.depth < Statistics.deepestFloor)
2014-07-27 13:39:07 +00:00
GLog.i( TXT_WELCOME_BACK, Dungeon.depth );
else
2014-07-27 13:39:07 +00:00
GLog.i( TXT_WELCOME, Dungeon.depth );
Sample.INSTANCE.play( Assets.SND_DESCEND );
2014-07-27 13:39:07 +00:00
switch (Dungeon.level.feeling) {
case CHASM:
GLog.w( TXT_CHASM );
break;
case WATER:
GLog.w( TXT_WATER );
break;
case GRASS:
GLog.w( TXT_GRASS );
break;
case DARK:
GLog.w( TXT_DARK );
break;
2014-07-27 13:39:07 +00:00
default:
}
if (Dungeon.level instanceof RegularLevel &&
((RegularLevel)Dungeon.level).secretDoors > Random.IntRange( 3, 4 )) {
GLog.w( TXT_SECRETS );
}
2014-07-27 13:39:07 +00:00
busy = new BusyIndicator();
busy.camera = uiCamera;
busy.x = 1;
busy.y = sb.bottom() + 1;
add( busy );
switch (InterlevelScene.mode) {
case RESURRECT:
WandOfBlink.appear( Dungeon.hero, Dungeon.level.entrance );
new Flare( 8, 32 ).color( 0xFFFF66, true ).show( hero, 2f ) ;
break;
case RETURN:
WandOfBlink.appear( Dungeon.hero, Dungeon.hero.pos );
break;
case FALL:
Chasm.heroLand();
break;
case DESCEND:
switch (Dungeon.depth) {
case 1:
WndStory.showChapter( WndStory.ID_SEWERS );
break;
case 6:
WndStory.showChapter( WndStory.ID_PRISON );
break;
case 11:
WndStory.showChapter( WndStory.ID_CAVES );
break;
case 16:
WndStory.showChapter( WndStory.ID_METROPOLIS );
break;
case 22:
WndStory.showChapter( WndStory.ID_HALLS );
break;
}
if (Dungeon.hero.isAlive() && Dungeon.depth != 22) {
Badges.validateNoKilling();
}
break;
default:
}
Camera.main.target = hero;
fadeIn();
}
public void destroy() {
freezeEmitters = false;
scene = null;
2014-07-27 13:39:07 +00:00
Badges.saveGlobal();
super.destroy();
}
@Override
public synchronized void pause() {
try {
Dungeon.saveAll();
Badges.saveGlobal();
} catch (IOException e) {
//
}
}
2014-07-27 13:39:07 +00:00
@Override
public synchronized void update() {
if (Dungeon.hero == null) {
return;
}
2014-07-27 13:39:07 +00:00
super.update();
if (!freezeEmitters) water.offset( 0, -5 * Game.elapsed );
2014-07-27 13:39:07 +00:00
Actor.process();
if (Dungeon.hero.ready && !Dungeon.hero.paralysed) {
log.newLine();
}
if (tagAttack != attack.active || tagLoot != loot.visible || tagResume != resume.visible) {
tagAttack = attack.active;
tagLoot = loot.visible;
tagResume = resume.visible;
layoutTags();
}
2014-07-27 13:39:07 +00:00
cellSelector.enabled = Dungeon.hero.ready;
}
private boolean tagAttack = false;
private boolean tagLoot = false;
private boolean tagResume = false;
private void layoutTags() {
float pos = tagAttack ? attack.top() : toolbar.top();
if (tagLoot) {
loot.setPos( uiCamera.width - loot.width(), pos - loot.height() );
pos = loot.top();
}
if (tagResume) {
resume.setPos( uiCamera.width - resume.width(), pos - resume.height() );
}
}
2014-07-27 13:39:07 +00:00
@Override
protected void onBackPressed() {
if (!cancel()) {
add( new WndGame() );
}
}
@Override
protected void onMenuPressed() {
if (Dungeon.hero.ready) {
selectItem( null, WndBag.Mode.ALL, null );
}
}
public void brightness( boolean value ) {
water.rm = water.gm = water.bm =
tiles.rm = tiles.gm = tiles.bm =
value ? 1.5f : 1.0f;
if (value) {
fog.am = +2f;
fog.aa = -1f;
} else {
fog.am = +1f;
fog.aa = 0f;
}
}
private void addHeapSprite( Heap heap ) {
ItemSprite sprite = heap.sprite = (ItemSprite)heaps.recycle( ItemSprite.class );
sprite.revive();
sprite.link( heap );
heaps.add( sprite );
}
private void addDiscardedSprite( Heap heap ) {
heap.sprite = (DiscardedItemSprite)heaps.recycle( DiscardedItemSprite.class );
heap.sprite.revive();
heap.sprite.link( heap );
heaps.add( heap.sprite );
}
private void addPlantSprite( Plant plant ) {
(plant.sprite = (PlantSprite)plants.recycle( PlantSprite.class )).reset( plant );
}
private void addBlobSprite( final Blob gas ) {
if (gas.emitter == null) {
gases.add( new BlobEmitter( gas ) );
}
}
private void addMobSprite( Mob mob ) {
CharSprite sprite = mob.sprite();
sprite.visible = Dungeon.visible[mob.pos];
mobs.add( sprite );
sprite.link( mob );
}
private void prompt( String text ) {
if (prompt != null) {
prompt.killAndErase();
prompt = null;
}
if (text != null) {
prompt = new Toast( text ) {
@Override
protected void onClose() {
cancel();
}
};
prompt.camera = uiCamera;
prompt.setPos( (uiCamera.width - prompt.width()) / 2, uiCamera.height - 60 );
add( prompt );
}
}
private void showBanner( Banner banner ) {
banner.camera = uiCamera;
banner.x = align( uiCamera, (uiCamera.width - banner.width) / 2 );
banner.y = align( uiCamera, (uiCamera.height - banner.height) / 3 );
add( banner );
}
// -------------------------------------------------------
public static void add( Plant plant ) {
if (scene != null) {
scene.addPlantSprite( plant );
}
}
public static void add( Blob gas ) {
Actor.add( gas );
if (scene != null) {
scene.addBlobSprite( gas );
}
}
public static void add( Heap heap ) {
if (scene != null) {
scene.addHeapSprite( heap );
}
}
public static void discard( Heap heap ) {
if (scene != null) {
scene.addDiscardedSprite( heap );
}
}
public static void add( Mob mob ) {
Dungeon.level.mobs.add( mob );
Actor.add( mob );
Actor.occupyCell( mob );
scene.addMobSprite( mob );
}
public static void add( Mob mob, float delay ) {
Dungeon.level.mobs.add( mob );
Actor.addDelayed( mob, delay );
Actor.occupyCell( mob );
scene.addMobSprite( mob );
}
public static void add( EmoIcon icon ) {
scene.emoicons.add( icon );
}
public static void effect( Visual effect ) {
scene.effects.add( effect );
}
public static Ripple ripple( int pos ) {
Ripple ripple = (Ripple)scene.ripples.recycle( Ripple.class );
ripple.reset( pos );
return ripple;
}
public static SpellSprite spellSprite() {
return (SpellSprite)scene.spells.recycle( SpellSprite.class );
}
public static Emitter emitter() {
if (scene != null) {
Emitter emitter = (Emitter)scene.emitters.recycle( Emitter.class );
emitter.revive();
return emitter;
} else {
return null;
}
}
public static FloatingText status() {
return scene != null ? (FloatingText)scene.statuses.recycle( FloatingText.class ) : null;
}
public static void pickUp( Item item ) {
scene.toolbar.pickup( item );
}
public static void updateMap() {
if (scene != null) {
scene.tiles.updated.set( 0, 0, Level.WIDTH, Level.HEIGHT );
}
}
public static void updateMap( int cell ) {
if (scene != null) {
scene.tiles.updated.union( cell % Level.WIDTH, cell / Level.WIDTH );
}
}
public static void discoverTile( int pos, int oldValue ) {
if (scene != null) {
scene.tiles.discover( pos, oldValue );
}
}
public static void show( Window wnd ) {
cancelCellSelector();
scene.add( wnd );
}
public static void afterObserve() {
if (scene != null) {
scene.fog.updateVisibility( Dungeon.visible, Dungeon.level.visited, Dungeon.level.mapped );
for (Mob mob : Dungeon.level.mobs) {
mob.sprite.visible = Dungeon.visible[mob.pos];
}
}
}
public static void flash( int color ) {
scene.fadeIn( 0xFF000000 | color, true );
}
public static void gameOver() {
Banner gameOver = new Banner( BannerSprites.get( BannerSprites.Type.GAME_OVER ) );
gameOver.show( 0x000000, 1f );
scene.showBanner( gameOver );
Sample.INSTANCE.play( Assets.SND_DEATH );
}
public static void bossSlain() {
if (Dungeon.hero.isAlive()) {
Banner bossSlain = new Banner( BannerSprites.get( BannerSprites.Type.BOSS_SLAIN ) );
bossSlain.show( 0xFFFFFF, 0.3f, 5f );
scene.showBanner( bossSlain );
Sample.INSTANCE.play( Assets.SND_BOSS );
}
}
public static void handleCell( int cell ) {
cellSelector.select( cell );
}
public static void selectCell( CellSelector.Listener listener ) {
cellSelector.listener = listener;
scene.prompt( listener.prompt() );
}
private static boolean cancelCellSelector() {
if (cellSelector.listener != null && cellSelector.listener != defaultCellListener) {
cellSelector.cancel();
return true;
} else {
return false;
}
}
public static WndBag selectItem( WndBag.Listener listener, WndBag.Mode mode, String title ) {
cancelCellSelector();
WndBag wnd = mode == Mode.SEED ?
WndBag.seedPouch( listener, mode, title ) :
WndBag.lastBag( listener, mode, title );
scene.add( wnd );
return wnd;
}
static boolean cancel() {
if (Dungeon.hero.curAction != null || Dungeon.hero.restoreHealth) {
Dungeon.hero.curAction = null;
Dungeon.hero.restoreHealth = false;
return true;
} else {
return cancelCellSelector();
}
}
public static void ready() {
selectCell( defaultCellListener );
QuickSlotButton.cancel();
2014-07-27 13:39:07 +00:00
}
private static final CellSelector.Listener defaultCellListener = new CellSelector.Listener() {
@Override
public void onSelect( Integer cell ) {
2014-10-18 08:56:57 +00:00
if (Dungeon.hero.handle( cell )) {
Dungeon.hero.next();
}
2014-07-27 13:39:07 +00:00
}
@Override
public String prompt() {
return null;
}
};
}