I'm trying to display the x location when y has the highest value. In the if statement i tried to compare the y value with 120 but it seems it's never true so it doesn't display my x location using text function. I've also tried to round up the y value but still the result is not the one i wanted. Can anyone help me ?
Regards Antmar.
float x = 0.0;
float y = 0.0;
void setup() {
background(150);
size(800,200);
smooth();
line(0,100,width,100);
}
void draw() {
//background(255);
x += 0.5;
y =map (sin(x/20),-1,1,80,120) ;
noStroke();
fill(#BBFFDD);
ellipse(x, y , 1, 1);
if ( y < 119 && y > 118.94) {
textSize(10);
text(x,x-10,y+20);
}
println("x =",x,"|","y =",y);
}
I think I've figured out what your issue is. When I ran your code, it printed out your x-value at several places, but it was not doing this printing every time. To fix this, I first incremented x by PI/4 instead of .5, to make it more likely to be close to 120. Then, I looked at the values of y, and the highest one was just a shade under 120. To print out the x-value at that point, I made the if-condition the following, as to only catch that one y-value. I also added another if-condition to get the value of x at the local maximums of this sin function:
if ( y >= 100 + 19.999) {
textSize(10);
text(x,x-10,y+20);
}else if(y <= 100 - 19.999){
textSize(10);
text(x,x+10,y-10);
}
Edit: After looking at the values of x and y, I found that incrementing x by PI/4 leads to y having values of exactly 120 and 80 as minimums and maximums, so you can just check for those values instead, like so:
if (y == 120) {
textSize(10);
text(x,x-10,y+20);
}else if(y == 80){
textSize(10);
text(x,x+10,y-10);
}
Related
I'm currently trying to make a basic platformer game, I'm trying to use a dist function to detect if the player is touching the ground or not. I need to just detect the Y coors of the ground and player. Any suggestions?
let x2,y2;
let x,y;
function setup() {
createCanvas(400, 400);
x=200;
y=200;
x2=200;
y2=200;
}
function draw() {
background(220);
ellipse(x,y,20,20)
rect(x2-300,y2+150,500,200);
if(dist(x,x2,y2,y)==140){
y=y+0;
}else{
y=y+5;
}
if(keyIsPressed&&keyCode === LEFT_ARROW){
x=x-2;
}
if(keyIsPressed&&keyCode === RIGHT_ARROW){
x=x+2;
}
}
You can use a more permissive threshold condition like a range instead of the distance being exactly 140 (e.g. >= 140).
Here's a version of your code with this minor tweak added:
let x2, y2;
let x, y;
function setup() {
createCanvas(400, 400);
x = 200;
y = 200;
x2 = 200;
y2 = 200;
}
function draw() {
background(220);
ellipse(x, y, 20, 20);
rect(x2 - 300, y2 + 150, 500, 200);
if (dist(x, x2, y2, y) >= 140) {
y = y + 0;
} else {
y = y + 5;
}
if (keyIsPressed && keyCode === LEFT_ARROW) {
x = x - 2;
}
if (keyIsPressed && keyCode === RIGHT_ARROW) {
x = x + 2;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
I do have a few more suggestions:
for an initial game prototype this ok, but for a more complex game using dist() (which uses sqrt()) behind the scenes could get computationally expensive. Since you only need to compare y coordinates you could implement this difference directly (if(y - y2 >= 140)).
additionally y = y + 0 doesn't add anything useful, but it does
read and write the y variable which again, takes a bit of time.
This won't impact performance that much and you should always
optimise at the end if you need to and not sacrifice code
readability, however less code means less to read and maintain in the
future. The more complex the programs you write will get the more
time you'll spend reading (and understanding) code rather than
writing it.
on above note I recommend also formatting code (in the
p5.js web editor Edit > Tidy Code does this for you, otherwise
there could be a similar option in your current code editor).
be kind to your future self and add code comments to explain what/why/how you did things. It will help a lot (imagine having to revisit your code after a few weeks/months and not remembering why you wrote things in a certain way).
Here's a modified version of your code with a few of the suggestions above:
let x2, y2;
let x, y;
function setup() {
createCanvas(400, 400);
x = 200;
y = 200;
x2 = 200;
y2 = 200;
}
function draw() {
background(220);
ellipse(x, y, 20, 20);
rect(x2 - 300, y2 + 150, 500, 200);
if(y - y2 < 140) {
y = y + 5;
}
if (keyIsPressed && keyCode === LEFT_ARROW) {
x = x - 2;
}
if (keyIsPressed && keyCode === RIGHT_ARROW) {
x = x + 2;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Have fun learning !
i have a task to make a pattern of circles and squares as described on photo, and i need to animate it so that all objects smoothly increase to four times the size and then shrink back to their original size and this is repeated. i tried but i cant understand problem
{
size(500,500);
background(#A5A3A3);
noFill();
rectMode(CENTER);
ellipseMode(CENTER);
}
void pattern(int a, int b)
{
boolean isShrinking = false;
for(int x = 0; x <= width; x += a){
for(int y = 0; y <= height; y += a){
stroke(#1B08FF);
ellipse(x,y,a,a);
stroke(#FF0000);
rect(x,y,a,a);
stroke(#0BFF00);
ellipse(x+25,y+25,a/2,a/2);
if (isShrinking){a -= b;}
else {a += b;}
if (a == 50 || a == 200){
isShrinking = !isShrinking ; }
}
}
}
void draw()
{
pattern(50,1);
}
this is what pattern need to look like
Great that you've posted your attempt.
From what you presented I can't understand the problem either. If this is an assignment, perhaps try to get more clarifications ?
If you comment you the isShrinking part of the code indeed you have an drawing similar to image you posted.
animate it so that all objects smoothly increase to four times the size and then shrink back to their original size and this is repeated
Does that simply mean scaling the whole pattern ?
If so, you can make use of the sine function (sin()) and the map() function to achieve that:
sin(), as the reference mentions, returns a value between -1 and 1 when you pass it an angle between 0 and 2 * PI (because in Processing trig. functions use radians not degrees for angles)
You can use frameCount divided by a fractional value to mimic an even increasing angle. (Even if you go around the circle multiple times (angle > 2 * PI), sin() will still return a value between -1 and 1)
map() takes a single value from one number range and maps it to another. (In your case from sin()'s result (-1,1) to the scale range (1,4)
Here's a tweaked version of your code with the above notes:
void setup()
{
size(500, 500, FX2D);
background(#A5A3A3);
noFill();
rectMode(CENTER);
ellipseMode(CENTER);
}
void pattern(int a)
{
for (int x = 0; x <= width; x += a) {
for (int y = 0; y <= height; y += a) {
stroke(#1B08FF);
ellipse(x, y, a, a);
stroke(#FF0000);
rect(x, y, a, a);
stroke(#0BFF00);
ellipse(x+25, y+25, a/2, a/2);
}
}
}
void draw()
{
// clear frame (previous drawings)
background(255);
// use the frame number as if it's an angle
float angleInRadians = frameCount * .01;
// map the sin of the frame based angle to the scale range
float sinAsScale = map(sin(angleInRadians), -1, 1, 1, 4);
// apply the scale
scale(sinAsScale);
// render the pattern (at current scale)
pattern(50);
}
(I've chosen the FX2D renderer because it's smoother in this case.
Additionally I advise in the future formatting the code. It makes it so much easier to read and it barely takes any effort (press Ctrl+T). On the long run you'll read code more than you'll write it, especially on large programs and heaving code that's easy to read will save you plenty of time and potentially headaches.)
When running this code, the rectangle 'moves' from left to right.
How does the code x = x + 1 generates this?
How does it keep creating rectangles one pixel further on the x-axis?
void setup() {
size(400, 400);
stroke(255);
background(192, 64, 0);
}
int hoogte = 50;
int breedte = 50;
int x = 50;
void draw () {
rect(x,100, breedte, hoogte);
stroke(181);
x = x + 1;
}
Result of running the code
Keep in mind that the draw() function is called 60 times per second.
The x = x + 1 line adds one to the x variable. Since you're drawing your rectangle based on the x variable, the rectangle moves across the screen over time.
Shameless self-promotion: here is a tutorial explaining animation in Processing.
I am currently going through Daniel Shiffman's 'The Nature Of Code', and have been playing around with one of the first exercises - a simple 'RandomWalker()'. I have implemented similar things in Java & had no trouble, however for some reason my walker always seems to go in more or less the same direction:
RandomWalker
This happens 100% of the time. Here is my code:
class Walker
{
int x;
int y;
// Constructor
Walker()
{
x = width / 2;
y = height / 2;
}
void display()
{
stroke(0); // Colour
point(x, y); // Colours one pixel in
}
void step()
{
float stepX;
float stepY;
stepX = random(-1, 1);
stepY = random(-1, 1);
x += stepX;
y += stepY;
}
}
Walker w;
void setup()
{
size(640, 360);
w = new Walker();
background(255);
}
void draw()
{
w.step();
w.display();
}
Is this some artefact of the random function? My first thought is that it's something to do with the pseudorandom nature of the function but the textbook specifically states that this should not be noticeable, and yet this happens every single time. I was wondering if maybe there's something wrong with my code?
Thanks in advance.
Your x and y variables are both int types. That means that they don't have a decimal part, so any time you add or subtract from them, they are truncated. Here are some examples:
int x = 1;
x = x + .5;
//1.5 is truncated, and x stays 1
int x = 1;
x = x - .5;
//.5 is truncated, and x becomes 0
This is why you see your x and y variables only decreasing. To fix this, just change x and y to float types, so they keep track of the decimals.
If you really need x and y to be int values, then you need stepX and stepY to also be int values:
int stepX;
int stepY;
stepX = (int)random(-5, 5);
stepY = (int)random(-5, 5);
x += stepX;
y += stepY;
But you probably just want to store x and y as float values.
PS: I love random walkers!
I'm having issues understanding how the error accumulation part works in Bresenham's line drawing algorithm.
Say we have x1 and x2. Let's assume that x1 < x2, y1 < y2, and (x2 - x1) >= (y2 - y1) for simplicity:
Let's start with the naive way of drawing a line. It would look something like:
void DrawLine(int x1, int y1, int x2, int y2)
{
float y = y1 + 0.5f;
float slope = (float)(y2 - y1) / (x2 - x1);
for (int x = x1; x <= x2; ++x)
{
PlotPixel(x, (int)y);
y += slope;
}
}
Let's make it more Bresenham'ish, and separate the integer and floating-point parts of y:
void DrawLine(int x1, int y1, int x2, int y2)
{
int yi = y1;
float yf = 0.5f;
float slope = (float)(y2 - y1) / (x2 - x1);
for (int x = x1; x <= x2; ++x)
{
PlotPixel(x, yi);
yf += slope;
if (yf >= 1.0f)
{
yf -= 1.0f;
++yi;
}
}
}
At this point we could multiply yf and slope by 2 * (x2 - x1) to make them integers, no more floats. I understand that.
The part I don't fully understand, is this:
if (yf >= 1.0f)
{
yf -= 1.0f;
++yi;
}
How does that actually work? why are we comparing against 1.0 and then decrementing by it?
I know that the basic question of Bresenham is: If we're currently at pixel x, y and we want to draw the next one, should we pick x + 1, y or x + 1, y + 1? - I just don't understand how that check is helping us answer this question.
Some people call it error term, some call it threshold, I just don't get what it represents.
Any explanations is appreciated,
thanks.
Bresenham's line rasterization algorithm performs all the calculations in integer arithmetic. In your code you are using float types and you shouldn't.
First consider that you know two pixels that are on the line. The starting pixel and the end pixel. What the algorithm calculates are the pixels that approximate the line such that the rasterized line starts and stops on the two input pixels.
Second, all lines drawn are reflections of lines with slope between 0 and 0.5. There is a special case for vertical lines. If your algorithm is correct for this input, then you need to initialize the starting state of the rasterizer to correctly rasterize a line: start pixel (x, y), ∆x, ∆y, and D the decision variable.
Since you can assume all lines are drawn from left to right, have positive slope equal to or less than 0.5, the problem boils down to:
is the next rasterized pixel to the current pixels right or to the right and up one pixel.
You can make this decision by keeping track of how much your rasterized line deviates from the true line. To do so, the line equation is re-written into an implicit function, F(x, y) = ∆yx - ∆xy + ∆xb = 0 and you repeatedly evaluate it F(x + 1 y + 0.5). Since that requires floating point math, you focus on identifying if you are on, above, or below the true line. Therefore, F(x + 1 y + 0.5) = ∆y - 0.5∆x and multiplying by two 2 * F(x + 1 y + 0.5) = 2∆y - ∆x. That's the first decision, if the result is less than zero, add one to x but zero to y.
The second decision and subsequent decisions follow similarly and the error is accumulated. A decision variable D is initialized to 2∆y - ∆x. If D < 0, then D = D + 2∆y; else y = y + 1 and D = D + 2(∆y - ∆x). The x variable is always incremented.
Jim Arvo had a great explanation of Bresenham's algorithm.
In your implementation yf is a 0.5 + distance between real floating-point Y coordinate and drawn (integral) Y coordinate. This distance is the current error of your drawing. You want to keep the error within at most half-of-pixel between real line and drawn line (-0.5..+0.5), so your yf which is 0.5+error should be between 0 and 1. When it exceeds one, you just increase your drawn Y coordinate (yi) by one and you need to decrease an error by one. Let's take an example:
slope = 0.3;
x = 0; yf = 0.5; y = 0; // start drawing: no error
x = 1; yf = 0.8; y = 0; // draw second point at (1, 0); error is +0.3
x = 2; yf = 1.1; y = 0; // error is too big (+0.6): increase y
yf = 0.1; y = 1; // now error is -0.4; draw point at (2, 1)
x = 3; yf = 0.4; y = 1; // draw at (3, 1); error is -0.1
x = 4; yf = 0.7; y = 1; // draw at (4, 1); error is +0.2
x = 5; yf = 1.0; y = 1; // error is too big (+0.5); increase y
yf = 0.0; y = 2; // now error is -0.5; draw point at (5, 2)
And so on.