v0.6.2a: reworked key display, new max of 6 keys at once

system is also more flexible, more keys can be added later.
This commit is contained in:
Evan Debenham 2017-10-30 04:14:46 -04:00
parent f95adc7452
commit e9b8bc3490
7 changed files with 262 additions and 60 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

After

Width:  |  Height:  |  Size: 404 B

View File

@ -110,7 +110,6 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.AttackIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
import com.shatteredpixel.shatteredpixeldungeon.utils.BArray; import com.shatteredpixel.shatteredpixeldungeon.utils.BArray;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndAlchemy; import com.shatteredpixel.shatteredpixeldungeon.windows.WndAlchemy;
@ -1467,7 +1466,7 @@ public class Hero extends Char {
Notes.remove(new SkeletonKey(Dungeon.depth)); Notes.remove(new SkeletonKey(Dungeon.depth));
Level.set( doorCell, Terrain.UNLOCKED_EXIT ); Level.set( doorCell, Terrain.UNLOCKED_EXIT );
} }
StatusPane.needsKeyUpdate = true; GameScene.updateKeyDisplay();
Level.set( doorCell, door == Terrain.LOCKED_DOOR ? Terrain.DOOR : Terrain.UNLOCKED_EXIT ); Level.set( doorCell, door == Terrain.LOCKED_DOOR ? Terrain.DOOR : Terrain.UNLOCKED_EXIT );
GameScene.updateMap( doorCell ); GameScene.updateMap( doorCell );
@ -1482,7 +1481,7 @@ public class Hero extends Char {
} else if (heap.type == Type.CRYSTAL_CHEST){ } else if (heap.type == Type.CRYSTAL_CHEST){
Notes.remove(new CrystalKey(Dungeon.depth)); Notes.remove(new CrystalKey(Dungeon.depth));
} }
StatusPane.needsKeyUpdate = true; GameScene.updateKeyDisplay();
heap.open( this ); heap.open( this );
} }
curAction = null; curAction = null;

View File

@ -26,7 +26,6 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes; import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndJournal; import com.shatteredpixel.shatteredpixeldungeon.windows.WndJournal;
import com.watabou.noosa.audio.Sample; import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
@ -54,7 +53,7 @@ public abstract class Key extends Item {
Notes.add(this); Notes.add(this);
Sample.INSTANCE.play( Assets.SND_ITEM ); Sample.INSTANCE.play( Assets.SND_ITEM );
hero.spendAndNext( TIME_TO_PICK_UP ); hero.spendAndNext( TIME_TO_PICK_UP );
StatusPane.needsKeyUpdate = true; GameScene.updateKeyDisplay();
return true; return true;
} }

View File

