Skip to content

Commit

Permalink
Merge pull request #307 from yugecin/keyoverlay
Browse files Browse the repository at this point in the history
Key overlay
  • Loading branch information
itdelatrisu authored Jul 1, 2017
2 parents d6284a4 + 2addaa6 commit da5a366
Show file tree
Hide file tree
Showing 9 changed files with 190 additions and 0 deletions.
Binary file added res/inputoverlay-background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/inputoverlay-key.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/itdelatrisu/opsu/GameImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public enum GameImage {
CURSOR_TRAIL ("cursortrail", "png"),

// Game
INPUTOVERLAY_KEY ("inputoverlay-key", "png"),
INPUTOVERLAY_BACKGROUND ("inputoverlay-background", "png"),
SECTION_PASS ("section-pass", "png"),
SECTION_FAIL ("section-fail", "png"),
WARNINGARROW ("play-warningarrow", "png"),
Expand Down
1 change: 1 addition & 0 deletions src/itdelatrisu/opsu/options/OptionGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class OptionGroup {
GameOption.BACKGROUND_DIM,
GameOption.FORCE_DEFAULT_PLAYFIELD,
GameOption.SHOW_HIT_ERROR_BAR,
GameOption.ALWAYS_SHOW_KEY_OVERLAY,
}),
new OptionGroup("Audio", GameImage.MENU_NAV_AUDIO),
new OptionGroup("VOLUME", new GameOption[] {
Expand Down
7 changes: 7 additions & 0 deletions src/itdelatrisu/opsu/options/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ public void setValue(int value) {
SHOW_PERFECT_HIT ("Perfect hits", "PerfectHit", "Shows perfect hit result bursts (300s, slider ticks).", true),
SHOW_FOLLOW_POINTS ("Follow points", "FollowPoints", "Shows follow points between hit objects.", true),
SHOW_HIT_ERROR_BAR ("Hit error bar", "ScoreMeter", "Shows precisely how accurate you were with each hit.", false),
ALWAYS_SHOW_KEY_OVERLAY ("Always show key overlay", "KeyOverlay", "Show the key overlay when playing instead of only on replays.", false),
LOAD_HD_IMAGES ("Load HD images", "LoadHDImages", String.format("Loads HD (%s) images when available.\nIncreases memory usage and loading times.", GameImage.HD_SUFFIX), true),
FIXED_CS ("Fixed CS", "FixedCS", "Determines the size of circles and sliders.", 0, 0, 100) {
@Override
Expand Down Expand Up @@ -1290,6 +1291,12 @@ public static boolean setCheckpoint(int time) {
*/
public static boolean isHitErrorBarEnabled() { return GameOption.SHOW_HIT_ERROR_BAR.getBooleanValue(); }

/**
* Returns whether or not to show the key overlay on non-replay game sessions.
* @return true if enabled
*/
public static boolean alwaysShowKeyOverlay() { return GameOption.ALWAYS_SHOW_KEY_OVERLAY.getBooleanValue(); }

/**
* Returns whether or not to load HD (@2x) images.
* @return true if HD images are enabled, false if only SD images should be loaded
Expand Down
11 changes: 11 additions & 0 deletions src/itdelatrisu/opsu/skins/Skin.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ public class Skin {
/** The default color of the stars that fall from the cursor during breaks. */
private static final Color DEFAULT_STAR_BREAK_ADDITIVE = new Color(255, 182, 193);

/** The default color of the text on the input overlay. */
private static final Color DEFAULT_INPUT_OVERLAY_TEXT = new Color(0, 0, 0);

/** The skin directory. */
private File dir;

Expand Down Expand Up @@ -165,6 +168,9 @@ public class Skin {
/** The color of the stars that fall from the cursor (star2 sprite) in breaks. */
protected Color starBreakAdditive = DEFAULT_STAR_BREAK_ADDITIVE;

/** The color of the text on the input overlay. */
protected Color inputOverlayText = DEFAULT_INPUT_OVERLAY_TEXT;

/**
* [Fonts]
*/
Expand Down Expand Up @@ -344,6 +350,11 @@ public Skin(File dir) {
*/
public Color getStarBreakAdditiveColor() { return starBreakAdditive; }

/**
* Returns the color of the text on the input overlay.
*/
public Color getInputOverlayText() { return inputOverlayText; }

/**
* Returns the prefix for the hit circle font sprites.
*/
Expand Down
3 changes: 3 additions & 0 deletions src/itdelatrisu/opsu/skins/SkinLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ public static Skin loadSkin(File dir) {
case "StarBreakAdditive":
skin.starBreakAdditive = color;
break;
case "InputOverlayText":
skin.inputOverlayText = color;
break;
default:
break;
}
Expand Down
42 changes: 42 additions & 0 deletions src/itdelatrisu/opsu/states/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import itdelatrisu.opsu.replay.ReplayFrame;
import itdelatrisu.opsu.ui.Colors;
import itdelatrisu.opsu.ui.Fonts;
import itdelatrisu.opsu.ui.InputOverlayKey;
import itdelatrisu.opsu.ui.MenuButton;
import itdelatrisu.opsu.ui.StarStream;
import itdelatrisu.opsu.ui.UI;
Expand Down Expand Up @@ -325,6 +326,9 @@ public enum PlayState {
/** The single merged slider (if enabled). */
private FakeCombinedCurve mergedSlider;

/** The objects holding data for the input overlay. */
private InputOverlayKey[] inputOverlayKeys;

/** Music position bar background colors. */
private static final Color
MUSICBAR_NORMAL = new Color(12, 9, 10, 0.25f),
Expand All @@ -339,6 +343,12 @@ public enum PlayState {

public Game(int state) {
this.state = state;
inputOverlayKeys = new InputOverlayKey[] {
new InputOverlayKey("K1", ReplayFrame.KEY_K1, 0, new Color(248, 216, 0)),
new InputOverlayKey("K2", ReplayFrame.KEY_K2, 0, new Color(248, 216, 0)),
new InputOverlayKey("M1", ReplayFrame.KEY_M1, 4, new Color(248, 0, 158)),
new InputOverlayKey("M2", ReplayFrame.KEY_M2, 8, new Color(248, 0, 158)),
};
}

@Override
Expand Down Expand Up @@ -725,6 +735,23 @@ else if (breakIndex > 1) {
}
}

// key overlay
if (isReplay || Options.alwaysShowKeyOverlay()) {
final float BTNSIZE = container.getHeight() * 0.0615f;
int x = (int) (container.getWidth() - BTNSIZE / 2f);
int y = (int) (container.getHeight() / 2f - BTNSIZE - BTNSIZE / 2f);
Image bg = GameImage.INPUTOVERLAY_BACKGROUND.getImage();
bg = bg.getScaledCopy(BTNSIZE * 4.3f / bg.getWidth());
bg.rotate(90f);
bg.drawCentered(container.getWidth() - bg.getHeight() / 2, container.getHeight() / 2);
Image keyimg =
GameImage.INPUTOVERLAY_KEY.getImage().getScaledCopy((int) BTNSIZE, (int) BTNSIZE);
for (int i = 0; i < 4; i++) {
inputOverlayKeys[i].render(g, x, y, keyimg);
y += BTNSIZE;
}
}

// returning from pause screen
if (pauseTime > -1 && pausedMousePosition != null) {
// darken the screen
Expand Down Expand Up @@ -904,6 +931,16 @@ else if (!gameFinished) {
}
}

// update key overlay
if (isReplay || Options.alwaysShowKeyOverlay()) {
for (int i = 0; i < 4; i++) {
int keys = autoMousePressed ? 1 : lastKeysPressed;
boolean countpresses = breakTime == 0 && !isLeadIn() &&
trackPosition > firstObjectTime;
inputOverlayKeys[i].update(keys, countpresses, delta);
}
}

lastTrackPosition = trackPosition;

// update in-game scoreboard
Expand Down Expand Up @@ -1443,6 +1480,11 @@ public void enter(GameContainer container, StateBasedGame game)

// restart the game
if (playState != PlayState.NORMAL) {
// reset key states
lastKeysPressed = 0;
for (int i = 0; i < 4; i++)
inputOverlayKeys[i].reset();

// update play stats
if (playState == PlayState.FIRST_LOAD) {
beatmap.incrementPlayCounter();
Expand Down
124 changes: 124 additions & 0 deletions src/itdelatrisu/opsu/ui/InputOverlayKey.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* opsu! - an open-source osu! client
* Copyright (C) 2014-2017 Jeffrey Han
*
* opsu! 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! 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!. If not, see <http://www.gnu.org/licenses/>.
*/

package itdelatrisu.opsu.ui;

import itdelatrisu.opsu.options.Options;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;

public class InputOverlayKey {
/** Time, in ms, of the shrink/expand key animation. */
private static final int ANIMTIME = 100;
/** The final scale of the input keys when the key is pressed. */
private static final float ACTIVESCALE = 0.75f;

/** The bits in the keystate that corresponds to this key. */
private final int targetKey;
/** The bits that may not be set for this key to be down. */
private final int ignoredKey;
/** The color of the button when the key is down. */
private final Color activeColor;
/** The initial text of the button. */
private final String initialText;

/** How long the key has been down, used for the scale animation. */
private int downtime;
/** Whether or not this key is currently down */
private boolean down;
/** The text that will be displayed on this button.*/
private String text;
/** The amount of times this key has been pressed. */
private int presses;

/**
* @param initialText The initial text of the button
* @param targetKey The bits in the keystate that corresponds to this key
* @param ignoredKey The bits that may not be set for this key to be down
* @param activeColor The color of the button when the key is down
*/
public InputOverlayKey(String initialText, int targetKey, int ignoredKey, Color activeColor) {
this.initialText = initialText;
this.targetKey = targetKey;
this.ignoredKey = ignoredKey;
this.activeColor = activeColor;
}

/**
* Resets all data
*/
public void reset() {
down = false;
downtime = 0;
presses = 0;
text = initialText;
}

/**
* Update this key
* @param keystates the current key states
* @param delta framedelta
*/
public void update(int keystates, boolean countkeys, int delta) {
boolean wasdown = down;
down = (keystates & targetKey) == targetKey && (keystates & ignoredKey) == 0;
if (!wasdown && down) {
if (countkeys)
presses++;
text = Integer.toString(presses);
}
if (down && downtime < ANIMTIME)
downtime = Math.min(ANIMTIME, downtime + delta);
else if (!down && downtime > 0)
downtime = Math.max(0, downtime - delta);
}

/**
* Render this key
* @param g graphics context
* @param x x position
* @param y y position
* @param baseImage the key image
*/
public void render(Graphics g, int x, int y, Image baseImage) {
g.pushTransform();
float scale = 1f;
if (downtime > 0) {
float progress = downtime / (float) ANIMTIME;
scale -= (1f - ACTIVESCALE) * progress;
g.scale(scale, scale);
x /= scale;
y /= scale;
}
baseImage.drawCentered(x, y, down ? activeColor : Color.white);
x -= Fonts.MEDIUMBOLD.getWidth(text) / 2;
y -= Fonts.MEDIUMBOLD.getLineHeight() / 2;
/*
// shadow
g.pushTransform();
g.scale (1.1f, 1.1f);
float shadowx = x / 1.1f - Fonts.MEDIUMBOLD.getWidth(text) * 0.05f;
float shadowy = y / 1.1f - Fonts.MEDIUMBOLD.getLineHeight() * 0.05f;
Fonts.MEDIUMBOLD.drawString(shadowx, shadowy, text, Color.black);
g.popTransform();
*/
Fonts.MEDIUMBOLD.drawString(x, y, text, Options.getSkin().getInputOverlayText());
g.popTransform();
}
}

0 comments on commit da5a366

Please sign in to comment.