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 )){ if (Dungeon.hero.sprite != null && Dungeon.hero.sprite.overlapsPoint( p.x, p.y )){
PointF c = DungeonTilemap.tileCenterToWorld(Dungeon.hero.pos); PointF c = DungeonTilemap.tileCenterToWorld(Dungeon.hero.pos);
if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) { 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; return;
} }
} }
@@ -100,7 +100,7 @@ public class CellSelector extends ScrollArea {
if (mob.sprite != null && mob.sprite.overlapsPoint( p.x, p.y )){ if (mob.sprite != null && mob.sprite.overlapsPoint( p.x, p.y )){
PointF c = DungeonTilemap.tileCenterToWorld(mob.pos); PointF c = DungeonTilemap.tileCenterToWorld(mob.pos);
if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) { if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) {
select(mob.pos); select(mob.pos, event.button);
return; return;
} }
} }
@@ -111,7 +111,7 @@ public class CellSelector extends ScrollArea {
if (heap.sprite != null && heap.sprite.overlapsPoint( p.x, p.y)){ if (heap.sprite != null && heap.sprite.overlapsPoint( p.x, p.y)){
PointF c = DungeonTilemap.tileCenterToWorld(heap.pos); PointF c = DungeonTilemap.tileCenterToWorld(heap.pos);
if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) { if (Math.abs(p.x - c.x) <= 12 && Math.abs(p.y - c.y) <= 12) {
select(heap.pos); select(heap.pos, event.button);
return; return;
} }
} }
@@ -120,7 +120,7 @@ public class CellSelector extends ScrollArea {
select( ((DungeonTilemap)target).screenToTile( select( ((DungeonTilemap)target).screenToTile(
(int) event.current.x, (int) event.current.x,
(int) event.current.y, (int) event.current.y,
true ) ); true ), event.button );
} }
} }
@@ -142,11 +142,18 @@ public class CellSelector extends ScrollArea {
return value; return value;
} }
public void select( int cell ) { public void select( int cell, int button ) {
if (enabled && Dungeon.hero.ready && !GameScene.InterfaceBlockingHero() if (enabled && Dungeon.hero.ready && !GameScene.InterfaceBlockingHero()
&& listener != null && cell != -1) { && listener != null && cell != -1) {
listener.onSelect( cell ); switch (button){
default:
listener.onSelect( cell );
break;
case PointerEvent.RIGHT:
listener.onRightClick( cell );
break;
}
GameScene.ready(); GameScene.ready();
} else { } else {
@@ -285,7 +292,7 @@ public class CellSelector extends ScrollArea {
// this is to make it easier to move 1 or 2 steps without overshooting // this is to make it easier to move 1 or 2 steps without overshooting
CharSprite.setMoveInterval( CharSprite.DEFAULT_MOVE_INTERVAL + CharSprite.setMoveInterval( CharSprite.DEFAULT_MOVE_INTERVAL +
Math.max(0, 0.05f - heldTurns *0.025f)); Math.max(0, 0.05f - heldTurns *0.025f));
select(cell); select(cell, PointerEvent.LEFT);
return true; return true;
} else { } else {
@@ -342,8 +349,11 @@ public class CellSelector extends ScrollArea {
KeyEvent.removeKeyListener( keyListener ); KeyEvent.removeKeyListener( keyListener );
} }
public interface Listener { public static abstract class Listener {
void onSelect( Integer cell ); public abstract void onSelect( Integer cell );
String prompt();
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.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy; 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.hero.Talent;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DemonSpawner; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DemonSpawner;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; 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.MenuPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton; import com.shatteredpixel.shatteredpixeldungeon.ui.QuickSlotButton;
import com.shatteredpixel.shatteredpixeldungeon.ui.ResumeIndicator; import com.shatteredpixel.shatteredpixeldungeon.ui.ResumeIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.RightClickMenu;
import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane; import com.shatteredpixel.shatteredpixeldungeon.ui.StatusPane;
import com.shatteredpixel.shatteredpixeldungeon.ui.Tag; import com.shatteredpixel.shatteredpixeldungeon.ui.Tag;
import com.shatteredpixel.shatteredpixeldungeon.ui.TargetHealthIndicator; 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.WndResurrect;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory; import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory;
import com.watabou.glwrap.Blending; import com.watabou.glwrap.Blending;
import com.watabou.input.PointerEvent;
import com.watabou.noosa.Camera; import com.watabou.noosa.Camera;
import com.watabou.noosa.Game; import com.watabou.noosa.Game;
import com.watabou.noosa.Gizmo; import com.watabou.noosa.Gizmo;
import com.watabou.noosa.Group; import com.watabou.noosa.Group;
import com.watabou.noosa.Image;
import com.watabou.noosa.NoosaScript; import com.watabou.noosa.NoosaScript;
import com.watabou.noosa.NoosaScriptNoLighting; import com.watabou.noosa.NoosaScriptNoLighting;
import com.watabou.noosa.SkinnedBlock; import com.watabou.noosa.SkinnedBlock;
@@ -121,6 +125,7 @@ import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.DeviceCompat; import com.watabou.utils.DeviceCompat;
import com.watabou.utils.GameMath; import com.watabou.utils.GameMath;
import com.watabou.utils.Point; import com.watabou.utils.Point;
import com.watabou.utils.PointF;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import com.watabou.utils.RectF; import com.watabou.utils.RectF;
@@ -1194,7 +1199,7 @@ public class GameScene extends PixelScene {
} }
public static void handleCell( int cell ) { public static void handleCell( int cell ) {
cellSelector.select( cell ); cellSelector.select( cell, PointerEvent.LEFT );
} }
public static void selectCell( CellSelector.Listener listener ) { public static void selectCell( CellSelector.Listener listener ) {
@@ -1272,49 +1277,19 @@ public class GameScene extends PixelScene {
return; return;
} }
ArrayList<String> names = new ArrayList<>(); ArrayList<Object> objects = getObjectsAtCell(cell);
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() ));
}
if (objects.isEmpty()) { if (objects.isEmpty()) {
GameScene.show(new WndInfoCell(cell)); GameScene.show(new WndInfoCell(cell));
} else if (objects.size() == 1){ } else if (objects.size() == 1){
examineObject(objects.get(0)); examineObject(objects.get(0));
} else { } else {
String[] names = getObjectNames(objects).toArray(new String[0]);
GameScene.show(new WndOptions(Icons.get(Icons.INFO), GameScene.show(new WndOptions(Icons.get(Icons.INFO),
Messages.get(GameScene.class, "choose_examine"), Messages.get(GameScene.class, "choose_examine"),
Messages.get(GameScene.class, "multiple_examine"), Messages.get(GameScene.class, "multiple_examine"),
names.toArray(new String[names.size()])){ names){
@Override @Override
protected void onSelect(int index) { protected void onSelect(int index) {
examineObject(objects.get(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){ public static void examineObject(Object o){
if (o == Dungeon.hero){ if (o == Dungeon.hero){
GameScene.show( new WndHero() ); GameScene.show( new WndHero() );
@@ -1352,6 +1362,104 @@ public class GameScene extends PixelScene {
Dungeon.hero.next(); 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 @Override
public String prompt() { public String prompt() {
return null; return null;

View File

@@ -126,6 +126,11 @@ public class RightClickMenu extends Component {
height += 13*buttons.length; height += 13*buttons.length;
width = icon.width + 2 + titleText.width()+bg.marginVer(); 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)){ if (x + width > (camera.width + camera.scroll.x)){
x -= (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 float GAP = 2;
private static final int WIDTH = 120; private static final int WIDTH = 120;
public WndInfoCell( int cell ) { public static Image cellImage( int cell ){
super();
int tile = Dungeon.level.map[cell]; int tile = Dungeon.level.map[cell];
if (Dungeon.level.water[cell]) { if (Dungeon.level.water[cell]) {
tile = Terrain.WATER; tile = Terrain.WATER;
@@ -50,7 +47,6 @@ public class WndInfoCell extends Window {
tile = Terrain.CHASM; tile = Terrain.CHASM;
} }
CustomTilemap customTile = null;
Image customImage = null; Image customImage = null;
int x = cell % Dungeon.level.width(); int x = cell % Dungeon.level.width();
int y = 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) && if ((x >= i.tileX && x < i.tileX+i.tileW) &&
(y >= i.tileY && y < i.tileY+i.tileH)){ (y >= i.tileY && y < i.tileY+i.tileH)){
if ((customImage = i.image(x - i.tileX, y - i.tileY)) != null) { 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; x -= i.tileX;
y -= i.tileY; y -= i.tileY;
customTile = i; customTile = i;
@@ -70,35 +120,20 @@ public class WndInfoCell extends Window {
String desc = ""; String desc = "";
IconTitle titlebar = new IconTitle(); IconTitle titlebar = new IconTitle();
titlebar.icon(cellImage(cell));
titlebar.label(cellName(cell));
if (customTile != null){ 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); String customDesc = customTile.desc(x, y);
if (customDesc != null) { if (customDesc != null) {
desc += customDesc; desc += customDesc;
} else { } else {
desc += Dungeon.level.tileDesc(tile); desc += Dungeon.level.tileDesc(Dungeon.level.map[cell]);
} }
} else { } else {
if (tile == Terrain.WATER) { desc += Dungeon.level.tileDesc(Dungeon.level.map[cell]);
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);
} }
titlebar.setRect(0, 0, WIDTH, 0); titlebar.setRect(0, 0, WIDTH, 0);
add(titlebar); add(titlebar);