Something is wrong with my code in processing - processing

I used codepen to write my code in and then I took it into processing and now there are many errors. it was alright in codepen but something happened in processing. This is my first time using processing so the language reference is a bit different. Could someone gear me in the right direction?
void draw() {
// Call the variableEllipse() method and send it the
// parameters for the current mouse position
// and the previous mouse position
ellipse(mouseX, mouseY, pmouseX, pmouseY);
}
// The simple method variableEllipse() was created specifically
// for this program. It calculates the speed of the mouse
// and draws a small ellipse if the mouse is moving slowly
// and draws a large ellipse if the mouse is moving quickly
void ellipse(x, y, px, py) {
let speed = abs(x - px) + abs(y - py);
stroke(speed);
ellipse(x, y, speed, speed);
}
//https://p5js.org/examples/drawing-patterns.html
void setup() {
size(500, 500);
background(50);
let num = 20;
let spanx = width / num;
let spany = height / num;
for (let i = 1; i < num; i++) {
for (let j = 1; j < num; j++) {
stroke(255, 255, 255);
if (random(1) < 0.8) {
line(width / 2, height/2, i * spanx, j * spany);
frameRate(35);
}
stroke(255, 0, 0);
if (random(1) < 0.3) {
line(width / 1, height, i * spanx, j * spany);
}
//red line
stroke(0, 0, 255);
if (random(1) < 0.5) {
line(6, height, i * spanx, j * spany);
//line(1, height / 2, i * spanx, j * spany);
}
stroke(0, 128, 0);
strokeWeight(1);
if (random(1) < 0.5) {
line(7, 3, i * spanx, j * spany);
}
stroke(255, 255, 0);
if (random(1) < 0.9) {
line(width, 9, i * spanx, i * spany);
//line(width / 2, height, i * spanx, i * spany);
//line(width, height / 2, i * spanx, i * spany);
//line(width / 2, 1, i * spanx, i * spany);
}
}
}
}

On CodePen you would have been using a JavaScript flavor of Processing (probably p5.js). The desktop editor defaults to Java.
Your code looks like a mix of the two.
You can add a mode for p5.js to the desktop editor if you want to continue working in JavaScript. Otherwise, you'll need to finish converting the rest of your syntax to Java.

Related

processing collision test return false at the beginning

