Java animation does not refresh properly and uses too much CPU - java

I have a problem with a simple Java game I am creating right now. I want a dot (a car) to be movable across the game screen, but instead of this all I can see on the screen is the long "snake" created by the dot moved by me:
Other problem is that activity manager on my Mac shows that the game uses huge amount of CPU power - my laptop gets very hot very fast. I suspect that there is something wrong with my game loop, but since now I haven't found any solution:
BoardPanel.java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class BoardPanel extends JPanel implements KeyListener, Runnable {
public static final int WIDTH = 600;
public static final int HEIGHT = 600;
private Thread thread;
private boolean running;
private BufferedImage image;
private Graphics2D g;
private int FPS = 30;
private int targetTime = 1000/FPS;
private Map map;
private Car car;
public BoardPanel() {
super();
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if(thread == null) {
thread = new Thread(this);
thread.start();
}
addKeyListener(this);
}
public void run() {
init();
long startTime;
long reTime;
long waitTime;
while (running) {
startTime = System.nanoTime();
update();
render();
draw();
reTime = System.nanoTime() - startTime;
waitTime = targetTime - reTime;
try {
Thread.sleep(waitTime);
}
catch(Exception e) {
}
}
}
private void init() {
running = true;
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
map = new Map();
car = new Car(map);
car.setxpos(50);
car.setypos(50);
}
private void update() {
map.update();
car.update();
}
private void render() {
map.draw(g);
car.draw(g);
}
private void draw() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
public void keyTyped(KeyEvent key) {
}
public void keyPressed(KeyEvent key) {
int code = key.getKeyCode();
if(code == KeyEvent.VK_LEFT) {
car.setLeft(true);
}
if(code == KeyEvent.VK_RIGHT) {
car.setRight(true);
}
if(code == KeyEvent.VK_UP) {
car.setUp(true);
}
if(code == KeyEvent.VK_DOWN) {
car.setDown(true);
}
}
public void keyReleased(KeyEvent key) {
int code = key.getKeyCode();
if(code == KeyEvent.VK_LEFT) {
car.setLeft(false);
}
if(code == KeyEvent.VK_RIGHT) {
car.setRight(false);
}
if(code == KeyEvent.VK_UP) {
car.setUp(false);
}
if(code == KeyEvent.VK_DOWN) {
car.setDown(false);
}
}
}
Car.java
import java.awt.*;
public class Car {
private double xpos;
private double ypos;
//private int xsize;
//private int ysize;
private boolean left;
private boolean right;
private boolean up;
private boolean down;
private Map map;
public Car(Map m) {
map = m;
}
public void setxpos(int i) {
xpos = i;
}
public void setypos(int i) {
ypos = i;
}
public void setLeft (boolean b) {
left = b;
}
public void setRight (boolean b) {
right = b;
}
public void setUp (boolean b) {
up = b;
}
public void setDown (boolean b) {
down = b;
}
public void update() {
if(left) {
xpos--;
}
if(right) {
xpos++;
}
if(up) {
ypos--;
}
if(down) {
ypos++;
}
}
public void draw(Graphics2D g) {
int mx = map.getx();
int my = map.gety();
g.setColor(Color.BLUE);
g.fillOval((int)(mx+xpos-20/2), (int)(my+ypos-20/2), 20, 20);
}
}
Map.java (I haven't created map yet, right now only want the dot to move properly)
import java.awt.*;
public class Map {
public int x;
public int y;
public int getx() {
return x;
}
public int gety() {
return y;
}
public void setx(int i) {
x = i;
}
public void sety(int i ) {
y = i;
}
public void update() {
}
public void draw(Graphics2D g) {
}
}
RacerMain.java
import javax.swing.JFrame;
public class RacerMain {
public static void main (String[]args) {
//MainFrame mf = new MainFrame();
JFrame mf = new JFrame("Racer");
mf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mf.setContentPane(new BoardPanel());;
mf.pack();
mf.setVisible(true);
}
}
Many thanks for your help!!!

In addition to what camickr said: Be careful with your usage of the Graphics. A rule of thumb:
Never call getGraphics on a Component!
Additionally, you are never disposing the Graphics that you are fetching from the BufferedImage. You are instead disposing the Graphics that you obtained from the Component, which may be even worse than fetching it in the first place!
I wonder why you are overriding the addNotify method. You should not implement any functionality based on averriding this method....
So you should change the respecive parts of your BoardPanel class roughly as follows:
public class BoardPanel extends JPanel implements KeyListener, Runnable {
...
// private Graphics2D g; // Don't store this here
public BoardPanel() {
...
// Create the thread here instead of in the "addNotify" method!
if(thread == null) {
thread = new Thread(this);
thread.start();
}
addKeyListener(this);
}
public void run() {
...
while (running) {
...
//draw(); // Don't call this method
repaint(); // Trigger a repaint instead!
}
}
private void render() {
Graphics2D g = image.createGraphics();
// Clear the background (see camickrs answer)
g.setColor(Color.BLACK);
g.fillRect(0,0,image.getWidth(),image.getHeight());
try
{
map.draw(g);
car.draw(g);
}
finally
{
g.dispose(); // Dispose the Graphics after it has been used
}
}
/** Don't call "getGraphics" on a component!
private void draw() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
*/
// Override the paintComponent method instead:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image,0,0,null);
}

In your draw() method you need to clear the BufferedImages background before your invoke the fillOval method. Something like:
g.setColor( Color.BLACK );
g.fillRect(...);
g.setColor( Color.BLUE );
g.fillOval(...);
Print out your "waitTime" to make sure you are waiting a reasonable time.

Related

Java Swing: how to react to clicking a custom JComponent?

I'm trying to make a game with ducks, the ducks are moving on the screen and I can't get a mouse click on them. I'm obviously doing something wrong because despite setting a MouseListener, its methods are not called. This is my code, I omitted getters and the DuckGame class, which is only generating ducks.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class DuckGameScreen extends JPanel {
private int initialDuckNum = 7;
private final int INTERVAL = 25;
private final int INTERVAL_BTWN_DUCKS = 1000;
private Timer duckTimer;
private int ducksStarted = 0;
private DuckGame duckGame;
public DuckGameScreen() {
setBackground(Color.cyan);
askAboutDifficulty();
startTimer();
startGame();
startDifficultyIncrease();
}
private void startGame() {
duckGame = new DuckGame(initialDuckNum);
startDucks();
addDuckListeners();
}
private void addDuckListeners() {
for (Duck duck : duckGame.getDucks()) {
duck.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {
System.out.println("Duck clicked");}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
});
}
}
#Override
public void paint(Graphics g) {
super.paint(g);
drawDucks(g);
Toolkit.getDefaultToolkit().sync();
}
private void animateDuck(Duck duck) {
new Thread() {
#Override
public void run() {
super.run();
while (!duck.isDuckStopped()) {
try {
Thread.sleep(INTERVAL);
duck.move();
if (duck.getX() - duck.getWidth() >= Toolkit.getDefaultToolkit().getScreenSize().width) {
duck.resetPosition();
}
repaint();
} catch (InterruptedException e) {
e.printStackTrace();
duck.stop();
break;
}
}
}
}
.start();
}
private void drawDucks(Graphics g) {
for (Duck duck : duckGame.getDucks()) {
duck.paintComponent(g);
}
}
}
And my Duck class:
public class Duck extends JComponent {
private final static int INIT_X = -100;
private int x = INIT_X;
private int y = 100;
private int width = 0;
private int height = 0;
private Image image = null;
private boolean isDuckStopped = false;
private final int STEP = 5;
public Duck() {
initRandomPosition();
loadImage();
setVisible(true);
setBounds(x, y, width, height);
}
private void initRandomPosition() {
y = getRandomY();
}
public void move() {
x += STEP;
}
private void loadImage() {
ImageIcon imageIcon = new ImageIcon(getFilePath(Images.DUCK.getFileName()));
Dimension newDimension = Utils.getScaledDimension(100, 100, imageIcon.getIconWidth(), imageIcon.getIconHeight());
image = imageIcon.getImage().getScaledInstance(newDimension.width, newDimension.height, Image.SCALE_DEFAULT);
width = image.getWidth(null);
height = image.getHeight(null);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponents(g);
drawDuck(g);
Toolkit.getDefaultToolkit().sync();
}
private void drawDuck(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(image, x, y, this);
setBounds(x, y, width, height);
}
public void stop() {
isDuckStopped = true;
setVisible(false);
}
public void resetPosition() {
x = INIT_X;
y = getRandomY();
}
}

