v1.2.0: added right click menu functionality to the game environment

This commit is contained in:
Evan Debenham
2022-02-17 11:47:42 -05:00
parent aa43adf833
commit f10b112161
4 changed files with 230 additions and 72 deletions

View File

@@ -90,7 +90,7 @@ public class CellSelector extends ScrollArea {
if (Dungeon.hero.sprite != null && Dungeon.hero.sprite.overlapsPoint( p.x, p.y )){
PointF c = DungeonTilemap.tileCenterToWorld(Dungeon.hero.pos);
if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) {
select(Dungeon.hero.pos);
select(Dungeon.hero.pos, event.button);
return;
}
}
@@ -100,7 +100,7 @@ public class CellSelector extends ScrollArea {
if (mob.sprite != null && mob.sprite.overlapsPoint( p.x, p.y )){
PointF c = DungeonTilemap.tileCenterToWorld(mob.pos);
if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) {
select(mob.pos);
select(mob.pos, event.button);
return;
}
}
@@ -111,7 +111,7 @@ public class CellSelector extends ScrollArea {
if (heap.sprite != null && heap.sprite.overlapsPoint( p.x, p.y)){
PointF c = DungeonTilemap.tileCenterToWorld(heap.pos);
if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) {
select(heap.pos);
select(heap.pos, event.button);
return;
}
}
@@ -120,7 +120,7 @@ public class CellSelector extends ScrollArea {
select( ((DungeonTilemap)target).screenToTile(
(int) event.current.x,
(int) event.current.y,
true ) );
true ), event.button );
}
}
@@ -142,11 +142,18 @@ public class CellSelector extends ScrollArea {
return value;
}
public void select( int cell ) {
public void select( int cell, int button ) {
if (enabled && Dungeon.hero.ready && !GameScene.InterfaceBlockingHero()
&& listener != null && cell != -1) {
listener.onSelect( cell );
switch (button){
default:
listener.onSelect( cell );
break;
case PointerEvent.RIGHT:
listener.onRightClick( cell );
break;
}
GameScene.ready();
} else {
@@ -285,7 +292,7 @@ public class CellSelector extends ScrollArea {
// this is to make it easier to move 1 or 2 steps without overshooting
CharSprite.setMoveInterval( CharSprite.DEFAULT_MOVE_INTERVAL +
Math.max(0, 0.05f - heldTurns *0.025f));
select(cell);
select(cell, PointerEvent.LEFT);
return true;
} else {
@@ -342,8 +349,11 @@ public class CellSelector extends ScrollArea {
KeyEvent.removeKeyListener( keyListener );
}
public interface Listener {
void onSelect( Integer cell );
String prompt();
public static abstract class Listener {
public abstract void onSelect( Integer cell );
public void onRightClick( Integer cell ){} //do nothing by default
public abstract String prompt();
}
}

View File

@@ -33,6 +33,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DemonSpawner;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
@@ -87,6 +88,7 @@ import com.shatteredpixel.shatteredpixeldungeon.ui.LootIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.MenuPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.ResumeIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.RightClickMenu;
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.Tag;
import com.shatteredpixel.shatteredpixeldungeon.ui.TargetHealthIndicator;
@@ -107,10 +109,12 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndResurrect;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory;
import com.watabou.glwrap.Blending;
import com.watabou.input.PointerEvent;
import com.watabou.noosa.Camera;
import com.watabou.noosa.Game;
import com.watabou.noosa.Gizmo;
import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.NoosaScript;
import com.watabou.noosa.NoosaScriptNoLighting;
import com.watabou.noosa.SkinnedBlock;
@@ -121,6 +125,7 @@ import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.DeviceCompat;
import com.watabou.utils.GameMath;
import com.watabou.utils.Point;
import com.watabou.utils.PointF;
import com.watabou.utils.Random;
import com.watabou.utils.RectF;
@@ -1194,7 +1199,7 @@ public class GameScene extends PixelScene {
}
public static void handleCell( int cell ) {
cellSelector.select( cell );
cellSelector.select( cell, PointerEvent.LEFT );
}
public static void selectCell( CellSelector.Listener listener ) {
@@ -1272,49 +1277,19 @@ public class GameScene extends PixelScene {
return;
}
ArrayList<String> names = new ArrayList<>();
final ArrayList<Object> objects = new ArrayList<>();
if (cell == Dungeon.hero.pos) {
objects.add(Dungeon.hero);
names.add(Dungeon.hero.className().toUpperCase(Locale.ENGLISH));
} else {
if (Dungeon.level.heroFOV[cell]) {
Mob mob = (Mob) Actor.findChar(cell);
if (mob != null) {
objects.add(mob);
names.add(Messages.titleCase( mob.name() ));
}
}
}
Heap heap = Dungeon.level.heaps.get(cell);
if (heap != null && heap.seen) {
objects.add(heap);
names.add(Messages.titleCase( heap.toString() ));
}
Plant plant = Dungeon.level.plants.get( cell );
if (plant != null) {
objects.add(plant);
names.add(Messages.titleCase( plant.plantName ));
}
Trap trap = Dungeon.level.traps.get( cell );
if (trap != null && trap.visible) {
objects.add(trap);
names.add(Messages.titleCase( trap.name() ));
}
ArrayList<Object> objects = getObjectsAtCell(cell);
if (objects.isEmpty()) {
GameScene.show(new WndInfoCell(cell));
} else if (objects.size() == 1){
examineObject(objects.get(0));
} else {
String[] names = getObjectNames(objects).toArray(new String[0]);
GameScene.show(new WndOptions(Icons.get(Icons.INFO),
Messages.get(GameScene.class, "choose_examine"),
Messages.get(GameScene.class, "multiple_examine"),
names.toArray(new String[names.size()])){
names){
@Override
protected void onSelect(int index) {
examineObject(objects.get(index));
@@ -1324,6 +1299,41 @@ public class GameScene extends PixelScene {
}
}
private static ArrayList<Object> getObjectsAtCell( int cell ){
ArrayList<Object> objects = new ArrayList<>();
if (cell == Dungeon.hero.pos) {
objects.add(Dungeon.hero);
} else if (Dungeon.level.heroFOV[cell]) {
Mob mob = (Mob) Actor.findChar(cell);
if (mob != null) objects.add(mob);
}
Heap heap = Dungeon.level.heaps.get(cell);
if (heap != null && heap.seen) objects.add(heap);
Plant plant = Dungeon.level.plants.get( cell );
if (plant != null) objects.add(plant);
Trap trap = Dungeon.level.traps.get( cell );
if (trap != null && trap.visible) objects.add(trap);
return objects;
}
private static ArrayList<String> getObjectNames( ArrayList<Object> objects ){
ArrayList<String> names = new ArrayList<>();
for (Object obj : objects){
if (obj instanceof Hero) names.add(((Hero) obj).className().toUpperCase(Locale.ENGLISH));
else if (obj instanceof Mob) names.add(Messages.titleCase( ((Mob)obj).name() ));
else if (obj instanceof Heap) names.add(Messages.titleCase( ((Heap)obj).toString() ));
else if (obj instanceof Plant) names.add(Messages.titleCase( ((Plant) obj).plantName ));
else if (obj instanceof Trap) names.add(Messages.titleCase( ((Trap) obj).name() ));
}
return names;
}
public static void examineObject(Object o){
if (o == Dungeon.hero){
GameScene.show( new WndHero() );
@@ -1352,6 +1362,104 @@ public class GameScene extends PixelScene {
Dungeon.hero.next();
}
}
@Override
public void onRightClick(Integer cell) {
if (cell == null
|| cell < 0
|| cell > Dungeon.level.length()
|| (!Dungeon.level.visited[cell] && !Dungeon.level.mapped[cell])) {
return;
}
ArrayList<Object> objects = getObjectsAtCell(cell);
ArrayList<String> textLines = getObjectNames(objects);
//determine title and image
String title = null;
Image image = null;
if (objects.isEmpty()) {
title = WndInfoCell.cellName(cell);
image = WndInfoCell.cellImage(cell);
} else if (objects.size() > 1){
title = "Multiple Objects";
image = Icons.get(Icons.INFO);
} else if (objects.get(0) instanceof Mob) {
title = textLines.remove(0);
image = new Image(((Mob) objects.get(0)).sprite);
} else if (objects.get(0) instanceof Heap) {
title = textLines.remove(0);
image = new ItemSprite((Heap) objects.get(0));
} else if (objects.get(0) instanceof Plant) {
title = textLines.remove(0);
image = TerrainFeaturesTilemap.tile(cell, Dungeon.level.map[cell]);
} else if (objects.get(0) instanceof Trap) {
title = textLines.remove(0);
image = TerrainFeaturesTilemap.tile(cell, Dungeon.level.map[cell]);
}
//determine first text line
if (objects.isEmpty()) {
textLines.add(0, "Go Here");
} else if (objects.get(0) instanceof Mob) {
if (((Mob) objects.get(0)).alignment != Char.Alignment.ENEMY) {
textLines.add(0, "Interact");
} else {
textLines.add(0, "Attack");
}
} else if (objects.get(0) instanceof Heap) {
switch (((Heap) objects.get(0)).type) {
case HEAP:
textLines.add(0, "Pick Up");
break;
case FOR_SALE:
textLines.add(0, "Purchase");
break;
default:
textLines.add(0, "Interact");
break;
}
} else if (objects.get(0) instanceof Plant) {
textLines.add(0, "Trample");
} else if (objects.get(0) instanceof Trap) {
textLines.add(0, "Interact");
}
//final text formatting
if (objects.size() > 1){
textLines.add(0, "_" + textLines.remove(0) + ":_ " + textLines.get(0));
for (int i = 1; i < textLines.size(); i++){
textLines.add(i, "_Examine:_ " + textLines.remove(i));
}
} else {
textLines.add(0, "_" + textLines.remove(0) + "_");
textLines.add(1, "_Examine_");
}
RightClickMenu menu = new RightClickMenu(image,
title,
textLines.toArray(new String[0])){
@Override
public void onSelect(int index) {
if (index == 0){
handleCell(cell);
} else {
if (objects.size() == 0){
GameScene.show(new WndInfoCell(cell));
} else {
examineObject(objects.get(index-1));
}
}
}
};
scene.addToFront(menu);
menu.camera = PixelScene.uiCamera;
PointF mousePos = PointerEvent.currentHoverPos();
mousePos = menu.camera.screenToCamera((int)mousePos.x, (int)mousePos.y);
menu.setPos(mousePos.x-3, mousePos.y-3);
}
@Override
public String prompt() {
return null;

View File

@@ -126,6 +126,11 @@ public class RightClickMenu extends Component {
height += 13*buttons.length;
width = icon.width + 2 + titleText.width()+bg.marginVer();
for (RedButton button : buttons){
if (width < button.reqWidth()+bg.marginHor()){
width = button.reqWidth()+bg.marginHor();
}
}
if (x + width > (camera.width + camera.scroll.x)){
x -= (x + width - (camera.width + camera.scroll.x));

View File

@@ -38,11 +38,8 @@ public class WndInfoCell extends Window {
private static final float GAP = 2;
private static final int WIDTH = 120;
public WndInfoCell( int cell ) {
super();
public static Image cellImage( int cell ){
int tile = Dungeon.level.map[cell];
if (Dungeon.level.water[cell]) {
tile = Terrain.WATER;
@@ -50,7 +47,6 @@ public class WndInfoCell extends Window {
tile = Terrain.CHASM;
}
CustomTilemap customTile = null;
Image customImage = null;
int x = cell % Dungeon.level.width();
int y = cell / Dungeon.level.width();
@@ -58,6 +54,60 @@ public class WndInfoCell extends Window {
if ((x >= i.tileX && x < i.tileX+i.tileW) &&
(y >= i.tileY && y < i.tileY+i.tileH)){
if ((customImage = i.image(x - i.tileX, y - i.tileY)) != null) {
break;
}
}
}
if (customImage != null){
return customImage;
} else {
if (tile == Terrain.WATER) {
Image water = new Image(Dungeon.level.waterTex());
water.frame(0, 0, DungeonTilemap.SIZE, DungeonTilemap.SIZE);
return water;
} else {
return DungeonTerrainTilemap.tile(cell, tile);
}
}
}
public static String cellName( int cell ){
CustomTilemap customTile = null;
int x = cell % Dungeon.level.width();
int y = cell / Dungeon.level.width();
for (CustomTilemap i : Dungeon.level.customTiles){
if ((x >= i.tileX && x < i.tileX+i.tileW) &&
(y >= i.tileY && y < i.tileY+i.tileH)){
if (i.image(x - i.tileX, y - i.tileY) != null) {
x -= i.tileX;
y -= i.tileY;
customTile = i;
break;
}
}
}
if (customTile != null && customTile.name(x, y) != null){
return customTile.name(x, y);
} else {
return Dungeon.level.tileName(Dungeon.level.map[cell]);
}
}
public WndInfoCell( int cell ) {
super();
CustomTilemap customTile = null;
int x = cell % Dungeon.level.width();
int y = cell / Dungeon.level.width();
for (CustomTilemap i : Dungeon.level.customTiles){
if ((x >= i.tileX && x < i.tileX+i.tileW) &&
(y >= i.tileY && y < i.tileY+i.tileH)){
if (i.image(x - i.tileX, y - i.tileY) != null) {
x -= i.tileX;
y -= i.tileY;
customTile = i;
@@ -70,35 +120,20 @@ public class WndInfoCell extends Window {
String desc = "";
IconTitle titlebar = new IconTitle();
titlebar.icon(cellImage(cell));
titlebar.label(cellName(cell));
if (customTile != null){
titlebar.icon(customImage);
String customName = customTile.name(x, y);
if (customName != null) {
titlebar.label(customName);
} else {
titlebar.label(Dungeon.level.tileName(tile));
}
String customDesc = customTile.desc(x, y);
if (customDesc != null) {
desc += customDesc;
} else {
desc += Dungeon.level.tileDesc(tile);
desc += Dungeon.level.tileDesc(Dungeon.level.map[cell]);
}
} else {
if (tile == Terrain.WATER) {
Image water = new Image(Dungeon.level.waterTex());
water.frame(0, 0, DungeonTilemap.SIZE, DungeonTilemap.SIZE);
titlebar.icon(water);
} else {
titlebar.icon(DungeonTerrainTilemap.tile( cell, tile ));
}
titlebar.label(Dungeon.level.tileName(tile));
desc += Dungeon.level.tileDesc(tile);
desc += Dungeon.level.tileDesc(Dungeon.level.map[cell]);
}
titlebar.setRect(0, 0, WIDTH, 0);
add(titlebar);