Some work
This commit is contained in:
@@ -23,7 +23,6 @@ public class AcousticHandler {
|
|||||||
private GameMusic playing = null; // Currently playing track
|
private GameMusic playing = null; // Currently playing track
|
||||||
private GameMusic scheduled = null; // Scheduled track to play next
|
private GameMusic scheduled = null; // Scheduled track to play next
|
||||||
private GameMusic old = null; // Old track being faded out
|
private GameMusic old = null; // Old track being faded out
|
||||||
private ArrayList<GameMusic> queue = new ArrayList<>();
|
|
||||||
|
|
||||||
private float mainVolume = 1.0f;
|
private float mainVolume = 1.0f;
|
||||||
private float musicVolume = 1.0f;
|
private float musicVolume = 1.0f;
|
||||||
@@ -91,7 +90,6 @@ public void playState(MdgaState state) {
|
|||||||
if (this.state == state) {
|
if (this.state == state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicAsset asset = null;
|
MusicAsset asset = null;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -135,125 +133,165 @@ private float lerp(float start, float end, float t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the music playback state, handling transitions between tracks with fades.
|
* Updates the state of audio playback, handling track transitions and volume adjustments.
|
||||||
*
|
*
|
||||||
* This function ensures smooth transitions between tracks, including fading out the
|
* This method ensures smooth transitions between tracks using fade-in and fade-out effects.
|
||||||
* current track, pausing, and fading in the next scheduled track. It also starts
|
* It also handles cases where no track is playing, starting a scheduled track immediately at full volume.
|
||||||
* music instantly if nothing is currently playing and a track is scheduled.
|
* The method prioritizes the latest scheduled track if multiple scheduling occurs quickly.
|
||||||
*
|
*
|
||||||
* Function Behavior:
|
* Behavior:
|
||||||
* 1. If no track is playing and a track is scheduled, it starts instantly.
|
* 1. If nothing is scheduled and no track is playing, it exits early.
|
||||||
* 2. If a track is playing and a new track is scheduled, it initiates a fade-out
|
* 2. If a scheduled track exists and no track is playing, the scheduled track starts immediately at full volume.
|
||||||
* of the current track, followed by a pause (if applicable), and a fade-in of the new track.
|
* 3. If a scheduled track exists while a track is playing, it initiates a fade-out for the currently playing track
|
||||||
* 3. If a fade process is ongoing, it respects the fade durations and smoothly transitions
|
* and prepares for the new track to fade in.
|
||||||
* between tracks.
|
* 4. If a track transition is in progress (fading), it processes the fade-out and fade-in states.
|
||||||
* 4. Tracks that finish their fade-out are paused, and their volume is set to 0.
|
* If a new track is scheduled during this process, it interrupts the current transition and prioritizes the new track.
|
||||||
* 5. During regular playback, the current track's volume is updated to match the overall
|
* 5. If no fading is needed and a track is playing, it ensures the track's volume is updated.
|
||||||
* music volume setting.
|
|
||||||
*
|
*
|
||||||
* Special Cases:
|
* Special cases:
|
||||||
* - If a new track is scheduled during an ongoing fade, it interrupts the current fade
|
* - If no track is playing and a new track is scheduled, it starts the track immediately without fading.
|
||||||
* and starts the new fade sequence.
|
* - If a new track is scheduled during fading, it resets the transition to prioritize the new track.
|
||||||
* - Handles null checks for playing and scheduled tracks to prevent errors.
|
|
||||||
* - Instant start of music is prioritized if nothing is playing.
|
|
||||||
*
|
|
||||||
* Preconditions:
|
|
||||||
* - `playing`, `scheduled`, and `old` may be null, and the function gracefully handles these states.
|
|
||||||
* - Fade durations and pause durations are configurable via `FADE_DURATION` and `CROSSFADE_DURATION`.
|
|
||||||
*
|
|
||||||
* Dependencies:
|
|
||||||
* - `getMusicVolumeTotal()`: Provides the total volume scaling factor for music.
|
|
||||||
* - `GameMusic` class methods: `play()`, `pause()`, `update(float volume)`, and `getPause()` for managing track playback.
|
|
||||||
* - `NanoTimer`: Used to track the elapsed time during fades.
|
|
||||||
*
|
|
||||||
* Exceptions:
|
|
||||||
* - Ensures no NullPointerException occurs by validating track states before invoking methods.
|
|
||||||
*/
|
*/
|
||||||
private void updateVolumeAndTrack() {
|
private void updateVolumeAndTrack() {
|
||||||
if(!fading) {
|
|
||||||
if(!queue.isEmpty()) {
|
|
||||||
scheduled = queue.removeFirst();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scheduled == null && !fading && playing == null) {
|
if (scheduled == null && !fading && playing == null) {
|
||||||
// Nothing to play or fade, early exit
|
// Nothing to do, early exit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scheduled != null && playing == null && !fading) {
|
if (scheduled != null && playing == null && !fading) {
|
||||||
// Start the scheduled music instantly if nothing is currently playing
|
// No current track, start scheduled track immediately at full volume
|
||||||
playing = scheduled;
|
playing = scheduled;
|
||||||
scheduled = null;
|
scheduled = null;
|
||||||
playing.play();
|
playing.play();
|
||||||
playing.update(getMusicVolumeTotal()); // Start at full volume
|
playing.update(getMusicVolumeTotal()); // Set volume to full
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scheduled != null && !fading) {
|
if (scheduled != null && !fading) {
|
||||||
// Start a new fade process if no fade is ongoing
|
// Initiate a fade process if a new track is scheduled
|
||||||
fading = true;
|
fading = true;
|
||||||
fadeTimer.reset();
|
fadeTimer.reset();
|
||||||
old = playing;
|
old = playing; // The currently playing track becomes the old track
|
||||||
playing = null; // Clear current track until fade-in begins
|
playing = null; // Clear the playing track during the fade process
|
||||||
outFadingFinished = false;
|
outFadingFinished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fading) {
|
if (fading) {
|
||||||
float time = fadeTimer.getTimeInSeconds();
|
handleFadeProcess();
|
||||||
|
|
||||||
if (old != null && time <= FADE_DURATION) {
|
// Handle any interruptions due to newly scheduled tracks
|
||||||
// Handle outfade for the old track
|
if (scheduled != null && playing != null && playing != scheduled) {
|
||||||
float t = Math.min(time / FADE_DURATION, 1.0f);
|
// Interrupt the current infade and switch to the new scheduled track
|
||||||
float oldVolume = lerp(1.0f, 0.0f, t);
|
old = playing; // Treat the currently infading track as the old track
|
||||||
old.update(getMusicVolumeTotal() * oldVolume);
|
playing = null; // Reset playing to allow switching
|
||||||
}
|
fadeTimer.reset(); // Restart fade timer for the new track
|
||||||
|
|
||||||
if (old != null && time > FADE_DURATION) {
|
|
||||||
// Complete the outfade for the old track
|
|
||||||
old.pause();
|
|
||||||
old = null;
|
|
||||||
outFadingFinished = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Respect the pause duration between outfade and infade
|
|
||||||
float pause = (scheduled != null) ? scheduled.getPause() : 0.0f;
|
|
||||||
if (time > FADE_DURATION + pause) {
|
|
||||||
// Start infade for the scheduled track
|
|
||||||
float infadeTime = time - FADE_DURATION - pause;
|
|
||||||
|
|
||||||
if (scheduled != null && infadeTime <= CROSSFADE_DURATION) {
|
|
||||||
float t = Math.min(infadeTime / CROSSFADE_DURATION, 1.0f);
|
|
||||||
float newVolume = lerp(0.0f, 1.0f, t);
|
|
||||||
|
|
||||||
if (playing != scheduled) {
|
|
||||||
playing = scheduled;
|
|
||||||
playing.play();
|
|
||||||
}
|
|
||||||
playing.update(getMusicVolumeTotal() * newVolume);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (infadeTime > CROSSFADE_DURATION) {
|
|
||||||
// Infade is complete, finalize state
|
|
||||||
fading = false;
|
|
||||||
if (playing != null) {
|
|
||||||
playing.update(getMusicVolumeTotal()); // Ensure playing track is at full volume
|
|
||||||
}
|
|
||||||
scheduled = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Regular playback state, ensure playing track is updated
|
|
||||||
if (playing != null) {
|
|
||||||
playing.update(getMusicVolumeTotal());
|
|
||||||
} else if (scheduled != null) {
|
|
||||||
// Handle immediate track switch
|
|
||||||
fading = true;
|
|
||||||
fadeTimer.reset();
|
|
||||||
old = playing;
|
|
||||||
playing = null; // Clear current track to start fade process
|
|
||||||
outFadingFinished = false;
|
outFadingFinished = false;
|
||||||
}
|
}
|
||||||
|
} else if (playing != null) {
|
||||||
|
// Update volume for the currently playing track
|
||||||
|
playing.update(getMusicVolumeTotal());
|
||||||
|
} else if (scheduled != null) {
|
||||||
|
// If no track is playing and one is scheduled, start it immediately at full volume
|
||||||
|
playing = scheduled;
|
||||||
|
scheduled = null;
|
||||||
|
playing.play();
|
||||||
|
playing.update(getMusicVolumeTotal()); // Set volume to full
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the fading process during audio track transitions.
|
||||||
|
*
|
||||||
|
* This method handles the fade-out of the currently playing (old) track, manages any pause between the fade-out
|
||||||
|
* and fade-in, and initiates the fade-in for the new track if applicable. It ensures smooth transitions between
|
||||||
|
* tracks while maintaining the correct volume adjustments.
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* 1. **Outfade:** Gradually decreases the volume of the `old` track over the duration of `FADE_DURATION`.
|
||||||
|
* Once the outfade completes, the `old` track is paused and cleared.
|
||||||
|
* 2. **Pause Handling:** Waits for a defined pause (if applicable) before initiating the infade for the next track.
|
||||||
|
* 3. **Infade:** If a `scheduled` track exists and the outfade and pause are complete, it begins playing
|
||||||
|
* the new track (`playing`) and initiates the infade process.
|
||||||
|
*
|
||||||
|
* Key Details:
|
||||||
|
* - The outfade volume adjustment is interpolated linearly from full volume to zero using the `lerp` function.
|
||||||
|
* - The pause duration is retrieved from the scheduled track if it is specified.
|
||||||
|
* - If a new track is scheduled during the fade process, it is handled by external logic to prioritize transitions.
|
||||||
|
*
|
||||||
|
* Preconditions:
|
||||||
|
* - `fading` is expected to be `true` when this method is called.
|
||||||
|
* - The method is invoked as part of the `updateVolumeAndTrack` process.
|
||||||
|
*/
|
||||||
|
private void handleFadeProcess() {
|
||||||
|
float time = fadeTimer.getTimeInSeconds();
|
||||||
|
|
||||||
|
// Handle outfade for the old track
|
||||||
|
if (old != null && time <= FADE_DURATION) {
|
||||||
|
float t = Math.min(time / FADE_DURATION, 1.0f);
|
||||||
|
float oldVolume = lerp(1.0f, 0.0f, t);
|
||||||
|
old.update(getMusicVolumeTotal() * oldVolume);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (old != null && time > FADE_DURATION) {
|
||||||
|
// Complete outfade
|
||||||
|
old.pause();
|
||||||
|
old = null;
|
||||||
|
outFadingFinished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle pause duration before infade
|
||||||
|
float pause = (scheduled != null) ? scheduled.getPause() : 0.0f;
|
||||||
|
if (time > FADE_DURATION + pause) {
|
||||||
|
if (playing == null && scheduled != null) {
|
||||||
|
// Begin infade for the new track
|
||||||
|
playing = scheduled;
|
||||||
|
scheduled = null;
|
||||||
|
playing.play(); // Start playing the new track
|
||||||
|
}
|
||||||
|
handleInfade(time - FADE_DURATION - pause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the fade-in process for the currently playing track.
|
||||||
|
*
|
||||||
|
* This method gradually increases the volume of the `playing` track from zero to full volume
|
||||||
|
* over the duration of `CROSSFADE_DURATION`. It ensures a smooth transition into the new track.
|
||||||
|
*
|
||||||
|
* Behavior:
|
||||||
|
* 1. If no track is set as `playing`, the method exits early, as there is nothing to fade in.
|
||||||
|
* 2. Linearly interpolates the volume of the `playing` track from 0.0 to 1.0 based on the elapsed
|
||||||
|
* `infadeTime` and the specified `CROSSFADE_DURATION`.
|
||||||
|
* 3. Once the fade-in is complete (when `infadeTime` exceeds `CROSSFADE_DURATION`), the method:
|
||||||
|
* - Marks the fade process (`fading`) as complete.
|
||||||
|
* - Ensures the `playing` track is updated to its full volume.
|
||||||
|
*
|
||||||
|
* Key Details:
|
||||||
|
* - Uses the `lerp` function to calculate the volume level for the `playing` track during the fade-in.
|
||||||
|
* - Ensures the volume is always a value between 0.0 and 1.0.
|
||||||
|
* - The `infadeTime` parameter should be relative to the start of the fade-in process.
|
||||||
|
*
|
||||||
|
* Preconditions:
|
||||||
|
* - The `playing` track must be initialized and actively fading in for this method to have an effect.
|
||||||
|
* - The method is invoked as part of the `updateVolumeAndTrack` process.
|
||||||
|
*
|
||||||
|
* @param infadeTime The elapsed time (in seconds) since the fade-in process started.
|
||||||
|
*/
|
||||||
|
private void handleInfade(float infadeTime) {
|
||||||
|
if (playing == null) {
|
||||||
|
// Nothing to infade
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed with the infade for the current playing track
|
||||||
|
float t = Math.min(infadeTime / CROSSFADE_DURATION, 1.0f);
|
||||||
|
float newVolume = lerp(0.0f, 1.0f, t);
|
||||||
|
playing.update(getMusicVolumeTotal() * newVolume);
|
||||||
|
|
||||||
|
if (infadeTime > CROSSFADE_DURATION) {
|
||||||
|
// Infade is complete, finalize state
|
||||||
|
fading = false;
|
||||||
|
playing.update(getMusicVolumeTotal()); // Ensure full volume
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,8 +328,7 @@ private void updateGameTracks() {
|
|||||||
|
|
||||||
MusicAsset nextTrack = gameTracks.remove(0);
|
MusicAsset nextTrack = gameTracks.remove(0);
|
||||||
|
|
||||||
GameMusic music = new GameMusic(app, nextTrack, getMusicVolumeTotal(), nextTrack.getSubVolume(), nextTrack.getLoop(), 0.0f);
|
scheduled = new GameMusic(app, nextTrack, getMusicVolumeTotal(), nextTrack.getSubVolume(), nextTrack.getLoop(), 0.0f);
|
||||||
queue.add(music);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,27 +5,54 @@
|
|||||||
import com.simsilica.lemur.Button;
|
import com.simsilica.lemur.Button;
|
||||||
import com.simsilica.lemur.Container;
|
import com.simsilica.lemur.Container;
|
||||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
|
import com.simsilica.lemur.component.QuadBackgroundComponent;
|
||||||
|
import com.simsilica.lemur.core.GuiComponent;
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
|
|
||||||
public abstract class Dialog {
|
public abstract class Dialog {
|
||||||
|
protected final ColorRGBA COLOR_DEFAULT = ColorRGBA.Gray;
|
||||||
|
protected final ColorRGBA COLOR_HOVER = ColorRGBA.DarkGray;
|
||||||
|
|
||||||
protected MdgaApp app;
|
protected MdgaApp app;
|
||||||
protected int xOffset = 0;
|
protected Container container;
|
||||||
protected int yOffset = 0;
|
|
||||||
|
|
||||||
public Dialog(MdgaApp app) {
|
public Dialog(MdgaApp app) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
|
this.container = new Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void show();
|
public void show() {
|
||||||
public abstract void hide();
|
app.getGuiNode().attachChild(container);
|
||||||
public abstract void addButton(MdgaButton button);
|
|
||||||
|
|
||||||
public void setYOffset(int yOffset) {
|
|
||||||
this.yOffset = yOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setXOffset(int xOffset) {
|
public void hide () {
|
||||||
this.xOffset = xOffset;
|
app.getGuiNode().detachChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createButton(String label, Runnable action, Vector3f size) {
|
||||||
|
Button button = new Button(label);
|
||||||
|
button.addClickCommands(source -> action.run());
|
||||||
|
button.setSize(size);
|
||||||
|
button.setFontSize(35);
|
||||||
|
button.setHighlightColor(ColorRGBA.White);
|
||||||
|
button.setColor(ColorRGBA.Black);
|
||||||
|
|
||||||
|
QuadBackgroundComponent background = new QuadBackgroundComponent(COLOR_DEFAULT);
|
||||||
|
background.setMargin(5, 5);
|
||||||
|
button.setBackground(background);
|
||||||
|
|
||||||
|
button.addCommands(com.simsilica.lemur.Button.ButtonAction.HighlightOn, (source) -> {
|
||||||
|
QuadBackgroundComponent hoverBackground = new QuadBackgroundComponent(COLOR_HOVER);
|
||||||
|
hoverBackground.setMargin(5, 5);
|
||||||
|
source.setBackground(hoverBackground);
|
||||||
|
});
|
||||||
|
|
||||||
|
button.addCommands(com.simsilica.lemur.Button.ButtonAction.HighlightOff, (source) -> {
|
||||||
|
QuadBackgroundComponent normalBackground = new QuadBackgroundComponent(COLOR_DEFAULT);
|
||||||
|
normalBackground.setMargin(5, 5);
|
||||||
|
source.setBackground(normalBackground);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.addChild(button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package pp.mdga.client.Dialog;
|
|
||||||
|
|
||||||
import com.jme3.math.ColorRGBA;
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.jme3.scene.Node;
|
|
||||||
import com.simsilica.lemur.Button;
|
|
||||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
|
|
||||||
import pp.mdga.client.MdgaApp;
|
|
||||||
|
|
||||||
public class HorizontalButtonDialog extends Dialog {
|
|
||||||
private Node row = new Node();
|
|
||||||
|
|
||||||
private int offset = 0;
|
|
||||||
|
|
||||||
public HorizontalButtonDialog(MdgaApp app) {
|
|
||||||
super(app);
|
|
||||||
|
|
||||||
//QuadBackgroundComponent quad = new QuadBackgroundComponent(ColorRGBA.Gray);
|
|
||||||
//quad.setMargin(10, 10);
|
|
||||||
//container.setBackground(quad);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void show() {
|
|
||||||
app.getGuiNode().attachChild(row);
|
|
||||||
|
|
||||||
row.setLocalTranslation((app.getCamera().getWidth() / 2) + xOffset, (app.getCamera().getHeight() / 2) + yOffset, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hide() {
|
|
||||||
app.getGuiNode().detachChild(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addButton(MdgaButton button) {
|
|
||||||
row.attachChild(button.getButton());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package pp.mdga.client.Dialog;
|
||||||
|
|
||||||
|
public class LobbyButtonDialog {
|
||||||
|
}
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package pp.mdga.client.Dialog;
|
|
||||||
|
|
||||||
import com.jme3.math.ColorRGBA;
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.simsilica.lemur.Button;
|
|
||||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
|
|
||||||
|
|
||||||
|
|
||||||
public class MdgaButton {
|
|
||||||
protected final ColorRGBA COLOR_DEFAULT = ColorRGBA.Gray;
|
|
||||||
protected final ColorRGBA COLOR_HOVER = ColorRGBA.DarkGray;
|
|
||||||
|
|
||||||
private Button button;
|
|
||||||
|
|
||||||
public MdgaButton(String label, Runnable action, Vector3f size) {
|
|
||||||
button = new Button(label);
|
|
||||||
|
|
||||||
button.addClickCommands(source -> action.run());
|
|
||||||
button.setSize(size);
|
|
||||||
|
|
||||||
QuadBackgroundComponent background = new QuadBackgroundComponent(COLOR_DEFAULT);
|
|
||||||
background.setMargin(5, 5);
|
|
||||||
button.setBackground(background);
|
|
||||||
|
|
||||||
button.addCommands(com.simsilica.lemur.Button.ButtonAction.HighlightOn, (source) -> {
|
|
||||||
QuadBackgroundComponent hoverBackground = new QuadBackgroundComponent(COLOR_HOVER);
|
|
||||||
hoverBackground.setMargin(5, 5);
|
|
||||||
source.setBackground(hoverBackground);
|
|
||||||
});
|
|
||||||
|
|
||||||
button.addCommands(com.simsilica.lemur.Button.ButtonAction.HighlightOff, (source) -> {
|
|
||||||
QuadBackgroundComponent normalBackground = new QuadBackgroundComponent(COLOR_DEFAULT);
|
|
||||||
normalBackground.setMargin(5, 5);
|
|
||||||
source.setBackground(normalBackground);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLocalTranslation(Vector3f pos) {
|
|
||||||
button.setLocalTranslation(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSize(Vector3f size) {
|
|
||||||
button.setSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Button getButton() {
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package pp.mdga.client.Dialog;
|
||||||
|
|
||||||
|
public class SettingsButtonDialog {
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package pp.mdga.client.Dialog;
|
||||||
|
|
||||||
|
public class SingleButtonLeftDialog {
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package pp.mdga.client.Dialog;
|
||||||
|
|
||||||
|
import com.jme3.math.ColorRGBA;
|
||||||
|
import com.jme3.math.Vector3f;
|
||||||
|
import com.simsilica.lemur.Button;
|
||||||
|
import com.simsilica.lemur.component.QuadBackgroundComponent;
|
||||||
|
import com.simsilica.lemur.core.GuiLayout;
|
||||||
|
import pp.mdga.client.MdgaApp;
|
||||||
|
|
||||||
|
public class SingleButtonRightDialog extends Dialog{
|
||||||
|
public SingleButtonRightDialog(MdgaApp app, String label, Runnable action) {
|
||||||
|
super(app);
|
||||||
|
|
||||||
|
createButton(label, action, new Vector3f(1, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show() {
|
||||||
|
super.show();
|
||||||
|
|
||||||
|
float vertical = app.getCamera().getWidth() / 16 - container.getPreferredSize().x / 16;
|
||||||
|
float horitontal = app.getCamera().getHeight() / 9 + container.getPreferredSize().y / 9;
|
||||||
|
|
||||||
|
float x = 12 * vertical;
|
||||||
|
float y = 1 * horitontal;
|
||||||
|
|
||||||
|
container.setLocalTranslation(x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hide() {
|
||||||
|
super.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,37 +8,32 @@
|
|||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
|
|
||||||
public class VerticalButtonDialog extends Dialog {
|
public class VerticalButtonDialog extends Dialog {
|
||||||
private Container container;
|
|
||||||
|
|
||||||
public VerticalButtonDialog(MdgaApp app) {
|
public VerticalButtonDialog(MdgaApp app) {
|
||||||
super(app);
|
super(app);
|
||||||
|
|
||||||
container = new Container();
|
QuadBackgroundComponent quad1 = new QuadBackgroundComponent(ColorRGBA.Gray);
|
||||||
|
quad1.setMargin(10, 10);
|
||||||
QuadBackgroundComponent quad = new QuadBackgroundComponent(ColorRGBA.Gray);
|
container.setBackground(quad1);
|
||||||
quad.setMargin(10, 10);
|
|
||||||
container.setBackground(quad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void show() {
|
public void show() {
|
||||||
app.getGuiNode().attachChild(container);
|
super.show();
|
||||||
|
|
||||||
container.setLocalTranslation(
|
container.setLocalTranslation(
|
||||||
(app.getCamera().getWidth() / 2 - container.getPreferredSize().x / 2) + xOffset,
|
app.getCamera().getWidth() / 2 - container.getPreferredSize().x / 2,
|
||||||
(app.getCamera().getHeight() / 2 + container.getPreferredSize().y / 2) + yOffset,
|
app.getCamera().getHeight() / 2 + container.getPreferredSize().y / 2,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hide() {
|
public void hide() {
|
||||||
app.getGuiNode().detachChild(container);
|
super.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void addButton(String label, Runnable action, Vector3f size) {
|
||||||
public void addButton(MdgaButton button) {
|
createButton(label, action, size);
|
||||||
container.addChild(button.getButton());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public static void main(String[] args) {
|
|||||||
settings.setCenterWindow(true);
|
settings.setCenterWindow(true);
|
||||||
settings.setWidth(1280);
|
settings.setWidth(1280);
|
||||||
settings.setHeight(720);
|
settings.setHeight(720);
|
||||||
|
settings.setVSync(false);
|
||||||
|
|
||||||
MdgaApp app = new MdgaApp();
|
MdgaApp app = new MdgaApp();
|
||||||
app.setSettings(settings);
|
app.setSettings(settings);
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package pp.mdga.client.View;
|
package pp.mdga.client.View;
|
||||||
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
|
||||||
import com.jme3.scene.shape.Quad;
|
|
||||||
import com.simsilica.lemur.Container;
|
import com.simsilica.lemur.Container;
|
||||||
import com.simsilica.lemur.Label;
|
import com.simsilica.lemur.Label;
|
||||||
import com.simsilica.lemur.Button;
|
import pp.mdga.client.Dialog.SingleButtonRightDialog;
|
||||||
import pp.mdga.client.Dialog.MdgaButton;
|
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
import pp.mdga.client.MdgaState;
|
import pp.mdga.client.MdgaState;
|
||||||
|
|
||||||
@@ -16,20 +12,31 @@ public class CeremonyView extends MdgaView {
|
|||||||
|
|
||||||
private enum SubState {
|
private enum SubState {
|
||||||
AWARD_CEREMONY,
|
AWARD_CEREMONY,
|
||||||
STATISTICS
|
STATISTICS,
|
||||||
|
MAIN,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SubState state;
|
||||||
|
|
||||||
|
private SingleButtonRightDialog continueButton;
|
||||||
|
|
||||||
public CeremonyView(MdgaApp app) {
|
public CeremonyView(MdgaApp app) {
|
||||||
super(app);
|
super(app);
|
||||||
|
|
||||||
|
continueButton = new SingleButtonRightDialog(app, "Weiter", () -> next());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnter() {
|
public void onEnter() {
|
||||||
switchToSubState(SubState.AWARD_CEREMONY);
|
state = SubState.AWARD_CEREMONY;
|
||||||
|
|
||||||
|
continueButton.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLeave() {}
|
public void onLeave() {
|
||||||
|
continueButton.hide();
|
||||||
|
}
|
||||||
|
|
||||||
private void awardCeremony() {
|
private void awardCeremony() {
|
||||||
node.detachAllChildren();
|
node.detachAllChildren();
|
||||||
@@ -37,19 +44,7 @@ private void awardCeremony() {
|
|||||||
Geometry background = createBackground("b1.png");
|
Geometry background = createBackground("b1.png");
|
||||||
node.attachChild(background);
|
node.attachChild(background);
|
||||||
|
|
||||||
Container container = new Container();
|
|
||||||
container.setLocalTranslation(300, app.getCamera().getHeight() - 100, 0);
|
|
||||||
|
|
||||||
container.addChild(new Label("GAME OVER"));
|
|
||||||
container.addChild(new Label("Spieler 1 auf Platz 1"));
|
|
||||||
container.addChild(new Label("Spieler 2 auf Platz 2"));
|
|
||||||
container.addChild(new Label("Spieler 3 auf Platz 3"));
|
|
||||||
|
|
||||||
MdgaButton button = new MdgaButton("Weiter", () -> switchToSubState(SubState.STATISTICS), new Vector3f(150, 200, 0));
|
|
||||||
button.setLocalTranslation(new Vector3f(app.getCamera().getWidth() - 200, 100, 0));
|
|
||||||
|
|
||||||
node.attachChild(button.getButton());
|
|
||||||
node.attachChild(container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void statistics() {
|
private void statistics() {
|
||||||
@@ -58,29 +53,34 @@ private void statistics() {
|
|||||||
Geometry background = createBackground("b2.png");
|
Geometry background = createBackground("b2.png");
|
||||||
node.attachChild(background);
|
node.attachChild(background);
|
||||||
|
|
||||||
Container container = new Container();
|
|
||||||
container.setLocalTranslation(200, app.getCamera().getHeight() - 100, 0);
|
|
||||||
|
|
||||||
container.addChild(new Label("Spielerstatistiken"));
|
|
||||||
container.addChild(new Label("Spieler 1: Punkte 100"));
|
|
||||||
container.addChild(new Label("Spieler 2: Punkte 80"));
|
|
||||||
container.addChild(new Label("Spieler 3: Punkte 60"));
|
|
||||||
|
|
||||||
MdgaButton button = new MdgaButton("Weiter", () -> app.enter(MdgaState.MAIN), new Vector3f(150, 200, 0));
|
|
||||||
button.setLocalTranslation(new Vector3f(app.getCamera().getWidth() - 200, 100, 0));
|
|
||||||
node.attachChild(button.getButton());
|
|
||||||
|
|
||||||
node.attachChild(container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switchToSubState(SubState subState) {
|
private void into() {
|
||||||
switch (subState) {
|
switch (state) {
|
||||||
case AWARD_CEREMONY:
|
case AWARD_CEREMONY:
|
||||||
awardCeremony();
|
awardCeremony();
|
||||||
break;
|
break;
|
||||||
case STATISTICS:
|
case STATISTICS:
|
||||||
statistics();
|
statistics();
|
||||||
break;
|
break;
|
||||||
|
case MAIN:
|
||||||
|
app.enter(MdgaState.MAIN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void next() {
|
||||||
|
switch (state) {
|
||||||
|
case AWARD_CEREMONY:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case STATISTICS:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case MAIN:
|
||||||
|
app.enter(MdgaState.MAIN);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
package pp.mdga.client.View;
|
package pp.mdga.client.View;
|
||||||
|
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.simsilica.lemur.Button;
|
|
||||||
import pp.mdga.client.Board.BoardHandler;
|
import pp.mdga.client.Board.BoardHandler;
|
||||||
import pp.mdga.client.Dialog.MdgaButton;
|
import pp.mdga.client.Dialog.SingleButtonRightDialog;
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
import pp.mdga.client.MdgaState;
|
import pp.mdga.client.MdgaState;
|
||||||
|
|
||||||
public class GameView extends MdgaView {
|
public class GameView extends MdgaView {
|
||||||
private BoardHandler boardHandler;
|
private BoardHandler boardHandler;
|
||||||
private MdgaButton button;
|
|
||||||
|
private SingleButtonRightDialog continueButton;
|
||||||
|
|
||||||
public GameView(MdgaApp app) {
|
public GameView(MdgaApp app) {
|
||||||
super(app);
|
super(app);
|
||||||
|
|
||||||
this.boardHandler = new BoardHandler(app);
|
this.boardHandler = new BoardHandler(app);
|
||||||
this.button = new MdgaButton("Weiter", () -> app.enter(MdgaState.CEREMONY), new Vector3f(150, 200, 0));
|
|
||||||
|
continueButton = new SingleButtonRightDialog(app, "Weiter", () -> app.enter(MdgaState.CEREMONY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
boardHandler.init();
|
boardHandler.init();
|
||||||
|
|
||||||
button.setLocalTranslation(new Vector3f(app.getCamera().getWidth() - 200, 100, 0));
|
continueButton.show();
|
||||||
app.getGuiNode().attachChild(button.getButton());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void leave() {
|
public void leave() {
|
||||||
app.getGuiNode().detachChild(button.getButton());
|
continueButton.hide();
|
||||||
|
|
||||||
boardHandler.shutdown();
|
boardHandler.shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +1,15 @@
|
|||||||
package pp.mdga.client.View;
|
package pp.mdga.client.View;
|
||||||
|
|
||||||
import com.jme3.input.InputManager;
|
|
||||||
import com.jme3.math.ColorRGBA;
|
|
||||||
import com.jme3.math.Vector3f;
|
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import pp.mdga.client.Dialog.SingleButtonRightDialog;
|
||||||
import com.simsilica.lemur.Button;
|
|
||||||
import com.simsilica.lemur.Container;
|
|
||||||
import com.simsilica.lemur.GuiGlobals;
|
|
||||||
import com.simsilica.lemur.style.ElementId;
|
|
||||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
|
|
||||||
import com.simsilica.lemur.style.Styles;
|
|
||||||
import pp.mdga.client.Dialog.HorizontalButtonDialog;
|
|
||||||
import pp.mdga.client.Dialog.MdgaButton;
|
|
||||||
import pp.mdga.client.Dialog.VerticalButtonDialog;
|
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
import pp.mdga.client.MdgaState;
|
import pp.mdga.client.MdgaState;
|
||||||
import pp.mdga.game.Color;
|
import pp.mdga.game.Color;
|
||||||
|
|
||||||
public class LobbyView extends MdgaView {
|
public class LobbyView extends MdgaView {
|
||||||
private Geometry background;
|
private Geometry background;
|
||||||
HorizontalButtonDialog dialog;
|
|
||||||
|
private SingleButtonRightDialog continueButton;
|
||||||
|
|
||||||
public LobbyView(MdgaApp app) {
|
public LobbyView(MdgaApp app) {
|
||||||
super(app);
|
super(app);
|
||||||
@@ -28,37 +17,17 @@ public LobbyView(MdgaApp app) {
|
|||||||
background = createBackground("lobby.png");
|
background = createBackground("lobby.png");
|
||||||
node.attachChild(background);
|
node.attachChild(background);
|
||||||
|
|
||||||
dialog = new HorizontalButtonDialog(app);
|
continueButton = new SingleButtonRightDialog(app, "Weiter", () -> app.enter(MdgaState.GAME));
|
||||||
|
|
||||||
float buttonWidth = 150;
|
|
||||||
float spacing = 80;
|
|
||||||
float startX = -((3 * buttonWidth + 2 * spacing) / 2);
|
|
||||||
float currentX = startX;
|
|
||||||
|
|
||||||
for (int i = 1; i <= 4; i++) {
|
|
||||||
Color color = Color.values()[i-1];
|
|
||||||
MdgaButton button = new MdgaButton(color.name(), () -> app.enter(MdgaState.GAME), new Vector3f(150, 200, 0));
|
|
||||||
|
|
||||||
button.setLocalTranslation(new Vector3f(currentX, 0, 0));
|
|
||||||
currentX += buttonWidth + spacing;
|
|
||||||
dialog.addButton(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog.setXOffset(-100);
|
|
||||||
|
|
||||||
//Button weiterButton = createButton("Weiter", new Vector3f(150, 50, 0), ColorRGBA.Blue, ColorRGBA.Cyan);
|
|
||||||
|
|
||||||
//weiterButton.setLocalTranslation(app.getCamera().getWidth() - 200, 100, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnter() {
|
public void onEnter() {
|
||||||
dialog.show();
|
continueButton.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLeave() {
|
public void onLeave() {
|
||||||
dialog.hide();
|
continueButton.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,11 @@
|
|||||||
package pp.mdga.client.View;
|
package pp.mdga.client.View;
|
||||||
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.shape.Quad;
|
|
||||||
import com.simsilica.lemur.*;
|
|
||||||
import pp.mdga.client.Dialog.MdgaButton;
|
|
||||||
import pp.mdga.client.Dialog.VerticalButtonDialog;
|
import pp.mdga.client.Dialog.VerticalButtonDialog;
|
||||||
import pp.mdga.client.MdgaApp;
|
import pp.mdga.client.MdgaApp;
|
||||||
import pp.mdga.client.MdgaState;
|
import pp.mdga.client.MdgaState;
|
||||||
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.shape.Quad;
|
|
||||||
import com.simsilica.lemur.Button;
|
|
||||||
import com.simsilica.lemur.Container;
|
|
||||||
import com.simsilica.lemur.Label;
|
|
||||||
|
|
||||||
import com.jme3.material.Material;
|
|
||||||
import com.jme3.scene.Geometry;
|
|
||||||
import com.jme3.scene.shape.Quad;
|
|
||||||
|
|
||||||
public class MainView extends MdgaView {
|
public class MainView extends MdgaView {
|
||||||
private Geometry background;
|
private Geometry background;
|
||||||
@@ -33,10 +19,10 @@ public MainView(MdgaApp app) {
|
|||||||
|
|
||||||
Vector3f size = new Vector3f(1, 1, 1);
|
Vector3f size = new Vector3f(1, 1, 1);
|
||||||
dialog = new VerticalButtonDialog(app);
|
dialog = new VerticalButtonDialog(app);
|
||||||
dialog.addButton(new MdgaButton("Spiel beitreten", () -> app.enter(MdgaState.LOBBY), size));
|
dialog.addButton("Spiel beitreten", () -> app.enter(MdgaState.LOBBY), size);
|
||||||
dialog.addButton(new MdgaButton("Spiel hosten", () -> app.enter(MdgaState.LOBBY), size));
|
dialog.addButton("Spiel hosten", () -> app.enter(MdgaState.LOBBY), size);
|
||||||
dialog.addButton(new MdgaButton("Einstellungen", () -> System.out.println("Einstellungen"), size));
|
dialog.addButton("Einstellungen", () -> System.out.println("Einstellungen"), size);
|
||||||
dialog.addButton(new MdgaButton("Spiel beenden", () -> app.stop(), size));
|
dialog.addButton("Spiel beenden", () -> app.stop(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user