Swing Timer with Graphics component - java

I want to creat a circle in on a panel which appears and dissapears every 2 seconds.
Here is that i have:
public class Board extends JPanel implements ActionListener {
private final int DELAY = 2000;
private Timer timer;
/*
* constructor
*/
public Board() {
setFocusable(true);
initGame();
}
/*
* initialize board
*/
public void initGame() {
timer = new Timer(DELAY, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.gray);
// draw an oval starting at 20,20 with a width and height of 100 and
// fill it
g.drawOval(20, 20, 100, 100);
g.fillOval(20, 20, 100, 100);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
thank you guys. Now I wanna control my circle. But again something is wrong and it is not moving as I want.
here are new methods:
private boolean left = false;
private boolean right = true;
private boolean up = false;
private boolean down = false;
private Timer timer;
public int x = 20;
public int y = 20;
public int x2 = 100;
public int y2 = 100;
...
public void paint(Graphics g) {
super.paint(g);
if (drawCircle) {
g.setColor(Color.gray);
// draw an oval starting at 20,20 with a width and height of 100 and
// fill it
g.drawOval(x, y, x2, y2);
g.fillOval(x, y, x2, y2);
}
// removes native non-Java recourses
g.dispose();
}
public void move() {
if (left) {
x -= 5;
}
if (right) {
x += 5;
}
if (up) {
y -= 5;
}
if (down) {
y += 5;
}
}
#Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
private class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_LEFT) && (!right)) {
left = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_RIGHT) && (!left)) {
right = true;
up = false;
down = false;
}
if ((key == KeyEvent.VK_UP) && (!down)) {
up = true;
right = false;
left = false;
}
if ((key == KeyEvent.VK_DOWN) && (!up)) {
down = true;
right = false;
left = false;
}
}
}
/****/
Solved , i just added
addKeyListener(new TAdapter());
to my Board constructor!

You just need to have your Timer modify some state. Try something like this:
private boolean drawCircle = false;
public void actionPerformed(ActionEvent e) {
drawCircle = !drawCircle;
repaint();
}
public void paintComponent(Graphics g) {
//...
if ( drawCircle ) {
g.setColor(Color.gray);
//...
}
}

Aren't you supposed to formulate the question... as a question?
Anyway, add a boolean to your class, toggle it on each action event, and paint the oval only if it is true.
Edit/Notes:
- Override paintComponent instead of paint
- Don't dispose of a Graphics you haven't created. Either drop the line, or use g.create() to make a copy. See http://java.sun.com/products/jfc/tsc/articles/swing2d/ for details.

Related

Java cannot get action/key listener to work

