Sign in to follow this  
ChristianFrantz

thread error

Recommended Posts

Why is this giving me an error? it says that the code is unreachable whatever that means

[source lang="java"] public class CreateDOTS extends Thread //create new dots every 10 seconds at random points on the screen
{
public void run()
{
while(true)
{
repaint();
int randomx = (int)(Math.random() * 399 + 1);//create random x
int randomy = (int)(Math.random() * 399 + 1);//create random y
}
try
{
Thread.sleep(5000);
}catch(InterruptedException e){}
}
}[/source Edited by burnt_casadilla

Share this post


Link to post
Share on other sites
In general, whenever you're asking for help with an error, it's helpful to tell us which line of code the error mentions and the exact text of the error.

Looking through the code, I imagine the error is at the [i]Thread.sleep(5000)[/i] line?

It's telling you that it's not possible to ever reach that line of code. In this case, it's right as your loop above it says while(true). Since true will always evaluate to true, you'll enter that while loop and never get out of it (which is what would need to happen to reach the errored line).

Share this post


Link to post
Share on other sites
i figured it out lol. the try was outside of the while loop. Another question tho... i created a new class file in order to stop confusing myself, so how do i import that into the main file i am using?

oh figured that out too. now another...

i have this code

[source lang="java"]import game.java.createDOTS;

import java.applet.*;
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
import java.util.concurrent.*;


public class game extends Applet implements Runnable
{
int xpos = 100;
int ypos = 100;
int radius = 5;
int xspeed = 0;
int yspeed = 0;
int randomx;
int randomy;
static final int WIDTH = 400;
static final int HEIGHT = 400;
private Image dbImage;
private Graphics dbg;

public void update(Graphics g)
{
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 void init()
{
this.setSize(WIDTH, HEIGHT);
}

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

Thread createDOTS = new createDOTS();
createDOTS.start();

System.out.println(randomx);
System.out.println(randomy);
}

public void stop()
{

}

public void destroy()
{

}

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

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

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

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

return true;
}
public void run()
{
while(true)
{
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

repaint();

if (xpos < 1)
{
xpos = 399;
}

if (xpos > 399)
{
xpos = 1;
}
if (ypos < 1)
{
ypos = 399;
}

if (ypos > 399)
{
ypos = 1;
}
ypos += yspeed;
xpos += xspeed;
try
{
Thread.sleep(20);
}
catch(InterruptedException ex)
{

}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}


public void paint(Graphics g)
{
g.setColor(Color.black);
g.fillOval(xpos - radius, ypos - radius, 2 * radius, 2 * radius);

}
}[/source]

with this class in another file

[source lang="java"]package game.java;
import java.applet.*;
import java.awt.*;

public class createDOTS extends Thread //create new dots every 10 seconds at random points on the screen
{
int randomx;
int randomy;
int high = 399;
int low = 1;
int dotradius = 10;

public void create_dots(int randomx, int randomy, Graphics g)
{
while(true)
{
randomx = (int)(Math.random() * (high - low + 1)) + low;//create random x
randomy = (int)(Math.random() * (high - low + 1)) + low;//create random y
System.out.println(randomx + " " + randomy);


g.setColor(Color.black);
g.fillOval(randomx, randomy, dotradius * 2, dotradius * 2);
try
{
Thread.sleep(5000);

}catch(InterruptedException e){}

}
}

}[/source]

and what i want to do with the createDOTS class is generate a random coordinate every 5 seconds and place a dot on the screen in that coordinate, but its not working and im not sure what i have to do to get it to work Edited by burnt_casadilla

Share this post


Link to post
Share on other sites
The documentation of Thread describes pretty well what you have to do: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html
Also, the Graphics context you have is in general not valid beyond the paint() method, so you cannot just transfer it to another thread anyway. You would need to add a point to a collection in the main Applet and tell the Applet to trigger a repaint.

Share this post


Link to post
Share on other sites
Threading is a very low level concept. There is a lot to be learned before you can effectively and safely use threads. The high level solution to this kind of problem is to create a [url="http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html"]timer[/url]. Another solution would be to include the dot spawning code in the main loop, using the value of System.currentTimeMillis() to control execution.

That said, your code doesn't appear to support multiple dots at the moment. I would suggest trying to get multiple dots to work first - for example by starting the game with 5 dots, before you try writing code to spawn additional dots. For example, you'll probably want a Dot class, and then the Game class would have a collection of Dot instances - perhaps held in an ArrayList.

Your code also seems to fall prey to the same problem described [url="http://stackoverflow.com/questions/8663286/what-is-wrong-with-this-applet-gameloop"]here[/url]. Again, this is caused by use of the low-level thread concept without enough care to respect the rules required. As mentioned in that thread, one solution is to synchronously request repaints via [url="http://docs.oracle.com/javase/1.4.2/docs/api/javax/swing/SwingUtilities.html#invokeAndWait(java.lang.Runnable)"]SwingUtilities.invokeAndWait()[/url].

Share this post


Link to post
Share on other sites
alright i added this to the beginning of my program.

[source lang="java"]class Ball extends Ellipse2D.Float//class to store the ball
{
private int diameter = 20;//diameter of ball
private int d;

public Ball(int diameter)
{
super((int)(Math.random() * (400 - 20)+ 1), (int)(Math.random() * (400 - 20) + 1), diameter, diameter);//create random points to spawn the ball
this.d = diameter;

}
}
class PaintSurface extends JComponent//class to draw the ball
{
public ArrayList<Ball> Balls = new ArrayList<Ball>();//arraylist to store 10 balls

public PaintSurface()
{
for (int i = 0; i < 10; i++)
Balls.add(new Ball(20));//add new ball to the arraylist up to 10
}

public void paintBalls (Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
for (Ball Ball : Balls)
{
g2.fill(Ball);//supposed to draw balls on the screen
}
}
}
[/source]

still doesnt work....

with this im just trying to add 10 balls at random places on the screen. seems simple enough Edited by burnt_casadilla

Share this post


Link to post
Share on other sites
Define "doesn't work". Compile error? Runtime error? Nothing drawn on screen? Ghosts escape from your computer?

I suspect one problem is that paintBalls() isn't getting called. The Swing framework only automatically calls some functions when things need to be drawn. Your PaintSurface should override "protected paintComponent(Graphics g)". This can simply call paintBalls() then, or you can move the paintBalls() code inside paintComponent().

Share this post


Link to post
Share on other sites
No, I don't think you need to be making any of your own threads right now unless the framework forces it on you.

So, show us what your code is looking like right now.
Is there a window even being drawn?
Is anything at all happening when you run this code?

Share this post


Link to post
Share on other sites
[source lang="java"]
import java.applet.*;
import java.awt.*;

import javax.swing.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.concurrent.*;


public class game extends Applet implements Runnable
{
int xpos = 100;
int ypos = 100;
int radius = 5;
int xspeed = 0;
int yspeed = 0;
static final int WIDTH = 400;
static final int HEIGHT = 400;
private Image dbImage;
private Graphics dbg;

public void update(Graphics g)//doublebuffer dont 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);
}

class AnimationThread implements Runnable
{
JApplet c;

public AnimationThread(game game)
{
this.c = c;
}

public void run()
{
c.repaint();
}
}
public void init()
{
this.setSize(WIDTH, HEIGHT);

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);
}

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

}

