gpt4 book ai didi

java - Component.setBounds 调用 Component.repaint?

转载 作者:行者123 更新时间:2023-11-29 03:09:31 31 4
gpt4 key购买 nike

所以我正在制作一个游戏,我有 EnemyAI 以及 player,它们都扩展了 JPanel。世界有一个 null 布局,所以我正在使用 setBounds(); 来“移动”(我实际上只是移动世界图像)entities(playerAI)并正确放置它们。但是当我添加(看起来,我测试了尽可能小的数字)5 时,它会完全自行调用 repaint()。这会导致玩家在视觉上原地行走。我添加的实体越多,间隔越快(即 5 个实体调用 repaint() 比 500 个慢很多)。

注意:下面类中的window只是一个JFrame

主类:

public class Game(){
public static boolean fighting = false;
public static void startGame(){
WorldPanel game = new WorldPanel();
game.setPreferredSize(new Dimension(window.getWidth(), window.getHeight()));
PlayerPane player = new PlayerPane(32,32, "Player 1");
game.addKeyListener(new KeyListener(){

public void keyPressed(KeyEvent arg0) {
if(fighting == false){
move(player, game, arg0.isShiftDown(), arg0.getKeyCode());
} else {
System.out.println("Fighting = " + fighting);
}
}
@Override
public void keyReleased(KeyEvent arg0) {
gameTimer.stop();
player.setIndex(0);
game.repaint();
}
@Override
public void keyTyped(KeyEvent arg0) {
}
});
window.add(game);
game.setLayout(null);
game.requestFocus();
setImages(player, PLAYER_DOWN);
player.setDrawY(349);
player.setDrawX(493);
player.updateBounds();
game.add(player);
entities.add(player);
addEntities(game);
redoWindow();
}
public static void updateEntityBounds(){
PlayerPane player = null;
EnemyAI enemy = null;
for(int i = 0; i < entities.size(); i++){
if(i == 0){
player = (PlayerPane) entities.get(i);
} else {
enemy = (EnemyAI) entities.get(i);
if(enemy.getBounds().intersects(player.getBounds())){
startFight(i);
}
}
if(player != null){
player.updateBounds();
}
if(enemy != null){
enemy.updateBounds();
}
}
}
public static void addEntities(WorldPanel game){
EnemyAI enemies[] = new EnemyAI[5];
for(int i = 0; i < enemies.length; i++){
if(i%6 == 0){
try{
enemies[i] = new EnemyAI(32,32, ImageIO.read(new File("H:\\Java\\Game\\src\\res\\SlimeLv3Still.png")));
enemies[i].start();
}catch(IOException e){
e.printStackTrace();
}
}else if (i % 2 == 0){
try{
enemies[i] = new EnemyAI(32,32, ImageIO.read(new File("H:\\Java\\Game\\src\\res\\SlimeLv2Still.png")));
enemies[i].setEnX(enemies[i].getRandomX());
enemies[i].setEnY(enemies[i].getRandomY());
enemies[i].start();
}catch(IOException e){
e.printStackTrace();
}
} else {
try{
enemies[i] = new EnemyAI(32,32, ImageIO.read(new File("H:\\Java\\Game\\src\\res\\SlimeLv1Still.png")));
enemies[i].setEnX(enemies[i].getRandomX());
enemies[i].setEnY(enemies[i].getRandomY());
enemies[i].start();
}catch(IOException e){
e.printStackTrace();
}
}
game.add(enemies[i]);
entities.add(enemies[i]);
}
}
public static void move(PlayerPane player, WorldPanel game, boolean shiftDown, int keyPressed){
gameTimer = new Timer(50, new ActionListener(){
public void actionPerformed(ActionEvent e){
updateEntityBounds();
redoWindow();
gameTimer.stop();
}
});
if(gameTimer.isRepeats()){
gameTimer.setRepeats(false);
}
if(shiftDown){
if(keyPressed == KeyEvent.VK_W && ((game.getImageY() == 0 && player.getDrawY() > 10) || player.getDrawY() >= 349)){
player.setDrawY(player.getDrawY() - 2);
setImages(player, PLAYER_UP);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_S && ((game.getImageY() == -3868 && player.getDrawY() < 681) || player.getDrawY() <= 349)){
player.setDrawY(player.getDrawY() + 2);
setImages(player, PLAYER_DOWN);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_A && ((game.getImageX() == 0 && player.getDrawX() > 10) || player.getDrawX() > 493 )){
player.setDrawX(player.getDrawX() - 2);
setImages(player, PLAYER_LEFT);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_D && ((game.getImageX() == -5126 && player.getDrawX() < player.getHeight() - 10) || player.getDrawX() < 493 )){
player.setDrawX(player.getDrawX() + 2);
setImages(player, PLAYER_RIGHT);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_W && game.getImageY() < 0){
if(game.getImageY() == -1){
game.setImageY(game.getImageY() + 1);
} else {
game.setImageY(game.getImageY() + 2);
}
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnY(enemy.getEnY() + 2);
}
setImages(player, PLAYER_UP);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_A && game.getImageX() < 0){
if(game.getImageX() == -1){
game.setImageX(game.getImageX() + 1);
} else {
game.setImageX(game.getImageX() + 2);
}
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnX(enemy.getEnX() + 2);
}
setImages(player, PLAYER_LEFT);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_S && game.getImageY() > -3868){
if(game.getImageY() == -3867){
game.setImageY(game.getImageY() - 1);
} else {
game.setImageY(game.getImageY() - 2);
}
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnY(enemy.getEnY() - 2);
}
setImages(player, PLAYER_DOWN);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_D && game.getImageX() > -5126){
if(game.getImageX() == -5125){
game.setImageX(game.getImageX() - 1);
} else {
game.setImageX(game.getImageX() - 2);
}
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnX(enemy.getEnX() - 2);
}
setImages(player, PLAYER_RIGHT);
gameTimer.start();

}
} else {
if(keyPressed == KeyEvent.VK_W && ((game.getImageY() == 0 && player.getDrawY() > 10) || player.getDrawY() > 349)){
player.setDrawY(player.getDrawY() - 1);
setImages(player, PLAYER_UP);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_S && ((game.getImageY() == -3868 && player.getDrawY() < 681) || player.getDrawY() < 349)){
player.setDrawY(player.getDrawY() + 1);
setImages(player, PLAYER_DOWN);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_A && ((game.getImageX() == 0 && player.getDrawX() > 10) || player.getDrawX() > 493 )){
player.setDrawX(player.getDrawX() - 1);
setImages(player, PLAYER_LEFT);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_D && ((game.getImageX() == -5126 && player.getDrawX() < player.getHeight() - 10) || player.getDrawX() < 493 )){
player.setDrawX(player.getDrawX() + 1);
setImages(player, PLAYER_RIGHT);
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_W && game.getImageY() < 0){
game.setImageY(game.getImageY() + 1);
setImages(player, PLAYER_UP);
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnY(enemy.getEnY() + 1);
}
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_A && game.getImageX() < 0){
game.setImageX(game.getImageX() + 1);
setImages(player, PLAYER_LEFT);
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnX(enemy.getEnX() + 1);
}
gameTimer.start();

} else
if(keyPressed == KeyEvent.VK_S && game.getImageY() > -3868){
game.setImageY(game.getImageY() - 1);
setImages(player, PLAYER_DOWN);
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnY(enemy.getEnY() - 1);
}
gameTimer.start();
} else
if(keyPressed == KeyEvent.VK_D && game.getImageX() > -5126){
game.setImageX(game.getImageX() - 1);
setImages(player, PLAYER_RIGHT);
for(int i = 1; i < entities.size(); i++){
EnemyAI enemy = (EnemyAI)entities.get(i);
enemy.setEnX(enemy.getEnX() - 1);
}
gameTimer.start();
}
}
}
}

