added "end card"

main
Jonah Bauer 3 years ago
parent c41caeef59
commit eef8f4ac40

@ -1,23 +1,19 @@
package eu.jonahbauer.wizard.client.libgdx.actions.overlay;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.scenes.scene2d.*;
import com.badlogic.gdx.scenes.scene2d.Action;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.ui.Container;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.I18NBundle;
import eu.jonahbauer.wizard.client.libgdx.util.AnimationTimings;
import eu.jonahbauer.wizard.client.libgdx.UiskinAtlas;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.screens.GameScreen;
import lombok.AccessLevel;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.run;
public abstract class Overlay extends Action {
protected final GameScreen screen;

@ -2,6 +2,8 @@ package eu.jonahbauer.wizard.client.libgdx.actions.overlay;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.actors.PadOfTruth;
import eu.jonahbauer.wizard.client.libgdx.screens.GameScreen;
@ -16,17 +18,38 @@ import static eu.jonahbauer.wizard.client.libgdx.screens.GameScreen.PAD_OF_TRUTH
import static eu.jonahbauer.wizard.client.libgdx.util.AnimationTimings.OVERLAY_SHARED_ELEMENT;
public class ScoreOverlay extends Overlay {
private final boolean finalScores;
private final PadOfTruth padOfTruth;
private TextButton back;
public ScoreOverlay(@NotNull GameScreen gameScreen) {
public ScoreOverlay(@NotNull GameScreen gameScreen, boolean finalScores) {
super(gameScreen, Long.MAX_VALUE);
padOfTruth = Objects.requireNonNull(gameScreen.getPadOfTruth());
this.finalScores = finalScores;
this.padOfTruth = Objects.requireNonNull(gameScreen.getPadOfTruth());
}
@Override
protected Actor createContent() {
var group = new Group();
group.addActor(padOfTruth);
if (finalScores) {
back = new TextButton(messages.get("game.overlay.scores.return_to_session"), skin);
back.setPosition(
(WizardGame.WIDTH - back.getWidth()) / 2,
(WizardGame.HEIGHT - padOfTruth.getHeight()) / 2 + 30 - back.getHeight()
);
back.setVisible(false);
back.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
screen.showSessionScreen();
}
});
group.addActor(back);
}
return group;
}
@ -35,20 +58,32 @@ public class ScoreOverlay extends Overlay {
var root = getRoot().fill();
super.show(parent);
if (finalScores) {
root.addAction(sequence(
run(() -> padOfTruth.setEnabled(false)),
parallel(
targeting(padOfTruth, scaleTo(1, 1, OVERLAY_SHARED_ELEMENT)),
targeting(padOfTruth, moveTo((WizardGame.WIDTH - padOfTruth.getWidth()) / 2,(WizardGame.HEIGHT - padOfTruth.getHeight()) / 2 + 50, OVERLAY_SHARED_ELEMENT))
),
delay(AnimationTimings.OVERLAY_HOLD),
targeting(back, visible(true))
));
} else {
root.addAction(sequence(
run(() -> padOfTruth.setEnabled(false)),
parallel(
targeting(padOfTruth, scaleTo(1, 1, OVERLAY_SHARED_ELEMENT)),
targeting(padOfTruth, moveTo((WizardGame.WIDTH - padOfTruth.getWidth()) / 2, (WizardGame.HEIGHT - padOfTruth.getHeight()) / 2, OVERLAY_SHARED_ELEMENT))
targeting(padOfTruth, moveTo((WizardGame.WIDTH - padOfTruth.getWidth()) / 2,(WizardGame.HEIGHT - padOfTruth.getHeight()) / 2, OVERLAY_SHARED_ELEMENT))
),
delay(AnimationTimings.OVERLAY_HOLD),
parallel(
targeting(padOfTruth, scaleTo(PadOfTruth.COLLAPSED_SCALE, PadOfTruth.COLLAPSED_SCALE, OVERLAY_SHARED_ELEMENT)),
targeting(padOfTruth, moveTo(PAD_OF_TRUTH_POSITION.x, PAD_OF_TRUTH_POSITION.y, OVERLAY_SHARED_ELEMENT))
targeting(padOfTruth, moveTo(PAD_OF_TRUTH_POSITION.x, PAD_OF_TRUTH_POSITION.y, OVERLAY_SHARED_ELEMENT) )
),
targeting(padOfTruth, changeParent(screen.getContentRoot())),
run(() -> padOfTruth.setEnabled(true)),
run(this::close)
));
}
}
}