public void stop()
{

}

public void destroy()
{

}

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

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

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

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

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

repaint();

if (xpos < 1)
{
xpos = 399;
}

if (xpos > 399)
{
xpos = 1;
}
if (ypos < 1)
{
ypos = 399;
}

if (ypos > 399)
{
ypos = 1;
}
ypos += yspeed;
xpos += xspeed;
try
{
Thread.sleep(20);
}
catch(InterruptedException ex)
{

}
}
}


public void paint(Graphics g)
{
g.setColor(Color.black);
g.fillOval(xpos - radius, ypos - radius, 2 * radius, 2 * radius);

}
}

class Ball extends Ellipse2D.Float
{
private int diameter = 20;
private int d;

public Ball(int diameter)
{
super((int)(Math.random() * (400 - 20)+ 1), (int)(Math.random() * (400 - 20) + 1), diameter, diameter);
this.d = diameter;

}
}
class PaintSurface extends JComponent
{
public ArrayList<Ball> Balls = new ArrayList<Ball>();

public PaintSurface()
{
for (int i = 0; i < 10; i++)
Balls.add(new Ball(20));
}

public void paintBalls (Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
for (Ball ball : Balls)
{
g2.fill(ball);
}
}
}
[/source]

so far all it does is draw one ball on the screen that i can move with the keys.
i want to eventually draw random balls every 10 seconds but id be happy with just drawing another ball lol