玩家:

public class PlayerPane extends JPanel{
private static final long serialVersionUID = 8946273935579723365L;
private ImageIcon images[] = new ImageIcon[9];
public static final int PLAYER_FRAMES = 9;
private String name;
private int index;
private int imageX, imageY;
private int HP = 100;



public PlayerPane(int width, int height, String playerName) {
setPreferredSize(new Dimension(width, height));
imageX = imageY = 0;
name = playerName;
// Border border = BorderFactory.createBevelBorder(BevelBorder.RAISED);
// PlayerPane.this.setBorder(border);
}
public String getName(){
return name;
}
public void paintComponent(Graphics g){
try {
g.drawImage(ImageIO.read(new File("H:\\Java\\Game\\src\\res\\TransparentImg.png")),0,0,getWidth(),getHeight(), null);
} catch (IOException e) {
e.printStackTrace();
}
g.drawImage(images[index].getImage(), 0,0, null);

if(index == images.length-1){
index = 0;
} else {
index++;
}
}
public void setIndex(int index){
this.index = index;
}
public void stop(){
index = 0;
}
public void addImage(ImageIcon image, int x){
images[x] = image;
}
public void setDrawX(int x){
imageX = x;
}
public void setDrawY(int y){
imageY = y;
}
public int getDrawY(){
return imageY;
}
public int getDrawX(){
return imageX;
}
public void updateBounds(){
setBounds(imageX, imageY, 32,32);
}
public int getHP(){
return HP;
}
public void setHP(int hp){
HP = hp;
}
}

