P5.js - Animation Rotation - How to rotate sword 360 degrees? - animation

Im trying to animate an object, in this example the object is a sword.
The animation is the sword rotating 360 degrees, one time, per button press.
I've drawn the sword, put it in my desired starting/ending position and I've got it to rotate once, but I can't seem to get it to rotate a second time.
Here's what I've got so far...
angleMode(DEGREES);
let angle = 150;
push();
translate(100,100);
rotate(angle);
rect(-15,-5,100,10);
pop();
if (key == 'z' && angle <= 150 && angle >= -190){
angle -= 20;
} else if (angle >= -190){
angle = 150;
}

Perhaps you meant to check if the angle <= -190 to reset it back to 150 ?
// ...
} else if (angle <= -190){
angle = 150;
}
running example snippet:
let angle = 150;
function setup() {
createCanvas(400, 400);
angleMode(DEGREES);
}
function draw() {
background(220);
push();
translate(100, 100);
rotate(angle);
rect(-15, -5, 100, 10);
triangle(85, -5, 85, 5, 110, 5);
pop();
if (keyIsPressed) {
if (key == "z" && angle <= 150 && angle >= -190) {
angle -= 20;
console.log("updated angle", angle);
} else if (angle <= -190) {
console.log("angle reset");
angle = 150;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

Related

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>

Translating horizontally inverted quads

A couple of days ago I asked a question about translations and rotations in Processing.
I wanted to:
translate, invert and rotate a single quadrilateral (PShape object) multiple times
then change the height of one of its 2 top vertices
so as the whole thing act as an articulated arm that can be bent either to the right or the left.
Thanks to the help of #Rabbid76 I was able to achieve this effect but I am now facing another issue when translating the last 5 top horizontally inverted quads.
When bending the object, the first 3 quads get separated from the last 5 and. And the more the bending leg is curved, the farther they get apart.
I would really appreciate if someone could help me fix the translation part (from line 65 to 68) so as the quads stay attached to each other to matter how strong the bending is.
Any suggestion regarding that matter would be also greatly appreciated.
SCRIPT
int W = 40;
int H = 40;
int nQuads = 8;
int xOffset = 27;
float[] p0 = {-W/2 + xOffset, -H/2};
float[] p1 = {-W/2, H/2};
float[] p2 = {W/2, H/2};
float[] p3 = {W/2, -H/2};
PShape object;
void setup(){
size(600, 600, P2D);
smooth(8);
}
void draw(){
background(255);
// Bending to the left
float bending = sin(frameCount*.05) * .1;
p0[1] -= bending;
pushMatrix();
translate(width/2, height/2);
float minX = min( min(p0[0], p3[0]), min(p2[0], p1[0]) );
float maxX = max( max(p0[0], p3[0]), max(p2[0], p1[0]) );
float cptX = (minX+maxX)/2;
//Rotation Angle
float angle = atan2(p3[1]-p0[1], p3[0]-p0[0]);
//Pivot Height
float PH = p0[1] + (p3[1]-p0[1]) * (cptX-p0[0])/(p3[0]-p0[0]);
for (int i = 0; i < nQuads; i++){
float PivotHeight = (i % 2 == 1) ? PH : H/2;
//Height translation
if (i > 0){
translate(0, PivotHeight);
}
//Rotate once every 2 quads
if (i%2 == 1){
rotate(angle*2);
}
//Height translation
//Flip all quads except 1st one
if (i > 0){
translate(0, PivotHeight);
scale(1, -1);
}
//NOT working --> Flipping horizontally the last 5 top QUADS
if (i == 3){
scale(-1, 1);
translate(- xOffset, 0); //trying to align the quads on the X axis. Y translation is missing
rotate(-angle*2);
}
object();
}
popMatrix();
}
void object() {
beginShape(QUADS);
vertex(p0[0], p0[1]);
vertex(p1[0], p1[1]);
vertex(p2[0], p2[1]);
vertex(p3[0], p3[1]);
endShape();
}
Just providing a workaround to my own question but won't accept it as a valid answer as I don't really understand what I'm doing and it's probably not the most efficient solution.
int W = 40;
int H = 40;
int nQuads = 8;
int xOffset = 27;
float[] p0 = {-W/2 + xOffset, -H/2};
float[] p1 = {-W/2, H/2};
float[] p2 = {W/2, H/2};
float[] p3 = {W/2, -H/2};
PShape object;
void setup(){
size(600, 600, P2D);
smooth(8);
}
void draw(){
background(255);
// Bending to the left
float bending = sin(frameCount*.05) * .3;
p0[1] -= bending;
pushMatrix();
translate(width/2, height/2);
float minX = min( min(p0[0], p3[0]), min(p2[0], p1[0]) );
float maxX = max( max(p0[0], p3[0]), max(p2[0], p1[0]) );
float cptX = (minX+maxX)/2;
//Rotation Angle
float angle = atan2(p3[1]-p0[1], p3[0]-p0[0]);
//Pivot Height
float PH = p0[1] + (p3[1]-p0[1]) * (cptX-p0[0])/(p3[0]-p0[0]);
for (int i = 0; i < nQuads; i++){
float PivotHeight = (i % 2 == 1) ? PH : H/2;
//Height translation
if (i > 0){
translate(0, PivotHeight);
}
//Rotate once every 2 quads
if (i%2 == 1){
rotate(angle*2);
}
//Height translation
//Flip all quads except 1st one
if (i > 0){
translate(0, PivotHeight);
scale(1, -1);
}
//Flipping horizontally the last 5 top QUADS
if (i == 3){
scale(-1, 1);
translate(0, PivotHeight);
rotate(-angle*2);
translate(0, PivotHeight);
translate(-xOffset , H/2 - p0[1]);
}
object();
}
popMatrix();
}
void object() {
beginShape(QUADS);
vertex(p0[0], p0[1]);
vertex(p1[0], p1[1]);
vertex(p2[0], p2[1]);
vertex(p3[0], p3[1]);
endShape();
}

What do i need to change to make the code work?

I started programming this pong game for CS class. I want to have the ball starting off in the center of the field so I used:
ellipse (width/2, height/2, 15, 15);
I want to make the game start once I press the space key. In order to do that I used:
if (keyPressed == true) {ellipse (ballX, ballY, 15, 15); fill (0, 255, 0);}
However it does not work. Can someone please help me figure out what is wrong with my code? Please consider that this is not a JavaScript but a Processing question.
Here is my entire code so far:
float ballX = 15, ballY = 15, dX = 15, dY = 15; // variables for the ball
float paddleX; // variables for the paddles
int mouseY; // variable to make the pong move with the mouse movement
boolean key, keyPressed;
void setup() {
size (1500,1100); // the field is going to be 1500x110px big
paddleX = width - 40;
ballX = 15; ballY = 15;
}
void draw() {
background(0); // black background
ellipse (width/2, height/2, 15, 15); // this is the starting point of the ball
if (keyPressed == true) { ellipse (ballX, ballY, 15, 15); fill (0, 255, 0); } // the game will only start when a key is pressed
if (ballX > width || ballX < 0) { dX = -dX; } // if the ball reaches the right or left wall it will switch directions
if (ballY > height || ballY < 0) { dY = -dY; }// if the ball reaches the upper or lower wall it will switch directions
ballX = ballX + dX; ballY = ballY + dY; // the ball with move with the speed set as dX and dY
rect(paddleX/58, mouseY, 20, 100); fill (255,10,20); // green pong
rect(paddleX, mouseY, 20, 100); fill (60,255,0); // red pong
}
The answer to this question is the same as the answer to your other question: you need to store the state of your sketch in variables, then you need to draw each frame based on that state, and finally you need to change those variables to change the state of your game.
Here's a simple example that only draws an ellipse after you press a key:
boolean playing = false;
void keyPressed() {
playing = true;
}
void draw() {
background(0);
if (playing) {
ellipse(width/2, height/2, 50, 50);
}
}
In this example, the playing variable is my state. I then update that state in the keyPressed() function, and I use that state to determine what I draw in my draw() function. You'll have to extrapolate a bit, but this process of breaking your problem down into a state, changing that state, and drawing that state is the answer to all of your questions.

Processing - Line in direction of mouse pointer

I am trying to achieve an effect like the image below
In my code, I managed to create this effect but in repeating the effect it seems to multiply inwards on itself. Could anyone help me to make my code achieve the effect in the image above?
void setup(){
size(500,500);
frameRate(60);
ellipseMode(CENTER);
smooth();
loop();
}
void draw() {
background(#ffffff);
//border
strokeWeight(3);
fill(255);
arc(50, 50, 50, 50, -PI, -PI / 2);
fill(255);
arc(450, 450, 50, 50, 0, PI / 2.0);
line(25, 50, 25, 475);
line(25, 475, 450, 475);
line(475, 450, 475, 25);
line(475, 25, 135, 25);
fill(0);
text("MAGNETS", 60, 30);
//Lines
for(int i=0; i<3; i++){
drawMagnet();
}
}
float angle = 0;
int x = 75;
int y = 75;
float tAngle = 0;
float easing = 0.1f;
void drawMagnet(){
int l = 10; //length
angle = atan2( mouseY - y, mouseX - x);
float dir = (angle - tAngle) / TWO_PI;
dir -= round(dir);
dir *= TWO_PI;
tAngle += dir * easing;
stroke(0);
translate(x, y);
rotate(tAngle);
line(-l, 0, l, 0);
}
Your rotations and translations are stacking, which is causing your problem. To fix this, you might do something like this:
pushMatrix();
translate(x, y);
rotate(tAngle);
line(-l, 0, l, 0);
popMatrix();
Here I'm using the pushMatrix() and popMatrix() functions so your rotations and translations don't stack.
But then all of your lines are at the same x,y location. So they'll all have the same angle towards the mouse position.
You're using the translate() function to draw them in different locations, but that doesn't change their underlying "model" position.
Similar to my answer to this question, you need to either base your calculations off the screen position of the lines (using the screenX() and screenY() functions), or you need to stop relying on translate() to move your lines around and calculate their positions directly.

Need to rotate and move images in processing?

I am fast approaching several deadlines for my highschool graduation project so any advice you can give would be great. My project is to code a movie. The idea is to use processing to move the characters like tokens and also use code to animate things like rain and fire. Right now I am finding it very difficult to move images and/or rotate them. This is a big hurtle for my project. The current code I have for this is butchered and complicated but here it is.
Image of leading lady, Radial: https://www.dropbox.com/s/x3gvendnaeftapj/radialoutlinel.png
/*
Radialrolling
*/
PImage img; // Declare variable "a" of type PImage
float ballX = 10;
float ballY = 200;
float h = 300;
//create a variable for speed
float speedY = 2; // spped set to 0 in order to test rotating. Necessary for rolling motion
float speedX = 0.;
void setup() {
size(800,800);
smooth();
noStroke();
background(0, 0, 0);// Load the image into the program
// change the mode we draw circles so they are
// aligned in the top left
ellipseMode(CORNER);
img = loadImage("radialoutlinel.png");
}
void RadialRoll(){
rotate(0);//if this is anything but 0 ball will appear of screen
image(img, ballX, ballY, h, h); //create a continuos rotation using the new fun
//nctions in the draw things
}
void draw() {
//clear the background and set the fill colour
background(0);
fill(255);
//draw the circle in it's current position
// ellipse(ballX, ballY, h,h);
//add a little gravity to the speed
speedY = speedY + 0;
speedX = speedX + .02;
ballX = ballX + speedX;
RadialRoll();
if (ballX > width - h) {
// set the position to be on the floor
ballX = width - h;
// and make the y speed 90% of what it was,
// but in the opposite direction
speedX = speedX * -1;
//switch the direction
//speedY = speedY;
}
if (ballX > width - h) {
// set the position to be on the floor
ballX = width - h;
// and make the y speed 90% of what it was,
// but in the opposite direction
speedX = speedX * -1;
//switch the direction
//speedY = speedY;
}
else if (ballX <= 0) {
// if the ball hits the top,
// make it bounce off
speedX = -speedX;
}
if (ballY > height - h) {
// set the position to be on the floor
ballY = height - h;
// and make the y speed 90% of what it was,
// but in the opposite direction
speedY = speedY * -1;
//switch the direction
//speedY = speedY;
}
else if (ballY <= 0) {
// if the ball hits the top,
// make it bounce off
speedY = -speedY;
}
}
How can I move images on screen and rotate them with little hassle?
Thank you very much.
-TheIronHobo
First when you look at rotate() function it take radians (values from 0 to TWO_PI) as argument so when you want fluent rotation use something like this
rotate(counter*TWO_PI/360);
Where counter could be integer value increased in every draw() loop. But if you just add this to you code image will be rotating around point [0,0] (upper left corner) and you will not see image for 1/4 of the rotation. To better understanding this you should read this TUTORIAL then you could start with basic rotation:
PImage img;
int counter = 1;
void setup() {
size(800, 800);
smooth();
background(0, 0, 0);
img = loadImage("radialoutlinel.png");
imageMode(CENTER); //you can change mode to CORNER to see the difference.
}
void draw() {
background(0);
fill(255);
counter++;
translate(width/2, height/2);
rotate(counter*TWO_PI/360);
image(img, 0, 0, 300, 300);
}
Then if you want also move image from left to right side you will just adjust translate() first parameter.

Resources