I've been scratching my head for the last hour, but I can't figure out how it's done.
What I want to do is a timer shaped like a circle. The timer is set to 60 seconds. As the timer goes down, the circle in drawing segment by segment and when it's a full circle. The timer is at 0.
So, before drawing a new segment, the program has to wait some time so when it's done the timer is precisely at 0. But I can't figure out how to calculate this amount of time.
Any ideas ?
Here is the code, just in case
public void circle(float x, float y, float rad, float start, float end){
float theta = start;
float x2 = (float) (x + rad * Math.sin(theta));
float y2 = (float) (y + rad * Math.cos(theta));
theta -= 0.01f;
timer.start();
while(theta >= -end){
float x1 = (float) (x + rad * Math.sin(theta));
float y1 = (float) (y + rad * Math.cos(theta));
ligne(x2, y2, x1, y1);
theta -= 0.01f;
x2 = x1;
y2 = y1;
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
timer.stop();
}
Related
I've been trying to rotate a square for a project, I've done research and think I have the right formula to calculate the rotated points. I calculate the points as if they're individual around the center of the square. How to fix it?
//Declaring variables
float x0, y0, xo, yo,x1,y1,x2,y2,x3,y3, theta, newx, newy, s, c;
void setup() {
size (800,800);
//To debug
//frameRate(1);
fill(0);
//Initializing variables
xo = 400;
yo = 400;
x0 = 350;
y0 = 450;
x1 = 350;
y1 = 350;
x2 = 450;
y2 = 350;
x3 = 450;
y3 = 450;
theta = radians(5);
s = sin(theta);
c = cos(theta);
}
void draw() {
//Reseting the background
background(255);
//Drawing the square
quad(x0,y0,x1,y1,x2,y2,x3,y3);
//Doing the rotations
x0 = rotateX(x0,y0);
y0 = rotateY(x0,y0);
x1 = rotateX(x1,y1);
y1 = rotateY(x1,y1);
x2 = rotateX(x2,y2);
y2 = rotateY(x2,y2);
x3 = rotateX(x3,y3);
y3 = rotateY(x3,y3);
}
//Rotate x coordinate method
float rotateX(float x, float y) {
x -= xo;
newx = x * c - y * s;
x = newx + xo;
return x;
}
//Rotate y coordinate method
float rotateY(float x, float y) {
y -= yo;
newy = x * s - y * c;
y = newy + yo;
return y;
}
There are two things:
1) You have a sign error in rotateY(). The y term should have a positive sign:
newy = x * s + y * c;
2) When you do this:
x0 = rotateX(x0,y0);
y0 = rotateY(x0,y0);
... then the first call modifies x0, which the second call then uses. But the second call needs the original coordinates to rotate correctly:
float x0Rotated = rotateX(x0, y0);
y0 = rotateY(x0, y0);
x0 = x0Rotated;
The same thing for the other points.
My code for the ball moving in a Bezier Curve from start to the middle of the curve is:
void ballMove()
{
if(y[0]==height*1/10)
{
bezier (x[0], y[0],x[1], y[1], x[2], y[2], x[3], y[3]);
float x0; float x1; float x2; float x3;
float y0; float y1; float y2; float y3;
x0 = x[0]; x1 = x[1]; x2 = x[2]; x3 = x[3];
y0 = y[0]; y1 = y[1]; y2 = y[2]; y3 = y[3];
float t = (frameCount/100.0)%1;
float x = bezierPoint(x0, x1, x2, x3, t);
float y = bezierPoint( y0, y1, y2, y3, t);
if(t>=0.5)
{
t=0;
}
while(t==0.5)
{
a=x;
b=y;
}
while(t>0.5)
{
ellipse(a,b,30,30);
}
fill(255,0,0);
if(t!=0)
{
ellipse(x, y, 15, 15);
}
}
}
I have defined everything in setup, draw etc, but i want to launch the ball from the start to the middle of the Bezier Curve only one time whenever space is pressed.
The current version shows me the loop. How can i do that?
Tried Everything like return, break, changing the t parameter etc, but the code doesn't work. I'm new in processing.
Do you have any suggestions?
Biggest mistake that you make is altering value of t after you calculated x and y positions of red ball. To avoid this you need first calculate t between [0, 1] in you case [0, 0.5] and then alter this value according to state of your program.
Second mistake you made while calculating t from frameCount. First you use modulo to extract numbers [0, 50] and then map it in range [0, 0.5] like this
float t = (frameCount % 50) * 0.01;
You also mentioned that you want to repeat this animation after pressing some key. For this you will need keyPressed method and some global variables to represent state of program and store starting frame of animation (because frameCount should be read only). So basic functionality can be achieved like this:
boolean run = false;
float f_start = 0;
void ballMove() {
noFill();
bezier (x0, y0, x1, y1, x2, y2, x3, y3);
float t = ((frameCount - f_start) % 50) * 0.01;
if (run == false) {
t = 0;
}
float x = bezierPoint(x0, x1, x2, x3, t);
float y = bezierPoint( y0, y1, y2, y3, t);
fill(255, 0, 0);
ellipse(x, y, 5, 5);
}
void keyPressed() {
run = !run;
f_start = frameCount;
}
Hope this will help you. Next time pls post an MCVE so we do not need to fight with your code.
Here is my source code:
int index;
int num = 60;
float mx[] = new float[num];
float my[] = new float[num];
float explosion;
float x;
float y;
float px;
float py;
float xold;
float yold;
float xplode1;
float yplode1;
float xplode2;
float yplode2;
float xplode3;
float yplode3;
float xplode4;
float yplode4;
float easing = 0.05;
void setup() {
size(1366, 768);
noStroke();
// noFill();
fill(25, 155);
}
void draw() {
int which = frameCount % num;
explosion = explosion + 0.32;
background(92, 55, 169);
float targetX = mouseX;
float dx = targetX - px;
float lx = targetX - x;
if (abs(dx) > 1) {
mx[which] += dx * easing;
x += lx * easing;
if (mousePressed && (mouseButton == LEFT)) {
xplode1 = dx + 50 + sin(explosion)*30;
xplode2 = dx + 50 + sin(explosion)*30;
xplode3 = dx - 50 - sin(explosion)*30;
xplode4 = dx - 50 - sin(explosion)*30;
}
else {
xplode1 = -10;
xplode2 = -10;
xplode3 = -10;
xplode4 = -10;
}
}
float targetY = mouseY;
float dy = targetY - py;
float ly = targetY - y;
if (abs(dy) > 1) {
my[which] += dy * easing;
y += dy * easing;
if (mousePressed && (mouseButton == LEFT)) {
yplode1 = dy + 50 + sin(explosion)*30;
yplode2 = dy - 50 - sin(explosion)*30;
yplode3 = dy - 50 - sin(explosion)*30;
yplode4 = dy + 50 + sin(explosion)*30;
}
else {
yplode1 = -10;
yplode2 = -10;
yplode3 = -10;
yplode4 = -10;
}
}
for(int i = 0;i<num;i++){
index = (which + 1 + i) % num;
ellipse(mx[index], my[index], i, i);
}
ellipse(xplode1, yplode1, 10, 10);
ellipse(xplode2, yplode2, 10, 10);
ellipse(xplode3, yplode3, 10, 10);
ellipse(xplode4, yplode4, 10, 10);
}
I would like to have a trail of ~60 and also have some easing for the whole thing. I have got each feature working individually but when I added in the fading. There is quite alot of unneeded variables, I have not cleaned the code at all, I have been working on it for hours, I know there is probably a very simple solution that I just cannot see at the moment. Any help would be great, thanks.
Don't bite more than you can chew, learn the little things. Vectors will make your code much less messy. You can find a detailed description of the Vector class on the Processing site. In this way, instead of having two different variables xplode1 and xplode2, there will be one Vector object that stores both values. You may find those concepts difficult at first, but they'll be invalubale tools for future sketches.
If you feel comfortable with basic concepts such as variables, functions, conditionals and loops, start studying OOP (Object Oriented Programming). Again, Daniel Shiffman comes to help.
Also, be more specific when asking on StackOverflow. Solving a problem often means finding the right question.
If it was the dist to a point it would be
dist(mouseX, mouseY, x, y)
for
point(x,y)
but how can I calculate dist() from the mouse's current position to
rectMode(CORNERS);
rect(x1,y2,x2,y2);
Thanks
Something like this should do it:
float distrect(float x, float y, float x1, float y1, float x2, float y2){
float dx1 = x - x1;
float dx2 = x - x2;
float dy1 = y - y1;
float dy2 = y - y2;
if (dx1*dx2 < 0) { // x is between x1 and x2
if (dy1*dy2 < 0) { // (x,y) is inside the rectangle
return min(min(abs(dx1), abs(dx2)),min(abs(dy1),abs(dy2)));
}
return min(abs(dy1),abs(dy2));
}
if (dy1*dy2 < 0) { // y is between y1 and y2
// we don't have to test for being inside the rectangle, it's already tested.
return min(abs(dx1),abs(dx2));
}
return min(min(dist(x,y,x1,y1),dist(x,y,x2,y2)),min(dist(x,y,x1,y2),dist(x,y,x2,y1)));
}
Basically, you need to figure out if the closes point is on one of the sides, or in the corner. This picture may help, it shows the distance of a point from a rectangle for different positions of the point:
Here's a somewhat interactive program which accomplishes what you're looking for. You can drop it into Processing and run it if you would like.
EDIT: Here's a screenshot:
// Declare vars.
int x_click = -20; // Initializes circle and point off-screen (drawn when draw executes)
int y_click = -20;
float temp = 0.0;
float min_dist = 0.0;
int x1, x2, x3, x4, y1, y2, y3, y4;
// Setup loop.
void setup() {
size(400, 400);
// Calculate the points of a 40x40 centered rectangle
x1 = width/2 - 20;
y1 = height/2 - 20;
x2 = width/2 + 20;
y2 = y1;
x3 = x1;
y3 = height/2 + 20;
x4 = x2;
y4 = y3;
}
// Draw loop.
void draw(){
background(255);
// Draws a purple rectangle in the center of the screen.
rectMode(CENTER);
fill(154, 102, 200);
rect(width/2, height/2, 40, 40);
// Draws an orange circle where the user last clicked.
ellipseMode(CENTER);
fill(204, 102, 0);
ellipse(x_click, y_click, 10, 10);
// Draws black point where the user last clicked.
fill(0);
point(x_click, y_click);
// Draws min dist onscreen.
textAlign(CENTER);
fill(0);
text("min dist = " + min_dist, width/2, height/2 + 150);
}
void mousePressed(){
x_click = mouseX;
y_click = mouseY;
// If the click isn't perpendicular to any side of the rectangle, the min dist is a corner.
if ( ((x_click <= x1) || (x_click >= x2)) && ((y_click <= y1) || (y_click >= y3)) ) {
min_dist = min(min(dist(x1,y1,x_click,y_click),dist(x2,y2,x_click,y_click)), min(dist(x3,y3,x_click,y_click),dist(x4,y4,x_click,y_click)));
} else if( (x_click > x1) && (x_click < x2) && ((y_click < y1) || (y_click > y3)) ) {
// outside of box, closer to top or bottom
min_dist = min(abs(y_click - y1), abs(y_click - y3));
} else if( (y_click > y1) && (y_click < y3) && ((x_click < x1) || (x_click > x2)) ) {
// outside of box, closer to right left
min_dist = min(abs(x_click - x1), abs(x_click - x2));
} else {
// inside of box, check against all boundaries
min_dist = min(min(abs(y_click - y1), abs(y_click - y3)),min(abs(x_click - x1), abs(x_click - x2)));
}
// Print to console for debugging.
//println("minimum distance = " + min_dist);
}
This is what I use. If you are only interested in the relative distance there is probably no need to take the square root which should make it slightly quicker.
- (NSInteger) distanceFromRect: (CGPoint) aPoint rect: (CGRect) aRect
{
NSInteger posX = aPoint.x;
NSInteger posY = aPoint.y;
NSInteger leftEdge = aRect.origin.x;
NSInteger rightEdge = aRect.origin.x + aRect.size.width;
NSInteger topEdge = aRect.origin.y;
NSInteger bottomEdge = aRect.origin.y + aRect.size.height;
NSInteger deltaX = 0;
NSInteger deltaY = 0;
if (posX < leftEdge) deltaX = leftEdge - posX;
else if (posX > rightEdge) deltaX = posX - rightEdge;
if (posY < topEdge) deltaY = topEdge - posY;
else if (posY > bottomEdge) deltaY = posY - bottomEdge;
NSInteger distance = sqrt(deltaX * deltaX + deltaY * deltaY);
return distance;
}
Does anyone have an algorithm for drawing an arrow in the middle of a given line. I have searched for google but haven't found any good implementation.
P.S. I really don't mind the language, but it would be great if it was Java, since it is the language I am using for this.
Thanks in advance.
Here's a function to draw an arrow with its head at a point p. You would set this to the midpoint of your line. dx and dy are the line direction, which is given by (x1 - x0, y1 - y0). This will give an arrow that is scaled to the line length. Normalize this direction if you want the arrow to always be the same size.
private static void DrawArrow(Graphics g, Pen pen, Point p, float dx, float dy)
{
const double cos = 0.866;
const double sin = 0.500;
PointF end1 = new PointF(
(float)(p.X + (dx * cos + dy * -sin)),
(float)(p.Y + (dx * sin + dy * cos)));
PointF end2 = new PointF(
(float)(p.X + (dx * cos + dy * sin)),
(float)(p.Y + (dx * -sin + dy * cos)));
g.DrawLine(pen, p, end1);
g.DrawLine(pen, p, end2);
}
Here's a method to add an arrow head to a line.
You just have to give it the coordinates of your arrow tip and tail.
private static void drawArrow(int tipX, int tailX, int tipY, int tailY, Graphics2D g)
{
int arrowLength = 7; //can be adjusted
int dx = tipX - tailX;
int dy = tipY - tailY;
double theta = Math.atan2(dy, dx);
double rad = Math.toRadians(35); //35 angle, can be adjusted
double x = tipX - arrowLength * Math.cos(theta + rad);
double y = tipY - arrowLength * Math.sin(theta + rad);
double phi2 = Math.toRadians(-35);//-35 angle, can be adjusted
double x2 = tipX - arrowLength * Math.cos(theta + phi2);
double y2 = tipY - arrowLength * Math.sin(theta + phi2);
int[] arrowYs = new int[3];
arrowYs[0] = tipY;
arrowYs[1] = (int) y;
arrowYs[2] = (int) y2;
int[] arrowXs = new int[3];
arrowXs[0] = tipX;
arrowXs[1] = (int) x;
arrowXs[2] = (int) x2;
g.fillPolygon(arrowXs, arrowYs, 3);
}