#22 Members - Reputation: 555
Posted 10 August 2012 - 05:19 PM
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.
#23 Members - Reputation: 264
Posted 11 August 2012 - 10:09 AM
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, 11 August 2012 - 10:10 AM.
#25 Members - Reputation: 555
Posted 11 August 2012 - 10:59 AM
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?
#26 Members - Reputation: 264
Posted 11 August 2012 - 11:03 AM
[source lang="java"] final int NUM_BALLS = 4; Ball b[]; 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(); } } class Ball extends Ellipse2D.Float { public Ball(int x, int y, int width, int height, Color mycolor) { } public Ball() { // TODO Auto-generated constructor stub } int x; int y; int width; int height; Color mycolor; public void paint(Graphics g) { g.setColor(mycolor); g.fillOval(x, y, width, height); } } public void Ball(int x, int y, int width, int height, Color mycolor) { b = new Ball[NUM_BALLS]; b[0] = new Ball(10, 10, 15, 15, Color.yellow); b[1] = new Ball(30, 30, 15, 15, Color.red); b[2] = new Ball(50, 50, 15, 15, Color.blue); b[3] = new Ball(70, 70, 15, 15, Color.red); } 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); for(int i = 0; i<NUM_BALLS; i++) { b[i].paint(g); } }}[/source]
the problem is in my ball class, i already know that
[source lang="java"] class Ball extends Ellipse2D.Float { int x; int y; int width; int height; Color mycolor; public void paint(Graphics g) { g.setColor(mycolor); g.fillOval(x, y, width, height); } } public void Ball(int x, int y, int width, int height, Color mycolor) { b = new Ball[NUM_BALLS]; b[0] = new Ball(10, 10, 15, 15, Color.yellow); b[1] = new Ball(30, 30, 15, 15, Color.red); b[2] = new Ball(50, 50, 15, 15, Color.blue); b[3] = new Ball(70, 70, 15, 15, Color.red); }[/source]
i know i have to make a constructor for the Ball class somewhere but idk where
Edited by burnt_casadilla, 11 August 2012 - 11:09 AM.
#27 Members - Reputation: 264
Posted 11 August 2012 - 11:14 AM
changed it to this, but the paint method at the bottom isnt reaching the variables from the constructor
[source lang="java"] public void paint(Graphics g) { Ball ball = new Ball(x, y, width, height, mycolor); g.setColor(Color.black); g.fillOval(xpos - radius, ypos - radius, 2 * radius, 2 * radius); for(int i = 0; i<NUM_BALLS; i++) { b[i].paint(g); } }}[/source]
#31 Members - Reputation: 264
Posted 11 August 2012 - 11:57 AM
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;
final int NUM_BALLS = 4;
Ball b[];
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();
}
}
class Ball extends Ellipse2D.Float
{
int ballx;
int bally;
int ballwidth;
int ballheight;
Color mycolor;
public Ball(int ballx, int bally, int ballwidth, int ballheight, Color mycolor)
{
b = new Ball[NUM_BALLS];
b[0] = new Ball(10, 10, 15, 15, Color.yellow);
b[1] = new Ball(30, 30, 15, 15, Color.red);
b[2] = new Ball(50, 50, 15, 15, Color.blue);
b[3] = new Ball(70, 70, 15, 15, Color.green);
}
public void paint(Graphics g)
{
g.setColor(mycolor);
g.fillOval(ballx, bally, ballwidth, ballheight);
}
}
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();
for(int i = 0; i<NUM_BALLS; i++)
{
b[i].paint(g);
}
g.setColor(Color.black);
g.fillOval(xpos - radius, ypos - radius, 2 * radius, 2 * radius);
}
}
#33 Members - Reputation: 555
Posted 11 August 2012 - 12:20 PM
For me, it didn't compile right away. The line Ball ball = new Ball(); is trying to call a method that doesn't exist (there is no empty constructor for the Ball class).
When I changed that line so it was calling the real constructor, I get a stack overflow error (Exception in thread "AWT-EventQueue-1" java.lang.StackOverflowError) because when I call the constructor once, it recursively calls the constructor again and again until I'm out of available stack memory.
So, I wanted to see what kind of things your'e experiencing before we overhaul this and try to adjust the mindset of this approach.
edit: restating the reason for StackOverflowError
Edited by j-locke, 11 August 2012 - 12:32 PM.
#34 Members - Reputation: 264
Posted 11 August 2012 - 12:36 PM
[source lang="java"]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; final int NUM_BALLS = 4; Ball b[]; public class Ball extends Ellipse2D.Float { int ballx; int bally; int ballwidth; int ballheight; Color mycolor; public Ball(int ballx, int bally, int ballwidth, int ballheight, Color mycolor) { this.ballx = ballx; this.bally = bally; this.ballwidth = ballwidth; this.ballheight = ballheight; } public void initBall() { b = new Ball[NUM_BALLS]; b[0] = new Ball(10, 10, 15, 15, Color.yellow); b[1] = new Ball(30, 30, 15, 15, Color.red); b[2] = new Ball(50, 50, 15, 15, Color.blue); b[3] = new Ball(70, 70, 15, 15, Color.green); } public void paint(Graphics g) { Ball ball = new Ball(ballx, bally, ballwidth, ballheight, mycolor); for(int i = 0; iGREATERTHANNUM_BALLS; i++) { b[i].paint(g); } g.setColor(mycolor); g.fillOval(ballx, bally, ballwidth, ballheight); } public void init() { initBall(); } } [/source]
unless there was a way to run the paint method within the BALL class, its not drawing anything but the main dot which is not in the ball class
when i move the paint method in the ball class to outside of the ball class, it cant call the variables used to create the ball.
i dont get any errors running it with the above code
i created a new file that holds the ball class so its a little less confusing and add package.game; to the top
im wondering if it would be easier to put the draw method into a thread and then run the thread from the main class...
Edited by burnt_casadilla, 11 August 2012 - 12:46 PM.
#35 Members - Reputation: 555
Posted 11 August 2012 - 12:54 PM
And moving the creation of the objects to an initialization method is very good too. Even better if the initBall method is moved out of the Ball class so it just resides in the game class. As a way to mentally approach that, should a Ball (which is what that class is designed to represent) know about creating and populating an array of balls; in my mind that's definitely a no.
In fact, I kind of think that maybe you do have initBall outside of the Ball class.. and maybe just in pasting the code, a closing brace was accidentally left out, but I can't say for sure of course.
What is the error and what line is the error on that it's giving you? I see it looks like in the Ball constructor you're not saving the passed in color.
#36 Members - Reputation: 264
Posted 11 August 2012 - 01:00 PM
alright i cleaned it up a bit
main GAME class
[source lang="java"]package Ball;import game.Ball;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); } public void init() { this.setSize(WIDTH, HEIGHT); } public void start() { Thread th = new Thread(this); th.start();//start main game } 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); } }[/source]
BALL class in another file
[source lang="java"]package game;import java.awt.Color;import java.awt.Graphics;import java.awt.geom.Ellipse2D;public class Ball extends Ellipse2D.Float{ final int NUM_BALLS = 4; Ball b[]; int ballx; int bally; int ballwidth; int ballheight; Color mycolor; public Ball(int ballx, int bally, int ballwidth, int ballheight, Color mycolor) { this.ballx = ballx; this.bally = bally; this.ballwidth = ballwidth; this.ballheight = ballheight; } public void initBall() { b = new Ball[NUM_BALLS]; b[0] = new Ball(10, 10, 15, 15, Color.yellow); b[1] = new Ball(30, 30, 15, 15, Color.red); b[2] = new Ball(50, 50, 15, 15, Color.blue); b[3] = new Ball(70, 70, 15, 15, Color.green); }}[/source]
now where and how in the main game class would i put some code in order to run the ball class?
Edited by burnt_casadilla, 11 August 2012 - 01:06 PM.
#37 Members - Reputation: 555
Posted 11 August 2012 - 01:27 PM
1. Don't create a new object in your paint method. If you're calling new in your paint method, get it out. Get it to an init method that makes sense for whatever it's initializing.
2. Make the Ball class represent one Ball. So give it the information it needs to represent that one ball and don't let it have any methods beyond that (so the Ball class should know nothing about this array of Ball's that the game is managing).
3. Take your code to where it's working (that was definitely happening with the approach you had implemented as of last night). And then make smaller changes to try to get it where you want it. So for this one I mean, don't try to change up 4 or 5 things at once. Just one at a time. So revert to drawing the ball object in the game's paint method. And then when you have that working, try to EITHER try to move drawing that one object into the Ball class OR try to draw the array of Ball's all from the game's paint method. But do one and get it working like you want first then you can take on the other one.
I think using number 3 will get you back to some working code that is progressing towards where you want it to be.
And using numbers 1 and 2 will get you writing code with some good attributes.
#38 Members - Reputation: 264
Posted 11 August 2012 - 01:45 PM
[source lang="java"]import game.Ball;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; class Ball1 extends Ellipse2D.Float { int x = 150; int y = 150; int width = 20; int height = 20; } class Ball2 extends Ellipse2D.Float { int x = 200; int y = 200; int width = 20; int height = 20; } class Ball3 extends Ellipse2D.Float { int x = 50; int y = 50; int width = 20; int height = 20; } class Ball4 extends Ellipse2D.Float { int x = 100; int y = 100; int width = 20; int height = 20; } 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); } public void init() { this.setSize(WIDTH, HEIGHT); } public void start() { Thread th = new Thread(this); th.start();//start main game } 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) { Ball1 ball1 = new Ball1(); Ball2 ball2 = new Ball2(); Ball3 ball3 = new Ball3(); Ball4 ball4 = new Ball4(); g.setColor(Color.black); g.fillOval(xpos - radius, ypos - radius, 2 * radius, 2 * radius); g.setColor(Color.blue); g.fillOval((int)ball1.x, (int)ball1.y, (int)ball1.width, (int)ball1.height); g.setColor(Color.red); g.fillOval((int)ball2.x, (int)ball2.y, (int)ball2.width, (int)ball2.height); g.setColor(Color.green); g.fillOval((int)ball3.x, (int)ball3.y, (int)ball3.width, (int)ball3.height); g.setColor(Color.magenta); g.fillOval((int)ball4.x, (int)ball4.y, (int)ball4.width, (int)ball4.height); } }[/source]
but when i move the
Ball1 ball1 = new Ball1();
Ball2 ball2 = new Ball2();
Ball3 ball3 = new Ball3();
Ball4 ball4 = new Ball4();
to the init method, i cant call the variables through the paint method
is there a reason i cant call a paint method from each class?
Edited by burnt_casadilla, 11 August 2012 - 02:07 PM.
#39 Members - Reputation: 555
Posted 11 August 2012 - 02:23 PM
Now in the spirit of small steps, try these things, but do them one at a time so you can get that small piece working before bringing it all together.
1. Get it so all of those are using the same Ball class. So no classes named Ball1, Ball2, etc. Just have variables named like that. So Ball ball1 = new Ball(); and so on.
2. Then get it so those balls are in one array. Like Ball balls[]; And then you can draw those balls from game's paint method with a for loop.
for (int i = 0; i< NUM_OF_BALLS; i++)
{
g.setColor(balls[i].myColor);
g.fillOval((int)balls[i].x, (int)balls[i].y, (int)balls[i].width, (int)balls[i].height);
}
#40 Members - Reputation: 264
Posted 11 August 2012 - 02:42 PM
got number 1 i think
Edited by burnt_casadilla, 11 August 2012 - 02:42 PM.