Share this post


Link to post
Share on other sites
Haha, well that's a good mentality. Sometimes getting to a goal is about a lot of small steps rather than a couple of huge leaps. Stick with it.

So, right now the one you have being drawn is just you calling g.fillOval(). I think a good next step would be to work on keeping that one as your "player" like it is for now and work on getting 1 Ball object drawn on the screen. Even if it's at a preset position (rather than random). As you're doing that, you'll start to see what you need to interact with the Ball class. Or what you need to add to the Ball class to make it work the way you want.

Share this post


Link to post
Share on other sites
Well this is as good a time as any to get one back on there. :) And to start putting your Ball class to use.

So, you'll want to create an instance of the Ball class once when the program gets started.
And then you'll want to draw that Ball each time your code draws on the screen.

It's up to you to think through how to carry out those 2 steps.

Share this post


Link to post
Share on other sites
the only thing i can think of is creating another fillOval() in the paint(Graphics g) method... but i cant treat the oval i create the oval as a variable or method can i? itd be so much easier if i could just create the oval as a variable and then set it as a variable and draw it to the screen at a random point. i really dont know what to do so im relearning threads and classes so maybe i can understand it a little better :P

Share this post


Link to post
Share on other sites
Putting another fillOval in the paint method would work, but it's definitely not the solution that you need to grow into.

I think relearning classes will be very beneficial for you! Threads less so as they are a very in-depth and subtle topic that I think will be very hard to really grasp before you've done some programming.

Maybe it would also be a good idea to step to some console programs (rather than graphical applets). That will remove one layer of complexity and allow you to really get comfortable with the constructs of the language like classes (inheritance, polymorphism, encapsulation), methods, conditionals (if and switch statements), loops (for, while, do-while), variables.

You already seem to have some of those topics down pat, but others have a lot of room for growth.

Maybe try a console game that has the player guess a number. So the program would choose a random number (between say 1 and 20) and then the player would guess a number. If the player is wrong, it can print out that he's wrong and needs to go higher or lower. And when the player is right, it congratulates him, tells him how many tries he took to get the right answer and asks if he wants to play again. It's a pretty solid beginner game. And the things I added in there will definitely present a few challenges to overcome.

Share this post


Link to post
Share on other sites
Ive already got the basic concepts of java; i have made a game like youve described but im proud of the rpg battle simulated battle text game i made. it took some work but i think i still need to practice the basics. i really dont know at this point if i have the basics learned if i cant figure out something simple like this lol

Share this post


Link to post
Share on other sites
Yes! Rpg text battle simulations are so fun to make. That was my go to when I was learning C++.

So, yeah if you can make something like that then you have several of the basics down. It looks like getting a better grasp on classes is the next thing on your plate.

You already understand some of the things needed for dealing with classes/objects. I can see because you've already written code that uses classes. To create a Ball object you call new Ball(20) on line 172 of the above code.

