added dice, started adding notification implementation, added hover, highlight and select functionality for pieces

This commit is contained in:
Cedric Beck
2024-11-27 03:05:35 +01:00
parent 6528e5c2b6
commit 0b9fc90274
18 changed files with 49202 additions and 98 deletions

View File

@@ -1,7 +1,7 @@
package pp.mdga.client;
public enum Asset {
bigTent(0.8f),
bigTent,
cardStack,
cir,
heer,
@@ -29,7 +29,8 @@ public enum Asset {
tree_big("Models/tree_big/tree_big.obj", "Models/tree_big/tree_big_diff.png"),
turboCard,
swapCard,
shieldCard
shieldCard,
dice("Models/dice/dice.obj", "Models/dice/dice_diff.jpeg")
;
private final String modelPath;

View File

@@ -79,7 +79,7 @@ public void onAction(String name, boolean isPressed, float tpf) {
if(cardLayerSelect == null && boardSelect != null) {
//boardSelect
if(boardSelect instanceof PieceControl pieceControl){
pieceControl.setSelect();
if(pieceControl.isSelectable()) gameView.getBoardHandler().pieceSelect(pieceControl);
}
if(boardSelect instanceof NodeControl nodeControl){
// nodeControl.outline();

View File

@@ -8,7 +8,7 @@
import com.jme3.system.AppSettings;
import pp.mdga.client.view.*;
import pp.mdga.game.Color;
import pp.mdga.notification.PlayerInGameNotification;
import pp.mdga.notification.*;
import java.util.ArrayList;
import java.util.List;
@@ -70,9 +70,24 @@ public void simpleInitApp() {
test.add(UUID.randomUUID());
test.add(UUID.randomUUID());
List<UUID> test_1 = new ArrayList<>();
UUID player0_1 = UUID.randomUUID();
test_1.add(player0_1);
UUID player1_1 = UUID.randomUUID();
test_1.add(player1_1);
test_1.add(UUID.randomUUID());
test_1.add(UUID.randomUUID());
notificationSynchronizer.addTestNotification(new PlayerInGameNotification(Color.AIRFORCE, test, "Player 1"));
notificationSynchronizer.addTestNotification(new PlayerInGameNotification(Color.NAVY, test_1, "Player 2"));
notificationSynchronizer.addTestNotification(new MovePieceNotification(player0, 0, true));
notificationSynchronizer.addTestNotification(new MovePieceNotification(player0_1, 20, true));
notificationSynchronizer.addTestNotification(new MovePieceNotification(player0_1, 20, 21));
notificationSynchronizer.addTestNotification(new MovePieceNotification(player1, 0, true));
notificationSynchronizer.addTestNotification(new MovePieceNotification(player0, 0, 7));
// notificationSynchronizer.addTestNotification(new SelectableMoveNotification(new ArrayList<>(List.of(player0, player1)), new ArrayList<>(List.of(7,3)), new ArrayList<>(List.of(false, false))));
notificationSynchronizer.addTestNotification(new SwapPieceNotification(player0, player0_1));
// notificationSynchronizer.addTestNotification(new SelectableSwapNotification(new ArrayList<>(List.of(player0, player1)), new ArrayList<>(List.of(player0_1))));
}
@Override

View File

@@ -71,8 +71,8 @@ private void handleGame(Notification notification) {
if (notification instanceof AcquireCardNotification) {
// Handle AcquireCardNotification
} else if (notification instanceof ActivePlayerNotification) {
// Handle ActivePlayerNotification
} else if (notification instanceof ActivePlayerNotification n) {
gameView.getGuiHandler().setActivePlayer(n.getColor());
} else if (notification instanceof CeremonyNotification) {
app.enter(MdgaState.CEREMONY);
} else if (notification instanceof DiceNowNotification) {
@@ -85,9 +85,15 @@ private void handleGame(Notification notification) {
gameView.getBoardHandler().moveHomePiece(home.getPieceId(), home.getHomeIndex());
} else if (notification instanceof InterruptNotification) {
// Handle InterruptNotification
} else if (notification instanceof MovePieceNotification) {
MovePieceNotification n = (MovePieceNotification)notification;
//gameView.getBoardHandler().movePiece(n.get); //TODO
} else if (notification instanceof MovePieceNotification n) {
if(n.isMoveStart()) {
//StartMove
gameView.getBoardHandler().movePieceStart(n.getPiece(), n.getMoveIndex());
}
else {
//InfieldMove
gameView.getBoardHandler().movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex());
}
} else if (notification instanceof MoveThrowPieceNotification) {
MoveThrowPieceNotification n = (MoveThrowPieceNotification)notification;
//gameView.getBoardHandler().throwPiece(n.); //TODO
@@ -102,16 +108,12 @@ private void handleGame(Notification notification) {
// Handle PlayerInGameNotification
gameView.getBoardHandler().addPlayer(n.getColor(),n.getPiecesList());
gameView.getGuiHandler().addPlayer(n.getColor(),n.getName());
gameView.getBoardHandler().enableHover(n.getPiecesList().get(0));
gameView.getBoardHandler().highlight(n.getPiecesList().get(0), true);
} else if (notification instanceof ResumeNotification) {
// Handle ResumeNotification
} else if (notification instanceof RollDiceNotification) {
// Handle RollDiceNotification
} else if (notification instanceof SelectableCardsNotification) {
// Handle SelectableCardsNotification
} else if (notification instanceof SelectablePiecesNotification) {
// Handle SelectablePiecesNotification
} else if (notification instanceof ShieldActiveNotification) {
ShieldActiveNotification n = (ShieldActiveNotification)notification;
gameView.getBoardHandler().shieldPiece(n.getPieceId());
@@ -120,10 +122,14 @@ private void handleGame(Notification notification) {
gameView.getBoardHandler().suppressShield(n.getPieceId());
} else if (notification instanceof StartDialogNotification) {
app.enter(MdgaState.MAIN);
} else if (notification instanceof SwapPieceNotification) {
// Handle SwapPieceNotification
} else if (notification instanceof SwapPieceNotification n) {
gameView.getBoardHandler().swapPieces(n.getFirstPiece(), n.getSecondPiece());
} else if (notification instanceof WaitMoveNotification) {
// Handle WaitMoveNotification
} else if (notification instanceof SelectableMoveNotification n) {
gameView.getBoardHandler().outlineMove(n.getPieces(), n.getMoveIndexe(), n.getHomeMoves());
} else if (notification instanceof SelectableSwapNotification n) {
gameView.getBoardHandler().outlineSwap(n.getOwnPieces(), n.getEnemyPieces());
} else {
throw new RuntimeException("notification not expected: " + notification.toString());
}

View File

@@ -42,13 +42,19 @@ public class BoardHandler {
private boolean scheduleInit = false;
private boolean scheduleShutdown = false;
private List<PieceControl> selectableOwnPieces = new ArrayList<>();
private List<PieceControl> selectableEnemyPieces = new ArrayList<>();
private PieceControl selectedOwnPiece;
private PieceControl selectedEnemyPiece;
public BoardHandler(MdgaApp app, FilterPostProcessor fpp) {
if(app == null) throw new RuntimeException("app is null");
this.isInitialised = false;
this.app = app;
this.fpp = fpp;
selectedEnemyPiece = null;
selectedOwnPiece = null;
initMap();
}
@@ -153,7 +159,9 @@ private void addHomeNode(Map<Color, List<NodeControl>> map, Color color, AssetOn
private float getRotationMove(Vector3f prev, Vector3f next) {
Vector3f direction = next.subtract(prev).normalizeLocal();
//I had to reverse dir.y, because then it worked.
return (float) Math.toDegrees(Math.atan2(direction.x, -direction.y));
float newRot = (float) Math.toDegrees(Math.atan2(direction.x, -direction.y));
if(newRot < 0) newRot += 360;
return newRot;
}
private void movePiece_rek(UUID uuid, int curIndex, int moveIndex){
@@ -200,6 +208,7 @@ public void addPlayer(Color color, List<UUID> uuid) {
for (int i = 0; i < playerAssets.size(); i++){
AssetOnMap assetOnMap = playerAssets.get(i);
PieceControl pieceControl = displayAndControl(assetOnMap, new PieceControl(assetOnMap.rot(), app.getAssetManager(), app, fpp));
pieceControl.setRotation(assetOnMap.rot());
movePieceToNode(pieceControl, waitNodes.get(i));
pieces.put(uuid.get(i), pieceControl);
@@ -343,11 +352,117 @@ public void deOutline(UUID uuid){
}
public void outline(int index){
infield.get(index).outline();
// infield.get(index).outline();
outlineControls.add(infield.get(index));
}
//called when (dice) moveNum is received from server to display the movable pieces and corresponding moveNodes
public void outlineMove(List<UUID> pieces, List<Integer> moveIndexe, List<Boolean> homeMoves) {
if(pieces.size() != moveIndexe.size() || pieces.size() != homeMoves.size()) throw new RuntimeException("arrays are not the same size");
selectableEnemyPieces.clear();
selectableOwnPieces.clear();
selectedOwnPiece = null;
selectedEnemyPiece = null;
for (int i = 0; i < pieces.size(); i++) {
UUID uuid = pieces.get(i);
PieceControl pieceControl = this.pieces.get(uuid);
NodeControl nodeControl;
if (homeMoves.get(i)) {
Color color = pieceColor.get(uuid);
nodeControl = homeNodesMap.get(color).get(moveIndexe.get(i));
}
else {
nodeControl = infield.get(moveIndexe.get(i));
}
nodeControl.highlight();
pieceControl.highlight(false);
pieceControl.setHoverable(true);
pieceControl.setSelectable(true);
selectableOwnPieces.add(pieceControl);
}
}
//called when swap notification is received to highlight and select own/enemy pieces
public void outlineSwap(List<UUID> ownPieces, List<UUID> enemyPieces){
selectableEnemyPieces.clear();
selectableOwnPieces.clear();
selectedOwnPiece = null;
selectedEnemyPiece = null;
for(UUID uuid : ownPieces) {
PieceControl p = pieces.get(uuid);
p.highlight(false);
p.setHoverable(true);
p.setSelectable(true);
selectableOwnPieces.add(p);
}
for(UUID uuid : enemyPieces) {
PieceControl p = pieces.get(uuid);
p.highlight(true);
p.setHoverable(true);
p.setSelectable(true);
selectableEnemyPieces.add(p);
}
}
//called from inputSynchronizer when a piece is selectable
public void pieceSelect(PieceControl pieceSelected) {
boolean isSelected = pieceSelected.isSelected();
if(selectableOwnPieces.contains(pieceSelected)){
for(PieceControl p : selectableOwnPieces) {
p.unSelect();
}
if (!isSelected) {
pieceSelected.select();
selectedOwnPiece = pieceSelected;
}
else {
pieceSelected.unSelect();
selectedOwnPiece = null;
}
}
else if(selectableEnemyPieces.contains(pieceSelected)) {
for(PieceControl p : selectableEnemyPieces) {
p.unSelect();
}
if (!isSelected) {
pieceSelected.select();
selectedEnemyPiece = pieceSelected;
}
else {
pieceSelected.unSelect();
selectedEnemyPiece = null;
}
}
else throw new RuntimeException("pieceSelected is not in own/enemySelectablePieces");
}
//called when view is no longer needed to select pieces
public void clearSelectable(){
for(PieceControl p : selectableEnemyPieces) {
p.unSelect();
p.setSelectable(false);
}
for(PieceControl p : selectableOwnPieces) {
p.unSelect();
p.setSelectable(false);
}
selectableEnemyPieces.clear();
selectableOwnPieces.clear();
selectedEnemyPiece = null;
selectedOwnPiece = null;
}
public void deOutline(int index){
infield.get(index).deOutline();

View File

@@ -10,17 +10,18 @@
public class NodeControl extends OutlineControl {
private static final ColorRGBA OUTLINE_COLOR = ColorRGBA.White;
private static final ColorRGBA OUTLINE_HIGHLIGHT_COLOR = ColorRGBA.White;
private static final int OUTLINE_HIGHLIGHT_WIDTH = 6;
public NodeControl(MdgaApp app, FilterPostProcessor fpp) {
super(app, fpp);
}
public void outline(){
super.outline(OUTLINE_COLOR);
}
public Vector3f getLocation(){
return this.getSpatial().getLocalTranslation();
}
public void highlight() {
super.outline(OUTLINE_HIGHLIGHT_COLOR, OUTLINE_HIGHLIGHT_WIDTH);
}
}

View File

@@ -30,7 +30,8 @@ public class PieceControl extends OutlineControl {
private static final ColorRGBA OUTLINE_ENEMY_COLOR = ColorRGBA.Red;
private static final ColorRGBA OUTLINE_OWN_HOVER_COLOR = ColorRGBA.Yellow;
private static final ColorRGBA OUTLINE_ENEMY_HOVER_COLOR = ColorRGBA.Green;
private static final ColorRGBA OUTLINE_SELECT_COLOR = ColorRGBA.Blue;
private static final ColorRGBA OUTLINE_OWN_SELECT_COLOR = ColorRGBA.Cyan;
private static final ColorRGBA OUTLINE_ENEMY_SELECT_COLOR = ColorRGBA.Orange;
private static final int OUTLINE_HIGHLIGHT_WIDTH = 6;
private static final int OUTLINE_HOVER_WIDTH = 6;
private static final int OUTLINE_SELECT_WIDTH = 8;
@@ -59,17 +60,19 @@ public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app,
}
public float getRotation() {
return (float) Math.toDegrees(this.spatial.getLocalRotation().toAngleAxis(new Vector3f(0,0,1)));
return (float) Math.toDegrees(spatial.getLocalRotation().toAngleAxis(new Vector3f(0,0,1)));
}
public void setRotation(float rot){
if(rot < 0) rot =- 360;
Quaternion quaternion = new Quaternion();
quaternion.fromAngleAxis((float) Math.toRadians(rot), new Vector3f(0,0,1));
this.spatial.setLocalRotation(quaternion);
spatial.setLocalRotation(quaternion);
}
public Vector3f getLocation(){
return this.getSpatial().getLocalTranslation();
return spatial.getLocalTranslation();
}
@Override
@@ -80,12 +83,12 @@ protected void controlUpdate(float delta) {
}
public void setLocation(Vector3f loc){
this.getSpatial().setLocalTranslation(loc);
this.spatial.setLocalTranslation(loc);
}
@Override
public void setSpatial(Spatial spatial){
if(this.getSpatial() == null && spatial != null){
if(this.spatial == null && spatial != null){
super.setSpatial(spatial);
initSpatial();
}
@@ -97,8 +100,8 @@ public void setSpatial(Spatial spatial){
public void initSpatial(){
setRotation(this.initRotation);
Node oldParent = this.spatial.getParent();
this.parentNode.setName(this.spatial.getName() + " Parent");
Node oldParent = spatial.getParent();
this.parentNode.setName(spatial.getName() + " Parent");
oldParent.detachChild(this.getSpatial());
this.parentNode.attachChild(this.getSpatial());
oldParent.attachChild(this.parentNode);
@@ -133,11 +136,11 @@ public void suppressShield(){
}
public void setMaterial(Material mat){
this.spatial.setMaterial(mat);
spatial.setMaterial(mat);
}
public Material getMaterial(){
return ((Geometry) this.spatial).getMaterial();
return ((Geometry) getSpatial()).getMaterial();
}
@@ -166,20 +169,27 @@ public void hoverOff(){
else deOutline();
}
public void select(){
super.outline(OUTLINE_SELECT_COLOR, OUTLINE_SELECT_WIDTH);
public void unSelect(){
select = false;
if(highlight) highlight(enemy);
else deOutline();
}
public void setSelect(){
public void select(){
if(!selectable) return;
select = !select;
if(select) select();
select = true;
super.outline(enemy ? OUTLINE_ENEMY_SELECT_COLOR : OUTLINE_OWN_SELECT_COLOR, OUTLINE_SELECT_WIDTH);
}
public void setSelectable(boolean selectable){
this.selectable = selectable;
}
public boolean isSelected() { return select; }
public boolean isSelectable() {
return selectable;
}
public void setHoverable(boolean hoverable) {
this.hoverable = hoverable;

View File

@@ -44,7 +44,7 @@ public void initialize(AppStateManager stateManager, Application app ) {
ViewPort view = app.getRenderManager().createMainView("Under gui ViewPort", overlayCam);
view.setEnabled(true);
view.setClearFlags(false, true, false);
view.setClearFlags(true, true, true);
view.attachScene(root);
fpp.setFrameBufferFormat(Image.Format.RGBA8);
fpp.addFilter(new ComposeFilter(backTexture));
@@ -67,7 +67,7 @@ public void render(RenderManager rm) {
@Override
public void update( float tpf ) {
root.updateLogicalState(tpf);
if (init && !cardBuffer.isEmpty()) {
for(Spatial spatial : cardBuffer){
@@ -75,13 +75,14 @@ public void update( float tpf ) {
}
cardBuffer.clear();
}
root.updateLogicalState(tpf);
}
public void addCard(Spatial card){
public void addSpatial(Spatial card){
cardBuffer.add(card);
}
public void deleteCard(Spatial spatial){
public void deleteSpatial(Spatial spatial){
root.detachChild(spatial);
}

View File

@@ -0,0 +1,105 @@
package pp.mdga.client.gui;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import java.util.Random;
public class DiceControl extends AbstractControl {
private final Random random = new Random();
private Quaternion targetRotation; // Final rotation of the dice
private final Vector3f angularVelocity = new Vector3f(); // Rotational velocity (radians/sec)
private float deceleration = 0.5f; // Friction-like deceleration
private boolean isRolling = false;
private boolean slerp = false;
private float timeElapsed = 0.0f;
private float rollDuration = 0.0001f;
@Override
protected void controlUpdate(float tpf) {
if (isRolling) {
if(!slerp) {
// Apply rotational velocity to the dice
Quaternion currentRotation = spatial.getLocalRotation();
Quaternion deltaRotation = new Quaternion();
deltaRotation.fromAngles(
angularVelocity.x * tpf,
angularVelocity.y * tpf,
angularVelocity.z * tpf
);
spatial.setLocalRotation(currentRotation.mult(deltaRotation));
// Gradually reduce rotational velocity (simulate deceleration)
angularVelocity.subtractLocal(
angularVelocity.mult(deceleration * tpf)
);
// Stop rolling when angular velocity is close to zero
if (angularVelocity.lengthSquared() < 3f) {
slerp = true;
}
}
else {
timeElapsed += tpf * rollDuration;
if (timeElapsed > 1.0f) timeElapsed = 1.0f;
// Quaternion interpolated = new Quaternion();
// interpolated.slerp(spatial.getLocalRotation(), targetRotation, progress);
// spatial.setLocalRotation(interpolated);
Quaternion interpolated = spatial.getLocalRotation().clone();
interpolated.nlerp(targetRotation, lerp(timeElapsed));
spatial.setLocalRotation(interpolated);
// Stop rolling once duration is complete
if (timeElapsed >= 1.0f) {
isRolling = false;
slerp = false;
}
}
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// No custom rendering needed
}
public void rollDice(int diceNum) {
if (isRolling) return; // Prevent re-rolling during animation
// Set high initial rotational velocity
angularVelocity.set(
random.nextFloat() * 1000f + 200f, // X-axis speed
random.nextFloat() * 1000f + 200f, // Y-axis speed
random.nextFloat() * 1000f + 200f // Z-axis speed
);
// Set final target rotation for the diceNum
targetRotation = getRotationForDiceNum(diceNum);
isRolling = true;
}
private Quaternion getRotationForDiceNum(int diceNum) {
// Define specific rotations for each dice face (adjust based on your dice model)
return switch (diceNum) {
case 1 -> new Quaternion().fromAngleAxis((float) (1 * (Math.PI / 2)), Vector3f.UNIT_X); //
case 2 -> new Quaternion().fromAngleAxis((float) (1 * (Math.PI / 2)), Vector3f.UNIT_Y); //
case 3 -> new Quaternion().fromAngleAxis((float) (0 * (Math.PI / 2)), Vector3f.UNIT_X); //
case 4 -> new Quaternion().fromAngleAxis((float) (2 * (Math.PI / 2)), Vector3f.UNIT_Y); //
case 5 -> new Quaternion().fromAngleAxis((float) (3 * (Math.PI / 2)), Vector3f.UNIT_Y); //
case 6 -> new Quaternion().fromAngleAxis((float) (3 * (Math.PI / 2)), Vector3f.UNIT_X); //
default -> throw new IllegalArgumentException("Invalid dice number: " + diceNum);
};
}
public static float lerp(float t) {
return (float) Math.sqrt(1 - Math.pow(t - 1, 2));
}
}

View File

@@ -75,13 +75,32 @@ private Asset bonusToAsset(BonusCard card){
public void addCard(BonusCard card, UUID uuid) {
CardControl control = createCard(bonusToAsset(card), nextPos());
ownCardsMap.put(uuid, control);
cardLayer.addCard(control.getSpatial());
cardLayer.addSpatial(control.getSpatial());
}
public void showDice(){
DiceControl control = createDice();
cardLayer.addSpatial(control.getSpatial());
control.rollDice(1);
}
private DiceControl createDice() {
Spatial spatial = app.getAssetManager().loadModel(Asset.dice.getModelPath());
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
mat.setTexture("ColorMap", app.getAssetManager().loadTexture(Asset.dice.getDiffPath()));
spatial.setMaterial(mat);
spatial.setLocalScale(1f);
spatial.setLocalTranslation(new Vector3f(0,0,0));
spatial.rotate((float)Math.toRadians(90), (float)Math.toRadians(180), (float)Math.toRadians(180));
DiceControl control = new DiceControl();
spatial.addControl(control);
return control;
}
public void deleteCard(UUID uuid){
if(!ownCardsMap.containsKey(uuid)) throw new RuntimeException("uuid dont exist in ownCardsmap");
cardLayer.deleteCard(ownCardsMap.get(uuid).getSpatial());
cardLayer.deleteSpatial(ownCardsMap.get(uuid).getSpatial());
ownCardsMap.remove(uuid);
}
@@ -129,8 +148,6 @@ private void renderName(String name, float paddingTop, float paddingLeft, boolea
playerNameNode.attachChild(hudText);
}
public void setPlayers(List<String> names, List<Color> colors){
if(names.size() != colors.size()) throw new RuntimeException("names and colors are not the same size");
@@ -175,7 +192,7 @@ public void test(){
addCard(BonusCard.TURBO, UUID.randomUUID());
addCard(BonusCard.SWAP, UUID.randomUUID());
// ownCardsMap.get(uuid).outline();
showDice();
}
public Camera getCardLayerCamera() {
@@ -185,4 +202,6 @@ public Camera getCardLayerCamera() {
public CardLayer getCardLayer(){
return cardLayer;
}
}

View File

@@ -4,10 +4,10 @@ world 0,0 90
#tree_big 0,0 0
#Marine Pos
marine 4,-5 -90
marine 4,-4 -90
marine 5,-4 -90
marine 5,-5 -90
marine 4,-5 270
marine 4,-4 270
marine 5,-4 270
marine 5,-5 270
#Blue (Marine) wait Node
node_wait_blue 4,-5 0

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB