package abdclient.gui.hud;
import org.lwjgl.input.Keyboard;
import org.newdawn.slick.opengl.renderer.Renderer;
import com.google.common.base.Predicate;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Optional;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
public class HUDConfigScreen extends GuiScreen {
private final HashMap<IRenderer, ScreenPosition> renderers = new HashMap<IRenderer, ScreenPosition>();
private Optional<IRenderer> selectedRenderer = Optional.empty();
private int prevX, prevY;
public HUDConfigScreen(HUDManager api) {
Collection<IRenderer> registeredRenderers = api.getRegisteredRenderers();
for(IRenderer ren : registeredRenderers) {
if(!ren.isEnabled()) {
continue;
}
ScreenPosition pos = ren.load();
if(pos == null) {
pos = ScreenPosition.fromRelativePosition(0.5, 0.5);
}
adjustBounds(ren, pos);
this.renderers.put(ren, pos);
}
}
#Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
super.drawDefaultBackground();
final float zBackup = this.zLevel;
this.zLevel =200;
this.drawHollowRect(0, 0, this.width - 1, this.height - 1, 0xFF0000FF);
for(IRenderer renderer : renderers.keySet()) {
ScreenPosition pos = renderers.get(renderer);
renderer.renderDummy(pos);
this.drawHollowRect(pos.getAbsoluteX(), pos.getAbsoluteY(), renderer.getWidth(), renderer.getHeight(), 0xFF00FFFF);
}
this.zLevel = zBackup;
}
private void drawHollowRect(int x, int y, int w, int h, int color) {
this.drawHorizontalLine(x, x + w, y, color);
this.drawHorizontalLine(x, x + w, y + h, color);
this.drawVerticalLine(x, y + h, y, color);
this.drawVerticalLine(x + w, y + h, y, color);
}
#Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
if(keyCode == Keyboard.KEY_ESCAPE) {
renderers.entrySet().forEach((entry) ->{
entry.getKey().save(entry.getValue());
});
this.mc.displayGuiScreen(null);
}
}
#Override
protected void mouseClickMove(int x, int y, int bButton, long time) {
if(selectedRenderer.isPresent()) {
moveSelectedRendererBy(x - prevX, y - prevY);
}
this.prevX = x;
this.prevY = y;
}
private void moveSelectedRendererBy(int offsetX, int offsetY) {
IRenderer renderer = selectedRenderer.get();
ScreenPosition pos = renderers.get(renderer);
pos.setAbsolute(pos.getAbsoluteX() + offsetX, pos.getAbsoluteY() + offsetY);
adjustBounds(renderer, pos);
}
#Override
public void onGuiClosed() {
for(IRenderer renderer : renderers.keySet()) {
renderer.save(renderers.get(renderer));
}
}
#Override
public boolean doesGuiPauseGame() {
return true;
}
private void adjustBounds(IRenderer renderer, ScreenPosition pos) {
ScaledResolution res = new ScaledResolution(Minecraft.getMinecraft());
int screenWidth = res.getScaledWidth();
int screenHeight = res.getScaledHeight();
int absoluteX = Math.max(0, Math.min(pos.getAbsoluteX(), Math.max(screenWidth - renderer.getWidth(),0)));
int absoluteY = Math.max(0, Math.min(pos.getAbsoluteY(), Math.max(screenHeight - renderer.getHeight(),0)));
pos.setAbsolute(absoluteX, absoluteY);
}
#Override
protected void mouseClicked(int x, int y, int button) throws IOException {
this.prevX = x;
this.prevY = y;
loadMouseOver(x, y);
}
private void loadMouseOver(int x, int y) {
this.selectedRenderer = renderers.keySet().stream().filter(new MouseOverFinder(x, y)).findFirst();
}
private class MouseOverFinder implements Predicate<IRenderer> {
private int mouseX, mouseY;
public MouseOverFinder(int x, int y) {
this.mouseX = x;
this.mouseY = y;
}
public boolean test(IRenderer renderer) {
ScreenPosition pos = renderers.get(renderer);
int absoluteX = pos.getAbsoluteX();
int absoluteY = pos.getAbsoluteY();
if(mouseX >= absoluteX && mouseX <= absoluteX + renderer.getWidth()) {
if(mouseY >= absoluteY && mouseY <= absoluteY + renderer.getHeight()) {
return true;
}
}
return false;
}
#Override
public boolean apply(IRenderer arg0) {
// TODO Auto-generated method stub
return false;
}
}
}
The main issue is on line 146
Sorry if the format is bad, I just have little experence with Java and StackOverflow
The game would boot as normal, open the gui as normal but the moment I clicked my game (with my mouse) to interact with the draggable GUI it would instantly crash. These are the logs; This is a minecraft 1.8.9 PVP client containing optifine. I am making it on eclipse IDE.
Time: 2023-02-07, 11:10 p.m.
Description: Updating screen events
java.lang.ClassCastException: class abdclient.gui.hud.HUDConfigScreen$MouseOverFinder cannot be cast to class java.util.function.Predicate (abdclient.gui.hud.HUDConfigScreen$MouseOverFinder is in unnamed module of loader 'app'; java.util.function.Predicate is in module java.base of loader 'bootstrap')
at abdclient.gui.hud.HUDConfigScreen.loadMouseOver(HUDConfigScreen.java:146)
at abdclient.gui.hud.HUDConfigScreen.mouseClicked(HUDConfigScreen.java:142)
at net.minecraft.client.gui.GuiScreen.handleMouseInput(GuiScreen.java:530)
at net.minecraft.client.gui.GuiScreen.handleInput(GuiScreen.java:502)
at net.minecraft.client.Minecraft.runTick(Minecraft.java:1666)
at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1025)
at net.minecraft.client.Minecraft.run(Minecraft.java:354)
at net.minecraft.client.main.Main.main(Main.java:113)
at Start.main(Start.java:11)
A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------
-- Head --
Stacktrace:
at abdclient.gui.hud.HUDConfigScreen.loadMouseOver(HUDConfigScreen.java:146)
at abdclient.gui.hud.HUDConfigScreen.mouseClicked(HUDConfigScreen.java:142)
at net.minecraft.client.gui.GuiScreen.handleMouseInput(GuiScreen.java:530)
at net.minecraft.client.gui.GuiScreen.handleInput(GuiScreen.java:502)
-- Affected screen --
Details:
Screen name: abdclient.gui.hud.HUDConfigScreen
Related
So, i coding a minecraft client from quickdaffy tutorial (click gui is in 7ep)..
Another So, if i click on "testMod" button, nothing happends
Link for this tutorial: www.youtube.com/watch?v=SR_NAVTTD5o&t
This is the code for click gui (without imports):
package moonlight.ui.clickgui;
public class ClickGUI extends GuiScreen {
ArrayList<ModButton> modButtons = new ArrayList();
#Override
public void initGui() {
super.initGui();
this.modButtons.add(new ModButton(210, 60, 240, 100, Moonlight.INSTANCE.hudManager.testMod));
}
#Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
ScaledResolution sr = new ScaledResolution(mc);
super.drawScreen(mouseX, mouseY, partialTicks);
Gui.drawRect(200, 50, sr.getScaledWidth(), sr.getScaledHeight(), 0x20000000);
for(ModButton m : modButtons) {
m.draw();
}
}
#Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
}
}
And this is for gui button (without imports):
package moonlight.ui.clickgui.comp;
public class ModButton {
public int x, y, w, h;
public HudMod m;
public ModButton(int x, int y, int w, int h, HudMod m) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.m = m;
}
public void draw() {
Gui.drawRect(y, x, h, w, 0x20000000);
Minecraft.getMinecraft().fontRendererObj.drawString(m.name, x + 2, y + 2, getColor());
}
private int getColor() {
if(m.isEnabled()) {
return new Color(0,255,0,255).getRGB();
} else {
return new Color(255,0,0,255).getRGB();
}
}
public void ocClick(int mouseX, int mouseY, int button) {
if (mouseX >= x && mouseX <= x + w && mouseY >= y && mouseY <= y + h) {
m.toggle();
System.out.println("HELLO");
}
}
}
Rly, please help
EDIT
: it seems that in my move() method, java has to skip one of the 2 if statements
Keeping it simple. I'm trying to make a GUI in java that models the following class Truck behavior: the blue squares are supposed to run up their diagonales, which they do. But when they are supposed to bounce back once they reach the edge point of the square they just fly away. I've placed a condition to prevent this, but it never passes. I'll upload GUI and Drawable, but I don't think they are needed.
Class Truck:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.plaf.ButtonUI;
public class Truck extends Thread implements Drawable {
private boolean isFull = false;
private int x, y;
private int capacity;
private Panel panel;
static int r = 20;
private int dx, dy;
private Site site;
private Building building;
public Truck(int x, int y, Panel panel, Building building, Site site) {
this.x = x;
this.y = y;
this.building = building;
this.panel = panel;
this.site = site;
this.start();
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
#Override
public void run() {
super.run();
while (true) {
move();
panel.repaint();
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setDirection(int i) {
if (i == 0) {
dx = -1;
dy = -1;
}
if (i == 1) {
dx = 1;
dy = -1;
}
if (i == 2) {
dx = -1;
dy = 1;
}
if (i == 3) {
dx = 1;
dy = 1;
}
}
private void move() {
if (site.truckOnSite(x, y)) {
site.loadTruck(this);
dx *= -1;
dy *= -1;
}
if (building.containsTruck(this)) {
building.unloadTruck(this);
dx *= -1;
dy *= -1;
}
x += dx;
y += dy;
}
public int getDx() {
return dx;
}
public void setFull(boolean isFull) {
this.isFull = isFull;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLUE);
if (isFull)
g.fillRect(x - 10, y - 10, r, r);
else
g.drawRect(x - 10, y - 10, r, r);
}
}
Class Panel:
package construction_site;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Panel extends JPanel {
private ArrayList<Drawable> drawables = new ArrayList<>();
private Site site;
private Building[] buildings = new Building[4];
private Truck[] trucks = new Truck[4];
private Van[] vans = new Van[4];
public Panel(int w, int h) {
setPreferredSize(new Dimension(w, h));
site = new Site(100, 75, 500, 500, this);
drawables.add(site);
buildings[0] = new Building(100, 75, this);
buildings[1] = new Building(100 + 500, 75, this);
buildings[2] = new Building(100, 75 + 500, this);
buildings[3] = new Building(100 + 500, 75 + 500, this);
for (Building b : buildings)
drawables.add(b);
trucks[0] = new Truck(100 + 250, 75 + 250, this, buildings[0], site);
trucks[1] = new Truck(100 + 250, 75 + 250, this, buildings[1], site);
trucks[2] = new Truck(100 + 250, 75 + 250, this, buildings[2], site);
trucks[3] = new Truck(100 + 250, 75 + 250, this, buildings[3], site);
for (int i = 0; i < 4; i++)
trucks[i].setDirection(i);
for (Truck t : trucks)
drawables.add(t);
}
#Override
public void paint(Graphics g) {
super.paint(g);
for (Drawable d : drawables)
d.draw(g);
g.setColor(Color.GREEN);
for (int i = 1; i <= 3; i++)
g.drawLine(buildings[0].getX(), buildings[0].getY(), buildings[i].getX(), buildings[i].getY());
g.drawLine(buildings[1].getX(), buildings[1].getY(), buildings[2].getX(), buildings[2].getY());
}
}
Class Building:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Building extends Thread implements Drawable {
private Panel panel;
private boolean done = false;
private int x, y;
static int w = 100;
static int h = 100;
private ReentrantLock lock = new ReentrantLock();
private Condition insufficientMaterial = lock.newCondition();
private Condition insufficientMisc = lock.newCondition();
private Condition sufficient = lock.newCondition();
private int material = 0;
private int misc = 0;
private int spent = 0;
public Building(int x, int y, Panel panel) {
this.x = x;
this.y = y;
this.panel = panel;
this.start();
}
#Override
public void run() {
super.run();
lock.lock();
while(material < 100 )
try {
insufficientMaterial.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
spent += 150;
misc -= 50;
material -= 100;
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void unloadVan(Van v) {
lock.lock();
System.out.println("Truck got in");
if (material >= 100 && misc >=50) {
}
misc += 50;
v.setCapacity(0);
insufficientMisc.signalAll();
lock.unlock();
}
public void unloadTruck(Truck t) {
lock.lock();
material += 10000;
t.setCapacity(0);
t.setFull(false);
insufficientMaterial.signalAll();
lock.unlock();
}
public void setMaterial(int material) {
this.material = material;
}
public void setMisc(int misc) {
this.misc = misc;
}
public boolean containsVan(int x2, int y2) {
return ( Math.sqrt((x - x2)*(x - x2) + (y - y2)*(y - y2)) <= h/2 );
}
public boolean containsTruck(Truck t) {
return (x == t.getX() && y == t.getY());
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.BLACK);
g.drawRect(x - 50, y - 50, 100, 100);
}
}
Class Site:
package construction_site;
import java.awt.Color;
import java.awt.Graphics;
public class Site implements Drawable {
private int x, y, w, h;
private Panel panel;
public Site(int x, int y, int w, int h, Panel panel) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.panel = panel;
}
public boolean contains(int x2, int y2) {
return (x == x2 && y == 2);
}
public boolean truckOnSite(int x2, int y2) {
return ( x2 == x + w / 2 && y2 == y + h / 2);
}
public boolean vanOnSite(int x2, int y2) {
return ( (x2 == x && y2 == y + h / 2) || (x2 == x + w && y2 == y + h / 2) );
}
public void loadVan(Van v) {
v.setCapacity(5000);
}
public void loadTruck(Truck t) {
t.setCapacity(10000);
t.setFull(true);
}
#Override
public void draw(Graphics g) {
g.setColor(Color.GRAY);
g.fillRect(x, y, w, h);
}
}
As it turned out much later, it doesn't seem truncation errors were the problem at hand. It was a mistake at setting the trucks' starting point and the condition that decides when they're supposed to turn the other way. What looked like the truck bouncing off, was actually the oppsoite truck from the same diagonal passing through. A simple change in direction of my Truck's move() method did the trick.
public void setDirection(int i) {
if (i == 0) {
dx = -1;
dy = -1;
}
if (i == 1) {
dx = 1;
dy = -1;
}
if (i == 2) {
dx = -1;
dy = 1;
}
if (i == 3) {
dx = 1;
dy = 1;
}
}
So, I am instructed to: "Modify the Sprite class by implementing the "overlaps" function to return true if any portion of the Sprite passed in as an argument overlaps the current Sprite. You will need to use the x and y coordinates as well as the size of the Sprites."
I was advised to use Rectangles to make this work and check for an intersection. However, I'm not sure if what I have is the correct way to do this: (It's implemented in the boolean overlaps method)
As always, thanks so much for your time.
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.Random;
abstract class Sprite
{
private int x;
private int y;
private int size;
private int w;
private int h;
private int xSlope;
private int ySlope;
private Image image;
private static Random rand;
public Sprite(int xIn, int yIn, int width, int height, String imagePath, int imageSize) {
if (rand == null) {
rand = new Random();
}
size = imageSize;
setImage(imagePath);
x = xIn;
y = yIn;
w = width;
h = height;
xSlope = rand.nextInt(11) - 5;
ySlope = rand.nextInt(11) - 5;
}
public int getX() { return x; }
public int getY() { return y; }
public int getSize() { return size; }
public void setSize(int s) { size = s; }
public void setX(int xIn) { x = xIn; }
public void setY(int yIn) { y = yIn; }
public void setImage(String imagePath) {
try {
image = ImageIO.read(new File(imagePath));
} catch (IOException ioe) {
System.out.println("Unable to load image file.");
}
}
public Image getImage() { return image; }
public boolean overlaps(Sprite s) {
int locX = this.getX();
int locY = this.getY();
int overX = s.getX();
int overY = s.getY();
Rectangle R1 = new Rectangle(locX, locY, this.w, this.h);
Rectangle R2 = new Rectangle(overX, overY, s.w, s.h );
boolean intersects = R1.intersects(R2);
return intersects;
}
public void update(Graphics g) {
g.drawImage(getImage(), x, y, getSize(), getSize(), null);
}
public void move() {
// Move the Sprite
int x = getX() + xSlope;
int y = getY() + ySlope;
if (x < 0) x = w;
if (x > w) x = 0;
if (y < 0) y = h;
if (y > h) y = 0;
setX(x);
setY(y);
}
}
I'm making a game with Slick2D. When a player get's under a window with an enemy in it, they can shoot, and points will be added. I have every mechanic completed besides the shooting one. Here is my "plan" on how it'll work.
When the player gets below the window(which the program picks up on via y coordinate) and fires, points will be added to a counter.
How can I get my program to realize that the player is indeed below a window?
Thanks, and here's my PlayState code.
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.Image;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.FadeOutTransition;
import java.util.Random;
import java.util.TimerTask;
import java.util.Timer;
public class PlayState extends BasicGameState{
int stateID = -1;
int w = SwegBoi.WIDTH;
int h = SwegBoi.HEIGHT;
static int enemylocation;
float s = SwegBoi.SCALE;
Image playbackground;
Image swegboiplayer;
Image quit;
Image enemy1;
Image enemy2;
float playery;
int score = 0;
final static Random ran = new Random();
static Timer tm = new Timer();
static long startTime = System.currentTimeMillis();
public static void main(String args){
}
public PlayState(int stateID){
this.stateID = stateID;
}
#Override
public void init(GameContainer gc, StateBasedGame sbg)
throws SlickException {
swegboiplayer = new Image("resources/swegboibackgun.png");
playbackground = new Image("resources/playstatebackground.png");
quit = new Image("resources/mainmenuquit.png");
enemy1 = new Image("resources/enemy1.png");
enemy2 = new Image("resources/enemy1.png");
tm.schedule(new TimerTask() {
#Override
public void run() {
enemylocation = ran.nextInt(4) + 1;
}
}, 1, 2000);
}
#Override
public void render(GameContainer gc, StateBasedGame sbg, Graphics g)
throws SlickException {
playbackground.setFilter(Image.FILTER_NEAREST);
playbackground.draw(0, 0, s*10);
quit.draw((w-175*s),5 *s,s/2);
if(enemylocation==1){
enemy1.setFilter(Image.FILTER_NEAREST);
enemy1.draw(200,170,s*10);
}
if(enemylocation==2){
enemy1.setFilter(Image.FILTER_NEAREST);
enemy1.draw(200,360,s*10);
}
if(enemylocation==3){
enemy1.setFilter(Image.FILTER_NEAREST);
enemy1.draw(950,170,s*10);
}
if(enemylocation==4){
enemy1.setFilter(Image.FILTER_NEAREST);
enemy1.draw(950,360,s*10);
}
swegboiplayer.setFilter(Image.FILTER_NEAREST);
swegboiplayer.draw((w*s)/2-(playery*s), 450*s, s*5);
g.drawString("Alpha V0.1",6,6);
}
#Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
Input input = gc.getInput();
if(input.isKeyDown(Input.KEY_LEFT)){playery += 17;}
if(input.isKeyDown(Input.KEY_RIGHT)){playery -= 17;}
int mouseX = input.getMouseX();
int mouseY = input.getMouseY();
if(mouseHover(mouseX,mouseY,(w-175*s),5*s,quit.getHeight()/2,quit.getWidth()) == true){
if(input.isMousePressed(0)){
sbg.enterState(SwegBoi.MAINMENUSTATE,new FadeOutTransition(), new FadeInTransition());
}
quit = new Image("resources/mainmenuquithover.png");
}else{
quit = new Image("resources/mainmenuquit.png");
}}
#Override
public int getID() {
return stateID;
}
public boolean mouseHover(int mouseX, int mouseY, float x, float y, float height, float width){
if((mouseX >= x && mouseX <= x + width && mouseY >= y && mouseY <= y + height)){
return true;
}else{
return false;
}
}}
Something like this should work. Every time you move, check if you are in a range of an enemy x position and determine if shooting should be enabled or disabled. Define some kind of range for each enemies X position.
private void checkShootStatus()
{
// Calculate image bounds X Position + width
float swegboiplayerEndBound = swegboiplayer.getX() + swegboiplayer.getWidth();
float enemyEndBound = enemy.getX() + enemy.getWidth();
// Check enemy 1
if (swegboiplayerEndBound > enemy.getX() && swegboiplayer.getX() < enemyEndBound)
{
canShoot = true;
}
else
{
canShoot = false;
}
}
Since you cannot get the x location of an image, create a wrapper class to track the x/y positions of the player and enemy.
public class Player extends Image
{
private String image;
private float x = 0;
private float y = 0;
public Player(String image) throws SlickException
{
super(image);
this.setImage(image);
}
public float getY()
{
return y;
}
public void setY(float y)
{
this.y = y;
}
public String getImage()
{
return image;
}
public void setImage(String image)
{
this.image = image;
}
public float getX()
{
return x;
}
public void setX(float x)
{
this.x = x;
}
}
Enemy
public class Enemy extends Image
{
private String image;
private int x;
private int y;
public Enemy(String image) throws SlickException
{
super(image);
this.setImage(image);
}
public int getY()
{
return y;
}
public void setY(int y)
{
this.y = y;
}
public String getImage()
{
return image;
}
public void setImage(String image)
{
this.image = image;
}
public int getX()
{
return x;
}
public void setX(int x)
{
this.x = x;
}
}
So I got two buttons on this state Click here to see the screenshot
And what is actually happening is that my second button "Start", doesn't work with this values:
backButton.renderImage(g, CONTAINER_CENTER_X - backButton.getWidth() - 10, CONTAINER_MAX_Y - backButton.getHeight() - 30);
startButton.renderImage(g, CONTAINER_CENTER_X + 10, CONTAINER_MAX_Y - startButton.getHeight() - 30);
Here is output of button coordinates and values I set for x and y:
BACK BUTTON: [x=245, y= 535, width= 145, height=35] / CURRENT X: 245 /
CURRENT Y: 535 START BUTTON: [x=410, y= 535, width= 0, height=35] /
CURRENT X: 410 / CURRENT Y: 535
Then I found out, that by adding and subtracting button.getWidth(), I get the button to work
backButton.renderImage(g, CONTAINER_CENTER_X - backButton.getWidth() - 10, CONTAINER_MAX_Y - backButton.getHeight() - 30);
startButton.renderImage(g, CONTAINER_CENTER_X + startButton.getWidth() - startButton.getWidth() + 10, CONTAINER_MAX_Y - startButton.getHeight() - 30);
which is pretty strange, and is very ugly... :D
Here is output of button coordinates and values I set for x and y:
BACK BUTTON: [x=245, y= 535, width= 145, height=35] / CURRENT X: 245 /
CURRENT Y: 535
START BUTTON: [x=410, y= 535, width= 145, height=35] / CURRENT X: 410 / CURRENT Y: 535
So, check this state code and button class, and tell me what do you think?
ThisState
package poker;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.state.transition.FadeInTransition;
import org.newdawn.slick.state.transition.FadeOutTransition;
import poker.gui.PButton;
import poker.gui.UIConstants;
import static poker.gui.UIConstants.CONTAINER_CENTER_X;
import static poker.gui.UIConstants.CONTAINER_MAX_Y;
import poker.util.RandomUtility;
public class SetupScreenState extends BasicGameState implements UIConstants, StatePanelInterface {
public static final int ID = 2;
private Image titleImage;
private PButton backButton;
private PButton startButton;
public SetupScreenState() {
}
#Override
public int getID() {
return ID;
}
#Override
public void init(GameContainer container, StateBasedGame game) throws SlickException {
titleImage = new Image("res/gui/title_setup.png");
backButton = new PButton("res/gui/button_back.png", "res/gui/button_back_hover.png");
startButton = new PButton("res/gui/button_start.png", "res/gui/button_start_hover.png");
}
#Override
public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
RandomUtility.bgTheme(container, g);
renderTopPanel(container, game, g);
renderCenterPanel(container, game, g);
renderBottomPanel(container, game, g);
}
#Override
public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
Input input = container.getInput();
int mx = input.getMouseX();
int my = input.getMouseY();
if (backButton.contains(mx, my)) {
if (backButton.isButtonPressed(input)) {
game.enterState(StartScreenState.ID, new FadeOutTransition(), new FadeInTransition());
}
} else if (startButton.contains(mx, my)) {
if (startButton.isButtonPressed(input)) {
game.enterState(PlayScreenState.ID, new FadeOutTransition(), new FadeInTransition());
}
}
}
#Override
public void renderTopPanel(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
g.drawImage(titleImage, 50, 50);
}
#Override
public void renderCenterPanel(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
}
#Override
public void renderBottomPanel(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
backButton.renderImage(g, CONTAINER_CENTER_X - backButton.getWidth() - 10, CONTAINER_MAX_Y - backButton.getHeight() - 30);
startButton.renderImage(g, CONTAINER_CENTER_X + startButton.getWidth() - startButton.getWidth() + 10, CONTAINER_MAX_Y - startButton.getHeight() - 30);
}
}
BUTTON CLASS
package poker.gui;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
public class PButton {
private int x;
private int y;
private int width;
private int height;
private Image image;
private String classicImage;
private String hoverImage;
public PButton() {
}
public PButton(String classicImage, String hoverImage) throws SlickException {
this.classicImage = classicImage;
this.hoverImage = hoverImage;
image = new Image(classicImage);
}
public PButton(String classicImage, String hoverImage, int x, int y) throws SlickException {
this.classicImage = classicImage;
this.hoverImage = hoverImage;
this.x = x;
this.y = y;
image = new Image(classicImage);
}
public void renderImage(Graphics g) {
g.drawImage(image, x, y);
}
public void renderImage(Graphics g, int x, int y) throws SlickException {
this.x = x;
this.y = y;
g.drawImage(image, x, y);
}
public boolean contains(int x, int y) throws SlickException {
int minX = this.x;
int minY = this.y;
int maxX = this.x + this.width;
int maxY = this.y + this.height;
if ((x > minX && x < maxX) && (y > minY && y < maxY)) {
if (hoverImage != null) {
image = new Image(hoverImage);
}
return true;
}
image = new Image(classicImage);
return false;
}
public boolean isButtonPressed(Input input) throws SlickException {
return input.isMouseButtonDown(Input.MOUSE_LEFT_BUTTON);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void setWidth(int width) {
this.width = width;
}
public int getWidth() {
return width = image.getWidth();
}
public void setHeight(int height) {
this.height = height;
}
public int getHeight() {
return height = image.getHeight();
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
#Override
public String toString() {
return "[x=" + x + ", y= " + y + ", width= " + width + ", height=" + height + "]";
}
}
Your problem is that you don't initialize the width fields properly.
In contains(), you use this.width, but it has not been initialized (or precisely it has been default initialized to 0 because it is an instance variable).
When you call getWidth(), width initializes because return width = image.getWidth(); assigns this.width = image.getWidth(), which explains why you have to call getWidth() to get your button to work.
Make sure you initialize your button fields properly. For example, when you create the button (i.e. in the constructor), you should set width to image.getWidth()