V0.1.0 Partial Commit

changed package and application names to differentiate from main PD
release
This commit is contained in:
Evan Debenham
2014-08-03 14:46:22 -04:00
parent 65dd9c2dc0
commit aed303672a
474 changed files with 3468 additions and 3458 deletions
@@ -0,0 +1,93 @@
/*
* 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;
import android.content.Intent;
import android.net.Uri;
import com.watabou.input.Touchscreen.Touch;
import com.watabou.noosa.BitmapTextMultiline;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Image;
import com.watabou.noosa.TouchArea;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
public class AboutScene extends PixelScene {
private static final String TXT =
"Code & graphics: Watabou\n" +
"Music: Cube_Code\n\n" +
"This game is inspired by Brian Walker's Brogue. " +
"Try it on Windows, Mac OS or Linux - it's awesome! ;)\n\n" +
"Please visit official website for additional info:";
private static final String LNK = "shatteredpixeldungeon.watabou.ru";
@Override
public void create() {
super.create();
BitmapTextMultiline text = createMultiline( TXT, 8 );
text.maxWidth = Math.min( Camera.main.width, 120 );
text.measure();
add( text );
text.x = align( (Camera.main.width - text.width()) / 2 );
text.y = align( (Camera.main.height - text.height()) / 2 );
BitmapTextMultiline link = createMultiline( LNK, 8 );
link.maxWidth = Math.min( Camera.main.width, 120 );
link.measure();
link.hardlight( Window.TITLE_COLOR );
add( link );
link.x = text.x;
link.y = text.y + text.height();
TouchArea hotArea = new TouchArea( link ) {
@Override
protected void onClick( Touch touch ) {
Intent intent = new Intent( Intent.ACTION_VIEW, Uri.parse( "http://" + LNK ) );
Game.instance.startActivity( intent );
}
};
add( hotArea );
Image wata = Icons.WATA.get();
wata.x = align( text.x + (text.width() - wata.width) / 2 );
wata.y = text.y - wata.height - 8;
add( wata );
new Flare( 7, 64 ).color( 0x112233, true ).show( wata, 0 ).angularSpeed = +20;
Archs archs = new Archs();
archs.setSize( Camera.main.width, Camera.main.height );
addToBack( archs );
fadeIn();
}
@Override
protected void onBackPressed() {
Game.switchScene( TitleScene.class );
}
}
@@ -0,0 +1,133 @@
/*
* 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;
import com.watabou.noosa.BitmapTextMultiline;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Image;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.watabou.utils.Random;
public class AmuletScene extends PixelScene {
private static final String TXT_EXIT = "Let's call it a day";
private static final String TXT_STAY = "I'm not done yet";
private static final int WIDTH = 120;
private static final int BTN_HEIGHT = 18;
private static final float SMALL_GAP = 2;
private static final float LARGE_GAP = 8;
private static final String TXT =
"You finally hold it in your hands, the Amulet of Yendor. Using its power " +
"you can take over the world or bring peace and prosperity to people or whatever. " +
"Anyway, your life will change forever and this game will end here. " +
"Or you can stay a mere mortal a little longer.";
public static boolean noText = false;
private Image amulet;
@Override
public void create() {
super.create();
BitmapTextMultiline text = null;
if (!noText) {
text = createMultiline( TXT, 8 );
text.maxWidth = WIDTH;
text.measure();
add( text );
}
amulet = new Image( Assets.AMULET );
add( amulet );
RedButton btnExit = new RedButton( TXT_EXIT ) {
@Override
protected void onClick() {
Dungeon.deleteGame( Dungeon.hero.heroClass, true );
Game.switchScene( noText ? TitleScene.class : RankingsScene.class );
}
};
btnExit.setSize( WIDTH, BTN_HEIGHT );
add( btnExit );
RedButton btnStay = new RedButton( TXT_STAY ) {
@Override
protected void onClick() {
onBackPressed();
}
};
btnStay.setSize( WIDTH, BTN_HEIGHT );
add( btnStay );
float height;
if (noText) {
height = amulet.height + LARGE_GAP + btnExit.height() + SMALL_GAP + btnStay.height();
amulet.x = align( (Camera.main.width - amulet.width) / 2 );
amulet.y = align( (Camera.main.height - height) / 2 );
btnExit.setPos( (Camera.main.width - btnExit.width()) / 2, amulet.y + amulet.height + LARGE_GAP );
btnStay.setPos( btnExit.left(), btnExit.bottom() + SMALL_GAP );
} else {
height = amulet.height + LARGE_GAP + text.height() + LARGE_GAP + btnExit.height() + SMALL_GAP + btnStay.height();
amulet.x = align( (Camera.main.width - amulet.width) / 2 );
amulet.y = align( (Camera.main.height - height) / 2 );
text.x = align( (Camera.main.width - text.width()) / 2 );
text.y = amulet.y + amulet.height + LARGE_GAP;
btnExit.setPos( (Camera.main.width - btnExit.width()) / 2, text.y + text.height() + LARGE_GAP );
btnStay.setPos( btnExit.left(), btnExit.bottom() + SMALL_GAP );
}
new Flare( 8, 48 ).color( 0xFFDDBB, true ).show( amulet, 0 ).angularSpeed = +30;
fadeIn();
}
@Override
protected void onBackPressed() {
InterlevelScene.mode = InterlevelScene.Mode.CONTINUE;
Game.switchScene( InterlevelScene.class );
}
private float timer = 0;
@Override
public void update() {
super.update();
if ((timer -= Game.elapsed) < 0) {
timer = Random.Float( 0.5f, 5f );
Speck star = (Speck)recycle( Speck.class );
star.reset( 0, amulet.x + 10.5f, amulet.y + 5.5f, Speck.DISCOVER );
add( star );
}
}
}
@@ -0,0 +1,88 @@
/*
* 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;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.NinePatch;
import com.watabou.noosa.audio.Music;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Chrome;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.BadgesList;
import com.shatteredpixel.shatteredpixeldungeon.ui.ScrollPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
public class BadgesScene extends PixelScene {
private static final String TXT_TITLE = "Your Badges";
@Override
public void create() {
super.create();
Music.INSTANCE.play( Assets.THEME, true );
Music.INSTANCE.volume( 1f );
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
Archs archs = new Archs();
archs.setSize( w, h );
add( archs );
int pw = Math.min( 160, w - 10 );
int ph = h - 24;
NinePatch panel = Chrome.get( Chrome.Type.WINDOW );
panel.size( pw, ph );
panel.x = (w - pw) / 2;
panel.y = (h - ph) / 2;
add( panel );
BitmapText title = PixelScene.createText( TXT_TITLE, 9 );
title.hardlight( Window.TITLE_COLOR );
title.measure();
title.x = align( (w - title.width()) / 2 );
title.y = align( (panel.y - title.baseLine()) / 2 );
add( title );
Badges.loadGlobal();
ScrollPane list = new BadgesList( true );
add( list );
list.setRect(
panel.x + panel.marginLeft(),
panel.y + panel.marginTop(),
panel.innerWidth(),
panel.innerHeight() );
fadeIn();
}
@Override
protected void onBackPressed() {
Game.switchScene( TitleScene.class );
}
}
@@ -0,0 +1,158 @@
/*
* 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;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.watabou.input.Touchscreen.Touch;
import com.watabou.noosa.TouchArea;
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
import com.watabou.utils.GameMath;
import com.watabou.utils.PointF;
public class CellSelector extends TouchArea {
public Listener listener = null;
public boolean enabled;
private float dragThreshold;
public CellSelector( DungeonTilemap map ) {
super( map );
camera = map.camera();
dragThreshold = PixelScene.defaultZoom * DungeonTilemap.SIZE / 2;
}
@Override
protected void onClick( Touch touch ) {
if (dragging) {
dragging = false;
} else {
select( ((DungeonTilemap)target).screenToTile(
(int)touch.current.x,
(int)touch.current.y ) );
}
}
public void select( int cell ) {
if (enabled && listener != null && cell != -1) {
listener.onSelect( cell );
GameScene.ready();
} else {
GameScene.cancel();
}
}
private boolean pinching = false;
private Touch another;
private float startZoom;
private float startSpan;
@Override
protected void onTouchDown( Touch t ) {
if (t != touch && another == null) {
if (!touch.down) {
touch = t;
onTouchDown( t );
return;
}
pinching = true;
another = t;
startSpan = PointF.distance( touch.current, another.current );
startZoom = camera.zoom;
dragging = false;
}
}
@Override
protected void onTouchUp( Touch t ) {
if (pinching && (t == touch || t == another)) {
pinching = false;
int zoom = Math.round( camera.zoom );
camera.zoom( zoom );
ShatteredPixelDungeon.zoom((int) (zoom - PixelScene.defaultZoom));
dragging = true;
if (t == touch) {
touch = another;
}
another = null;
lastPos.set( touch.current );
}
}
private boolean dragging = false;
private PointF lastPos = new PointF();
@Override
protected void onDrag( Touch t ) {
camera.target = null;
if (pinching) {
float curSpan = PointF.distance( touch.current, another.current );
camera.zoom( GameMath.gate(
PixelScene.minZoom,
startZoom * curSpan / startSpan,
PixelScene.maxZoom ) );
} else {
if (!dragging && PointF.distance( t.current, t.start ) > dragThreshold) {
dragging = true;
lastPos.set( t.current );
} else if (dragging) {
camera.scroll.offset( PointF.diff( lastPos, t.current ).invScale( camera.zoom ) );
lastPos.set( t.current );
}
}
}
public void cancel() {
if (listener != null) {
listener.onSelect( null );
}
GameScene.ready();
}
public interface Listener {
void onSelect( Integer cell );
String prompt();
}
}
@@ -0,0 +1,613 @@
/*
* 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;
import java.io.IOException;
import com.shatteredpixel.shatteredpixeldungeon.*;
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.QuickSlot;
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;
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!";
private static final String TXT_NIGHT_MODE = "Be cautious, since the dungeon is even more dangerous at night!";
private static final String TXT_CHASM = "Your steps echo across the dungeon.";
private static final String TXT_WATER = "You hear the water splashing around you.";
private static final String TXT_GRASS = "The smell of vegetation is thick in the air.";
private static final String TXT_SECRETS = "The atmosphere hints that this floor hides many secrets.";
static GameScene scene;
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;
@Override
public void create() {
Music.INSTANCE.play( Assets.TUNE, true );
Music.INSTANCE.volume( 1f );
ShatteredPixelDungeon.lastClass(Dungeon.hero.heroClass.ordinal());
super.create();
Camera.main.zoom( defaultZoom + ShatteredPixelDungeon.zoom() );
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() );
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 );
AttackIndicator attack = new AttackIndicator();
attack.camera = uiCamera;
attack.setPos(
uiCamera.width - attack.width(),
toolbar.top() - attack.height() );
add( attack );
log = new GameLog();
log.camera = uiCamera;
log.setRect( 0, toolbar.top(), attack.left(), 0 );
add( log );
if (Dungeon.depth < Statistics.deepestFloor) {
GLog.i( TXT_WELCOME_BACK, Dungeon.depth );
} else {
GLog.i( TXT_WELCOME, Dungeon.depth );
Sample.INSTANCE.play( Assets.SND_DESCEND );
}
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;
default:
}
if (Dungeon.level instanceof RegularLevel &&
((RegularLevel)Dungeon.level).secretDoors > Random.IntRange( 3, 4 )) {
GLog.w( TXT_SECRETS );
}
if (Dungeon.nightMode && !Dungeon.bossLevel()) {
GLog.w( TXT_NIGHT_MODE );
}
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() {
scene = null;
Badges.saveGlobal();
super.destroy();
}
@Override
public synchronized void pause() {
try {
Dungeon.saveAll();
Badges.saveGlobal();
} catch (IOException e) {
//
}
}
@Override
public synchronized void update() {
if (Dungeon.hero == null) {
return;
}
super.update();
water.offset( 0, -5 * Game.elapsed );
Actor.process();
if (Dungeon.hero.ready && !Dungeon.hero.paralysed) {
log.newLine();
}
cellSelector.enabled = Dungeon.hero.ready;
}
@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 );
QuickSlot.cancel();
}
private static final CellSelector.Listener defaultCellListener = new CellSelector.Listener() {
@Override
public void onSelect( Integer cell ) {
if (cell != -1) {
Dungeon.hero.handle( cell );
}
}
@Override
public String prompt() {
return null;
}
};
}
@@ -0,0 +1,335 @@
/*
* 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;
import java.io.FileNotFoundException;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.audio.Music;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndError;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory;
public class InterlevelScene extends PixelScene {
private static final float TIME_TO_FADE = 0.3f;
private static final String TXT_DESCENDING = "Descending...";
private static final String TXT_ASCENDING = "Ascending...";
private static final String TXT_LOADING = "Loading...";
private static final String TXT_RESURRECTING= "Resurrecting...";
private static final String TXT_RETURNING = "Returning...";
private static final String TXT_FALLING = "Falling...";
private static final String ERR_FILE_NOT_FOUND = "File not found. For some reason.";
private static final String ERR_GENERIC = "Something went wrong..." ;
public static enum Mode {
DESCEND, ASCEND, CONTINUE, RESURRECT, RETURN, FALL
};
public static Mode mode;
public static int returnDepth;
public static int returnPos;
public static boolean noStory = false;
public static boolean fallIntoPit;
private enum Phase {
FADE_IN, STATIC, FADE_OUT
};
private Phase phase;
private float timeLeft;
private BitmapText message;
private Thread thread;
private String error = null;
@Override
public void create() {
super.create();
String text = "";
switch (mode) {
case DESCEND:
text = TXT_DESCENDING;
break;
case ASCEND:
text = TXT_ASCENDING;
break;
case CONTINUE:
text = TXT_LOADING;
break;
case RESURRECT:
text = TXT_RESURRECTING;
break;
case RETURN:
text = TXT_RETURNING;
break;
case FALL:
text = TXT_FALLING;
break;
}
message = PixelScene.createText( text, 9 );
message.measure();
message.x = (Camera.main.width - message.width()) / 2;
message.y = (Camera.main.height - message.height()) / 2;
add( message );
phase = Phase.FADE_IN;
timeLeft = TIME_TO_FADE;
thread = new Thread() {
@Override
public void run() {
try {
Generator.reset();
Sample.INSTANCE.load(
Assets.SND_OPEN,
Assets.SND_UNLOCK,
Assets.SND_ITEM,
Assets.SND_DEWDROP,
Assets.SND_HIT,
Assets.SND_MISS,
Assets.SND_STEP,
Assets.SND_WATER,
Assets.SND_DESCEND,
Assets.SND_EAT,
Assets.SND_READ,
Assets.SND_LULLABY,
Assets.SND_DRINK,
Assets.SND_SHATTER,
Assets.SND_ZAP,
Assets.SND_LIGHTNING,
Assets.SND_LEVELUP,
Assets.SND_DEATH,
Assets.SND_CHALLENGE,
Assets.SND_CURSED,
Assets.SND_EVOKE,
Assets.SND_TRAP,
Assets.SND_TOMB,
Assets.SND_ALERT,
Assets.SND_MELD,
Assets.SND_BOSS,
Assets.SND_BLAST,
Assets.SND_PLANT,
Assets.SND_RAY,
Assets.SND_BEACON,
Assets.SND_TELEPORT,
Assets.SND_CHARMS,
Assets.SND_MASTERY,
Assets.SND_PUFF,
Assets.SND_ROCKS,
Assets.SND_BURNING,
Assets.SND_FALLING,
Assets.SND_GHOST,
Assets.SND_SECRET,
Assets.SND_BONES );
switch (mode) {
case DESCEND:
descend();
break;
case ASCEND:
ascend();
break;
case CONTINUE:
restore();
break;
case RESURRECT:
resurrect();
break;
case RETURN:
returnTo();
break;
case FALL:
fall();
break;
}
if ((Dungeon.depth % 5) == 0) {
Sample.INSTANCE.load( Assets.SND_BOSS );
}
} catch (FileNotFoundException e) {
error = ERR_FILE_NOT_FOUND;
} catch (Exception e ) {
error = ERR_GENERIC;
}
if (phase == Phase.STATIC && error == null) {
phase = Phase.FADE_OUT;
timeLeft = TIME_TO_FADE;
}
}
};
thread.start();
}
@Override
public void update() {
super.update();
float p = timeLeft / TIME_TO_FADE;
switch (phase) {
case FADE_IN:
message.alpha( 1 - p );
if ((timeLeft -= Game.elapsed) <= 0) {
if (!thread.isAlive() && error == null) {
phase = Phase.FADE_OUT;
timeLeft = TIME_TO_FADE;
} else {
phase = Phase.STATIC;
}
}
break;
case FADE_OUT:
message.alpha( p );
if (mode == Mode.CONTINUE || (mode == Mode.DESCEND && Dungeon.depth == 1)) {
Music.INSTANCE.volume( p );
}
if ((timeLeft -= Game.elapsed) <= 0) {
Game.switchScene( GameScene.class );
}
break;
case STATIC:
if (error != null) {
add( new WndError( error ) {
public void onBackPressed() {
super.onBackPressed();
Game.switchScene( StartScene.class );
};
} );
}
break;
}
}
private void descend() throws Exception {
Actor.fixTime();
if (Dungeon.hero == null) {
Dungeon.init();
if (noStory) {
Dungeon.chapters.add( WndStory.ID_SEWERS );
noStory = false;
}
} else {
Dungeon.saveLevel();
}
Level level;
if (Dungeon.depth >= Statistics.deepestFloor) {
level = Dungeon.newLevel();
} else {
Dungeon.depth++;
level = Dungeon.loadLevel( Dungeon.hero.heroClass );
}
Dungeon.switchLevel( level, level.entrance );
}
private void fall() throws Exception {
Actor.fixTime();
Dungeon.saveLevel();
Level level;
if (Dungeon.depth >= Statistics.deepestFloor) {
level = Dungeon.newLevel();
} else {
Dungeon.depth++;
level = Dungeon.loadLevel( Dungeon.hero.heroClass );
}
Dungeon.switchLevel( level, fallIntoPit ? level.pitCell() : level.randomRespawnCell() );
}
private void ascend() throws Exception {
Actor.fixTime();
Dungeon.saveLevel();
Dungeon.depth--;
Level level = Dungeon.loadLevel( Dungeon.hero.heroClass );
Dungeon.switchLevel( level, level.exit );
}
private void returnTo() throws Exception {
Actor.fixTime();
Dungeon.saveLevel();
Dungeon.depth = returnDepth;
Level level = Dungeon.loadLevel( Dungeon.hero.heroClass );
Dungeon.switchLevel( level, Level.resizingNeeded ? level.adjustPos( returnPos ) : returnPos );
}
private void restore() throws Exception {
Actor.fixTime();
Dungeon.loadGame( StartScene.curClass );
if (Dungeon.depth == -1) {
Dungeon.depth = Statistics.deepestFloor;
Dungeon.switchLevel( Dungeon.loadLevel( StartScene.curClass ), -1 );
} else {
Level level = Dungeon.loadLevel( StartScene.curClass );
Dungeon.switchLevel( level, Level.resizingNeeded ? level.adjustPos( Dungeon.hero.pos ) : Dungeon.hero.pos );
}
}
private void resurrect() throws Exception {
Actor.fixTime();
if (Dungeon.bossLevel()) {
Dungeon.hero.resurrect( Dungeon.depth );
Dungeon.depth--;
Level level = Dungeon.newLevel(/* true */);
Dungeon.switchLevel( level, level.entrance );
} else {
Dungeon.hero.resurrect( -1 );
Dungeon.resetLevel();
}
}
@Override
protected void onBackPressed() {
}
}
@@ -0,0 +1,47 @@
/*
* 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;
import com.watabou.noosa.Game;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory;
public class IntroScene extends PixelScene {
private static final String TEXT =
"Many heroes of all kinds ventured into the Dungeon before you. Some of them have returned with treasures and magical " +
"artifacts, most have never been heard of since. But none have succeeded in retrieving the Amulet of Yendor, " +
"which is told to be hidden in the depths of the Dungeon.\n\n" +
"" +
"You consider yourself ready for the challenge, but most importantly, you feel that fortune smiles on you. " +
"It's time to start your own adventure!";
@Override
public void create() {
super.create();
add( new WndStory( TEXT ) {
@Override
public void hide() {
super.hide();
Game.switchScene( InterlevelScene.class );
}
} );
fadeIn();
}
}
@@ -0,0 +1,325 @@
/*
* 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;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.watabou.input.Touchscreen;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.BitmapText.Font;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.BitmapTextMultiline;
import com.watabou.noosa.Camera;
import com.watabou.noosa.ColorBlock;
import com.watabou.noosa.Game;
import com.watabou.noosa.Scene;
import com.watabou.noosa.Visual;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.effects.BadgeBanner;
import com.watabou.utils.BitmapCache;
public class PixelScene extends Scene {
public static final float MIN_WIDTH = 128;
public static final float MIN_HEIGHT = 224;
public static float defaultZoom = 0;
public static float minZoom;
public static float maxZoom;
public static boolean landscapeAvailable;
public static Camera uiCamera;
public static BitmapText.Font font1x;
public static BitmapText.Font font15x;
public static BitmapText.Font font2x;
public static BitmapText.Font font25x;
public static BitmapText.Font font3x;
@Override
public void create() {
super.create();
GameScene.scene = null;
defaultZoom = (int)Math.ceil( Game.density * 2.5 );
while ((
Game.width / defaultZoom < MIN_WIDTH ||
Game.height / defaultZoom < MIN_HEIGHT
) && defaultZoom > 1) {
defaultZoom--;
}
landscapeAvailable =
Game.height / defaultZoom >= MIN_WIDTH &&
Game.width / defaultZoom >= MIN_HEIGHT;
if (ShatteredPixelDungeon.scaleUp()) {
while ((Game.width / (defaultZoom + 1) >= MIN_WIDTH && Game.height / (defaultZoom + 1) >= MIN_HEIGHT)) {
defaultZoom++;
}
}
minZoom = 1;
maxZoom = defaultZoom * 2;
Camera.reset( new PixelCamera( defaultZoom ) );
float uiZoom = defaultZoom;
uiCamera = Camera.createFullscreen( uiZoom );
Camera.add( uiCamera );
if (font1x == null) {
// 3x5 (6)
font1x = Font.colorMarked(
BitmapCache.get( Assets.FONTS1X ), 0x00000000, BitmapText.Font.LATIN_FULL );
font1x.baseLine = 6;
font1x.tracking = -1;
// 5x8 (10)
font15x = Font.colorMarked(
BitmapCache.get( Assets.FONTS15X ), 12, 0x00000000, BitmapText.Font.LATIN_FULL );
font15x.baseLine = 9;
font15x.tracking = -1;
// 6x10 (12)
font2x = Font.colorMarked(
BitmapCache.get( Assets.FONTS2X ), 14, 0x00000000, BitmapText.Font.LATIN_FULL );
font2x.baseLine = 11;
font2x.tracking = -1;
// 7x12 (15)
font25x = Font.colorMarked(
BitmapCache.get( Assets.FONTS25X ), 17, 0x00000000, BitmapText.Font.LATIN_FULL );
font25x.baseLine = 13;
font25x.tracking = -1;
// 9x15 (18)
font3x = Font.colorMarked(
BitmapCache.get( Assets.FONTS3X ), 22, 0x00000000, BitmapText.Font.LATIN_FULL );
font3x.baseLine = 17;
font3x.tracking = -2;
}
Sample.INSTANCE.load(
Assets.SND_CLICK,
Assets.SND_BADGE,
Assets.SND_GOLD );
}
@Override
public void destroy() {
super.destroy();
Touchscreen.event.removeAll();
}
public static BitmapText.Font font;
public static float scale;
public static void chooseFont( float size ) {
float pt = size * defaultZoom;
if (pt >= 19) {
scale = pt / 19;
if (1.5 <= scale && scale < 2) {
font = font25x;
scale = (int)(pt / 14);
} else {
font = font3x;
scale = (int)scale;
}
} else if (pt >= 14) {
scale = pt / 14;
if (1.8 <= scale && scale < 2) {
font = font2x;
scale = (int)(pt / 12);
} else {
font = font25x;
scale = (int)scale;
}
} else if (pt >= 12) {
scale = pt / 12;
if (1.7 <= scale && scale < 2) {
font = font15x;
scale = (int)(pt / 10);
} else {
font = font2x;
scale = (int)scale;
}
} else if (pt >= 10) {
scale = pt / 10;
if (1.4 <= scale && scale < 2) {
font = font1x;
scale = (int)(pt / 7);
} else {
font = font15x;
scale = (int)scale;
}
} else {
font = font1x;
scale = Math.max( 1, (int)(pt / 7) );
}
scale /= defaultZoom;
}
public static BitmapText createText( float size ) {
return createText( null, size );
}
public static BitmapText createText( String text, float size ) {
chooseFont( size );
BitmapText result = new BitmapText( text, font );
result.scale.set( scale );
return result;
}
public static BitmapTextMultiline createMultiline( float size ) {
return createMultiline( null, size );
}
public static BitmapTextMultiline createMultiline( String text, float size ) {
chooseFont( size );
BitmapTextMultiline result = new BitmapTextMultiline( text, font );
result.scale.set( scale );
return result;
}
public static float align( Camera camera, float pos ) {
return ((int)(pos * camera.zoom)) / camera.zoom;
}
public static float align( float pos ) {
return ((int)(pos * defaultZoom)) / defaultZoom;
}
public static void align( Visual v ) {
Camera c = v.camera();
v.x = align( c, v.x );
v.y = align( c, v.y );
}
protected void fadeIn() {
fadeIn( 0xFF000000, false );
}
protected void fadeIn( int color, boolean light ) {
add( new Fader( color, light ) );
}
public static void showBadge( Badges.Badge badge ) {
BadgeBanner banner = BadgeBanner.show( badge.image );
banner.camera = uiCamera;
banner.x = align( banner.camera, (banner.camera.width - banner.width) / 2 );
banner.y = align( banner.camera, (banner.camera.height - banner.height) / 3 );
Game.scene().add( banner );
}
protected static class Fader extends ColorBlock {
private static float FADE_TIME = 1f;
private boolean light;
private float time;
public Fader( int color, boolean light ) {
super( uiCamera.width, uiCamera.height, color );
this.light = light;
camera = uiCamera;
alpha( 1f );
time = FADE_TIME;
}
@Override
public void update() {
super.update();
if ((time -= Game.elapsed) <= 0) {
alpha( 0f );
parent.remove( this );
} else {
alpha( time / FADE_TIME );
}
}
@Override
public void draw() {
if (light) {
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE );
super.draw();
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
} else {
super.draw();
}
}
}
private static class PixelCamera extends Camera {
public PixelCamera( float zoom ) {
super(
(int)(Game.width - Math.ceil( Game.width / zoom ) * zoom) / 2,
(int)(Game.height - Math.ceil( Game.height / zoom ) * zoom) / 2,
(int)Math.ceil( Game.width / zoom ),
(int)Math.ceil( Game.height / zoom ), zoom );
}
@Override
protected void updateMatrix() {
float sx = align( this, scroll.x + shakeX );
float sy = align( this, scroll.y + shakeY );
matrix[0] = +zoom * invW2;
matrix[5] = -zoom * invH2;
matrix[12] = -1 + x * invW2 - sx * matrix[0];
matrix[13] = +1 - y * invH2 - sy * matrix[5];
}
}
}
@@ -0,0 +1,219 @@
/*
* 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;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.BitmapTextMultiline;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Music;
import com.watabou.noosa.ui.Button;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Rankings;
import com.shatteredpixel.shatteredpixeldungeon.effects.Flare;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndError;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndRanking;
public class RankingsScene extends PixelScene {
private static final String TXT_TITLE = "Top Rankings";
private static final String TXT_TOTAL = "Total games played: %d";
private static final String TXT_NO_GAMES = "No games have been played yet.";
private static final String TXT_NO_INFO = "No additional information";
private static final float ROW_HEIGHT = 30;
private static final float GAP = 4;
private Archs archs;
@Override
public void create() {
super.create();
Music.INSTANCE.play( Assets.THEME, true );
Music.INSTANCE.volume( 1f );
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
archs = new Archs();
archs.setSize( w, h );
add( archs );
Rankings.INSTANCE.load();
if (Rankings.INSTANCE.records.size() > 0) {
float left = (w - Math.min( 160, w )) / 2 + GAP;
float top = align( (h - ROW_HEIGHT * Rankings.INSTANCE.records.size()) / 2 );
BitmapText title = PixelScene.createText( TXT_TITLE, 9 );
title.hardlight( Window.TITLE_COLOR );
title.measure();
title.x = align( (w - title.width()) / 2 );
title.y = align( top - title.height() - GAP );
add( title );
int pos = 0;
for (Rankings.Record rec : Rankings.INSTANCE.records) {
Record row = new Record( pos, pos == Rankings.INSTANCE.lastRecord, rec );
row.setRect( left, top + pos * ROW_HEIGHT, w - left * 2, ROW_HEIGHT );
add( row );
pos++;
}
if (Rankings.INSTANCE.totalNumber >= Rankings.TABLE_SIZE) {
BitmapText total = PixelScene.createText( Utils.format( TXT_TOTAL, Rankings.INSTANCE.totalNumber ), 8 );
total.hardlight( Window.TITLE_COLOR );
total.measure();
total.x = align( (w - total.width()) / 2 );
total.y = align( top + pos * ROW_HEIGHT + GAP );
add( total );
}
} else {
BitmapText title = PixelScene.createText( TXT_NO_GAMES, 8 );
title.hardlight( Window.TITLE_COLOR );
title.measure();
title.x = align( (w - title.width()) / 2 );
title.y = align( (h - title.height()) / 2 );
add( title );
}
fadeIn();
}
@Override
protected void onBackPressed() {
Game.switchScene( TitleScene.class );
}
public static class Record extends Button {
private static final float GAP = 4;
private static final int TEXT_WIN = 0xFFFF88;
private static final int TEXT_LOSE = 0xCCCCCC;
private static final int FLARE_WIN = 0x888866;
private static final int FLARE_LOSE = 0x666666;
private Rankings.Record rec;
private ItemSprite shield;
private Flare flare;
private BitmapText position;
private BitmapTextMultiline desc;
private Image classIcon;
public Record( int pos, boolean latest, Rankings.Record rec ) {
super();
this.rec = rec;
if (latest) {
flare = new Flare( 6, 24 );
flare.angularSpeed = 90;
flare.color( rec.win ? FLARE_WIN : FLARE_LOSE );
addToBack( flare );
}
position.text( Integer.toString( pos+1 ) );
position.measure();
desc.text( rec.info );
desc.measure();
if (rec.win) {
shield.view( ItemSpriteSheet.AMULET, null );
position.hardlight( TEXT_WIN );
desc.hardlight( TEXT_WIN );
} else {
position.hardlight( TEXT_LOSE );
desc.hardlight( TEXT_LOSE );
}
classIcon.copy( Icons.get( rec.heroClass ) );
}
@Override
protected void createChildren() {
super.createChildren();
shield = new ItemSprite( ItemSpriteSheet.TOMB, null );
add( shield );
position = new BitmapText( PixelScene.font1x );
add( position );
desc = createMultiline( 9 );
add( desc );
classIcon = new Image();
add( classIcon );
}
@Override
protected void layout() {
super.layout();
shield.x = x;
shield.y = y + (height - shield.height) / 2;
position.x = align( shield.x + (shield.width - position.width()) / 2 );
position.y = align( shield.y + (shield.height - position.height()) / 2 + 1 );
if (flare != null) {
flare.point( shield.center() );
}
classIcon.x = align( x + width - classIcon.width );
classIcon.y = shield.y;
desc.x = shield.x + shield.width + GAP;
desc.maxWidth = (int)(classIcon.x - desc.x);
desc.measure();
desc.y = position.y + position.baseLine() - desc.baseLine();
}
@Override
protected void onClick() {
if (rec.gameFile.length() > 0) {
parent.add( new WndRanking( rec.gameFile ) );
} else {
parent.add( new WndError( TXT_NO_INFO ) );
}
}
}
}
@@ -0,0 +1,506 @@
/*
* 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;
import java.util.HashMap;
import com.shatteredpixel.shatteredpixeldungeon.*;
import com.watabou.input.Touchscreen;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.BitmapTextMultiline;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.NinePatch;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.TouchArea;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.particles.Emitter;
import com.watabou.noosa.ui.Button;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.Icons;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.SimpleButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.Window;
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndList;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndTitledMessage;
public class StartScene extends PixelScene {
private static final float BUTTON_HEIGHT = 24;
private static final float GAP = 2;
private static final String TXT_TITLE = "Select Your Hero";
private static final String TXT_LOAD = "Load Game";
private static final String TXT_NEW = "New Game";
private static final String TXT_ERASE = "Erase current game";
private static final String TXT_DPTH_LVL = "Depth: %d, level: %d";
private static final String TXT_REALLY = "Do you really want to start new game?";
private static final String TXT_WARNING = "Your current game progress will be erased.";
private static final String TXT_YES = "Yes, start new game";
private static final String TXT_NO = "No, return to main menu";
private static final String TXT_UNLOCK = "To unlock this character class, slay the 3rd boss with any other class";
private float width;
private float height;
private float top;
private float left;
private static HashMap<HeroClass, GemButton> gems = new HashMap<HeroClass, StartScene.GemButton>();
private Avatar avatar;
private NinePatch frame;
private BitmapText className;
private SimpleButton btnMastery;
private GameButton btnLoad;
private GameButton btnNewGame;
private boolean huntressUnlocked;
private Group unlock;
public static HeroClass curClass;
@Override
public void create() {
super.create();
Badges.loadGlobal();
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
width = 128;
height = 220;
left = (w - width) / 2;
top = (h - height) / 2;
Archs archs = new Archs();
archs.setSize( w, h );
add( archs );
BitmapText title = PixelScene.createText( TXT_TITLE, 9 );
title.hardlight( Window.TITLE_COLOR );
title.measure();
title.x = align( (w - title.width()) / 2 );
title.y = align( top );
add( title );
float pos = title.y + title.height() + GAP;
GemButton btns[] = {
new GemButton( HeroClass.WARRIOR ),
new GemButton( HeroClass.MAGE ),
new GemButton( HeroClass.ROGUE ),
new GemButton( HeroClass.HUNTRESS ) };
float space = width;
for (GemButton btn : btns) {
space -= btn.width();
}
float p = 0;
for (GemButton btn : btns) {
add( btn );
btn.setPos( align( left + p ), align( pos ) );
p += btn.width() + space / 3;
}
frame = Chrome.get( Chrome.Type.TOAST_TR );
add( frame );
btnNewGame = new GameButton( TXT_NEW ) {
@Override
protected void onClick() {
if (GamesInProgress.check( curClass ) != null) {
StartScene.this.add( new WndOptions( TXT_REALLY, TXT_WARNING, TXT_YES, TXT_NO ) {
@Override
protected void onSelect( int index ) {
if (index == 0) {
startNewGame();
}
}
} );
} else {
startNewGame();
}
}
};
add( btnNewGame );
btnLoad = new GameButton( TXT_LOAD ) {
@Override
protected void onClick() {
InterlevelScene.mode = InterlevelScene.Mode.CONTINUE;
Game.switchScene( InterlevelScene.class );
}
};
add( btnLoad );
frame.size( width, BUTTON_HEIGHT + frame.marginVer() );
frame.x = align( left );
frame.y = align( h - top - frame.height() );
avatar = new Avatar();
NinePatch avFrame = Chrome.get( Chrome.Type.TOAST_TR );
avFrame.size( avatar.width() * 1.6f, avatar.height() * 1.6f );
avFrame.x = align( (w - avFrame.width()) / 2 );
avFrame.y = align( (frame.y + btns[0].bottom() - avFrame.height()) / 2 );
add( avFrame );
className = PixelScene.createText( "Placeholder", 9 );
className.measure();
className.y = align( avFrame.y + avFrame.innerBottom() - className.height() );
add( className );
avatar.point( avFrame.center() );
avatar.camera = Camera.main;
align( avatar );
add( avatar );
Image iconInfo = Icons.INFO.get();
iconInfo.x = avFrame.x + avFrame.innerRight() - iconInfo.width();
iconInfo.y = avFrame.y + avFrame.marginTop();
add( iconInfo );
add( new TouchArea( avFrame ) {
@Override
protected void onClick( Touchscreen.Touch touch ) {
add( new WndList( curClass.perks() ) );
}
} );
btnMastery = new SimpleButton( Icons.MASTERY.get() ) {
@Override
protected void onClick() {
String text = null;
switch (curClass) {
case WARRIOR:
text = HeroSubClass.GLADIATOR.desc() + "\n\n" + HeroSubClass.BERSERKER.desc();
break;
case MAGE:
text = HeroSubClass.BATTLEMAGE.desc() + "\n\n" + HeroSubClass.WARLOCK.desc();
break;
case ROGUE:
text = HeroSubClass.FREERUNNER.desc() + "\n\n" + HeroSubClass.ASSASSIN.desc();
break;
case HUNTRESS:
text = HeroSubClass.SNIPER.desc() + "\n\n" + HeroSubClass.WARDEN.desc();
break;
}
StartScene.this.add( new WndTitledMessage( Icons.MASTERY.get(), "Mastery", text ) );
}
};
btnMastery.setPos(
avFrame.x + avFrame.innerRight() - btnMastery.width(),
avFrame.y + avFrame.innerBottom() - btnMastery.height() );
add( btnMastery );
unlock = new Group();
add( unlock );
if (!(huntressUnlocked = Badges.isUnlocked( Badges.Badge.BOSS_SLAIN_3 ))) {
BitmapTextMultiline text = PixelScene.createMultiline( TXT_UNLOCK, 5 );
text.maxWidth = (int)frame.innerWidth();
text.measure();
pos = frame.center().y - text.height() / 2;
for (BitmapText line : text.new LineSplitter().split()) {
line.measure();
line.hardlight( 0xFFFF00 );
line.x = PixelScene.align( frame.center().x - line.width() / 2 );
line.y = PixelScene.align( pos );
unlock.add( line );
pos += line.height();
}
}
curClass = null;
updateClass( HeroClass.values()[ShatteredPixelDungeon.lastClass()] );
fadeIn();
}
private void updateClass( HeroClass cl ) {
if (curClass == cl) {
return;
}
if (curClass != null) {
gems.get( curClass ).highlight( false );
}
gems.get( curClass = cl ).highlight( true );
className.text( Utils.capitalize( cl.title() ) );
className.measure();
className.x = align( frame.center().x - className.width() / 2 );
if (cl != HeroClass.HUNTRESS || huntressUnlocked) {
unlock.visible = false;
float buttonPos = frame.y + frame.innerBottom() - BUTTON_HEIGHT;
GamesInProgress.Info info = GamesInProgress.check( curClass );
if (info != null) {
btnLoad.visible = true;
btnLoad.secondary( Utils.format( TXT_DPTH_LVL, info.depth, info.level ) );
btnNewGame.visible = true;
btnNewGame.secondary( TXT_ERASE );
float w = (frame.innerWidth() - GAP) / 2;
btnLoad.setRect(
frame.x + frame.marginLeft(), buttonPos, w, BUTTON_HEIGHT );
btnNewGame.setRect(
btnLoad.right() + GAP, buttonPos, w, BUTTON_HEIGHT );
} else {
btnLoad.visible = false;
btnNewGame.visible = true;
btnNewGame.secondary( null );
btnNewGame.setRect(
frame.x + frame.marginLeft(), buttonPos, frame.innerWidth(), BUTTON_HEIGHT );
}
Badges.Badge badgeToCheck = null;
switch (curClass) {
case WARRIOR:
badgeToCheck = Badges.Badge.MASTERY_WARRIOR;
break;
case MAGE:
badgeToCheck = Badges.Badge.MASTERY_MAGE;
break;
case ROGUE:
badgeToCheck = Badges.Badge.MASTERY_ROGUE;
break;
case HUNTRESS:
badgeToCheck = Badges.Badge.MASTERY_HUNTRESS;
break;
}
btnMastery.active =
btnMastery.visible =
Badges.isUnlocked( badgeToCheck );
} else {
unlock.visible = true;
btnLoad.visible = false;
btnNewGame.visible = false;
btnMastery.active = btnMastery.visible = false;
}
avatar.selectClass( curClass );
}
private void startNewGame() {
Dungeon.hero = null;
InterlevelScene.mode = InterlevelScene.Mode.DESCEND;
if (ShatteredPixelDungeon.intro()) {
ShatteredPixelDungeon.intro(false);
Game.switchScene( IntroScene.class );
} else {
Game.switchScene( InterlevelScene.class );
}
}
@Override
protected void onBackPressed() {
Game.switchScene( TitleScene.class );
}
private static class Avatar extends Image {
private static final int WIDTH = 24;
private static final int HEIGHT = 32;
private static final int SCALE = 2;
private TextureFilm frames;
private float brightness = 0;
public Avatar() {
super( Assets.AVATARS );
frames = new TextureFilm( texture, WIDTH, HEIGHT );
selectClass( HeroClass.WARRIOR );
scale.set( SCALE );
origin.set( width() / 2, height() / 2 );
}
public void selectClass( HeroClass cl ) {
frame( frames.get( cl.ordinal() ) );
}
public void flash() {
brightness = 1f;
}
@Override
public void update() {
super.update();
if (brightness > 0) {
ra = ga = ba = brightness;
brightness -= Game.elapsed * 4;
if (brightness < 0) {
resetColor();
}
}
}
}
private class GemButton extends Button {
private NinePatch bg;
private Image icon;
private HeroClass cl;
public GemButton( HeroClass cl ) {
super();
this.cl = cl;
gems.put( cl, this );
icon.copy( Icons.get( cl ) );
setSize( 32, 32 );
highlight( false );
}
@Override
protected void createChildren() {
super.createChildren();
bg = Chrome.get( Chrome.Type.GEM );
add( bg );
icon = new Image();
add( icon );
}
@Override
protected void layout() {
super.layout();
bg.x = x;
bg.y = y;
bg.size( width, height );
icon.x = x + (width - icon.width) / 2;
icon.y = y + (height - icon.height) / 2;
}
@Override
protected void onTouchDown() {
Emitter emitter = (Emitter)recycle( Emitter.class );
emitter.revive();
emitter.pos( bg );
emitter.burst( Speck.factory( Speck.LIGHT ), 3 );
updateClass( cl );
avatar.flash();
Sample.INSTANCE.play( Assets.SND_CLICK, 1, 1, 1.2f );
}
public void highlight( boolean value ) {
if (value) {
bg.rm = 1.2f;
bg.gm = 1.2f;
bg.bm = 1.1f;
bg.am = 0.8f;
} else {
bg.rm = 1.0f;
bg.gm = 1.0f;
bg.bm = 1.0f;
bg.am = 0.6f;
}
}
}
private static class GameButton extends RedButton {
private static final int SECONDARY_COLOR = 0xCACFC2;
private BitmapText secondary;
public GameButton( String primary ) {
super( primary );
this.secondary.text( null );
}
@Override
protected void createChildren() {
super.createChildren();
secondary = createText( 6 );
secondary.hardlight( SECONDARY_COLOR );
add( secondary );
}
@Override
protected void layout() {
super.layout();
if (secondary.text().length() > 0) {
text.y = y + (height - text.height() - secondary.baseLine()) / 2;
secondary.x = align( x + (width - secondary.width()) / 2 );
secondary.y = align( text.y + text.height() );
} else {
text.y = y + (height - text.baseLine()) / 2;
}
}
public void secondary( String text ) {
secondary.text( text );
secondary.measure();
}
}
}
@@ -0,0 +1,363 @@
/*
* 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;
import java.nio.FloatBuffer;
import com.watabou.gltextures.Gradient;
import com.watabou.gltextures.SmartTexture;
import com.watabou.glwrap.Matrix;
import com.watabou.glwrap.Quad;
import com.watabou.input.Touchscreen.Touch;
import com.watabou.noosa.Camera;
import com.watabou.noosa.ColorBlock;
import com.watabou.noosa.Game;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.NoosaScript;
import com.watabou.noosa.TextureFilm;
import com.watabou.noosa.TouchArea;
import com.watabou.noosa.Visual;
import com.watabou.noosa.audio.Music;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.sprites.RatSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.RedButton;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
public class SurfaceScene extends PixelScene {
private static final int WIDTH = 80;
private static final int HEIGHT = 112;
private static final int NSTARS = 100;
private static final int NCLOUDS = 5;
private Camera viewport;
@Override
public void create() {
super.create();
Music.INSTANCE.play( Assets.HAPPY, true );
Music.INSTANCE.volume( 1f );
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
Archs archs = new Archs();
archs.reversed = true;
archs.setSize( w, h );
add( archs );
float vx = align( (w - WIDTH) / 2 );
float vy = align( (h - HEIGHT) / 2 );
Point s = Camera.main.cameraToScreen( vx, vy );
viewport = new Camera( s.x, s.y, WIDTH, HEIGHT, defaultZoom );
Camera.add( viewport );
Group window = new Group();
window.camera = viewport;
add( window );
boolean dayTime = !Dungeon.nightMode;
Sky sky = new Sky( dayTime );
sky.scale.set( WIDTH, HEIGHT );
window.add( sky );
if (!dayTime) {
for (int i=0; i < NSTARS; i++) {
float size = Random.Float();
ColorBlock star = new ColorBlock( size, size, 0xFFFFFFFF );
star.x = Random.Float( WIDTH ) - size / 2;
star.y = Random.Float( HEIGHT ) - size / 2;
star.am = size * (1 - star.y / HEIGHT);
window.add( star );
}
}
float range = HEIGHT * 2 / 3;
for (int i=0; i < NCLOUDS; i++) {
Cloud cloud = new Cloud( (NCLOUDS - 1 - i) * (range / NCLOUDS) + Random.Float( range / NCLOUDS ), dayTime );
window.add( cloud );
}
int nPatches = (int)(sky.width() / GrassPatch.WIDTH + 1);
for (int i=0; i < nPatches * 4; i++) {
GrassPatch patch = new GrassPatch( (i - 0.75f) * GrassPatch.WIDTH / 4, HEIGHT + 1, dayTime );
patch.brightness( dayTime ? 0.7f : 0.4f );
window.add( patch );
}
Avatar a = new Avatar( Dungeon.hero.heroClass );
// Removing semitransparent contour
a.am = 2; a.aa = -1;
a.x = PixelScene.align( (WIDTH - a.width) / 2 );
a.y = HEIGHT - a.height + 1;
window.add( a );
final Pet pet = new Pet();
pet.rm = pet.gm = pet.bm = 1.2f;
pet.x = WIDTH / 2 + 2;
pet.y = HEIGHT - pet.height;
window.add( pet );
if (dayTime) {
a.brightness( 1.2f );
pet.brightness( 1.2f );
}
window.add( new TouchArea( sky ) {
protected void onClick( Touch touch ) {
pet.jump();
};
} );
for (int i=0; i < nPatches; i++) {
GrassPatch patch = new GrassPatch( (i - 0.5f) * GrassPatch.WIDTH, HEIGHT, dayTime );
patch.brightness( dayTime ? 1.0f : 0.8f );
window.add( patch );
}
Image frame = new Image( Assets.SURFACE );
if (!dayTime) {
frame.hardlight( 0xDDEEFF );
}
frame.frame( 0, 0, 88, 125 );
frame.x = vx - 4;
frame.y = vy - 9;
add( frame );
RedButton gameOver = new RedButton( "Game Over" ) {
protected void onClick() {
Game.switchScene( TitleScene.class );
}
};
gameOver.setSize( WIDTH - 10, 20 );
gameOver.setPos( 5 + frame.x + 4, frame.y + frame.height + 4 );
add( gameOver );
Badges.validateHappyEnd();
fadeIn();
}
@Override
public void destroy() {
Badges.saveGlobal();
Camera.remove( viewport );
super.destroy();
}
@Override
protected void onBackPressed() {
}
private static class Sky extends Visual {
private static final int[] day = {0xFF4488FF, 0xFFCCEEFF};
private static final int[] night = {0xFF001155, 0xFF335980};
private SmartTexture texture;
private FloatBuffer verticesBuffer;
public Sky( boolean dayTime ) {
super( 0, 0, 1, 1 );
texture = new Gradient( dayTime ? day : night );
float[] vertices = new float[16];
verticesBuffer = Quad.create();
vertices[2] = 0.25f;
vertices[6] = 0.25f;
vertices[10] = 0.75f;
vertices[14] = 0.75f;
vertices[3] = 0;
vertices[7] = 1;
vertices[11] = 1;
vertices[15] = 0;
vertices[0] = 0;
vertices[1] = 0;
vertices[4] = 1;
vertices[5] = 0;
vertices[8] = 1;
vertices[9] = 1;
vertices[12] = 0;
vertices[13] = 1;
verticesBuffer.position( 0 );
verticesBuffer.put( vertices );
}
@Override
public void draw() {
super.draw();
NoosaScript script = NoosaScript.get();
texture.bind();
script.camera( camera() );
script.uModel.valueM4( matrix );
script.lighting(
rm, gm, bm, am,
ra, ga, ba, aa );
script.drawQuad( verticesBuffer );
}
}
private static class Cloud extends Image {
private static int lastIndex = -1;
public Cloud( float y, boolean dayTime ) {
super( Assets.SURFACE );
int index;
do {
index = Random.Int( 3 );
} while (index == lastIndex);
switch (index) {
case 0:
frame( 88, 0, 49, 20 );
break;
case 1:
frame( 88, 20, 49, 22 );
break;
case 2:
frame( 88, 42, 50, 18 );
break;
}
lastIndex = index;
this.y = y;
scale.set( 1 - y / HEIGHT );
x = Random.Float( WIDTH + width() ) - width();
speed.x = scale.x * (dayTime ? +8 : -8);
if (dayTime) {
tint( 0xCCEEFF, 1 - scale.y );
} else {
rm = gm = bm = +3.0f;
ra = ga = ba = -2.1f;
}
}
@Override
public void update() {
super.update();
if (speed.x > 0 && x > WIDTH) {
x = -width();
} else if (speed.x < 0 && x < -width()) {
x = WIDTH;
}
}
}
private static class Avatar extends Image {
private static final int WIDTH = 24;
private static final int HEIGHT = 32;
public Avatar( HeroClass cl ) {
super( Assets.AVATARS );
frame( new TextureFilm( texture, WIDTH, HEIGHT ).get( cl.ordinal() ) );
}
}
private static class Pet extends RatSprite {
public void jump() {
play( run );
}
@Override
public void onComplete( Animation anim ) {
if (anim == run) {
idle();
}
}
}
private static class GrassPatch extends Image {
public static final int WIDTH = 16;
public static final int HEIGHT = 14;
private float tx;
private float ty;
private double a = Random.Float( 5 );
private double angle;
private boolean forward;
public GrassPatch( float tx, float ty, boolean forward ) {
super( Assets.SURFACE );
frame( 88 + Random.Int( 4 ) * WIDTH, 60, WIDTH, HEIGHT );
this.tx = tx;
this.ty = ty;
this.forward = forward;
}
@Override
public void update() {
super.update();
a += Random.Float( Game.elapsed * 5 );
angle = (2 + Math.cos( a )) * (forward ? +0.2 : -0.2);
scale.y = (float)Math.cos( angle );
x = tx + (float)Math.tan( angle ) * width;
y = ty - scale.y * height;
}
@Override
protected void updateMatrix() {
super.updateMatrix();
Matrix.skewX( matrix, (float)(angle / Matrix.G2RAD) );
}
}
}
@@ -0,0 +1,176 @@
/*
* 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;
import com.watabou.noosa.BitmapText;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Image;
import com.watabou.noosa.audio.Music;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.ui.Button;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites;
import com.shatteredpixel.shatteredpixeldungeon.effects.Fireball;
import com.shatteredpixel.shatteredpixeldungeon.ui.Archs;
import com.shatteredpixel.shatteredpixeldungeon.ui.PrefsButton;
public class TitleScene extends PixelScene {
private static final String TXT_PLAY = "Play";
private static final String TXT_HIGHSCORES = "Rankings";
private static final String TXT_BADGES = "Badges";
private static final String TXT_ABOUT = "About";
@Override
public void create() {
super.create();
Music.INSTANCE.play( Assets.THEME, true );
Music.INSTANCE.volume( 1f );
uiCamera.visible = false;
int w = Camera.main.width;
int h = Camera.main.height;
float height = 180;
Archs archs = new Archs();
archs.setSize( w, h );
add( archs );
Image title = BannerSprites.get( BannerSprites.Type.PIXEL_DUNGEON );
add( title );
title.x = (w - title.width()) / 2;
title.y = (h - height) / 2;
placeTorch( title.x + 18, title.y + 20 );
placeTorch( title.x + title.width - 18, title.y + 20 );
DashboardItem btnBadges = new DashboardItem( TXT_BADGES, 3 ) {
@Override
protected void onClick() {
Game.switchScene( BadgesScene.class );
}
};
btnBadges.setPos( w / 2 - btnBadges.width(), (h + height) / 2 - DashboardItem.SIZE );
add( btnBadges );
DashboardItem btnAbout = new DashboardItem( TXT_ABOUT, 1 ) {
@Override
protected void onClick() {
Game.switchScene( AboutScene.class );
}
};
btnAbout.setPos( w / 2, (h + height) / 2 - DashboardItem.SIZE );
add( btnAbout );
DashboardItem btnPlay = new DashboardItem( TXT_PLAY, 0 ) {
@Override
protected void onClick() {
Game.switchScene( StartScene.class );
}
};
btnPlay.setPos( w / 2 - btnPlay.width(), btnAbout.top() - DashboardItem.SIZE );
add( btnPlay );
DashboardItem btnHighscores = new DashboardItem( TXT_HIGHSCORES, 2 ) {
@Override
protected void onClick() {
Game.switchScene( RankingsScene.class );
}
};
btnHighscores.setPos( w / 2, btnPlay.top() );
add( btnHighscores );
BitmapText version = new BitmapText( "v " + Game.version, font1x );
version.measure();
version.hardlight( 0x888888 );
version.x = w - version.width();
version.y = h - version.height();
add( version );
PrefsButton btnPrefs = new PrefsButton();
btnPrefs.setPos( w - btnPrefs.width() - 1, 1 );
add( btnPrefs );
fadeIn();
}
private void placeTorch( float x, float y ) {
Fireball fb = new Fireball();
fb.setPos( x, y );
add( fb );
}
private static class DashboardItem extends Button {
public static final float SIZE = 48;
private static final int IMAGE_SIZE = 32;
private Image image;
private BitmapText label;
public DashboardItem( String text, int index ) {
super();
image.frame( image.texture.uvRect( index * IMAGE_SIZE, 0, (index + 1) * IMAGE_SIZE, IMAGE_SIZE ) );
this.label.text( text );
this.label.measure();
setSize( SIZE, SIZE );
}
@Override
protected void createChildren() {
super.createChildren();
image = new Image( Assets.DASHBOARD );
add( image );
label = createText( 9 );
add( label );
}
@Override
protected void layout() {
super.layout();
image.x = align( x + (width - image.width()) / 2 );
image.y = align( y );
label.x = align( x + (width - label.width()) / 2 );
label.y = align( image.y + image.height() +2 );
}
@Override
protected void onTouchDown() {
image.brightness( 1.5f );
Sample.INSTANCE.play( Assets.SND_CLICK, 1, 1, 0.8f );
}
@Override
protected void onTouchUp() {
image.resetColor();
}
}
}