I'm trying to draw concentric circles that appear one at a time, from smallest to largest outward. I'm wanting to give an illusion of the circle expanding, by adding an additional circle to the outside of the existing outer circle each time the loop executes. At the moment all the circles appear at the same time when I run my program. Please help, I have no idea how to do this. Thanks in advance.
public static void drawCircles(Graphics g) {
int radius = 10;
int x = 0;
while(x <= 10) {
int z = radius / 2;
g.drawOval(100 - z, 100 - z, radius, radius);
x++;
radius = radius + 10;
}
}
To pause the program between circle draws add a call to Thread.sleep(long millis) where millis is the number of milliseconds that you want to pause.
public static void drawCircles(Graphics g) {
int radius = 10;
int x = 0;
while(x <= 10) {
int z = radius / 2;
g.drawOval(100 - z, 100 - z, radius, radius);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
x++;
radius = radius + 10;
}
}
To give the illusion of expanding circle. Your algorithm should remove the old circle by wiping off the canvas or for example drawing the background again so that it seems that you have cleared the old circle,before drawing the new one.
So, say if my background was a gray color box, i will draw that before I draw my new circle.
g.setColor(Color.GRAY);
g.fillRect(0,0,BACKGROUND_SIDE_X, BACKGROUND_SIDE_Y);
g.drawOval(100 - z, 100 - z, radius, radius);
Related
It's basically a simple game, in that, when the mouse pointer is within the circle, it adds one to the score. I'm new to processing and tried to create this simple game.
Here's the code:
float dist;
float score;
float x;
float y;
float ran;
float a;
float b;
void setup(){
size(800,600);
background(0);
score = 0;
}
void draw(){
background(0);
text("score: "+score,600,20);
x = random(800);
y = random(600);
circle_(x,y);
if ( (abs(mouseX - x) <= 200) && (abs(mouseY - y) <= 200 )) { // algorithm for checking whether mouse inside the circle or not
score = score + 1;
}
}
void circle_(float x,float y){
delay(1000);
circle(x,y,50);
}
There are 2 problems here: first, you're checking 200 pixels where it should be 25 (as in 25 being half the diameter of the circle). But this is the easy one. The real issue is with the delay(1000); line.
That's the real pain.
It means that your program "sleeps" for about 1000/1001 seconds. While the mouse can go around the screen, this one just isn't listening. It's waiting.
You can track time in Processing with the millis() method. It gives you how many milliseconds have passed since you started running the sketch. I ninja coded you a couple lines to keep track of time and teleport the circle every 1 second. Here's the code:
float score;
float x;
float y;
int respawnCircle;
void setup() {
size(800, 600);
background(0);
score = 0;
}
void draw() {
background(0);
text("score: "+score, 600, 20);
if (millis() > respawnCircle) {
changeCircleCoordinates();
}
circle_(x, y);
if ((abs(mouseX - x) <= 25) && (abs(mouseY - y) <= 25 )) { // using 25 as it's half the circle's diameter
score = score + 1;
// if you want the circle to change place right when you get one point uncomment the next line
// changeCircleCoordinates();
}
}
void changeCircleCoordinates() {
respawnCircle = millis() + 1000;
x = random(800);
y = random(600);
}
void circle_(float x, float y) {
//delay(1000); // this is why your collision detection wasn't working: the program is sleeping for about 1000/1001 milliseconds... you have to be very lucky to be on target at just the right time
circle(x, y, 50);
}
Hope it helps. Have fun!
My bouncing ball is meant to bounce between 200x200 window's borders.
I'v managed to make him stop and change direction when he touches the right and bottom borders.
But when he reaches the top and left borders, a 1/4 of the ball goes through the border and only then it changes direction.
I have no idea why it happens, I mean it's literally the same code lines for each border.
How can it even be that for the same code it will work differently?
I went through lots of codes around the net about this topic, and tried every solution or code, and it's still stays the same.
Thanks.
public Point applyToPoint(Point p) {
return new Point(p.getX() + dx, p.getY() + dy);
}
public void moveOneStep(int width, int height) {
if (this.center.getX() + this.getVelocity().dx + r > width) {
this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
}
if (this.center.getX() + this.getVelocity().dx < 0) {
this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
}
if (this.center.getY() + this.getVelocity().dy + r > height) {
this.setVelocity(this.getVelocity().dx, -(this.getVelocity().dy));
}
if (this.center.getY() + this.getVelocity().dy < 0) {
this.setVelocity(this.getVelocity().dx, -(this.getVelocity().dy));
}
moveOneStep();
}
public void moveOneStep() {
this.center = this.getVelocity().applyToPoint(this.center);
}
r = radius of the ball.
"this.center" = the center point of the ball.
screenshot of the ball on the left border:
import biuoop.DrawSurface;
import biuoop.GUI;
import biuoop.Sleeper;
public class BouncingBallAnimation {
static private void drawAnimation(Point start, double dx, double dy) {
GUI gui = new GUI("BouncingBall",200,200);
Sleeper sleeper = new Sleeper();
Ball ball = new Ball(new Point(start.getX(), start.getY()), 30, java.awt.Color.BLACK);
ball.setVelocity(dx, dy);
while (true) {
DrawSurface d = gui.getDrawSurface();
ball.moveOneStep(d.getHeight(),d.getWidth());
ball.drawOn(d);
gui.show(d);
sleeper.sleepFor(50); // wait for 50 milliseconds.
}
}
public static void main(String[] args) {
drawAnimation(new Point(20,33),6,6); //just a random input that I decided
}
}
I mean it's literally the same code lines for each border
And that would be the problem. How can it be the same because you have different situations?
When the ball moves to the right/down the x/y values increase.
When the ball move to the left/up the x/y values decrease.
if (this.center.getX() + this.getVelocity().dx < 0) {
I would guess that should be:
if (this.center.getX() - this.getVelocity().dx - r < 0) {
This assumes that the "center" is actually the center of the circle.
Edit:
Also:
this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
}
if (this.center.getX() + this.getVelocity().dx < 0) {
this.setVelocity(-(this.getVelocity().dx), this.getVelocity().dy);
How can the x velocity change be negative in both cases.
When moving to the right you go from a positive velocity to a negative velocity
So when going to the left should you not be going from a negative velocity to a positive velocity?
Ok so here's the working code:
public void moveOneStep(int startX, int height, int startY, int width) {
if (this.center.getX() + this.getVelocity().dx + r >= width) {
this.setVelocity(-1 * (this.getVelocity().dx), this.getVelocity().dy);
}
if (this.center.getX() + this.getVelocity().dx - r <= startX) {
this.setVelocity(-1 * (this.getVelocity().dx), this.getVelocity().dy);
}
if (this.center.getY() + this.getVelocity().dy + r >= height) {
this.setVelocity(this.getVelocity().dx, -1 * (this.getVelocity().dy));
}
if (this.center.getY() + this.getVelocity().dy - r <= startY) {
this.setVelocity(this.getVelocity().dx, -1 * (this.getVelocity().dy));
}
moveOneStep();
}
The problem was not the code but the starting point I entered to check the circle.
You can't give the circle a starting center point of lets say (20,50) if the Radius is 30.
Why?
Because then the circle will be out of bounds right from the beginning, because he has a starting center point of 20,50, and radius of 30, which means his left radius will reach (-10, 50). And that's why I had many problems.
You always should check if the starting point fits the radius.
public class SimpleHarmonic {
public static void main(String[] args) {
StdDraw.setXscale(0,900);
StdDraw.setYscale(0,700);
while (true) {
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.line(0,350,900,350); // x-axis
StdDraw.line(450,0,450,900); // y-axis
StdDraw.setPenColor(StdDraw.RED);
for (double x = -450; x <= 450; x += 0.5) {
double y = 50 * Math.sin(x * (Math.PI / 180));
int Y = (int) y;
int X = (int) x;
StdDraw.line(450 + X, 350 - Y, 450 + X, 350 - Y);
}
StdDraw.clear();
}
}
}
In this code I am attempting to simulate simple harmonic motion. However, I have only been able to draw a static graph, but I need it to move continously.
I believe I need to use a loop to contionusly redraw the points, but I am not sure how to do that.
How can I make my current sine graph move contionusly?
Edit: Voted to close as non-programming? what?
I took a look at the StdDraw class you are using and it looks like what you want is the
StdDRaw.show(int) method, this method comment states:
/**
* Display on screen, pause for t milliseconds, and turn on
* <em>animation mode</em>: subsequent calls to
* drawing methods such as {#code line()}, {#code circle()}, and {#code square()}
* will not be displayed on screen until the next call to {#code show()}.
* This is useful for producing animations (clear the screen, draw a bunch of shapes,
* display on screen for a fixed amount of time, and repeat). It also speeds up
* drawing a huge number of shapes (call {#code show(0)} to defer drawing
* on screen, draw the shapes, and call {#code show(0)} to display them all
* on screen at once).
* #param t number of milliseconds
*/
In this library any time you call a draw method such as line or circle it conditionally repaints the frame. By passing the int param to the draw method it will turn all painting methods into "animation mode" and defer repainting the frame until you call draw() (no params).
To make it animate you must make each iteration of your while loop 1 animation frame, each frame will need to differ from the previous one. You can do this by using a variable outside your loop to offset each frame by a small ammount. Ill call this offset
With this information you can alter your loop to look like:
double offset = 0;
while (true) {
offset+=1; // move the frame slightly
StdDraw.show(10); // defer repainting for 10 milisecoinds
StdDraw.clear(); // clear before painting
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.line(0,350,900,350); // x-axis
StdDraw.line(450,0,450,900); // y-axis
StdDraw.setPenColor(StdDraw.RED);
for (double x = -450; x <= 450; x += 0.5) {
// apply the offset inside of calculation of Y only such that it
// slowly "moves" the sin wave
double y = 50 * Math.sin((offset+x) * (Math.PI / 180));
int Y = (int) y;
int X = (int) x;
StdDraw.line(450 + X, 350 - Y, 450 + X, 350 - Y);
}
StdDraw.show(); // end animation frame. force a repaint
}
A few improvements in your code
1 Inside your loop where you draw each "dot" you are increnting by .5. Because that X value is literally 1 pixel you arent gaining anything by going to .5 instead of 1. 1 is quite literally the smallest you can visually see in this enviroment. I recommend making it at least be x+=1
for (double x = -450; x <= 450; x += 1)
2 You are using the .line method but drawing to the same point. You could significantly speed up your program by only calculating every 3rd pixels Y value and connecting the dots. For instance
double prevX = -450;
double prevY = 50 * Math.sin((prevX+offset) * (Math.PI / 180)); // seed the previous Y to start
for (double x = 0; x <= 450; x += 3) {
double y = 50 * Math.sin((x+offset) * (Math.PI / 180));
StdDraw.line(450 + (int)prevX, 350 - (int)prevY, 450 + (int)x, 350 - (int)y);
prevX = x;
prevY = y;
}
3 This isnt your code but in the StdDraw.init method you can set some rendering hints to allow for cleaner lines. This should make it look alot nicer
offscreen.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_PURE);
Combining all those things heres what I wrote
public static void main(String[] args) {
StdDraw.setXscale(0,900);
StdDraw.setYscale(0,700);
double offset = 0;
while (true) {
StdDraw.show(10);
StdDraw.clear();
offset-=1;
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.line(0,350,900,350); // x-axis
StdDraw.line(450,0,450,900); // y-axis
StdDraw.setPenColor(StdDraw.RED);
double prevX = 0;
double prevY = 50 * Math.sin((prevX+offset) * (Math.PI / 180)); // seed the previous Y to start
StdDraw.filledCircle(450 + prevX, 350 - prevY, 5);
for (double x = 0; x <= 450; x += 3) {
double y = 50 * Math.sin((x+offset) * (Math.PI / 180));
StdDraw.line(450 + (int)prevX, 350 - (int)prevY, 450 + (int)x, 350 - (int)y);
prevX = x;
prevY = y;
}
StdDraw.show();
}
}
I dont have an animation recorder so heres a picture
I'm trying to draw a circle on my canvas. Pseudocode of my algorithm looks like that
double R = 1.0;
// Draw 11 points, lying on the circle with the radius of 1
// and angle from 0 to 90 degrees
for(int i=0; i<=10; i++)
{
drawPoint( R*cos(PI*i/20), R*sin(PI*i/20) );
}
// Draw a circle with center at the (0; 0) and with the radius of 1
drawCircle(0, 0, R);
That's what I've got:
Looks fine, but there is one problem. When I increase radius only points with angles 0, 45 and 90 lie on a circle.
That's how it looks 72 degrees:
There is no any info about accuracy of the method drawCircle on developer.android.com.
I guess that it draws, based on the values at points with angles 0, 45, 90, ..., and calculate line in other positions very approximately.
I know, that I can draw circle as accurate as I want to, if I'll draw it like a polyline with tiny step, but it will work very slow.
So I want to find out - is there any methods to draw circle accurate in Android?
UPD 1:
How do I draw a points:
int x, y;
x = getPixelX(point.getX());
y = getPixelY(point.getY());
canvas.drawCircle(x, y, point.radius, paint);
Where getPixelX and getPixelY takes a coorditate of the point on plane and returns the same coordinate on the screen, basing on scale and offset.
I thought that I could make some mistake in those methods, but they work perfectly with the lines. I can zoom in lines and there is no error, all the points lies just on the line.
UPD 2:
There are comments, that probably I make a mistake in my calculations. I do not argue, perhaps you're right. So here is my "calculations".
How do I zoom in:
public void mouseWheelMoved(MouseWheelEvent e) {
// zoomQ is 0.9 or 1.1
double zoomQ = (e.getWheelRotation() + 10) / 10.0;
scaleX *= zoomQ;
scaleY *= zoomQ;
}
How do I move the plane:
public void mouseDragged(MouseEvent e) {
centerX -= (e.getX() - lastMouseX)/scaleX;
centerY -= (e.getY() - lastMouseY)/scaleY;
lastMouseX = e.getX();
lastMouseY = e.getY();
}
How do getPixelX/Y works:
public int getPixelX(double planeX) {
return (int)Math.round( scaleX*(planeX - centerX) + ScreenWidth/2 );
}
public int getPixelY(double planeY) {
return (int)Math.round( scaleY*(planeY - centerY) + ScreenHeight/2 );
}
I have another question, this is also extra credit and not homework. This time I need to create a border with out using java2d. The instructions are...
Write a method called drawRectangleBorder having six parameters which does not use the graphics package. It draws a rectangular border starting at the x and y coordinates given as the first two parameters, having a width and height given by the third and fourth parameters, the width of the border given by the fifth parameter in the color given by the sixth parameter. The parameter list is: x, y, width, height, borderWidth, color
I used a previous method I made to create a border around the outside of a picture but the best I can make it do now is a couple scattered boxes. The most recent version will not show anything
public void drawRectangleBorder(
int x, int y, int width, int height, int border, Color newColor) {
int startX = 0;
int startY = 0;
// top and bottom
for (startX = x; x < width; x++) {
for (startY = y; y < border; y++) {
// top pixel
this.getPixel(startX, startY).setColor(newColor);
// bottom pixel
this.getPixel(startX + width, startY + height).setColor(newColor);
} // for-y
} // for-x
// left and right
for (startX = x; x < border; x++) {
for (startY = y; y < height; y++) {
// left pixel
this.getPixel(startX, startY).setColor(newColor);
// right pixel
this.getPixel(startX + width, StartY + height).setColor(newColor);
} // for-y
} // for-x
return;
} // end drawRectangleBorder
Again I thank you for any input.
You can alter the pixels in a java.awt.BufferedImage as shown here.
I might be too sleepy but I think your forgetting to set the pixel back into this (whatever this is ^^)
I'm guessing this.getPixel sends your back a copy so you might want to do something like
Pixel p = this.getPixel( startX, startY );
p.setColor(newColor);
this.setPixel(startX, startY, p);