EnemyAI 类:

public class EnemyAI extends AI{
private static final long serialVersionUID = -2417438750134536982L;

private Rectangle rect;
private BufferedImage backgroundImg;
private int HP = 1;
private int damage = 15;

public EnemyAI(int width, int height, BufferedImage backgroundImg){
super();
rect = new Rectangle(width, height);
this.backgroundImg = backgroundImg;
}
@Override
public void paintComponent(Graphics g) {
try{
g.drawImage(ImageIO.read(new File("H:\\Java\\Game\\src\\res\\TransparentImg.png")), 0,0,null);
}catch(IOException e){
e.printStackTrace();
}

g.drawImage(backgroundImg, 0, 0, null);
}
public boolean intersects(Rectangle r){
return rect.intersects(r);
}
public int getRandomX(){
Random ran = new Random();
int rand = ran.nextInt(6144);
return rand;
}
public int getRandomY(){
Random ran = new Random();
int rand = ran.nextInt(4608);
return rand;
}
public int getHP(){
return HP;
}
public void setHP(int hp){
HP = hp;
}
public int getDamage(){
return damage;
}
}

上述类扩展的AI类:

public abstract class AI extends JPanel implements Runnable{
private static final long serialVersionUID = 283692586329054555L;

private boolean running = false;
private Thread moveThread;
private int x = 0, y = 0;

public AI(){
moveThread = new Thread(this);
}
public void start(){
running = true;
moveThread.start();
}
public void stop(){
running = false;
}
public boolean isRunning(){
return running;
}

public void run(){
while(running){
if(Game.fighting == false){
Random direction = new Random();
int dir = direction.nextInt(4);
switch(dir){
case 1:
if(this.getX() < Game.getWindowWidth()){
this.setEnX(this.getX() + 1);
}
break;
case 2:
if(this.getX() > 0){
this.setEnX(this.getX() - 1);
}
break;
case 3:
if(this.getX() < Game.getWindowHeight()){
this.setEnY(this.getY() + 1);
}
break;
case 4:
if(this.getX() < 0){
this.setEnY(this.getY() - 1);
}
break;
}
updateBounds();
try{
Thread.sleep(200);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
public void setEnX(int x){
this.x = x;
}
public void setEnY(int y){
this.y = y;
}
public int getEnX(){
return x;
}
public int getEnY(){
return y;
}
public void updateBounds(){
setBounds(x, y, 32,32);
}
public abstract void paintComponent(Graphics g);
}

我知道我只是向你们扔了很多代码。我试着不这样做,但回过头来看我试图提供一个运行的例子。如果我遗漏了任何代码,请告诉我,我会添加它。

无论如何,我需要知道的是如何让 setBounds() 停止调用 repaint()(除了使用少于 5 个 实体)。此外,我在添加 entities 时删除了 EnemyAI.start() 并且确实阻止了它。所以我有理由相信问题出在AI类的run()方法中。这几乎只是调用 setBounds()

最佳答案

这是正常行为,这就是为什么您不能在 paintComponent 中修改状态的原因。我们无法控制重绘何时发生:系统有时会自行完成。

这是我的意思的一个例子,你不应该这样做:

public class PlayerPane extends JPanel{
...

public void paintComponent(Graphics g){
...

// modifying index
if(index == images.length-1){
index = 0;
} else {
index++;
}
}
}

您需要遍历所有代码,查找您在 paintComponent 中修改过这样的变量的每个地方,并将其移出到其他地方。

作为旁注,您还应该移动您的 ImageIO.read 调用,使它们不在 paintComponent 中。程序启动时将图像加载到 static 变量或类似变量中。

作为一般提示,您应该通过绘画来研究动画,而不是尝试为组件设置动画。从长远来看,这对您的游戏大有裨益。


总结一下:

  • 保持 paintComponent 无状态。
  • 在非 UI 对象中使用游戏/动画状态包装图像。
  • paintComponent 中绘制这些图像。

这是一个最小的例子,它通过动画形状从窗口落下来演示这一点:

falling shapes

import java.net.*;
import javax.swing.*;
import javax.imageio.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Graphics;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;

class FallingShapes implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new FallingShapes());
}

@Override
public void run() {
List<Entity> entities = new ArrayList<Entity>();

int w = 0;
int h = 0;

for (BufferedImage img : Resources.images) {
entities.add(new Entity(img));

w += img.getWidth();
h += img.getHeight();
}

PaintPanel p = new PaintPanel(entities);
p.setPreferredSize(new Dimension(w, (2 * h)));

JFrame f = new JFrame();

f.setContentPane(p);
f.pack();
f.setLocationRelativeTo(null);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);

new Animator((1000 / 60), p, entities).start();
}

static class Animator implements ActionListener {
int period;
JPanel context;
int height;
List<Entity> entities;

Animator(int period, JPanel context, List<Entity> entities) {
this.context = context;
this.height = context.getHeight();
this.period = period;
this.entities = entities;
}

@Override
public void actionPerformed(ActionEvent a) {
for (Entity e : entities) {
double dist =
(period / 1000.0) * (height * e.rate);

e.y += dist;
e.y %= height;
}

context.repaint();
}

void start() {
Random r = new Random();
int x = 0;
for (Entity e : entities) {
e.x = x;
e.y = r.nextInt(height);
e.rate = (0.25 + (0.75 * r.nextDouble()));

x += e.width;
}

new Timer(period, this).start();
}
}

static class Entity {
BufferedImage img;

double x, y, rate;
int width, height;

Entity(BufferedImage img) {
this.img = img;
this.width = img.getWidth();
this.height = img.getHeight();
}

void paint(Graphics g, JPanel context) {
int x = (int) Math.round(this.x);
int y = (int) Math.round(this.y);
g.drawImage(img, x, y, null);

int cHeight = context.getHeight();
if ((y + height) > cHeight) {
g.drawImage(img, x, y - cHeight, null);
}
}
}

static class PaintPanel extends JPanel {
List<Entity> entities;

PaintPanel(List<Entity> entities) {
this.entities = entities;

setBackground(Color.white);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

for (Entity e : entities) {
e.paint(g, this);
}
}
}

static class Resources {
static final String[] paths = {
"http://i.stack.imgur.com/wCF8S.png",
"http://i.stack.imgur.com/5v2TX.png",
"http://i.stack.imgur.com/F0JHK.png",
"http://i.stack.imgur.com/4EVv1.png",
"http://i.stack.imgur.com/xj49g.png",
};

static final List<BufferedImage> images =
new ArrayList<BufferedImage>();
static {
for (String path : paths) {
try {
images.add(ImageIO.read(new URL(path)));
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
}
}

(图片来自 here .)

其他有用的动画和绘画示例:

关于java - Component.setBounds 调用 Component.repaint?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30175533/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com