Ugh, I'm sorry MadProgrammer but I just couldn't get the KeyBinding to work the way I wanted it to :(. But I'll keep looking at some more tutorials till I figure it out. For now though I've stuck to a KeyListener and it works. But now I'm having an issue where p.move(); doesn't actually move the player. All other code I've put in works fine except p.move();. I probably shouldn't be asking this many questions, so if you want me to stop just say so, but the whole SO community is really nice. Again, I'll post the code.
Main class:
import javax.swing.*;
public class Game extends JFrame{
public static void main(String[] args){
new Game();
}
public Game(){
add(new Board());
setTitle("Hi mom");
setSize(555,330);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(3);
setVisible(true);
}
}
Board Class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Board extends JPanel implements ActionListener {
Image background;
Player p;
boolean moving;
public Board() {
setFocusable(true);
requestFocus();
addKeyListener(new KeyInputEvents());
Timer timer = new Timer(25, this);
timer.start();
ImageIcon img = new ImageIcon(getClass().getResource("images/map.png"));
background = img.getImage();
p = new Player();
}
public void paint(Graphics g) {
g.drawImage(background, 0, 0, null);
g.drawImage(p.getPlayer(), p.getX(), p.getY(), null);
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public JPanel getBoard(){
return this;
}
)
Player Class (This is probably where stuff goes wrong):
import javax.swing.*;
import java.awt.*;
public class Player{
int x = 30;
int y = 187;
Image player;
public Player(){
ImageIcon img = new ImageIcon(getClass().getResource("images/player.png"));
player = img.getImage();
}
public Image getPlayer(){
return player;
}
public void move(int x, int y){
this.x += x;
this.y += y;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
)
KeyInputEvents Class:
import java.awt.event.*;
import javax.swing.*;
public class KeyInputEvents extends KeyAdapter implements ActionListener{
int k;
boolean moving = true;
Player p = new Player();
public KeyInputEvents(){
Timer timer = new Timer(25,this);
timer.start();
}
public void keyPressed(KeyEvent e){
k = e.getKeyCode();
moving = true;
}
public void keyReleased(KeyEvent e){
moving = false;
}
public void actionPerformed(ActionEvent e) {
if(k == 'D' && moving == true){p.move(5,0);}
if(k == 'A' && moving == true){p.move(-5,0);}
}
}
The Player that is on the screen is not the same Player you are moving in your KeyInputEvents class...
In Board you create an instance of Player...
public class Board extends JPanel implements ActionListener {
Player p;
public Board() {
//...
p = new Player();
}
And in KeyInputEvents you create another one...
public class KeyInputEvents extends KeyAdapter implements ActionListener {
//....
Player p = new Player();
These two instances are in no way related...
While I'm here, you shouldn't really override paint, but instead, override paintComponent and you should definitely be calling super.paintXxx
Update with a Key Bindings example
import java.awt.Graphics;
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.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
public class Game extends JFrame {
public static void main(String[] args) {
new Game();
}
public Game() {
add(new Board());
setTitle("Hi mom");
setSize(555, 330);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(3);
setVisible(true);
}
public class Board extends JPanel implements ActionListener {
Image background;
Player p;
private int xDelta, yDelta;
public Board() {
setFocusable(true);
requestFocus();
ImageIcon img = new ImageIcon(getClass().getResource("/images/map.jpg"));
background = img.getImage();
p = new Player();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "Left.move");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "Left.stop");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), "Right.move");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), "Right.stop");
ActionMap am = getActionMap();
am.put("Left.move", new MoveLeft(this));
am.put("Left.stop", new StopAllMovement(this));
am.put("Right.move", new MoveRight(this));
am.put("Right.stop", new StopAllMovement(this));
Timer timer = new Timer(25, this);
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
g.drawImage(background, 0, 0, null);
g.drawImage(p.getPlayer(), p.getX(), p.getY(), null);
}
protected void setMovement(int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
}
public void actionPerformed(ActionEvent e) {
p.move(xDelta, yDelta);
repaint();
}
public JPanel getBoard() {
return this;
}
}
public class Player {
int x = 30;
int y = 187;
Image player;
public Player() {
ImageIcon img = new ImageIcon(getClass().getResource("/images/player.png"));
player = img.getImage();
}
public Image getPlayer() {
return player;
}
public void move(int x, int y) {
this.x += x;
this.y += y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
public abstract class AbstractMove extends AbstractAction {
private Board board;
private int xDelta;
private int yDelta;
public AbstractMove(Board board, int xDelta, int yDelta) {
this.board = board;
this.xDelta = xDelta;
this.yDelta = yDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
board.setMovement(xDelta, yDelta);
}
}
public class MoveLeft extends AbstractMove {
public MoveLeft(Board board) {
super(board, -5, 0);
}
}
public class MoveRight extends AbstractMove {
public MoveRight(Board board) {
super(board, 5, 0);
}
}
public class StopAllMovement extends AbstractMove {
public StopAllMovement(Board board) {
super(board, 0, 0);
}
}
}
Related
I am currently doing a new project and long story short I am trying to implement action listener on a rectangle object so it can be moved up and down.
But here the code completely crashes when making an object of well in this case test2 class in the test3 class (yes I am aware of the need for a uppercase for classes). As I have replicated the problem making a new project and just used the code that is needed.
public class test {
test2 board = new test2();
public void frame() {
JFrame b = new JFrame("test");
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) {
test start = new test();
start.frame();
}
}
public class test2 extends JPanel {
public int playerScore = 0;
public int opponentScore = 0;
test3 player = new test3();
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
board(g);
g.setColor(Color.WHITE);
g2d.fill(player.player);
}
public void board(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, 900, 900);
}
}
public class test3 {
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);
test2 theBoard = new test2();
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;
}
}
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
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;
}
}
theBoard.repaint();
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
for (int r = playerYpos; r >= 0; r--) {
if (r == 0) {
playerYpos = playerYpos + 20;
} else {
playerYpos = playerYpos - 1;
}
if (playerYpos > 800){
playerYpos = 800;
}
}
theBoard.repaint();
}
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
Your code doesn't compile.
I took some of your code and created the following GUI.
Here's the GUI after moving the player rectangle.
Oracle has a helpful tutorial, Creating a GUI With JFC/Swing. Skip the Netbeans section.
The first thing I did was start the Swing application with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created a Player class to hold the player rectangle. This way, you can change the player shape in one place.
I created a JFrame. The JFrame methods have to be called in a specific order. This is the order I use for my Swing applications.
I created a drawing JPanel. This JPanel is similar to yours, except I override the paintComponent method. I pass an instance of Player to the drawing JPanel so the JPanel can draw the player rectangle.
I used key bindings instead of a key listener. This makes the keys functional whether the drawing JPanel is in focus or not. Key bindings also made it easy for me to add the WASD keys as well as the arrow keys.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class ExampleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ExampleGUI());
}
private final DrawingPanel drawingPanel;
private final Player player;
public ExampleGUI() {
this.player = new Player();
this.drawingPanel = new DrawingPanel(player);
}
#Override
public void run() {
JFrame frame = new JFrame("Example GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(drawingPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
setKeyBindings(drawingPanel);
frame.setVisible(true);
}
private void setKeyBindings(JPanel panel) {
String up = "up";
String down = "down";
String left = "left";
String right = "right";
InputMap inputMap = panel.getInputMap();
ActionMap actionMap = panel.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), up);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), down);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), left);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), right);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), up);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), down);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), left);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), right);
actionMap.put(up, new PlayerAction(this, player, 0, -10));
actionMap.put(down, new PlayerAction(this, player, 0, +10));
actionMap.put(left, new PlayerAction(this, player, -10, 0));
actionMap.put(right, new PlayerAction(this, player, +10, 0));
}
public void repaint() {
drawingPanel.repaint();
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
private final Player player;
public DrawingPanel(Player player) {
this.player = player;
this.setPreferredSize(new Dimension(600, 600));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
drawBoard(g2d);
drawPlayer(g2d);
}
private void drawBoard(Graphics2D g2d) {
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
private void drawPlayer(Graphics2D g2d) {
g2d.setColor(player.getColor());
g2d.fill(player.getPosition());
}
}
public class PlayerAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private final ExampleGUI frame;
private final Player player;
private final Point moveDirection;
public PlayerAction(ExampleGUI frame, Player player, int x, int y) {
this.frame = frame;
this.player = player;
this.moveDirection = new Point(x, y);
}
#Override
public void actionPerformed(ActionEvent event) {
player.move(moveDirection);
frame.repaint();
}
}
public class Player {
private final Color color;
private Rectangle position;
public Player() {
this.color = Color.WHITE;
this.position = new Rectangle(300, 300, 20, 80);
}
public void move(Point point) {
position.x += point.x;
position.y += point.y;
}
public Color getColor() {
return color;
}
public Rectangle getPosition() {
return position;
}
}
}
I've added keybinding on one of my JPanels. The problem is this keybinding didn't do its "actionPerformed". Even though I put a sysout in the actionPerformed, nothing was outputted on the console. Can someone help me with this problem? I've already tried to disable my buttons, but still my keybinding doesn't work.
package project.fin;
import java.awt.*;
import java.io.*;
import java.util.List;
import java.awt.event.*;
import javax.swing.*;
//Panel for my game
public class GamePlayPanel extends JPanel{
private Image current;
private Baby bayi;
public GamePlayPanel(String img) {
Dimension size = new Dimension(1200, 500);
this.setPreferredSize(size);
this.setMaximumSize(size);
this.setMinimumSize(size);
this.setSize(size);
this.setLayout(null);
//An baby object
bayi = new Baby(100, 410, 5);
//this is where my keyBinding initialized
bayi.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,0), "moveRight");
bayi.getActionMap().put("moveRight", new Move_it(1));
}
//this is the action class that i want to put in my keybinding
private class Move_it extends AbstractAction{
int code;
public Move_it(int code) {
this.code=code;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("test\n");
if (this.code==1) {
bayi.MoveRight();
}
repaint();
}
}
//To draw my baby
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
bayi.draw(g);
}
}
This is my baby class:
package project.fin;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import java.awt.event.*;
public class Baby extends JComponent{
float x, y;
float speed;
Image current;
private List <Image> ImgPool;
private int Current;
public Baby(float x, float y, float speed) {
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
this.speed = speed;
ImgPool = new ArrayList<Image>();
//These are just some images that i use to build my moving baby
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby2_50.png").getImage());
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby3_50.png").getImage());
this.current = ImgPool.get(0);
this.Current = 0;
}
//The action that i want my baby to do when a key is pressed
public void MoveRight() {
if (x>600) return;
this.x+=speed;
if (this.Current==3)this.Current=0;
else
this.Current++;
this.current = this.ImgPool.get(Current);
}
public void draw(Graphics g) {
g.drawImage(this.current, (int)this.x, (int)this.y, null);
}
}
Baby isn't attached to the component hierarchy and therefore won't receive any key events. In fact, the design doesn't make sense. There's no need for Bady to extend from JPanel at all.
Instead, make use of the GamePlayPanel directly
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new GamePlayPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePlayPanel extends JPanel {
private Baby bayi;
public GamePlayPanel() {
//An baby object
bayi = new Baby(100, 410, 5);
//this is where my keyBinding initialized
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "moveRight");
getActionMap().put("moveRight", new Move_it(1));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(1200, 500);
}
//this is the action class that i want to put in my keybinding
private class Move_it extends AbstractAction {
int code;
public Move_it(int code) {
this.code = code;
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
System.out.println("test\n");
if (this.code == 1) {
bayi.moveRight();
}
repaint();
}
}
//To draw my baby
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
bayi.draw(g);
}
}
public class Baby {
float x, y;
float speed;
Image current;
private List<Image> ImgPool;
private int Current;
public Baby(float x, float y, float speed) {
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
this.speed = speed;
ImgPool = new ArrayList<Image>();
//These are just some images that i use to build my moving baby
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby2_50.png").getImage());
ImgPool.add(new ImageIcon("baby1_50.png").getImage());
ImgPool.add(new ImageIcon("baby3_50.png").getImage());
this.current = ImgPool.get(0);
this.Current = 0;
}
//The action that i want my baby to do when a key is pressed
public void moveRight() {
if (x > 600) {
return;
}
this.x += speed;
if (this.Current == 3) {
this.Current = 0;
} else {
this.Current++;
}
this.current = this.ImgPool.get(Current);
}
public void draw(Graphics g) {
g.drawImage(this.current, (int) this.x, (int) this.y, null);
}
}
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.ArrayList;
#SuppressWarnings("serial")
public class GUI extends JFrame implements ActionListener, MouseListener {
private boolean drawLine = false;
private boolean drawRec = false;
private boolean drawOval = false;
private final JButton line;
private final JButton oval;
private final JButton rectangle;
private final JPanel buttonPanel;
public DrawStuff drawPanel = new DrawStuff();
public int x1;
public int x2;
public int y1;
public int y2;
public int click;
public GUI() {
super("Graphics IO");
this.click = 1;
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
line = new JButton("Line");
line.addActionListener(this);
buttonPanel.add(line);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.SOUTH);
//add(drawPanel);
addMouseListener((MouseListener) this);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == line) {
drawLine = true;
repaint();
} else if (source == oval) {
drawOval = true;
repaint();
} else if (source == rectangle) {
drawRec = true;
repaint();
}
}
public static void main(String[] args) {
GUI guiIO = new GUI();
}
class DrawStuff extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.BLUE);
ArrayList<Shape> shapes = new ArrayList<>();
if (drawLine) {
drawLine = false;
} else if (drawOval) {
//no clue how to add an oval
drawOval = false;
} else if (drawRec) {
Rectangle rec = new Rectangle(x1, y1,Math.abs(x2-x1) , Math.abs(y2-y1));
shapes.add(rec);
drawRec = false;
}
Graphics2D j = (Graphics2D)g;
shapes.stream().map((s) -> {
((Graphics2D) j).draw((Shape) s);
return s;
}).forEach((_item) -> {
repaint();
});
}
}
#Override
public void mousePressed(MouseEvent me) {
if (click == 1){
x1 = me.getX();
y1 = me.getY();
System.out.println(x1);
System.out.println(y1);
click = 2;
}else if (click == 2) {
x2 = me.getX();
y2 = me.getY();
System.out.println(x2);
System.out.println(y2);
click = 1;
}
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseClicked(MouseEvent e) {
}
}
Okay so i have to make a program to create shapes using two mouseclicks and then be able to export/import them. I am trying to use arraylist for this but im having a hard time trying to get it to work. The rectangle im creating will not show up on the panel. What am i doing wrong? Please help me.
Lets start with the fact that DrawStuff hasn't actually been added to anything that is capable of painting it.
DrawStuff#paintComponent should be making decisions about updating the state of the shapes List, instead, your ActionListener and MouseListener should be making these decisions (what to add, where and what do modify), the DrawStuff panel should just be painting what's in the Shape list
You also shouldn't be modifying the state of the component from within the paintComponent calling things like setBackground could set up a repeated repaint request which could cripple your application if not your PC
Modify DrawStuff so it has it's own MouseListener and methods that allow your GUI to ask it to create new shapes. Make the shapes List a instance field so you can manage from within DrawStuff more easily
Something like...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GUI extends JFrame implements ActionListener {
private boolean drawLine = false;
private boolean drawRec = false;
private boolean drawOval = false;
private final JButton line;
private final JButton oval;
private final JButton rectangle;
private final JPanel buttonPanel;
public DrawStuff drawPanel = new DrawStuff();
public int x1;
public int x2;
public int y1;
public int y2;
public int click;
public GUI() {
super("Graphics IO");
this.click = 1;
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 3));
line = new JButton("Line");
line.addActionListener(this);
buttonPanel.add(line);
oval = new JButton("Oval");
oval.addActionListener(this);
buttonPanel.add(oval);
rectangle = new JButton("Rectangle");
rectangle.addActionListener(this);
buttonPanel.add(rectangle);
Container contentPane = this.getContentPane();
contentPane.add(buttonPanel, BorderLayout.SOUTH);
add(drawPanel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == line) {
drawPanel.setDrawShape(DrawStuff.DrawShape.LINE);
} else if (source == oval) {
drawPanel.setDrawShape(DrawStuff.DrawShape.OVAL);
} else if (source == rectangle) {
drawPanel.setDrawShape(DrawStuff.DrawShape.RECTANGLE);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GUI guiIO = new GUI();
}
});
}
public static class DrawStuff extends JPanel {
public enum DrawShape {
LINE, OVAL, RECTANGLE;
}
private ArrayList<Shape> shapes = new ArrayList<>();
private DrawShape drawShape = DrawShape.LINE;
private Shape currentShape;
public DrawStuff() {
setBackground(Color.BLUE);
MouseAdapter ma = new MouseAdapter() {
private Point clickPoint;
#Override
public void mousePressed(MouseEvent e) {
clickPoint = e.getPoint();
currentShape = null;
}
#Override
public void mouseReleased(MouseEvent e) {
if (currentShape != null) {
shapes.add(currentShape);
currentShape = null;
repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
switch (getDrawShape()) {
case LINE:
currentShape = new Line2D.Double(clickPoint, e.getPoint());
break;
case OVAL:
case RECTANGLE:
int x = clickPoint.x;
int y = clickPoint.y;
int width = p.x - clickPoint.x;
int height = p.y - clickPoint.y;
if (width < 0) {
x = p.x;
width *= -1;
}
if (height < 0) {
y = p.y;
height *= -1;
}
switch (getDrawShape()) {
case OVAL:
currentShape = new Ellipse2D.Double(x, y, width, height);
break;
case RECTANGLE:
currentShape = new Rectangle2D.Double(x, y, width, height);
break;
}
break;
}
repaint();
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
public DrawShape getDrawShape() {
return drawShape;
}
public void setDrawShape(DrawShape drawShape) {
this.drawShape = drawShape;
currentShape = null;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
for (Shape shape : shapes) {
g2d.draw(shape);
}
if (currentShape != null) {
g2d.setColor(Color.RED);
g2d.draw(currentShape);
}
}
}
}
For example. You always need to be asking yourself "who is responsible for doing what". In this case the DrawStuff panel is actually responsible for determine "where" something is drawn, but it needs more information about "what", then based on that information it can perform the actual operation
So i am making a small game called dodge were rectangles fall from the "sky" and you have to do dodge them. As i ran the game this error message just popped up and i have no clue why. Also the screen just goes white whenever i run the program.
I cannot figure this out, Ive searched for hours in my code cant figure out why. Please Halp
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at dodge.Enemy.move(Enemy.java:22)
at dodge.Enemy.draw(Enemy.java:32)
at dodge.EnemyManager.draw(EnemyManager.java:34)
at dodge.Dodge.paint(Dodge.java:38)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:585)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5226)
at
Sorry thats long. But here is my code.
Dodge.java
package dodge;
import java.awt.event.KeyListener;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.event.*;
public class Dodge extends JPanel implements KeyListener{
private Player player;
private Stage stage;
private EnemyManager manager;
public Dodge(){
setSize(new Dimension(800, 600));
setPreferredSize(new Dimension(800, 600));
addKeyListener(this);
setFocusable(true);
stage = new Stage();
player = new Player(this, 200, 200);
manager = new EnemyManager(this, 10);
}
#Override
public void update(Graphics g){
paint(g);
}
#Override
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
stage.draw(g);
player.draw(g);
manager.draw(g);
g.dispose();
repaint();
}
#Override
public void keyReleased(KeyEvent e){
player.setXD(0);
player.setYD(0);
}
#Override
public void keyTyped(KeyEvent e){
}
public Stage getStage(){
return stage;
}
#Override
public void keyPressed(KeyEvent e){
int c = e.getKeyCode();
if(c == KeyEvent.VK_W){
}
if(c ==KeyEvent.VK_A){
player.setXD(-1);
}
if(c == KeyEvent.VK_S){
}
if(c ==KeyEvent.VK_D){
player.setXD(1);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("Dodge the Rectangles");
frame.add(new Dodge());
frame.pack();
frame.setResizable(false);
frame.setSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
EnemyManager.java
package dodge;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
public class EnemyManager {
private int amount;
private List<Enemy> enemies = new ArrayList<Enemy>();
private Dodge instance;
public EnemyManager(Dodge instance, int a){
this.amount = a;
spawn();
this.instance = instance;
}
private void spawn(){
Random random = new Random();
int ss = enemies.size();
if(ss<amount){
for(int i = 0; i < amount - ss; i++){
enemies.add(new Enemy(instance, random.nextInt(778), 10));
}
}else if(ss>amount){
for(int i = 0; i < ss - amount; i++){
enemies.remove(i);
}
}
}
public void draw(Graphics g){
for(Enemy e : enemies) e.draw(g);
}
}
Enemy.java
package dodge;
import java.awt.*;
public class Enemy extends Entity{
private Rectangle hitbox;
private int ix, iy;
private boolean dead = false;
private Dodge instance;
public Enemy(Dodge instance, int x, int y){
super(x, y);
this.instance = instance;
hitbox = new Rectangle (x, y, 32, 32);
ix = 0;
iy = 1;
}
private void move(){
if(instance.getStage().isCollided(hitbox)){
iy = 0;
dead = true;
}
hitbox.x += ix;
hitbox.y +=iy;
}
private boolean isDead() {return dead;}
#Override
public void draw(Graphics g){
move();
g.setColor(Color.CYAN);
g.fillRect(hitbox.x, hitbox.y, hitbox.width, hitbox.height);
}
}
Entity.java
package dodge;
import java.awt.*;
public abstract class Entity {
protected int x, y, w, h;
protected boolean removed = false;
public Entity(int x, int y){
this.x = x;
this.y = y;
}
public void draw(Graphics g){
}
public int getX() {return x;}
public int getY(){return y;}
public int getW() {return w;}
public int getH(){return h;}
}
Player.java
package dodge;
import java.awt.*;
public class Player extends Entity{
private int xd, yd;
private Dodge instance;
private Rectangle hitbox;
public Player(Dodge instance, int x , int y){
super(x, y);
this.instance = instance;
w = 16; h = 16;
hitbox = new Rectangle(x, y, w, h);
}
public void draw(Graphics g){
move();
if(!instance.getStage().isCollided(hitbox)){
yd = 1;
}else yd = 0;
g.setColor(Color.ORANGE);
g.fillOval(hitbox.x, hitbox.y, hitbox.width, hitbox.height);
}
private void move(){
hitbox.x += xd;
hitbox.y +=yd;
}
public void setXD(int value){
xd = value;
}
public void setYD(int value){
yd = value;
}
}
Stage.java
package dodge;
import java.awt.*;
public class Stage {
private Rectangle platform = new Rectangle(0, 540, 800, 100);
public Stage(){
}
public boolean isCollided(Rectangle entity){
return platform.intersects(entity);
}
public void draw(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(platform.x, platform.y, platform.width, platform.height);
}
}
I hope that wasnt too long. Thanks
Read the stacktrace. Either Enemy.instance or Enemy.instance.getStage() is null.
Also the screen just goes white whenever i run the program.
Don't override update() and paint(). That is old code used in AWT and is NOT the way custom painting is done in Swing. In Swing you simply override the paintComponent() method of the JPanel and don't forget to invoke super.paintComponent(). Read the section from the Swing tutorial on Custom Painting for more information and examples.
Don't invoke repaint() in a painting method. That will cause an infinite loop. The is not the way to do animation. Use a Swing Timer or a separate Thread to schedule the animation.
Im having trouble getting the key pressed event to work, it doesn't recognize key input, can someone please help?
I have three classes player, exe, and board
Here is the board class
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Board extends JPanel implements ActionListener{
private Timer timer;
private Player player;
//private Floor
public Board() {
addKeyListener( new TAdapter() );
setFocusable(true);
setBackground(Color.WHITE);
setDoubleBuffered(true);
player = new Player();
//floor = new Floor();
timer = new Timer(5, this);
timer.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(player.getImage(), player.getX(), player.getY(), this);
// g2d.drawImage(floor.getImage(), floor.getX(), floor.getY(), this);
//System.out.println(player.getX() + ", " + player.getY());
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void actionPerformed(ActionEvent e) {
// checkPlayerOnGround();
player.move();
repaint();
}
private class TAdapter extends KeyAdapter implements KeyListener{
public void keyTyped(KeyEvent e) {
player.keyReleased(e);
System.out.println("Released");
}
public void keyPressed(KeyEvent e) {
player.keyPressed(e);
System.out.println("Pressed");
}
}
}
here is the player class
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.Timer;
import java.util.TimerTask;
public class Player{
private String player = "player.jpg";
private int moveX;
private int moveY;
private int x;
private int y;
private Image image;
private boolean canFall = false;
//private Timer jumpTimer = new Timer();
boolean canJump = true;
public Player() {
ImageIcon playeriImage = new ImageIcon(this.getClass().getResource(player));
image = playeriImage.getImage();
x = 40;
y = 60;
}
public void checkFall() {
if(canFall) {
moveY = -4;
}
}
public void move() {
//checkFall();
x = moveX + x;
y = moveY + y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public Image getImage() {
return image;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
moveX = -4;
}
if (key == KeyEvent.VK_D) {
moveX = 4;
}
if (key == KeyEvent.VK_W) {
if(canJump)
this.jump();
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_A) {
moveX = 0;
}
if (key == KeyEvent.VK_D) {
moveX = 0;
}
}
here is the exe class
import javax.swing.JFrame;
public class Exe extends JFrame {
public Exe() {
add(new Board());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setLocationRelativeTo(null);
setTitle("TSA Video Game");
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
new Exe();
}
}
thanks in advance
KeyListener will only respond to key events IF the component is focusable AND has focus.
It would be better to use the Key Bindings API which will allow you to overcome this limitation (if you want to)
I would also recommend that you override paintComponent instead of paint. You should also not be calling Graphics#dispose, as you did not create the Graphics context, this could actually prevent anything from being painted on some systems
I would also suggest that a delay of 5 milliseconds (on your Timer) might be a little excessive (5 milliseconds = 200fps!).
A value of 16 (60fps) or 40 (25fps) may be more suitable and reduce the overhead on the system...IMHO