I am coding a Java pong game I am stuck on how to get the player paddle to move. I for some reason cannot get the program to notice the key inputs.
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Pong {
Board board = new Board();
public void frame() {
JFrame b = new JFrame("Pong");
b.setSize(905,705);
b.setLocation(300,60);
b.setResizable(false);
b.setVisible(true);
b.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
b.add(board);
}
public static void main(String[] args) {
Pong start = new Pong();
start.frame();
}
}
The board class
public class Board extends JPanel{
public int playerScore = 0;
public int opponentScore = 0;
Player player = new Player();
int test = 1;
private Timer timer;
private int time = 100;{
timer = new Timer(time, player);
timer.start();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
board(g);
g.setColor(Color.WHITE);
// player.playerGenerate();
g2d.fill(player.player);
g.fillRect(30, test, 20, 20);
player.paint(g);
control();
//repaint();
}
public void board(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g.setColor(Color.black);
g.fillRect(0, 0, 900, 900);
Stroke stroke1 = new BasicStroke(4f);
g2d.setColor(Color.white);
g2d.setStroke(stroke1);
g2d.drawRect(20, 50, 850, 600);
g2d.setColor(Color.white);
float[] dashingPattern2 = {10f, 4f};
Stroke stroke2 = new BasicStroke(4f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 1.0f, dashingPattern2, 0.0f);
g2d.setStroke(stroke2);
g2d.drawLine(435, 50, 435, 650);
g.setFont(new Font("arial",Font.PLAIN,30));
g.drawString(""+playerScore, 20, 35);
g.drawString(""+opponentScore, 855, 35);
}
public void control() {
if (player.down == true) {
player.playerYpos = player.playerYpos = player.playerYpos -10;
repaint();
}
}
}
And finally the player class.
public class Player extends JPanel implements KeyListener,ActionListener{
//Board theBoard = new Board();
public boolean down = false;
public boolean up = false;
public int playerXpos = 45;
public int playerYpos = 300;
public int playerWidth = 15;
public int playerHeight = 80;
Rectangle player = new Rectangle(playerXpos,playerYpos,playerWidth,playerHeight);
// Board theBoard = new Board();
public void playerGenerate() {
playerXpos = 45;
playerYpos = 300;
playerWidth = 15;
playerHeight = 80;
//Rectangle r = new Rectangle(playerXpos,playerYpos,playerWidth,playerHeight);
}
#Override
public void actionPerformed(ActionEvent e) {
if (down) {
down = true;
if(up != true) {
down = true;
}
else
{
up = true;
down = false;
}
}
if (up) {
up = true;
if(down != true) {
up = true;
}
else
{
up = false;
down = true;
}
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP) {
for(int r = playerYpos;r >=0;r--) {
if(r==0) {
playerYpos = playerYpos -20;
}
else {
playerYpos = playerYpos -1 ;
}
if(playerYpos < 50){
playerYpos = 50;
}
}
//repaint();
}
if(e.getKeyCode() == KeyEvent.VK_DOWN) {
for(int r = playerYpos;r >=0;r--) {
if(r==0) {
playerYpos = playerYpos +20;
}
else {
playerYpos = playerYpos -1 ;
System.out.print("down");
}
if(playerYpos > 800){
playerYpos = 800;
}
}
//repaint();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
I tried googling around and looked at code that went with a similar approach of implementing action/key listener in the player/paddle class. I assume there is something minor and small I am just not seeing.
You have just wrote the method names. You need to register action/key listener to a particular swing component which you want to listen.
Suppose if your JComponent is JButton named btnPlayer you need to register the action performed event like :
private void btnPlayerActionPerformed(java.awt.event.ActionEvent e) {....
...}
You can add action listener from swing design. Right click on the JComponent -> Events -> ActionPerformed.
It will register click event for the component. Adding events through the properties is a better option.

How to make the sprite move once when arrow key is pressed?

I am trying to make the sprite stop continuously moving. Right now, the code makes the sprite move in the direction indicated by the user through arrow keys without stopping. I want to press an arrow key and make the sprite move once (ex. 10 steps only) in that direction.
public class Contents extends JPanel implements ActionListener, KeyListener {
Timer t = new Timer(100, this);
private Image man;
int x=0, y=0;
public Contents() {
super.setDoubleBuffered(true);
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
#Override
public void paintComponent (Graphics g) {
super.paintComponent(g);
super.setBackground(Color.white);
ImageIcon ii = new ImageIcon("guy.png");
man = ii.getImage();
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(man, x, y, this);
}
double xv = 0;
double yv = 0;
public void move() {
x += xv;
y += yv;
}
public void up() {
yv = -1;
xv = 0;
}
public void down() {
yv = 1;
xv = 0;
}
public void left () {
xv = -1;
yv = 0;
}
public void right () {
xv = 1;
yv = 0;
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
//Collision for left and right walls
if (x==0) {
xv = 1;
}
else if (x==900-240) {
xv = -1;
}
// Collision for top and bottom walls
if (y==0) {
yv = 1;
}
else if (y==600-320) {
yv = -1;
}
move();
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
}
It works when I delete the boundaries under ActionEvent. The boundaries prevent the sprite from going off screen. But I want to keep the boundaries and control the sprite too.
I figured it out. Under keyReleased, set xv=0. Then when you release the arrow key, the sprite will stop moving.

Why does this not draw my Polygon? (Java game)

Basically, all that shows up is a JFrame with the black JPanel inside but no Ball/polygon anywhere. It's really annoying me now and I can't see the reason why. Any help greatly appreciated.
EDIT: Added code. Sorry for posting to Github, didn't know it was frowned upon.
public class Board extends JFrame {
private int width = 800;
private int height = 1000;
private int currentKeyCode = 0;
private boolean keyHeldDown = false;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
Board b = new Board();
b.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Board() {
setSize(width, height);
setTitle("Drop");
setBackground(Color.BLACK);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
currentKeyCode = KeyEvent.VK_RIGHT;
keyHeldDown = true;
System.out.println("Right + 10");
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
currentKeyCode = KeyEvent.VK_LEFT;
keyHeldDown = true;
System.out.println("Left + 10");
}
if (e.getKeyCode() == KeyEvent.VK_P) {
currentKeyCode = KeyEvent.VK_P;
keyHeldDown = true;
System.out.println("Pause");
}
}
#Override
public void keyReleased(KeyEvent e) {
keyHeldDown = false;
}
});
setContentPane(new Panel(this));
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5);
executor.scheduleAtFixedRate(new RepaintBoard(this), 0L, 20L, TimeUnit.MILLISECONDS);
}
#Override
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
#Override
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
private class RepaintBoard implements Runnable {
final Board board;
public RepaintBoard(Board board) {
this.board = board;
}
#Override
public void run() {
board.repaint();
}
}
}
class Panel extends JComponent {
Ball ball;
private Board board;
public Panel(Board board) {
this.board = board;
ball = new Ball();
}
#Override
public void paint(Graphics g1) {
Graphics2D g = (Graphics2D) g1;
g.setColor(Color.BLACK);
g.drawRect(0, 0, board.getWidth(), board.getHeight());
g.drawPolygon(ball);
}
}
class Ball extends Polygon {
private int radius = 5;
private Point loc;
private int[] xPos = new int[radius * 2 + 1];
private int[] yPos = new int[radius * 2 + 1];
public Ball() {
for (int i = -radius, j = 0; i <= radius; i++, j++) {
xPos[j] = i;
yPos[j] = i;
}
new Ball(xPos, yPos, radius * 2 + 1, 100, 100);
}
public Ball(int[] xPos, int[] yPos, int points, int x, int y) {
super(xPos, yPos, points);
loc = new Point(x, y);
for (int i : xPos) {
System.out.println(i);
}
}
}
Don't have Ball extends Polygon
Put a drawBall(Grapchics g) {} method in the Ball class, and do your ball painting in there.
call the drawBall method in the paint
ball.drawBall(g);
Don't override paint, instead override paintComponent on the panel, and don't forget to call super.paintComponent
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
This new Ball(xPos, yPos, radius * 2 + 1, 100, 100); in your constructor does absolutely nothing. You should instead just use the second constructor, and create the ball with that constructor. Each ball should be different, so a no-arg constructor is pointless

