So I am trying to make my own version of the Pong game. My problems with this program is that my player doesn't move. I think I made a mistake but because I am really new to java I don't fully understand game mechanics in code. Could one of you please review my code carefully and tell me whats wrong and how to correct it. Also, would one of you tell me where did you learn or where can I learn game development with Java. Your answers will be really appreciated.
Window Class
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Window{
public Window(){
JFrame window = new JFrame();
GamePanel gamePanel = new GamePanel();
window.setSize(720, 480);
window.setResizable(true);
window.setTitle("2DGame");
window.add(gamePanel);
window.setUndecorated(false);
window.setLocationRelativeTo(null);
window.getContentPane().setBackground(Color.BLACK);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setMinimumSize(new Dimension(720, 480));
}
}
GamePanel Class
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class GamePanel extends JPanel{
Wall wall = new Wall();
Player player = new Player();
public GamePanel(){
setBackground(new Color(16, 16, 16));
}
public void paintComponent(Graphics g){
super.paintComponent(g);
wall.paintComponent(g);
player.paintComponent(g);
}
}
Player Class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Player extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5, this);
private int x = 28;
private int y = 190;
private int ydirection;
private int speed = 1;
public Player(){
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(x, y, 20, 100);
}
public void actionPerformed(ActionEvent e){
y += ydirection;
repaint();
}
public void keyPressed(KeyEvent e){
int KeyCode = e.getKeyCode();
if(KeyCode == KeyEvent.VK_W){
ydirection -= speed;
}
if(KeyCode == KeyEvent.VK_S){
ydirection += speed;
}
}
public void keyReleased(KeyEvent e){
int KeyCode = e.getKeyCode();
if(KeyCode == KeyEvent.VK_W){
ydirection = 0;;
}
if(KeyCode == KeyEvent.VK_S){
ydirection = 0;
}
}
public void keyTyped(KeyEvent e){}
}
Your logic is not entirely good, but you can easily fix it. Please study the OOP (principle).
For example:
The player is not JPanel.
The ActionListener and KeyListener interface management is not the Player class job, please create a separate class for her.
Please study the access modifiers.
Pay more attention to the transparency of your code.
For example:
Use the ovverride annotation.
Use the formatter(Ctrl + Shift + F in eclipse)
The problem was that you wrote Keylistener on another Jpanel. What I think you inadvertently put on the player class.
I quickly reworked the code a bit.
Window class:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
public class Window {
public Window() {
JFrame window = new JFrame();
GamePanel gamePanel = new GamePanel();
window.setSize(720, 480);
window.setResizable(true);
window.setTitle("2DGame");
window.add(gamePanel);
window.setUndecorated(false);
window.setLocationRelativeTo(null);
window.getContentPane().setBackground(Color.BLACK);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setMinimumSize(new Dimension(720, 480));
}
public static void main(String args[]) {
Window window = new Window();
}
}
PlayerDirections enum:
public enum PlayerDirections {
UP, DOWN
}
Player class:
import java.awt.Color;
import java.awt.Graphics;
public class Player {
private int x = 28;
private int y = 190;
private int speed = 1;
public Player() {
}
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(x, y, 20, 100);
}
public void Move(PlayerDirections direction) {
switch (direction) {
case UP:
y -= speed;
break;
case DOWN:
y += speed;
break;
}
}
}
GamePanel class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements ActionListener {
Player player = new Player();
public GamePanel() {
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
int KeyCode = e.getKeyCode();
if (KeyCode == KeyEvent.VK_W) {
player.Move(PlayerDirections.UP);
}
if (KeyCode == KeyEvent.VK_S) {
player.Move(PlayerDirections.DOWN);
}
}
});
setFocusable(true);
setFocusTraversalKeysEnabled(false);
setBackground(new Color(16, 16, 16));
Timer t = new Timer(5, this);
t.start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
player.draw(g);
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Related
Hi am new to programming and am trying to make a game with a start menu and then if you click "start" the screen clears and shows a rect in a black background that you can move around the screen with VK up/down/left/right.
But every time i click start i have to click outside of the window and then back the window for the rect to move around
I have tried to use getContentPane to add panel to the window but still every time i click start have to click outside and then back in the window to move the rect.
Help, what do i need to fix/add to not click outside of the frame and the back again to move the rect around
Heres my code the menu screen :
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class Menuscreen {
private int WIDTH = 800;
private int HEIGHT = 600;
public void menuscreen () {
//Window
final JFrame window = new JFrame();
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(WIDTH, HEIGHT);
window.setResizable(false);
window.setLocationRelativeTo(null);
//Panel
final JPanel panel = new JPanel();
panel.setBackground(Color.BLACK);
panel.setVisible(true);
panel.setLayout(null);
window.add(panel);
//Title
JLabel label = new JLabel("SNAKE");
panel.add(label);
label.setBounds(290, 5, 204, 73);
label.setFont(new Font("Tahoma", Font.BOLD, 60));
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setForeground(Color.RED);
label.setBackground(Color.red);
//Buttons
//start button
JButton bstart = new JButton ("Start");
panel.add(bstart);
bstart.setBounds(424, 200, 70, 60);
bstart.setVisible(true);
//start button - run snake on click
bstart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
window.getContentPane().remove(panel);
snake snake = new snake();
window.add(snake);
window.revalidate();
window.repaint();
}
});
//exit button
JButton bexit = new JButton ("Exit");
panel.add(bexit);
bexit.setBounds(290, 200, 70, 60);
bexit.setVisible(true);
//exit button - close on click
bexit.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
and the snake class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class snake extends JPanel implements ActionListener, KeyListener {
public void thicks () {}
public snake () {
setBackground(Color.BLACK);
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
//thread = new Thread(this);
// thread.start();
}
private static final long serialVersionUID = 1L;
Timer fps = new Timer( 5, this);
double x =0 , y = 0, speedx = 0, speedy = 0;
public void paintComponent(Graphics g) {
fps.start();
super.paintComponent(g);
g.setColor(Color.blue);
Graphics2D graphics = (Graphics2D) g;
Rectangle2D rect = new Rectangle2D.Double(x, y, 40, 40);
graphics.fill(rect);
}
public void actionPerformed(ActionEvent e) {
if(x < 0 || x > 740 ) {
speedx= -speedx;
}
if(y < 0 || y > 520) {
speedy = -speedy;
}
x += speedx;
y += speedy;
repaint();
}
public void down() {
speedy = 2;
speedx = 0;
}
public void up() {
speedy = -2;
speedx = 0;
}
public void right() {
speedy = 0;
speedx = 2;
}
public void left() {
speedy = 0;
speedx = -2;
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_DOWN) {
down();
}
if(keyCode == KeyEvent.VK_UP) {
up();
}
if(keyCode == KeyEvent.VK_RIGHT) {
right();
}
if(keyCode == KeyEvent.VK_LEFT) {
left();
}
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public void run() {
}
}
lastly the main
public class Main {
public static void main(String [] args) {
Menuscreen Menuscreen = new Menuscreen();
Menuscreen.menuscreen();
}
}
Please help me guys. I just can't run the KeyListener. But I have added everything you need (i think). I really have no idea what's wrong with this code. I added a Key Listener, implemented a key listener and included all classes so what did I forgot? :/
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
/******Key classes are included*********/
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
/********Key listener is Implemented********/
public class Game extends JPanel implements KeyListener,Runnable
{
JPanel m_mainPanel;
Thread moveBall = new Thread();
Timer t = new Timer(5, this);
int radius = 50;
int posx = 400;
int posy = 400;
int RectPosX = 10;
int RectPosY = 400;
int velocityX = 0;
int velocityY = 0;
//Konstruktor
public Game(JPanel mainPanel) {
m_mainPanel = mainPanel;
setLayout(new GridLayout(3, 1));
JPanel north_panel = new JPanel();
north_panel.setLayout(new FlowLayout(FlowLayout.LEFT));
/**********I didn't forget this********/
this.addKeyListener(this);
/*******Focus is set**********/
setFocusable(true);
setFocusTraversalKeysEnabled(false);
add(north_panel);
}
//Painting rectangle
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(RectPosX, RectPosY, radius, radius);
}
//the key event wich isn't called
#Override
public void keyPressed(KeyEvent e)
{
System.out.println("Key pressed");
if(e.getKeyCode() == KeyEvent.VK_UP)
{
velocityY = 10;
}
if(e.getKeyCode() == KeyEvent.VK_DOWN)
{
velocityY = -10;
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void run()
{
while(true)
{
repaint();
}
}
}
Here's a little example MCVE:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel{
public Main(){
addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
System.out.println("Typed: " + e.getKeyChar());
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed: " + e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("Released: " + e.getKeyChar());
}
});
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
frame.setSize(300, 300);
frame.setVisible(true);
}
}
This program exhibits the same problem you're having: the key listener is never called! This is because the focus is on the JFrame, not the JPanel.
To change this, you have to make the JPanel focusable. You do this by simply calling the setFocusable() method. Now your JPanel will have the focus:
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel{
public Main(){
addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
System.out.println("Typed: " + e.getKeyChar());
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println("Pressed: " + e.getKeyChar());
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("Released: " + e.getKeyChar());
}
});
setFocusable(true);
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
frame.setSize(300, 300);
frame.setVisible(true);
}
}
More complicated programs might require the requestFocusInWindow() function. Or you might want to look into using KeyBindings instead. But your main problem is caused by focus issues.
So I am trying to create a simple paint program and I have been having a problem. The program has a window, on the left of the window is a bar with pen size control, and the rest of the window is the drawing pane. However, whenever I draw on the pane, the side bar is basically copied onto the pane, but it can be drawn over.
Here is my CHPaint class (main):
package paint;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class CHPaint{
JFrame frame;
JLabel penSizeLabel;
PaintPanel panel;
JButton upButton;
JButton downButton;
JPanel left;
JPanel main;
int penSize = 1;
public static void main(String[] args){
CHPaint gui = new CHPaint();
System.out.println("gui built");
gui.go();
}
public void go() {
frame = new JFrame("Caleb's Paint");
panel = new PaintPanel();
upButton = new JButton("Up");
downButton = new JButton("Down");
penSizeLabel = new JLabel("Size: " + penSize);
left = new JPanel();
main = new JPanel();
panel.addMouseListener(new Painting());
panel.addMouseMotionListener(new Painting());
upButton.addActionListener(new UpButton());
downButton.addActionListener(new DownButton());
left.setLayout(new BoxLayout(left, BoxLayout.Y_AXIS));
main.setLayout(new BorderLayout());
left.add(upButton);
left.add(penSizeLabel);
left.add(downButton);
left.setBackground(Color.gray);
penSizeLabel.setBackground(Color.gray);
frame.getContentPane().add(BorderLayout.CENTER, main);
main.add(BorderLayout.WEST, left);
main.add(BorderLayout.CENTER, panel);
frame.setSize(600, 600);
frame.setVisible(true);
}
class UpButton implements ActionListener{
public void actionPerformed(ActionEvent e){
panel.changePenSize(1);
penSize++;
penSizeLabel.setText("Size: " + penSize);
}
}
class DownButton implements ActionListener{
public void actionPerformed(ActionEvent e){
panel.changePenSize(-1);
if (penSize > 1){
penSize--;
}
penSizeLabel.setText("Size: " + penSize);
}
}
class Painting implements MouseListener, MouseMotionListener{
public void mousePressed(MouseEvent e) {
panel.draw(e.getX(), e.getY());
}
public void mouseDragged(MouseEvent e) {
panel.draw(e.getX(), e.getY());
}
public void mouseReleased(MouseEvent e) {
panel.mouseUp();
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
}
}
Here is the class for the drawing panel:
package paint;
import java.awt.*;
import javax.swing.*;
public class PaintPanel extends JPanel {
int drawX = -10;
int drawY = -10;
int oldX = -10;
int oldY = -10;
int penSize = 1;
public void draw(int x, int y){
oldX = drawX;
oldY = drawY;
drawX = x;
drawY = y;
this.repaint();
}
public void mouseUp(){
oldX = -10;
oldY = -10;
drawX= -10;
drawY= -10;
}
public void changePenSize(int p){
if (penSize > 0){
penSize = penSize+p;
}
}
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
if (oldX != -10 && (oldY) != -10){ // If you didn't just start or lift the pen
g2.setStroke(new BasicStroke(penSize, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g.setColor(Color.red);
g.drawLine(oldX, oldY, drawX, drawY);
} else {
g.setColor(Color.red);
g.fillOval(drawX-(penSize/2), drawY-(penSize/2), penSize, penSize);
}
}
}
EDIT:
Sorry, I didn't know the rules here for posting, please forgive me D:. Also, I didn't know what part of the code messed it up so I didn't know what I should cut out. Thanks for your help.
This won't solve your problem but the following is not used anymore:
main.add(BorderLayout.CENTER, panel); // read the API for more info
You should be using:
main.add(panel, BorderLayout.CENTER);
You need to call super.paintComponent() in your paintComponent() method. Among other things, this will clear the JPanel for you.
The code for the JPanel
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.Timer;
import java.awt.EventQueue;
import javax.swing.JPanel;
public class Board extends JPanel
implements ActionListener{
private final int B_WIDTH = 500;
private final int B_HEIGHT = 500;
private final int INITIAL_X = 400;
private final int INITIAL_Y = 0;
private final int DELAY = 25;
private Image star;
private Timer timer;
private int x, y;
public Board(){
loadImage();
initBoard();
}
public void loadImage(){
ImageIcon ii = new ImageIcon("star.png");
star = ii.getImage();
}
public void initBoard() {
setBackground(Color.BLACK);
setPreferredSize(new Dimension(B_WIDTH,B_HEIGHT));
setDoubleBuffered(true);
x = INITIAL_X;
y = INITIAL_Y;
timer = new Timer(DELAY, this);
timer.start();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
drawStar(g);
}
private void drawStar(Graphics g){
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(star, x, y, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
Here is where I want to call the JFrame to close but I dont know a way how.
I would like to close it from inside the if statement.
#Override
public void actionPerformed(ActionEvent e){
x -= 3;
if(x < -400){
}
repaint();
}
}
And for the JFrame
import javax.swing.JFrame;
java.awt.EventQueue;
public class SwingTimer extends JFrame {
public SwingTimer(){
add(new Board());
setTitle("FIGHT");
pack();
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void FightGraphics(){
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
JFrame ex = new SwingTimer();
ex.setVisible(true);
}
});
}
}
mb JFrame's dispose() helps. Check this!
I am making a game. There are 3 different files in the project, there is a file called Dude, Frame and Board. So can anyone help me? The code:
The code for Board:
package Ourgame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener{
Dude p;
Image img;
Timer time;
public Board() {
p = new Dude();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("/Users/appleuser/Desktop");
img = i.getImage();
time = new Timer(5, this);
time.start();
}
public void actionPerformed(ActionEvent e) {
p.move();
repaint();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img, 0, 0, null);
g2d.drawImage(p.getImage(), p.getX(), p.getY(), null);
}
private class AL extends KeyAdapter {
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
}
}
The code for Dude:
package Ourgame;
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class Dude {
int x, dx, y;
Image still;
public Dude() {
ImageIcon i = new ImageIcon("/Users/appleuser/Desktop/the man.bmp");
still = i.getImage();
x = 10;
y = 172;
}
public void move() {
x = x + dx;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return still;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT);
dx = -1;
if(key == KeyEvent.VK_RIGHT)
dx = 1;
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT);
dx = 0;
if(key == KeyEvent.VK_RIGHT)
dx = 0;
}
}
The code for Frame:
package Ourgame;
import javax.swing.JFrame;
public class Frame {
public static void main(String[] args){
JFrame frame = new JFrame("2D game");
frame.add(new Board());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 365);
frame.setVisible(true);
}
}
You might just need to call JFrame.pack(). It's possible the layout manager hasn't set the bounds of your Board. Try:
frame.getContentPane().add(new Board());
frame.pack();
frame.setVisible(true);
If this doesn't work then I suggest you follow the other advice on here: use a Debugger and/or check your image paths. "/Users/appleuser/Desktop" is definitely not an image.
Try invoking your Swing code on the EDT:
package Ourgame;
import javax.swing.JFrame;
public class Frame
{
public static void main(String[] args)
{
SwingUtilities.invokeLater( new Runnable()
{
#Override
public void run()
{
JFrame frame = new JFrame("2D game");
frame.add(new Board());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 365);
frame.setVisible(true);
}
});
}
}