thread error

Started by
138 comments, last by ChristianFrantz 11 years, 8 months ago
here it is. im done coding for the night tho lol

[source lang="java"]import java.applet.Applet;
import java.awt.Color;
import java.awt.Component;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class game extends Applet implements Runnable
{
static final int WIDTH = 450; //set screen height
static final int HEIGHT = 450; // set screen width
private Image dbImage;
private Graphics dbg;

public static long NEW_DOT_FREQ = TimeUnit.SECONDS.toMillis(3);
public long lastUpdateTime;
public long timeSinceLastNewDot;


public ArrayList<Ball> BALLS; //arraylist to store balls

Color[] color = {Color.red, Color.blue, Color.green, Color.yellow, Color.magenta, Color.black};
int colorIndex;

static final int NUM_OF_BALLS = 4;

int i;
int t;

MainBall mainBall = new MainBall(100, 100, 10, 10, 0, 0);
Ball fixedBall = new Ball(250, 250, 20, 20);

Rectangle mainBallRectangle = getMainBallBounds();
Rectangle fixedBallRectangle = getFixedBallBounds();

Thread updateTime = new updateTime();

public void start()
{
lastUpdateTime = System.currentTimeMillis();

Thread th = new Thread(this);
th.start();//start main game

updateTime.start();
}

public void updateGame()
{

checkCollision();

//Get the current time
long currentTime = System.currentTimeMillis();
//Calculate how much time has passed since the last update
long elapsedTime = currentTime - lastUpdateTime;
//Store this as the most recent update time
lastUpdateTime = currentTime;

//Create a new dot if enough time has passed
//Update the time since last new dot was drawn
timeSinceLastNewDot += elapsedTime;

if (timeSinceLastNewDot >= NEW_DOT_FREQ)
{
int newX = randomNumber();
int newY = randomNumber();

debugPrint("New dot created at x:" + newX + ", y:" + newY + ".");

BALLS.add(new Ball(newX, newY, 20, 20));

timeSinceLastNewDot = 0;
}



if (mainBall.xpos < 1)
{
mainBall.xpos = 449;
}

if (mainBall.xpos > 449)
{
mainBall.xpos = 1;
}
if (mainBall.ypos < 1)
{
mainBall.ypos = 449;
}

if (mainBall.ypos > 449)
{
mainBall.ypos = 1;
}

try
{
Thread.sleep(20);
}
catch(InterruptedException ex){}

checkCollision();

mainBall.ypos += mainBall.yspeed;
mainBall.xpos += mainBall.xspeed;
}

private void debugPrint(String value)
{
System.out.println(value);
}

public class updateTime extends Thread implements Runnable
{
public void run()
{
for(t = 0; ; t++)
{
try
{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
}

public int randomNumber()
{
return (int)(Math.random() * 400);
}

public int getRandomColor()
{
return (int)(Math.random() * 6);
}

public class MainBall
{
int width;
int height;
int xpos;
int ypos;
int xspeed;
int yspeed;

public MainBall( int xpos, int ypos, int width, int height, int xspeed, int yspeed)
{
this.width = 10;
this.height = 10;
this.xpos = 100;
this.ypos = 100;
this.xspeed = 0;
this.yspeed = 0;
}

public void paintMainBall(Graphics g)
{
g.setColor(Color.black);
g.fillOval(mainBall.xpos, mainBall.ypos, width, height);
g.drawString(xpos + ", " + ypos, 20, 40);
}

}//mainBall

class Ball
{
int x;
int y;
int width;
int height;

public Ball(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}//end ball

public void paint(Graphics g)
{
g.setColor(color[getRandomColor()]);
g.fillOval(x, y, width, height);
} //end paint


} //ball class

public void update(Graphics g) //double buffer don't touch!!
{
if(dbImage == null)
{
dbImage = createImage(this.getSize().width, this.getSize().height);
dbg = dbImage.getGraphics();
}

dbg.setColor(getBackground());
dbg.fillRect(0, 0, this.getSize().width, this.getSize().height);

dbg.setColor(getForeground());
paint(dbg);

g.drawImage(dbImage, 0, 0, this);
}

public boolean keyDown (Event e, int key)
{
if(key == Event.LEFT)
{
mainBall.xspeed = -5;
mainBall.yspeed = 0;
}

if(key == Event.RIGHT)
{
mainBall.xspeed = 5;
mainBall.yspeed = 0;
}

if(key == Event.UP)
{
mainBall.yspeed = -5;
mainBall.xspeed = 0;
}

if(key == Event.DOWN)
{
mainBall.yspeed = 5;
mainBall.xspeed = 0;
}
return true;
}
public void passThroughWalls()
{

}
public void run()
{
while(true)
{
repaint();
}
}

public void init()
{
this.setSize(WIDTH, HEIGHT);

BALLS = new ArrayList<Ball>();

System.out.println(getFixedBallBounds());

}

public void paint(Graphics g)
{
updateGame();

g.drawString("time: " + t, 20, 20);

mainBall.paintMainBall(g);

g.setColor(Color.blue);
fixedBall.paint(g);

for (Ball ball : BALLS)
{
ball.paint(g);
}

}

public Rectangle getFixedBallBounds()
{
return new Rectangle (250, 250, 20, 20);
}


public Rectangle getMainBallBounds()
{
return new Rectangle(mainBall.xpos, mainBall.ypos, 10, 10);
}


public void checkCollision()
{
if(mainBallRectangle.intersects(fixedBallRectangle))
{
mainBall.xspeed = 0;
mainBall.yspeed = 0;
mainBall.xpos = 100;
mainBall.ypos = 100;
}
}

}[/source]

If you see a post from me, you can safely assume its C# and XNA :)

Advertisement
You'll want to take a look at the code snippet that I posted most recently. In your updateGame method, you'll want to update the mainBall Rectangle and you might as well do the fixedBall one as well. Make sure you do that before you check for collisions in the method.
oooooh now it works. my brain is tired lol. tomorrow ill deal with collision and the arraylist

If you see a post from me, you can safely assume its C# and XNA :)

Yeah, I'm done for the night as well. You made good progress for a weekend of coding. Hopefully you've learned some stuff and are feeling more comfortable with what's going on as well. That's what it's really all about. Building that understanding and comfort in knowing that you're growing as a developer. :)
alright back to work lol
i have this in my ball class

[source lang="java"] public Rectangle getBallBounds()
{
for(Ball ball : BALLS)
return new Rectangle()
}[/source]

this should return a rectangle every time one is created i think? besides the return method not being finished. i dont know how to call the coordinates of a ball in the array

Changed it to this

[source lang="java"] public Rectangle getBallBounds()
{
for(int i = 0; i < BALLS.size(); i++)
{
return new Rectangle(BALLS(i).x, BALLS(i).y, 20, 20);
}
Rectangle ballRectangle = getBallBounds();
}[/source]

so i will increase when the arraylist BALLS increases. but for some reason its saying BALLS(int) isnt a method when i want to call the ArrayList BALLS

and now to this

[source lang="java"] public Rectangle getBallBounds()
{
for(int i = 0; i < BALLS.size(); i++)
{
return new Rectangle(BALLS.get(i).x, BALLS.get(i).y, 20, 20);
}
Rectangle ballRectangle = getBallBounds();
}[/source]

now its saying the type im returning isnt a rectangle?

alright try again...
[source lang="java"] public Rectangle getBallBounds()
{
for(int i = 0; i < BALLS.size(); i++)
{
new Rectangle(BALLS.get(i).x, BALLS.get(i).y, 20, 20);
}
return randomBallRectangle;
}[/source]

i made an object in the main game class Rectangle randomBallRectangle = getBallBounds();
the compiler shows no errors until i run it then i get this:

java.lang.NullPointerException
at game.getBallBounds(game.java:290)
at game.<init>(game.java:38)

If you see a post from me, you can safely assume its C# and XNA :)

In the Ball class is definitely the right place for this method. Glad to see you moved it there rather than keeping it outside of the class. :)

You don't want a for loop here. The reason you don't goes back to a concept that we talked about earlier. This class is designed to represent 1 ball. That means inside the Ball class, you should pretend that the array of balls doesn't exist. Because this code is intended to represent 1 ball, it doesn't care if you stick it in an array or not to make your game work. Because you do want an array of balls for your game, that's why your game class is creating and managing an array of balls.

So this method inside the Ball class should be concerned with returning you the Rectangle that encloses "me".. "me" being the 1 and only ball that it knows or cares about. The fact that you have an array of Balls and need Rectangles for them all is something for the game class to deal with (again, because the game class does want this array of Balls so that it can accomplish what it wants for this game).

So for the first step, focus on getting this method returning the Rectangle around itself (the "me" I mentioned before).
And then for the second step, get a loop (somewhere in the game class because the Ball class doesn't and shouldn't care about the array) that goes through each of the Balls in the array and stores you a Rectangle for each one.
Note: Determining where step 2 goes should be made easier by the fact that we did some simplifying of things last night. In your game class, you should be adding code in one of relatively few places. In the init method if you just need it to happen once when you initially launch your game. In the updateGame method if it's related to updating things that change during your game. And in the paint method if this involves drawing things for your game.
[source lang="java"]
public Rectangle getBallBounds()
{
return new Rectangle(this.x, this.y, 20, 20);
}
[/source]

this is called everytime the ball class is used?

can you explain why i should keep this in the ball class? why would it be any different if it was outside of the class?

im thinking i should put it in the updateGame method and in the if method after the new ball is created every three seconds

[source lang="java"] if (timeSinceLastNewDot >= NEW_DOT_FREQ)
{
int newX = randomNumber();
int newY = randomNumber();

debugPrint("New dot created at x:" + newX + ", y:" + newY + ".");

BALLS.add(new Ball(newX, newY, 20, 20));

getBallBounds();

timeSinceLastNewDot = 0;
}[/source]

so maybe something like this?

If you see a post from me, you can safely assume its C# and XNA :)


can you explain why i should keep this in the ball class? why would it be any different if it was outside of the class?


Definitely. Good question. Inside the class, it allows you to have a ball object Ball myBall = new Ball(x, y, width, height); and be able to refer to that ball's rectangle without needing to know about or deal with any other balls, Rectangle boundary = myBall.getBallBounds();.

If I put it outside the class and I want to know the boundaries of any given ball, I'll need to provide this method with what ball I am talking about (something like Rectangle boundary = getBallBounds(myBall);). It would certainly not be wrong to do it that way. But I've noticed that generally if you're making a method from scratch, you've tended to make it with no parameters. So I was favoring the way your were already writing methods.

And another perk (but not a 'metric' you should be using to make decisions at this point) is if your next game was going to do something different but still be using balls, you could very well have this Ball class in its own file and use it for both this game and the next one. If you have getBallBounds(Ball ball) in this game class, that means if your next game needed that same functionality, you'd have to implement it again. But since it does make good sense that the ball would be able to provide you with its own bounds, having inside the class is logical and makes one less piece of functionality that you'd have to re-implement.


im thinking i should put it in the updateGame method and in the if method after the new ball is created every three seconds

...

so maybe something like this?

In this code, you call getBallBounds() so it's returning you a Rectangle object but you're not doing anything with it. So you're not using it right now nor are you saving it somewhere (in some variable) so you can pull it back up later to use.

Your getBallBounds method is looking alright. You did pull up the x and y values from this particular ball. Why did you hardcode the width and height rather than pulling those values from this particular ball as well?
the width and height of the randomBalls will always be 20, 20 for now until i figure this out and can add more types of balls.

thanks for the explanation smile.png

well in the code i listed it would be calling the method, but in the main game class i would create the object Rectangle randomBallRectangle = getBallBounds();



also for my next game im planning on making a "Snake" clone so ill keep in mind what methods and classes i can reuse

If you see a post from me, you can safely assume its C# and XNA :)


well in the code i listed it would be calling the method, but in the main game class i would create the object Rectangle randomBallRectangle = getBallBounds();


Ah, ok. You may already know this (because I realize we're talking in kind of code short hand sometimes and it's just understood what code goes where) but in case not I'll bring it up now before it is an issue of confusion later.


When you call getBallBounds(), it will return you the Rectangle and store it in whatever variable you put on the left side of the equal sign. So if you call balls.get(i).getBallBounds(), it won't go find some matching piece of code to find out where to store the Rectangle that is returned. It will simply return it and then it will be forever lost. So the confusion i wanted to be sure to avoid is that calling getBallBounds() is useless unless you are using the returned Rectangle either by having it in a statement (such as if (playerRectangle.intersects(balls.get(i).getBallBounds()))) or storing it so you can use it later (such as randomBallRectangle = balls.get(i).getBallBounds()).

I like that the next planned project isn't overly complex. That small steps approach will have you making some bigger projects in a couple of months time and hopefully not feeling TOO overwhelmed as you didn't jump too far beyond your knowledge all at once. :)

This topic is closed to new replies.

Advertisement