我怎样才能让我的每个物体在碰撞时彼此“反弹”?

问题描述 投票:0回答:1

这是我的程序,它有一个运行模拟的 run 方法。

import java.util.*;
public class Game{
    public static int size;
    public int numObjects;
    public static int speedX;
    public static int speedY;
    ArrayList<Rock> rockArrayList = new ArrayList<>();
    ArrayList<Paper> paperArrayList = new ArrayList<>();
    ArrayList<Scissors> scissorsArrayList = new ArrayList<>();
    public Game(int size, int numObjects, int speedX, int speedY){
        Game.size = size;
        Game.speedX = speedX;
        Game.speedY = speedY;
        this.numObjects = numObjects;
        StdDraw.setCanvasSize(size, size); //set up drawing canvas
        StdDraw.setXscale(0, size);        //<0, 0> is bottom left.  <size-1, size-1> is top right
        StdDraw.setYscale(0, size);

        Random random = new Random();

        for(int i = 0; i<numObjects; i++) {
            int neg = random.nextInt(2);
            speedX *= ((neg == 0) ? 1:-1);
            int x = random.nextInt(size);

            neg = random.nextInt(2);
            speedY*=((neg == 0) ? 1:-1);
            int y = random.nextInt(size);

            rockArrayList.add(new Rock(x,y,speedX, speedY));
        }

        for(int i = 0; i<numObjects; i++) {
            int neg = random.nextInt(2);
            speedX *= ((neg == 0) ? 1:-1);
            int x = random.nextInt(size);

            neg = random.nextInt(2);
            speedY*=((neg == 0) ? 1:-1);
            int y = random.nextInt(size);
            paperArrayList.add(new Paper(x,y,speedX,speedY));
        }

        for(int i = 0; i<numObjects; i++) {
            int neg = random.nextInt(2);
            speedX *= ((neg == 0) ? 1:-1);
            int x = random.nextInt(size);

            neg = random.nextInt(2);
            speedY*=((neg == 0) ? 1:-1);
            int y = random.nextInt(size);
            scissorsArrayList.add(new Scissors(x,y,speedX,speedY));
        }
    }

    public void run() {
        while (true){
            StdDraw.clear(StdDraw.BLACK);

            StdDraw.enableDoubleBuffering();

            for(Rock r : rockArrayList) {
                r.update();
            }

            for(Paper p : paperArrayList) {
                p.update();
            }

            for(Scissors s : scissorsArrayList) {
                s.update();
            }

            for(int i = 0; i < paperArrayList.size(); i++) {
                for(int j = 0; j < rockArrayList.size(); j++) {
                    if(paperArrayList.get(i).doesCollideWith(rockArrayList.get(j))) {
                        paperArrayList.add(new Paper(rockArrayList.get(j).getX(), rockArrayList.get(j).getY(),speedX,speedY));
                        paperArrayList.get(paperArrayList.size()-1).changeSpeedX(-1);
                        rockArrayList.remove(j);
                    }
                }
            }

            for(int i = 0; i < rockArrayList.size(); i++) {
                for(int j = 0; j < scissorsArrayList.size(); j++) {
                    if(rockArrayList.get(i).doesCollideWith(scissorsArrayList.get(j))) {
                        rockArrayList.add(new Rock(scissorsArrayList.get(j).getX(), scissorsArrayList.get(j).getY(),speedX,speedY));
                        rockArrayList.get(rockArrayList.size()-1).changeSpeedY(-1);
                        scissorsArrayList.remove(j);
                    }
                }
            }

            for(int i = 0; i < scissorsArrayList.size(); i++) {
                for(int j = 0; j < paperArrayList.size(); j++) {
                    if(scissorsArrayList.get(i).doesCollideWith(paperArrayList.get(j))) {
                        scissorsArrayList.add(new Scissors(paperArrayList.get(j).getX(), paperArrayList.get(j).getY(),speedX,speedY));
                        scissorsArrayList.get(scissorsArrayList.size()-1).changeSpeedY(-1);
                        paperArrayList.remove(j);
                    }
                }
            }

            if((rockArrayList.isEmpty() && paperArrayList.isEmpty()) || (rockArrayList.isEmpty() && scissorsArrayList.isEmpty()) || (paperArrayList.isEmpty() && scissorsArrayList.isEmpty()) )
                break;

            for(Rock r : rockArrayList)
                r.draw();

            for(Paper p : paperArrayList)
                p.draw();

            for(Scissors s : scissorsArrayList)
                s.draw();

            StdDraw.show();
            StdDraw.pause(20);
        }
    }
}

这里,石头、布和剪刀都是被模拟在弹跳中生成的物体(我可能应该创建一个超类),直到其中一个“获胜”。这是它们的构造函数(除了名称之外它们都是相同的):

public Rock(int x, int y, int speedX, int speedY){
    this.x = x;
    this.y = y;
    this.speedX = speedX;
    this.speedY = speedY;
}

每个对象都有一个更新方法,可以帮助对象保留在屏幕上:

