Multithread applet Java balles rebondissantes
Je suis en train de créer une applet Java qui rebondit plusieurs balles dans une applet fenêtre, chacun avec son propre thread. Avec le code ci-dessous toutes les boules sont tirées, mais seule la première personne se déplace. Ce que je fais mal?
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static java.awt.Color.*;
public class BouncingBalls extends Applet implements Runnable {
List<Ball> ballList = new ArrayList(); //holds Ball objects
Color[] colors = new Color[]{BLACK, GRAY, WHITE, PINK, RED, ORANGE, YELLOW,
GREEN, BLUE, CYAN}; //array holding available colors
static int width, height; //variables for applet dimensions
int ballCount; //number of balls to be created, set by html parameter
Random random = new Random(); //random number generator
public void init() {
//get window dimensions
width = getSize().width;
height = getSize().height;
//get number of balls from html
String ballCountString = this.getParameter("ballCount");
try {
ballCount = Integer.parseInt(ballCountString);
} catch (NumberFormatException e) {
ballCount = 10; //set to 10 by default
}
for (int i = 0; i < ballCount; i++) {
//randomly assign ballDiameter between 1 and 20
int ballDiameter = random.nextInt(20) + 1;
//create and add balls to ballList
ballList.add(new Ball(
random.nextInt(width - ballDiameter), //set x coordinate
random.nextInt(height - ballDiameter), //set y coordinate
ballDiameter, //set ballDiameter
random.nextInt(ballDiameter) + 1, //deltaX <= ballDiameter
random.nextInt(ballDiameter) + 1, //deltaY <= ballDiameter
colors[i % 10] //use remainder to choose colors[] element
)
);
} //end for
} //end init
public void start() {
for (Ball ball: ballList) {
Thread t;
t = new Thread(this);
t.start();
} //end for
} //end start
public void run() {
for (Ball ball : ballList) {
//infinite loop: ball moves until applet is closed
while (true) {
ball.move();
repaint(); //call paint method to draw circle in new location
//set ball repaint delay using Thread sleep method
try {
Thread.sleep(20); //wait 20 msec before continuing
} catch (InterruptedException e) {
return;
}
} //end while
} //end for
} //end run
public void paint(Graphics g) {
super.paint(g);
for (Ball ball : ballList) {
//set current color
g.setColor(ball.ballColor);
//draw filled oval using current x and y coordinates and diameter
g.fillOval(ball.x, ball.y, ball.diameter, ball.diameter);
} //end for
} //end paint
}
class Ball {
int x, y, //coordinates of upper-left corner of circle
diameter, //circle diameter
deltaX, deltaY; //number of pixels ball moves each time it's repainted
Color ballColor;
public Ball(int x, int y, int diameter, int deltaX, int deltaY,
Color ballColor) {
this.x = x;
this.y = y;
this.diameter = diameter;
this.deltaX = deltaX;
this.deltaY = deltaY;
this.ballColor = ballColor;
} //end Ball constructor
public void move() {
//update x and y coordinates using delta values
x += deltaX;
y += deltaY;
//reverse x direction when ball reaches boundary
if (x >= BouncingBalls.width - diameter || x <= 0){
deltaX = -deltaX;
} //end if
//reverse y direction when ball reaches boundary
if (y >= BouncingBalls.height - diameter || y <= 0) {
deltaY = -deltaY;
} //end if
} //end move
} //end BouncingBalls
Vous devez vous connecter pour publier un commentaire.
Votre
while(true)
devrait être en dehors de la boucle for. Elle s'assoit sur la première balle renvoyée à partir de l'itérateur.Cela étant dit, vous pouvez aller sur votre logique pour un ballon-par-fil. Il apparaît en effet de créer des N nombre de threads (N étant le nombre de boules) dans laquelle chaque fil se déplacer toutes les balles au lieu d'une seule.
Modifier à l'adresse de mon deuxième point:
Disons que vous avez 10 balles. Vous commencez à 10 threads, et chaque thread itère sur tous les ballons.
Par exemple:
C'est fait parce que vous créer des threads avec la même
this
instance d'un exécutable qui itère sur chaque ballon.Donc, je pense que, si chaque ballon est censé pour un déplacement de 1 unité toutes les 20 millisecondes. Vous devriez voir de toutes les 20 millisecondes déplacer N*1 unités dans ce cas, 10 toutes les 20 millisecondes.
Edit - en ce qui concerne une suggestion.
Au lieu de
this
que l'exécutable, vous devez supprimer la mise en œuvre de l'Exécutable duthis
classe et de créer un nouvel Exécutable qui va prendre une seule Balle comme un paramètre.Plus tard dans votre méthode de démarrage
Donc, ici, chaque Balle a son propre thread avec son propre Exécutable. Chaque balle va maintenant seulement d'invoquer
move
une fois par thread toutes les 20 millisecondes.Mais il n'est toujours pas parfait parce que
repaint
ne devrait être invoquée par le thread d'INTERFACE utilisateur, de l'avoir invoqué par chaque thread peut causer différents problèmes (même si vous ne remarquez pas, c'est juste important de dire).