简体   繁体   中英

Random is shared between all instances of an object

I want to create a bunch of dots and move each of them in a random direction. Problem is that all dots are heading the same direction, so they look like a single dot even if there are a hundred of them. I tried to google it but found nothing. I bet it's just my stupidity, but I really don't know what to do with it. Thanks for helping me.

Dot class:

public class Dot extends JPanel {
    
    private PVector pos;
    private PVector vel;
    private PVector acc;
    
    private Brain brain;
    
    private boolean dead = false;
    
    public Dot(){
        this.brain = new Brain(400);
        
        this.pos = new PVector(Main.width/2, Main.height/2);
        this.vel = new PVector(0, 0);
        this.acc = new PVector(0, 0);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillOval((int)pos.x, (int)pos.y, 4, 4);
    }
    
    public void show(JFrame frame) {
        frame.add(this);
    }
    
    public void move() {
        if(brain.directions.length > brain.step) {
            acc = brain.directions[brain.step];
            brain.step++;
        } else {
            dead = true;
        }
        
        vel.add(acc);
        vel.limit(5);
        pos.add(vel);
    }
    
    public void update() {
        if(!dead) {
            move();
            
            if(pos.y < 2 || pos.y < 2 || pos.x > Main.width - 2 || pos.y > Main.height - 2) {
                dead = true;
            }
        }
    }
}

Brain class:

public class Brain {

    public PVector[] directions;
    public int step = 0;
    
    public Brain(int size) {
        directions = new PVector[size];
        randomize();
    }
    
    private void randomize() {
        for(int i = 0; i < directions.length; i++) {
            Random random = new Random();
            float randomAngle = (float)(random.nextFloat() * 2 * Math.PI);
            directions[i] = PVector.fromAngle(randomAngle);
        }
    }
}

Population class:

public class Population {

    public Dot[] dots;
    
    public Population(int size) {
        dots = new Dot[size];
        
        for(int i = 0; i < size; i++) {
            dots[i] = new Dot();
        }
    }
    
    public void show(JFrame frame) {
        for(int i = 0; i < dots.length; i++) {
            dots[i].show(frame);
        }
    }
    
    public void update() {
        for(int i = 0; i < dots.length; i++) {
            dots[i].update();
        }
    }
}

Gui class:

public class Gui {

    JFrame frame = new JFrame();
    
    Population test = new Population(100);
    
    public Gui() {
        startup();
    }
    
    private void startup() {
        frame.setSize(Main.width, Main.height);
        frame.setLocation(200, 200);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        
        ScheduledExecutorService executor = Executors
                .newSingleThreadScheduledExecutor();
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                update();
            }
        }, 0, 1000 / 60, TimeUnit.MILLISECONDS);
        
        test.show(frame);
    }
    
    private void update() {
        frame.repaint();
        
        test.update();
    }
}

Each "Dot" instance is a separate panel. You have a 100 Dots, so you have 100 panels. But: the layout manager set on JFrame only shows one of the Dots (probably the last Dot).

There may be a way to make this work so that the 100 panels are all painted on top of each other, by playing around with layout managers, but the "proper" (in my opinion) way to fix this is to make Population extend JPanel, not Dot. That way, Population is a single component that displays the entire population.

These are the changes you need to make:

// add "extends JPanel"
public class Population extends JPanel {
    // Change "show" into "paintComponent"
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for(int i = 0; i < dots.length; i++) {
            dots[i].show(g);
        }
    }
}

// Remove "extends JPanel"
public class Dot {
    // Change "paintComponent" into "show"
    public void show(Graphics g) {
        g.fillOval((int)pos.x, (int)pos.y, 4, 4);
    }
}

public class Gui {
    private void startup() {
        // remove this:
        // test.show(frame);

        // add this:
        frame.add(test);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM