Hi I made a pause menu for my game, and you navigate through it with the arrow keys on the keyboard. My question is how do I make it so I can navigate with my mouse, and click the buttons rather then having to use the arrow keys?
here is the code:
public class InGameMenu implements KeyListener {
private String[] string = { "Resume Game", "Options", "Save Game", "Load Game", "Exit Game" };
private String[] optionStrings = { "Help", "Back" };
public static int selected = 0;
private int space = 25;
public int width = 800;
public int height = 600;
public static boolean isInMenu = true;
public static boolean isInOptions = false;
public static boolean saving = false;
public static boolean loading = false;
public InGameMenu() {
}
public void tick() {
}
public void render(Graphics g) {
g.setColor(new Color(0, 0, 0, 90));
g.fillRect(0, 0, Component.width, Component.height);
if (isInMenu) {
g.setColor(Color.LIGHT_GRAY);
if (saving) {
g.drawString("Saving", Component.width / 2 / Component.pixelSize - (int) (Component.width / 25), 35);
}
if (loading) {
g.drawString("Loading", Component.width / 2 / Component.pixelSize - (int) (Component.width / 25), 35);
}
for (int i = 0; i < string.length; i++) {
if (selected == i) {
g.setColor(Color.RED);
} else {
g.setColor(Color.WHITE);
}
g.drawString(string[i], Component.width / 2 / Component.pixelSize - (int) (Component.width / 17.5), Component.height / 8 + (i * space));
}
} else if (isInOptions) {
for (int i = 0; i < optionStrings.length; i++) {
if (selected == i) {
g.setColor(Color.RED);
} else {
g.setColor(Color.WHITE);
}
g.drawString(optionStrings[i], Component.width / 2 / Component.pixelSize - (int) (Component.width / 17.5), Component.height / 8 + (i * space));
}
}
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (isInMenu) {
if (key == KeyEvent.VK_UP) {
selected--;
if (selected < 0) {
selected = string.length - 1;
}
}
if (key == KeyEvent.VK_DOWN) {
selected++;
if (selected > string.length - 1) {
selected = 0;
}
}
if (key == KeyEvent.VK_ENTER) {
if (selected == 0) {
Component.isInMenu = false;
} else if (selected == 1) {
isInMenu = false;
isInOptions = true;
selected = 0;
} else if (selected == 2) {
saving = true;
SaveLoad.save();
saving = false;
} else if (selected == 3) {
loading = true;
SaveLoad.load();
loading = false;
} else if (selected == 4) {
System.exit(0);
}
}
} else if (isInOptions) {
if (key == KeyEvent.VK_UP) {
selected--;
if (selected < 0) {
selected = optionStrings.length - 1;
}
}
if (key == KeyEvent.VK_DOWN) {
selected++;
if (selected > optionStrings.length - 1) {
selected = 0;
}
}
if (key == KeyEvent.VK_ENTER) {
if (selected == 0) {
System.out.println("HELP");
} else if (selected == 1) {
isInOptions = false;
isInMenu = true;
}
}
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
You can implement MouseListener too.
You can add these methods from MouseListener:
public void mousePressed(MouseEvent e) {
if(e.getSource() == button1)
{
isInMenu = false;
isInOptions = true;
selected = 0;
}
if(e.getSource() == button2)
{
saving = true;
SaveLoad.save();
saving = false;
}
if(e.getSource() == button3)
{
loading = true;
SaveLoad.load();
loading = false;
}
if(e.getSource() == button4)
{
System.exit(0);
}
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
First, you must get the bounds (x, y, width and height) of the text.
You already have the x and y:
g.drawString(string[i], Component.width / 2 / Component.pixelSize - (int) (Component.width / 17.5), Component.height / 8 + (i * space));
// x = Component.width / 2 / Component.pixelSize - (int) (Component.width / 17.5)
// y = Component.height / 8 + (i * space)
You can determine the width and height via Font#getStringBounds(String, FontRenderContext):
FontRenderContext renderContext = new FontRenderContext(null, true, true);
Font font = new Font("Arial", Font.PLAIN, 14);
String labelText = "Start";
Rectangle2D labelBounds = font.getStringBounds(labelText, renderContext);
int labelWidth = (int) labelBounds.getWidth();
int labelHeight = (int) labelBounds.getHeight();
The bounds is needed to determine if the mouse is hovering over the text when the click occurs.
Next, you must maintain the bounds for each menu item.
Right now, you're only maintaining the names in string and optionStrings. You'll need to maintain the x, y, width and height for every menu item.
Since every menu item each has their own name, size and position, it would be easier to create a new type composed of these properties:
public class Label {
private String name;
private Font font;
private int x, y;
private int width, height;
public Label(String name, Font font, int x, int y, int width, int height) {
this.name = name;
this.font = font;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
Instead of a String[], you could have a Label[]. Although it's preferrable to use List for it's higher-level functionality:
public class InGameMenu implements MouseListener {
private List<Label> labels;
public void mousePressed(MouseEvent event) {
int x = event.getX();
int y = event.getY();
labels.forEach(label -> {
// if (mouse hovering over label)
// ...
});
}
}
Then, you must determine if the mouse position is within the label's position.
The formula is pretty simple:
// checks if mouse intersects with label on X axis
intersectsHorizontally := mouseX > labelX && mouseX < labelX + labelWidth;
// checks if mouse intersects with label on Y axis
intersectsVertically := mouseY > labelY && mouseY < labelY + labelHeight;
// if both conditions above are true, mouse is hovering over label
The easiest way to implement this would be to give your Label objects a containsPoint(int x, int y) behavior:
public class Label {
private int x, y;
private int width, height;
//...
public boolean containsPoint(int pointX, int pointY) {
boolean containsHorizontally = pointX > x && pointX < x + width;
boolean containsVertically = pointY > y && pointY < y + height;
return containsHorizontally && containsVertically;
}
}
Now you can easily determine whether the mouse is hovering over a specific label:
public void mousePressed(MouseEvent event) {
int x = event.getX();
int y = event.getY();
labels.forEach(label -> {
if(label.containsPoint(x, y)) {
//...
}
});
}
Finally, you must determine which label was clicked
There are many ways to go about this. Instead of a List, you could maintain the labels independently and check each one:
public class InGameMenu implements MouseListener {
private Label startLabel;
private Label loadLabel;
public InGameMenu(Label startLabel, Label loadLabel) {
this.startLabel = startLabel;
this.loadLabel = loadLabel;
}
public void mousePressed(MouseEvent event) {
int x = event.getX();
int y = event.getY();
if(startLabel.containsPoint(x, y)) {
//start game
} else if(loadLabel.containsPoint(x, y)) {
//load game
}
}
}
But this isn't dynamic, as InGameMenu is forced to know about every label it has, and adding labels would be a pain.
A better approach is to create all the Label objects outside of InGameMenu, as the examples above have been doing:
FontRenderContext renderContext = ...;
Font font = ...;
// start label
String labelText = "Start";
Rectangle2D labelBounds = font.getStringBounds(labelText, renderContext);
int x = ...;
int y = ...;
int width = (int) labelBounds.getWidth();
int height = (int) labelBounds.getHeight();
Label label = new Label(labelText, font, labelX, labelY, labelWidth, labelHeight);
// list of all labels for menu
List<Label> labels = new ArrayList<>();
labels.add(label);
InGameMenu menu = new InGameMenu(labels);
Then have the label object tell us when it has been clicked. We can do this by giving Label a click() method for InGameMenu to trigger when the label has been clicked:
public class InGameMenu implements MouseListener {
private List<Label> labels;
public InGameMenu(List<Label> labels) {
this.labels = labels;
}
public void mousePressed(MouseEvent event) {
int x = event.getX();
int y = event.getY();
labels.forEach(label -> {
if(label.containsPoint(x, y))
label.click();
});
}
}
Then allowing Label to accept a callback function:
public class Label {
private String name;
private Font font;
private int x, y;
private int width, height;
private Runnable onClick;
public Label(String name, Font font, int x, int y, int width, int height, Runnable onClick) {
this.name = name;
this.font = font;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.onClick = onClick;
}
public void click() {
onClick.run();
}
//...
}
So when you create Label objects, you can give them actions that make use of outside data (maybe a GameStateManager or something):
Runnable onClick = () -> System.out.println("Start button was clicked!");
Label label = new Label("Start", ..., onClick);
Related
i have a problem with the DS Desktop Notify library
in this library, all of notify banners has left to right orientation
i want to change the direction of these notifies from LTR to RTL
(the icons most be in the right side of the banner, also title and message need to start from right side of the banner
how can i do this in this library?
https://i.imgur.com/uTlOpqs.png "screenshot"
i have tried using the "applyComponentOrientation" for the frame, but it's not working
private static class DesktopLayoutFrame extends JDialog {
Image bg;
boolean nativeTrans;
boolean finished=true;
boolean clicked=false;
public DesktopLayoutFrame() {
super((JFrame)null,"DesktopLayoutFrame");
setUndecorated(true);
nativeTrans=Utils.isTranslucencySupported();
setBackground(new Color(0,0,0,nativeTrans? 0:255));
setContentPane(new JComponent(){
#Override
public void paintComponent(Graphics g){
render((Graphics2D)g);
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt){
clicked=true;
}
});
setFocusableWindowState(false);
setAlwaysOnTop(true);
System.out.println("Desktop Notify Frame deployed.");
}
#Override
public void setVisible(boolean visible) {
boolean bool=isVisible();
if (visible) {
Rectangle screenSize = Utils.getScreenSize();
setBounds(screenSize.x+screenSize.width-310, screenSize.y,
305, screenSize.height-5);
if (!bool && !nativeTrans)
bg=Utils.getBackgroundCap(getBounds());
}
super.setVisible(visible);
}
/**
* Paints the window contents.
* #param rd a graphics2D object received from the original paint event.
*/
public void render(Graphics2D rd) {
Point p = getMousePosition();
finished = false;
int x = 0, y = getHeight();
long l = System.currentTimeMillis();
if (windows.isEmpty()) finished = true;
int cur = Cursor.DEFAULT_CURSOR;
if (!nativeTrans) rd.drawImage(bg, 0, 0, this);
for (int i = 0; i < windows.size(); i++) {
DesktopNotify window = windows.get(i);
if (window.isVisible()) {
y -= window.h;
if (window.popupStart == 0) {
window.popupStart = System.currentTimeMillis();
}
if (y > 0) {
boolean hover = false;
if (p != null) {
if (p.y > y && p.y < y + window.h) {
hover = true;
if (window.getAction() != null) {
cur = Cursor.HAND_CURSOR;
}
if (clicked) {
if (window.getAction() != null) {
final DesktopNotify w = window;
final long lf = l;
java.awt.EventQueue.invokeLater(new Runnable(){#Override public void run(){
w.getAction().actionPerformed(new ActionEvent(w, ActionEvent.ACTION_PERFORMED, "fireAction", lf, 0));
}});
}
if (window.expTime() == Long.MAX_VALUE) {
window.timeOut = l - window.popupStart + 500;
}
}
}
}
window.render(x, y, hover, rd, l);
if (window.markedForHide) {
window.timeOut = l - window.popupStart + 500;
window.markedForHide = false;
}
} else {
window.popupStart = l;
}
if (l > window.expTime() || (y <= 0 && window.markedForHide)) {
window.markedForHide = false;
window.setVisible(false);
windows.remove(window);
i--;
}
y -= 5;
}
}
clicked = false;
setCursor(new Cursor(cur));
}
}
i think above code in "DesktopNotifyDriver.java" has to be edited for this. sorry for my english
Please Help Me Through This
When gameover is true and I call the startGame method from the DOWN button KeyListener, it breaks my game and doesn't allow me to click the exit button on the JFrame and the paddle doesn't work anymore. Please help.
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Image;
public class AustinsBrickBreaker {
JFrame window;
DrawPanel panel;
public AustinsBrickBreaker() {
window = new JFrame("Brick Breaker");
panel = new DrawPanel();
window.setSize(800, 592);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(panel);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public void go() {
panel.startGame();
}
public static void main(String[] args) {
AustinsBrickBreaker game = new AustinsBrickBreaker();
game.go();
}
}
#SuppressWarnings("serial")
class DrawPanel extends JPanel implements KeyListener {
final int WIDTH = 800, HEIGHT = 592;
BufferedImage buffer;
public static Brick[][] bricks = new Brick[3][5];
Paddle paddle;
Ball ball;
int score = 0;
int lives = 3;
boolean gameover = false;
Image brickImage = Toolkit.getDefaultToolkit().getImage("brick.png");
Image brickImage2 = Toolkit.getDefaultToolkit().getImage("brick2.png");
Image brickImage3 = Toolkit.getDefaultToolkit().getImage("brick3.png");
Image brickImage4 = Toolkit.getDefaultToolkit().getImage("brick4.png");
Image brickImage5 = Toolkit.getDefaultToolkit().getImage("brick5.png");
Image paddleImage = Toolkit.getDefaultToolkit().getImage("paddle.png");
Image background = Toolkit.getDefaultToolkit().getImage("background.jpg");
Image ballImage = Toolkit.getDefaultToolkit().getImage("ball.png");
Image heartImage = Toolkit.getDefaultToolkit().getImage("heart.png");
public DrawPanel() {
setIgnoreRepaint(true);
addKeyListener(this);
setFocusable(true);
}
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) paddle.left = true;
if (key == KeyEvent.VK_RIGHT) paddle.right = true;
if (key == KeyEvent.VK_UP && gameover) {
gameover = false;
score = 0;
lives = 3;
startGame();
}
if (key == KeyEvent.VK_DOWN && gameover) System.exit(0);
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) paddle.left = false;
if (key == KeyEvent.VK_RIGHT) paddle.right = false;
}
public int count() {
int count = 0;
for (int r = 0; r < DrawPanel.bricks.length; r++)
for (int c = 0; c < DrawPanel.bricks[r].length; c++)
if (!bricks[r][c].visible) count++;
else
break;
int returner = 0;
if (count == 15) returner = 1;
return returner;
}
public void initialize() {
buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
for (int r = 0; r < DrawPanel.bricks.length; r++)
for (int c = 0; c < DrawPanel.bricks[r].length; c++)
DrawPanel.bricks[r][c] = new Brick(c * 150 + 50, r * 60 + 30, 100, 50);
ball = new Ball(390, 200, 20, 20, 10);
paddle = new Paddle(350, 510, 100, 20, 8);
}
public void updateMovement() {
paddle.move();
ball.move();
}
public void checkCollisions() {
if (paddle.x <= 20) paddle.x = 20;
if (paddle.x >= 679) paddle.x = 679;
if (ball.x < 21) {
ball.left = false;
ball.right = true;
}
if (ball.x > 761) {
ball.left = true;
ball.right = false;
}
if (ball.y < 21) {
ball.up = false;
ball.down = true;
}
if (paddle.getBounds().intersects(ball.getBounds())) ball.swap();
for (int r = 0; r < DrawPanel.bricks.length; r++)
for (int c = 0; c < DrawPanel.bricks[r].length; c++) {
if (ball.getBounds().intersects(DrawPanel.bricks[r][c].getBounds()) && !DrawPanel.bricks[r][c].collision) {
ball.swap();
bricks[r][c].collide();
score += 10;
}
}
}
public void drawBuffer() {
Graphics2D b = buffer.createGraphics();
b.drawImage(background, 0, 0, null);
if (!gameover) {
for (int l = 0; l < lives; l++)
b.drawImage(heartImage, 20 * l + 620, 535, null);
b.drawString("Score: " + score, 700, 550);
b.drawImage(paddleImage, paddle.getX(), paddle.getY(), null);
b.drawImage(ballImage, ball.getX(), ball.getY(), null);
for (int r = 0; r < DrawPanel.bricks.length; r++)
for (int c = 0; c < DrawPanel.bricks[r].length; c++) {
if (bricks[r][c].visible == true)
if (bricks[r][c].colour == 1)
b.drawImage(brickImage, DrawPanel.bricks[r][c].getX(), DrawPanel.bricks[r][c].getY(), null);
else if (bricks[r][c].colour == 2)
b.drawImage(brickImage2, DrawPanel.bricks[r][c].getX(), DrawPanel.bricks[r][c].getY(), null);
else if (bricks[r][c].colour == 3)
b.drawImage(brickImage3, DrawPanel.bricks[r][c].getX(), DrawPanel.bricks[r][c].getY(), null);
else if (bricks[r][c].colour == 4)
b.drawImage(brickImage4, DrawPanel.bricks[r][c].getX(), DrawPanel.bricks[r][c].getY(), null);
else if (bricks[r][c].colour == 5)
b.drawImage(brickImage5, DrawPanel.bricks[r][c].getX(), DrawPanel.bricks[r][c].getY(), null);
}
b.dispose();
} else {
b.drawString("G A M E O V E R !", 340, 300);
b.drawString("G A M E O V E R !", 341, 300);
b.drawString("G A M E O V E R !", 342, 300);
b.drawString("Press ↑ To Play Again!", 332, 320);
b.drawString("Press ↓ To Exit :(", 342, 340);
}
}
public void drawScreen() {
Graphics2D g = (Graphics2D) this.getGraphics();
g.drawImage(buffer, 0, 0, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void startGame() {
initialize();
while (!gameover) {
try {
updateMovement();
checkCollisions();
drawBuffer();
drawScreen();
Thread.sleep(15);
if (ball.y > 562 && lives != -1) {
Thread.sleep(500);
lives -= 1;
ball.x = 390;
ball.y = 200;
ball.left = false;
ball.right = false;
paddle.x = 350;
}
if (lives == -1) {
Thread.sleep(500);
gameover = true;
drawBuffer();
drawScreen();
}
//Replace Bricks
if (count() == 1) {
Thread.sleep(500);
startGame();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/*--|--|--|--| GAME CLASSES |--|--|--|--*/
class Brick {
int x, y, width, height, colour;
boolean collision, visible;
public Brick(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.collision = false;
this.visible = true;
this.colour = (int) Math.ceil(Math.random() * 5);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Rectangle getBounds() {
return new Rectangle(getX(), getY(), getWidth(), getHeight());
}
public void collide() {
if (collision == false) {
visible = false;
collision = true;
}
}
}
class Paddle {
int x, y, width, height, speed;
boolean left, right;
public Paddle(int x, int y, int w, int h, int s) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.speed = s;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Rectangle getBounds() {
return new Rectangle(getX(), getY(), getWidth(), getHeight());
}
public void move() {
if (left) x -= speed;
if (right) x += speed;
}
}
class Ball {
int x, y, width, height, speed;
boolean up, down, left, right;
public Ball(int x, int y, int w, int h, int s) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.speed = s;
this.up = false;
this.down = true;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Rectangle getBounds() {
return new Rectangle(getX(), getY(), getWidth(), getHeight());
}
public void move() {
if (up) y -= speed;
if (down) y += speed;
if (left) x -= (float) Math.ceil(Math.random() * 5);
if (right) x += (float) Math.ceil(Math.random() * 5);
}
public void swap() {
if (up) {
down = true;
up = false;
} else if (down) {
up = true;
down = false;
}
double r = Math.random();
if (r <= 0.5) {
left = false;
right = true;
} else if (r > 0.5) {
left = true;
right = false;
} else left = true;
}
}
Your code completely ignores Swing threading rules, and this is somehow allowed when first run, since when first run, the startGame() method is called in the main thread off of the Swing event thread. But when it is called a second time, it is then called on the event thread, and this time, all those sleep calls put the Swing event thread and your application to sleep. The solution: learn about Swing threading rules, and have your application obey these rules, including not calling Thread.sleep, or having forever loops called on the event thread.
see: Lesson: Concurrency in Swing.
This is not an answer, but a very long comment
First, getGraphics is NOT how custom painting works in Swing and you should never use it.
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing.
Swing uses a passive rendering approaching, meaning that it's painting process can take place at any time, for any reason most without your interaction or knowledge, under your current approach, you could end up with intermediate flickering which be near impossible to diagnose or repeat.
If you want control over the painting (active painting), have a look at BufferStrategy and BufferStrategy and BufferCapabilities
Second, don't use KeyListener, there are a very limited number of circumstances I might consider using KeyListener, but this is not one of them and when you find yourself wanting to respond to key events, you should start with the key bindings API
Third, don't use Toolkit.getDefaultToolkit().getImage, but instead use ImageIO, it supports more images, it loads the image first before returning (rather than using a background thread) and throws an IOException when the image can't be loaded. See Reading/Loading an Image for more details
Fourth, you are violating the single thread rules of Swing. Basically, because the way the system works, main is called within what is called the "main" thread, but Swing runs in it's own thread (AKA The Event Dispatching Thread).
So when you first start, go is running in the "main" thread, but when you call start from your KeyListener, you're running within the EDT, meaning that you "game-loop" will block the EDT and nothing will ever paint again and the user won't be able to interact with your program.
See Concurrency in Swing for more details and How to Use Swing Timers for a possible solution
I know I have asked a question like this before, but none of the answers in the old question worked for me. I am trying to make a little single-player pong game (It is in a Java applet). I already have a moveBall() function, as you can see below. But I don't know where to call it. I can't call it in the paint() method because it is double buffered.
public class Main extends Applet implements KeyListener, MouseListener {
private Rectangle paddle;
private Rectangle ball;
private ArrayList<Integer> keysDown;
private Image dbImage;
private Graphics dbg;
public int time = 300000;
Random randomGenerator = new Random();
int speed = 10;
int level = 1; // change to 0 once start menu works
int xpos, ypos;
int ballx, bally;
int width = 1024;
int height = 768;
int paddleWidth = 96;
int ballSize = 16;
String version = "0.0.1";
public static final int START_X_POS = 160;
public static final int START_Y_POS = 160;
public static final int START_WIDTH = 256;
public static final int START_HEIGHT = 64;
boolean startClicked;
boolean falling = true;
public void init() {
setSize(width, height);
addKeyListener(this);
addMouseListener(this);
setBackground(Color.black);
Frame c = (Frame)getParent().getParent();
c.setTitle("Asteroid Attack - Version " + version);
keysDown = new ArrayList<Integer>();
paddle = new Rectangle(getWidth()/2-paddleWidth, getHeight()-96, paddleWidth, 12);
ball = new Rectangle(getWidth()/2-ballSize, 96, ballSize, ballSize);
}
public void update(Graphics g) {
dbImage = createImage(getSize().width, getSize().height);
dbg = dbImage.getGraphics ();
if (dbImage == null) {}
dbg.setColor(getBackground ());
dbg.fillRect(0, 0, getSize().width, getSize().height);
dbg.setColor(getForeground());
paint(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
if (level != 0) {
g2.setPaint(Color.gray);
g2.fill(paddle);
g2.setPaint(Color.darkGray);
g2.fill(ball);
moveBall();
}
}
public void moveBall() {
bally = ball.y;
ballx = ball.x;
if (bally < paddle.y-32 && falling) {
bally += 12;
}
if (bally < paddle.y-32 && falling && paddle.x <= ballx && paddle.getMaxX() >= ball.x) { // collides with paddle
falling = false;
}
else { // does not collide with paddle
}
ball.setLocation(ballx, bally);
}
#Override
public void keyPressed(KeyEvent e) {
if (!keysDown.contains(e.getKeyCode()))
keysDown.add(new Integer(e.getKeyCode()));
key();
}
#Override
public void keyReleased(KeyEvent e) {
keysDown.remove(new Integer(e.getKeyCode()));
}
public void key() {
if (level != 0) {
int x = paddle.x;
int y = paddle.y;
if (keysDown.contains(KeyEvent.VK_ESCAPE)) {System.exit(0);}
if (x > 0 && x+paddleWidth < this.getWidth()) {
if (keysDown.contains(KeyEvent.VK_LEFT)) {x -= speed;}
if (keysDown.contains(KeyEvent.VK_RIGHT)) {x += speed;}
}
else { // so paddle doesn't exit room
if (x <= 0) {x += 4;}
else {x -= 4;}
}
paddle.setLocation(x, y);
repaint();
}
}
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void mouseClicked(MouseEvent me) {
if (level == 0) {
xpos = me.getX();
ypos = me.getY();
if (xpos >= START_X_POS && ypos >= START_Y_POS && xpos <= START_X_POS + START_WIDTH && ypos <= START_X_POS + START_HEIGHT ) {
level = 1;
}
}
}
#Override
public void mouseEntered(MouseEvent me) {}
#Override
public void mouseExited(MouseEvent me) {}
#Override
public void mouseReleased(MouseEvent me) {}
#Override
public void mousePressed(MouseEvent me) {}
}
Any help would be greatly appreciated!
You'll probably want a separate Thread to move the ball which keeps track of time while in a in a loop - that way if frame rates drop, or speed up, you can try ensure consistency in the ball movement speed.
e.g. here on using a thread in a applet http://www.realapplets.com/tutorial/threadexample.html
I have post this question before also but this time I have added only required and necessary code only although the code is somewhat lengthy.
I want to load image in Jlabel and then after change image when user clicks next button. And when user want to move or scale image he can just easily do it by selecting image edges but it's not working.
All problem are solved except the scaling and moving image.
my code :
public class CopyOfPictureEditor extends JFrame
{
private static final long serialVersionUID = 6676383931562999417L;
String[] validpicturetypes = {"png", "jpg", "jpeg", "gif"};
Stack<File> pictures ;
JLabel label = new JLabel();
BufferedImage a = null;
JPanel panel = new JPanel();
public CopyOfPictureEditor()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
e.printStackTrace();
}
JMenuBar menubar = new JMenuBar();
JMenu toolsmenu = new JMenu(" File ");
final File dir = new File("");
final JFileChooser file;
file = new JFileChooser();
file.setCurrentDirectory(dir);
file.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
file.showOpenDialog(panel);
String path = file.getSelectedFile().getAbsolutePath();
System.out.println(path);
pictures= getFilesInFolder(path.toString());
JButton NEXT = new JButton("");
NEXT.setToolTipText("Next Image");
Image imgn = null;
try
{
imgn = ImageIO.read(getClass().getResource("/images/next12.png"));
}catch (IOException e) {
e.printStackTrace();
}
NEXT.setIcon(new ImageIcon(imgn));
JPanel buttonPane = new JPanel();
buttonPane.add(Box.createRigidArea(new Dimension(250,0)));
buttonPane.add(Box.createRigidArea(new Dimension(250,0)));
NEXT.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
nextImage();
}
});
buttonPane.add(NEXT);
getContentPane().add(buttonPane, BorderLayout.SOUTH);
setJMenuBar(menubar);
menubar.add(toolsmenu);
panel.add(label,BorderLayout.CENTER);
add(panel);
setTitle("Aero Picture Editor");
setVisible(true);
setPreferredSize(getPreferredSize());
setLocation(0,0);
label.addMouseListenet(new MouseHandler());
label.addMouseMotionListenet(new MouseHandler());
}
public Stack<File> getFilesInFolder(String startPath){
File startFolder = new File(startPath);
Stack<File> picturestack = new Stack<File>();
String extension;
int dotindex;
for (File file : startFolder.listFiles()) {
extension = "";
dotindex = file.getName().lastIndexOf('.');
if (dotindex > 0) {
extension = file.getName().substring(dotindex + 1);
for (String filetype : validpicturetypes){
if (extension.equals(filetype)) {
picturestack.add(file);
}
}
}
}
return picturestack;
}
public void nextImage() {
String p;
File f;
try{
f= pictures.pop().getAbsoluteFile();
a=ImageIO.read(f);
p = f.getPath();
System.out.println(p);
} catch (IOException e1) {
e1.printStackTrace();
}
ImageIcon image = new ImageIcon(a);
label.setIcon(image);
repaint();
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - a.getWidth()) / 2;
int y = (getHeight() - a.getHeight()) / 2;
AffineTransform at = new AffineTransform();
at.translate(x, y);
g2d.setTransform(at);
g2d.drawImage(a, 0, 0, this);
g2d.dispose();
}
public enum MouseAction {
Move(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)),
ResizeSouth(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)),
ResizeNorth(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)),
ResizeEast(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)),
ResizeWest(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)),
ResizeNorthEast(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)),
ResizeNorthWest(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)),
ResizeSouthEast(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)),
ResizeSouthWest(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
private Cursor cursor;
private MouseAction(Cursor cursor) {
this.cursor = cursor;
}
public Cursor getCursor() {
return cursor;
}
}
public class MouseHandler extends MouseAdapter
{
private MouseAction action;
private Point clickPoint;
private boolean ignoreMoves;
protected void updateAction(MouseEvent e) {
int x = e.getX();
int y = e.getY();
int width = getWidth();
int height = getHeight();
if (x < 10 && y < 10) {
action = MouseAction.ResizeNorthWest;
} else if (x > width - 10 && y < 10) {
action = MouseAction.ResizeNorthWest;
} else if (y < 10) {
action = MouseAction.ResizeNorth;
} else if (x < 10 && y > height - 10) {
action = MouseAction.ResizeSouthWest;
} else if (x > width - 10 && y > height - 10) {
action = MouseAction.ResizeSouthEast;
} else if (y > height - 10) {
action = MouseAction.ResizeSouth;
} else if (x < 10) {
action = MouseAction.ResizeWest;
} else if (x > width - 10) {
action = MouseAction.ResizeEast;
} else {
action = MouseAction.Move;
} setCursor(action.getCursor());
}
#Override
public void mouseMoved(MouseEvent e) {
if (!ignoreMoves)
{
updateAction(e);
}
}
#Override
public void mousePressed(MouseEvent e) {
updateAction(e);
ignoreMoves = true;
clickPoint = e.getPoint();
repaint();
System.out.println(e.getX());
System.out.println(e.getY());*/
}
#Override
public void mouseReleased(MouseEvent e) {
clickPoint = null;
ignoreMoves = false;
}
#Override
public void mouseDragged(MouseEvent e) {
switch (action) {
case Move: {
Point p = e.getPoint();
p.x -= clickPoint.x;
p=SwingUtilities.convertPoint(label, p, null);
setLocation(p);
}
break;
case ResizeWest: {
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() - xDelta;
int x = getX() + xDelta;
setSize(width, getHeight());
setLocation(x, getY());
revalidate();
}
break;
case ResizeEast: {
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() + xDelta;
setSize(width, getHeight());
revalidate();
clickPoint = p;
}
break;
case ResizeNorth: {
Point p = e.getPoint();
int yDelta = p.y - clickPoint.y;
int height = getHeight() - yDelta;
int y = getY() + yDelta;
setSize(getWidth(), height);
setLocation(getX(), y);
revalidate();
}
break;
case ResizeSouth: {
Point p = e.getPoint();
int yDelta = p.y - clickPoint.y;
int height = getHeight() + yDelta;
setSize(getWidth(), height);
revalidate();
clickPoint = p;
}
break;
}
}
#Override
public void mouseExited(MouseEvent e)
{
}
}
}
Found this one:
label.addMouseListener(new MouseHandler());
label.addMouseMotionListener(new MouseHandler());
Since you set your clickPoint in mousePressed and want to have it in mouseDragged, it should be the same object. You should actually get some nullpointers in mouseDragged?
Hard to see without complete code, but for one, you're calling setSize and setLocation on the Window itself in your MouseDragged method. If you want to get the object the user clicked on you need to get it from e.getSource(), like:
public void mouseDragged(MouseEvent e){
JLabel l = (JLabel)e.getSource();
switch(action){
case ResizeWest:
Point p = e.getPoint();
int xDelta = p.x - clickPoint.x;
int width = getWidth() - xDelta;
int x = getX() + xDelta;
l.setSize(width, getHeight()); // call setSize on JLabel l
l.setLocation(x, getY());
l.revalidate();
break;
}
Incidentally, why are you using a JLabel for this? I would use a Java object that draws itself onto the JFrame using the JFrame's graphics context.
Im currently am working on a game in Java that spawns blocks on the top of the screen and they fall down (you have to dodge them). Currently I have the game spawning blocks on the top of the screen from an array but I do not know how to make their y position go down by (int).
Basically I just need help making a public void that checks an object array and with every instance of a object it finds it drops the y position of it by 12.
Selected snippits from code:
static Object[][] food = new Object[7][700];
public void draw() {
try {
Graphics g = bufferStrategy.getDrawGraphics();
g.clearRect(0, 0, this.getSize().width, this.getSize().height);
// Draw to back buffer
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getSize().width, this.getSize().height);
g.setColor(Color.BLUE);
g.fillRect(Player.getX(), Player.getY(), Player.WIDTH, Player.HEIGHT);
g.setColor(Color.GRAY);
for(int x = 0; x < food.length; x++) {
for(int y = 0; y < food[x].length; y ++) {
Object o = food[x][y];
if(o instanceof Hamburger) {
new Hamburger(x * 100, y, g);
}
else if(o instanceof Salad) {
new Salad(x * 100, y, g);
}
}
}
GUI.draw(g);
} catch(Exception e) {
e.printStackTrace();
} finally {
bufferGraphics.dispose();
}
}
public void dropBlocks() {
}
public void addBlock() {
if(new Random().nextInt(2) == 1) {
food[new Random().nextInt(7)][0] = new Hamburger(0, 0);
} else food[new Random().nextInt(7)][0] = new Salad(0, 0);
}
public void drawBackbufferToScreen() {
bufferStrategy.show();
Toolkit.getDefaultToolkit().sync();
}
public void run() {
int i = 0;
while(running) {
i++;
draw();
Player.update();
drawBackbufferToScreen();
if(i == 50) {
addBlock();
i = 0;
}
dropBlocks();
Thread.currentThread();
try {
Thread.sleep(10);
} catch(Exception e) {
e.printStackTrace();
}
}
}
Food.java (What Hamburger and Salad extend)
public class Food {
public static int x;
public static int y;
public static int HEIGHT;
public static int WIDTH;
public int type;
private static Image blockImage;
// Default constructor
public Food() {
Food.x = 0;
Food.y = 0;
Food.HEIGHT = 80;
Food.WIDTH = 80;
}
public Food(int x, int y) {
Food.x = x;
Food.y = y;
Food.HEIGHT = 80;
Food.WIDTH = 80;
}
// Getters and setters
I would do something like this:
Object[][] board = new Object[7][700]; //Game board.
//you can also switch the width and height
//Initialization
for (int x = 699; x >= 0; x--) {
for (int y = 0; y < 7; y++) {
if (x == 699) {
board[y][x] = BLANK; //set spot to open if it is the bottom row
continue;
}
board[y][x+1] = board[y][x]; //move row down
}
}
//Generate new Objects if needed for the top row of the board.
Clearly Object does not have a getY() method. You could do ugly things with casting and instanceof, but this design is rather putrid. Try moving towards an object oriented model.
interface Drawable {
int getX();
int getY();
void moveDown(int numSpaces);
}
class Hamburger implements Drawable {
private int x;
private int y;
public Hamburger(final int xPos, final int yPos) {
x = xPos;
y = yPos;
}
#Override
public void moveDown(final int numSpaces) {
// eg negative number, off the screen
if(isValid(numSpaces)) {
setY(getY() - numSpaces);
}
}
}
class Positioner {
public static void moveMyObjects(final Drawable[][] objs) {
for(Drawable[] rows : objs) {
for(Drawable col : rows) {
// clearly Object doesn't have a getY() method, so you should create your own interface and implement it
col.moveDown(12);
}
}
}
}