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.
Related
I'm trying to make the lines around the circle in void explosion to appear when tailY == upHeight. I don't know where to place explosion. Can someone help me with this please? The rocket needs to explode when it reaches certain height.
void draw() {
background(0);
drawRocket();
if (tailY == upHeight) {
explosion();
}
}
void explosion() {
noFill();
noStroke();
circle(tailX, tailY, circleSize);
for (int i = 0; i < a; i++) {
float angle;
if (a*i==0)
angle = radians(360.0);
else
angle = radians(360.0/a*i);
float x1 = tailX + circleSize/2 * cos(angle);
float y1 = tailY + circleSize/2 * sin(angle);
float x2 = tailX + (circleSize+10) * cos(angle);
float y2 = tailY + (circleSize+10) * sin(angle);
stroke(red, green, blue);
line(x1, y1, x2, y2);
}
}
You're so close, literally and figuratively :) !
The issue is that you're checking if two floating points value match exactly: if (tailY == upHeight).
If you add println(tailY, upHeight); right before this condition you'll see values get really close, never match, then diverge.
With floating point number it's safer to compare with a bit of tolerance (e.g. if tailY is close to upHeight (with a bit of +/- tolerance).
In you're case, since you only want to see the explosion past a threshold(upHeight) you can loosen the condition (e.g. <=) to:
if (tailY <= upHeight) {
explosion();
}
I just started to learn processing and I have a few problems that I couldn't solve. I hope someone could help me. This should draw lines where i could choose the starting and finishing points with mousePressed(), but I failed before trying implementing that.
//int x1, x2, y1, y2;
void setup() {
size(640, 480);
}
void draw() {
midpoint(0, 0, 100, 100);
}
//void mousePressed() {
// pmouseX =x1;
// pmouseY =y1;
// mouseX =x2;
// mouseY =y2;
//}
void midpoint(int x1, int y1, int x2, int y2) {
int dx, dy, d, x, y;
dx = x2-x1;
dy = y2-y1;
d = 2*dy-dx;
x = x1;
y = y1;
for (int i = 1; i <dx; i++) {
point(x, y);
if (d>0) {
y++;
d+=2*(dy-dx);
} else {
d+=2*dy;
}
x++;
}
}
My problem is that it will not always draw the line.
e.g.
midpoint(0,0,100,100);
it will draw it
midpoint(100,100,0,0);
it draws nothing.
It should draw the same line if I exchange the points coordinates, or draw a single point if the coordinates are the same.
In Bresenham's midpoint line algorithm you have to be careful with the gradient of the line drawn, the base algorithm you described only works for gradients between 0 and 1. In order to deal with gradients that are steeper (m > 1 or m < -1), you have to switch the roles of the x and y values, therefore you have to step in y and then calculate x. Also to deal with negative steps just switch the point order.
void midpoint(int x1, int y1, int x2, int y2) {
// Is gradient of line greater than 1
boolean steep = abs(y2-y1) > abs(x2-x1);
int temp;
if (steep) { // If gradient > 1
// Swap roles of x and y components to step in y instead
temp = y1;
y1 = x1;
x1 = temp;
temp = y2;
y2 = x2;
x2 = temp;
}
if (x2 < x1) {
// Swap points such that step in x is positive
temp = x1;
x1 = x2;
x2 = temp;
temp = y1;
y1 = y2;
y2 = temp;
}
// Change in x and y which are now both positive
int dx = x2 - x1;
int dy = abs(y2 - y1);
// Step in y
int sy = y2 > y1 ? 1 : -1;
int y = y1;
// Decision variable
int d = 2*dy-dx;
// Small step in x
for (int x=x1; x<=x2; x++) {
// Depending on gradient plot x and y
if (steep) {
point(y, x);
} else {
point(x, y);
}
// Update decision parameter
if (d>0) {
y += sy;
d+=2*(dy-dx);
}else{
d+=2*dy;
}
}
}
Actually I'm trying to convert this JavaScript code to processing code. But got stuck.
var leftToRight = Math.random() >= 0.5;
if(leftToRight) {
context.moveTo(x, y);
context.lineTo(x + width, y + height);
} else {
context.moveTo(x + width, y);
context.lineTo(x, y + height);
}
context.stroke();
This is what I came up with and I know its fundamentally wrong but there must be a way. If anyone can at least point me in the right direction it would be great.
void draw() {
line(x1, y1, x2, y2);
for(int i = 0; i < 1000; i++) {
if(x1 == 0) {
x1 = width;
y1 = 0;
x2 = 0;
y2 = height;
line(x1, y1, x2, y2);
} else if(x1 == width) {
x1 = 0;
y1 = 0;
x2 = width;
y2 = height;
line(x1, y1, x2, y2);
}
}
Due to the nature of your question, it was difficult to assume what exactly you needed answered. For simplicity's sake, I assume you want the Java code converted to Processing. Hence, I will be ignoring what you wrote in your second code snippet.
The Java code essentially does the following:
Generates a random number from 0.0 to 1.0
Chooses one output based on whether the number is greater than 0.5:
Creates a line from (x, y) to (x + width, y + height) or
Creates a line from (x + width, y) to (x, y + height).
Here's a sample of Processing code that may assist you in this. This code is very close to that of the Java snippet you provided, as that is what you asked for.
int x = 0, y = 0;
if(random(0, 1) > 0.5) line(x, y, x + width, y + height);
else line(x + width, y, x, y + height);
When run, the canvas will show either this:
or this:
I hope this helps.
On the 2D grid, there is a cartesian coordinate C(Cx,Cy) which is a center of square and it has 'b' of radius.
And there are two points P1(x1,y1), P2(x2,y2). When I connect P1 with P2 directly by line, there should be a straight line.
I wanna make the pseudo code that checking whether the straight line between P1 and P2 is on the square area or not.
The argument would be center point and two different points and radius.
Square center: (Cx,Cy)
Two points: P1(x1,y1), P2(x2,y2)
Radius: 'b'
function Straight ((x1,y1),(x2,y2),(Cx,Cy),b)
If the straight line is not on the square area, it should return true, if it is on the square area, it should return false.
You can convert this problem (by projecting the coordinates) to a square at (0, 0) with "radius" 1.
For determining whether the line segment (p1, p2) crosses the top side of the square, you can first test these conditions:
(y2 - 1) * (y2 - 1) > 0. If this is true, it means that the line segment is completely above the top of the square, or completely below it.
y1 = y2. If this is true, the line segment is parallel with the square.
In all other cases, the x-coordinate of the intersection point is:
x = x1 - y1 * (x2 - x1) / (y2 - y1)
If this x is not in the range [-1, 1], the line segment does not intersect the top of the square.
A similar operation can be done for the three other sides.
If any of them gives an intersection coordinate in the range [-1, 1], the function straight should return true, and false otherwise.
Here is an interactive JavaScript implementation with which you can draw a line segment (by "dragging" the mouse) near a square. The square will highlight when the call to straight returns true:
function intersectionWithXaxis(x1, y1, x2, y2) {
if (y1 * y2 > 0 || y1 === y2) return Infinity; // No intersection
return x1 - y1 * (x2 - x1) / (y2 - y1); // x-coordinate of intersection
}
function straight(x1, y1, x2, y2, cx, cy, b) {
// Project the coordinates so the square is at (0, 0) with "radius" 1
x1 = (x1-cx)/b;
y1 = (y1-cy)/b;
x2 = (x2-cx)/b;
y2 = (y2-cy)/b;
let z;
// Get intersections with top, bottom, left and right side of box:
z = intersectionWithXaxis(x1, y1-1, x2, y2-1);
if (Math.abs(z) <= 1) return true;
z = intersectionWithXaxis(x1, y1+1, x2, y2+1);
if (Math.abs(z) <= 1) return true;
// We can use the same function for vertical line intersections by swapping x and y
z = intersectionWithXaxis(y1, x1-1, y2, x2-1);
if (Math.abs(z) <= 1) return true;
z = intersectionWithXaxis(y1, x1+1, y2, x2+1);
if (Math.abs(z) <= 1) return true;
return false;
}
let cx = 100;
let cy = 60;
let b = 30;
let x1, y1, x2, y2;
// I/O handling
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "yellow";
let isMouseDown = false;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.rect(cx-b, cy-b, 2*b, 2*b);
ctx.stroke();
if (!isMouseDown) return;
// Call the main function. If true, highlight the square
if (straight(x1, y1, x2, y2, cx, cy, b)) ctx.fill();
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
canvas.addEventListener("mousedown", function(e) {
x1 = e.clientX - this.offsetLeft;
y1 = e.clientY - this.offsetTop;
isMouseDown = true;
});
canvas.addEventListener("mousemove", function(e) {
if (!isMouseDown) return;
x2 = e.clientX - this.offsetLeft;
y2 = e.clientY - this.offsetTop;
draw();
});
canvas.addEventListener("mouseup", function(e) {
isMouseDown = false;
});
draw();
<canvas width="400" height="180"></canvas>
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.