Reputation: 35
Okay so bascially i have these key events set up in the main class already: https://prnt.sc/jhbxz9.
what im trying to accomplish here is use these key events set in my main class so i can write a method with if/else statements under peformAction in my sub class (player) to make the player move when a key is pressed and stop moving when released. Currently all i can get it to do is consistently move in one direction till it goes off screen without the need of any keys being pressed, but i want it so that it changes velX when VK_LEFT is being pressed but i have 0 idea how to refer to the key event in my sub class without the code breaking. One last thing is that i noticed there is setKey under every key event which made me think i needed to use the setKeys, but still nothing.
Usfull screenshots if u cant be asked to read all of the code. Player Class(sub class): http://prntscr.com/jhbx58 + http://prntscr.com/jhbxim
GameManager Class (main class): http://prntscr.com/jhbxz9
GameManager Class:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JFrame;
public class GameManager extends JFrame implements KeyListener {
private int canvasWidth;
private int canvasHeight;
private int borderLeft;
private int borderTop;
private BufferedImage canvas;
private Stage stage;
private Enemy[] enemies;
private Player player;
private Goal goal;
private Graphics gameGraphics;
private Graphics canvasGraphics;
private int numEnemies;
private boolean continueGame;
public static void main(String[] args) {
// During development, you can adjust the values provided in the brackets below
// as needed. However, your code must work with different/valid combinations
// of values.
GameManager managerObj = new GameManager(1920, 1280, 30);
}
public GameManager(int preferredWidth, int preferredHeight, int maxEnemies) {
this.borderLeft = getInsets().left;
this.borderTop = getInsets().top;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
if (screenSize.width < preferredWidth) {
this.canvasWidth = screenSize.width - getInsets().left - getInsets().right;
} else {
this.canvasWidth = preferredWidth - getInsets().left - getInsets().right;
}
if (screenSize.height < preferredHeight) {
this.canvasHeight = screenSize.height - getInsets().top - getInsets().bottom;
} else {
this.canvasHeight = preferredHeight - getInsets().top - getInsets().bottom;
}
setSize(this.canvasWidth, this.canvasHeight);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
addKeyListener(this);
Random rng = new Random(2);
this.canvas = new BufferedImage(this.canvasWidth, this.canvasHeight, BufferedImage.TYPE_INT_RGB);
// Create a Stage object to hold the background images
this.stage = new Stage();
// Create a Goal object with its initial x and y coordinates
this.goal = new Goal(this.canvasWidth / 2, Math.abs(rng.nextInt()) % this.canvasHeight);
// Create a Player object with its initial x and y coordinates
this.player = new Player(this.canvasWidth - (Math.abs(rng.nextInt()) % (this.canvasWidth / 2)),
(Math.abs(rng.nextInt()) % this.canvasHeight));
// Create the Enemy objects, each with a reference to this (GameManager) object
// and their initial x and y coordinates.
this.numEnemies = maxEnemies;
this.enemies = new Enemy[this.numEnemies];
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i] = new Enemy(this, Math.abs(rng.nextInt()) % (this.canvasWidth / 4),
Math.abs(rng.nextInt()) % this.canvasHeight);
}
this.gameGraphics = getGraphics();
this.canvasGraphics = this.canvas.getGraphics();
this.continueGame = true;
while (this.continueGame) {
updateCanvas();
}
this.stage.setGameOverBackground();
updateCanvas();
}
public void updateCanvas() {
long start = System.nanoTime();
// If the player is alive, this should move the player in the direction of the
// key that has been pressed
// Note: See keyPressed and keyReleased methods in the GameManager class.
this.player.performAction();
// If the enemy is alive, the enemy must move towards the goal. The goal object
// is obtained
// via the GameManager object that is given at the time of creating an Enemy
// object.
// Note: The amount that the enemy moves by must be much smaller than that of
// the player above
// or else the game becomes too hard to play.
for (int i = 0; i < this.numEnemies; i++) {
this.enemies[i].performAction();
}
if ((Math.abs(this.goal.getX() - this.player.getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.player.getY()) < (this.goal.getCurrentImage().getWidth()
/ 2))) {
for (int i = 0; i < this.numEnemies; i++) {
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
this.enemies[i].die();
}
// Sets the image of the enemy to the "dead" image and sets its status to
// indicate dead
this.goal.die();
// Sets the background of the stage to the finished game background.
this.stage.setGameOverBackground();
this.continueGame = false;
}
// If an enemy is close to the goal, the player and goal die
int j = 0;
while (j < this.numEnemies) {
if ((Math.abs(this.goal.getX() - this.enemies[j].getX()) < (this.goal.getCurrentImage().getWidth() / 2))
&& (Math.abs(this.goal.getY() - this.enemies[j].getY())
< (this.goal.getCurrentImage().getWidth() / 2))) {
this.player.die();
this.goal.die();
this.stage.setGameOverBackground();
j = this.numEnemies;
this.continueGame = false;
}
j++;
}
try {
// Draw stage
this.canvasGraphics.drawImage(stage.getCurrentImage(), 0, 0, null);
// Draw player
this.canvasGraphics.drawImage(player.getCurrentImage(),
this.player.getX() - (this.player.getCurrentImage().getWidth() / 2),
this.player.getY() - (this.player.getCurrentImage().getHeight() / 2), null);
// Draw enemies
for (int i = 0; i < this.numEnemies; i++) {
this.canvasGraphics.drawImage(this.enemies[i].getCurrentImage(),
this.enemies[i].getX() - (this.enemies[i].getCurrentImage().getWidth() / 2),
this.enemies[i].getY() - (this.enemies[i].getCurrentImage().getHeight()
/ 2), null);
}
// Draw goal
this.canvasGraphics.drawImage(this.goal.getCurrentImage(),
this.goal.getX() - (this.goal.getCurrentImage().getWidth() / 2),
this.goal.getY() - (this.goal.getCurrentImage().getHeight() / 2), null);
} catch (Exception e) {
System.err.println(e.getMessage());
}
// Draw everything.
this.gameGraphics.drawImage(this.canvas, this.borderLeft, this.borderTop, this);
long end = System.nanoTime();
this.gameGraphics.drawString("FPS: " + String.format("%2d", (int) (1000000000.0 / (end - start))),
this.borderLeft + 50, this.borderTop + 50);
}
public Goal getGoal() {
return this.goal;
}
public void keyPressed(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently pressed.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
if (ke.getKeyCode() == KeyEvent.VK_LEFT) {
this.player.setKey('L', true);
}
if (ke.getKeyCode() == KeyEvent.VK_RIGHT) {
this.player.setKey('R', true);
}
if (ke.getKeyCode() == KeyEvent.VK_UP) {
this.player.setKey('U', true);
}
if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
this.player.setKey('D', true);
}
if (ke.getKeyCode() == KeyEvent.VK_ESCAPE) {
this.continueGame = false;
}
}
@Override
public void keyReleased(KeyEvent ke) {
// Below, the setKey method is used to tell the Player object which key is
// currently released.
// The Player object must keep track of the pressed key and use it for
// determining the direction
// to move.
if (ke.getKeyCode() == KeyEvent.VK_LEFT) {
this.player.setKey('L', false);
}
if (ke.getKeyCode() == KeyEvent.VK_RIGHT) {
this.player.setKey('R', false);
}
if (ke.getKeyCode() == KeyEvent.VK_UP) {
this.player.setKey('U', false);
}
if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
this.player.setKey('D', false);
}
}
@Override
public void keyTyped(KeyEvent ke) {
}
}
My Player Class (subclass):
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Player {
private BufferedImage imageRunning;
private BufferedImage imageOver;
private BufferedImage imageCurrent;
int valx = 500;
int valy = 100;
public Player(int valx, int valy) {
try {
this.imageRunning = ImageIO.read(new File("C:/Users/HUS/Desktop/Assigment222/images/player-alive.png"));
this.imageOver = ImageIO.read(new File("C:/Users/HUS/Desktop/Assigment222/images/player-dead.png"));
} catch (IOException e) {
e.printStackTrace();
}
this.imageCurrent = this.imageRunning;
}
public BufferedImage getCurrentImage() {
return this.imageCurrent;
}
public void setGameOverBackground() {
this.imageCurrent = this.imageOver;
}
public void performAction() {
if(Player.setKey('D', true) == true) {
this.valx += 2;
}
else if(Player.setKey('D', false) == false) {
this.valx = 0;
}
return;
}
public int getX() {
return valx;
}
public int getY() {
return valy;
}
public void die() {
return;
}
public static boolean setKey(char c, boolean b) {
return b;
}
}
Upvotes: 0
Views: 315
Reputation: 347314
So when keyPressed
or keyReleased
is called, they will, in turn, call Player.setKey
. When this gets called, you store the state.
For example...
public class Player {
//...
// I really, really, really don't static been used this way, it
// has a bad code smell about it...
public static Set<Character> inputState = new TreeSet<Character>();
//...
public static void setKey(char c, boolean b) {
if (b) {
inputState.add(c);
} else {
inputState.remove(c);
}
}
}
So, all this really does is either adds the char
to the Set
or removes it. Because Set
guarantees uniqueness, we don't need to care if the key has already been pressed.
Then when performAction
is called, you check to see if the input is in the Set
or not and take appropriate action...
public void performAction() {
if (inputState.contains('U')) {
// Going up
} else if (inputState.contains('D')) {
// Going down
}
//... other inputs
}
Upvotes: 1