动画岩石没有正确产卵

时间:2012-11-04 03:01:20

标签: java animation timer

我正在创造一个洞穴探险者投掷石块的游戏,当你点击时,一块岩石会产生。前五个左右工作正常,然后等到岩石离开屏幕然后它们可以再次产卵。我想点击它时会产生它们。

提前致谢

代码:

 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;
    }
}

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; } }

下一堂课:



1 个答案:

答案 0 :(得分:1)

我没有问题让岩石池空了,然后等待它们消失,但我有很多其他问题......

让我们从...开始

nextRock().start(rise, run);

这可能会返回一个null对象,这将导致NullPointerException

正如我之前所说,你不应该混淆ThreadTimer,这是我对摇滚的简单看法..

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)。当抛出岩石时,您可以查看此列表以查看是否有任何可用的岩石,如果没有,则返回,否则,从列表中移除第一块岩石并放入“inFlight”列表中。这样可以更快地检查岩石堆(使用类似List#isEmptyList#get(0)的速度更快)。

当摇滚再次变为“可用”时,您会将其从“inFlight”列表中删除并重新放回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);