How can I make my game fall when off the platform I made?

I want it so when my player goes off the platform, (in checkCollision() method PlatformerPanel class) it will fall and then do something when gone off the screen, i haven't set up an end game screen yet but that's what I'm planning to do. Anyway, the problem is that it goes way too fast for some reason and falls too early, and also when an arrow key is pressed while its falling it will go back up to the platform.
Please try to help me overcome this or think of a new, easy to understand, way to do this/make this work the way i am planning.
EDIT 1:
I fixed the thing where it falls too early so don't worry about that
```
public class PlatformerMain {
public static void main(String[] args) {
PlatformerGameFrame platformerGame = new PlatformerGameFrame();
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class PlatformerGameFrame extends JFrame{
PlatformerGamePanel panel;
PlatformerGameFrame() {
panel = new PlatformerGamePanel();
this.add(panel);
this.setTitle("Platformer Game");
this.setResizable(false);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.pack();
this.setVisible(true);
this.setLocationRelativeTo(null);
this.getContentPane().setBackground(new Color(0,0,0));
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class PlatformerGamePanel extends JPanel implements Runnable{
PlatformerPlayer player1;
PlatformerMap map1;
static final int SCREEN_WIDTH = 1000;
static final int SCREEN_HEIGHT = 600;
static final int PLAYER_WIDTH = 50;
static final int PLAYER_HEIGHT = 60;
static final Dimension SCREEN_SIZE = new Dimension(SCREEN_WIDTH,SCREEN_HEIGHT);
static boolean falling = false;
Image backgroundImage;
Thread gameThread;
Image image;
Graphics graphics;
PlatformerMap map;
public PlatformerGamePanel() {
java.net.URL imgIcon = Main.class.getResource(
"/Resources/spaceImage.jpg");
backgroundImage = new ImageIcon(imgIcon).getImage();
newPlayer();
newMap();
this.setFocusable(true);
this.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {
player1.KeyPressed(e);
}
#Override
public void keyReleased(KeyEvent e) {
player1.KeyReleased(e);
}
});
this.setPreferredSize(SCREEN_SIZE);
this.setOpaque(true);
gameThread = new Thread(this);
gameThread.start();
}
public void paint(Graphics g) {
image = createImage(getWidth(),getHeight());
graphics = image.getGraphics();
draw(graphics);
g.drawImage(image, 0,0, null);
}
public void draw(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.drawImage(backgroundImage, 0,0, null);
player1.paint(g);
map.paint(g);
}
public void newPlayer() {
player1 = new PlatformerPlayer((SCREEN_WIDTH/2)-(PLAYER_WIDTH/2), (SCREEN_HEIGHT/2)-(PLAYER_WIDTH/2), PLAYER_WIDTH, PLAYER_HEIGHT);
}
public void newMap() {
map = new PlatformerMap();
}
public void checkCollision() {
if(player1.x > SCREEN_WIDTH-PLAYER_WIDTH) {
player1.x = SCREEN_WIDTH-PLAYER_WIDTH;
}
else if(player1.x < 0) {
player1.x = 0;
}
if(!(player1.x >map.PLATFORM_WIDTH)) {
if(player1.y > SCREEN_HEIGHT-250) {
player1.y = SCREEN_HEIGHT-250;
}
} else if(player1.x > map.PLATFORM_WIDTH) {
gravity();
}
}
public void falling() {
}
public void gravity() {
player1.gravity();
}
public void move() {
player1.move();
}
public void run() {
long lastTime = System.nanoTime();
double amountOfTicks = 120.0;
double ns = 1000000000 / amountOfTicks;
double delta = 0;
while(true) {
long now = System.nanoTime();
delta += (now - lastTime)/ns;
lastTime = now;
if(delta >= 1) {
move();
checkCollision();
gravity();
repaint();
delta--;
}
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class PlatformerPlayer extends Rectangle {
/*static int playerPosX = 100;
static int playerPosY = 100;*/
static double velocityY = 0;
static double velocityX = 0;
static int vertical_position;
static final int TERMINAL_VELOCITY = 200;
static final int PLAYER_WIDTH = 50;
static final int PLAYER_HEIGHT = 50;
static int speed = 2;
protected boolean falling = true;
protected boolean jumping = false;
double gravity = 0.05;
public PlatformerPlayer(int x, int y, int PLAYERWIDTH, int PLAYERHEIGHT) {
super(x,y,PLAYERWIDTH,PLAYERHEIGHT);
}
public void KeyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_LEFT) {
setXDirection(-speed);
move();
}
else if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
setXDirection(speed);
move();
}
}
public void KeyReleased(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_LEFT) {
setXDirection(0);
move();
}
else if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
setXDirection(0);
move();
}
}
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setColor(Color.red);
g2D.fillRect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT);
}
public void setYDirection(int YDirection) {
velocityY = YDirection;
}
public void setXDirection(int XDirection) {
if(speed > 10) {
speed = 10;
}
velocityX = XDirection;
}
public void move() {
y += velocityY;
x += velocityX;
}
public void gravity() {
velocityY += gravity;
if (velocityY > TERMINAL_VELOCITY)
{
velocityY = TERMINAL_VELOCITY;
}
vertical_position -= velocityY;
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class PlatformerMap extends Rectangle {
int PLATFORM_WIDTH = 600;
int PLATFORM_HEIGHT = 150;
public PlatformerMap() {
}
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setColor(Color.gray);
g2D.fillRect(100,400,PLATFORM_WIDTH,PLATFORM_HEIGHT);
}
}

First Java Game Not Rendering

I decided I wanted to experiment with making a game and I like Java, so I started following a tutorial here. I did deviate from the video a few times when I felt it was cleaner while being synonymous with the tutorial's code, but not in any way I thought would affect how the code worked. For example, it made sense to me that there should only ever be one instance of the Renderer, and Object Registry so I made them Singletons.
The code I have so far is supposed to create a window with a black background, and a blue square in the middle of the window representing the player, that much is working. However, it should also be sliding around in response to the wasd keys, and even more slowly drifting in one direction regardless. Instead it's doing nothing.
I spent no less than an hour trying to figure out why it wasn't working. It seems to be ticking just fine and the data looks like it's updating properly, but even though my render methods are also being called, the screen just isn't changing.
This is all the code I have so far, since I'm out of ideas as to the problem. I apologize for listing a whole project.
public class Game implements Runnable {
private final Thread thread;
private boolean running = false;
Game() {
thread = new Thread(this);
}
public static void main(String[] args) {
Game game = new Game();
game.start();
new Player(600,450,0));
}
private void start() {
thread.start();
running = true;
}
#Override
public void run() {
double tps = 10.0;
double nsPerTick = 1000000000 / tps;
double delta = 0;
int frames = 0;
long timer = System.currentTimeMillis();
long lTime = System.nanoTime();
long now;
while (running) {
now = System.nanoTime();
delta += (now - lTime) / nsPerTick;
lTime = now;
while (delta >= 1) {
Registry.getInstance().tick();
delta--;
}
if (running) Renderer.getInstance().run();
frames++;
if (System.currentTimeMillis() - timer > 1000) {
timer += 1000;
System.out.println("FPS: " + frames);
frames = 0;
}
}
stop();
}
private void stop() {
try {
thread.join();
} catch (Exception e) {
e.printStackTrace();
}
running = false;
}
}
public class Renderer extends Canvas {
private static final Renderer renderer = new Renderer();
private final Window window;
private final BufferStrategy bs;
private final Graphics g;
boolean black = true;
private Renderer() {
window = new Window(1200, 900, "First Game", this);
this.createBufferStrategy(2);
bs = this.getBufferStrategy();
g = bs.getDrawGraphics();
addKeyListener(Controller.getInstance());
}
public static Renderer getInstance() {return renderer;}
public void run() {
g.setColor(Color.BLACK);
//this was to see if even the background would update, it wouldn't
//g.setColor(black ? Color.BLACK : Color.WHITE);
//black = !black;
g.fillRect(0,0,1200, 900);
Registry.getInstance().render();
g.dispose();
bs.show();
}
public Graphics getGraphics() {return g;}
private static class Window extends Canvas {
private Window(int width, int height, String title, Renderer renderer) {
JFrame frame = new JFrame(title);
frame.setPreferredSize(new Dimension(width, height));
frame.setMinimumSize(new Dimension(width, height));
frame.setMaximumSize(new Dimension(width, height));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(renderer);
frame.setVisible(true);
}
}
}
public class Registry {
private static final Registry reg = new Registry();
private final LinkedList<GameObject> objects = new LinkedList<>();
private Registry() {
}
public static Registry getInstance() { return reg; }
public void tick() { //System.out.println("tick");
objects.forEach(GameObject::tick); }
public void render() { objects.forEach(GameObject::render); }
public void add(GameObject gameObject) { objects.add(gameObject); }
public void remove(GameObject gameObject) { objects.remove(gameObject);}
}
public class Controller extends KeyAdapter {
private static final Controller controller = new Controller();
private final HashMap<Character,Boolean> keyStates = new HashMap<>();
private Controller() {
}
public static Controller getInstance() {
return controller;
}
public void keyPressed(KeyEvent e) {
if (!keyStates.getOrDefault(e.getKeyChar(), true)) System.out.println(e.getKeyChar() + " down");
keyStates.put(e.getKeyChar(),true);
}
public void keyReleased(KeyEvent e) {
keyStates.put(e.getKeyChar(),false);
System.out.println(e.getKeyChar() + " up " + keyStates.size());
}
public boolean isKeyDown(char c) {return keyStates.getOrDefault(c,false);}
}
public abstract class GameObject {
protected Graphics graphics = Renderer.getInstance().getGraphics();
protected final ObjectType type;
protected float x,y,r;
protected GameObject(ObjectType objectType, float x, float y, float r) {
this.type = objectType;
this.x = x;
this.y = y;
this.r = r;
Registry.getInstance().add(this);
}
public abstract void tick();
public abstract void render();
public void destroy() { Registry.getInstance().remove(this); }
public float getX() { return x; }
public void setX(float x) { this.x = x; }
public float getY() { return y; }
public void setY(float y) { this.y = y; }
public float getR() { return r; }
public void setR(float r) { this.r = r; }
}
public class Player extends GameObject {
private final Controller controller;
public Player(float x, float y, float r) {
super(ObjectType.PLAYER, x, y, r);
controller = Controller.getInstance();
}
#Override
public void tick() {
this.x += 1;
if (controller.isKeyDown('w')) x += 2;
if (controller.isKeyDown('a')) y -= 2;
if (controller.isKeyDown('s')) x -= 2;
if (controller.isKeyDown('d')) y += 2;
}
#Override
public void render() {
graphics.setColor(Color.BLUE);
graphics.fillRect((int) (this.x-12),(int) (this.y-12), 24,24);
}
}
The problem lies in your handling of Graphics. There's only ONE active Graphics object you can effectively address.
Refactor your code, so that you pass the current Graphics object via parameter through the target methods (like here: Player.render() should become Player.render(Gpahics g). And get rid of the Gameobject.graphics member variable. That is the culprit.
Adding to that, the best way to do simple rendering is to override the paint(Graphics g) method or the paintComponents(Graphics g), and from outside call repaint() on the JPanel/Canvas. This way the UI instigates drawing itself, takes care of the actual frequency, and draws default components/design too if there is some.

How to make different animations for keyboard input

I'm making a top-down shooter game in java where I have a stationary player who can turn side to side and can shoot a gun at enemies that move to the center(where the player is). I have made different faces for each side when my player turns, but I'm not able to figure out how to switch the faces when I use the arrow keys. Here is my main panel:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class FinalPanel extends JPanel
{
private static final int FRAME = 1600;
private static final Color BACKGROUND = new Color(255, 255, 255);
private Player player;
private ImageIcon faces;
private ImageIcon playerFace = new ImageIcon("PlayerUpImage.png");
private BufferedImage myImage;
private Graphics myBuffer;
private Timer timer;
public FinalPanel()
{
myImage = new BufferedImage(FRAME, FRAME, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
addKeyListener(new Key());
setFocusable(true);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
ImageIcon player = new ImageIcon("PlayerUpImage.png");
myBuffer.drawImage(player.getImage(), 800, 800, null);
repaint();
}
}
public void paintComponent(Graphics g)
{
super.paintComponenet(g);
g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);
}
private class Key extends KeyAdapter//The arrow keys make the player change directions and it replaces his face with a different animation to show the change in direction
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_W)
{
playerFace = new ImageIcon("PlayerUpImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_S)
{
playerFace = new ImageIcon("PlayerDownImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_A)
{
playerFace = new ImageIcon("PlayerLeftImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_D)
{
playerFace = new ImageIcon("PlayerRightImage.png");
}
repaint();
}
}
}
Player class:
import java.awt.*;
import javax.swing.*;
public class Player
{
//Private fields for player class
private int myX;
private int myY;
private int myXWidth;
private int myYWidth;
public Player()
{
myX = 775;
myY = 775;
myXWidth = 50;
myYWidth = 50;
}
public Player(int x, int y, int xWidth, int yWidth)
{
myX = x;
myY = y;
myXWidth = xWidth;
myYWidth = yWidth;
}
//I borrowed this health code from: https://stackoverflow.com/questions/9834609/how-to-make-a-player-class-that-holds-lives-inheritance//
int liveCount = 10;
public boolean damage() {
--liveCount;
return isDead();
}
public boolean isDead() {
return liveCount < 1;
}
public void boostLives(int moreLives) {
liveCount += moreLives;
}
//Accessor Methods//
public int getX()
{
return myX;
}
public int getY()
{
return myY;
}
public int getXWidth()
{
return myXWidth;
}
public int getYWidth()
{
return myYWidth;
}
//Modifier Methods//
public void setX(int x)
{
myX = x;
}
public void setY(int y)
{
myY = y;
}
public void setXWidth(int xWidth)
{
myXWidth = xWidth;
}
public void setYWidth(int yWidth)
{
myYWidth = yWidth;
}
}
I have some suggestions that might help:
Don’t use the variable faces, instead, have an ImageIcon called playerFace with a default direction of up
private ImageIcon playerFace = new ImageIcon(“PlayerUpImage.png”);
Your paint method could then look like this
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(playerFace.getImage(), 800, 800, null);
}
In your keyPressed method, all you have to do is change the player image and call the method repaint so that the panel calls the paintComponent method again:
public void keyPressed(KeyEvent e) {
//pressed d for example
if(e.getKeyCode() == KeyEvent.VK_D)
playerFace = new ImageIcon(“PlayerImageRight.png”);
... //if else’s for other keys
repaint();
}
Preferably, you’d want to have playerFaces as an attribute of the Player class with a getter method to get the playerFace direction (so making playerFace a variable of Player). But this is to get you started
You’ll also want to set up a frame instead of using your current variable FRAME
public FinalPanel() {
JFrame frame = new JFrame();
frame.setSize(1600, 1600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.setVisible(true);
addKeyListener(new Key());
setFocusable(true);
}

Issue with calling a method and updating graphics

I have a KeyListener that works, but when I try to call a method such as getdx(), I'm not seeing any change. goal is to make a map move with arrows.
I've searched google and stackoverflow in various places, chopped my code all up and it's now pretty messy. what am I doing wrong?
public class GuiPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private Timer timer;
private DrawMap drawmap = new DrawMap();
private DrawChar drawchar = new DrawChar();
KeyBoard keyboard = new KeyBoard();
boolean change = false;
public GuiPanel()
{
KeyListener listener = new KeyBoard();
addKeyListener(listener);
initGuiPanel();
}
private void initGuiPanel()
{
setFocusable(true);
setBackground(Color.BLACK);
setDoubleBuffered(true);
timer = new Timer(1000, this);
timer.start();
new GameLogic ("gamelogic").start();
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
draw(g);
Toolkit.getDefaultToolkit().sync();
}
private void draw(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
drawmap.drawmap(g2d);
drawchar.drawchar(g2d);
}
#Override
public void actionPerformed(ActionEvent e)
{
keyboard.getdx();
keyboard.getdy();
drawmap.move(keyboard.getdx(),keyboard.getdy());
repaint();
}
}
public class KeyBoard extends KeyAdapter
{
private int dx;
private int dy;
private int angle=1;
private boolean change = false;
KeyBoardLogic keyboardlogic = new KeyBoardLogic();
public int getdx()//does not return proper value
{
return keyboardlogic.getdx();
}
public void keyPressed(KeyEvent e)
{
keyboardlogic.keypressed(e);
}
public void keyReleased(KeyEvent e)
{
keyboardlogic.keyreleased(e);
}
}
public class KeyBoardLogic
{
private int dx=0;
public int getdx()
{
return dx;
}
public void keypressed(KeyEvent e)
{
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
{
dx = -1;//does not update when getdx() is called
System.out.println("left");//works
}
}
public void keyreleased(KeyEvent e)
{
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
{
dx = -1;//just to know that something happened...
}
}
}
Initialize dx in the constructor of KeyBoardLogic like this:
public class KeyBoardLogic
{
private int dx;
public keyBoardLogic()
{
this.dx = 0;
}
//Remaining methods....
}
Got it. after a week of troubleshooting. dx and dy needed to be static. also a number of other coding errors masked the main problem.

Categories