These are all of my classes, I'm trying to make a platformer game with an array list to hold my platforms, this is so I can add more platforms any time and anywhere. For some reason, it's not drawing the platforms.
Can someone please help me with this issue or give me an alternative?
NOTE: some of the variables and methods I either haven't used yet or forgot to delete when i was re-creating my code. package Game;
import Game.Frame;
public class Main {
public static void main(String[] args) {
new Frame();
}
}
package Game;
import javax.swing.*;
import java.awt.*;
public class Frame extends JFrame {
GamePanel panel;
public Frame() {
panel = new GamePanel();
this.add(panel);
this.setTitle("Platformer Game");
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
package Game;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.Timer;
public class GamePanel extends JPanel implements ActionListener{
Player player1;
Map map1;
final int SCREEN_WIDTH = 1000;
final int SCREEN_HEIGHT = 600;
final int PLAYER_WIDTH = 50;
final int PLAYER_HEIGHT = 60;
final Dimension SCREEN_SIZE = new Dimension(SCREEN_WIDTH,SCREEN_HEIGHT);
boolean falling = false;
boolean playing = true;
Image backgroundImage;
Thread gameThread;
Image image;
Graphics graphics;
Timer gameTimer;
ArrayList<Map> platform = new ArrayList<>();
public GamePanel() {
java.net.URL imgIcon = Main.class.getResource(
"/Resources/spaceImage.jpg");
backgroundImage = new ImageIcon(imgIcon).getImage();
newPlayer();
newMap();
this.setFocusable(true);
this.setPreferredSize(SCREEN_SIZE);
this.setOpaque(true);
this.addKeyListener(new KeyListener(
) {
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
KeyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
KeyReleased(e);
}
});
gameTimer = new Timer();
gameTimer.schedule(new TimerTask(){
@Override
public void run() {
player1.move();
repaint();
}
}, 0 , 17);
}
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);
for(Map map1: platform) {
map1.paint(g2D);
}
}
public void KeyPressed(KeyEvent e) {
if(e.getKeyChar()=='a') {
player1.keyLeft = true;
}
if(e.getKeyChar()=='d') player1.keyRight = true;
if(e.getKeyChar()=='s') player1.keyDown = true;
if(e.getKeyChar()=='w') player1.keyUp = true;
}
public void KeyReleased(KeyEvent e) {
if(e.getKeyChar()=='a') player1.keyLeft = false;
if(e.getKeyChar()=='d') player1.keyRight = false;
if(e.getKeyChar()=='s') player1.keyDown = false;
if(e.getKeyChar()=='w') player1.keyUp = false;
}
public void newPlayer() {
player1 = new Player((SCREEN_WIDTH/2)-(PLAYER_WIDTH/2), (SCREEN_HEIGHT/2)-(PLAYER_WIDTH/2), PLAYER_WIDTH, PLAYER_HEIGHT, this);
}
public void newMap() {
for(int i=50;i<650;i =50){
platform.add(new Map(i,600,50,50));
}
}
public void gameOver() {
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
package Game;
import Game.GamePanel;
import java.awt.*;
import java.awt.event.KeyEvent;
public class Player extends Rectangle{
double velocityY = 0;
double velocityX = 0;
final int PLAYER_WIDTH = 50;
final int PLAYER_HEIGHT = 50;
static int speed = 2;
GamePanel panel;
boolean keyRight = false;
boolean keyLeft = false;
boolean keyUp = false;
boolean keyDown = false;
Rectangle hitbox;
public Player(int x, int y, int PLAYERWIDTH, int PLAYERHEIGHT, GamePanel panel) {
super(x,y,PLAYERWIDTH,PLAYERHEIGHT);
this.panel = panel;
hitbox = new Rectangle();
}
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setColor(Color.red);
g2D.fillRect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT);
}
public void move() {
if(keyLeft && keyRight || !keyLeft && !keyRight) {
velocityX *= 0.8;
}
if(keyLeft && !keyRight) {
velocityX--;
}
if(keyRight && !keyLeft) {
velocityX ;
}
if(velocityX > 0 && velocityX < 0.75) velocityX = 0;
if(velocityX < 0 && velocityX > -0.75) velocityX = 0;
if(velocityX > 7) velocityX = 7;
if(velocityX < -7) velocityX = -7;
if(keyUp) {
velocityY = -6;
}
velocityY = 0.3;
y = velocityY;
x = velocityX;
hitbox.x = x;
hitbox.y = y;
}
}
package Game;
import java.awt.*;
public class Map {
int PLATFORM_WIDTH = 600;
int PLATFORM_HEIGHT = 150;
int x;
int y;
Rectangle hitbox;
public Map(int x, int y, int PLATFORM_WIDTH, int PLATFORM_HEIGHT) {
this.x = x;
this.y = y;
this.PLATFORM_WIDTH = PLATFORM_WIDTH;
this.PLATFORM_HEIGHT = PLATFORM_HEIGHT;
hitbox = new Rectangle(x,y,PLATFORM_WIDTH, PLATFORM_HEIGHT);
}
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setColor(Color.gray);
g2D.fillRect(x,y,PLATFORM_WIDTH,PLATFORM_HEIGHT);
}
}
CodePudding user response:
So you set the screen height to 600
, final int SCREEN_HEIGHT = 600;
but then create your platforms y
position to 600
as well, platform.add(new Map(i,600,50,50));
.
Since they never move, this is going to paint them off screen, so, a quick solution is to change the y
position to something which is within the visible range, maybe 550
, that way you will see them (to start with).
Observations
There's a lot of, interesting, ideas going on and I'm not sure you entirely understand how the API works.
Start by having a look at:
This will give you a better understanding of how the paint system works in Swing and how you should work with it.
Having said that, Swing is double buffered by default, so you don't need your own backing buffer, just override paintComponent
and paint to the Graphics
context
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
draw(g2d);
g2d.dispose();
}
this will help eliminate one possible area of issues.
Swing is also not thread safe, so you should avoid making up dates to the UI (or state the UI relies on) from outside the context of the Event Dispatching Thread.
Instead of using java.util.Timer
, you should be using javax.swing.Timer
, which will generate it's callbacks within the context of the EDT.
See Concurrency in Swing and How to Use Swing Timers for more details
gameTimer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
player1.move();
repaint();
}
});
gameTimer.start();
KeyListener
is well know for causing issues and there is a better system available which resolves these issues, see How to Use Key Bindings for more details.
I'm also not really sure what's going on with Player
public class Player extends Rectangle {
double velocityY = 0;
double velocityX = 0;
final int PLAYER_WIDTH = 50;
final int PLAYER_HEIGHT = 50;
static int speed = 2;
GamePanel panel;
boolean keyRight = false;
boolean keyLeft = false;
boolean keyUp = false;
boolean keyDown = false;
Rectangle hitbox;
public Player(int x, int y, int PLAYERWIDTH, int PLAYERHEIGHT, GamePanel panel) {
super(x, y, PLAYERWIDTH, PLAYERHEIGHT);
this.panel = panel;
hitbox = new Rectangle();
}
public void paint(Graphics g) {
Graphics2D g2D = (Graphics2D) g;
g2D.setColor(Color.red);
g2D.fillRect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT);
}
You extend it from Rectangle
, but then you create another Rectangle
within it and I have no idea what all the instance fields are doing at all (you basically ignore what ever's passed in, in favour of your properties)
You could just do something like and use Player
as the hotbox
itself
public class Player extends Rectangle {
enum Direction {
UP, DOWN, LEFT, RIGHT
}
private double velocityY = 0;
private double velocityX = 0;
private int speed = 2;
public Player(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void paint(Graphics2D g2D) {
g2D.setColor(Color.RED);
g2D.fill(this);
}
Runnable example...
Key bindings can be fun to get your head around, so I've modified your code to support them (and the above mentioned changes) to give you a better idea.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Set;
import java.util.TreeSet;
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 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 GamePanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GamePanel extends JPanel implements ActionListener {
protected static final int SCREEN_WIDTH = 1000;
protected static final int SCREEN_HEIGHT = 600;
protected static final int PLAYER_WIDTH = 50;
protected static final int PLAYER_HEIGHT = 60;
protected static final Dimension SCREEN_SIZE = new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);
boolean falling = false;
boolean playing = true;
Player player1;
Map map1;
Image backgroundImage;
Timer gameTimer;
ArrayList<Map> platform = new ArrayList<>();
public GamePanel() {
BufferedImage img = new BufferedImage(SCREEN_WIDTH, SCREEN_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.BLUE);
g2d.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g2d.dispose();
backgroundImage = new ImageIcon(img).getImage();
newPlayer();
newMap();
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "Pressed.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), "Pressed.right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "Pressed.up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "Pressed.down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "Released.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), "Released.right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "Released.up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), "Released.down");
am.put("Pressed.left", new MoveAction(player1, Player.Direction.LEFT, true));
am.put("Pressed.right", new MoveAction(player1, Player.Direction.RIGHT, true));
am.put("Pressed.up", new MoveAction(player1, Player.Direction.UP, true));
am.put("Pressed.down", new MoveAction(player1, Player.Direction.DOWN, true));
am.put("Released.left", new MoveAction(player1, Player.Direction.LEFT, false));
am.put("Released.right", new MoveAction(player1, Player.Direction.RIGHT, false));
am.put("Released.up", new MoveAction(player1, Player.Direction.UP, false));
am.put("Released.down", new MoveAction(player1, Player.Direction.DOWN, false));
gameTimer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
player1.move();
repaint();
}
});
gameTimer.start();
}
@Override
public Dimension getPreferredSize() {
return SCREEN_SIZE;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
draw(g2d);
g2d.dispose();
}
public void draw(Graphics2D g2D) {
g2D.drawImage(backgroundImage, 0, 0, null);
player1.paint(g2D);
for (Map map1 : platform) {
map1.paint(g2D);
}
}
public void newPlayer() {
player1 = new Player((SCREEN_WIDTH / 2) - (PLAYER_WIDTH / 2), (SCREEN_HEIGHT / 2) - (PLAYER_WIDTH / 2), PLAYER_WIDTH, PLAYER_HEIGHT);
}
public void newMap() {
for (int i = 50; i < 650; i = 50) {
platform.add(new Map(i, 550, 50, 50));
}
}
public void gameOver() {
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
public class MoveAction extends AbstractAction {
private Player player;
private Player.Direction direction;
private boolean pressed;
public MoveAction(Player player, Player.Direction direction, boolean pressed) {
this.player = player;
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
player.putDirection(direction);
} else {
player.removeDirection(direction);
}
}
}
public class Player extends Rectangle {
enum Direction {
UP, DOWN, LEFT, RIGHT
}
private double velocityY = 0;
private double velocityX = 0;
private int speed = 2;
private Set<Direction> directions = new TreeSet<>();
public Player(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void putDirection(Direction direction) {
directions.add(direction);
}
public void removeDirection(Direction direction) {
directions.remove(direction);
}
public void paint(Graphics2D g2D) {
g2D.setColor(Color.RED);
g2D.fill(this);
}
protected boolean hasDirection(Direction direction) {
return directions.contains(direction);
}
public void move() {
System.out.println(hasDirection(Direction.UP));
if (hasDirection(Direction.LEFT) && hasDirection(Direction.RIGHT) || !hasDirection(Direction.LEFT) && !hasDirection(Direction.RIGHT)) {
velocityX *= 0.8;
}
if (hasDirection(Direction.LEFT) && !hasDirection(Direction.RIGHT)) {
velocityX--;
}
if (hasDirection(Direction.RIGHT) && !hasDirection(Direction.LEFT)) {
velocityX ;
}
if (velocityX > 0 && velocityX < 0.75) {
velocityX = 0;
}
if (velocityX < 0 && velocityX > -0.75) {
velocityX = 0;
}
if (velocityX > 7) {
velocityX = 7;
}
if (velocityX < -7) {
velocityX = -7;
}
if (hasDirection(Direction.UP)) {
velocityY = -6;
}
velocityY = 0.3;
y = velocityY;
x = velocityX;
}
}
public class Map {
int width;
int height;
int x;
int y;
Rectangle hitbox;
public Map(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
hitbox = new Rectangle(x, y, width, height);
}
public void paint(Graphics2D g2D) {
g2D.setColor(Color.GRAY);
g2D.fill(hitbox);
}
}
}