Hello Stack Overflow people :)
I'm a huge newbie when it comes to coding, and I've just ran into a problem that my brain just won't get over...
Before I start blabbering about this issue, I'll paste my code so as to give a little bit of context (sorry in advance if looking at it makes you wanna puke). The main focus of the issue is commented and should therefore be fairly visible :
Main
ArrayList<Individual> individuals = new ArrayList<Individual>();
void setup()
{
size(500,500);
for(int i = 0; i < 2; i++)
{
individuals.add(new Individual());
}
println(frameRate);
}
void draw()
{
background(230);
for(int i = 0; i < individuals.size(); i++)
{
individuals.get(i).move();
individuals.get(i).increaseTimers();
individuals.get(i).display();
}
}
Individual
class Individual
{
float x;
float y;
int size = 5;
Timer rdyBreed; /* Here is the object that appears to be shared
between individuals of the ArrayList */
float breedRate;
float breedLimit;
Individual()
{
x = random(0, width);
y = random(0, height);
rdyBreed = new Timer("rdyBreed", 0);
breedRate = random(.2, 3);
breedLimit = random(10, 20);
}
void move()
{
int i = (int)random(0, 1.999);
int j = (int)random(0, 1.999);
if (i == 0)
{
x = x + 1;
} else
{
x = x - 1;
}
if (j == 0)
{
y = y + 1;
} else
{
y = y - 1;
}
checkWalls();
}
void checkWalls()
{
if (x < size/2)
{
x = width - size/2;
}
if (x > width - size/2)
{
x = size/2;
}
if (y < size/2)
{
y = width - size/2;
}
if (y > width - size/2)
{
y = size/2;
}
}
void display()
{
noStroke();
if (!rdyBreed.finished)
{
fill(255, 0, 0);
} else
{
fill(0, 255, 0);
}
rect(x - size/2, y - size/2, size, size);
}
void increaseTimers()
{
updateBreedTimer();
}
void updateBreedTimer()
{
rdyBreed.increase(frameRate/1000);
rdyBreed.checkLimit(breedLimit);
rdyBreed.display(x, y);
}
}
Timer
class Timer
{
float t;
String name;
boolean finished = false;
Timer(String name, float t)
{
this.t = t;
this.name = name;
}
void increase(float step)
{
if (!finished)
{
t = t + step;
}
}
void checkLimit(float limit)
{
if (t >= limit)
{
t = 0;
finished = true;
}
}
void display(float x, float y)
{
textAlign(RIGHT);
textSize(12);
text(nf(t, 2, 1), x - 2, y - 2);
}
}
Now that that's done, let's get to my question.
Basically, I'm trying to create some sort of a personal Conway's Game of Life, and I'm encountering a lot of issues right off the bat.
Now my idea when writing this piece of code was that every individual making up the small simulated "society" would have different timers and values for different life events, like mating to have children for example.
Problem is, I'm not a huge pro at object-oriented programming, and I'm therefore quite clueless as to why the objects are not having each their own Timer but both a reference to the same timer.
I would guess making an ArrayList of timers and using polymorphism to my advantage could make a change, but I'm not really certain of it or really how to do it so... yeah, I need help.
Thanks in advance :)
EDIT : Here is a screenshot of the debugger. The values keep being the same with each iteration of the updates.
Screenshot
What makes you think they reference the same Timer object? The values of t displayed in the debugger are going to be the same until one of them reaches the breedLimit and gets set to 0, because they're being initialized at the same time.
Try this and see that the values of t are different.
void setup() {
size(500,500);
}
void mouseClicked() {
individuals.add(new Individual());
}
I'd recommend setting the breakpoint somewhere around here:
t = 0;
finished = true;
They do not share the same timer, you create a new Timer object for each Individual.
class Individual {
// ...
Timer rdyBreed;
Individual() {
// ...
rdyBreed = new Timer("rdyBreed", 0);
//...
The only way they could be sharing the same Timer is if you were setting rdyBreed elsewhere, but since you don't want that I recommend making it final.
If you did want to share the same Timer instance across all individuals then you could declare it static.
Related
First off apologies for not being able to word my question accurately!
The problem I face is I have an array list with 4 classes that do the exact same thing , only that they need to be called at different times (when the first one's coordinate exceeds a certain value) but Im having trouble getting it done , and Cant find it online (probably because I cant word my questions accurately :/) anyway I will post my code below and if anyone could shed some light I would be extremely grateful!
**What im making is a a tunnel effect by connecting the center of the screen with each corner with lines, and now im attempting to simulate moving by starting lines coming from the middle of the screen towards the edge (starting with bottom portion) **
speedLines sline1, sline2, sline3, sline4;
// holds speedLines classes
ArrayList<speedLines> gameObject;
void setup() {
background(0);
size(750, 750);
smooth();
gameObject = new ArrayList<speedLines>();
sline1 = new speedLines(height/2);
sline2 = new speedLines(height/8);
sline3 = new speedLines(height/4);
sline4 = new speedLines((height/2)*3);
gameObject.add(sline1);
gameObject.add(sline2);
gameObject.add(sline3);
gameObject.add(sline4);
}
void draw() {
background(0);
for(int i=0; i< gameObject.size(); i++){
// go through the different classes
// 2 added so far
gameObject.get(i).display();
}
Guidelines();
}
//GLOBAL VARIABLES
int line=0;
int linewidth=0;
void Guidelines() {
stroke(255);
//MAIN GUIDE
line(0, 0, width/2, height/2);//top left guide
line(width, 0, width/2, height/2);//top right guide
line(0, height, width/2, height/2);//bottom left guide
line(width, height, width/2, height/2);//bottom right guide
//SUB GUIDE
stroke(60, 60, 60);
line(width/3, height, width/2, height/2);//sub guide left
line((width/3)*2, height, width/2, height/2);//sub guide right
}
class speedLines {
//Global variables
int Y;
speedLines(int y) {
}
void display() {
stroke(60, 60, 60);
line((width/2)-linewidth, (height/2)+line, (width/2)+linewidth, (height/2)+line);
line++;
linewidth++;
if ((height/2)+line >= height)
{
line=0;
linewidth=0;
}
}
}
If I were you, I would try to narrow this down to a smaller example sketch. I'd also try to clean up your code a bit: is there a reason you have sketch-level sline variables when you put them in the ArrayList anyway?
That being said, I'll try to help. You're passing a parameter into the speedLines class (which should really be called SpeedLine since classes should start with an upper-case letter and each instance only represents one line) constructor, but you're never using that parameter. Try to get it working with just one instance, like this:
Line myLine;
void setup() {
size(100, 500);
myLine = new Line(height/2);
}
void draw() {
background(200);
myLine.move();
myLine.render();
}
class Line {
float lineY;
public Line(float lineY) {
this.lineY = lineY;
}
public void move() {
lineY++;
if (lineY > height) {
lineY = 0;
}
}
public void render() {
line(0, lineY, width, lineY);
}
}
Notice how I'm actually using the lineY variable that I'm passing into my Line constructor. Try to get something like this working in your code. Then it'll be easier to use an ArrayList to draw multiple lines:
ArrayList<Line> myLines = new ArrayList<Line>();
void setup() {
size(100, 500);
for (float lineY = 0; lineY < height; lineY += 100) {
myLines.add(new Line(lineY));
}
}
void draw() {
background(200);
for (Line myLine : myLines) {
myLine.move();
myLine.render();
}
}
class Line {
float lineY;
public Line(float lineY) {
this.lineY = lineY;
}
public void move() {
lineY++;
if (lineY > height) {
lineY = 0;
}
}
public void render() {
line(0, lineY, width, lineY);
}
}
Also note that you're only ever really using a single value in your class (in my example, the lineY variable). So you probably don't really need a class to do this. You could probably do this with just an array of float values that hold the lineY values instead:
float[] lineY = new float[10];
void setup() {
size(100, 500);
for (int i = 0; i < lineY.length; i++) {
lineY[i] = i * 10;
}
}
void draw() {
background(200);
for (int i = 0; i < lineY.length; i++) {
lineY[i]++;
if (lineY[i] > height) {
lineY[i] = 0;
}
line(0, lineY[i], width, lineY[i]);
}
}
Please note that all of these are just examples, and you'll have to take these examples and understand what they're doing, then do similar things in your code. Good luck.
Need some help modifying this code. I was working through some tutorials on particle systems, and I'm currently trying to write seom logic that says:
"If this particle system has been running for 10 seconds, stop adding particles to it. When the last of the particles are dead, and the system is empty,remove it from the systems ArrayList."
What is going on now:
- The timer counts down and particles stop being added to the particle system except it is acting like a timer for every particle system in the array list.
- the timer does not reset when you add a new particle system
What I need help with:
- Where to reset the timer, or re-initialize the timer when you make a new system.
- only having the timer affect the system its in (rather than all of them on screen)
// particle system
class ParticleSystem {
ArrayList<Particle> plist;
PVector origin; // An origin point for where particles are birthed
float c;
int t;
int countdown; // 10 seconds.
boolean end;
ParticleSystem(float col, int num, PVector v){
plist = new ArrayList<Particle>();
origin = v.get();
c = col;
end = false;
countdown = 10;
t = 10;
for(int i = 0; i < num; i++){
plist.add(new Particle(c,origin));
}
}
void applyForce(PVector force){
for (Particle p : plist){
p.applyForce(force);
}
}
void run(){
// iterate through array of single particles backwards
// remove single particles when they are dead.
t = countdown-int(millis()/1000);
print(t);
for (int i = plist.size()-1; i > 0; i--){
Particle p = plist.get(i);
p.run();
if (p.isDead()){
plist.remove(i);
}
}
if(t > 0){
addParticle();
} else {
dead();
}
//print(plist.size());
}
void addParticle(){
//println("AP: "+r);
float r = random(1);
if (r<0.4) {
plist.add(new SquareParticle(c,origin));
}else{
plist.add(new Particle(c,origin));
}
}
boolean dead(){
if(plist.isEmpty() || plist.size() == 1){
t = 10;
return true;
}else{
return false;
}
}
}
// main tab
ArrayList<ParticleSystem> systems;
PVector windRight = new PVector(0.1,0);
PVector sortaSpeed = new PVector(0,0.1);
PVector gravity = new PVector(0,0.05);
boolean wR = false;
boolean sP = false;
void setup() {
size(640,480);
systems = new ArrayList<ParticleSystem>();
noStroke();
}
void draw() {
background(0);
if(!systems.isEmpty()){
for (int i =0; i < systems.size(); i++){
ParticleSystem ps = systems.get(i);
ps.applyForce(gravity);
ps.run();
if(wR){
ps.applyForce(windRight);
}
if(sP){
ps.applyForce(sortaSpeed);
}
if(ps.dead()){
systems.remove(ps);
}
//print(systems.size());
}
} else {
fill(255);
text("'w' controls wind, 'a' controls speed, 's' adds particle systems",1,height-30);
}
}
void keyPressed() {
if(key == 'w'){
wR = true;
} else if(key == 'a'){
//print('a');
sP = true;
}else{
systems.add(new ParticleSystem(random(100,200),10,new PVector(random(10,630),10))); //random(480)
}
}
void keyReleased(){
if(key == 'w'){
wR = false;
} else if(key == 'a'){
sP = false;
}
}
In the future, please try to post an MCVE. Right now we can't run your code because it contains compiler errors. We don't need to see your entire sketch anyway though, just a small example that gets the point across.
But looking at your code, there is a problem here:
for (int i =0; i < systems.size(); i++){
...
if(ps.dead()){
systems.remove(ps);
}
Run through an example using a piece of paper and a pencil. Let's say you have 3 ParticleSystem instances in your systems list, and the loop is on the second one. You then remove the second one, moving the third one into the second index. The next iteration of the loop moves to the third index... but now there's nothing there!
To get around this problem, you could iterate through the ArrayList backwards, or better yet, you could use an Iterator.
From there it's just a matter of keeping track of each instance's startTime and comparing that to millis(), which you aren't doing right now.
Here's an MCVE that demonstrates using millis() and an Iterator to kill off Particle instances after 10 seconds:
import java.util.Iterator;
ArrayList<Particle> particles = new ArrayList<Particle>();
void setup() {
size(500, 500);
}
void draw() {
background(0);
Iterator<Particle> particleIterator = particles.iterator();
while (particleIterator.hasNext()) {
Particle p = particleIterator.next();
p.draw();
if (p.isDead()) {
particleIterator.remove();
}
}
}
void mousePressed() {
particles.add(new Particle(mouseX, mouseY));
}
class Particle {
int startTime;
float x;
float y;
public Particle(float x, float y) {
startTime = millis();
this.x = x;
this.y = y;
}
void draw() {
x += random(-2, 2);
y += random(-2, 2);
ellipse(x, y, 10, 10);
}
boolean isDead() {
return millis() > startTime + 10*1000;
}
}
Note that you'll have to use this logic twice: once for your individual particles, and again for the particle systems themselves. But the logic is the same: record a start time, then compare that to millis(), and use an Iterator to remove stuff when it has timed out.
Also note that Iterator is specific to Java mode. If you want to deploy as JavaScript, you might want to go with the backwards loop approach instead.
I'm working on trying to use this free source code I found (http://solemone.de/demos/snow-effect-processing/) into a class that I can utilize within a larger, more complex "game" code. It's a pretty basic snow fall code:
int quantity = 15;
float [] xPosition = new float[quantity];
float [] yPosition = new float[quantity];
int [] flakeSize = new int[quantity];
int [] direction = new int[quantity];
int minFlakeSize = 10;
int maxFlakeSize = 20;
void setup() {
size(800, 350);
frameRate(30);
noStroke();
smooth();
for(int i = 0; i < quantity; i++) {
flakeSize[i] = round(random(minFlakeSize, maxFlakeSize));
xPosition[i] = random(0, width);
yPosition[i] = random(0, height);
direction[i] = round(random(0, 1));
}
}
void draw() {
background(0);
for(int i = 0; i < xPosition.length; i++) {
ellipse(xPosition[i], yPosition[i], flakeSize[i], flakeSize[i]);
if(direction[i] == 0) {
xPosition[i] += map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
} else {
xPosition[i] -= map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
}
yPosition[i] += flakeSize[i] + direction[i];
if(xPosition[i] > width + flakeSize[i] || xPosition[i] < -flakeSize[i] || yPosition[i] > height + flakeSize[i]) {
xPosition[i] = random(0, width);
yPosition[i] = -flakeSize[i];
}
}
}
I just haven't quite grasped on how to separate the for() loops, integers, and arrays into functions I can put into a separate class that I've titled Snow so that I can easily move it and manipulate it within the greater code. Here's one of my (many) attempts so far:
Class Tab:
class Snow{
int quantity = 15;
float [] xPosition = new float[quantity];
float [] yPosition = new float[quantity];
int [] flakeSize = new int[quantity];
int [] direction = new int[quantity];
int minFlakeSize = 10;
int maxFlakeSize = 20;
Snow(){
frameRate(30);
noStroke();
smooth();
}
void display() {
flakeSize = round(random(minFlakeSize, maxFlakeSize));
xPosition = random(0, width);
yPosition = random(0, height);
direction = round(random(0, 1));
}
void update() {
for(int i = 0; i < xPosition.length; i++) {
ellipse(xPosition[i], yPosition[i], flakeSize[i], flakeSize[i]);
if(direction[i] == 0) {
xPosition[i] += map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
} else {
xPosition[i] -= map(flakeSize[i], minFlakeSize, maxFlakeSize, .1, .5);
}
yPosition[i] += flakeSize[i] + direction[i];
if(xPosition[i] > width + flakeSize[i] || xPosition[i] < -flakeSize[i] || yPosition[i] > height + flakeSize[i]) {
xPosition[i] = random(0, width);
yPosition[i] = -flakeSize[i];
}
}
}
}
Main Tab:
//Ice
Snow [] flakes = new Snow[15];
int quantity = 15;
void setup(){
size(600,800);
flakes = new Snow[15];
}
void draw(){
background(0);
for(int i = 0; i < quantity; i++){
flakes[i].display();
flakes[i].update();
}
}
I'm sure it's a really simple method of breaking down the code and separating them into the proper places, but I can't seem to grasp it.
If anyone could help me with this process, I would really appreciate it.
This code doesn't make sense, because the Snow class seems to be keeping track of every snowflake, but you then have multiple instances of Snow.
Instead of trying to copy-paste random code into your sketch, you'll have much better luck if you take a step back, start a little smaller, try to understand what the code does, and then write your own code.
Step 1: Can you create a class that encapsulates the data and behavior for a single snowflake?
Don't worry about multiple snowflakes yet. Just get something very basic working. Here's a simple example class:
class SnowFlake{
float x = random(width);
float y = random(height);
float r = random(10);
void draw(){
ellipse(x, y, r, r);
y++;
if(y > height){
y = 0;
x = random(width);
}
}
}
Step 2: Can you use that class in a single variable to draw a single snowflake?
You might create a little example sketch like this:
SnowFlake snowFlake;
void setup(){
size(500, 500);
snowFlake = new SnowFlake();
}
void draw(){
background(0);
snowFlake.draw();
}
Get this single snowflake working perfectly before moving on.
Step 3: Now that you have the single snowflake working, can you use an array or ArrayList to create multiple snowflakes?
If you work in small steps, it will be easy to add one thing at a time:
ArrayList<SnowFlake> snowFlakes = new ArrayList<SnowFlake>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
snowFlakes.add(new SnowFlake());
}
}
void draw() {
background(0);
for (SnowFlake snowFlake : snowFlakes) {
snowFlake.draw();
}
}
You can't program by trying to blindly copy-paste code into your sketch. You have to really understand what it's doing, and you're usually better off just writing your own code based on that understanding. Good luck!
I'm working on a program that displays circles colliding with the wall and with themselves.
I'm having trouble with the method that will compensate for collisions.
public class bouncyFX extends Application {
public ArrayList<Ball> arr = new ArrayList<Ball>();
public static void main(String[] args) {
launch(args);
}
static Pane pane;
#Override
public void start(final Stage primaryStage) {
pane = new Pane();
final Scene scene = new Scene(pane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
pane.setOnMouseClicked(new EventHandler<MouseEvent>() {
public void handle(final MouseEvent event) {
final Ball ball = new Ball(event.getX(), event.getY(), 40, Color.AQUA);
ball.circle.relocate(event.getX(), event.getY());
pane.getChildren().addAll(ball.circle);
arr.add(ball);
final Bounds bounds = pane.getBoundsInLocal();
final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {
double deltaX = ball.ballDeltaX;
double deltaY = ball.ballDeltaY;
public void handle(final ActionEvent event) {
ball.circle.setLayoutX(ball.circle.getLayoutX() + deltaX);
ball.circle.setLayoutY(ball.circle.getLayoutY() + deltaY);
final boolean atRightBorder = ball.circle.getLayoutX() >= (bounds.getMaxX()-ball.circle.getRadius());
final boolean atLeftBorder = ball.circle.getLayoutX() <= (bounds.getMinX()+ball.circle.getRadius());
final boolean atBottomBorder = ball.circle.getLayoutY() >= (bounds.getMaxY()-ball.circle.getRadius());
final boolean atTopBorder = ball.circle.getLayoutY() <= (bounds.getMinY()+ball.circle.getRadius());
if(atRightBorder || atLeftBorder)
deltaX *= -1;
if(atBottomBorder || atTopBorder)
deltaY *= -1;
for(int i = 0; i<arr.size(); i++){
for(int j = i+1; j<arr.size()-1; j++){
arr.get(i).collisionMagnitued(arr.get(j));
}
}
}
}));
loop.setCycleCount(Timeline.INDEFINITE);
loop.play();
}
});
}
class Ball{
public Circle circle;
public double ballDeltaX = 3;
public double ballDeltaY = 3;
public void AddBall(Ball b){
arr.add(b);
}
public Ball(double X, double Y, double Rad, Color color) {
circle = new Circle(X, Y, Rad);
circle.setFill(color);
}
private boolean defineCollision(Ball b){
double xd = this.circle.getLayoutX() - b.circle.getLayoutX();
double yd = this.circle.getLayoutY() - b.circle.getLayoutY();
double sumRad = this.circle.getRadius() + b.circle.getRadius();
double squareRad = Math.pow(sumRad, 2);
double distSquare = Math.pow(xd, 2) + Math.pow(yd, 2);
if(distSquare <= squareRad){
return true;
}return false;
}
public void collisionMagnitued(Ball b){
if(this.defineCollision(b)){
double tempDeltaX = ballDeltaX;
double tempDeltaY = ballDeltaY;
if((this.ballDeltaX < 0 && b.ballDeltaX > 0) || (this.ballDeltaX >0 && b.ballDeltaX <0)){
this.ballDeltaX *= -this.ballDeltaX;
b.ballDeltaX *= -b.ballDeltaX;
System.out.println("tredje");
}
if((this.ballDeltaY < 0 && b.ballDeltaY > 0) || (this.ballDeltaY > 0 && b.ballDeltaY < 0)){
this.ballDeltaY *= -this.ballDeltaY;
b.ballDeltaY *= -b.ballDeltaY;
System.out.println("fjärde");
}
else{
System.out.println("Knull");
this.ballDeltaX *= -1;
b.ballDeltaX *= -1;
}
}
}
}
}
The Balls (or circles) are created and are bouncing against the Bounds as expected.
The Collision detection method works as I'm getting print statements inside the last method. However, it seems that there's something wrong with either my ArrayList not being filled with objects or the method trying to compare the parameter Ball and the Ball that calls the method.
Am I way off? Not sure how I'm suppossed to go forth from here.
I see a few issues with your logic:
The first problem is that when the balls "bounce" off the boundaries of the pane, you don't change their ballDeltaX or ballDeltaY values (you just change a local value in the animation loop and use the local value to update the position). So the first time two balls collide, both of their ballDeltaX and ballDeltaY values are equal to +3 (the initial value), which may not represent the actual direction the animation loop is moving them in. In fact, you never actually use any updated values of ballDeltaX or ballDeltaY to compute the new positions; you get the initial values of those variables, copy them into deltaX and deltaY, and then just compute the new positions using deltaX and deltaY. So if you change ballDeltaX and ballDeltaY, the animation loop never sees the change.
The for loops look wrong to me; I don't think they compare the last two elements of the list. (When i = arr.size()-2 in the penultimate iteration of the outer loop, your inner loop is for (int j = arr.size() - 1; j < arr.size() -1; j++) {...} which of course never iterates.) I think you want the bounding conditions to be i < arr.size() - 1 and j < arr.size(), i.e. the other way around.
And then your if/else structure in collisionMagnitued(...) is probably not exactly what you want. I'm not sure what you're trying to implement there, but the else clause only kicks in if the second if is false, and no matter what happens in the first if.
Finally, you are starting a new animation on each mouse click. So, for example, if you have three balls bouncing around, you have three animation loops running, each of which is updating values when the balls collide. You need to start just one loop; it shouldn't do any harm if it refers to an empty list.
I am currently making a collision detection in java, I have a two objects coming from a different class which is a bird and a worm. The worm moves in a random direction while the bird move only when I want him to move because I'm the one who's controlling him by using key arrow buttons. Now, if the two objects collide I want only the worm to be vanish and the bird will remain there. Could somebody help me how to do that? Thanks in advance for sharing your ideas.
This codes is coming from my World class.
public void render()
{
setupStrategy();
x0_pixel = 0;
y0_pixel = 0;
x1_pixel = getWidth();
y1_pixel = getHeight();
x1_world = x1_pixel / meter;
y1_world = y1_pixel / meter;
Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
g2d.setBackground(Color.lightGray);
g2d.clearRect(0, 0, x1_pixel, y1_pixel);
g2d.setColor(Color.BLACK);
for (double x = 0; x < x1_world; x++)
{
for (double y = 0; y < y1_world; y++)
{
int xx = convertToPixelX(x);
int yy = convertToPixelY(y);
g2d.drawOval(xx, yy, 2, 2);
}
}
for (Worm worm : worms)
{
for (Sprite bird : birds)
{
if (!collides())
{
bird.render(g2d);
worm.render(g2d);
}
}
}
g2d.dispose();
strategy.show();
Toolkit.getDefaultToolkit().
sync();
}
public void start() throws InterruptedException
{
long prevLoopStart = System.nanoTime();
Avg avg = new Avg();
while (true)
{
final long loopStart = System.nanoTime();
final long dt = loopStart - prevLoopStart;
for (Worm worm : worms)
{
worm.move(dt);
}
for (Bird bird : birds)
{
bird.move(dt);
}
render();
Collides();
frame.onFpsUpdated(1.0 / dt * SECOND, avg.add(loopStart));
final long elapsed_ns = System.nanoTime() - loopStart;
long expected_elapsed_ms = 1000 / 60;
long elapsed_ms = (long) (elapsed_ns / (1000.0 * 1000.0));
long sleep_ms = expected_elapsed_ms - elapsed_ms;
if (sleep_ms > 0)
{
Thread.sleep(sleep_ms /* ms */);
}
prevLoopStart = loopStart;
}
}
private boolean Collides()
{
ArrayList<Sprite> toDisappear = new ArrayList<Sprite>();
for (int i = 0; i < worms.size(); i++)
{
Sprite r1 = worms.get(i);
for (int j = i + 1; j < birds.size(); j++)
{
Sprite r2 = birds.get(j);
if (r1 == r2)
{
continue;
}
Rectangle me = r1.getBounds();
Rectangle him = r2.getBounds();
if (me.intersects(him))
{
collision = true;
toDisappear.add(r1);
toDisappear.add(r2);
}
toDisappear.remove(r1);
todisappear.remove(r2);
}
}
return collision;
}
This book provides a lot of INFO regarding "Collision Detection" ( Read Chapter 2 and 3 ) and other topics related to Game programming in Java.
http://fivedots.coe.psu.ac.th/~ad/jg/
There are open source frameworks that already do that. If you are doing it for learning purposes then just check their code.
One is Genuts and it SpriteCollisionManager.
The resource that #Upul mention is also of great value.
Regards.
you have a nested for-loop which checks for collisions between birds and worms. if there is a collision neither of them are drawn. Your code also incorrectly draws birds and worms multiple times.
for (Worm worm : worms){
for (Sprite bird : birds){
if (!collides()){
bird.render(g2d);
worm.render(g2d);
}
}
}
The correct way to go is to remove the worm from the list when there is a collision:
for (Iterator<Worm> wit = worms.getIterator(); wit.hasNext(); ){
Worm worm = wit.next();
for (Sprite bird : birds){
if (worm.collidesWith(bird)){
wit.remove();
break;
}
}
}
for (Worm worm : worms){
worm.render(g2d);
}
for (Sprite bird : birds){
bird.render(g2d);
}
Now I assume that you will implement a boolean collidesWith(Bird other) method in class worm so that you can compare that specific worm with the bird you got as an argument. Alternatively make a function as such:
boolean collidesWormBird(Sprite worm, Sprite bird){
Rectangle me = worm.getBounds();
Rectangle him = bird.getBounds();
return me.intersects(him);
}