我正在创建一个游戏,其中一个穴居人在扔石头,当您单击时,就会生成一块石头。前五个左右工作正常,然后等待直到岩石脱离屏幕,然后它们才能再次产生。我希望它们在我单击时产生。
提前致谢
码:
ojit_pre
下课:
package com.russell.raphael.birds;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class Start extends JFrame {
ImageIcon landImage, manImage, skyImage, RockPileImage, RockImage;
JLabel skylbl, manlbl, landlbl, rockPilelbl;
Bird[] birds = new Bird[10];
Rock[] rocks = new Rock[10000];
public static MouseListener throwrock;
public static void main(String[] args){
new Start();
}
public Start() {
setVisible(true);
initComp();
setSize(1000, 1100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setTitle("Not the Birds!!!");
setIconImage(Toolkit.getDefaultToolkit().getImage(Start.class.getResource("/com/russell/raphael/images/Icon.png")));
}
private void initComp() {
throwrock = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int eventX = 0, eventY = 0, sourceX = 420, sourceY = 840;
int rise = 0, run = 0;
try {
JLabel source = (JLabel) e.getSource();
eventX = (source.getLocation().x) + (e.getX());
eventY = (source.getLocation().y) + (e.getY());
rise = Math.abs(eventY - sourceY);
run = eventX - sourceX;
nextRock().start(rise, run);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
setResizable(false);
for(int counter =0; counter < rocks.length; counter++){
rocks[counter] = new Rock();
getContentPane().add(rocks[counter]);
}
landImage = new ImageIcon(
Start.class.getResource("/com/russell/raphael/images/land.png"));
manImage = new ImageIcon(
Start.class.getResource("/com/russell/raphael/images/man.png"));
skyImage = new ImageIcon(
Start.class.getResource("/com/russell/raphael/images/sky.jpg"));
RockPileImage = new ImageIcon(
Start.class
.getResource("/com/russell/raphael/images/rockpile.png"));
getContentPane().setLayout(null);
skylbl = new JLabel(skyImage);
skylbl.addMouseListener(throwrock);
skylbl.setLocation(0, 0);
skylbl.setSize(1010, 983);
skylbl.setVisible(true);
manlbl = new JLabel(manImage);
manlbl.setSize(200, 300);
manlbl.addMouseListener(throwrock);
manlbl.setLocation(400, 700);
landlbl = new JLabel(landImage);
landlbl.setBounds(0, 725, 1000, 400);
manlbl.addMouseListener(throwrock);
rockPilelbl = new JLabel();
rockPilelbl.setIcon(RockPileImage);
rockPilelbl.setBounds(236, 782, 220, 174);
getContentPane().add(rockPilelbl);
manlbl.addMouseListener(throwrock);
getContentPane().add(manlbl);
getContentPane().add(landlbl);
getContentPane().add(skylbl);
}
public Rock nextRock(){
for(int counter = 0; counter < rocks.length; counter++){
if(!rocks[counter].hasBeenUsed){
return rocks[counter];
}
}
return null;
}
}
最佳答案
我没有将岩石池清空然后等待它们消失的问题,但是我还有很多其他问题...
让我们从...开始
nextRock().start(rise, run);
这可能会返回
null
对象,这将导致NullPointerException
如前所述,您无需混合使用
Thread
和Timer
,这是我的简单做法。public class Rock extends JLabel {
Timer timer;
private volatile boolean hasBeenUsed = false;
public Rock() {
super();
setIcon(new ImageIcon(Rock.class.getResource("/Rock.png")));
setBounds(415, 840, getPreferredSize().width, getPreferredSize().height);
setVisible(false);
}
public void start(final int rise, final int run) {
hasBeenUsed = true;
setVisible(true);
timer = new Timer(30, new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
setBounds(getBounds().x + run / 20, getBounds().y
+ -rise / 20, getBounds().width,
getBounds().height);
if (getBounds().x < 0 || getBounds().y < 0
|| getBounds().y > 1000) {
timer.stop();
hasBeenUsed = false;
setBounds(415, 840, getPreferredSize().width, getPreferredSize().height);
}
}
});
timer.start();
}
}
您的岩石池包含10,000个岩石!我认为您单击得不够快,无法耗尽这堆内容。
尝试将其减少到2或3左右进行测试...
边注
这是一个非常昂贵的电话...
public Rock nextRock() {
for (int counter = 0; counter < rocks.length; counter++) {
if (!rocks[counter].hasBeenUsed) {
return rocks[counter];
}
}
return null;
}
如果您有9 999个岩石,那么到达最后一个岩石将花费大量时间,因为您必须遍历当前不可用的所有岩石。
将所有岩石添加到
java.util.List
(将其称为rockPile)可能会更容易。扔石头时,您可以检查此列表以查看是否有可用的岩石,如果没有,请返回,否则,从列表中删除第一个岩石并放入“飞行中”列表。这样可以更快地检查岩石堆(使用List#isEmpty
和List#get(0)
之类的速度更快)。当岩石再次变为“可用”时,您可以将其从“飞行中”列表中删除,然后放回
rockPile
列表中。这也意味着您可能会下降到一个负责遍历
Timer
列表并在那里更新位置的inFlight
。使用列表更新
基本上,您需要某种“经理”来维护所有必需的信息,并可以在感兴趣的各方之间共享...
public class RockManager {
private List<Rock> rockPile;
private List<Rock> inFlight;
public static final int MAX_ROCKS = 2;
public RockManager() {
rockPile = new ArrayList<Rock>(MAX_ROCKS);
inFlight = new ArrayList<Rock>(MAX_ROCKS);
for (int index = 0; index < MAX_ROCKS; index++) {
rockPile.add(new Rock(this));
}
}
public Rock[] getRocksOnPile() {
return rockPile.toArray(new Rock[rockPile.size()]);
}
public Rock[] getRocksInFlight() {
return inFlight.toArray(new Rock[inFlight.size()]);
}
public Rock pickRockOfPile() {
Rock rock = null;
if (!rockPile.isEmpty()) {
rock = rockPile.remove(0);
inFlight.add(rock);
}
return rock;
}
public void putRockBackOnPile(Rock rock) {
if (inFlight.contains(rock)) {
inFlight.remove(rock);
rockPile.add(rock);
}
}
}
注意:从技术上讲,您可能不需要“
inFlight
”,但是我正在使用它作为陷阱,以确保不会将岩石添加到不在飞行中的堆中;)。您还可以对Set
使用rockPile
,因为这将确保列表中仅包含唯一引用。接下来,我在
RockManager
类中添加了Start
的实例字段。在
initComp
类的Start
方法中,您需要更改构造岩石的方式...所以,代替
for(int counter =0; counter < rocks.length; counter++){
rocks[counter] = new Rock();
getContentPane().add(rocks[counter]);
}
您现在将拥有...
rockManager = new RockManager();
for (Rock rock : rockManager.getRocksOnPile()) {
getContentPane().add(rock);
}
您的
nextRock
方法将变成...public Rock nextRock() {
return rockManager.pickRockOfPile();
}
最后,您的
Rock
类将需要对RockManager
的引用,基本上,我通过构造函数传递了一个引用...private RockManager manager;
public Rock(RockManager manager) {
super();
this.manager = manager;
然后,当岩石离开运动场时,您可以通过
RockManager
将其添加回桩中。manager.putRockBackOnPile(Rock.this);
关于java - 动画岩石无法正确生成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13215669/