A friend and I are starting to make a simple Java game and my job was to make a JFrame that has a player block that can jump on a platform. I am able to make the player class by making it extend Block.
I have reached a point where I can draw the player, but it only moves up and won't come back down, and the block thats supposed to be the floor wont show up. Here is my Main method, Block and Player classes, respectively.
package michael.s.game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MichaelSGame {
/**
* #param args the command line arguments
*/
static JFrame frame = new JFrame("Lab 54");
static JPanel panel;
static int height = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
static int width = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
static Player player = new Player(5,5,height - 20,width/2,0,0,Color.BLUE);
static Block floor = new Block(10,width,width,height - 20,Color.GREEN){
#Override
public void update() {
if(isTouching(player))
player.vy=0;
}
};
public static void main(String[] args) {
panel = new JPanel(){
//#Override
public void paint(Graphics g)
{
super.paint(g);
g.setColor(Color.GREEN);
floor.paint(g);
player.paint(g);
}
};
panel.setBackground(Color.white);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setBounds(0,0,width,height);
frame.setUndecorated(true);
KeyListener controls = new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE)
{
player.jump();
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
player.left();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT)
{
player.right();
}
}
#Override
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_LEFT)
{
player.stop();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT)
{
player.stop();
}
if(e.getKeyCode() == KeyEvent.VK_SPACE)
{
player.stop();
}
}
};
frame.add(panel);
panel.setFocusable(true);
panel.addKeyListener(controls);
panel.addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ESCAPE)
System.exit(0);
}
});
frame.setVisible(true);
new Thread(new Runnable(){
#Override
public void run() {
try{
while(true){
floor.update();
player.update();
panel.repaint();
Thread.currentThread().sleep(10);
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}).start();
}
}
///////////////////////////////
package michael.s.game;
import java.awt.Color;
import java.awt.Graphics;
/**
*
* #author David
*/
public abstract class Block {
protected int ht;
protected int wt;
protected double x;
protected double y;
protected Color color;
public Block(int ht, int wt, double x, double y, Color color)
{
this.ht = ht;
this.wt = wt;
this.x = x;
this.y = y;
this.color = color;
}
public boolean isTouching(Block other)
{
return x+wt >= other.getX() && other.getX() + other.getWt() >= x && y+ht >= other.getY() && other.getY() + other.getHt() >= y;
}
public int getX()
{
return (int) x;
}
public int getY()
{
return (int) y;
}
public int getHt()
{
return this.ht;
}
public int getWt()
{
return this.wt;
}
public void paint(Graphics g)
{
g.setColor(color);
g.fillRect(getX(), getY(), wt, ht);
}
public abstract void update();
}
/////////////////
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package michael.s.game;
import java.awt.Color;
/**
*
* #author David
*/
public class Player extends Block
{
public double vx;
public double vy;
public double GRAVITY;
public Player(int ht, int wt, double x, double y, double vx, double vy, Color color)
{
super(ht,wt,x,y, color);
}
#Override
public void update()
{
vy+= GRAVITY;
x+=vx;
y+=vy;
}
public void left()
{
vx = -5;
}
public void right()
{
vx = 5;
}
public void jump()
{
vy = -10;
}
public void stop()
{
vy = 0;
}
}
How can I get gravity to work in this, and have the floor actually show up?
I need help on adding a gravity function, having the floor show itself, and having the player stop when the player hits the floor.
Related
When I run this code, the square is responding so slow, like the program was running on 2 fps. Can you tell me why is it so slow and how can i make it run faster? Additionally I'll say that I used to code in pygame (python) and there was a system that allowed me to set FPS, but i can't find anything like this in java if you could show me how to set FPS I would be grateful.
Thanks for answering.
package World;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;
public class Map {
private final String title = "The Lord of the Dungeon";
private final int width = 1600;
private final int height = width / 16 * 9;
private Player player = new Player(width / 2, height / 2, 50);
//class Player contains only: int x, int y, int width, int height
public Map () {
//generate map
}
public void draw () {
boolean running = true;
//Creating the frame.
JFrame frame = new JFrame(title);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
//Creating the canvas.
Canvas canvas = new Canvas();
canvas.setSize(width, height);
canvas.setBackground(Color.BLACK);
canvas.setVisible(true);
frame.add(canvas);
canvas.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent keyEvent) {
}
#Override
public void keyPressed(KeyEvent keyEvent) {
int keyCode = keyEvent.getKeyCode();
if (keyCode == KeyEvent.VK_W) {
player.setY(player.getY() - 10);
}
else if (keyCode == KeyEvent.VK_A) {
player.setX(player.getX() - 10);
}
else if (keyCode == KeyEvent.VK_S) {
player.setY(player.getY() + 10);
}
else if (keyCode == KeyEvent.VK_D) {
player.setX(player.getX() + 10);
}
}
#Override
public void keyReleased(KeyEvent keyEvent) {
}
});
canvas.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent mouseEvent) {
}
#Override
public void mousePressed(MouseEvent mouseEvent) {
int mouseCode = mouseEvent.getButton();
if (mouseCode == 1) {
System.out.println("1");
}
}
#Override
public void mouseReleased(MouseEvent mouseEvent) {
}
#Override
public void mouseEntered(MouseEvent mouseEvent) {
}
#Override
public void mouseExited(MouseEvent mouseEvent) {
}
});
canvas.createBufferStrategy(3);
BufferStrategy bufferStrategy;
Graphics graphics;
while (running) {
bufferStrategy = canvas.getBufferStrategy();
graphics = bufferStrategy.getDrawGraphics();
graphics.clearRect(0, 0, width, height);
graphics.fillRect(player.getX(), player.getY(), player.getWidth(), player.getHeight());
bufferStrategy.show();
graphics.dispose();
}
}
}
here is Player class:
public class Player {
private int x;
private int y;
private int width;
private int height;
public Player (int x, int y, int width) {
this.x = x;
this.y = y;
this.width = width;
this.height = width / 9 * 16;
}
public int getX () {
return this.x;
}
public int getY () {
return this.y;
}
public int getWidth () {
return this.width;
}
public int getHeight () {
return this.height;
}
public void setX (int newX) {
this.x = newX;
}
public void setY (int newY) {
this.y = newY;
}
public void setWidth (int newWidth) {
this.width = newWidth;
this.height = newWidth / 9 * 16;
}
}
This question already has answers here:
How to use Key Bindings instead of Key Listeners
(4 answers)
Closed 5 years ago.
When VK_UP or VK_DOWN is pressed the Graphic g I created is not changing its position whatsoever. If someone could look and see if there is something wrong with my move method etc. Would really appreciate it.
Here is all my code so far:
package ping2;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Ping2 extends Applet implements Runnable, KeyListener{
final int WIDTH = 700, HEIGHT = 500;
Thread thread;
UserPaddle user1;
public void init() {
this.resize(WIDTH, HEIGHT);
this.addKeyListener(this);
user1 = new UserPaddle(1);
thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, WIDTH, HEIGHT);
user1.draw(g);
}
public void update(Graphics g) {
paint(g);
}
public void run() {
for(;;) {
user1.move();
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
user1.setUpAccel(true);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
user1.setDownAccel(true);
}
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
user1.setUpAccel(false);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN) {
user1.setDownAccel(false);
}
}
public void keyTyped(KeyEvent arg0) {
}
}
package ping2;
import java.awt.*;
public class UserPaddle implements InterfaceBar{
double y, yVelocity;
boolean upAccel, downAccel;
int player1, x;
final double FRICTION = 0.90;
public UserPaddle(int player1) {
upAccel = false;
downAccel = false;
y = 210;
yVelocity = 0;
if(player1 == 1)
x = 20;
else
x = 660;
}
public void draw(Graphics g) {
g.setColor(Color.white);
g.fillRect(x, (int)y, 20, 80);
}
public void move() {
if(upAccel) {
yVelocity -= 2;
}else if(downAccel) {
yVelocity += 2;
}
//Automatically slows bar down if key not being pressed.
else if(!upAccel && !downAccel) {
yVelocity *= FRICTION;
}
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
public int getY() {
return (int)y;
}
}
package ping2;
import java.awt.Graphics;
public interface InterfaceBar {
public void draw(Graphics g);
public void move();
public int getY();
}
I have modified your move() a bit give it a try
move()
public void move() {
if(upAccel) {
yVelocity -= 2;
y = yVelocity;
}else if(downAccel) {
yVelocity += 2;
y = yVelocity;
}
}
I have a project that a circle goes with random x and y values and with selected colors but when the user pressed the space bar the color of the circle must be changed. My circle moves both x and y coordinate and I want to change the color of the circle when I press the space button. But it does not work when I pressed it. It goes with its original color. So how can I make this code right?
public class c {
private int x,y,r;
private Color co;
private int Re,G,B;
private Random ran;
public c() {
// TODO Auto-generated constructor stub
ran= new Random();
x=100;
y=50;
r= ran.nextInt(200)+50;
Re=ran.nextInt(255);
G=ran.nextInt(255);
B=ran.nextInt(255);
co= new Color(Re,G,B);
}
public int getRe() {
return Re;
}
public int getG() {
return G;
}
public int getB() {
return B;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getR() {
return r;
}
public void setCo(int Re,int G,int B) {
co= new Color(Re,G,B);
}
public Color getCo() {
return co;
}
public Random getRan() {
return ran;
}
public void setX(int x) {
this.x=x;
}
public void setY(int y) {
this.y=y;
}
}
public class Circle extends JFrame implements ActionListener,KeyListener{
private Timer timer;
private int x,y,a=5,b=5;
private Random rand;
c circ = new c();
public Circle() {
setLayout(new BorderLayout());
x=circ.getX();
y=circ.getY();
timer=new Timer(50,this);
timer.start();
addKeyListener(this);
setSize(550,550);
setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
g.fillOval(x,y,100,100);
g.setColor(circ.getCo());
}
public static void main(String[]args) {
new Circle();
}
#Override
public void actionPerformed(ActionEvent e) {
moveWithTimer();
repaint();
}
public void moveWithTimer() {
x=x+b;
y=y+a;
if(x<0) {
b=5;
}
if(x+50>500) {
b=-5;
}
if(y<0){
a=5;
}
if(y+50>500) {
a=-5;
}
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode()==e.VK_SPACE) {
circ.setCo(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255));
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
But it does not work when I pressed it. It goes with its original color. So how can I make this code right?
KeyListener is fickle, better to use the Key Bindings API which overcomes the primary, focus related, issues of KeyListener
As a general rule of thumb, you shouldn't override paint of top level containers like JFrame, they are compound components and it's just a real mess.
Instead, start with a JPanel and override it's paintComponent method. It's generally more flexible. Have a look at Performing Custom Painting for more details.
Your movement code is wrong. You assign the x/y values of the circle class to some other variables, the problem here is, changing the values of these variables will have no affect on the variables in you circle class, instead, you need assign them back...
public void moveWithTimer() {
int x = circ.getX();
int y = circ.getY();
x = x + b;
y = y + a;
if (x < 0) {
b = 5;
}
if (x + 50 > 500) {
b = -5;
}
if (y < 0) {
a = 5;
}
if (y + 50 > 500) {
a = -5;
}
circ.setX(x);
circ.setY(y);
}
Your "circle" class could also use a couple of additional methods. One to randomise the color (it already has a Random object, might as well use it) and one to paint the object.
public class Circle {
//...
public void paint(Graphics2D g2d) {
g2d.setColor(co);
g2d.fillOval(x, y, r * 2, r * 2);
}
//...
public void randomColor() {
setCo(ran.nextInt(255), ran.nextInt(255), ran.nextInt(255));
}
//...
}
If it was me, I'd be tempted to add a move method as well, but that's me ;)
As a runnable example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Timer timer;
private int a = 5, b = 5;
private Random rand;
private Circle circ = new Circle();
public TestPane() {
timer = new Timer(50, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
moveWithTimer();
repaint();
}
});
timer.start();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "spaced");
am.put("spaced", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
circ.randomColor();
repaint();
}
});
}
public void moveWithTimer() {
int x = circ.getX();
int y = circ.getY();
x = x + b;
y = y + a;
if (x < 0) {
b = 5;
}
if (x + 50 > 500) {
b = -5;
}
if (y < 0) {
a = 5;
}
if (y + 50 > 500) {
a = -5;
}
circ.setX(x);
circ.setY(y);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
circ.paint(g2d);
g2d.dispose();
}
}
public class Circle {
private int x, y, r;
private Color co;
private int Re, G, B;
private Random ran;
public Circle() {
// TODO Auto-generated constructor stub
ran = new Random();
x = 100;
y = 50;
r = ran.nextInt(50) + 50;
Re = ran.nextInt(255);
G = ran.nextInt(255);
B = ran.nextInt(255);
co = new Color(Re, G, B);
}
public void paint(Graphics2D g2d) {
g2d.setColor(co);
g2d.fillOval(x, y, r * 2, r * 2);
}
public int getRe() {
return Re;
}
public int getG() {
return G;
}
public int getB() {
return B;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getR() {
return r;
}
public void randomColor() {
setCo(ran.nextInt(255), ran.nextInt(255), ran.nextInt(255));
}
public void setCo(int Re, int G, int B) {
co = new Color(Re, G, B);
}
public Color getCo() {
return co;
}
public Random getRan() {
return ran;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}
}
I suggest you should set the color of the graphics object within paint(g) before painting the circle.
public void paint(Graphics g) {
super.paint(g);
g.setColor(circ.getCo());
g.fillOval(x,y,100,100);
}
In general, you should not override the paint() method of the JFrame. Instead, create a JPanel, add it to your frame and override the paintComponent() method of the panel.
I'm working on a game project. The aim is clicking the balls and drop them into the basket which is below in the JPanel. I created some ways to do that but I can't achieve it. In my opinion, when the user click the ball's center with a margin of error (because the program can't catch the real point of balls), the program understands the action and runs the function of this issue. After clicking the ball it should be dropped down straight but the other balls should be continued. I use MouseListener#mousePressed method, but it doesn't work or I'm missing some parts. In addition, I made some changes in my source code, but I want to listen your advices so I am writing this topic.
I wrote a method which finds the mouse and ball coordinates. So when I make some changes to it, I can achieve my project goal. You can see the editing in the picture.
This is my source code ;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Game {
public Game() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException
| IllegalAccessException
| UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("MultipleBallApp");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new BallControl());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BallControl extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private BallPanel ballPanel = new BallPanel();
private JButton Suspend = new JButton("Suspend");
private JButton Resume = new JButton("Resume");
private JButton Add = new JButton("+1");
private JButton Subtract = new JButton("-1");
private JScrollBar Delay = new JScrollBar();
public BallControl() {
// Group buttons in a panel
JPanel panel = new JPanel();
panel.add(Suspend);
panel.add(Resume);
panel.add(Add);
panel.add(Subtract);
// Add ball and buttons to the panel
ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
Delay.setOrientation(JScrollBar.HORIZONTAL);
ballPanel.setDelay(Delay.getMaximum());
setLayout(new BorderLayout());
add(Delay, BorderLayout.NORTH);
add(ballPanel, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
this.addMouseListener(new MouseListener() {
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent clickEvent) {
// TODO Auto-generated method stub
System.out.println("X coordinate =" + clickEvent.getX());
System.out.println("Y coordinate = " + clickEvent.getY());
double radius1;
int x = 0;
double y = 0;
int radius = 15;
double xM = clickEvent.getX();
double yM = clickEvent.getY();
radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y)
* (yM - y));
System.out.println("Radius1 =" + radius1);
// ballPanel.list.get(0).setD
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
});
// Register listeners
Suspend.addActionListener(new Listener());
Resume.addActionListener(new Listener());
Add.addActionListener(new Listener());
Subtract.addActionListener(new Listener());
Delay.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
ballPanel.setDelay(Delay.getMaximum() - e.getValue());
}
});
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == Suspend) {
ballPanel.suspend();
} else if (e.getSource() == Resume) {
ballPanel.resume();
} else if (e.getSource() == Add) {
ballPanel.add();
} else if (e.getSource() == Subtract) {
ballPanel.subtract();
}
}
}
}
class BallPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
private int delay = 30;
public ArrayList<AnimatedShape> list = new ArrayList<AnimatedShape>();
private AnimatedRectange rectangle;
public BallPanel() {
this.rectangle = new AnimatedRectange(-25, 373, 50, 25, Color.BLACK);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Create a timer with the initial delay
protected Timer timer = new Timer(delay, new ActionListener() {
/**
* Handle the action event
*/
#Override
public void actionPerformed(ActionEvent e) {
for (AnimatedShape ball : list) {
ball.update(getBounds());
}
rectangle.update(getBounds());
repaint();
}
});
public void add() {
int radius = 15;
// Randomised position
int x = (int) (Math.random() * (getWidth() - (radius * 2)))
+ radius;
int y = (int) (Math.random() * (getHeight() - (radius * 2)))
+ radius;
Color color = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256), (int) (Math.random() * 256));
AnimatedBall ball = new AnimatedBall(x, y, radius, color);
list.add(ball);
}
// public void formula(MouseEvent clickEvent) {
// double radius1;
// int x = 0;
// double y = 0;
// int radius = 15;
// double xM = clickEvent.getX();
// double yM = clickEvent.getY();
// radius1 = Math.sqrt((xM - x) * (xM - x) + (yM - y) * (yM - y));
// System.out.println("Radius1 =" + radius1);
// }
public void subtract() {
if (list.size() > 0) {
list.remove(list.size() - 1); // Remove the last ball
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
for (AnimatedShape ball : list) {
ball.paint(this, g2d);
}
rectangle.paint(this, g2d);
}
public void suspend() {
timer.stop();
}
public void resume() {
timer.start();
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
}
public interface AnimatedShape {
public void update(Rectangle bounds);
public void paint(JComponent parent, Graphics2D g2d);
}
public abstract class AbstractAnimatedShape implements AnimatedShape {
private Rectangle bounds;
private int dx, dy;
public AbstractAnimatedShape() {
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public Rectangle getBounds() {
return bounds;
}
public int getDx() {
return dx;
}
public int getDy() {
return dy;
}
public void setDx(int dx) {
this.dx = dx;
}
public void setDy(int dy) {
this.dy = dy;
}
#Override
public void update(Rectangle parentBounds) {// ball
Rectangle bounds = getBounds();
int dx = getDx();
int dy = getDy();
bounds.x += dx;
bounds.y += dy;
if (bounds.x < parentBounds.x) {
bounds.x = parentBounds.x;
setDx(dx *= -1);
} else if (bounds.x + bounds.width > parentBounds.x
+ parentBounds.width) {
bounds.x = parentBounds.x + (parentBounds.width - bounds.width);
setDx(dx *= -1);
}
if (bounds.y < parentBounds.y) {
bounds.y = parentBounds.y;
setDy(dy *= -1);
} else if (bounds.y + bounds.height > parentBounds.y
+ parentBounds.height) {
bounds.y = parentBounds.y
+ (parentBounds.height - bounds.height);
setDy(dy *= -1);
}
}
}
public class AnimatedBall extends AbstractAnimatedShape {
private Color color;
public AnimatedBall(int x, int y, int radius, Color color) {
setBounds(new Rectangle(x, y / 2, radius * 2, radius * 2));
this.color = color;
setDx(Math.random() > 0.5 ? 2 : -2);
// setDy(Math.random() > 0.5 ? 2 : -2);
}
public Color getColor() {
return color;
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(getColor());
g2d.fillOval(bounds.x, bounds.y, bounds.width, bounds.height);
}
}
public class AnimatedRectange extends AbstractAnimatedShape {
private Color color;
public AnimatedRectange(int x, int y, int width, int height, Color color) {
setBounds(new Rectangle(x, y, width, height));
this.color = color;
setDx(2);
}
// Don't want to adjust the vertical speed
#Override
public void setDy(int dy) {
}
#Override
public void paint(JComponent parent, Graphics2D g2d) {
Rectangle bounds = getBounds();
g2d.setColor(color);
g2d.fill(bounds);
}
}
/**
* Main method
*/
public static void main(String[] args) {
new Game();
}
}
At the end of your mousePressed method, you can go though all AnimatedShape objects, check whether they are an AnimatedBall. When the object is a ball, you can test whether the mouse click hits the ball. The mouse click hits the ball when the distance between the center of the ball and the mouse position is smaller than the ball radius. When the ball is hit, you can set its horizontal speed to 0, and the vertical speed to 5 or so.
for (AnimatedShape as : ballPanel.list)
{
if (as instanceof AnimatedBall)
{
AnimatedBall ball = (AnimatedBall)as;
Rectangle b = ball.getBounds();
int ballCenterX = b.x + b.width / 2;
int ballCenterY = b.y + b.height / 2;
Point p = new Point(ballCenterX, ballCenterY);
double d = p.distance(clickEvent.getPoint());
if (d < radius)
{
ball.setDx(0);
ball.setDy(5);
}
}
}
Note
In order to make this work properly, you have to attach this listener to the ballPanel. Originally, you had the line
this.addMouseListener(new MouseListener() {
in your code. You have to change this to
ballPanel.addMouseListener(new MouseListener() {
Otherwise, the mouse coordinates will refer to the wrong component!
Concerning the question from the comment
how can I stop and disapper clickedball's when they crash the bound
You may probably insert method to check this, and call this method in the actionPerformed method of your timer. Further explainations are probably beyond the scope of an anser on a Q&A site. Stackoverflow is not a homework-solution-generator.
I've switched from KeyListeners to KeyBindings as instructed, however they still seem to do nothing. My keybinds are set up as to allow the left and right arrow keys to call a setDx() method in paddle.java which instructs the move() method to move the paddle.
gamePanel.java:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class gamePanel extends JPanel implements ActionListener {
paddle Paddle;
boolean ingame = true;
int delay = 1000;
Timer timer;
JLabel text = new JLabel("stuff here");
InputMap im = this.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = this.getActionMap();
public gamePanel() {
setBackground(Color.WHITE);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "RightArrow");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "LeftArrow");
add(text);
text.setBounds(100, 100, 200, 300);
timer = new Timer(delay, this);
Paddle = new paddle();
timer.start();
}
#Override
public void paint(Graphics g) {
super.paint(g);
if (ingame) {
g.drawImage(Paddle.getImage(), Paddle.getX(), Paddle.getY(),
Paddle.getWidth(), Paddle.getHeight(), this);
}
}
#Override
public void actionPerformed(ActionEvent ae) {
Object obj = ae.getSource();
if (obj == timer) {
Paddle.move();
validate();
repaint();
}
}
public class ArrowAction extends AbstractAction {
private String cmd;
public ArrowAction(String cmd) {
this.cmd = cmd;
}
#Override
public void actionPerformed(ActionEvent e) {
if (cmd.equalsIgnoreCase("LeftArrow")) {
Paddle.setDx(-20);
} else if (cmd.equalsIgnoreCase("RightArrow")) {
Paddle.setDx(20);
}
}
}
/*
#Override
public void keyPressed(KeyEvent ke) {
int KeyCode = ke.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
text.setText("key pressed");
Paddle.setDx(-20);
}
if (KeyCode == KeyEvent.VK_RIGHT) {
Paddle.setDx(20);
}
}
#Override
public void keyReleased(KeyEvent ke) {
int KeyCode = ke.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
Paddle.setDx(0);
}
if (KeyCode == KeyEvent.VK_RIGHT) {
Paddle.setDx(0);
}
}
#Override
public void keyTyped(KeyEvent ke) {
}
*/
}
Paddle.java:
import java.awt.Image;
import java.awt.Rectangle;
import javax.swing.ImageIcon;
public class paddle {
int dx = 0;
int x, y;
int height, width;
Image image;
public paddle() {
ImageIcon ii = new ImageIcon("src/Paddle.png");
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
//dx = 20;
resetState();
}
public void setDx(int z) {
dx = z;
}
public void move() {
x += dx;
if (x <= 2) {
x = 2;
}
if (x >= (640 - getWidth())) {
x = (640 - getWidth());
}
}
public void resetState() {
x = 250;
y = 375;
}
public void setX(int x) {
this.x = x;
}
public int getX() {
return x;
}
public void setY(int y) {
this.y = y;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
Image getImage() {
return image;
}
Rectangle getRect() {
return new Rectangle(x, y, image.getWidth(null), image.getHeight(null));
}
}
If your KeyListener methods are not being called I suspect it's because the correct component does not have focus. It's difficult sometimes to manage what component has focus especially in a game, so I would suggest switching over to using key bindings which doesn't require components to have focus.
You never add the corresponding actions you the ActionMap
am.put("LeftArrow", new ArrowAction("LeftArrow"));
am.put("RightArrow", new ArrowAction("RightArrow"));
Also, if you don't repaint() in the actioPerformed of the ArrowAction, you won't see it update immediately, until repaint() is called by the Timer, which isn't very long, but still a miniscule delay.