#java #arrays #draw #paint
#java #массивы #рисовать #Краски
Вопрос:
Это все мои классы, я пытаюсь создать платформерную игру со списком массивов для хранения моих платформ, чтобы я мог добавлять больше платформ в любое время и в любом месте. По какой-то причине он не рисует платформы.
Может кто-нибудь, пожалуйста, помочь мне с этой проблемой или дать мне альтернативу?
ПРИМЕЧАНИЕ: некоторые переменные и методы, которые я либо еще не использовал, либо забыл удалить при повторном создании своего кода. пакетная игра;
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 amp;amp; keyRight || !keyLeft amp;amp; !keyRight) {
velocityX *= 0.8;
}
if(keyLeft amp;amp; !keyRight) {
velocityX--;
}
if(keyRight amp;amp; !keyLeft) {
velocityX ;
}
if(velocityX > 0 amp;amp; velocityX < 0.75) velocityX = 0;
if(velocityX < 0 amp;amp; 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);
}
}
Комментарии:
1. Что именно происходит при запуске вашей программы?
2. Я заметил, что вы рисуете все платформы, а затем рисуете свой фон поверх.
3.
SCREEN_HEIGHT
установлено600
значение, и вы устанавливаете начальнуюy
позицию платформы600
, и она никогда не перемещается…
Ответ №1:
Итак, вы устанавливаете высоту экрана на 600
, final int SCREEN_HEIGHT = 600;
но затем y
600
также создаете положение своих платформ platform.add(new Map(i,600,50,50));
.
Поскольку они никогда не перемещаются, это выведет их за пределы экрана, поэтому быстрое решение — изменить y
позицию на что-то, что находится в пределах видимого диапазона, возможно 550
, таким образом вы их увидите (для начала).
Наблюдения
Существует много интересных идей, и я не уверен, что вы полностью понимаете, как работает API.
Начните с просмотра:
Это даст вам лучшее понимание того, как работает система рисования в Swing и как вы должны с ней работать.
Сказав это, Swing по умолчанию имеет двойную буферизацию, поэтому вам не нужен собственный резервный буфер, просто переопределите paintComponent
и нарисуйте Graphics
контекст
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
draw(g2d);
g2d.dispose();
}
это поможет устранить одну из возможных проблем.
Swing также не является потокобезопасным, поэтому вам следует избегать добавления дат в пользовательский интерфейс (или состояния, на которое опирается пользовательский интерфейс) вне контекста потока отправки событий.
Вместо использования java.util.Timer
вы должны использовать javax.swing.Timer
, который будет генерировать обратные вызовы в контексте EDT.
Подробнее см. Параллелизм в Swing и как использовать таймеры Swing
gameTimer = new Timer(5, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
player1.move();
repaint();
}
});
gameTimer.start();
KeyListener
хорошо известно, что вызывает проблемы, и существует более совершенная система, которая решает эти проблемы, подробнее см. В разделе Как использовать привязки клавиш.
Я также не совсем уверен, что происходит с 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);
}
Вы расширяете его Rectangle
, но затем создаете Rectangle
внутри него другой, и я понятия не имею, что вообще делают все поля экземпляра (вы в основном игнорируете то, что когда-либо передавалось, в пользу ваших свойств)
Вы могли бы просто сделать что-то вроде и использовать Player
как hotbox
само
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);
}
Выполняемый пример…
Привязки клавиш могут быть интересными, поэтому я изменил ваш код для их поддержки (и вышеупомянутых изменений), чтобы дать вам лучшее представление.
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) amp;amp; hasDirection(Direction.RIGHT) || !hasDirection(Direction.LEFT) amp;amp; !hasDirection(Direction.RIGHT)) {
velocityX *= 0.8;
}
if (hasDirection(Direction.LEFT) amp;amp; !hasDirection(Direction.RIGHT)) {
velocityX--;
}
if (hasDirection(Direction.RIGHT) amp;amp; !hasDirection(Direction.LEFT)) {
velocityX ;
}
if (velocityX > 0 amp;amp; velocityX < 0.75) {
velocityX = 0;
}
if (velocityX < 0 amp;amp; 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);
}
}
}