@ -21,6 +21,7 @@ import eu.jonahbauer.wizard.client.libgdx.actors.CardStack;
import eu.jonahbauer.wizard.client.libgdx.actors.CardsGroup;
import eu.jonahbauer.wizard.client.libgdx.actors.PadOfTruth;
import eu.jonahbauer.wizard.client.libgdx.state.Game;
import eu.jonahbauer.wizard.client.libgdx.state.Session;
import eu.jonahbauer.wizard.client.libgdx.util.AnimationTimings;
import eu.jonahbauer.wizard.client.libgdx.util.CardUtil;
import eu.jonahbauer.wizard.client.libgdx.util.Pair;
@ -357,6 +358,10 @@ public class GameScreen extends WizardScreen {
game.getClient().execute(Game.class, (s, c) -> s.onPredictionMade(c, prediction));
}
public void showSessionScreen() {
game.getClient().execute(Session.class, Session::showInfoScreen);
}
//<editor-fold desc="UI">
public void dim(int layer, boolean dim) {
var old = dimLayer;
@ -773,8 +778,8 @@ public class GameScreen extends WizardScreen {
return overlay;
}
public void showScoreOverlay() {
execute(new ScoreOverlay(this));
public void showScoreOverlay(boolean finalScores) {
execute(new ScoreOverlay(this, finalScores));
}
public InteractionOverlay showMakePredictionOverlay(int round, long timeout) {

@ -68,6 +68,8 @@ public final class Game extends BaseState {
private Card juggleCard;
private boolean werewolf;
private int finishing = 0;
public void init(List<ObserverMessage> messages) {
pendingMessages = messages;
}
@ -104,11 +106,16 @@ public final class Game extends BaseState {
}
private Optional<ClientState> onMessage(ObserverMessage message) {
if (finishing != 0) return onMessageWhileFinishing(message);
if (message instanceof StateMessage state) {
switch (state.getState()) {
case "starting_round" -> onStartRound();
case "starting_round" -> {
return onStartRound();
}
case "starting_trick" -> onStartTrick();
case "juggling" -> onJuggle();
case "finishing_round" -> onFinishingRound();
case "finished" -> {
onFinished();
return returnToSession();
@ -129,20 +136,44 @@ public final class Game extends BaseState {
} else if (message instanceof CardMessage card) {
onCardMessage(card.getPlayer(), card.getCard());
} else if (message instanceof ScoreMessage score) {
onScoreMessage(score.getPoints());
onScoreMessage(score.getPoints(), true);
} else if (message instanceof UserInputMessage input) {
onUserInputMessage(input.getPlayer(), input.getAction(), input.getTimeout());
} else if (message instanceof TimeoutMessage) {
onTimeoutMessage();
} else {
log.fatal("Unknown observer message type {}.", message.getClass());
// TODO user feedback
return Optional.of(new Menu());
return unexpectedMessage(new GameMessage(message));
}
return Optional.empty();
}
private void onStartRound() {
private Optional<ClientState> onMessageWhileFinishing(ObserverMessage message) {
if (finishing == 1) { // last "finishing_round" has been received
if (message instanceof ScoreMessage score) {
onScoreMessage(score.getPoints(), false);
return Optional.empty();
} else if (message instanceof StateMessage state && "finishing".equals(state.getState())) {
finishing++;
return Optional.empty();
}
} else if (finishing == 2) { // "finishing" has been received
if (message instanceof ScoreMessage) {
return Optional.empty();
} else if (message instanceof StateMessage state && "finished".equals(state.getState())) {
onFinished();
finishing++;
return returnToSession();
}
}
return unexpectedMessage(new GameMessage(message));
}
private Optional<ClientState> onStartRound() {
if (isLastRound()) {
log.fatal("Cannot start round {} with {} players", round + 1, players.size());
return unexpectedMessage(new GameMessage(new StateMessage("starting_round")));
}
log.info("Round {} is starting...", round + 1);
round ++;
@ -153,6 +184,7 @@ public final class Game extends BaseState {
trick = -1;
if (gameScreen != null) gameScreen.startRound(round);
return Optional.empty();
}
private void onStartTrick() {
@ -168,8 +200,15 @@ public final class Game extends BaseState {
juggleCard = null;
}
private void onFinishingRound() {
if (isLastRound()) finishing = 1; // start finish procedure
}
private void onFinished() {
log.info("The game has finished.");
if (gameScreen != null) {
gameScreen.showScoreOverlay(true);
}
}
private void onError() {
@ -256,12 +295,12 @@ public final class Game extends BaseState {
if (gameScreen != null) gameScreen.playCard(player, handCard, card);
}
private void onScoreMessage(@Unmodifiable Map<@NotNull UUID, @NotNull Integer> points) {
private void onScoreMessage(@Unmodifiable Map<@NotNull UUID, @NotNull Integer> points, boolean showOverlay) {
log.info("The scores are as follows: " + points);
scores.put(round, points);
if (gameScreen != null) {
gameScreen.addScores(round, points);
gameScreen.showScoreOverlay();
if (showOverlay) gameScreen.showScoreOverlay(false);
}
}
@ -392,7 +431,8 @@ public final class Game extends BaseState {
players.entrySet().stream()
.map(entry -> new PlayerData(entry.getKey(), entry.getValue(), false))
.toList(),
self
self,
true
));
}
@ -509,6 +549,10 @@ public final class Game extends BaseState {
}
}
private boolean isLastRound() {
return round + 1 >= 60 / getPlayers().size();
}
//<editor-fold desc="Logging" defaultState="collapsed">
/**

@ -24,27 +24,29 @@ public final class Session extends BaseState {
private final String sessionName;
private final Configuration configuration;
private final LinkedHashMap<UUID, PlayerData> players = new LinkedHashMap<>();
private final boolean dontSwitchScreen;
private boolean sending;
public Session(SessionData session, Collection<PlayerData> players, UUID self) {
this(session, players, self, false);
}
public Session(SessionData session, Collection<PlayerData> players, UUID self, boolean dontSwitchScreen) {
this.session = session.getUuid();
this.sessionName = session.getName();
this.configuration = session.getConfiguration();
players.forEach(p -> this.players.put(p.getUuid(), p));
this.dontSwitchScreen = dontSwitchScreen;
this.self = self;
}
@Override
public Optional<ClientState> onEnter(Client client) {
sessionScreen = new WaitingScreen(client.getGame());
client.getGame().setScreen(sessionScreen);
sessionScreen.setPlayers(players.values().toArray(new PlayerData[0]));
sessionScreen.setReady(false);
sessionScreen.setPlayerName(getName());
sessionScreen.setSession(session, sessionName, configuration);
if (!dontSwitchScreen) {
showInfoScreen(client);
}
return super.onEnter(client);
}
@ -112,6 +114,16 @@ public final class Session extends BaseState {
return Optional.of(new AwaitingJoinLobby());
}
public Optional<ClientState> showInfoScreen(Client client) {
sessionScreen = new WaitingScreen(client.getGame());
client.getGame().setScreen(sessionScreen);
sessionScreen.setPlayers(players.values().toArray(new PlayerData[0]));
sessionScreen.setReady(players.get(self).isReady());
sessionScreen.setPlayerName(getName());
sessionScreen.setSession(session, sessionName, configuration);
return Optional.empty();
}
private boolean isReady() {
return players.get(self).isReady();
}

@ -237,3 +237,5 @@ game.overlay.play_colored_card.cancel=Cancel
game.overlay.play_changeling.prompt=Do you want to play the changeling as a wizard or a jester?
game.overlay.play_changeling.cancel=Cancel
game.overlay.scores.return_to_session=Done

@ -227,3 +227,5 @@ game.overlay.play_colored_card.cancel=Abbrechen
game.overlay.play_changeling.prompt=Möchtest du den Gestaltwandler als Zauberer oder als Narr spielen?
game.overlay.play_changeling.cancel=Abbrechen
game.overlay.scores.return_to_session=Fertig
Loading…
Cancel
Save