@ -746,6 +746,10 @@ public class GameScene extends PixelScene {
public static void flashJournal(){ public static void flashJournal(){
if (scene != null) scene.pane.flash(); if (scene != null) scene.pane.flash();
} }
public static void updateKeyDisplay(){
if (scene != null) scene.pane.updateKeys();
}
public static void resetMap() { public static void resetMap() {
if (scene != null) { if (scene != null) {

View File

@ -0,0 +1,217 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2017 Evan Debenham
*
* 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.ui;
import android.graphics.RectF;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.CrystalKey;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.watabou.gltextures.SmartTexture;
import com.watabou.gltextures.TextureCache;
import com.watabou.glwrap.Quad;
import com.watabou.glwrap.Vertexbuffer;
import com.watabou.noosa.NoosaScript;
import com.watabou.noosa.Visual;
import java.nio.FloatBuffer;
import java.util.HashMap;
public class KeyDisplay extends Visual {
private float[] vertices = new float[16];
private FloatBuffer quads;
private Vertexbuffer buffer;
private SmartTexture tx = TextureCache.get(Assets.MENU);
private boolean dirty = true;
private int[] keys;
//mapping of key types to slots in the array, 0 is reserved for black (missed) keys
//this also determines the order these keys will appear (lower first)
//and the order they will be truncated if there is no space (higher first, larger counts first)
private static final HashMap<Class<? extends Key>, Integer> keyMap = new HashMap<>();
static {
keyMap.put(SkeletonKey.class, 1);
keyMap.put(CrystalKey.class, 2);
keyMap.put(GoldenKey.class, 3);
keyMap.put(IronKey.class, 4);
}
private int totalKeys = 0;
public KeyDisplay() {
super(0, 0, 0, 0);
}
public void updateKeys(){
keys = new int[keyMap.size()+1];
for (Notes.KeyRecord rec : Notes.getRecords(Notes.KeyRecord.class)){
if (rec.depth() < Dungeon.depth){
//only ever 1 black key
keys[0] = 1;
} else if (rec.depth() == Dungeon.depth){
keys[keyMap.get(rec.type())] += rec.quantity();
}
}
totalKeys = 0;
for (int k : keys){
totalKeys += k;
}
dirty = true;
}
public int keyCount(){
return totalKeys;
}
@Override
public void draw() {
super.draw();
if (dirty){
updateVertices();
quads.limit(quads.position());
if (buffer == null)
buffer = new Vertexbuffer(quads);
else
buffer.updateVertices(quads);
}
NoosaScript script = NoosaScript.get();
tx.bind();
script.camera( camera() );
script.uModel.valueM4( matrix );
script.lighting(
rm, gm, bm, am,
ra, ga, ba, aa );
script.drawQuadSet( buffer, totalKeys, 0 );
}
private void updateVertices(){
//assumes shorter key sprite
int maxRows = (int)(height +1) / 5;
//1 pixel of padding between each key
int maxPerRow = (int)(width + 1) / 4;
int maxKeys = maxPerRow * maxRows;
while (totalKeys > maxKeys){
Class<? extends Key> mostType = null;
int mostNum = 0;
for (Class<?extends Key> k : keyMap.keySet()){
if (keys[keyMap.get(k)] >= mostNum){
mostType = k;
mostNum = keys[keyMap.get(k)];
}
}
keys[keyMap.get(mostType)]--;
totalKeys--;
}
int rows = (int)Math.ceil(totalKeys / (float)maxPerRow);
boolean shortKeys = (rows * 8) > height;
float left;
if (totalKeys > maxPerRow){
left = 0;
} else {
left = (width + 1 - (totalKeys*4))/2;
}
float top = (height + 1 - (rows * (shortKeys ? 5 : 8)))/2;
quads = Quad.createSet(totalKeys);
for (int i = 0; i < totalKeys; i++){
int keyIdx = 0;
if (i == 0 && keys[0] > 0){
//black key
keyIdx = 0;
} else {
for (int j = 1; j < keys.length; j++){
if (keys[j] > 0){
keys[j]--;
keyIdx = j;
break;
}
}
}
//texture coordinates
RectF r = tx.uvRect(43 + 3*keyIdx, shortKeys ? 8 : 0,
46 + 3*keyIdx, shortKeys ? 12 : 7);
vertices[2] = r.left;
vertices[3] = r.top;
vertices[6] = r.right;
vertices[7] = r.top;
vertices[10] = r.right;
vertices[11] = r.bottom;
vertices[14] = r.left;
vertices[15] = r.bottom;
//screen coordinates
vertices[0] = left;
vertices[1] = top;
vertices[4] = left + 3;
vertices[5] = top;
vertices[8] = left + 3;
vertices[9] = top + (shortKeys ? 4 : 7);
vertices[12] = left;
vertices[13] = top + (shortKeys ? 4 : 7);
quads.put(vertices);
//move to the right for more keys, drop down if the row is done
left += 4;
if (left + 3 > width){
left = 0;
top += (shortKeys ? 5 : 8);
}
}
dirty = false;
}
}

View File

@ -27,8 +27,6 @@ import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics; import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
@ -224,21 +222,23 @@ public class StatusPane extends Component {
public void pickup( Item item, int cell) { public void pickup( Item item, int cell) {
pickedUp.reset( item, pickedUp.reset( item,
cell, cell,
btnJournal.icon.x + btnJournal.icon.width()/2f, btnJournal.journalIcon.x + btnJournal.journalIcon.width()/2f,
btnJournal.icon.y + btnJournal.icon.height()/2f); btnJournal.journalIcon.y + btnJournal.journalIcon.height()/2f);
} }
public void flash(){ public void flash(){
btnJournal.flashing = true; btnJournal.flashing = true;
} }
public static boolean needsKeyUpdate = false; public void updateKeys(){
btnJournal.updateKeyDisplay();
}
private static class JournalButton extends Button { private static class JournalButton extends Button {
private Image bg; private Image bg;
//used to display key state to the player private Image journalIcon;
private Image icon; private KeyDisplay keyIcon;
private boolean flashing; private boolean flashing;
@ -255,10 +255,13 @@ public class StatusPane extends Component {
bg = new Image( Assets.MENU, 2, 2, 13, 11 ); bg = new Image( Assets.MENU, 2, 2, 13, 11 );
add( bg ); add( bg );
icon = new Image( Assets.MENU, 31, 0, 11, 7); journalIcon = new Image( Assets.MENU, 31, 0, 11, 7);
add( icon ); add( journalIcon );
needsKeyUpdate = true;
keyIcon = new KeyDisplay();
add(keyIcon);
updateKeyDisplay();
} }
@Override @Override
@ -267,10 +270,16 @@ public class StatusPane extends Component {
bg.x = x + 13; bg.x = x + 13;
bg.y = y + 2; bg.y = y + 2;
icon.x = bg.x + (bg.width() - icon.width())/2f; journalIcon.x = bg.x + (bg.width() - journalIcon.width())/2f;
icon.y = bg.y + (bg.height() - icon.height())/2f; journalIcon.y = bg.y + (bg.height() - journalIcon.height())/2f;
PixelScene.align(icon); PixelScene.align(journalIcon);
keyIcon.x = bg.x + 1;
keyIcon.y = bg.y + 1;
keyIcon.width = bg.width - 2;
keyIcon.height = bg.height - 2;
PixelScene.align(keyIcon);
} }
private float time; private float time;
@ -278,11 +287,10 @@ public class StatusPane extends Component {
@Override @Override
public void update() { public void update() {
super.update(); super.update();
if (needsKeyUpdate)
updateKeyDisplay();
if (flashing){ if (flashing){
icon.am = (float)Math.abs(Math.cos( 3 * (time += Game.elapsed) )); journalIcon.am = (float)Math.abs(Math.cos( 3 * (time += Game.elapsed) ));
keyIcon.am = journalIcon.am;
if (time >= 0.333f*Math.PI) { if (time >= 0.333f*Math.PI) {
time = 0; time = 0;
} }
@ -290,54 +298,29 @@ public class StatusPane extends Component {
} }
public void updateKeyDisplay() { public void updateKeyDisplay() {
needsKeyUpdate = false; keyIcon.updateKeys();
keyIcon.visible = keyIcon.keyCount() > 0;
boolean blackKey = false; journalIcon.visible = !keyIcon.visible;
boolean specialKey = false; if (keyIcon.keyCount() > 0) {
int ironKeys = 0; bg.brightness(.8f - (Math.min(6, keyIcon.keyCount()) / 20f));
for (Notes.KeyRecord rec : Notes.getRecords(Notes.KeyRecord.class)){
if (rec.depth() < Dungeon.depth){
blackKey = true;
} else if (rec.depth() == Dungeon.depth){
if (rec.type().equals(IronKey.class)) {
ironKeys += rec.quantity();
} else {
specialKey = true;
}
}
}
if (blackKey || specialKey || ironKeys > 0){
int left = 46, top = 0, width = 0, height = 7;
if (blackKey){
left = 43;
width += 3;
}
if (specialKey){
top = 8;
width += 3;
}
width += ironKeys*3;
width = Math.min( width, 9);
icon.frame(left, top, width, height);
} else { } else {
icon.frame(31, 0, 11, 7); bg.resetColor();
} }
layout();
} }
@Override @Override
protected void onTouchDown() { protected void onTouchDown() {
bg.brightness( 1.5f ); bg.brightness( 1.5f );
icon.brightness( 1.5f );
Sample.INSTANCE.play( Assets.SND_CLICK ); Sample.INSTANCE.play( Assets.SND_CLICK );
} }
@Override @Override
protected void onTouchUp() { protected void onTouchUp() {
bg.resetColor(); if (keyIcon.keyCount() > 0) {
icon.resetColor(); bg.brightness(.8f - (Math.min(6, keyIcon.keyCount()) / 20f));
} else {
bg.resetColor();
}
} }
@Override @Override