So just for the practice of getting that understanding a little more complete, create a ball object in your init method ([i]ball = new Ball(20);)[/i].
Since we'll want to access that same object in the paint method, declare the variable as a field of the game class (like you have xpos, ypos and others right now) ([i]Ball ball;).[/i]
And last but not least, we want to draw that ball in the paint method. Let me say right up front, this is not the ideal way to draw your ball class, but it is a very straightforward way. Add as the last line in the paint method [i]g.drawOval((int)ball.x, (int)ball.y, (int)ball.width, (int)ball.height);[/i]

That draw line is calling the drawOval method of the Graphics object and passing it an x, y set of coordinates and a width and height for the oval. And each of those values is being pulled from Ball class (which extends the Ellipse2D class, where each of those values (x, y, width, height) are declared). Because you extend Ellipse2D.Float, those values are all floats and we need them to be ints for the drawOval method. That's why each one is cast to int.

edit: typos Edited by j-locke

Share this post


Link to post
Share on other sites
As soon as I got to the (Ball ball); part I had to hit myself because I knew that and it's so simple -_- but yeah that'll work for now until I can understand how to draw multiple balls at different times

Share this post


Link to post
Share on other sites
Ah, that's programming. That's why we all keep writing code though; because there's always something else for us to learn. And once you've learned it, hopefully it'll stick with you so you can use it next time a similar situation comes up.

While it's not quite your final goal, you should now be able to pretty easily change that code to handle say 10 balls instead of just one. This would create all 10 and have all 10 at random locations right at the start (so not appearing over time like you eventually want). But as a good step in the right direction, you could add the code to make that a reality. A collection (like ArrayList that you tried using earlier) and a for loop should allow you to make that change by only adding 5 or so lines of code.

Share this post


Link to post
Share on other sites
[source lang="java"] class AnimationThread implements Runnable
{
JApplet c;

public AnimationThread(game game)
{
this.c = c;
}

public void run()
{
c.repaint();
}
}

class Ball extends Ellipse2D.Float
{

public Ball()
{
int x = 150;
int y = 150;
int width = 20;
int height = 20;

}
}

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

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
executor.scheduleAtFixedRate(new AnimationThread(this), 0L, 20L, TimeUnit.MILLISECONDS);



}

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

}

public void stop()
{

}

public void destroy()
{

}

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

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

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

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

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

repaint();

if (xpos < 1)
{
xpos = 399;
}

if (xpos > 399)
{
xpos = 1;
}
if (ypos < 1)
{
ypos = 399;
}

if (ypos > 399)
{
ypos = 1;
}
ypos += yspeed;
xpos += xspeed;
try
{
Thread.sleep(20);
}
catch(InterruptedException ex)
{

}
}
}


public void paint(Graphics g)
{
Ball ball = new Ball();

g.setColor(Color.black);
g.fillOval(xpos - radius, ypos - radius, 2 * radius, 2 * radius);

g.drawOval((int)ball.x, (int)ball.y, (int)ball.width, (int)ball.height);
}
}
[/source]

ok now what? in the ball class i created variables that define the x, y, width and height for the ball and created a new ball in the public void paint(Graphics g) method and then drew the ball to the variables, but no ball is being drawn :( Edited by burnt_casadilla

Share this post


Link to post
Share on other sites
hahahahahahahaaha finally!!! all i did was change the ball class to this

[source lang="java"]class Ball extends Ellipse2D.Float
{

int x = 150;
int y = 150;
int width = 20;
int height = 20;

}
[/source]

Share this post


Link to post
Share on other sites
Nice job going back over the code and cleaning it up a bit.

One problem with what you're doing is you're creating a new instance of Ball everytime the paint method gets called (which is a LOT). You could likely get away with doing it through a smaller game, but I'd say it's worth breaking that habit right now. The init method is a much better place for creating that Ball object.

So, what do you have your project doing right now? Drawing the one oval and the one dot? Using the arrow keys to move the oval around? Wrapping that oval from one side of the screen to the other when it reaches the end?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this