I am creating a track and field game and I need the player to tap the button to fill the meter up. When the player releases the key the meter goes down. Unfortunately, when I hold the button the meter fills up.
Code:
public class TapGame extends JPanel implements ActionListener, KeyListener{
Timer tm = new Timer(5,this);
int barHeight = 0, bar = 0;
boolean canPress = true;
public TapGame(){
tm.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 355, bar, 10);
g.setColor(Color.WHITE);
g.drawRect(0, 355, 100, 10);
}
public void actionPerformed(ActionEvent e){
bar+= barHeight;
bar -= 2;
if (bar < 0) bar = 0;
if (bar > 98) bar = 98;
repaint();
}
public void keyPressed(KeyEvent e){
int c = e.getKeyCode();
if (c == KeyEvent.VK_A){
if (canPress) {
barHeight = 4;
canPress = false;
}
else barHeight=0;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){
canPress = true;
barHeight =0;
}
public static void main(String[] args){
TapGame t = new TapGame();
JFrame jf = new JFrame("Tap Mini Game Test");
jf.setSize(600,400);
jf.setLocationRelativeTo(null);
jf.setVisible(true);
jf.add(t);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
It appears java calls those button presses multiple times. See here:
https://stackoverflow.com/questions/5199581/java-keylistener-keypressed-method-fires-too-fast
Related
This code is kind of a mess. Im trying to prevent the mouse from going outside the red. MouseMotionListener is not working. Ive added The Listener, implemented it. When I try to use e.getX()Nothing shows up! Here is the code: Any help is good!
Class MazeMouse
public class MazeMouse extends JPanel implements ActionListener, MouseMotionListener {
JButton d,k;
JLabel f;
int button = 0;
MazeMouse(){
addMouseMotionListener(this);
setBackground(Color.black);
f= new JLabel(" ");
k = new JButton("Press To Finish");
d = new JButton("Press To Begin");
add(d);
add(f);
add(k);
k.addActionListener(this);
d.addActionListener(this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if(button == 1) {
g2.setColor(Color.red);
//start Rect
g2.fillRect(150,0,200,50);
//below start
g2.fillRect(150, 50, 50, 200);
//finish Rect
g2.fillRect(450, 0, 200, 50);
//below finish
g2.fillRect(600,50,50,200);
//really tiny line
g2.fillRect(150, 250, 500, 1);
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==d)
{
button++;
d.setEnabled(false);
repaint();
}
if(e.getSource()==k) {
setBackground(Color.green);
}
}
#Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent e) {
e.getX();
if(button ==1) {
if(e.getX() < 150 && e.getX() > 350 ) {
System.out.println("Game Over");
}
}
}
}
And MM
public class MM {
JFrame f;
MazeMouse p;
int button = 0;
public MM(){
f = new JFrame();
Container c = f.getContentPane();
c.setLayout(new BorderLayout());
p = new MazeMouse();
c.add(p);
f.setSize(800,800);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[ ]){
MM t = new MM();
}
}
Thanks
I am writing a simple game and I am working with java in JFrame. My output looks very bad untill I move the platform at the bottom, it looks like it have not enought update rate untill I press a button update and when I release the key it does the same thing. So this is the complete code with 2 classes:
public class BrickBreaker {
private static final String TITLE = "break ball";
private static final int X = 200, Y = 200, WIDTH = 700, HEIGHT = 600;
public static void main(String[] arg){
JFrame window = new JFrame();
GamePlay gp = new GamePlay();
window.setBounds(X,Y,WIDTH,HEIGHT);
window.setTitle(TITLE);
window.setResizable(false);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(gp);
}
}
public class GamePlay extends JPanel implements KeyListener, ActionListener {
private boolean play = false;
private int score = 0, totalBricks = 21, delay = 10;
private int playerX = 310;
private int ballX = 120, ballY = 350, ballDirX = -1, ballDirY = -2;
private final Timer TIMER;
public GamePlay(){
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
TIMER = new Timer(delay, this);
TIMER.start();
}
public void paint(Graphics g){
//Background
g.setColor(Color.BLACK);
g.fillRect(1,1,700,592);
//Borders
g.setColor(Color.YELLOW);
g.fillRect(0,0,3,592);
g.fillRect(697,0,3,592);
g.fillRect(0,0,697,3);
//Paddle
g.setColor(Color.GREEN);
g.fillRect(playerX, 550, 100, 8);
//Ball
g.setColor(Color.YELLOW);
g.fillOval(ballX, ballY, 20, 20);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
TIMER.start();
if (play){
TIMER.start();
ballX += ballDirX;
ballY += ballDirY;
if(ballX <= 0 || ballX >= 700){
ballDirX = - ballDirX;
}
if(ballY <= 0 || ballY >= 600){
ballDirY = -ballDirY;
}
}
repaint();
}
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT){
if(playerX >= 590){
playerX = 590;
}else{
moveRight();
}
}else if(e.getKeyCode() == KeyEvent.VK_LEFT){
if(playerX <= 10){
playerX = 10;
}else{
moveLeft();
}
}
}
private void moveLeft() {
play = true;
playerX -= 20;
}
private void moveRight() {
play = true;
playerX += 20;
}
}
I want to know how to smooth the movement of the ball to be always at the rate of the keypressed state.
First of all there is no need to start the Timer in the ActionListener. You already start the Timer in the constructor.
JFrame updates my screen slow untill I press a key
There is no animation at all when I run the code.
Lets do some basic debugging:
public void actionPerformed(ActionEvent e) {
System.out.println(Play); // basic debugging
What do you see?
Then what happens when you press an arrow key?
Why do you only set the play variable in the moveRight/moveLeft methods?
When I press a specific key, I want to update an int value in another class and repaint a JPanel based on this updated int.
Here is my code for the class with the key_event:
frame.addKeyListener(new KeyListener(){
#Override
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_W){
dP.status = 1;
w.x = w.x; //pos.xC(pos.maxSize(frame));
w.y = w.Y(w.y, -w.val);
if ( w.y < 0) {
w.y = 0;
}
frame.validate();
dP.repaint();
System.out.println("w.y: "+w.y);
}
});
Here is my class with the int supposed to be updated:
public class Objects {
public int x = 10;
public int y = 10;
public int height = 10;
public int width = 10;
public int val = 5;
public void dW(Graphics stift){
stift.setColor(Color.RED);
stift.fillRect(x, y, width, height);
}
}
And here is my JPanel class:
public class DisplayPanel extends JPanel {
public Objects w = new Objects();
public int status = 0;
public void setUp(){
this.setBackground(Color.WHITE);
}
#Override
protected void paintComponent(Graphics stift){
super.paintComponent(stift);
if (status == 0){
stift.setColor(Color.RED);
stift.drawLine(200, 200, 400, 200);
stift.drawLine(200, 400, 300, 500);
stift.setColor(Color.GREEN);
stift.drawLine(200, 200, 2000, 200);
stift.fillRect(w.x, w.y, w.width, w.height);
}
while (status == 1){
w.dW(stift);
break;
}
}
}
While pressing the key for the first time, the JPanel is updated, the values for w.x and w.y wont update, they remain exact 10. How can I change this?
(PS: I know that it would be better to implement a switch case break statement for the key_events).
I am teaching myself 2D graphics in Java right now. I am trying to create a block-stacking game. So far, I am able to get the first row moving and stopping, but my aim is to generate a new row below the first while the first row stays in place. I feel like the fix for this is a simple concept I haven't learned yet. However, any advice will be appreciated. If you want to point me in the right direction to where I can teach myself 2D Graphics in general, I will appreciate that also.
My code for the JFrame is as follows:
public class BlockStacker extends JFrame {
public class AL extends KeyAdapter {
stack2 s2 = new stack2();
public void keyPressed(KeyEvent e){
int keyCode = e.getKeyCode();
}
}
public static void main(String[] args){
stack2 s = new stack2();
JFrame f = new JFrame();
f.add(s);
f.setVisible(true);
f.setSize(1920, 1080);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("Block Stacker");
}
}
The code with the graphics and the keylistener is this:
public class stack2 extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(250, this);
double x, y, velX = 253;
public stack2() {
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
setBackground(Color.BLACK);
Color blue = new Color(0,0,255);
g2.setColor(blue);
Rectangle2D.Double rectangle = new Rectangle.Double(x + 210, y, 200, 100);
g2.fill(rectangle);
Rectangle2D.Double rectangle2 = new Rectangle.Double(x, y, 200, 100);
g2.fill(rectangle2);
Rectangle2D.Double rectangle3 = new Rectangle.Double(x + 420, y, 200, 100);
g2.fill(rectangle3);
}
public void actionPerformed(ActionEvent e) {
if (x < 0) {
velX = -velX;
}
x += velX;
repaint();
if (x < 10 || x > 1200) {
velX = -velX;
repaint();
}
}
public void space() {
velX = 0;
repaint();
}
public void space2() {
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_SPACE) {
space();
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_SPACE) {
space2();
}
}
}
There are multiple problems...
You attach the KeyListener to JFrame, but a JFrame has a JRootPane, content pane and it's content between it and the user, any of those components could have keyboard focus, preventing the frame from receiving key events
You create a instance of Stack in both the KeyAdapter and then the frame, so the instance of Stack you are trying to change isn't the version that's on the screen
KeyListener only responds to key events when the component that they are registed to are focus able and have focus...
Use key bindings instead? See How to use key bindings
I'm recreating the classic snake game. I've already finished coding the snake. What I have to do now is code the walls (that are supposed to be located at the edges of the frame).
As the painter of the snake "repaints" every 30 miliseconds, I thought it would not be really efficient to let this painter draw the walls as well, as the walls stay on the same place during the whole game so it isn't really necessary to redraw the walls every 30 miliseconds.
Thus, I was wondering whether it was possible to have two painters in my game, one that repaints the snake every 30 miliseconds, and one that paints only once (it paints the walls at the beginning of the game)? How should I do that?
These are the most important parts of the code related to the question (full code can be found below this):
//this is in the main class
public Snake(){
painter = new Painter(this);
this.add(painter, BorderLayout.CENTER);
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);
this.requestFocusInWindow();
timer = new Timer(30, this);
startGame();
}
public void startGame(){
snakeList = new LinkedList<Point>();
snakeList.addFirst(new Point(10, 10));
snakeSegments(3);
setFood(30, 30);
movementX = 0;
movementY = 0;
timer.start(); //timer triggers gameUpdate();
}
public void gameUpdate(){
snakeMove(movementX, movementY);
snakeInstructor();
snakeEat();
snakeCollision();
painter.repaint();
}
-
// this is in the painter class
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
paintSnake(g);
paintFood(g);
}
This is the full code:
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Snake extends JFrame implements KeyListener, ActionListener{
Painter painter;
LinkedList<Point> snakeList;
Timer timer;
Point foodLocation;
int direction;
int snakeSize;
int movementX, movementY;
public static void main(String[] arg){
new Snake();
}
public Snake(){
painter = new Painter(this);
this.add(painter, BorderLayout.CENTER);
this.setSize(500, 500);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.addKeyListener(this);
this.requestFocusInWindow();
timer = new Timer(30, this);
startGame();
}
public void startGame(){
snakeList = new LinkedList<Point>();
snakeList.addFirst(new Point(10, 10));
snakeSegments(3);
setFood(30, 30);
movementX = 0;
movementY = 0;
timer.start();
}
public void gameUpdate(){
snakeMove(movementX, movementY);
snakeInstructor();
snakeEat();
snakeCollision();
painter.repaint();
}
public void snakeCollision(){
for(int i = 4; i < getSnakeSize(); i++){
if(getFirst().equals(snakeList.get(i))){
gameOver();
}
}
}
public void gameOver(){
timer.stop();
}
public void snakeEat(){
if(getFirst().equals(getFood())){
newFood();
setSnakeSize();
snakeSegments(4);
}
}
public void snakeSegments(int i){
snakeSize = i;
while(snakeSize > 0){
snakeList.addLast(new Point(getLast()));
snakeSize--;
}
}
public void snakeInstructor(){
int currentDirection = getDirection();
if (currentDirection == 1){
snakeMove(-1, 0);
} else if (currentDirection == 2){
snakeMove(1, 0);
} else if (currentDirection == 3){
snakeMove(0, -1);
} else if (currentDirection == 4){
snakeMove(0, 1);
}
}
public void snakeMove(int directionX, int directionY){
snakeList.getFirst().x = snakeList.getFirst().x + directionX;
snakeList.getFirst().y = snakeList.getFirst().y + directionY;
for(int i = getSnakeSize()-1; i >=1; i--) {
snakeList.get(i).setLocation(snakeList.get(i-1));
}
}
public void newFood(){
Random generator = new Random();
int x = generator.nextInt(49);
int y = generator.nextInt(47);
setFood(x, y);
}
public void setFood(int x, int y){
foodLocation = new Point(x, y);
}
public Point getFood(){
return foodLocation;
}
public void setDirection(int newDirection){
direction = newDirection;
}
public int getDirection (){
return direction;
}
Point getFirst(){
return snakeList.getFirst();
}
Point getLast(){
return snakeList.getLast();
}
Point get(int i){
return snakeList.get(i);
}
public void addFirst(Point p){
snakeList.addFirst(p);
}
public void addLast(Point p){
snakeList.addLast(p);
}
public int getSnakeSize(){
return snakeList.size();
}
public void setSnakeSize(){
snakeSize = getSnakeSize() + 1;
}
#Override
public void actionPerformed(ActionEvent event) {
gameUpdate();
}
#Override public void keyReleased(KeyEvent e){ }
#Override public void keyTyped(KeyEvent e){ }
#Override public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if((key == KeyEvent.VK_LEFT) && direction != 2){
setDirection(1);
} else if ((key == KeyEvent.VK_RIGHT) && direction != 1){
setDirection(2);
} else if ((key == KeyEvent.VK_UP) && direction != 4){
setDirection(3);
} else if ((key == KeyEvent.VK_DOWN) && direction != 3){
setDirection(4);
} else if (key == KeyEvent.VK_SPACE){
startGame();
}
}
}
-
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
public class Painter extends JPanel{
Snake snake;
public Painter(Snake snake){
this.snake = snake;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 500, 500);
paintSnake(g);
paintFood(g);
}
public void paintSnake(Graphics g){
for(int i = 0; i < snake.getSnakeSize(); i++){
g.setColor(Color.WHITE);
Point p = snake.snakeList.get(i);
g.fillRect(p.x*10, p.y*10, 10, 10);
}
}
public void paintFood(Graphics g){
Point p = snake.getFood();
g.setColor(Color.RED);
g.fillRect(p.x*10, p.y*10, 10, 10);
}
}
Yes and no...
You could make the Painter transparent and overlay the snake on top of the walls, but the call to g.fillRect(0, 0, 500, 500); would make that redundant, as it fills the entire component with the current color...
Seen as the paintComponent method for both painters would be called every time you want to update the UI, it's also kind of pointless.
A better solution would be to render the map to BufferedImage and paint it inside the painter before painting the snake.