public void update(){
    x += speedX;
    y += speedY;
    if(x+speedX >= Game.size || x+speedX<=0)
        speedX *= -1;
    if(y+speedY >= Game.size || y+speedY<=0)
        speedY*=-1;
}

最后我有一个名为 Collideable 的接口,它检查一个对象是否与另一个对象发生碰撞(此方法的实现在所有 3 个类中都是相同的)

@Override
public boolean doesCollideWith(Collideable collideable){
    if(Math.abs(collideable.getX()-this.x)<10){
        return Math.abs(collideable.getY() - this.y) < 10;
    }
    return false;
}

正如你在我的 run 方法中看到的,我想要一种方法来使每个对象相互反弹,而不会使该程序的时间复杂度超过 O(n^2)。本质上,我想停止使用如此多的循环来检查可以以更简洁的方式完成的事情。对于所有图形内容,我使用 Princeton 的 StdDraw 类。

我尝试使用三重嵌套的 for 循环来检查,但它看起来一团糟,我羞于分享它,因为代码质量很差。我不是 100% 确定,但我认为使用不同的数据结构而不是 Arraylist 可能更容易,但我目前不知道任何此类其他数据结构。

以下是该计划中的所有课程:

public class Main {
   public static void main(String[] args) {
       Game game = new Game(900,100, 3,3);
       game.run();
   }
}
import java.util.*;

public class Game{
    public static int size;
    public int numObjects;
    public static int speedX;
    public static int speedY;
    ArrayList<Rock> rockArrayList = new ArrayList<>();
    ArrayList<Paper> paperArrayList = new ArrayList<>();
    ArrayList<Scissors> scissorsArrayList = new ArrayList<>();
    public Game(int size, int numObjects, int speedX, int speedY){
        Game.size = size;
        Game.speedX = speedX;
        Game.speedY = speedY;
        this.numObjects = numObjects;
        StdDraw.setCanvasSize(size, size); //set up drawing canvas
        StdDraw.setXscale(0, size);        //<0, 0> is bottom left.  <size-1, size-1> is top right
        StdDraw.setYscale(0, size);

        Random random = new Random();

        for(int i = 0; i<numObjects; i++) {
            int neg = random.nextInt(2);
            speedX *= ((neg == 0) ? 1:-1);
            int x = random.nextInt(size);

            neg = random.nextInt(2);
            speedY*=((neg == 0) ? 1:-1);
            int y = random.nextInt(size);

            rockArrayList.add(new Rock(x,y,speedX, speedY));
        }

        for(int i = 0; i<numObjects; i++) {
            int neg = random.nextInt(2);
            speedX *= ((neg == 0) ? 1:-1);
            int x = random.nextInt(size);

            neg = random.nextInt(2);
            speedY*=((neg == 0) ? 1:-1);
            int y = random.nextInt(size);
            paperArrayList.add(new Paper(x,y,speedX,speedY));
        }

        for(int i = 0; i<numObjects; i++) {
            int neg = random.nextInt(2);
            speedX *= ((neg == 0) ? 1:-1);
            int x = random.nextInt(size);

            neg = random.nextInt(2);
            speedY*=((neg == 0) ? 1:-1);
            int y = random.nextInt(size);
            scissorsArrayList.add(new Scissors(x,y,speedX,speedY));
        }
    }

    public void run() {
        while (true){
            StdDraw.clear(StdDraw.BLACK);

            StdDraw.enableDoubleBuffering();

            for(Rock r : rockArrayList) {
                r.update();
            }

            for(Paper p : paperArrayList) {
                p.update();
            }

            for(Scissors s : scissorsArrayList) {
                s.update();
            }

            for(int i = 0; i < paperArrayList.size(); i++) {
                for(int j = 0; j < rockArrayList.size(); j++) {
                    if(paperArrayList.get(i).doesCollideWith(rockArrayList.get(j))) {
                        paperArrayList.add(new Paper(rockArrayList.get(j).getX(), rockArrayList.get(j).getY(),speedX,speedY));
                        paperArrayList.get(paperArrayList.size()-1).changeSpeedX(-1);
                        rockArrayList.remove(j);
                    }
                }
            }

            for(int i = 0; i < rockArrayList.size(); i++) {
                for(int j = 0; j < scissorsArrayList.size(); j++) {
                    if(rockArrayList.get(i).doesCollideWith(scissorsArrayList.get(j))) {
                        rockArrayList.add(new Rock(scissorsArrayList.get(j).getX(), scissorsArrayList.get(j).getY(),speedX,speedY));
                        rockArrayList.get(rockArrayList.size()-1).changeSpeedY(-1);
                        scissorsArrayList.remove(j);
                    }
                }
            }

            for(int i = 0; i < scissorsArrayList.size(); i++) {
                for(int j = 0; j < paperArrayList.size(); j++) {
                    if(scissorsArrayList.get(i).doesCollideWith(paperArrayList.get(j))) {
                        scissorsArrayList.add(new Scissors(paperArrayList.get(j).getX(), paperArrayList.get(j).getY(),speedX,speedY));
                        scissorsArrayList.get(scissorsArrayList.size()-1).changeSpeedY(-1);
                        paperArrayList.remove(j);
                    }
                }
            }

            if((rockArrayList.isEmpty() && paperArrayList.isEmpty()) || (rockArrayList.isEmpty() && scissorsArrayList.isEmpty()) || (paperArrayList.isEmpty() && scissorsArrayList.isEmpty()) )
                break;

            for(Rock r : rockArrayList)
                r.draw();

            for(Paper p : paperArrayList)
                p.draw();

            for(Scissors s : scissorsArrayList)
                s.draw();

            StdDraw.show();
            StdDraw.pause(20);
        }
    }
}
public class Rock implements Collideable {
    int x;
    int y;
    int speedX;
    int speedY;
    public Rock(int x, int y, int speedX, int speedY){
        this.x = x;
        this.y = y;
        this.speedX = speedX;
        this.speedY = speedY;
    }
    public void draw(){
        StdDraw.picture(x,y,"res/rock.png", 20, 20);
    }

