mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
Merge remote-tracking branch 'origin/UI' into UI
# Conflicts: # app/src/main/java/org/toop/app/layer/layers/MultiplayerLayer.java # app/src/main/java/org/toop/app/layer/layers/game/TicTacToeLayer.java
This commit is contained in:
@@ -93,7 +93,11 @@ public final class App extends Application {
|
|||||||
final int childrenCount = root.getChildren().size();
|
final int childrenCount = root.getChildren().size();
|
||||||
|
|
||||||
for (int i = 0; i < childrenCount; i++) {
|
for (int i = 0; i < childrenCount; i++) {
|
||||||
|
try {
|
||||||
root.getChildren().removeLast();
|
root.getChildren().removeLast();
|
||||||
|
} catch (Exception e) {
|
||||||
|
IO.println(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stack.removeAllElements();
|
stack.removeAllElements();
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package org.toop.app.layer.layers;
|
||||||
|
|
||||||
|
import org.toop.app.layer.Layer;
|
||||||
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
|
import org.toop.framework.networking.events.NetworkEvents;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public final class ConnectedLayer extends Layer {
|
||||||
|
long clientId;
|
||||||
|
String user;
|
||||||
|
List<String> onlinePlayers = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
public ConnectedLayer(long clientId, String user) {
|
||||||
|
super("multiplayer.css");
|
||||||
|
this.clientId = clientId;
|
||||||
|
this.user = user;
|
||||||
|
reload();
|
||||||
|
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.SendLogin(this.clientId, this.user)).postEvent();
|
||||||
|
new EventFlow().listen(this::handleReceivedChallenge);
|
||||||
|
|
||||||
|
new Thread(this::populatePlayerList).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populatePlayerList() {
|
||||||
|
EventFlow sendGetPlayerList = new EventFlow().addPostEvent(new NetworkEvents.SendGetPlayerlist(this.clientId));
|
||||||
|
new EventFlow().listen(NetworkEvents.PlayerlistResponse.class, e -> {
|
||||||
|
if (e.clientId() == this.clientId) {
|
||||||
|
List<String> playerList = new java.util.ArrayList<>(List.of(e.playerlist())); // TODO: Garbage, but works
|
||||||
|
playerList.removeIf(name -> name.equalsIgnoreCase(user));
|
||||||
|
if (this.onlinePlayers != playerList) {
|
||||||
|
this.onlinePlayers.clear();
|
||||||
|
this.onlinePlayers.addAll(playerList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TimerTask task = new TimerTask() {
|
||||||
|
public void run() {
|
||||||
|
sendGetPlayerList.postEvent();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Timer pollTimer = new Timer();
|
||||||
|
pollTimer.schedule(task, 0L, 5000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendChallenge(String oppUsername, String gameType) {
|
||||||
|
if (onlinePlayers.contains(oppUsername)) {
|
||||||
|
new EventFlow().addPostEvent(new NetworkEvents.SendChallenge(this.clientId, oppUsername, gameType))
|
||||||
|
.postEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleReceivedChallenge(NetworkEvents.ChallengeResponse response) {
|
||||||
|
// TODO: Popup? Idk what this actually sends back.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
popAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
package org.toop.app.layer.layers.game;
|
package org.toop.app.layer.layers.game;
|
||||||
|
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import org.toop.app.App;
|
import org.toop.app.App;
|
||||||
import org.toop.app.GameInformation;
|
import org.toop.app.GameInformation;
|
||||||
import org.toop.app.canvas.TicTacToeCanvas;
|
import org.toop.app.canvas.TicTacToeCanvas;
|
||||||
import org.toop.app.layer.Container;
|
import org.toop.app.layer.Container;
|
||||||
import org.toop.app.layer.Layer;
|
import org.toop.app.layer.Layer;
|
||||||
import org.toop.app.layer.NodeBuilder;
|
|
||||||
import org.toop.app.layer.containers.VerticalContainer;
|
import org.toop.app.layer.containers.VerticalContainer;
|
||||||
import org.toop.app.layer.layers.MainLayer;
|
import org.toop.app.layer.layers.MainLayer;
|
||||||
import org.toop.framework.eventbus.EventFlow;
|
import org.toop.framework.eventbus.EventFlow;
|
||||||
@@ -17,9 +14,13 @@ import org.toop.game.tictactoe.TicTacToe;
|
|||||||
import org.toop.game.tictactoe.TicTacToeAI;
|
import org.toop.game.tictactoe.TicTacToeAI;
|
||||||
import org.toop.local.AppContext;
|
import org.toop.local.AppContext;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class TicTacToeLayer extends Layer {
|
public final class TicTacToeLayer extends Layer {
|
||||||
private TicTacToeCanvas canvas;
|
private TicTacToeCanvas canvas;
|
||||||
@@ -36,9 +37,9 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
private String player2Name = "";
|
private String player2Name = "";
|
||||||
|
|
||||||
public TicTacToeLayer(GameInformation information) {
|
public TicTacToeLayer(GameInformation information) {
|
||||||
super("bg-primary");
|
super("game.css");
|
||||||
|
|
||||||
canvas = new TicTacToeCanvas(Color.LIME, (App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75, (cell) -> {
|
canvas = new TicTacToeCanvas(Color.WHITE, (App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75, (cell) -> {
|
||||||
try {
|
try {
|
||||||
if (information.isConnectionLocal()) {
|
if (information.isConnectionLocal()) {
|
||||||
if (ticTacToe.getCurrentTurn() == 0) {
|
if (ticTacToe.getCurrentTurn() == 0) {
|
||||||
@@ -47,12 +48,10 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
playerMoveQueue.put(new Game.Move(cell, 'O'));
|
playerMoveQueue.put(new Game.Move(cell, 'O'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ticTacToe.getCurrentTurn() == 0) {
|
|
||||||
if (information.isPlayerHuman()[0] && currentPlayerMove != Game.EMPTY) {
|
if (information.isPlayerHuman()[0] && currentPlayerMove != Game.EMPTY) {
|
||||||
playerMoveQueue.put(new Game.Move(cell, currentPlayerMove));
|
playerMoveQueue.put(new Game.Move(cell, currentPlayerMove));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -94,13 +93,11 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final var backButton = NodeBuilder.button(AppContext.getString("back"), () -> {
|
final Container controlContainer = new VerticalContainer(5);
|
||||||
|
controlContainer.addButton(AppContext.getString("back"), () -> {
|
||||||
App.activate(new MainLayer());
|
App.activate(new MainLayer());
|
||||||
});
|
});
|
||||||
|
|
||||||
final Container controlContainer = new VerticalContainer(5);
|
|
||||||
controlContainer.addNodes(backButton);
|
|
||||||
|
|
||||||
addContainer(controlContainer, Pos.BOTTOM_LEFT, 2, -2, 0, 0);
|
addContainer(controlContainer, Pos.BOTTOM_LEFT, 2, -2, 0, 0);
|
||||||
addGameCanvas(canvas, Pos.CENTER, 0, 0);
|
addGameCanvas(canvas, Pos.CENTER, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -164,10 +161,8 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
public long receivedMove = -1;
|
public long receivedMove = -1;
|
||||||
public boolean firstPlayerIsMe = true;
|
public boolean firstPlayerIsMe = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomicBoolean firstPlayerIsMe = new AtomicBoolean(true);
|
AtomicBoolean firstPlayerIsMe = new AtomicBoolean(true);
|
||||||
AtomicBoolean gameHasStarted = new AtomicBoolean(false);
|
AtomicBoolean gameHasStarted = new AtomicBoolean(false);
|
||||||
|
|
||||||
private void serverGameThread(NetworkEvents.StartClientResponse event) {
|
private void serverGameThread(NetworkEvents.StartClientResponse event) {
|
||||||
boolean running = true;
|
boolean running = true;
|
||||||
final long clientId = event.clientId();
|
final long clientId = event.clientId();
|
||||||
@@ -184,26 +179,20 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
.listen(this::handleReceivedMessage)
|
.listen(this::handleReceivedMessage)
|
||||||
.listen(this::onMoveResponse);
|
.listen(this::onMoveResponse);
|
||||||
|
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendLogin(clientId, information.playerName()[0]))
|
|
||||||
.postEvent();
|
|
||||||
|
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendSubscribe(clientId, "tic-tac-toe"))
|
|
||||||
.postEvent();
|
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(250);
|
Thread.sleep(250);
|
||||||
} catch (InterruptedException exception) {
|
} catch (InterruptedException exception) {}
|
||||||
}
|
|
||||||
boolean hasStarted = gameHasStarted.get();
|
boolean hasStarted = gameHasStarted.get();
|
||||||
if (hasStarted) {
|
if (hasStarted) {
|
||||||
onlineGameState.firstPlayerIsMe = firstPlayerIsMe.get();
|
onlineGameState.firstPlayerIsMe = firstPlayerIsMe.get();
|
||||||
if (onlineGameState.firstPlayerIsMe) {
|
if (onlineGameState.firstPlayerIsMe) {
|
||||||
currentPlayerMove = 'X';
|
currentPlayerMove = 'X';
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
currentPlayerMove = 'O';
|
currentPlayerMove = 'O';
|
||||||
}
|
}
|
||||||
if (!information.isPlayerHuman()[0]) {
|
if(!information.isPlayerHuman()[0]){
|
||||||
boolean myTurn = (onlineGameState.firstPlayerIsMe && ticTacToe.getCurrentTurn() % 2 == 0)
|
boolean myTurn = (onlineGameState.firstPlayerIsMe && ticTacToe.getCurrentTurn() % 2 == 0)
|
||||||
|| (!onlineGameState.firstPlayerIsMe && ticTacToe.getCurrentTurn() % 2 == 1);
|
|| (!onlineGameState.firstPlayerIsMe && ticTacToe.getCurrentTurn() % 2 == 1);
|
||||||
if (myTurn) {
|
if (myTurn) {
|
||||||
@@ -212,7 +201,8 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
new EventFlow().addPostEvent(new NetworkEvents.SendMove(clientId, (short) move.position()))
|
new EventFlow().addPostEvent(new NetworkEvents.SendMove(clientId, (short) move.position()))
|
||||||
.postEvent();
|
.postEvent();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
try {
|
try {
|
||||||
final Game.Move wants = playerMoveQueue.take();
|
final Game.Move wants = playerMoveQueue.take();
|
||||||
final Game.Move[] legalMoves = ticTacToe.getLegalMoves();
|
final Game.Move[] legalMoves = ticTacToe.getLegalMoves();
|
||||||
@@ -224,6 +214,7 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (InterruptedException exception) {
|
} catch (InterruptedException exception) {
|
||||||
|
System.out.println(exception.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,9 +231,10 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleServerGameStart(NetworkEvents.GameMatchResponse resp) {
|
private void handleServerGameStart(NetworkEvents.GameMatchResponse resp) {
|
||||||
if (resp.playerToMove().equals(resp.opponent())) {
|
if(resp.playerToMove().equals(resp.opponent())){
|
||||||
firstPlayerIsMe.set(false);
|
firstPlayerIsMe.set(false);
|
||||||
} else {
|
}
|
||||||
|
else{
|
||||||
firstPlayerIsMe.set(true);
|
firstPlayerIsMe.set(true);
|
||||||
}
|
}
|
||||||
gameHasStarted.set(true);
|
gameHasStarted.set(true);
|
||||||
@@ -253,10 +245,11 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
if (resp.player().equals(information.playerName()[0]) && firstPlayerIsMe.get()
|
if (resp.player().equals(information.playerName()[0]) && firstPlayerIsMe.get()
|
||||||
|| !resp.player().equals(information.playerName()[0]) && !firstPlayerIsMe.get()) {
|
|| !resp.player().equals(information.playerName()[0]) && !firstPlayerIsMe.get()) {
|
||||||
playerChar = 'X';
|
playerChar = 'X';
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
playerChar = 'O';
|
playerChar = 'O';
|
||||||
}
|
}
|
||||||
Game.Move move = new Game.Move(Integer.parseInt(resp.move()), playerChar);
|
Game.Move move =new Game.Move(Integer.parseInt(resp.move()),playerChar);
|
||||||
Game.State state = ticTacToe.play(move);
|
Game.State state = ticTacToe.play(move);
|
||||||
if (state != Game.State.NORMAL) { //todo differentiate between future draw guaranteed and is currently a draw
|
if (state != Game.State.NORMAL) { //todo differentiate between future draw guaranteed and is currently a draw
|
||||||
gameHasStarted.set(false);
|
gameHasStarted.set(false);
|
||||||
@@ -265,7 +258,7 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleChallengeResponse(NetworkEvents.ChallengeResponse resp) {
|
private void handleChallengeResponse(NetworkEvents.ChallengeResponse resp) {
|
||||||
new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(resp.clientId(), Integer.parseInt(resp.challengeId())))
|
new EventFlow().addPostEvent(new NetworkEvents.SendAcceptChallenge(resp.clientId(),Integer.parseInt(resp.challengeId())))
|
||||||
.postEvent();
|
.postEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +268,6 @@ public final class TicTacToeLayer extends Layer {
|
|||||||
//new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(),(short)2))
|
//new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(),(short)2))
|
||||||
// .postEvent();
|
// .postEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReceivedMessage(NetworkEvents.ReceivedMessage msg) {
|
private void handleReceivedMessage(NetworkEvents.ReceivedMessage msg) {
|
||||||
System.out.println("Received Message: " + msg.message()); //todo add chat window
|
System.out.println("Received Message: " + msg.message()); //todo add chat window
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ import org.toop.framework.asset.types.LoadableResource;
|
|||||||
|
|
||||||
import javax.sound.sampled.*;
|
import javax.sound.sampled.*;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
@FileExtension({"wav"})
|
@FileExtension({"wav"})
|
||||||
public class SoundEffectAsset extends BaseResource implements LoadableResource {
|
public class SoundEffectAsset extends BaseResource implements LoadableResource {
|
||||||
|
private byte[] rawData;
|
||||||
|
|
||||||
public SoundEffectAsset(final File audioFile) {
|
public SoundEffectAsset(final File audioFile) {
|
||||||
super(audioFile);
|
super(audioFile);
|
||||||
@@ -15,10 +17,6 @@ public class SoundEffectAsset extends BaseResource implements LoadableResource {
|
|||||||
|
|
||||||
// Gets a new clip to play
|
// Gets a new clip to play
|
||||||
public Clip getNewClip() throws LineUnavailableException, UnsupportedAudioFileException, IOException {
|
public Clip getNewClip() throws LineUnavailableException, UnsupportedAudioFileException, IOException {
|
||||||
if(!this.isLoaded()){
|
|
||||||
this.load();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a new clip from audio system
|
// Get a new clip from audio system
|
||||||
Clip clip = AudioSystem.getClip();
|
Clip clip = AudioSystem.getClip();
|
||||||
|
|
||||||
@@ -32,7 +30,13 @@ public class SoundEffectAsset extends BaseResource implements LoadableResource {
|
|||||||
|
|
||||||
// Generates a new audio stream from byte array
|
// Generates a new audio stream from byte array
|
||||||
private AudioInputStream getAudioStream() throws UnsupportedAudioFileException, IOException {
|
private AudioInputStream getAudioStream() throws UnsupportedAudioFileException, IOException {
|
||||||
return AudioSystem.getAudioInputStream(this.file);
|
// Check if raw data is loaded into memory
|
||||||
|
if(!this.isLoaded()){
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turn rawData into an input stream and turn that into an audio input stream;
|
||||||
|
return AudioSystem.getAudioInputStream(new ByteArrayInputStream(this.rawData));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AudioInputStream downSampleAudio(AudioInputStream audioInputStream, AudioFormat baseFormat) {
|
private AudioInputStream downSampleAudio(AudioInputStream audioInputStream, AudioFormat baseFormat) {
|
||||||
@@ -52,16 +56,17 @@ public class SoundEffectAsset extends BaseResource implements LoadableResource {
|
|||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
try {
|
try {
|
||||||
this.getAudioStream();
|
this.rawData = Files.readAllBytes(file.toPath());
|
||||||
this.isLoaded = true;
|
this.isLoaded = true;
|
||||||
} catch (UnsupportedAudioFileException | IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unload() {
|
public void unload() {
|
||||||
this.isLoaded = false; // TODO?
|
this.rawData = null;
|
||||||
|
this.isLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -75,6 +75,20 @@ public class SoundManager {
|
|||||||
for (MediaPlayer mediaPlayer : this.activeMusic) {
|
for (MediaPlayer mediaPlayer : this.activeMusic) {
|
||||||
mediaPlayer.setVolume(this.volume);
|
mediaPlayer.setVolume(this.volume);
|
||||||
}
|
}
|
||||||
|
for (Clip clip : this.activeSoundEffects.values()){
|
||||||
|
updateClipVolume(clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateClipVolume(Clip clip){
|
||||||
|
if (clip.isControlSupported(FloatControl.Type.MASTER_GAIN)){
|
||||||
|
FloatControl volumeControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
|
||||||
|
float min = volumeControl.getMinimum();
|
||||||
|
float max = volumeControl.getMaximum();
|
||||||
|
float dB = (float) (Math.log10(Math.max(volume, 0.0001)) * 20.0); // convert linear to dB
|
||||||
|
dB = Math.max(min, Math.min(max, dB));
|
||||||
|
volumeControl.setValue(dB);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) {
|
private void handleGetCurrentVolume(AudioEvents.GetCurrentVolume event) {
|
||||||
@@ -144,6 +158,9 @@ public class SoundManager {
|
|||||||
// Get a new clip from resource
|
// Get a new clip from resource
|
||||||
Clip clip = asset.getNewClip();
|
Clip clip = asset.getNewClip();
|
||||||
|
|
||||||
|
// Set volume of clip
|
||||||
|
updateClipVolume(clip);
|
||||||
|
|
||||||
// If supposed to loop make it loop, else just start it once
|
// If supposed to loop make it loop, else just start it once
|
||||||
if (loop) {
|
if (loop) {
|
||||||
clip.loop(Clip.LOOP_CONTINUOUSLY);
|
clip.loop(Clip.LOOP_CONTINUOUSLY);
|
||||||
|
|||||||
Reference in New Issue
Block a user