saner transition management

This commit is contained in:
yugecin 2017-05-05 00:44:51 +02:00
parent 0a0320e81a
commit 1ebf2c2dcb
9 changed files with 78 additions and 314 deletions

View File

@ -62,8 +62,6 @@ import yugecin.opsudance.core.events.EventBus;
import yugecin.opsudance.core.inject.Inject;
import yugecin.opsudance.core.inject.InstanceContainer;
import yugecin.opsudance.core.state.ComplexOpsuState;
import yugecin.opsudance.core.state.transitions.FadeInTransitionState;
import yugecin.opsudance.core.state.transitions.FadeOutTransitionState;
import yugecin.opsudance.events.BarNotificationEvent;
import yugecin.opsudance.events.BubbleNotificationEvent;
import yugecin.opsudance.objects.curves.FakeCombinedCurve;
@ -766,7 +764,7 @@ public class Game extends ComplexOpsuState {
// focus lost: go back to pause screen
else if (!Display.isActive()) {
displayContainer.switchStateNow(GamePauseMenu.class);
displayContainer.switchState(GamePauseMenu.class);
pausePulse = 0f;
}
@ -1050,7 +1048,7 @@ public class Game extends ComplexOpsuState {
if (MusicController.isPlaying() || isLeadIn()) {
pauseTime = trackPosition;
}
displayContainer.switchStateNow(GamePauseMenu.class);
displayContainer.switchStateInstantly(GamePauseMenu.class);
}
// drain health
@ -1077,7 +1075,7 @@ public class Game extends ComplexOpsuState {
rotations = new IdentityHashMap<>();
SoundController.playSound(SoundEffect.FAIL);
displayContainer.switchState(GamePauseMenu.class, FadeOutTransitionState.class, MUSIC_FADEOUT_TIME - LOSE_FADEOUT_TIME, FadeInTransitionState.class, 300);
displayContainer.switchState(GamePauseMenu.class, MUSIC_FADEOUT_TIME - LOSE_FADEOUT_TIME, 300);
}
}
}
@ -1158,7 +1156,7 @@ public class Game extends ComplexOpsuState {
if (MusicController.isPlaying() || isLeadIn()) {
pauseTime = trackPosition;
}
displayContainer.switchStateNow(GamePauseMenu.class);
displayContainer.switchStateInstantly(GamePauseMenu.class);
break;
case Input.KEY_SPACE:
// skip intro
@ -1311,7 +1309,7 @@ public class Game extends ComplexOpsuState {
if (MusicController.isPlaying() || isLeadIn()) {
pauseTime = trackPosition;
}
displayContainer.switchStateNow(GamePauseMenu.class);
displayContainer.switchStateInstantly(GamePauseMenu.class);
return true;
}

View File

@ -48,7 +48,6 @@ import yugecin.opsudance.core.state.OpsuState;
import yugecin.opsudance.core.state.specialstates.BarNotificationState;
import yugecin.opsudance.core.state.specialstates.BubbleNotificationState;
import yugecin.opsudance.core.state.specialstates.FpsRenderState;
import yugecin.opsudance.core.state.transitions.*;
import yugecin.opsudance.events.BubbleNotificationEvent;
import yugecin.opsudance.events.ResolutionOrSkinChangedEvent;
import yugecin.opsudance.options.Configuration;
@ -79,12 +78,6 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
private BarNotificationState barNotifState;
private BubbleNotificationState bubNotifState;
private TransitionState outTransitionState;
private TransitionState inTransitionState;
private final TransitionFinishedListener outTransitionListener;
private final TransitionFinishedListener inTransitionListener;
private OpsuState state;
public final DisplayMode nativeDisplayMode;
@ -123,31 +116,52 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
public final Cursor cursor;
public boolean drawCursor;
class Transition {
int in;
int out;
int total;
int progress = -1;
OpsuState nextstate;
Color OVERLAY = new Color(Color.black);
public void update() {
if (progress == -1) {
return;
}
progress += delta;
if (progress > out && nextstate != null) {
switchStateInstantly(nextstate);
nextstate = null;
}
if (progress > total) {
progress = -1;
}
}
public void render(Graphics graphics) {
if (progress == -1) {
return;
}
int relprogress = progress;
int reltotal = out;
if (progress > out) {
reltotal = in;
relprogress = total - progress;
}
OVERLAY.a = (float) relprogress / reltotal;
graphics.setColor(OVERLAY);
graphics.fillRect(0, 0, width, height);
}
}
private final Transition transition = new Transition();
@Inject
public DisplayContainer(InstanceContainer instanceContainer) {
this.instanceContainer = instanceContainer;
this.cursor = new Cursor();
drawCursor = true;
outTransitionListener = new TransitionFinishedListener() {
@Override
public void onFinish() {
state.leave();
outTransitionState.getApplicableState().leave();
state = inTransitionState;
state.enter();
inTransitionState.getApplicableState().enter();
}
};
inTransitionListener = new TransitionFinishedListener() {
@Override
public void onFinish() {
state.leave();
state = inTransitionState.getApplicableState();
}
};
EventBus.subscribe(ResolutionOrSkinChangedEvent.class, new EventListener<ResolutionOrSkinChangedEvent>() {
@Override
public void onEvent(ResolutionOrSkinChangedEvent event) {
@ -220,6 +234,7 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
mouseX = input.getMouseX();
mouseY = input.getMouseY();
transition.update();
fpsState.update();
state.update();
@ -258,6 +273,8 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
}
UI.drawTooltip(graphics);
transition.render(graphics);
timeSinceLastRender = 0;
Display.update(false);
@ -454,16 +471,6 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
public void writeErrorDump(StringWriter dump) {
dump.append("> DisplayContainer dump\n");
dump.append("OpenGL version: ").append(glVersion).append( "(").append(glVendor).append(")\n");
if (isTransitioning()) {
dump.append("doing a transition\n");
dump.append("using out transition ").append(outTransitionState.getClass().getSimpleName()).append('\n');
dump.append("using in transition ").append(inTransitionState.getClass().getSimpleName()).append('\n');
if (state == inTransitionState) {
dump.append("currently doing the in transition\n");
} else {
dump.append("currently doing the out transition\n");
}
}
state.writeErrorDump(dump);
}
@ -471,32 +478,37 @@ public class DisplayContainer implements ErrorDumpable, KeyListener, MouseListen
return state.isInstance(state);
}
public boolean isTransitioning() {
return state instanceof TransitionState;
}
public void switchState(Class<? extends OpsuState> newState) {
switchState(newState, FadeOutTransitionState.class, 200, FadeInTransitionState.class, 300);
}
public void switchStateNow(Class<? extends OpsuState> newState) {
switchState(newState, EmptyTransitionState.class, 0, FadeInTransitionState.class, 300);
}
public void switchStateInstantly(Class<? extends OpsuState> newState) {
state.leave();
state = instanceContainer.provide(newState);
state.enter();
}
public void switchState(Class<? extends OpsuState> newState, Class<? extends TransitionState> outTransition, int outTime, Class<? extends TransitionState> inTransition, int inTime) {
if (isTransitioning()) {
public void switchState(Class<? extends OpsuState> newState, int outtime, int intime) {
if (transition.progress != -1) {
return;
}
outTransitionState = instanceContainer.provide(outTransition).set(state, outTime, outTransitionListener);
inTransitionState = instanceContainer.provide(inTransition).set(instanceContainer.provide(newState), inTime, inTransitionListener);
state = outTransitionState;
state.enter();
// TODO remove this v
OpsuState _newstate = instanceContainer.provide(newState);
if (outtime == 0) {
switchStateInstantly(_newstate);
_newstate = null;
}
transition.nextstate = _newstate;
transition.total = transition.in = intime;
transition.out = outtime;
transition.total += outtime;
transition.progress = 0;
}
@Deprecated // TODO instcontainer
public void switchState(Class<? extends OpsuState> state) {
switchState(state, 200, 300);
}
@Deprecated // TODO instcontainer
public void switchStateInstantly(Class<? extends OpsuState> state) {
switchStateInstantly(instanceContainer.provide(state));
}
public void switchStateInstantly(OpsuState state) {
this.state.leave();
this.state = state;
this.state.enter();
}
/*

View File

@ -13,6 +13,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
*
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.inject;
@ -27,9 +28,6 @@ import yugecin.opsudance.core.DisplayContainer;
import yugecin.opsudance.core.state.specialstates.BarNotificationState;
import yugecin.opsudance.core.state.specialstates.BubbleNotificationState;
import yugecin.opsudance.core.state.specialstates.FpsRenderState;
import yugecin.opsudance.core.state.transitions.EmptyTransitionState;
import yugecin.opsudance.core.state.transitions.FadeInTransitionState;
import yugecin.opsudance.core.state.transitions.FadeOutTransitionState;
import yugecin.opsudance.core.errorhandling.ErrorHandler;
import yugecin.opsudance.options.Configuration;
import yugecin.opsudance.options.OptionsService;
@ -57,10 +55,6 @@ public class OpsuDanceInjector extends Injector {
bind(BarNotificationState.class).asEagerSingleton();
bind(BubbleNotificationState.class).asEagerSingleton();
bind(EmptyTransitionState.class).asEagerSingleton();
bind(FadeInTransitionState.class).asEagerSingleton();
bind(FadeOutTransitionState.class).asEagerSingleton();
bind(GameObjectRenderer.class).asEagerSingleton();
bind(Splash.class).asEagerSingleton();

View File

@ -1,27 +0,0 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state.transitions;
public class EmptyTransitionState extends TransitionState {
@Override
public void enter() {
finish();
}
}

View File

@ -1,27 +0,0 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state.transitions;
public class FadeInTransitionState extends FadeTransitionState {
@Override
protected float getMaskAlphaLevel(float fadeProgress) {
return 1f - fadeProgress;
}
}

View File

@ -1,27 +0,0 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state.transitions;
public class FadeOutTransitionState extends FadeTransitionState {
@Override
protected float getMaskAlphaLevel(float fadeProgress) {
return fadeProgress;
}
}

View File

@ -1,42 +0,0 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state.transitions;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
public abstract class FadeTransitionState extends TransitionState {
private final Color black;
public FadeTransitionState() {
super();
black = new Color(Color.black);
}
@Override
public void render(Graphics g) {
applicableState.render(g);
black.a = getMaskAlphaLevel((float) transitionTime / transitionTargetTime);
g.setColor(black);
g.fillRect(0, 0, displayContainer.width, displayContainer.height);
}
protected abstract float getMaskAlphaLevel(float fadeProgress);
}

View File

@ -1,24 +0,0 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state.transitions;
public interface TransitionFinishedListener {
void onFinish();
}

View File

@ -1,93 +0,0 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2017 yugecin
*
* opsu!dance is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* opsu!dance is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with opsu!dance. If not, see <http://www.gnu.org/licenses/>.
*/
package yugecin.opsudance.core.state.transitions;
import org.newdawn.slick.Graphics;
import yugecin.opsudance.core.state.BaseOpsuState;
import yugecin.opsudance.core.state.OpsuState;
import java.io.StringWriter;
public abstract class TransitionState extends BaseOpsuState {
protected OpsuState applicableState;
protected int transitionTargetTime;
protected int transitionTime;
private TransitionFinishedListener listener;
public final TransitionState set(OpsuState applicableState, int targetTime, TransitionFinishedListener listener) {
this.applicableState = applicableState;
this.transitionTargetTime = targetTime;
this.listener = listener;
return this;
}
public final OpsuState getApplicableState() {
return applicableState;
}
@Override
public void update() {
applicableState.update();
transitionTime += displayContainer.delta;
if (transitionTime >= transitionTargetTime) {
finish();
}
}
@Override
public void preRenderUpdate() {
applicableState.preRenderUpdate();
}
@Override
public void render(Graphics g) {
applicableState.render(g);
}
@Override
public void enter() {
super.enter();
transitionTime = 0;
}
protected final void finish() {
listener.onFinish();
}
@Override
public boolean onCloseRequest() {
return false;
}
@Override
public void writeErrorDump(StringWriter dump) {
dump.append("> TransitionState dump\n");
dump.append("progress: ").append(String.valueOf(transitionTime)).append("/").append(String.valueOf(transitionTargetTime)).append('\n');
dump.append("applicable state: ");
if (applicableState == null) {
dump.append("IS NULL");
return;
}
dump.append(applicableState.getClass().getSimpleName()).append('\n');
applicableState.writeErrorDump(dump);
}
}