    public void update(){
        x += speedX;
        y += speedY;
        if(x+speedX >= Game.size || x+speedX<=0)
            speedX *= -1;
        if(y+speedY >= Game.size || y+speedY<=0)
            speedY*=-1;
    }

    @Override
    public int getX() {
        return x;
    }

    @Override
    public int getY() {
        return y;
    }

    public void changeSpeedX(int speedX){
        this.speedX *= speedX;
    }

    public void changeSpeedY(int speedY){
        this.speedY *= speedY;
    }

    @Override
    public boolean doesCollideWith(Collideable collideable){
        if(Math.abs(collideable.getX()-this.x)<10){
            return Math.abs(collideable.getY() - this.y) < 10;
        }
        return false;
    }
}
public class Paper implements Collideable {
    int x;
    int y;
    int speedX;
    int speedY;
    public Paper(int x, int y, int speedX, int speedY){
        this.x = x;
        this.y = y;
        this.speedX = speedX;
        this.speedY = speedY;
    }
    public void draw(){
        StdDraw.picture(x,y,"res/paper.png",20,20);
    }

    public void update(){
        x += speedX;
        y += speedY;
        if(x+speedX >= Game.size || x+speedX<=0)
            speedX *= -1;
        if(y+speedY >= Game.size || y+speedY<=0)
            speedY*=-1;
    }

    @Override
    public int getX() {
        return x;
    }

    @Override
    public int getY() {
        return y;
    }
    public void changeSpeedX(int speedX){
        this.speedX *= speedX;
    }

    public void changeSpeedY(int speedY){
        this.speedY *= speedY;
    }
    @Override
    public boolean doesCollideWith(Collideable collideable){
        if(Math.abs(collideable.getX()-this.x)<10){
            return Math.abs(collideable.getY() - this.y) < 10;
        }
        return false;
    }
}
public class Scissors implements Collideable {
    int x;
    int y;
    int speedX;
    int speedY;
    public Scissors(int x, int y, int speedX, int speedY){
        this.x = x;
        this.y = y;
        this.speedX = speedX;
        this.speedY = speedY;
    }
    public void draw(){
        StdDraw.picture(x,y,"res/scissors.png",20,20);
    }

    public void update(){
        x += speedX;
        y += speedY;
        if(x+speedX >= Game.size || x+speedX<=0)
            speedX *= -1;
        if(y+speedY >= Game.size || y+speedY<=0)
            speedY*=-1;
    }

    @Override
    public int getX() {
        return x;
    }

    @Override
    public int getY() {
        return y;
    }
    public void changeSpeedX(int speedX){
        this.speedX *= speedX;
    }

    public void changeSpeedY(int speedY){
        this.speedY *= speedY;
    }
    @Override
    public boolean doesCollideWith(Collideable collideable){
        if(Math.abs(collideable.getX()-this.x)<10){
            return Math.abs(collideable.getY() - this.y) < 10;
        }
        return false;
    }
}
public interface Collideable {
    public boolean doesCollideWith(Collideable collideable);
    public int getX();
    public int getY();
}
java arrays loops stddraw
1个回答
0
投票

因此,#1,在 HashSet 中使用 .contains() 比在 ArrayList 中使用 .contains() 效率更高(O(1) vs O(n))。因此,您应该使用 HashSet(或者可能是 TreeSet,您可以在 oracle 或 smth 上了解有关这些的更多信息)来跟踪它们的位置。

然后,使用pairs(也请阅读这些)来存储数据,并获取一组岩石(假设您当前正在检查剪刀和岩石碰撞)并检查每个剪刀的坐标Pair是否包含在HashSet中。利用这些坐标,您可以更改这些坐标处的每块石头/纸。您可以对其他检查重复此过程。

因为您想要检查对象何时位于坐标的距离内,所以您可能必须将所有坐标除以 10 或您想要的半径,并且您可能希望首先执行此操作您添加到包含石头/布/剪刀的集合中的所有坐标,以避免将来出现烦恼。您可能需要对代码进行大量更改,但这是我认为可行的方式。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.