I have made a mini tennis game that moves the racquet left and right using a keylistener.
package mini_tennis;
import java.awt.Rectangle;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
public class Racquet {
private static final int Y = 330;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 0;
int xa = 0;
private Game game;
public Racquet(Game game) {
this.game= game;
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth()-60)
x = x + xa;
}
public void paint(Graphics2D g) {
g.fillRect(x, 330, 60, 10);
}
public void keyReleased(KeyEvent e) {
xa = 0;
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = -game.speed;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = game.speed;
}
public Rectangle getBounds() {
return new Rectangle(x, Y, WIDTH, HEIGHT);
}
public int getTopY() {
return Y;
}
}
I would like to know how to move the racquet using mouse events. For example, when I click on the racquet using the left button it will drag the racquet left or right. Could you also include how I could move the racquet by moving my mouse left and right without pressing any buttons.
you will need an mouse listener
public class Racquet {
...
public void moveM(int mx)
{
x = mx; //invoked from panel to move the racquet
}
...
}
your panel class:
class yourPanelClass implements MouseListener {
...
panel.addMouseListener(this); //add listener to the panel
Racquet raq = new Racquet(); //create the racquet
...
#Override
public void mouseClicked(MouseEvent e) {
raq.moveM(e.getX()+((int)raq.getWidth()/2));
// get pointer position on mouse press and invoke method
// in Racquet passing the current X location of the pointer
// subtracting half of the width of the racquet thus positioning it in
// the middle.
}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
....
}
Related
So I am creating a brick breaker game. I got the paddle moving using key listeners, however I got some advice to use key bindings instead. I've been reading and looking everywhere on this and I think I've kinda got the idea but the implementation is confusing me a bit.
For my paddle, I created it with the paint component. Hence this is what I want to be able to move left and right with the arrow keys. However, all the key bindings explanations I find seem to use JComponent which the paddle is not. Is there a way around it or will I have to make my paddle a JComponent image icon instead? If so would I just load the image into my Paddle class?
Also what's the best way of structuring my code to contain the key bindings? For instance am I better off creating a whole new class for it, or putting it in e.g. my GamePanel class
Any tips?
Here is some of my code so you can get an idea:
Main Class:
public class BrickBreakerGameApp {
public static void main(String[] args) {
int pw = 500;
int ph = 900;
GamePanel gPanel = new GamePanel(pw,ph);
GameFrame gFrame = new GameFrame();
gFrame.getContentPane().add(gPanel); //add game panel to frame
// gFrame.addKeyListener(gPanel); //adds the key listener for the game panel frame
gFrame.pack();
gFrame.setVisible(true); //make frame visible
}
}
GameFrame class:
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
//Global Variables
public int frameWidth = 500;
public int frameHeight = 800;
//create constructor
GameFrame () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //so app closes properly
this.setPreferredSize(new Dimension(frameWidth, frameHeight)); //set frame size
this.setTitle("Brick Breaker Game");
ImageIcon icon = new ImageIcon("res/brick-breaker-logo.jpg"); //create image icon
this.setIconImage(icon.getImage()); //update frame icon
this.pack();
}
}
GamePanel Class
import java.awt.Color;
import java.awt.event.*;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.*;
/**
* This class handles the game panel as a whole
*/
public class GamePanel extends JPanel {
// Global Variables
private Ball ball;
private Paddle paddle;
private Bricks bricks;
private GameFrame gameFrame;
private int width;
private int height;
private int[] bArray = new int[20];
// create a constructor
GamePanel (int gamePanelWidth, int gamePanelHeight) {
this.setWidth(gamePanelWidth);
this.setHeight(gamePanelHeight);
initialiseGame();
this.isVisible();
}
private void initialiseGame() {
ball = new Ball(10, 520, 30, 30); //create the ball object
paddle = new Paddle(this, 50, 700, 100, 10); //creates paddle object
bricks = new Bricks(10, 10, 60, 30, bArray); //creates the bricks object
//for key binding initialisation
MotionAction motion = new MotionAction(paddle, 24);
}
// paint all the elements in
public void paintComponent(Graphics g) {
super.paintComponent(g);
// background
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// paddle
// g.setColor(Color.CYAN);
// g.fillRect(paddle.getPaddleX(), paddle.getPaddleY(), paddle.getPaddleWidth(), paddle.getPaddleHeight());
// ball
g.setColor(Color.MAGENTA);
g.fillOval(ball.getBallX(), ball.getBallY(), ball.getBallWidth(), ball.getBallHeight());
// brick
g.setColor(Color.GREEN);
g.fillRect(bricks.getBrickX(), bricks.getBrickY(), bricks.getBrickWidth(), bricks.getBrickHeight());
}
//add any unimplemented methods because we are using an interface
/* #Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
paddle.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
paddle.moveRight();
}
this.repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
} */
//create get and set methods for all panel attributes
public int getWidth() {
return width;
}
public void setWidth(int pWidth) {
this.width = pWidth;
}
public int getHeight() {
return height;
}
public void setHeight(int pHeight) {
this.height = pHeight;
}
}
Paddle class:
import javax.swing.AbstractAction;
import java.awt.event.*;
public class Paddle extends AbstractAction implements ActionListener {
//Global Variables
private int paddleWidth;
private int paddleHeight;
private int paddleX; //paddle x position
private int paddleY;
private GamePanel gamePanel;
//create paddle constructor
Paddle() {
}
//create a paddle constructor based off parameters
Paddle(GamePanel gPanel, int pX, int pY, int pWidth, int pHeight) {
//set the values
this.setPaddleWidth(pWidth);
this.setPaddleHeight(pHeight);
this.setPaddleX(pX);
this.setPaddleY(pY);
this.setGamePanel(gPanel);
}
//create get and set methods for all paddle attributes
public int getPaddleWidth() {
return paddleWidth;
}
public void setPaddleWidth(int pWidth) {
this.paddleWidth = pWidth;
}
public int getPaddleHeight() {
return paddleHeight;
}
public void setPaddleHeight(int pHeight) {
this.paddleHeight = pHeight;
}
public int getPaddleX() {
return paddleX;
}
public void setPaddleX(int pX) {
this.paddleX = pX;
}
public int getPaddleY() {
return paddleY;
}
public void setPaddleY(int pY) {
this.paddleY = pY;
}
public GamePanel getGamePanel() {
return gamePanel;
}
public void setGamePanel(GamePanel gPanel) {
this.gamePanel = gPanel;
}
//move the paddle left if it is not already positoned at 0 (far left)
public void moveLeft() {
try {
if(getPaddleX() <= 0) {
setPaddleX(0);
System.out.println("less than 0, x: " + getPaddleX());
}
else if (getPaddleX() > 0) {
setPaddleX(getPaddleX()-10); //to move paddle left -10
// gamePanel.repaint(getPaddleX()+10, getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint old position
// gamePanel.repaint(getPaddleX(), getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint new position
System.out.println("left, x: " + getPaddleX());
}
}
catch (Exception e) {
}
}
//move the paddle right if it is not already positioned to the far right of the panel
public void moveRight() {
if(getPaddleX() >= gamePanel.getWidth() - getPaddleWidth()) { //dont move the paddle if it is on the right edge of the panel
setPaddleX(gamePanel.getWidth() - getPaddleWidth());
System.out.println("right1, x:" + getPaddleX());
}
else if ((getPaddleX()+getPaddleWidth()) <= gamePanel.getWidth()){ //if the paddle is within the panel bounds
setPaddleX(getPaddleX() + 10); //to move paddle right +10
System.out.println("right, x:" + getPaddleX());
}
}
}
Here are some of the main resources I've being trying:
This one I tried but got really confused on the best way to integrate it into my own code --> https://tips4java.wordpress.com/2013/06/09/motion-using-the-keyboard/
This one I tried until I realised I don't have jcomponent --> https://coderanch.com/t/606742/java/key-bindings
You could register the key bindings with the GamePanel, or the frame content pane (both extend from JComponent). E.g.:
public class DemoFrame extends JFrame {
public static void main(String[] args) throws Exception {
new DemoFrame().setVisible(true);
}
public DemoFrame() {
setSize(800, 600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
{
String actionId = "left";
KeyStroke keyStroke = KeyStroke.getKeyStroke("LEFT");
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, actionId);
getRootPane().getActionMap().put(actionId, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
actionLeft();
}
});
}
}
private void actionLeft() {
System.out.println("left");
}
}
I'm making a brick breaker game and I'm stuck on getting the repaint() method working. I've used the debugger and it's not calling the paintComponent method. I am trying to get the paddle to move left or right when the left/right arrow keys are pressed. Hence I am trying to repaint the graphics, but have no luck in it working and can't figure out what I'm doing wrong.
My main class:
public class BrickBreakerGameApp {
public static void main(String[] args) {
int pw = 500;
int ph = 900;
GamePanel gPanel = new GamePanel(pw,ph);
GameFrame gFrame = new GameFrame();
gFrame.getContentPane().add(gPanel); //add game panel to frame
gFrame.addKeyListener(new GamePanel(pw,ph)); //adds the key listener for the game panel frame
gFrame.pack();
gFrame.setVisible(true); //make frame visible
}
}
My frame class:
import java.awt.Dimension;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
//Global Variables
public int frameWidth = 500;
public int frameHeight = 800;
//create constructor
GameFrame () {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //so app closes properly
this.setPreferredSize(new Dimension(frameWidth, frameHeight)); //set frame size
this.setTitle("Brick Breaker Game");
ImageIcon icon = new ImageIcon("res/brick-breaker-logo.jpg"); //create image icon
this.setIconImage(icon.getImage()); //update frame icon
this.pack();
}
}
My panel class:
import java.awt.Color;
import java.awt.event.*;
import javax.swing.JPanel;
import java.awt.*;
/**
* This class handles the game panel as a whole
*/
public class GamePanel extends JPanel implements ActionListener, KeyListener {
// Global Variables
private Ball ball;
private Paddle paddle;
private GameFrame gameFrame;
private int width;
private int height;
// create a constructor
GamePanel (int gamePanelWidth, int gamePanelHeight) {
this.setWidth(gamePanelWidth);
this.setHeight(gamePanelHeight);
initialiseGame();
this.isVisible();
}
private void initialiseGame() {
ball = new Ball(10, 520, 30, 30); //create the ball object
paddle = new Paddle(this, 50, 550, 100, 10); //creates paddle object
}
// paint all the elements in
public void paintComponent(Graphics g) {
super.paintComponent(g);
// background
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
// paddle
g.setColor(Color.CYAN);
g.fillRect(paddle.getPaddleX(), paddle.getPaddleY(), paddle.getPaddleWidth(), paddle.getPaddleHeight());
// ball
g.setColor(Color.MAGENTA);
g.fillOval(ball.getBallX(), ball.getBallY(), ball.getBallWidth(), ball.getBallHeight());
}
//add any unimplemented methods because we are using an interface
#Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_LEFT) {
paddle.moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
paddle.moveRight();
}
this.repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
//create get and set methods for all paddle attributes
public int getWidth() {
return width;
}
public void setWidth(int pWidth) {
this.width = pWidth;
}
public int getHeight() {
return height;
}
public void setHeight(int pHeight) {
this.height = pHeight;
}
}
My Paddle class:
public class Paddle {
//Global Variables
private int paddleWidth;
private int paddleHeight;
private int paddleX; //paddle x position
private int paddleY;
private GamePanel gamePanel;
//create paddle constructor
Paddle() {
}
//create a paddle constructor based off parameters
Paddle(GamePanel gPanel, int pX, int pY, int pWidth, int pHeight) {
//set the values
this.setPaddleWidth(pWidth);
this.setPaddleHeight(pHeight);
this.setPaddleX(pX);
this.setPaddleY(pY);
this.setGamePanel(gPanel);
}
//create get and set methods for all paddle attributes
public int getPaddleWidth() {
return paddleWidth;
}
public void setPaddleWidth(int pWidth) {
this.paddleWidth = pWidth;
}
public int getPaddleHeight() {
return paddleHeight;
}
public void setPaddleHeight(int pHeight) {
this.paddleHeight = pHeight;
}
public int getPaddleX() {
return paddleX;
}
public void setPaddleX(int pX) {
this.paddleX = pX;
}
public int getPaddleY() {
return paddleY;
}
public void setPaddleY(int pY) {
this.paddleY = pY;
}
public GamePanel getGamePanel() {
return gamePanel;
}
public void setGamePanel(GamePanel gPanel) {
this.gamePanel = gPanel;
}
//move the paddle left if it is not already positoned at 0 (far left)
public void moveLeft() {
try {
if(getPaddleX() <= 0) {
setPaddleX(0);
System.out.println("less than 0, x: " + getPaddleX());
}
else if (getPaddleX() > 0) {
setPaddleX(getPaddleX()-10); //to move paddle left -10
// gamePanel.repaint(getPaddleX()+10, getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint old position
// gamePanel.repaint(getPaddleX(), getPaddleY(), getPaddleWidth(), getPaddleHeight()); //repaint new position
System.out.println("left, x: " + getPaddleX());
}
}
catch (Exception e) {
}
}
//move the paddle right if it is not already positioned to the far right of the panel
public void moveRight() {
if(getPaddleX() >= gamePanel.getWidth() - getPaddleWidth()) { //dont move the paddle if it is on the right edge of the panel
setPaddleX(gamePanel.getWidth() - getPaddleWidth());
System.out.println("right1, x:" + getPaddleX());
}
else if ((getPaddleX()+getPaddleWidth()) <= gamePanel.getWidth()){ //if the paddle is within the panel bounds
setPaddleX(getPaddleX() + 10); //to move paddle right +10
System.out.println("right, x:" + getPaddleX());
}
}
}
After a little bite of debugging/testing I found out that in your main method:
public class BrickBreakerGameApp {
public static void main(String[] args) {
int pw = 500;
int ph = 900;
GamePanel gPanel = new GamePanel(pw,ph);
GameFrame gFrame = new GameFrame();
gFrame.getContentPane().add(gPanel); //add game panel to frame
gFrame.addKeyListener(new GamePanel(pw,ph)); //adds the key listener for the game panel frame
gFrame.pack();
gFrame.setVisible(true); //make frame visible
}
}
to the gFrame.addKeyListener method call do not add a new GamePanel but the one that you created already, namely:
gFrame.addKeyListener(gPanel); //adds the key listener for the game panel frame
I am attempting to create a Big Bang world which contains a circle whose initial state should have it moving one pixel diagonally to the bottom-right. Every time the user presses the four arrow keys, the circle should move one pixel towards that direction and keep moving. For example, if I keep pressing the right arrow key, the circle should move towards the right and keep moving faster and faster each time I press it. The problem I am having is that I can't get the circle to move at all! I thought changing x and y coordinates oft he circle for each method should move it accordingly. What am I doing wrong? What can I do to have the circle move as I have described it? Here is the file Game.java that I need to fix:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Game implements World {
public Game() { }
int x, y = 200;
int width, height = 100;
void Circle(int x, int y, int width, int height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void draw(Graphics g) {
int x = 200;
int y = 200;
int width = 100;
int height = 100;
g.setColor(Color.red);
g.fillOval(x,
y,
width,
height);
}
public void teh() {
this.x++;
this.y++;
}
public void meh(MouseEvent e) {
int x = e.getX(), y = e.getY();
System.out.println("Mouse event detected.");
}
public void keh(KeyEvent e) {
int x = e.getKeyLocation(), y = e.getKeyLocation();
int key = e.getKeyCode();
if (key == KeyEvent.VK_UP){
this.y--;
System.out.println("Up.");
}
else if (key == KeyEvent.VK_DOWN){
this.y++;
System.out.println("Down.");
}
else if (key == KeyEvent.VK_RIGHT){
this.x++;
System.out.println("Right.");
}
else if (key == KeyEvent.VK_LEFT){
this.x--;
System.out.println("Left.");
}
else{}
// switch( keyCode ) {
// case KeyEvent.VK_UP:
// // handle up
// break;
// case KeyEvent.VK_DOWN:
// // handle down
// break;
// case KeyEvent.VK_LEFT:
// // handle left
// break;
// case KeyEvent.VK_RIGHT :
// // handle right
// break;
// }
}
public boolean hasEnded() {
return false;
}
public void sayBye() {
System.out.println("BYE!");
}
public static void main(String[] args) {
BigBang b = new BigBang(new Game());
b.start( 50, // delay
400 // size
);
}
}
These are the supplementary files that are used but should remain untouched. I am including them for your reference:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BigBang extends JComponent implements ActionListener, MouseListener, MouseMotionListener, KeyListener {
Timer timer;
World world;
public BigBang(World world) {
this.world = world;
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.addKeyListener(this);
this.setFocusable(true);
this.requestFocus();
}
public void start(int delay, int size) {
JFrame a = new JFrame();
a.add( this );
a.setVisible(true);
a.setSize(size, size);
this.timer = new Timer(delay, this);
this.timer.start();
}
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) {
this.world.meh(e);
this.repaint();
}
public void mouseDragged(MouseEvent e) {
this.world.meh(e);
this.repaint();
}
public void mouseMoved(MouseEvent e) { }
public void mouseReleased(MouseEvent u) {
this.world.meh(u);
this.repaint();
}
public void mouseClicked(MouseEvent e) { }
public void keyPressed(KeyEvent e) {
this.world.keh(e);
this.repaint();
}
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
// int count;
public void actionPerformed(ActionEvent e) {
// this.count += 1;
// System.out.println("Ouch" + this.count);
if (this.world.hasEnded()) {
this.timer.stop();
this.world.sayBye();
} else {
this.world.teh();
}
this.repaint();
}
public void paintComponent(Graphics g) {
this.world.draw(g);
}
}
And the interface World.java:
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
interface World {
void draw(Graphics g);
void teh();
void meh(MouseEvent e);
void keh(KeyEvent e);
boolean hasEnded();
void sayBye();
}
Where does my mistake lie? Why am I not able to move the circle when the arrow keys are pressed? How can I continue to add on to the velocity of the object each time the arrow key is pressed? Any modifications or advice will be helpful.
The issue is in your draw method:
public void draw(Graphics g)
{
int x = 200;
int y = 200;
int width = 100;
int height = 100;
g.setColor(Color.red);
g.fillOval(x, y, width, height);
}
You are constantly making new local variables, x, y, width, and height, and drawing with those
Instead you should be using the variables your class already has designed:
public void draw(Graphics g)
{
g.setColor(Color.red);
g.fillOval(x, y, width, height);
}
Here's my ordeal. I'm trying to make a simple platformer, where a ball moves around the screen and can jump around to different platforms. For now, I'm just trying to get a ball to move around on the screen with proper class structure and encapsulation. My game structure looks like this:
Game Frame
Creates JFrame
Runs engine as content pane
package main;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GameFrame {
public static void main(String[] args) {
JFrame window = new JFrame("Game");
Ball ball = new Ball(125, 250, 25, 0, 0, 2);
BallPanel ballPanel = new BallPanel(ball);
Engine engine = new Engine(ball, ballPanel);
window.add(engine);
window.add(ballPanel);
window.setContentPane(engine);
window.getContentPane().setSize(new Dimension(400, 800));
window.getContentPane().add(ballPanel);
window.pack();
window.setVisible(true);
window.setDefaultCloseOperation(3);
window.addKeyListener(engine);
}
}
Engine
Implements listeners
Updates values of position, motion, and size for ball
Calls a "step" function for the ball on a 60fps timer
`package main;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.Timer;
public class Engine extends JPanel implements KeyListener, ActionListener{
private boolean spacePressed = false, rightPressed = false, leftPressed = false;
private boolean offGround = true;
private Ball b;
private ArrayList<Platform> platforms;
private BallPanel bP;
private ArrayList<PlatformPanel> pPs;
public Engine(Ball ball, BallPanel ballPanel, ArrayList<Platform> ps, ArrayList<PlatformPanel> pps){
b = ball;
platforms = ps;
bP = ballPanel;
pPs = pps;
setFocusable(true);
Timer timer = new Timer(1000/60, this);
timer.start();
addKeyListener(this);
}
public Engine(Ball ball, BallPanel ballPanel){
b = ball;
bP = ballPanel;
setFocusable(true);
Timer timer = new Timer(1000/60, this);
timer.start();
addKeyListener(this);
}
// public void checkCollision(Platform p, Ball b){
// //right side of ball with left side of platform
// if(linesIntersect(b.getX()+b.getR(), b.getY()-b.getR(), b.getX()+b.getR(), b.getY()+b.getR(), p.getX(), p.getY(), p.getX(), p.getY()+p.getH())){
// b.setVx(0);
// } //left side of ball with right side of platform
// else if(linesIntersect(b.getX()-b.getR(), b.getY()-b.getR(), b.getX()-b.getR(), b.getY()+b.getR(), p.getX()+p.getW(), p.getY(), p.getX()+p.getW(), p.getY()+p.getH())){
// b.setVx(0);
// }//bottom side of ball with top of platform
// else if(linesIntersect(b.getX()-b.getR(), b.getY()+b.getR(), b.getX()+b.getR(), b.getY()+b.getR(), p.getX(), p.getY(), p.getX()+p.getW(), p.getY())){
// b.setVy(0);
// }//upper side of ball with bottom of platform
// else if(linesIntersect(b.getX()-b.getR(), b.getY()-b.getR(), b.getX()+b.getR(), b.getY()-b.getR(), p.getX(), p.getY()+p.getH(), p.getX()+p.getW(), p.getY()+p.getH())){
// b.setVy(0);
// }
// }
public void update(){
b.setVy(b.getVy()+b.getAcc());
if(spacePressed && !offGround){
b.setVy(b.getVy()-20);
b.setY(b.getY()+b.getVy());
offGround = true;
}
if(leftPressed){
b.setX(b.getX()-b.getVx());
}
if(rightPressed){
b.setX(b.getX()+b.getVx());
}
if(b.getY() < 250){
b.setY(b.getY()+b.getVy());
}
else{
b.setVy(0);
b.setY(250);
offGround = false;
}
}
public void actionPerformed(ActionEvent e) {
update();
bP.step();
// for(PlatformPanel pP : pPs){
// pP.step();
// }
}
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_SPACE){
spacePressed = true;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
rightPressed = true;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
leftPressed = true;
}
}
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_SPACE){
spacePressed = false;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
rightPressed = false;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
leftPressed = false;
}
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Ball
Stores values for position, motion, and size
Has setter/getter methods for accessibility
package main;
public class Ball implements Collidable {
private int ballX, ballY, ballR, Vx, Vy, acc;
public Ball(int x, int y, int r, int vx, int vy, int a){
ballX = x;
ballY = y;
ballR = r;
Vx = vx;
Vy = vy;
acc = a;
}
#Override
public int getX() {
return ballX;
}
#Override
public int getY() {
return ballY;
}
public int getVx(){
return Vx;
}
public int getVy(){
return Vy;
}
public int getAcc(){
return acc;
}
public int getR(){
return ballR;
}
#Override
public void setX(int x) {
ballX = x;
}
#Override
public void setY(int y) {
ballY = y;
}
public void setVx(int x){
Vx = x;
}
public void setVy(int y){
Vy = y;
}
public void setAcc(int a){
acc = a;
}
}
BallPanel
Paints the ball using its values
package main;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.Timer;
public class BallPanel extends JPanel
{
private Ball b;
public BallPanel(Ball ball){
b = ball;
}
public void step(){
System.out.println("step working");
repaint();
}
#Override
public void paintComponent(Graphics g){
System.out.println("PaintComponent working");
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(b.getX(), b.getY(), 2*b.getR(), 2*b.getR());
}
}
However, even though PaintComponent is being called, nothing is being drawn in the frame. Why is this? Should my game structure be changed? My friend suggested not having a BallPanel and just drawing the ball from within the engine. Would this work better? I did read something about paintComponent only being called on components within the content pane (which is why i tried adding ballPanel to it)
The problem is that this ball after it is dragged and exited click, it is supposed to repaint according to the new y component given. This is calculated from the gravity final and added to the velocity which is added to the existing y component in a loop.
I have debugged many times and I just cant hit it on the head.
Its supposed to..
move to where you drag it >>> when you let go it is supposed to fall until it hits the ground.
Thank you ahead of time.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragBallPanel extends JPanel implements MouseListener, MouseMotionListener
{
private static final int BALL_DIAMETER = 40;
private int screen_size_x = 300;
private int screen_size_y = 300;
private int ground_lvl = screen_size_y - 15;
private int _ballX = ground_lvl/2;
private int _ballY = ground_lvl - BALL_DIAMETER;
private final double GRAVITY = -9.8;
private double velocity;
private static final double TERM_VEL = -100;
private int _dragFromX = 0;
private int _dragFromY = 0;
private boolean _canDrag = false;
public DragBallPanel() throws InterruptedException
{
setPreferredSize(new Dimension(screen_size_x, screen_size_y));
setBackground(Color.darkGray);
setForeground(Color.darkGray);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g); // Required for background.
g.setColor (Color.green);
g.fillRect (0, 280, 400, 50 );
g.setColor (Color.black);
g.fillOval(_ballX, _ballY, BALL_DIAMETER, BALL_DIAMETER);
}
public void mousePressed(MouseEvent e)
{
int x = e.getX();
int y = e.getY();
if (x >= _ballX && x <= (_ballX + BALL_DIAMETER)
&& y >= _ballY && y <= (_ballY + BALL_DIAMETER))\
{
_canDrag = true;
_dragFromX = x - _ballX;
_dragFromY = y - _ballY;
} else
{
_canDrag = false;
}
}
//===== mouseDragged ======
/** Set x,y to mouse position and repaint. */
public void mouseDragged(MouseEvent e)
{
if (_canDrag)
{ // True only if button was pressed inside ball.
//--- Ball pos from mouse and original click displacement
_ballX = e.getX() - _dragFromX;
_ballY = e.getY() - _dragFromY;
//--- Don't move the ball off the screen sides
_ballX = Math.max(_ballX, 0);
_ballX = Math.min(_ballX, getWidth() - BALL_DIAMETER);
//--- Don't move the ball off top or bottom
_ballY = Math.max(_ballY, 0);
_ballY = Math.min(_ballY, getHeight() - BALL_DIAMETER);
this.repaint();
}
}
public void mouseExited(MouseEvent e)
{
while(_ballY < ground_lvl)
{
simulateGravity();
}
}
public void simulateGravity()
{
if(_canDrag)
{
try{
velocity = velocity + GRAVITY;
if (velocity < TERM_VEL)
{
velocity = TERM_VEL;
}
if (_ballY >= ground_lvl - BALL_DIAMETER)
{
velocity = velocity/4;
}
_ballY += velocity;
Thread.sleep(400);
this.repaint();//**problem occurs here**
}catch(InterruptedException ie)
{
}
}
}
public void mouseMoved (MouseEvent e){}
public void mouseEntered (MouseEvent e){}
public void mouseClicked (MouseEvent e){}
public void mouseReleased(MouseEvent e){}
}
main() class
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class DragDemo extends JApplet
{
public static void main(String[] args) throws InterruptedException
{
JFrame window = new JFrame();
window.setTitle("Drag Demo");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//window.add(new DragBallPanel());
window.setContentPane(new DragBallPanel());
window.setResizable(false);
window.pack();
window.show();
}
public DragDemo() throws InterruptedException
{
new DragBallPanel();
}
}
This SSCCE begins to show the problems in the code.
Compile the code.
Run it.
Drag the ball upwards.
Release the ball.
Remove the mouse from the drawing area, to see..
The ball fall upwards!
You seem to have gotten the Y values upside down. They start at top of screen, and go downwards. Also, the code was blocking the EDT in an infinite loop. To solve that, run the animation using a Swing Timer.
Please read the document on the SSCCE & ask if there is anything in it you do not understand. I am well placed to explain. :)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragBallPanel extends JPanel implements MouseListener, MouseMotionListener
{
private static final int BALL_DIAMETER = 40; // Diameter of ball
private int screen_size_x = 300;
private int screen_size_y = 300;
private int ground_lvl = screen_size_y - 15;
private int _ballX = ground_lvl/2;
private int _ballY = ground_lvl - BALL_DIAMETER;
private final double GRAVITY = -9.8;
private double velocity;
private static final double TERM_VEL = 100;
private int _dragFromX = 0; // pressed this far inside ball's
private int _dragFromY = 0; // bounding box.
/** true means mouse was pressed in ball and still in panel.*/
private boolean _canDrag = false;
public DragBallPanel()
{
setPreferredSize(new Dimension(screen_size_x, screen_size_y));
setBackground(Color.darkGray);
setForeground(Color.darkGray);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g); // Required for background.
g.setColor (Color.green);
g.fillRect (0, 280, 400, 50 );
g.setColor (Color.black);
g.fillOval(_ballX, _ballY, BALL_DIAMETER, BALL_DIAMETER);
}
public void mousePressed(MouseEvent e)
{
int x = e.getX(); // Save the x coord of the click
int y = e.getY(); // Save the y coord of the click
if (x >= _ballX && x <= (_ballX + BALL_DIAMETER)
&& y >= _ballY && y <= (_ballY + BALL_DIAMETER)) {
_canDrag = true;
_dragFromX = x - _ballX; // how far from left
_dragFromY = y - _ballY; // how far from top
} else {
_canDrag = false;
}
}
//========= mouseDragged =================
/** Set x,y to mouse position and repaint. */
public void mouseDragged(MouseEvent e)
{
if (_canDrag) { // True only if button was pressed inside ball.
//--- Ball pos from mouse and original click displacement
_ballX = e.getX() - _dragFromX;
_ballY = e.getY() - _dragFromY;
//--- Don't move the ball off the screen sides
_ballX = Math.max(_ballX, 0);
_ballX = Math.min(_ballX, getWidth() - BALL_DIAMETER);
//--- Don't move the ball off top or bottom
_ballY = Math.max(_ballY, 0);
_ballY = Math.min(_ballY, getHeight() - BALL_DIAMETER);
this.repaint(); // Repaint because position changed.
}
}
//====================================================== method mouseExited
/** Turn off dragging if mouse exits panel. */
public void mouseExited(MouseEvent e)
{
System.out.println("Exited: " + e);
//_canDrag = false;
runGravity();
/* while(_ballY < ground_lvl)
{
simulateGravity();
}*/
}
Timer timer;
ActionListener animate;
public void runGravity() {
if (animate==null) {
animate = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("Ground: " + (_ballY-ground_lvl));
if (_ballY > ground_lvl) {
timer.stop();
} else {
simulateGravity();
}
}
};
timer = new Timer(100,animate);
}
timer.start();
}
public void simulateGravity()
{
System.out.println("_canDrag: " + _canDrag);
if(_canDrag)
{
velocity = velocity + GRAVITY;
if (velocity > TERM_VEL)
{
velocity = TERM_VEL;
}
if (_ballY >= ground_lvl - BALL_DIAMETER)
{
//We have hit the "ground", so bounce back up. Reverse
//the speed and divide by 4 to make it slower on bouncing.
//Just change 4 to 2 or something to make it faster.
velocity = velocity/4;
}
_ballY += velocity;
//this.revalidate();
this.repaint();
}
}
public void mouseMoved (MouseEvent e){}
public void mouseEntered (MouseEvent e){}
public void mouseClicked (MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
DragBallPanel dbp = new DragBallPanel();
JOptionPane.showMessageDialog(null, dbp);
}
});
}
}
Try updateUI() instead of repaint().
If there is no effect remove the component and add it again.