Trying to make pong in java but can't move both paddles at once. You can move one or the other but not both at the same time. Do I need to create 2 threads with 2 different pannels?
Here is where I am specifying the key events
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_A || e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_QUOTE || e.getKeyCode() == KeyEvent.VK_SEMICOLON){
if(e.getKeyCode() == KeyEvent.VK_A){
y-=10;
}
if(e.getKeyCode() == KeyEvent.VK_S){
y+=10;
}
if(e.getKeyCode() == KeyEvent.VK_QUOTE){
ytwo-=10;
}
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON){
ytwo+=10;
}
}
}
Here is the full code
import java.awt.Color;
import java.awt.Event;
import java.awt.Graphics;
import java.util.Random;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Pong extends JFrame implements ActionListener{
//implement constants
PongPanel pongPanel = new PongPanel();
//JFrame pong x and y coordinates
static final int jfpX = 150;
static final int jfpY = 20;
// JFrame pong width and height
static final int jfpW = 800;
static final int jfpH = 600;
Thread thrd;
public static void main(String[] args) {
Pong jfp = new Pong();
jfp.setVisible(true);
}
public Pong(){
setBounds(jfpX,jfpY,jfpW,jfpH);
setTitle("Pong");
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground(Color.black);
add(pongPanel);
addKeyListener(pongPanel);
thrd = new Thread (pongPanel);
thrd.start();
}
public void actionPerformed(ActionEvent e) {
}
}
class PongPanel extends JPanel implements Runnable, KeyListener{
Random random = new Random();
static final int jpW = 800;
static final int jpH = 600;
int paddleStart = (jpH/2)-35;
int paddleStarttwo = (jpH/2)-35;
int ballStartX = (jpW/2)-20;
int ballStartY = (jpH/2)-20;
int ytwo,x,y;
int ballD = 30;
int paddleW1 = 20;
int paddleH1 = 100;
int paddleW2 = 20;
int paddleH2 = 100;
int min = -2;
int max = 2;
int randomBallx, randomBally;
// int randomBallx = random.nextInt(max-min+1)+min;
// int randomBally = random.nextInt(max-min+1)+min;
int rand1 = random.nextInt(2-1 + 1)+1; // random for function to determine ballx and bally
int rand2 = random.nextInt(2-1+2)+1;
int dx = 4;
int dy = 4; //direction of y
public void ballNotZero(){// makes sure the ball doesnt go straight up and down
if (randomBallx ==0){
randomBallx = random.nextInt(max-min+1)+min;
}
if(randomBally == 0){
randomBally=random.nextInt(max-min+1)+min;
}
// if(rand1 ==1){
// randomBallx=-1;
// }
// if(rand1 ==2){
// randomBallx=1;
// }
// if(rand2 ==1){
// randomBally =-1;
// }
// if(rand2==2){
// randomBally = 1;
// }
}
public PongPanel(){
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Color ball;
Color paddleOne;
Color paddleTwo;
ball = new Color(255,0,255);
paddleOne = new Color(255,0,0);
paddleTwo = new Color(0,0,255);
g.setColor(ball);
g.fillOval(ballStartX+randomBallx,ballStartY+randomBally,ballD,ballD);
g.setColor(paddleOne);
g.fillRect(20,paddleStart+y,paddleW1,paddleH1);
g.setColor(paddleTwo);
g.fillRect(760,paddleStarttwo+ytwo,paddleW2,paddleH2);
}
public void run() {
while(true){
ballNotZero();
detectPaddle();
randomBall();
ballMove();
repaint();
try {Thread.sleep(75); } catch(Exception e){
};
}
}
public static boolean intervallContains(int low, int high, int n) { //determines if something is in a certain range
return n >= low && n <= high;
}
public void detectPaddle(){ //determines if ball is close enough to paddle for detection
int withinY = (paddleStart+y) -(ballStartY+randomBally);
int withinY1 = (paddleStarttwo+ytwo)-(ballStartY+randomBally);
if (ballStartX+randomBallx <=20 && intervallContains(-50,50,withinY)){
dx = -dx;
}
if(ballStartX+randomBallx >=760 && intervallContains(-50,50,withinY1)){
dx = -dx;
}
}
public void randomBall(){
if(randomBallx >=0 ){
randomBallx+=dx;
}
if(randomBallx<0){
randomBallx-=dx;
}
if(randomBally>=0){
randomBally+=dy;
}
if(randomBally<0){
randomBally-=dy;
}
// randomBallx+=randomBallx;
// randomBally+=randomBally;
}
public void ballMove(){
if(ballStartY+randomBally > jpH-60){
dy= -dy;
}
if(ballStartY+randomBally <0){
dy = -dy;
}
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_A || e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_QUOTE || e.getKeyCode() == KeyEvent.VK_SEMICOLON){
if(e.getKeyCode() == KeyEvent.VK_A){
y-=10;
}
if(e.getKeyCode() == KeyEvent.VK_S){
y+=10;
}
if(e.getKeyCode() == KeyEvent.VK_QUOTE){
ytwo-=10;
}
if(e.getKeyCode() == KeyEvent.VK_SEMICOLON){
ytwo+=10;
}
}
}
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Don't use while (true) but rather a Swing timer.
Don't use KeyListeners but rather Key Bindings.
Consider turning on a Swing Timer (which can act as your "background thread") that moves one paddle when the bindings detect the correct key has been pressed,
and stopping the timer that moves the paddle when the same key is released.
Same for the other paddle but of course having its actions respond to a bindings of a different pair of keys.
When attempting to get something like this working, try to get it working in a very simple program first, one without all the other junk required for your main program, but one which will allow you to test and prove your concept. Then if you get things working in your small program, great, you add the functionality to your main program. And if your small program code doesn't work and you need our help, you can post the small self-contained program here (an sscce) for us to test and modify.
Related
First of all, sorry for my english!
I have a problem, I´m trying to make a simple java videogame, and I make booleans for the inputs. The inputs works well, but when I try to update the booleans in another class, it doesnt work.
I put here the important classes
I put all the classes in this drive.
Classes
package Launcher;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyHandler implements KeyListener {
public boolean upPressed, downPressed, leftPressed, rightPressed;
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_W){
upPressed = true;
System.out.println(upPressed);
}
if(code == KeyEvent.VK_S){
downPressed = false;
}
if(code == KeyEvent.VK_A){
leftPressed = true;
}
if(code == KeyEvent.VK_D){
rightPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_W){
upPressed = false;
}
if(code == KeyEvent.VK_S){
downPressed = false;
}
if(code == KeyEvent.VK_A){
leftPressed = false;
}
if(code == KeyEvent.VK_D){
rightPressed = false;
}
}
}
package Launcher;
import java.awt.*;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
//Window settings variables
KeyHandler KH = new KeyHandler();
final int originalTileSize = 16; //16x16px
final int scale = 3;
final int tileSize = originalTileSize * scale; //48x48px
final int maxScreenCol = 16; //Tiles in a column
final int maxScreenRow = 12; //Tiles in a row
final int maxScreenWidth = tileSize * maxScreenCol;
final int maxScreenHeight = tileSize * maxScreenRow;
Thread gameThread;
//Player pos
int playerX = 100;
int playerY = 100;
int playerSpeed = 4;
public GamePanel(){
//Window Settings with variable implementation
this.setPreferredSize(new Dimension(maxScreenWidth, maxScreenHeight));
this.setBackground(Color.black);
this.setDoubleBuffered(true);
this.addKeyListener(KH);
this.setFocusable(true);
}
public void startGameThread(){
gameThread = new Thread(this);
gameThread.start();
}
public void update(){
//System.out.println(playerY);
boolean upP = KH.upPressed;
//System.out.println(upP);
if(upP){
System.out.println("Updating");
playerY -= playerSpeed;
}
else if(KH.downPressed == true){
playerY += playerSpeed;
}
else if(KH.leftPressed == true){
playerX -= playerSpeed;
}
else if(KH.rightPressed){
playerX += playerSpeed;
}
}
public void run(){
while(gameThread != null){
//System.out.println("Running game");
//1.Update
update();
//2Draw screen info
repaint();
}
}
I only want the update function get the boolean variables, for me to be able to move my character. Thank you so much!
I had a look at the other classes and the reason is outside the code above, it's in class Launcher.Main:
public static void main(String[] args){
WindowPanel WP = new WindowPanel();
WP.windowPanel();
GamePanel GP = new GamePanel();
GP.startGameThread();
}
in here you create a new instance of class WindowPanel, which - by itself - create a another instance of GamePanel.
public void windowPanel(){
// ...
GamePanel gamePanel = new GamePanel();
window.add(gamePanel);
window.pack();
// ...
}
So, the GamePanel that you created in Main, after you created the WindowPanel is not related to the GamePanel you create afterwards and start threading.
Fix:
remove the additional GamePanel from Main class
add to the end of windowPanel() method in WindowPanel class:
gamePanel.startGameThread();
I am generally a very bad programmer but have been trying to learn game development for a school project. My problem is that I have a draw method that draws a white rectangle and have a key Listener for movement but for some reason it moves upward despite what key I press not just W A S and D.
If you could help with this I would appreciate.
thanks
package Main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
final int screenHeight = 600;
final int screenWidth = 800;
final int playerSize = 48;
int fps = 60;
KeyHandler keyH = new KeyHandler();
Thread gameThread;
//player default position
int playerX = 100;
int playerY = 100;
int playerSpeed = 1;
public GamePanel() {
this.setPreferredSize(new Dimension (screenWidth, screenHeight));
this.setBackground(Color.black);
this.setDoubleBuffered(true);
this.addKeyListener(keyH);
this.setFocusable(true);
}
public void startGameThread() {
gameThread = new Thread (this);
gameThread.start();
}
public void run() {
double drawInterval = 1000000000/fps; // 0.01666 seconds = 60 times per seconds
double nextDrawTime = System.nanoTime() + drawInterval;
while(gameThread != null) {
System.out.println("this gmae is runing");
// update information such as character positions
// draw the screen with the updated information
update();
repaint();
try {
double remainingTime = nextDrawTime - System.nanoTime();
remainingTime = remainingTime/1000000;
if(remainingTime<0) {
remainingTime = 0;
}
Thread.sleep ((long) remainingTime);
nextDrawTime += drawInterval;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void update() {
if(keyH.upPressed ==true) {
playerY = playerY - playerSpeed;
}
else if (keyH.downPressed ==true){
playerY = playerY + playerSpeed;
}
else if (keyH.leftPressed== true){
playerX = playerX - playerSpeed;
}
else if (keyH.rightPressed == true) {
playerX = playerX +playerSpeed;
}
}
public void paintComponent(Graphics g) {
// to draw something
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.white);
g2.fillRect(playerX, playerY, playerSize, playerSize);
g2.dispose();
}
}
package game;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyHandler implements KeyListener {
public boolean leftPressed;
public boolean rightPressed;
public boolean upPressed;
public boolean downPressed;
public boolean spacePressed;
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_D);{
rightPressed = true;
}
if(code == KeyEvent.VK_A);{
leftPressed = true;
}
if(code == KeyEvent.VK_W);{
upPressed = true;
}
if(code == KeyEvent.VK_S);{
downPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
int code = e.getExtendedKeyCode();
if(code == KeyEvent.VK_D);{
rightPressed = false;
}
if(code == KeyEvent.VK_A);{
leftPressed = false;
}
if(code == KeyEvent.VK_W);{
upPressed = false;
}
if(code == KeyEvent.VK_S);{
downPressed = false;
}
}
}
I have been trying my best to work out collision detection between Pacman and the walls, however my implementation doesn't seem to work as correctly
Does collision detection work at all? Yes
Does it behave correctly? No
How is it currently behaving? When you hit a wall it stops Pacman
from moving which is okay, however any new key presses to move only changes
the images axis (up, right, down or left depending on key press),
it will not move the Pacman beyond its current location after hitting the wall.
Any assistance would be greatly appreciated. thanks in advance
GamePanel.java
package pacman;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements Runnable{
private Thread animator;
private boolean isRunning;
private Map map = new Map();
public GamePanel(){
this.setBackground(Color.BLACK);
this.setDoubleBuffered(true);
addKeyListener(new TAdapter());
setFocusable(true);
}
#Override
public void run() {
isRunning = true;
System.out.println("Is running? "+isRunning);
long startTime, timeDiff, sleepTime;
startTime = System.currentTimeMillis();
while(isRunning){
repaint();
gameUpdate();
timeDiff = System.currentTimeMillis() - startTime;
sleepTime = 5 - timeDiff;
try{
Thread.sleep(sleepTime);
}
catch(InterruptedException ex){
System.exit(0);
}
startTime = System.currentTimeMillis();
}
// gameOver(); not implemented yet, will focus on this when I have some basic animation and the game loop working to satisfaction.
}
#Override
public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if(animator == null || !isRunning){
animator = new Thread(this);
animator.start();
}
} //end of StartGame method
public void gameUpdate(){
map.getPlayer().move();
checkCollision();
} //implementation of ingame updates such as pacman getting killed.
public void checkCollision(){ //this is where I officially set collision up
for(int i = 0; i < map.tiles.length; i++){
for(int j = 0; j < map.tiles.length; j++){
if(map.tiles[i][j] != null){
if(map.getPlayer().getPlayerBox().intersects(map.tiles[i][j].getR())){
map.getPlayer().setColliding(true);
System.out.println("OWW"+map.tiles[i][j].getR().getLocation());
}
}
}
}
}
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
super.paintComponent(g);
if(isRunning){
drawDot(g2d);
drawPlayer(g2d);
map.drawMap(g2d);
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void drawDot(Graphics2D g){
g.setColor(Color.GREEN);
for(int x= 0; x < 400; x++){
for(int y = 0; y < 400; y++){
g.drawRect(x * 20, y * 20, 1, 1);
}
}
}
public void drawPlayer(Graphics2D g){
g.drawImage(map.getPlayer().getImage(), map.getPlayer().getX(),map.getPlayer().getY(), this);
}
private class TAdapter extends KeyAdapter{
#Override
public void keyPressed(KeyEvent e) {
map.getPlayer().keyPressed(e);
}
#Override
public void keyReleased(KeyEvent e) {
map.getPlayer().keyReleased(e);
}
}
}
Player.java
package pacman;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Player extends Commons{
private int dx, dy;
private int speed = 1;
private static int playerWidth = 52; //these figures seem off, but that is because the image is not designed correctly or the pacman image is not obeying the logic of not going passed the frame size.
private static int playerHeight = 82;
private Rectangle playerBox;
private Image playerImg = new ImageIcon(Player.class.getResource("Pacman.png")).getImage();
private Image playerImgUp = new ImageIcon(Player.class.getResource("PacmanUp.png")).getImage();
private Image playerImgLeft = new ImageIcon(Player.class.getResource("PacmanLeft.png")).getImage();
private Image playerImgDown = new ImageIcon(Player.class.getResource("PacmanDown.png")).getImage();
private boolean isColliding = false;
public Player(){
this.setX(320);
this.setY(280);
playerBox = new Rectangle(this.getX(), this.getY(),40,40);
}
public void setSpeed(int sp){
speed = sp;
}
public Image getImage(){
if(dy == 1){
return playerImgDown;
}
else if(dy == -1){
return playerImgUp;
}
else if(dx == -1){
return playerImgLeft;
}
else
return playerImg;
}//Responsible for displaying pacman image based on direction of pacman's movement.
void move(){
int x = this.getX();
int y = this.getY();
/*
* This is the part where I am trying to implement some degree of logic to stop it from moving
*/
if(isColliding == false){
this.setX(x += dx);
playerBox.setLocation(x, y);
this.setY(y += dy);
}else if(isColliding == true){
this.setColliding(false);
this.setX(this.getX());
this.setY(this.getY());
}
if (this.getX() <= 1) {
this.setX(1);
}
if (this.getX() >= 400 - playerWidth) {
this.setX(400 - playerWidth);
}
if (this.getY() <= 2) {
this.setY(2);
}
if (this.getY() >= 400 - playerHeight ) {
this.setY(400 - playerHeight);
}
}//Most simplist form of collision detection, stops pacman from leaving the JFrame
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT ){
dx = -speed;
dy = 0;
}
if(key == KeyEvent.VK_RIGHT){
dx = speed;
dy = 0;
}
if(key == KeyEvent.VK_UP){
dx = 0;
dy = -speed;
}
if(key == KeyEvent.VK_DOWN){
dx = 0;
dy = speed;
}
if(key == KeyEvent.VK_ESCAPE){
System.exit(0);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT){
dy = 0;
}
if(key == KeyEvent.VK_RIGHT){
dy = 0;
}
if(key == KeyEvent.VK_UP){
dx = 0;
}
if(key == KeyEvent.VK_DOWN){
dx = 0;
}
}//end of key release
public Rectangle getPlayerBox() {
return playerBox;
}
public void setPlayerBox(Rectangle playerBox) {
this.playerBox = playerBox;
}
public boolean isColliding() {
return isColliding;
}
public void setColliding(boolean isColliding) {
this.isColliding = isColliding;
}
}// end of class
It looks like what happens is the player enters a tile which causes collision and isColliding is set to true.
The next iteration of the game update calls movement code which checks the player's isColliding boolean. That condition is true and no movement occurs. Next, collision is checked and we haven't moved out of the tile causing the collision so we are stuck in this tile.
I suggest when collision happens to move the player just out of the colliding tile.
We know which direction the player is moving so we can use the inverse direction (multiply dx and dy by -1) to move the player out of the colliding tile.
I have just started to learn Java, so excuse my messy code. Looking all over the internet, I have not found a solution to this question yet. This is the game pong. I have to padels that I am controlling ith the keys, 'w', 's', up, and down. When I draw the panels in my graphics section, I use the padelY for Y1 and use padelY + padelLength(A constant) for Y2. I cannot seem to understand why when I rut the program the padels change size as I move them up and down. Also, the padel on the right is named panel1, when I draw the padel I use the screen size - the padel spacing for X1 yet the padel appears to be stuck on the side.
I would really appreciate any advice that anyone could give on those issues or how to clean up my code in general!
Thanks!
package Pong;
//Import Libraries
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class Pong extends JPanel implements KeyListener{
int padel1y = 150;
int padel2y = 150;
static final int padelLength = 100;
int padelWidth = 10;
int padelSpeed = 2;
int padel2Speed = 0;
int padel1Speed = 0;
int ballX = BOX_WIDTH/2;
int ballY= BOX_HEIGHT/2;
int ballXSpeed = 2;
int ballYSpeed = 1;
int ballRadius = 10;
int ballCount = 0;
public final static int ballSpeedIncrease = 500;
public final static int BOX_WIDTH = 600;
public final static int BOX_HEIGHT = 600;
public final static int UPDATE_RATE = 100;
public final static int padelSpace = 10;
public Pong() {
setPreferredSize(new Dimension(BOX_WIDTH,BOX_HEIGHT));
Thread gameThread = new Thread() {
public void run(){
while(true){
ballCount = ballCount + 1;
if(ballCount%ballSpeedIncrease == 0){
if(ballXSpeed < 0){
ballXSpeed = ballXSpeed - 1;
}
if(ballYSpeed < 0){
ballYSpeed = ballYSpeed - 1;
}
if(ballXSpeed > 0){
ballXSpeed++;
}
if(ballYSpeed > 0){
ballYSpeed++;
}
}
if(ballX-ballRadius <= 10+padelWidth){
if(ballY<padel2y || ballY>padel2y+padelLength){
System.exit(0);
}
else{
ballXSpeed = -ballXSpeed;
}
}
else if(ballX+ballRadius >= 590-padelWidth){
if(ballY<padel1y || ballY>padel1y+padelLength){
System.exit(0);
}
else{
ballXSpeed = -ballXSpeed;
}
}
if(ballY-ballRadius <= 0){
ballYSpeed = -ballYSpeed;
}
else if(ballY+ballRadius >= BOX_HEIGHT){
ballYSpeed = -ballYSpeed;
}
padel1y = padel1y +padel1Speed;
padel2y = padel2y +padel2Speed;
ballX = ballX + ballXSpeed;
ballY = ballY+ ballYSpeed;
repaint();
try {
Thread.sleep(1000 / UPDATE_RATE);
}
catch (InterruptedException ex) {}
}
}
};
gameThread.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0,0,BOX_WIDTH,BOX_HEIGHT);
g.setColor(Color.blue);
g.fillRect(padelSpace,padel2y,padelSpace + padelWidth,padel2y+padelLength);
g.fillRect(BOX_WIDTH-padelSpace,padel1y,BOX_WIDTH-padelSpace-padelWidth,padel1y+padelLength);
g.setColor(Color.green);
g.fillOval(ballX, ballY, ballRadius*2, ballRadius*2);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Create Frame
JFrame frame = new JFrame("PONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONGPONG");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Pong pong = new Pong();
frame.setContentPane(pong);
frame.setSize(BOX_WIDTH,BOX_HEIGHT);
frame.pack();
frame.addKeyListener(pong);
frame.setVisible(true);
}
});
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP){
padel1Speed = -padelSpeed;
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN){
padel1Speed = padelSpeed;
}
else if(e.getKeyCode() == KeyEvent.VK_W){
padel2Speed = -padelSpeed;
}
else if(e.getKeyCode() == KeyEvent.VK_S){
padel2Speed = padelSpeed;
}
}
#Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
padel1Speed = 0;
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN){
padel1Speed = 0;
}
else if(e.getKeyCode() == KeyEvent.VK_W){
padel2Speed = 0;
}
else if(e.getKeyCode() == KeyEvent.VK_S){
padel2Speed = 0;
}
}
#Override
public void keyTyped(KeyEvent e) {}
}
See this for documentation on how to use the fillRect() method: https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html#fillRect(int,%20int,%20int,%20int)
The arguments are: x position, y position, width and height.
You use it like this: g.fillRect(padelSpace,padel2y,padelSpace + padelWidth,padel2y+padelLength);
The second and third arguments are wrong. You should only be passing the width and height. Like this: g.fillRect(padelSpace, padel2y, padelWidth, padelLength);
More generally, when something is going wrong (drawing the paddle) read the documentation on the methods you use to do that.
The program works fine, but when I hold a key or change keys the motion is not smooth. It pauses for a split second before becoming smooth. I'm still a beginner at Java so please explain in detail.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Game2015
{
JFrame frame;
DrawRect mainPanel;
GridBagLayout gridbag;
GridBagConstraints constraints;
Data data;
int width;
int height;
public static void main(String[] args)
{
new Game2015();
}
public Game2015()
{
frame = new JFrame();
width = 400;
height = 500;
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
frame.setSize(width, height);
frame.setResizable(false);
data = new Data();
mainPanel = new DrawRect(data);
mainPanel.setFocusable(true);
mainPanel.setBackground(Color.WHITE);
KeyHandler keys = new KeyHandler();
mainPanel.addKeyListener(keys);
frame.add(mainPanel);
frame.validate();
frame.setLocationRelativeTo(null);
Thread thread = new Thread(new Runnable(){
public void run()
{
while(true)
{
mainPanel.repaint();
mainPanel.requestFocus(true);
}
}
});
thread.start();
}
public class KeyHandler implements KeyListener
{
public void keyReleased(KeyEvent event)
{
}
public void keyTyped(KeyEvent event)
{
}
public void keyPressed(KeyEvent event)
{
if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP)
{
if(data.getY() >= data.getSpeed())
{
data.setY(data.getY() - data.getSpeed());
}
else
{
data.setY(0);
}
}
else if(event.getKeyCode() == KeyEvent.VK_S || event.getKeyCode() == KeyEvent.VK_DOWN)
{
if(data.getY() + 95 <= height - data.getSpeed())
{
data.setY(data.getY() + data.getSpeed());
}
else
{
data.setY(height - 95);
}
}
else if(event.getKeyCode() == KeyEvent.VK_A || event.getKeyCode() == KeyEvent.VK_LEFT)
{
if(data.getX() >= data.getSpeed())
{
data.setX(data.getX() - data.getSpeed());
}
else
{
data.setX(0);
}
}
else if(event.getKeyCode() == KeyEvent.VK_D || event.getKeyCode() == KeyEvent.VK_RIGHT)
{
if(data.getX() + 75 <= width - data.getSpeed())
{
data.setX(data.getX() + data.getSpeed());
}
else
{
data.setX(width - 75);
}
}
else if(event.getKeyCode() == KeyEvent.VK_ESCAPE)
{
frame.dispose();
System.exit(0);
}
}
}
}
The code for drawing the rectangle is this:
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
public class DrawRect extends JPanel
{
BufferedImage img_player;
File file;
Data data;
public DrawRect(Data newData)
{
data = newData;
try
{
file = new File("Images\\Player.png");
img_player = ImageIO.read(file);
}
catch (Exception exception)
{
}
}
#Override
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
Graphics2D graphics2D = (Graphics2D) graphics;
graphics2D.drawImage(img_player, data.getX(), data.getY(), null);
}
}
and the code for the Data class is this:
public class Data
{
int x, y, speed;
public Data()
{
x = 0;
y = 0;
speed = 10;
}
public void setSpeed(int new_speed)
{
speed = new_speed;
}
public int getSpeed()
{
return speed;
}
public void setX(int new_x)
{
x = new_x;
}
public int getX()
{
return x;
}
public void setY(int new_y)
{
y = new_y;
}
public int getY()
{
return y;
}
}
This is because of have java handles events: When you first press a key, it fires an event (pressing the key), and only after a small period of time does it continue to fire events (holding the key). You can test this by printing out every time an event is fired, and it will have a small delay between the first and the rest of the events.
The way to work around this is instead of every time you press a key changing the characters position, change the characters velocity.
For example, instead of
if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
if(data.getY() >= data.getSpeed())
{
data.setY(data.getY() - data.getSpeed());
} else {
data.setY(0);
}
} ... etc ...
it would be
if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
data.setVelocityY(-data.getSpeed());
} ... etc ...
as well as that, you'd also need to stop their velocity when they release the key. In your keyReleased() method, just do the same thing, but instead of setting velocity to speed, set it to 0.
if(event.getKeyCode() == KeyEvent.VK_W || event.getKeyCode() == KeyEvent.VK_UP){
data.setVelocityY(0);
} ... etc ...
and then in your game loop and a method update() that handles calculations (adding velocity to position)
So
public void run() {
while(true) {
mainPanel.repaint();
mainPanel.requestFocus(true);
}
}
would be
public void run() {
while(true) {
update();
mainPanel.repaint();
mainPanel.requestFocus(true);
}
}
where the update method would be
public static void update() {
data.setY(data.getY() + data.getVelocityY());
data.setX(data.getX() + data.getVelocityX());
}
You should look up basic tutorials on java games. For example, I always found this a good introductory tutorial.