为啥我的平台不绘制当使用带有数组列表的 for 循环(访问多个平台)时
Posted
技术标签:
【中文标题】为啥我的平台不绘制当使用带有数组列表的 for 循环(访问多个平台)时【英文标题】:Why doesn't my Platform draw When using for loops (to access multiple platforms) with array lists为什么我的平台不绘制当使用带有数组列表的 for 循环(访问多个平台)时 【发布时间】:2022-01-14 00:42:12 【问题描述】:这些都是我的课程,我正在尝试制作一个带有数组列表的平台游戏来保存我的平台,这样我就可以随时随地添加更多平台。出于某种原因,它没有绘制平台。
有人可以帮我解决这个问题或给我一个替代方案吗?
注意:我在重新创建代码时尚未使用或忘记删除的一些变量和方法。 打包游戏;
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);
【问题讨论】:
运行程序时究竟发生了什么? 我注意到您绘制了所有平台,然后在顶部绘制了背景。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 的工作原理。
先看看:
Performing Custom Painting Painting in AWT and Swing这将使您更好地了解绘制系统在 Swing 中的工作原理以及您应该如何使用它。
话虽如此,Swing 默认是双缓冲的,所以你不需要自己的后备缓冲区,只需覆盖 paintComponent
并绘制到 Graphics
上下文
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
draw(g2d);
g2d.dispose();
这将有助于消除一个可能的问题领域。
Swing 也不是线程安全的,因此您应该避免从事件分派线程的上下文之外向 UI(或 UI 所依赖的状态)更新日期。
您应该使用javax.swing.Timer
,而不是使用java.util.Timer
,这将在EDT 的上下文中生成它的回调。
更多详情请参阅Concurrency in Swing 和How to Use Swing Timers
gameTimer = new Timer(5, new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
player1.move();
repaint();
);
gameTimer.start();
KeyListener
众所周知会引起问题,并且有更好的系统可以解决这些问题,请参阅How to Use Key Bindings 了解更多详细信息。
我也不确定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) && 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);
【讨论】:
以上是关于为啥我的平台不绘制当使用带有数组列表的 for 循环(访问多个平台)时的主要内容,如果未能解决你的问题,请参考以下文章
为啥带有pop-method(或del语句)的for循环不会遍历所有列表元素