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 <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-02-19 15:05:55 -05:00
parent ab1a377be0
commit 80c66a98c3
10 changed files with 97 additions and 33 deletions

View File

@ -226,7 +226,7 @@ public enum GameMod {
*/ */
GameMod(Category category, int categoryIndex, GameImage image, String abbrev, GameMod(Category category, int categoryIndex, GameImage image, String abbrev,
int bit, int key, float multiplier, String description) { 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); } 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. * Resets the hover fields for the button.
*/ */
@ -378,4 +368,12 @@ public enum GameMod {
* @param y the y coordinate * @param y the y coordinate
*/ */
public void hoverUpdate(int delta, float x, float y) { button.hoverUpdate(delta, x, y); } 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); }
} }

View File

@ -242,6 +242,24 @@ public class MenuButton {
(cy > y - yRadius && cy < y + yRadius)); (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. * Resets the hover fields for the button.
*/ */
@ -325,9 +343,31 @@ public class MenuButton {
* @param cy the y coordinate * @param cy the y coordinate
*/ */
public void hoverUpdate(int delta, float cx, float cy) { 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) if (hoverEffect == 0)
return; return;
boolean isHover = contains(cx, cy);
// scale the button // scale the button
if ((hoverEffect & EFFECT_EXPAND) > 0) { if ((hoverEffect & EFFECT_EXPAND) > 0) {

View File

@ -179,12 +179,8 @@ public class ButtonMenu extends BasicGameState {
@Override @Override
public void update(GameContainer container, int delta, int mouseX, int mouseY) { public void update(GameContainer container, int delta, int mouseX, int mouseY) {
super.update(container, delta, mouseX, mouseY); super.update(container, delta, mouseX, mouseY);
for (GameMod mod : GameMod.values()) { for (GameMod mod : GameMod.values())
if (mod.isActive()) mod.hoverUpdate(delta, mod.isActive());
mod.hoverUpdate(delta, mod.getButtonX(), mod.getButtonY());
else
mod.hoverUpdate(delta, -1, -1);
}
} }
@Override @Override

View File

@ -267,9 +267,9 @@ public class MainMenu extends BasicGameState {
Utils.updateCursor(delta); Utils.updateCursor(delta);
Utils.updateVolumeDisplay(delta); Utils.updateVolumeDisplay(delta);
int mouseX = input.getMouseX(), mouseY = input.getMouseY(); int mouseX = input.getMouseX(), mouseY = input.getMouseY();
logo.hoverUpdate(delta, mouseX, mouseY); logo.hoverUpdate(delta, mouseX, mouseY, 0.25f);
playButton.hoverUpdate(delta, mouseX, mouseY); playButton.hoverUpdate(delta, mouseX, mouseY, 0.25f);
exitButton.hoverUpdate(delta, mouseX, mouseY); exitButton.hoverUpdate(delta, mouseX, mouseY, 0.25f);
if (repoButton != null) if (repoButton != null)
repoButton.hoverUpdate(delta, mouseX, mouseY); repoButton.hoverUpdate(delta, mouseX, mouseY);
downloadsButton.hoverUpdate(delta, mouseX, mouseY); downloadsButton.hoverUpdate(delta, mouseX, mouseY);
@ -337,11 +337,11 @@ public class MainMenu extends BasicGameState {
throws SlickException { throws SlickException {
// reset button hover states if mouse is not currently hovering over the button // reset button hover states if mouse is not currently hovering over the button
int mouseX = input.getMouseX(), mouseY = input.getMouseY(); int mouseX = input.getMouseX(), mouseY = input.getMouseY();
if (!logo.contains(mouseX, mouseY)) if (!logo.contains(mouseX, mouseY, 0.25f))
logo.resetHover(); logo.resetHover();
if (!playButton.contains(mouseX, mouseY)) if (!playButton.contains(mouseX, mouseY, 0.25f))
playButton.resetHover(); playButton.resetHover();
if (!exitButton.contains(mouseX, mouseY)) if (!exitButton.contains(mouseX, mouseY, 0.25f))
exitButton.resetHover(); exitButton.resetHover();
if (!musicPlay.contains(mouseX, mouseY)) if (!musicPlay.contains(mouseX, mouseY))
musicPlay.resetHover(); musicPlay.resetHover();
@ -418,7 +418,7 @@ public class MainMenu extends BasicGameState {
// start moving logo (if clicked) // start moving logo (if clicked)
else if (!logoClicked) { else if (!logoClicked) {
if (logo.contains(x, y)) { if (logo.contains(x, y, 0.25f)) {
logoClicked = true; logoClicked = true;
logoTimer = 0; logoTimer = 0;
playButton.getImage().setAlpha(0f); playButton.getImage().setAlpha(0f);
@ -429,10 +429,10 @@ public class MainMenu extends BasicGameState {
// other button actions (if visible) // other button actions (if visible)
else if (logoClicked) { 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); SoundController.playSound(SoundEffect.MENUHIT);
game.enterState(Opsu.STATE_SONGMENU, new FadeOutTransition(Color.black), new FadeInTransition(Color.black)); 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(); container.exit();
} }
} }

View File

@ -24,7 +24,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.newdawn.slick; package org.newdawn.slick;
@ -1408,6 +1408,36 @@ public class Image implements Renderable {
} }
} }
/**
* 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 * Check if this image has been destroyed
* *

View File

@ -24,7 +24,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.newdawn.slick; package org.newdawn.slick;

View File

@ -24,7 +24,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.newdawn.slick.openal; package org.newdawn.slick.openal;

View File

@ -24,7 +24,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.newdawn.slick.openal; package org.newdawn.slick.openal;

View File

@ -24,7 +24,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.newdawn.slick.openal; package org.newdawn.slick.openal;

View File

@ -24,7 +24,7 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * 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 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
package org.newdawn.slick.openal; package org.newdawn.slick.openal;