I am doing the collision test for the programme, and I tried to insert the test into draw() and I'm expecting it to display "GameOver" and no further events will result any change.
float x;
float y;
float w;
float h;
float xPed;
float yPed;
float yPedc;
float objectX;
float objectY;
float objectWidth;
float objectHeight;
float triangleWidth;
float triangleHeight;
float dia;
int speed = 2;
boolean gameOver;
int N_LANES = 1;
void setup() {
size(1200, 400);
background(255);
x = width / 60;
y = height / 40;
w = width / 80;
xPed = width / 2;
triangleWidth = height / 4;
triangleHeight = 2.5 * w;
yPed = height - 3 * w;
yPedc = 2.5 * w / 2;
dia = w / 2;
h = w / 2;
objectX = x + 2 * w;
objectY = y + 5 * h;
objectWidth = 4 * w;
objectHeight = 10 * h;
gameOver = false;
}
void draw() {
//reset background
background(255);
line(0, height/4, width, height/4);
vehicle();
pedestrian();
// collision detect
if (gameOver == true) {
textSize(100);
fill(255, 0, 0);
text("Game Over", width / 3, height / 2);
}
}
void vehicle() {
//moving vehicle
x += speed;
// reset vehicle
noFill();
if (x > width) {
x = 0;
} else if (x < 0) {
x = width;
}
for (int i = 0; i < N_LANES; i++) {
//head of vehicle
fill(0, 194, 0, 50);
rect(x, y, w, h);
rect(x + 3 * w, y, w, h);
rect(x, y + h, 4 * w, 4 *h);
//eyes of vehicle
fill(0);
rect(x + w, 3 * y, w * 0.85, h);
rect(x + 3 * w, 3 * y, w * 0.85, h);
//body of vehicle
fill(0, 240, 0, 80);
rect(x + 1.5 * w, 6.3 * h, 1.5 * w, 3 *h );
//left arm
line(x + 1.5 *w, 6.3 * h, x + 0.5 * w, 7.3 * h);
//right arm
line(x + 3 * w, 6.3 * h, x + 4 * w, 7.3 * h);
//left leg
line(x + 1.5 * w, 9.3 * h, x + w, 11.3 * h);
//right leg
line(x + 3 * w, 9.3 * h, x + 3.5 * w, 11.3 * h);
}
}
// draw pedestrian
void pedestrian() {
fill(255, 140, 0, 70);
//body of pedestrian
triangle(xPed, yPed, xPed - triangleWidth / 2, yPed + 2.5 * w, xPed + triangleWidth / 2, yPed + 2.5 * w);
fill(0);
circle(xPed + triangleWidth / 4, yPed, dia);
circle(xPed - triangleWidth / 4, yPed, dia);
fill(255, 165, 0);
ellipse(xPed, yPed + w, 1.5 * dia, 3 * dia);
}
// arrow key moving
void keyPressed() {
if (gameOver != true) {
if (key == CODED) {
if (keyCode == UP) {
yPed -= height / 4;
if (yPed <= 0) {
yPed = height - 3 * w;
}
}
if (keyCode == DOWN) {
yPed += height / 4;
if (yPed > height) {
yPed = height - 3 * w;
}
}
if (keyCode==LEFT) {
xPed -= height / 4;
if (xPed < 0 + triangleWidth / 2) {
xPed = width / 2;
}
}
if (keyCode==RIGHT) {
xPed += height / 4;
if (xPed > width - triangleWidth / 2) {
xPed = width / 2;
}
}
}
}
}
boolean gameOver() {
// optional visualise collision objects
rect(objectX, objectY, objectWidth, objectHeight);
rect(xPed, yPed, triangleWidth, triangleHeight);
// x axis
float distX = abs( (objectX + objectWidth / 2) - (xPed + triangleWidth / 2) );
// y axis
float distY = abs( (objectY + objectHeight / 2) - (yPedc + triangleHeight / 2) );
// half combined x distance
float combinedHalfWidth = ( (objectWidth / 2) + (triangleWidth / 2) );
// half combined y distance
float combinedHalfHeight = ( (objectHeight / 2) + (triangleHeight / 2) );
// check collision
if (distX < combinedHalfWidth) {
if (distY < combinedHalfHeight) {
return true;
}
}
return false;
}
I tried to insert the gameOver boolean into draw and it returns the same value everytime.
Just wondering what the logical problem or the coding problem is.
As Rabbid76 mentions, you should format the code correctly first.
Let's assume the code been copied from a pdf with code snippets and that's how formatting got messed up.
The code still has a few glaring bugs:
confusingly you're using both a boolean variable gameOver and a boolean function gameOver() and the variable isn't always updated. (In fact gameOver is only set once in setup() and gameOver() which actually does the collision detection is never called). I recommend either update the boolean variable, or simpler yet, just call gameOver() to compute the collision as needed. This is one of the reasons your code won't behave as you expect.
You're checking collisions between two objects: the vehicle and the pedestrian. However, there are 3 sets of coordinates: x, y, xPed, objectX, objectY. When rendering in draw, the vehicle uses x,y, however, when checking for collisions, gameOver() uses objectX, objectY (which don't match and aren't updated). This is the other reason you're collisions don't behave as expected.
aside from the question you've asked, N_LANES is used in a for loop, but never declared. Even if I declare it, the for loop uses the exact same x,y coordinates, making the for loop redundant.
Here's a formatted version of your code with extra bounding boxes highlighting what the collision function is checking against (and commenting a few unused variables):
float x;
float y;
float w;
float h;
float xPed;
float yPed;
//float yPedc;
float objectX;
float objectY;
float objectWidth;
float objectHeight;
float triangleWidth;
float triangleHeight;
float dia;
int speed = 2;
//boolean gameOver;
int N_LANES = 1;
void setup() {
size(1200, 400);
background(255);
x = width / 60;
y = height / 40;
w = width / 80;
xPed = width / 2;
triangleWidth = height / 4;
triangleHeight = 2.5 * w;
yPed = height - 3 * w;
//yPedc = 2.5 * w / 2;
dia = w / 2;
h = w / 2;
objectX = x + 2 * w;
objectY = y + 5 * h;
objectWidth = 4 * w;
objectHeight = 10 * h;
//gameOver = false;
}
void draw() {
//reset background
background(255);
line(0, height/4, width, height/4);
vehicle();
pedestrian();
// collision detect
if (gameOver() == true) {
textSize(100);
fill(255, 0, 0);
text("Game Over", width / 3, height / 2);
}
}
void vehicle() {
//moving vehicle
x += speed;
// reset vehicle
noFill();
if (x > width) {
x = 0;
} else if (x < 0) {
x = width;
}
for (int i = 0; i < N_LANES; i++) {
//head of vehicle
fill(0, 194, 0, 50);
rect(x, y, w, h);
rect(x + 3 * w, y, w, h);
rect(x, y + h, 4 * w, 4 *h);
//eyes of vehicle
fill(0);
rect(x + w, 3 * y, w * 0.85, h);
rect(x + 3 * w, 3 * y, w * 0.85, h);
//body of vehicle
fill(0, 240, 0, 80);
rect(x + 1.5 * w, 6.3 * h, 1.5 * w, 3 *h );
//left arm
line(x + 1.5 *w, 6.3 * h, x + 0.5 * w, 7.3 * h);
//right arm
line(x + 3 * w, 6.3 * h, x + 4 * w, 7.3 * h);
//left leg
line(x + 1.5 * w, 9.3 * h, x + w, 11.3 * h);
//right leg
line(x + 3 * w, 9.3 * h, x + 3.5 * w, 11.3 * h);
}
}
// draw pedestrian
void pedestrian() {
fill(255, 140, 0, 70);
//body of pedestrian
triangle(xPed, yPed, xPed - triangleWidth / 2, yPed + 2.5 * w, xPed + triangleWidth / 2, yPed + 2.5 * w);
fill(0);
circle(xPed + triangleWidth / 4, yPed, dia);
circle(xPed - triangleWidth / 4, yPed, dia);
fill(255, 165, 0);
ellipse(xPed, yPed + w, 1.5 * dia, 3 * dia);
// visualise bounding box
//fill(255, 140, 0, 70);
//rect(xPed - triangleWidth / 2, yPed, triangleWidth, triangleHeight);
}
// arrow key moving
void keyPressed() {
if (gameOver() != true) {
if (key == CODED) {
if (keyCode == UP) {
yPed -= height / 4;
if (yPed <= 0) {
yPed = height - 3 * w;
}
}
if (keyCode == DOWN) {
yPed += height / 4;
if (yPed > height) {
yPed = height - 3 * w;
}
}
if (keyCode==LEFT) {
xPed -= height / 4;
if (xPed < 0 + triangleWidth / 2) {
xPed = width / 2;
}
}
if (keyCode==RIGHT) {
xPed += height / 4;
if (xPed > width - triangleWidth / 2) {
xPed = width / 2;
}
}
}
}
}
boolean gameOver() {
// optional visualise collision objects
rect(objectX, objectY, objectWidth, objectHeight);
rect(xPed, yPed, triangleWidth, triangleHeight);
// x axis
float distX = abs( (objectX + objectWidth / 2) - (xPed + triangleWidth / 2) );
// y axis
float distY = abs( (objectY + objectHeight / 2) - (yPed + triangleHeight / 2) );
// half combined x distance
float combinedHalfWidth = ( (objectWidth / 2) + (triangleWidth / 2) );
// half combined y distance
float combinedHalfHeight = ( (objectHeight / 2) + (triangleHeight / 2) );
// check collision
if (distX < combinedHalfWidth) {
if (distY < combinedHalfHeight) {
return true;
}
}
return false;
}
Here's a version of the code with a few of the 3 notes above applied, somewhat resolving the collision and gameOver state issue:
float x;
float y;
float w;
float h;
float xPed;
float yPed;
float objectWidth;
float objectHeight;
float triangleWidth;
float triangleHeight;
float dia;
int speed = 2;
void setup() {
size(1200, 400);
background(255);
x = width / 60;
y = height / 40;
w = width / 80;
xPed = width / 2;
triangleWidth = height / 4;
triangleHeight = 2.5 * w;
yPed = height - 3 * w;
dia = w / 2;
h = w / 2;
objectWidth = 4 * w;
objectHeight = 10 * h;
}
void draw() {
//reset background
background(255);
line(0, height/4, width, height/4);
vehicle();
pedestrian();
// collision detect
if (gameOver()) {
textSize(100);
fill(255, 0, 0);
text("Game Over", width / 3, height / 2);
}
}
void vehicle() {
//moving vehicle
x += speed;
// reset vehicle
noFill();
if (x > width) {
x = 0;
} else if (x < 0) {
x = width;
}
//head of vehicle
fill(0, 194, 0, 50);
rect(x, y, w, h);
rect(x + 3 * w, y, w, h);
rect(x, y + h, 4 * w, 4 *h);
//eyes of vehicle
fill(0);
rect(x + w, 3 * y, w * 0.85, h);
rect(x + 3 * w, 3 * y, w * 0.85, h);
//body of vehicle
fill(0, 240, 0, 80);
rect(x + 1.5 * w, 6.3 * h, 1.5 * w, 3 *h );
//left arm
line(x + 1.5 *w, 6.3 * h, x + 0.5 * w, 7.3 * h);
//right arm
line(x + 3 * w, 6.3 * h, x + 4 * w, 7.3 * h);
//left leg
line(x + 1.5 * w, 9.3 * h, x + w, 11.3 * h);
//right leg
line(x + 3 * w, 9.3 * h, x + 3.5 * w, 11.3 * h);
}
// draw pedestrian
void pedestrian() {
fill(255, 140, 0, 70);
//body of pedestrian
triangle(xPed, yPed, xPed - triangleWidth / 2, yPed + 2.5 * w, xPed + triangleWidth / 2, yPed + 2.5 * w);
fill(0);
circle(xPed + triangleWidth / 4, yPed, dia);
circle(xPed - triangleWidth / 4, yPed, dia);
fill(255, 165, 0);
ellipse(xPed, yPed + w, 1.5 * dia, 3 * dia);
// visualise bounding box
//fill(255, 140, 0, 70);
//rect(xPed - triangleWidth / 2, yPed, triangleWidth, triangleHeight);
}
// arrow key moving
void keyPressed() {
if (!gameOver()) {
if (key == CODED) {
if (keyCode == UP) {
yPed -= height / 4;
if (yPed <= 0) {
yPed = height - 3 * w;
}
}
if (keyCode == DOWN) {
yPed += height / 4;
if (yPed > height) {
yPed = height - 3 * w;
}
}
if (keyCode==LEFT) {
xPed -= height / 4;
if (xPed < 0 + triangleWidth / 2) {
xPed = width / 2;
}
}
if (keyCode==RIGHT) {
xPed += height / 4;
if (xPed > width - triangleWidth / 2) {
xPed = width / 2;
}
}
}
}
}
boolean gameOver() {
// optional visualise collision objects
rect(x, y, objectWidth, objectHeight);
rect(xPed, yPed, triangleWidth, triangleHeight);
// x axis
float distX = abs( (x + objectWidth / 2) - (xPed + triangleWidth / 2) );
// y axis
float distY = abs( (y + objectHeight / 2) - (yPed + triangleHeight / 2) );
// half combined x distance
float combinedHalfWidth = ( (objectWidth / 2) + (triangleWidth / 2) );
// half combined y distance
float combinedHalfHeight = ( (objectHeight / 2) + (triangleHeight / 2) );
// check collision
if (distX < combinedHalfWidth) {
if (distY < combinedHalfHeight) {
return true;
}
}
return false;
}
Notice that the triangle bounding box needs to be moved to the left by half the triangle width ideally.
I'd also like to point you to java.awt.Rectangle which has an intersects() that could be useful:
import java.awt.Rectangle;
float x;
float y;
float w;
float h;
float xPed;
float yPed;
float objectWidth;
float objectHeight;
float triangleWidth;
float triangleHeight;
float dia;
int speed = 2;
Rectangle vehicleBoundingBox;
Rectangle pedestrianBoundingBox;
void setup() {
size(1200, 400);
background(255);
x = width / 60;
y = height / 40;
w = width / 80;
xPed = width / 2;
triangleWidth = height / 4;
triangleHeight = 2.5 * w;
yPed = height - 3 * w;
dia = w / 2;
h = w / 2;
objectWidth = 4 * w;
objectHeight = 10 * h;
vehicleBoundingBox = new Rectangle((int)x, (int)y, (int)objectWidth, (int)objectHeight);
pedestrianBoundingBox = new Rectangle((int)xPed, (int)yPed, (int)triangleWidth, (int)triangleHeight);
}
void draw() {
//reset background
background(255);
line(0, height/4, width, height/4);
vehicle();
pedestrian();
// collision detect
if (gameOver()) {
textSize(100);
fill(255, 0, 0);
text("Game Over", width / 3, height / 2);
}
}
void vehicle() {
//moving vehicle
x += speed;
// reset vehicle
noFill();
if (x > width) {
x = 0;
} else if (x < 0) {
x = width;
}
//head of vehicle
fill(0, 194, 0, 50);
rect(x, y, w, h);
rect(x + 3 * w, y, w, h);
rect(x, y + h, 4 * w, 4 *h);
//eyes of vehicle
fill(0);
rect(x + w, 3 * y, w * 0.85, h);
rect(x + 3 * w, 3 * y, w * 0.85, h);
//body of vehicle
fill(0, 240, 0, 80);
rect(x + 1.5 * w, 6.3 * h, 1.5 * w, 3 *h );
//left arm
line(x + 1.5 *w, 6.3 * h, x + 0.5 * w, 7.3 * h);
//right arm
line(x + 3 * w, 6.3 * h, x + 4 * w, 7.3 * h);
//left leg
line(x + 1.5 * w, 9.3 * h, x + w, 11.3 * h);
//right leg
line(x + 3 * w, 9.3 * h, x + 3.5 * w, 11.3 * h);
}
// draw pedestrian
void pedestrian() {
fill(255, 140, 0, 70);
//body of pedestrian
triangle(xPed, yPed, xPed - triangleWidth / 2, yPed + 2.5 * w, xPed + triangleWidth / 2, yPed + 2.5 * w);
fill(0);
circle(xPed + triangleWidth / 4, yPed, dia);
circle(xPed - triangleWidth / 4, yPed, dia);
fill(255, 165, 0);
ellipse(xPed, yPed + w, 1.5 * dia, 3 * dia);
}
// arrow key moving
void keyPressed() {
if (!gameOver()) {
if (key == CODED) {
if (keyCode == UP) {
yPed -= height / 4;
if (yPed <= 0) {
yPed = height - 3 * w;
}
}
if (keyCode == DOWN) {
yPed += height / 4;
if (yPed > height) {
yPed = height - 3 * w;
}
}
if (keyCode==LEFT) {
xPed -= height / 4;
if (xPed < 0 + triangleWidth / 2) {
xPed = width / 2;
}
}
if (keyCode==RIGHT) {
xPed += height / 4;
if (xPed > width - triangleWidth / 2) {
xPed = width / 2;
}
}
}
}
}
boolean gameOver(){
// update bounding box positions
vehicleBoundingBox.x = (int)x;
vehicleBoundingBox.y = (int)y;
pedestrianBoundingBox.x = (int)(xPed - triangleWidth / 2);
pedestrianBoundingBox.y = (int)yPed;
//optional: visualise boxes
fill(255, 140, 0, 70);
rect(pedestrianBoundingBox.x, pedestrianBoundingBox.y, pedestrianBoundingBox.width, pedestrianBoundingBox.height);
rect(vehicleBoundingBox.x, vehicleBoundingBox.y, vehicleBoundingBox.width, vehicleBoundingBox.height);
return vehicleBoundingBox.intersects(pedestrianBoundingBox);
}
//boolean gameOver() {
// // optional visualise collision objects
// rect(x, y, objectWidth, objectHeight);
// rect(xPed, yPed, triangleWidth, triangleHeight);
// // x axis
// float distX = abs( (x + objectWidth / 2) - (xPed + triangleWidth / 2) );
// // y axis
// float distY = abs( (y + objectHeight / 2) - (yPed + triangleHeight / 2) );
// // half combined x distance
// float combinedHalfWidth = ( (objectWidth / 2) + (triangleWidth / 2) );
// // half combined y distance
// float combinedHalfHeight = ( (objectHeight / 2) + (triangleHeight / 2) );
// // check collision
// if (distX < combinedHalfWidth) {
// if (distY < combinedHalfHeight) {
// return true;
// }
// }
// return false;
//}
void circle(float x, float y, float dia){
ellipse(x, y, dia, dia);
}
Bare in mind, if this is an assignment/homework, you might not be allowed to use java.awt.Rectangle. Speaking of which, if this is an assignment you should mention that in the question.
Update
Here's an updated version better handling the game over state.
float x;
float y;
float w;
float h;
float xPed;
float yPed;
float objectWidth;
float objectHeight;
float triangleWidth;
float triangleHeight;
float dia;
int speed = 2;
// defaults to false
boolean isGameOver;
void setup() {
size(1200, 400);
background(255);
x = width / 60;
y = height / 40;
w = width / 80;
xPed = width / 2;
triangleWidth = height / 4;
triangleHeight = 2.5 * w;
yPed = height - 3 * w;
dia = w / 2;
h = w / 2;
objectWidth = 4 * w;
objectHeight = 10 * h;
}
void draw() {
//reset background
background(255);
line(0, height/4, width, height/4);
if (isGameOver) {
textSize(100);
fill(255, 0, 0);
text("Game Over", width / 3, height / 2);
}else{
// check colloisions only in game state and update game over state
isGameOver = checkCollisions();
vehicle();
pedestrian();
}
}
void vehicle() {
//moving vehicle
x += speed;
// reset vehicle
noFill();
if (x > width) {
x = 0;
} else if (x < 0) {
x = width;
}
//head of vehicle
fill(0, 194, 0, 50);
rect(x, y, w, h);
rect(x + 3 * w, y, w, h);
rect(x, y + h, 4 * w, 4 *h);
//eyes of vehicle
fill(0);
rect(x + w, 3 * y, w * 0.85, h);
rect(x + 3 * w, 3 * y, w * 0.85, h);
//body of vehicle
fill(0, 240, 0, 80);
rect(x + 1.5 * w, 6.3 * h, 1.5 * w, 3 *h );
//left arm
line(x + 1.5 *w, 6.3 * h, x + 0.5 * w, 7.3 * h);
//right arm
line(x + 3 * w, 6.3 * h, x + 4 * w, 7.3 * h);
//left leg
line(x + 1.5 * w, 9.3 * h, x + w, 11.3 * h);
//right leg
line(x + 3 * w, 9.3 * h, x + 3.5 * w, 11.3 * h);
}
// draw pedestrian
void pedestrian() {
fill(255, 140, 0, 70);
//body of pedestrian
triangle(xPed, yPed, xPed - triangleWidth / 2, yPed + 2.5 * w, xPed + triangleWidth / 2, yPed + 2.5 * w);
fill(0);
circle(xPed + triangleWidth / 4, yPed, dia);
circle(xPed - triangleWidth / 4, yPed, dia);
fill(255, 165, 0);
ellipse(xPed, yPed + w, 1.5 * dia, 3 * dia);
// visualise bounding box
//fill(255, 140, 0, 70);
//rect(xPed - triangleWidth / 2, yPed, triangleWidth, triangleHeight);
}
// arrow key moving
void keyPressed() {
if (isGameOver){
// exit game over
isGameOver = false;
// lazy way to restart the game
// normally you'd write & call a reset() function to reset player/vehicle positions, avodiing instant gameOver
setup();
} else {
if (key == CODED) {
if (keyCode == UP) {
yPed -= height / 4;
if (yPed <= 0) {
yPed = height - 3 * w;
}
}
if (keyCode == DOWN) {
yPed += height / 4;
if (yPed > height) {
yPed = height - 3 * w;
}
}
if (keyCode==LEFT) {
xPed -= height / 4;
if (xPed < 0 + triangleWidth / 2) {
xPed = width / 2;
}
}
if (keyCode==RIGHT) {
xPed += height / 4;
if (xPed > width - triangleWidth / 2) {
xPed = width / 2;
}
}
}
}
}
boolean checkCollisions() {
// optional visualise collision objects
fill(255, 140, 0, 70);
rect(x, y, objectWidth, objectHeight);
rect(xPed - triangleWidth / 2, yPed, triangleWidth, triangleHeight);
// x axis
float distX = abs( (x + objectWidth / 2) - xPed );
// y axis
float distY = abs( (y + objectHeight / 2) - (yPed + triangleHeight / 2) );
// half combined x distance
float combinedHalfWidth = ( (objectWidth / 2) + (triangleWidth / 2) );
// half combined y distance
float combinedHalfHeight = ( (objectHeight / 2) + (triangleHeight / 2) );
// check collision
if (distX < combinedHalfWidth) {
if (distY < combinedHalfHeight) {
return true;
}
}
return false;
}
The main changes are:
reintroduced gameOver boolean as isGameOver which is used to change between the two states
renamed gameOver() to checkCollisions() to avoid confusion.
In this case, with just two states, a boolean will do.
It's important to also reset game variables when changing state (e.g. reset player/vehicle positions, etc.)
In case your game may require more states you can use an integer and constants. This answer has a demo code snippet.
If multiple states are required OOP was introduced, this answer also has demo code.

