add hover animations to buttons

This commit is contained in:
yugecin 2018-07-07 18:26:27 +02:00
parent 8ef1316b1f
commit 3463bfd9df
No known key found for this signature in database
GPG Key ID: 2C5AC035A7068E44
2 changed files with 99 additions and 18 deletions

View File

@ -54,6 +54,7 @@ import yugecin.opsudance.core.Constants;
import yugecin.opsudance.core.Entrypoint; import yugecin.opsudance.core.Entrypoint;
import yugecin.opsudance.core.state.BaseOpsuState; import yugecin.opsudance.core.state.BaseOpsuState;
import yugecin.opsudance.core.state.OpsuState; import yugecin.opsudance.core.state.OpsuState;
import yugecin.opsudance.ui.ImagePosition;
import static itdelatrisu.opsu.GameImage.*; import static itdelatrisu.opsu.GameImage.*;
import static itdelatrisu.opsu.ui.Colors.*; import static itdelatrisu.opsu.ui.Colors.*;
@ -99,8 +100,10 @@ public class MainMenu extends BaseOpsuState {
private int lastMouseY; private int lastMouseY;
private AnimatedValue logoClickScale; private AnimatedValue logoClickScale;
private AnimatedValue buttonsAnimation; private AnimatedValue buttonAnimation;
private int buttonsX; private int buttonsX;
private AnimatedValue[] buttonAnimations;
private ImagePosition[] buttonPositions;
/** Logo button alpha levels. */ /** Logo button alpha levels. */
private AnimatedValue logoButtonAlpha; private AnimatedValue logoButtonAlpha;
@ -158,7 +161,12 @@ public class MainMenu extends BaseOpsuState {
public MainMenu() { public MainMenu() {
this.nowPlayingPosition = new AnimatedValue(1000, 0, 0, OUT_QUART); this.nowPlayingPosition = new AnimatedValue(1000, 0, 0, OUT_QUART);
this.logoClickScale = new AnimatedValue(300, .9f, 1f, OUT_QUAD); this.logoClickScale = new AnimatedValue(300, .9f, 1f, OUT_QUAD);
this.buttonsAnimation = new AnimatedValue(1, 0f, 1f, OUT_QUAD); this.buttonAnimation = new AnimatedValue(1, 0f, 1f, OUT_QUAD);
this.buttonAnimations = new AnimatedValue[3];
for (int i = 0; i < 3; i++) {
this.buttonAnimations[i] = new AnimatedValue(1, 0f, 1f, LINEAR);
}
this.buttonPositions = new ImagePosition[3];
this.timeFormat = new SimpleDateFormat("HH:mm"); this.timeFormat = new SimpleDateFormat("HH:mm");
} }
@ -267,11 +275,21 @@ public class MainMenu extends BaseOpsuState {
// initialize star fountain // initialize star fountain
starFountain = new StarFountain(displayContainer.width, displayContainer.height); starFountain = new StarFountain(displayContainer.width, displayContainer.height);
// logo animations // logo & buttons
logoPositionOffsetX = 0.35f * MENU_LOGO.getImage().getHeight(); logoPositionOffsetX = 0.35f * MENU_LOGO.getImage().getHeight();
logoPosition = new AnimatedValue(1, 0, 1, AnimationEquation.OUT_QUAD); logoPosition = new AnimatedValue(1, 0, 1, AnimationEquation.OUT_QUAD);
logoButtonAlpha = new AnimatedValue(200, 0f, 1f, AnimationEquation.LINEAR); logoButtonAlpha = new AnimatedValue(200, 0f, 1f, AnimationEquation.LINEAR);
this.buttonsX = (displayContainer.width - MENU_OPTIONS.getImage().getWidth()) / 2; this.buttonsX = (displayContainer.width - MENU_OPTIONS.getImage().getWidth()) / 2;
this.buttonPositions[0] = new ImagePosition(MENU_PLAY.getImage());
this.buttonPositions[1] = new ImagePosition(MENU_OPTIONS.getImage());
this.buttonPositions[2] = new ImagePosition(MENU_EXIT.getImage());
final int basey = displayContainer.height / 2 - MENU_OPTIONS.getImage().getHeight() / 2;
final float halfradius = MENU_LOGO.getImage().getHeight() * 0.44498f / 2f;
for (int i = 0; i < 3; i++) {
this.buttonPositions[i].width = MENU_OPTIONS.getImage().getWidth();
this.buttonPositions[i].y = (int) (basey + (i - 1f) * halfradius);
this.buttonPositions[i].height = MENU_OPTIONS.getImage().getHeight();
}
} }
@Override @Override
@ -343,14 +361,13 @@ public class MainMenu extends BaseOpsuState {
} }
// draw buttons // draw buttons
final float buttonProgress = this.buttonsAnimation.getValue(); final float buttonProgress = this.buttonAnimation.getValue();
if (this.logoState != LogoState.DEFAULT && buttonProgress > 0f) { if (this.logoState != LogoState.DEFAULT && buttonProgress > 0f) {
final int btnwidth = MENU_OPTIONS.getImage().getWidth(); final int btnwidth = MENU_OPTIONS.getImage().getWidth();
final float btnhalfheight = MENU_OPTIONS.getImage().getHeight() / 2f; final float btnhalfheight = MENU_OPTIONS.getImage().getHeight() / 2f;
final int basey = displayContainer.height / 2; final int basey = displayContainer.height / 2;
final int x = (int) (this.buttonsX + btnwidth * 0.4f * buttonProgress); final int x = (int) (this.buttonsX + btnwidth * 0.3f * buttonProgress);
final float clipxstart = x - this.logo.getX(); final Color col = new Color(1f, 1f, 1f, buttonProgress);
Color col = new Color(1f, 1f, 1f, buttonProgress);
final Image[] imgs = { final Image[] imgs = {
MENU_PLAY.getImage(), MENU_PLAY.getImage(),
MENU_OPTIONS.getImage(), MENU_OPTIONS.getImage(),
@ -360,13 +377,18 @@ public class MainMenu extends BaseOpsuState {
final float halfradius = circleradius / 2f; final float halfradius = circleradius / 2f;
final float cr = circleradius * totalLogoScale; final float cr = circleradius * totalLogoScale;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
final float hoverprogress = this.buttonAnimations[i].getValue();
final int bx = x + (int) (btnwidth * 0.075f * hoverprogress);
this.buttonPositions[i].x = bx;
final float yoff = (i - 1f) * halfradius; final float yoff = (i - 1f) * halfradius;
final double cliptop = cr * cos(asin((yoff - btnhalfheight) / cr)); final double cliptop = cr * cos(asin((yoff - btnhalfheight) / cr));
final double clipbot = cr * cos(asin((yoff + btnhalfheight) / cr)); final double clipbot = cr * cos(asin((yoff + btnhalfheight) / cr));
final float clipxstart = bx - this.logo.getX();
final int ct = (int) (cliptop - clipxstart); final int ct = (int) (cliptop - clipxstart);
final int cb = (int) (clipbot - clipxstart); final int cb = (int) (clipbot - clipxstart);
final int y = (int) (basey + yoff); final int y = (int) (basey + yoff);
this.drawMenuButton(imgs[i], x, y, ct, cb, col); col.a = buttonProgress * 0.8f + hoverprogress * 0.2f;
this.drawMenuButton(imgs[i], bx, y, ct, cb, col);
} }
} }
@ -540,9 +562,9 @@ public class MainMenu extends BaseOpsuState {
case OPENING: case OPENING:
if (logoPosition.update(delta)) { if (logoPosition.update(delta)) {
logo.setX(centerX - logoPosition.getValue()); logo.setX(centerX - logoPosition.getValue());
this.buttonsAnimation.update(delta); this.buttonAnimation.update(delta);
} else { } else {
this.buttonsAnimation.setTime(this.buttonsAnimation.getDuration()); this.buttonAnimation.setTime(this.buttonAnimation.getDuration());
logoState = LogoState.OPEN; logoState = LogoState.OPEN;
logoTimer = 0; logoTimer = 0;
logoButtonAlpha.setTime(0); logoButtonAlpha.setTime(0);
@ -573,14 +595,32 @@ public class MainMenu extends BaseOpsuState {
} }
if (logoPosition.update(-delta)) { if (logoPosition.update(-delta)) {
logo.setX(centerX - logoPosition.getValue()); logo.setX(centerX - logoPosition.getValue());
this.buttonsAnimation.update(-delta); this.buttonAnimation.update(-delta);
} else { } else {
this.logoState = LogoState.DEFAULT; this.logoState = LogoState.DEFAULT;
this.buttonsAnimation.setTime(0); this.buttonAnimation.setTime(0);
} }
break; break;
} }
this.logoClickScale.update(delta); this.logoClickScale.update(delta);
for (int i = 0; i < 3; i++) {
final ImagePosition pos = this.buttonPositions[i];
final AnimatedValue anim = this.buttonAnimations[i];
if (pos.contains(mouseX, mouseY, 0.25f)) {
if (anim.getDuration() != 500) {
anim.change(500, 0f, 1f, OUT_ELASTIC);
continue;
}
anim.update(delta);
continue;
}
if (anim.getDuration() != 350) {
anim.change(350, 0f, 1f, IN_QUAD);
continue;
}
anim.update(-delta);
}
// tooltips // tooltips
if (musicPositionBarContains(mouseX, mouseY)) if (musicPositionBarContains(mouseX, mouseY))
@ -615,7 +655,7 @@ public class MainMenu extends BaseOpsuState {
nowPlayingPosition.setTime(0); nowPlayingPosition.setTime(0);
logoState = LogoState.DEFAULT; logoState = LogoState.DEFAULT;
this.logoClickScale.setTime(this.logoClickScale.getDuration()); this.logoClickScale.setTime(this.logoClickScale.getDuration());
this.buttonsAnimation.setTime(0); this.buttonAnimation.setTime(0);
UI.enter(); UI.enter();
if (!enterNotification) { if (!enterNotification) {
@ -786,7 +826,7 @@ public class MainMenu extends BaseOpsuState {
logocontains = true; logocontains = true;
this.logoClickScale.setTime(0); this.logoClickScale.setTime(0);
} }
if (logocontains || playButton.contains(x, y, 0.25f)) { if (logocontains || this.buttonPositions[0].contains(x, y, 0.25f)) {
SoundController.playSound(SoundEffect.MENUHIT); SoundController.playSound(SoundEffect.MENUHIT);
enterSongMenu(); enterSongMenu();
return true; return true;
@ -897,7 +937,7 @@ public class MainMenu extends BaseOpsuState {
} }
private void openLogo() { private void openLogo() {
buttonsAnimation.change(300, 0f, 1f, OUT_QUAD); buttonAnimation.change(300, 0f, 1f, OUT_QUAD);
logoPosition.change(300, 0, logoPositionOffsetX, OUT_CUBIC); logoPosition.change(300, 0, logoPositionOffsetX, OUT_CUBIC);
logoState = LogoState.OPENING; logoState = LogoState.OPENING;
playButton.getImage().setAlpha(0f); playButton.getImage().setAlpha(0f);
@ -905,7 +945,7 @@ public class MainMenu extends BaseOpsuState {
} }
private void closeLogo() { private void closeLogo() {
buttonsAnimation.change(500, 0f, 1f, OUT_QUAD); buttonAnimation.change(500, 0f, 1f, OUT_QUAD);
logoPosition.change(1800, 0, logoPositionOffsetX, IN_QUAD); logoPosition.change(1800, 0, logoPositionOffsetX, IN_QUAD);
logoState = LogoState.CLOSING; logoState = LogoState.CLOSING;
} }
@ -922,8 +962,8 @@ public class MainMenu extends BaseOpsuState {
final Texture t = img.getTexture(); final Texture t = img.getTexture();
t.bind(); t.bind();
final int width = t.getImageWidth(); final int width = img.getWidth();
final int height = t.getImageHeight(); final int height = img.getHeight();
final float twidth = t.getWidth(); final float twidth = t.getWidth();
final float theight = t.getHeight(); final float theight = t.getHeight();
y -= height / 2; y -= height / 2;

View File

@ -0,0 +1,41 @@
/*
* opsu!dance - fork of opsu! with cursordance auto
* Copyright (C) 2018 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.ui;
import java.awt.Rectangle;
import org.newdawn.slick.Image;
public class ImagePosition extends Rectangle {
private Image image;
public ImagePosition(Image image) {
this.image = image;
}
public boolean contains(int x, int y, float alphaThreshold) {
if (!super.contains(x, y)) {
return false;
}
final int ix = x - this.x;
final int iy = y - this.y;
return this.image.getAlphaAt(ix, iy) > alphaThreshold;
}
}