Problems with KeyBindings

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.

Ball is not moving like I want

i want to create a Pong game. I want to move the ball in a way until it touch a wall. if it touch the wall, it go the other way. The problem is that when I start playing, the ball goes in the right way but when it touch the wall, the ball direction reverse but only for one pixel so the ball reverse for 1 pixel and then the direction change angain and it touch the wall again. My code for the moving ball is in the initBall method. Please help me :(
here is my playPanel class :
private int posX = SCREEN_WIDTH / 2;
private int posY;
public Point posMouse = new Point();
private Point posBall = new Point();
private int playPanelWidth;
private int playPanelHeight;
private int padPanelWidth;
private int padPanelHeight;
private int panPanelWidth;
private int panPanelHeight;
private JLabel player1Score = new JLabel("0");
private JLabel ComputerScore = new JLabel("0");
private JPanel panPlayer1;
public JPanel panComputer;
public JPanel padPlayer1;
public JPanel padComputer;
private JButton but_Escape = new JButton("Press escape to continue !");
/*
* Constructor
*/
// ==============================================
public PlayPanel() {
super(new BorderLayout());
setBackground(PANPLAY_COLOR);
panPlayer1 = new JPanel();
panComputer = new JPanel();
padPlayer1 = new JPanel();
padComputer = new JPanel();
padPlayer1.setBackground(Color.DARK_GRAY);
padComputer.setBackground(Color.DARK_GRAY);
padPlayer1.setPreferredSize(PADPANEL_SIZE);
padComputer.setPreferredSize(PADPANEL_SIZE);
panPlayer1.setBackground(PANPLAY_COLOR);
panComputer.setBackground(PANPLAY_COLOR);
panPlayer1.add(padPlayer1);
panComputer.add(padComputer);
add(panPlayer1, BorderLayout.WEST);
add(panComputer, BorderLayout.EAST);
addMouseMotionListener(this);
panPlayer1.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent arg0) {
setPanPanelWidth(arg0.getComponent().getSize().width);
setPanPanelHeight(arg0.getComponent().getSize().height);
}
});
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent arg0) {
setPlayPanelWidth(arg0.getComponent().getSize().width);
setPlayPanelHeight(arg0.getComponent().getSize().height);
}
});
}
/*
* Setters and Getters
*/
// ==============================================
public int getPosX() {
return posX;
}
public void setPosX(int posX) {
this.posX = posX;
}
public int getPosY() {
return posY;
}
public void setPosY(int posY) {
this.posY = posY;
}
public JPanel getPanPlayer1() {
return panPlayer1;
}
public void setPanPlayer1(JPanel panPlayer1) {
this.panPlayer1 = panPlayer1;
}
public JPanel getPanComputer() {
return panComputer;
}
public void setPanComputer(JPanel panComputer) {
this.panComputer = panComputer;
}
public int getPlayPanelHeight() {
return playPanelHeight;
}
public void setPlayPanelHeight(int playPanelHeight) {
this.playPanelHeight = playPanelHeight;
}
public int getPlayPanelWidth() {
return playPanelWidth;
}
public void setPlayPanelWidth(int playPanelWidth) {
this.playPanelWidth = playPanelWidth;
}
public int getPadPanelWidth() {
return padPanelWidth;
}
public void setPadPanelWidth(int padPanelWidth) {
this.padPanelWidth = padPanelWidth;
}
public int getPadPanelHeight() {
return padPanelHeight;
}
public void setPadPanelHeight(int padPanelHeight) {
this.padPanelHeight = padPanelHeight;
}
public int getPanPanelWidth() {
return panPanelWidth;
}
public void setPanPanelWidth(int panPanelWidth) {
this.panPanelWidth = panPanelWidth;
}
public int getPanPanelHeight() {
return panPanelHeight;
}
public void setPanPanelHeight(int panPanelHeight) {
this.panPanelHeight = panPanelHeight;
}
/*
* Add the ball
*/
// ==============================================
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.BLACK);
initBall(g2);
// trait épais
g2.setColor(Color.DARK_GRAY);
g2.setStroke(new BasicStroke(10));
g2.drawLine((getPlayPanelWidth() / 2) - 5, getPlayPanelHeight(),
(getPlayPanelWidth() / 2) - 5, 0);
}
/*
* Init ball
*/
// ==============================================
private void initBall(Graphics2D graphics2d) {
int x = getPosX(), y = getPosY();
boolean backX = false;
boolean backY = false;
Graphics2D g2 = graphics2d;
g2.fillOval(posX, posY, BALL_WIDTH, BALL_HEIGHT);
//posBall.setLocation(posX + BALL_WIDTH, posY + (BALL_HEIGHT / 2));
if (x < 1)
backX = false;
if (x > getWidth() - 50)
backX = true;
if (y < 1)
backY = false;
if (y > getHeight() - 50)
backY = true;
if (!backX)
setPosX(++x);
else {
setPosX(--x);
}
if (!backY)
setPosY(++y);
else
setPosY(--y);
repaint();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
}
#Override
public void mouseMoved(MouseEvent arg0) {
posMouse.setLocation(arg0.getX(), arg0.getY()
- (getPadPanelHeight() / 2));
padPlayer1.setLocation(getPanPanelWidth() - 15, (int) posMouse.getY());
padComputer.setLocation(5, (int) posMouse.getY());
}
}
So you have:
private void initBall(Graphics2D graphics2d) {
int x = getPosX(), y = getPosY();
boolean backX = false;
boolean backY = false;
in the beginning, so that regardless of which direction the ball is going, booth booleans are set to false every time. Then, you don't have an "Else" when it comes to setting the back option in
if (x < 1)
backX = false;
if (x > getWidth() - 50)
backX = true;
if (y < 1)
backY = false;
if (y > getHeight() - 50)
backY = true;
What is happening is that the ball is moving in the right direction, until it hits a wall (I'm guessing the top wall). then this is called:
if (y > getHeight() - 50)
backY = true;
So then for that iteration the ball goes back because of
if (!backY)
setPosY(++y);
else
setPosY(--y);
But then you set it back to false right away. I suggest you have
private boolean backX = false; //same for backY
outside your method.

Categories