How do I oscillate the height of individual shapes whilst keeping the total height of their sum constant?

I am trying to create an effect where the total height of a group of shapes is constant (say 300), whilst each shape within that group has a dynamic, oscillating, height. In one instance, maybe the middle shape is 'taller' whilst the outer shapes are shorter.
This desired effect is similar to if you held a slinky, with each end in one hand fixed at 30cm apart, and then shook it around: the total height remains the same (30cm) but the 'sections' inside the slinky are having their individual heights bounce up and down.
My attempts so far use the sin function to get an oscillating number as an angle value increases. This works for the sections, but I can't figure out how to maintain the constant overall height. See the code snippet below; red (and the tip of the bottom black triangle) should always be touching the bottom of the container.
// Prepare variables for angles, separated by 1
let a1 = 0;
let a2 = 1;
let a3 = 2;
let a4 = 3;
let a5 = 4;
// Prepare shape width
let shapeW = 150;
function setup() {
createCanvas(300, 300);
rect(10, 10, 10, 10);
}
function draw() {
background(240);
noStroke();
// Use the sin ratio to 'oscillate' a height value between 0 and 60
let x1 = map(sin(a1), -1, 1, 0, height / 5);
let x2 = map(sin(a2), -1, 1, 0, height / 5);
let x3 = map(sin(a3), -1, 1, 0, height / 5);
let x4 = map(sin(a4), -1, 1, 0, height / 5);
let x5 = map(sin(a5), -1, 1, 0, height / 5);
// Store these in an array so I can loop through
let listOfValues = [x1, x2, x3, x4, x5];
// Loop through and draw shapes
push();
translate((width / 2) - shapeW / 2, 0)
for (let i = 0; i < listOfValues.length; i++) {
fill(255, 0, 0);
rect(0, 0, shapeW, listOfValues[i]);
fill(0)
triangle(0, 0, shapeW / 2, listOfValues[i], shapeW, 0)
translate(0, listOfValues[i]);
}
pop();
// Increment each angle by the same amount
let incAmount = 0.1;
a1 += incAmount;
a2 += incAmount;
a3 += incAmount;
a4 += incAmount;
a5 += incAmount;
}
html,
body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.0/lib/p5.js"></script>
With help, I've found the solution is to use binomial coefficients. That is achieved here via a binomial() function. The only caveat is that the number of 'sections' (represented as n) must be an even number.
let angle = 0;
let N;
let containerW = 300;
let shapeW = 150;
let n = 6;
let speed = 0.0075;
function setup() {
createCanvas(containerW, containerW);
N = n * binomial(n, n / 2);
}
function draw() {
background(240);
noStroke();
let listOfVals = [];
for (let i = 0; i < n; i++) {
listOfVals.push(x(i + 1));
}
push();
translate(width / 2 - shapeW / 2, 0);
for (let i = 0; i < listOfVals.length; i++) {
fill(255, 0, 0);
rect(0, 0, shapeW, listOfVals[i] * height);
fill(0);
triangle(0, 0, shapeW / 2, listOfVals[i] * height, shapeW, 0);
translate(0, listOfVals[i] * height);
}
pop();
// Increment angle
angle += speed;
}
function x(k) {
return (2 ** n * sin(angle + (k * PI) / n) ** n) / N;
}
function binomial(n, k) {
if (typeof n !== "number" || typeof k !== "number") return false;
var coeff = 1;
for (var x = n - k + 1; x <= n; x++) coeff *= x;
for (x = 1; x <= k; x++) coeff /= x;
return coeff;
}
html,
body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.0/lib/p5.js"></script>
Nice self answer (+1).
This is more of an idea for a slightly different approach, hopefully with a few simplifications:
// Prepare shape width
let shapeW = 150;
// Prepare shape height
let shapeH;
// total number of shapes
let numShapes = 5;
// Increment each angle offset by the same amount
let incAmount = 0.05;
function setup() {
createCanvas(300, 300);
rect(10, 10, 10, 10);
// assign shape height after sketch height has been set
shapeH = height / 5;
}
function draw() {
background(240);
noStroke();
// Loop through and draw shapes
push();
// horizontally center shapes
translate((width - shapeW) / 2, 0);
// for each shape
for (let i = 0; i < numShapes; i++) {
// map the current height to the increment asdasdakrk
let currentH = map(sin(i + (frameCount * incAmount)), -1, 1, 0, shapeH);
fill(255, 0, 0);
rect(0, 0, shapeW, currentH);
fill(0)
triangle(0, 0, shapeW / 2, currentH, shapeW, 0)
translate(0, currentH);
}
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
The above is using the same logic, mostly removing the need for the a1, a2, a3, a4, a5 values as they coincide with the i counter for each shape.
A visual way I think about it having to connect the tip of one triangle with the base of the next triangle (or the current triangle's base being the same as the the previous triangle tip's y position):
// Prepare shape width
let shapeW = 150;
// Prepare shape height
let shapeH;
// total number of shapes
let numShapes = 5;
// Increment each angle offset by the same amount
let incAmount = 0.05;
// sine driven scales
let minYScale = 0.5;
let maxYScale = 2.0;
function setup() {
createCanvas(300, 300);
rect(10, 10, 10, 10);
// assign shape height after sketch height has been set
shapeH = height / 5;
}
function draw() {
background(240);
noStroke();
// Loop through and draw shapes
push();
// horizontally center shapes
translate((width - shapeW) / 2, 0);
// draw red background
fill(255, 0, 0);
rect(0, 0, shapeW, height);
// remember where the previous array base was
let lastY = 0;
// for each shape
for (let i = 0; i < numShapes; i++) {
// map the current y scale to the increment
let currentYScale = map(sin(i + (frameCount * incAmount)), -1, 1, minYScale, maxYScale);
// compute the current scale based on the sine scalar
let currentH = currentYScale * shapeH;
fill(0);
triangle(0, lastY,
shapeW / 2, lastY + currentH,
shapeW, lastY);
// update absolute y position of the arrow base
lastY += currentH;
// optional: for debugging only, visualise lastY
if(mouseIsPressed) rect(-shapeW, lastY, width + shapeW, 3);
}
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

p5.js: make an animated spiral with line instead of ellipse?

I'm trying to animate a spiral using a line, but can only seem to get it to work using ellipses.
Does anyone know how to replace the ellipse() with line()?
here is the code:
var angle = 0.0;
var offset = 60;
var scalar = 10;
var speed = 0.05;
function setup() {
createCanvas(600, 120);
fill(0);
}
function draw() {
var x = offset + cos(angle) * scalar;
var y = offset + sin(angle) * scalar;
ellipse( x, y, 2, 2);
angle += speed;
scalar += speed;
}
Assuming you would like to draw the entire spiral instantaneously using line segments, the you simply need a for loop that calculates the x and y coordinates for the current and next point in the spiral for some increment of change, and then draw lines between each pair of points. There are certainly numerous ways to write such a for loop, depending on what the constrains are (do you want a specific number of rings in your spiral? a specific number of degrees of rotation?), but importantly the bigger your increment of change the less smooth your spiral will look. Here is an example that uses the mouse position to determine the number of rings and the size of the change increments:
function setup() {
createCanvas(windowWidth, windowHeight);
stroke(0);
strokeWeight(4);
textAlign(LEFT, TOP);
}
function draw() {
background(255);
// let the horizontal mouse position indicate the
// size of the steps
let speed = map(mouseX, 0, width, 0.01, 1, true);
// let the vertical mouse position indicate the
// total amount of rotation
let maxRotation = map(mouseY, 0, height, TWO_PI, TWO_PI * 50, true);
push();
noStroke();
fill('red');
text(`Rings: ${(maxRotation / TWO_PI).toFixed(1)}, Speed: ${speed.toFixed(2)}`, 10, 10);
pop();
translate(width / 2, height / 2);
let scalar = 10;
if (speed <= 0) {
console.error('cannot have <= 0 speed');
return;
}
for (let angle = 0; angle < maxRotation; angle += speed, scalar += speed) {
const x = cos(angle) * scalar;
const y = sin(angle) * scalar;
const x2 = cos(angle + speed) * (scalar + speed);
const y2 = sin(angle + speed) * (scalar + speed);
line(x, y, x2, y2);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

How to draw curved text using MFC functions?

How to draw curved text using MFC functions? I want to achieve like this below.
DrawText() function draws text in straight line only, I do not know how to draw curved text at particular angle. Please help me.
Thanks.
You could use GDI+, There is a sample in code project, which is written in C#, I translate it into C++:
Graphics graphics(hWnd);
RECT rect = { 0 };
GetWindowRect(hWnd, &rect);
POINT center = { (rect.right - rect.left) / 2,(rect.bottom - rect.top) / 2 };
double radius = min(rect.right - rect.left, (rect.bottom - rect.top)) / 3;
TCHAR text[] = L"ABCDEFGHIJLKMNOPQRSTUVWXYZ";
REAL emSize = 24;
Font* font = new Font(FontFamily::GenericSansSerif(), emSize, FontStyleBold);
for (int i = 0; i < _tcslen(text); ++i)
{
RectF re, in;
Status result = graphics.MeasureString(&text[i], 1, font, in, &re);;
double charRadius = radius + re.Height;
double angle = (((float)i / _tcslen(text)) - 0.25) * 2 * M_PI;
double x = (int)(center.x + cos(angle) * charRadius);
double y = (int)(center.y + sin(angle) * charRadius);
result = graphics.TranslateTransform(x, y);
result = graphics.RotateTransform((float)(90 + 360 * angle / (2 * M_PI)));
PointF start(0, 0);
SolidBrush Red(Color(255, 255, 0, 0));
result = graphics.DrawString(&text[i], 1, font, start, &Red);
result = graphics.ResetTransform();
SolidBrush Green(Color(255, 0, 255, 0));
Pen* pen = new Pen(&Green, 2.0f);
result = graphics.DrawArc(pen, (REAL)(center.x - radius), (REAL)(center.y - radius), radius * 2, radius * 2, 0, 360);
}
Some header files:
#define _USE_MATH_DEFINES
#include <math.h>
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
Usage:
You must call GdiplusStartup before you create any GDI+ objects, and
you must delete all of your GDI+ objects (or have them go out of
scope) before you call GdiplusShutdown.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
//To Do.
GdiplusShutdown(gdiplusToken);
Result:
UPDATE:
Graphics graphics(hWnd);
RECT rect = { 0 };
GetWindowRect(hWnd, &rect);
POINT center = { (rect.right - rect.left) / 2,(rect.bottom - rect.top) / 2 };
double radius = min(rect.right - rect.left, (rect.bottom - rect.top)) / 3;
TCHAR text[72][4] = { 0 };
for (int i = 0; i < 72; i++)
{
_itot((i/2)*10, text[i],10);
i++;
_tcscpy(text[i],L"");
}
REAL emSize = 8;
Font* font = new Font(FontFamily::GenericSansSerif(), emSize, FontStyleBold);
for (int i = 0; i < 72; ++i)
{
RectF re, in,rel;
Status result = graphics.MeasureString(text[i], _tcslen(text[i]), font, in, &re);
result = graphics.MeasureString(L"|", 1, font, in, &rel);
double charRadius = radius - re.Height;
double angle = (((float)i / 72) - 0.25) * 2 * M_PI;
double x = (center.x + cos(angle) * charRadius);
double y = (center.y + sin(angle) * charRadius);
result = graphics.TranslateTransform(x, y);
result = graphics.RotateTransform((float)(90 + 360 * angle / (2 * M_PI)));
PointF start(0- re.Width/2, 0);
SolidBrush Red(Color(255, 255, 0, 0));
result = graphics.DrawString(text[i], _tcslen(text[i]), font, start, &Red);
result = graphics.ResetTransform();
x = (int)(center.x + cos(angle) * radius);
y = (int)(center.y + sin(angle) * radius);
result = graphics.TranslateTransform(x, y);
result = graphics.RotateTransform((float)(90 + 360 * angle / (2 * M_PI)));
PointF start1(0 - rel.Width / 2, 0);
result = graphics.DrawString(L"|", 1, font, start1, &Red);
result = graphics.ResetTransform();
}
SolidBrush Green(Color(255, 0, 255, 0));
Pen* pen = new Pen(&Green, 2.0f);
Status result = graphics.DrawArc(pen, (REAL)(center.x - radius), (REAL)(center.y - radius), radius * 2, radius * 2, 0, 360);
Result:

How to make an (moving) ellipse clickable? Processing

So I started learning processing since a week ago and I'm trying to get a moving ellipse clickable. I followed the processing API, but I can't figure it out. I removed all the code relating to the clickable ellipse because it was a mess.
In the section where I declare all my vars you can see me using:
int breedte = 600;
int hoogte = 600;
These are suppose to be:
int breedte = width;
int hoogte = height;
But for some reason the width and height don't output the width and height declared in:
size(600,600)
So what I'm asking is:
How can I make the (moving) ellipse clickable?
Why I can't use width and height on 'int hoogte' and 'int breedte'?
Thanks in advace.
Main file:
int x = 0;
int leftSide = 0;
int rightSide = width;
int bottomSide = height;
int totalHits = 0;
int totalMiss = 0;
boolean start = false;
int circelSize = 100;
int circelRings = 24;
int circelSpeed = 1;
int circelPositionY = 0;
int breedte = 600;
int hoogte = 600;
String[] buttonText = {"Start","Stop"};
String buttonTextActive = buttonText[0];
int[] buttonColor = {0,90};
int buttonColorActive = buttonColor[0];
int buttonHighlight = 50;
int buttonSize = 80;
int buttonY = breedte - (buttonSize /2);
int buttonX = hoogte / 2 - 40;
void setup() {
size(600, 600);
smooth();
noStroke();
}
void draw() {
if (start) {
circelPositionY = circelPositionY + circelSpeed;
drawCircel(circelPositionY);
if (circelPositionY == (width + circelSize)) {
circelPositionY = 0;
}
}
drawButton();
}
Events file:
void mousePressed() {
// Start or Stop button
if(mouseX > buttonX & mouseX < buttonX + buttonSize & mouseY > buttonY & mouseY < buttonY + (buttonSize / 2)){
if(start) {
start = false;
buttonColorActive = buttonColor[0];
buttonTextActive = buttonText[0];
println("Game stoped");
} else {
start = true;
buttonColorActive = buttonColor[1];
buttonTextActive = buttonText[1];
println("Game started");
}
}
//HERE SHOULD GO THE CLICKABLE ELLPISE
}
Functions file:
void drawCircel(int circelPositionY) {
background(204);
for (int i = 0; i < circelRings; i = i+1) {
int even = i % 2;
if (even == 0) {
fill(255,0,0);
ellipse(-(circelSize / 2) + circelPositionY, height / 2 - (circelSize / 2), circelSize - (i * (circelSize / circelRings)), circelSize - (i * (circelSize / circelRings)));
} else {
fill(255);
ellipse(-(circelSize / 2) + circelPositionY, height / 2 - (circelSize / 2), circelSize - (i * (circelSize / circelRings)), circelSize - (i * (circelSize / circelRings)));
}
}
}
void drawButton() {
fill(buttonColorActive);
rect(buttonX,buttonY, buttonSize, buttonSize / 2);
fill(255);
textAlign(CENTER, CENTER);
text(buttonTextActive, buttonX + (buttonSize / 2),buttonY + (buttonSize / 4));
}
In the future, please try to post a MCVE instead of a bunch of disconnected snippets or your whole project. Also please only ask one question per post.
To make your circle clickable, you're going to have to write code that checks whether the circle is being clicked. That's actually two separate checks. First you have to detect when the mouse is pressed. One way to do that is by defining a mousePressed() function:
void mousePressed(){
// mouse is pressed
}
Then you have to check whether the mouse is currently inside the circle. You can use the dist() function for that: if the distance between the mouse and the center of the circle is less than the radius of the circle, then the mouse is inside the circle. That might look like this:
void mousePressed(){
if(dist(mouseX, mouseY, circleX, circleY) < circleRadius){
// mouse is pressed inside the circle
}
}
Shameless self-promotion: I wrote a tutorial on collision detection in Processing, including point-circle collision, available here.
As for why you can't use width and height at the top of your sketch, that's because code at the top of your sketch is executed before the setup() function fires, and the width and height variables aren't set until after you call size() from the setup() function. So you have to move that code to after you call size().
If you have follow-up questions, please post an updated MCVE in a new question post, and we'll go from there. Good luck.
Processing does not provide an api for hit detection, so you need to implement this by yourself, which I think is a great learning exercise. You can explore the mathematics of an ellipse here.
But the general approach is to use a function like the one below to check that the point you clicked on was indeed inside the ellipse you provided.
boolean InsideEllipse(
float x, float y,
float xc, float yc,
float width, float height
) {
// First half the width and height to get the ellipse parameters
float a = width / 2;
float b = height / 2;
// Now calculate the deltas:
float xd = x - xc;
float yd = y - yd;
// Now the equation of an ellipse is given by
// x^2 / a ^ 2 + y^2 / b ^ 2 = 1
// So if we are inside the ellipse, we would expect the left hand
// side of this expression to be less than one
boolean inside = xd * xd / (a * a) + yd * yd / (b * b) <= 1.0
return inside
}

Resources