From 80c66a98c3b66abd814d289597e8f0fe8a61190a Mon Sep 17 00:00:00 2001 From: Jeffrey Han Date: Thu, 19 Feb 2015 15:05:55 -0500 Subject: [PATCH] Added methods to check for transparent pixels in images. This is currently being used for the logo/play/exit buttons in the main menu. Also fixed bug where mod multipliers weren't being read. Signed-off-by: Jeffrey Han --- src/itdelatrisu/opsu/GameMod.java | 20 ++++----- src/itdelatrisu/opsu/MenuButton.java | 42 ++++++++++++++++++- src/itdelatrisu/opsu/states/ButtonMenu.java | 8 +--- src/itdelatrisu/opsu/states/MainMenu.java | 18 ++++---- src/org/newdawn/slick/Image.java | 32 +++++++++++++- src/org/newdawn/slick/Music.java | 2 +- .../slick/openal/AudioInputStream.java | 2 +- .../newdawn/slick/openal/Mp3InputStream.java | 2 +- .../slick/openal/OpenALStreamPlayer.java | 2 +- src/org/newdawn/slick/openal/SoundStore.java | 2 +- 10 files changed, 97 insertions(+), 33 deletions(-) diff --git a/src/itdelatrisu/opsu/GameMod.java b/src/itdelatrisu/opsu/GameMod.java index 037ed70b..323f244b 100644 --- a/src/itdelatrisu/opsu/GameMod.java +++ b/src/itdelatrisu/opsu/GameMod.java @@ -226,7 +226,7 @@ public enum GameMod { */ GameMod(Category category, int categoryIndex, GameImage image, String abbrev, int bit, int key, float multiplier, String description) { - this(category, categoryIndex, image, abbrev, bit, key, 1f, true, description); + this(category, categoryIndex, image, abbrev, bit, key, multiplier, true, description); } /** @@ -355,16 +355,6 @@ public enum GameMod { */ public boolean contains(float x, float y) { return button.contains(x, y); } - /** - * Returns the center x coordinate of the button. - */ - public float getButtonX() { return button.getX(); } - - /** - * Returns the center y coordinate of the button. - */ - public float getButtonY() { return button.getY(); } - /** * Resets the hover fields for the button. */ @@ -378,4 +368,12 @@ public enum GameMod { * @param y the y coordinate */ public void hoverUpdate(int delta, float x, float y) { button.hoverUpdate(delta, x, y); } + + /** + * Updates the scale of the button depending on whether or not the cursor + * is hovering over the button. + * @param delta the delta interval + * @param isHover true if the cursor is currently hovering over the button + */ + public void hoverUpdate(int delta, boolean isHover) { button.hoverUpdate(delta, isHover); } } diff --git a/src/itdelatrisu/opsu/MenuButton.java b/src/itdelatrisu/opsu/MenuButton.java index 8233d9d7..667c16b5 100644 --- a/src/itdelatrisu/opsu/MenuButton.java +++ b/src/itdelatrisu/opsu/MenuButton.java @@ -242,6 +242,24 @@ public class MenuButton { (cy > y - yRadius && cy < y + yRadius)); } + /** + * Returns true if the coordinates are within the button bounds and the + * pixel at the specified location has an alpha level above the given bound. + * @param cx the x coordinate + * @param cy the y coordinate + * @param alpha the alpha level lower bound + */ + public boolean contains(float cx, float cy, float alpha) { + Image image = this.img; + if (image == null) + image = anim.getCurrentFrame(); + float xRad = img.getWidth() / 2f, yRad = img.getHeight() / 2f; + + return ((cx > x - xRad && cx < x + xRad) && + (cy > y - yRad && cy < y + yRad) && + image.getAlphaAt((int) (cx - (x - xRad)), (int) (cy - (y - yRad))) > alpha); + } + /** * Resets the hover fields for the button. */ @@ -325,9 +343,31 @@ public class MenuButton { * @param cy the y coordinate */ public void hoverUpdate(int delta, float cx, float cy) { + hoverUpdate(delta, contains(cx, cy)); + } + + /** + * Processes a hover action depending on whether or not the cursor + * is hovering over the button, only if the specified pixel of the + * image has an alpha level above the given bound. + * @param delta the delta interval + * @param cx the x coordinate + * @param cy the y coordinate + * @param alpha the alpha level lower bound + */ + public void hoverUpdate(int delta, float cx, float cy, float alpha) { + hoverUpdate(delta, contains(cx, cy, alpha)); + } + + /** + * Processes a hover action depending on whether or not the cursor + * is hovering over the button. + * @param delta the delta interval + * @param isHover true if the cursor is currently hovering over the button + */ + public void hoverUpdate(int delta, boolean isHover) { if (hoverEffect == 0) return; - boolean isHover = contains(cx, cy); // scale the button if ((hoverEffect & EFFECT_EXPAND) > 0) { diff --git a/src/itdelatrisu/opsu/states/ButtonMenu.java b/src/itdelatrisu/opsu/states/ButtonMenu.java index cdc7b08e..b05e4fa9 100644 --- a/src/itdelatrisu/opsu/states/ButtonMenu.java +++ b/src/itdelatrisu/opsu/states/ButtonMenu.java @@ -179,12 +179,8 @@ public class ButtonMenu extends BasicGameState { @Override public void update(GameContainer container, int delta, int mouseX, int mouseY) { super.update(container, delta, mouseX, mouseY); - for (GameMod mod : GameMod.values()) { - if (mod.isActive()) - mod.hoverUpdate(delta, mod.getButtonX(), mod.getButtonY()); - else - mod.hoverUpdate(delta, -1, -1); - } + for (GameMod mod : GameMod.values()) + mod.hoverUpdate(delta, mod.isActive()); } @Override diff --git a/src/itdelatrisu/opsu/states/MainMenu.java b/src/itdelatrisu/opsu/states/MainMenu.java index 72b8a569..8a97fefe 100644 --- a/src/itdelatrisu/opsu/states/MainMenu.java +++ b/src/itdelatrisu/opsu/states/MainMenu.java @@ -267,9 +267,9 @@ public class MainMenu extends BasicGameState { Utils.updateCursor(delta); Utils.updateVolumeDisplay(delta); int mouseX = input.getMouseX(), mouseY = input.getMouseY(); - logo.hoverUpdate(delta, mouseX, mouseY); - playButton.hoverUpdate(delta, mouseX, mouseY); - exitButton.hoverUpdate(delta, mouseX, mouseY); + logo.hoverUpdate(delta, mouseX, mouseY, 0.25f); + playButton.hoverUpdate(delta, mouseX, mouseY, 0.25f); + exitButton.hoverUpdate(delta, mouseX, mouseY, 0.25f); if (repoButton != null) repoButton.hoverUpdate(delta, mouseX, mouseY); downloadsButton.hoverUpdate(delta, mouseX, mouseY); @@ -337,11 +337,11 @@ public class MainMenu extends BasicGameState { throws SlickException { // reset button hover states if mouse is not currently hovering over the button int mouseX = input.getMouseX(), mouseY = input.getMouseY(); - if (!logo.contains(mouseX, mouseY)) + if (!logo.contains(mouseX, mouseY, 0.25f)) logo.resetHover(); - if (!playButton.contains(mouseX, mouseY)) + if (!playButton.contains(mouseX, mouseY, 0.25f)) playButton.resetHover(); - if (!exitButton.contains(mouseX, mouseY)) + if (!exitButton.contains(mouseX, mouseY, 0.25f)) exitButton.resetHover(); if (!musicPlay.contains(mouseX, mouseY)) musicPlay.resetHover(); @@ -418,7 +418,7 @@ public class MainMenu extends BasicGameState { // start moving logo (if clicked) else if (!logoClicked) { - if (logo.contains(x, y)) { + if (logo.contains(x, y, 0.25f)) { logoClicked = true; logoTimer = 0; playButton.getImage().setAlpha(0f); @@ -429,10 +429,10 @@ public class MainMenu extends BasicGameState { // other button actions (if visible) else if (logoClicked) { - if (logo.contains(x, y) || playButton.contains(x, y)) { + if (logo.contains(x, y, 0.25f) || playButton.contains(x, y, 0.25f)) { SoundController.playSound(SoundEffect.MENUHIT); game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black)); - } else if (exitButton.contains(x, y)) + } else if (exitButton.contains(x, y, 0.25f)) container.exit(); } } diff --git a/src/org/newdawn/slick/Image.java b/src/org/newdawn/slick/Image.java index fe0fb45f..05027b9b 100644 --- a/src/org/newdawn/slick/Image.java +++ b/src/org/newdawn/slick/Image.java @@ -24,7 +24,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. -*/ + */ package org.newdawn.slick; @@ -1407,6 +1407,36 @@ public class Image implements Renderable { translate(pixelData[offset+2])); } } + + /** + * Get the alpha value of a pixel at a specified location in this image, + * or 1f if the image does not support transparency. + * + * @param x The x coordinate of the pixel + * @param y The y coordinate of the pixel + * @return The alpha level of the pixel at the specified location + */ + public float getAlphaAt(int x, int y) { + if (!texture.hasAlpha()) + return 1f; + + if (pixelData == null) + pixelData = texture.getTextureData(); + + // scale coordinates based on the image scale + x = x * texture.getImageWidth() / width; + y = y * texture.getImageHeight() / height; + + int xo = (int) (textureOffsetX * texture.getTextureWidth()); + int yo = (int) (textureOffsetY * texture.getTextureHeight()); + + x = (textureWidth < 0) ? xo - x : xo + x; + y = (textureHeight < 0) ? yo - y : yo + y; + + int offset = x + (y * texture.getTextureWidth()); + offset *= 4; + return (offset + 3 >= pixelData.length) ? 1f : translate(pixelData[offset + 3]) / 255f; + } /** * Check if this image has been destroyed diff --git a/src/org/newdawn/slick/Music.java b/src/org/newdawn/slick/Music.java index c3da9aeb..e8929a0e 100644 --- a/src/org/newdawn/slick/Music.java +++ b/src/org/newdawn/slick/Music.java @@ -24,7 +24,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. -*/ + */ package org.newdawn.slick; diff --git a/src/org/newdawn/slick/openal/AudioInputStream.java b/src/org/newdawn/slick/openal/AudioInputStream.java index b5947e79..0f73fdcc 100644 --- a/src/org/newdawn/slick/openal/AudioInputStream.java +++ b/src/org/newdawn/slick/openal/AudioInputStream.java @@ -24,7 +24,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. -*/ + */ package org.newdawn.slick.openal; diff --git a/src/org/newdawn/slick/openal/Mp3InputStream.java b/src/org/newdawn/slick/openal/Mp3InputStream.java index 3ed4a800..8d8cb6df 100644 --- a/src/org/newdawn/slick/openal/Mp3InputStream.java +++ b/src/org/newdawn/slick/openal/Mp3InputStream.java @@ -24,7 +24,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. -*/ + */ package org.newdawn.slick.openal; diff --git a/src/org/newdawn/slick/openal/OpenALStreamPlayer.java b/src/org/newdawn/slick/openal/OpenALStreamPlayer.java index 2a7417f7..0ce42e6d 100644 --- a/src/org/newdawn/slick/openal/OpenALStreamPlayer.java +++ b/src/org/newdawn/slick/openal/OpenALStreamPlayer.java @@ -24,7 +24,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. -*/ + */ package org.newdawn.slick.openal; diff --git a/src/org/newdawn/slick/openal/SoundStore.java b/src/org/newdawn/slick/openal/SoundStore.java index 71c5319a..a49a0e79 100644 --- a/src/org/newdawn/slick/openal/SoundStore.java +++ b/src/org/newdawn/slick/openal/SoundStore.java @@ -24,7 +24,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. -*/ + */ package org.newdawn.slick.openal;