p5.js mouseclick move over Canvas - javascript

I am trying to solve a school assignment in p5 JavaScript. I want something to move over the canvas after one mouseclick. But it only moves a little bit and I have to click several times to get it all the way over. What have I done wrong? Shouldn't the loop make it move all the way? Can post the whole code if needed.
function CanvasPressed()
{
if ( mouseX > 0 && mouseX < 638 && mouseY > 0 && mouseY < 100 )
{
Bird.stop();
Bird.play();
for ( let b = 640; b > 0; b--)
{
x = x - 0.05;
}
}

Alright, so you've got a couple misunderstood things, here:
// purely aesthetic but in javascript functions are usually written as (i think) camelCase
// so: canvasPressed() rather than CanvasPressed(), Class-es start with upper case
function CanvasPressed()
{
// you can check for width & height if you want if ( mouseX > 0 && mouseX < width)
if ( mouseX > 0 && mouseX < 638 && mouseY > 0 && mouseY < height )
{
for ( let b = 640; b > 0; b--) // this, in this case, does the same as for(let i = 0; i < width; i ++)
{
x += 0.05
// 0.05 is very little, only a very small part of a pixel
}
// here it moves 0.05 * 640 (0.05 + 0.05 + 0.05 ... )
}
}
javascript naming conventions thingy if you want
and this is how i would make it move through the canvas:
let mouseWasPressed = false;
let x = 20
function draw() {
background(20);
ellipse(x, height / 2, 40)
if(mouseWasPressed) // don't need {} for 1 line after the if()
x ++; // x = x + 1 shortening in javascript
// }
}
function mousePressed(){
mouseWasPressed = true
}
if you don't want the "animation" you could use your previous method, but change the 0.05 to 1:
for(let i = 0; i <= width; i ++) // you don't have to add parentheses for 1 line
x ++; // x = x + 1 just a shortening in javascript
OR just
x = width // or x += width (x = x + width)

Related

Collision detection and resolving in a generalized coordinate system

I have this game I'm working on with a 2 dimensional array with coordinates and a generalized coordinate system (i.e. player x = 0 and y = 0, it's standing in the first item in the array). I'm trying to work out a solution to collision detection and resolving, but I'm having a really hard time.
This is my code so far (detecting collisions but not resolving them correctly and I have just no clue how to fix thayut):
let xOffset = 0;
let yOffset = 0;
let self = this;
let a, b, c, d, e, f, g, h;
// get the 4 colliding tiles from the layout array
function reset() {
a = Math.floor(self.x);
b = Math.ceil(self.x);
c = Math.floor(self.y);
d = Math.ceil(self.y);
e = (currentClassRoom.layout[c] || [])[a];
f = (currentClassRoom.layout[c] || [])[b];
g = (currentClassRoom.layout[d] || [])[a];
h = (currentClassRoom.layout[d] || [])[b];
}
function X() {
// x collisions
// get the distance inside the block from corresponding direction
if (Walkable.indexOf(f) < 0 || Walkable.indexOf(h) < 0) { xOffset += -(self.x - a) }
if (Walkable.indexOf(e) < 0 || Walkable.indexOf(g) < 0) { xOffset += 1 - (self.x - a) }
}
function Y() {
// y collisions
// get the distance inside the block from corresponding direction
if (Walkable.indexOf(e) < 0 || Walkable.indexOf(f) < 0) { yOffset += 1 - (self.y - c) };
if (Walkable.indexOf(g) < 0 || Walkable.indexOf(h) < 0) { yOffset += -(self.y - c) };
}
// run and resolve
reset();
Y();
this.y += yOffset;
X();
this.x += xOffset;
Is there something wrong with my code or is a generalized coordinate system a bad idea in my case? I haven't made anything like this and can't seem to find solutions online (which might be an indicator that the way I'm thinking about this is bad but I just don't know)

Why is splice removing all the elements from an array?

So I am trying to make this game(which I've seen in a video), but I'd like to make it differently, and I am stuck. I have this array with projectiles. Basically, every time a projectile moves out of the screen I'd like to delete that projectile from the array. The problem is when the projectile hits the screen all of the projectiles are being deleted.
The code:
function animate(){
requestAnimationFrame(animate);
c.clearRect(0, 0, width, height);
player.draw();
//shoot on click
addEventListener('click', function(event){
mousex = event.clientX;
mousey = event.clientY;
let angle = Math.atan2(mousey - player.y, mousex - player.x);
projectiledx = Math.cos(angle) * 8;
projectiledy = Math.sin(angle) * 8;
projectileArray.push(new Projectile(width/2, height/2, 10, projectiledx, projectiledy, black));
})
for(let i = 0; i < projectileArray.length; i++){
projectileArray[i].update();
if(projectileArray[i].x + projectileArray[i].radius < 0 || projectileArray[i].x - projectileArray[i].radius >= width){
projectileArray[i].splice(i, 1);
}
if(projectileArray[i].y + projectileArray[i].radius < 0 || projectileArray[i].y - projectileArray[i].radius >= height){
projectileArray[i].splice(i, 1);
}
}
}
animate();
I can see at least two problems here:
there should not be [i] before .splice
You are iterating the array with for loop and whithin that loop you want to modify the length of that array - it looks like a bad idea to me..
Better take a list of items to remove and after that loop ...remove them (begining from the last) in another loop like this:
var removalList = [];
for(let i = 0; i < projectileArray.length; i++){
projectileArray[i].update();
if(
projectileArray[i].x + projectileArray[i].radius < 0 ||
projectileArray[i].x - projectileArray[i].radius >= width ||
projectileArray[i].y + projectileArray[i].radius < 0 ||
projectileArray[i].y - projectileArray[i].radius >= height
){
removalList.push(i);
}
}
for(let i=removalList.length; i>0; i--){
projectileArray.splice( removalList[i-1], 1 );
}

JS Optimization - constantly setting variables on fast fire events

I am working on a script using Three.js where a lot a variables depend on mouse position. Does it matter if I am constantly setting variables to their same value each time the move event fires, or should I only set a variable when a change is detected?
Let's say I want to set a variable "quadrant" to 1,2,3 or 4 depending upon which part of the screen the mouse is over... should I use this :
var quadrant;
function mouseMove(e){
var mouse;
mouse.x = e.clientX;
mouse.y = e.clientY;
if(mouse.x < window.innerWidth / 2){
if(mouse.y < window.innerHeight / 2){
quadrant = 1;
} else {
quadrant = 3;
}
} else {
if(mouse.y < window.innerHeight / 2){
quadrant = 2;
} else {
quadrant = 4;
}
}
};
window.addEventListener('mousemove', mouseMove);
Which will reset the variable every time the event fires. Or should I only be setting variables when a change is detected, like this :
var quadrant;
function mouseMove(e){
var mouse;
mouse.x = e.clientX;
mouse.y = e.clientY;
if(mouse.x < window.innerWidth / 2){
if(mouse.y < window.innerHeight / 2){
if(quadrant != 1){
quadrant = 1;
}
} else {
if(quadrant != 3){
quadrant = 3;
};
}
} else {
if(mouse.y < window.innerHeight / 2){
if(quadrant != 2){
quadrant = 2;
};
} else {
if(quadrant != 4){
quadrant = 4;
};
}
}
};
window.addEventListener('mousemove', mouseMove);
Does the act of setting a variable to the memory (even if it's to the same value) cost more than it takes to read the extra lines of code necessary to add the conditions? I instinctively do the latter as it seems tidier and like less work at runtime, but I really have no idea how this actually translates to performance. I seem to remember reading that each time a variable is set in js that it's actually creating an instance of itself, which seems like work... but maybe I misunderstood.
As noted in the comments, the simpler version is very likely to be faster - and it's easier to read and less error-prone too.
While I've got you, let me suggest a completely different approach: calculate the quadrant instead of using a bunch of if statements.
// Calculate the quadrant for a given x and y and width and height.
// The quadrants are defined like this:
//
// +---+---+
// | 1 | 2 |
// +---+---+
// | 3 | 4 |
// +---+---+
function getQuadrant( x, y, width, height ) {
return 1 +
( x >= width / 2 ) +
( y >= height / 2 ) * 2;
}
console.log( getQuadrant( 25, 25, 100, 100 ) ); // 1
console.log( getQuadrant( 75, 25, 100, 100 ) ); // 2
console.log( getQuadrant( 25, 75, 100, 100 ) ); // 3
console.log( getQuadrant( 75, 75, 100, 100 ) ); // 4
This code works because when you use an arithmetic operator on a boolean value, it converts a false value to 0 and a true value to 1.
I don't know if this will be faster or slower (you would have to benchmark it to find out) but since you are looking at different approaches to solving the problem, I thought you might find it interesting.
You may wonder "aren't those multiplies and divides slow?" But modern JavaScript engines, like most optimizing compilers, can convert multiplies or divides by a power of 2 into a very fast bit-shifting operation.
Let's take a look at the machine code that V8 generates for the getQuadrant function (just showing the core part of the code, not the function setup and teardown).
When we enter this code, the four function parameters are stored in these registers:
r8 is x.
r11 is y.
rdx is width.
rdi is height.
And here's the compiled code:
; Divide height and width by 2 for the comparisons below
sarl rdi, 1
sarl rdx, 1
; Compare y with half the height and set rcx to 0 or 1
cmpl rdi,r11
setlel cl
movzxbl rcx,rcx
; Compare x with half the width and set rdx to 0 or 1
cmpl rdx,r8
setlel dl
movzxbl rdx,rdx
; Set rdx to the final result, calculated in a single instruction
leal rdx,[rdx+rcx*2+0x1]
One likely performance advantage is that this code avoids the branches used by the if statements. On modern CPUs, when you can avoid branches, it is often a performance win.
But again, any of these approaches will likely be more than fast enough! Just posting this alternative method in case it is of interest to you.
If you're curious how I got that machine code listing, I created a standalone JavaScript file called quadrants.js with this content:
function getQuadrant( x, y, width, height ) {
return 1 +
( x >= width / 2 ) +
( y >= height / 2 ) * 2;
}
// We need to actually do something with the result returned by getQuadrant,
// otherwise the JavaScript engine may notice that the result is unused and
// it may skip compiling the function body entirely.
quadrants = [];
for( let i = 0; i < 1000000; ++i ) {
quadrants.push( getQuadrant( 25, 25, 100, 100 ) );
quadrants.push( getQuadrant( 75, 25, 100, 100 ) );
quadrants.push( getQuadrant( 25, 75, 100, 100 ) );
quadrants.push( getQuadrant( 75, 75, 100, 100 ) );
}
// Log the first few results as a sanity check
console.log( quadrants.length );
for( let i = 0; i < 16; ++i ) {
console.log( quadrants[i] );
}
Then I ran it with this command:
node --print-opt-code --code-comments quadrants.js >code.txt
And then I looked through the generated code.txt file to find the code for the getQuadrant function.
Performance wise, they should be very similar. However it really depends on what happens after setting the variable. Are you going to call a function that do hefty work each time? Then you're better of using the second one.
You shouldn't bother yourself with micro-optimizations, A couple milliseconds delay won't really affect your application.
Also if you need to see for yourself here's some benchmark code to run (It won't be that accurate though). It shows the average time in seconds for running each function 1k times
let sum1 = 0, sum2 = 0, quadrant;
for(i = 0; i < 1000; i++){
let obj = calculate(1000);
sum1 += obj.t1;
sum2 += obj.t2;
}
console.log("avg for first: ", sum1 / 1000);
console.log("avg for second: ", sum2 / 1000);
function calculate(numIterations){
//first function
let start = Date.now();
for(let i = 0; i < numIterations; i++){
mouseMove(generateEventObject());
}
let t1 = (Date.now() - start) / 1000;
//second function
start = Date.now();
for(let i = 0; i < numIterations; i++){
mouseMove2(generateEventObject());
}
let t2 = (Date.now() - start) / 1000;
return {t1, t2}
}
function generateRandom(max) {
return Math.random() * max;
}
function generateEventObject() {
return {
clientX: generateRandom(window.innerWidth),
clientY: generateRandom(window.innerHeight)
}
}
function mouseMove(e){
var mouse = {};
mouse.x = e.clientX;
mouse.y = e.clientY;
if(mouse.x < window.innerWidth / 2){
if(mouse.y < window.innerHeight / 2){
quadrant = 1;
} else {
quadrant = 3;
}
} else {
if(mouse.y < window.innerHeight / 2){
quadrant = 2;
} else {
quadrant = 4;
}
}
};
function mouseMove2(e){
var mouse = {};
mouse.x = e.clientX;
mouse.y = e.clientY;
if(mouse.x < window.innerWidth / 2){
if(mouse.y < window.innerHeight / 2){
if(quadrant != 1){
quadrant = 1;
}
} else {
if(quadrant != 3){
quadrant = 3;
};
}
} else {
if(mouse.y < window.innerHeight / 2){
if(quadrant != 2){
quadrant = 2;
};
} else {
if(quadrant != 4){
quadrant = 4;
};
}
}
};

Moving a ball around the screen in p5.js

I wanted to move the ellipse around the screen using if statement I only made it move left and down and right but I couldn't manage to move it up so it complete a full cycle that is my code:
var x;
var y;
var r=33;
var speed=4;
function setup() {
createCanvas(660, 500);
x=width;
y=0;
}
function draw() {
background("black");
ellipse(x,y,r)
if(x<=width&&x>=0)
{
if(y<=0)
x-=12;
else if(y>=height)
x+=21;
}
if(y>=0&&y<=height)
{
if(x>=width)
y-=21;
else if(x<=0)
y+=21
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
The issue is, that the ball does not stop exactly at the borders of the window. It slightly moves beyond. Use min() and max(), to keep the ball in bounds.
e.g.:
x = max(r, x - speed_x);
y = min(height-r, y + speed_y);
See the example
var x, y, r=25, speed_x = 12, speed_y = 12;
function setup() {
createCanvas(500, 200);
x=width-r;
y=r;
}
function draw() {
background("black");
ellipse(x,y, r*2)
// move left
if (y == r && x > r)
x = max(r, x - speed_x);
// move down
if (x == r && y < height-r)
y = min(height-r, y + speed_y);
// move right
if (y == height-r && x < width-r)
x = min(width-r, x + speed_x);
// move up
if (x == width-r && y > r)
y = max(r, y - speed_y);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>

Increment to max number and then decrement to minimum

I want to make a Javascript function that will eventually cause a div to animate by updating a calculation as the user scrolls.
My aim is to do this by incrementing a number, initially from 0 up to 20. Once 20 is the value this number needs to be recognised and then the value needs to decrement down from 20 to -20 (For example)
At the moment I have a function that will count up as I scroll down the page and then when I scroll up will count down again but I'm not sure how best to get the values to also update when the numbers reach 20 and -20 as the user scrolls.
let scrollCount = 0;
window.addEventListener("mousewheel", function(e){
if(e.wheelDelta < 0 && scrollCount < 20){
scrollCount++
}
else if(e.wheelDelta > 0 && scrollCount > -20){
scrollCount--
}
let x = scrollCount * window.innerWidth
let y = 30 * window.innerHeight
moveEye(irisLeft, x, y)
moveEye(irisRight, x, y)
console.log(scrollCount)
});
I think using PageOffset would be a better option.
var scrollTop = window.pageYOffset;
This will give you an absolute px value of scroll position. Though it is not in range [-20,20], you can scale it mathematically(min-max scaling).
Scaling Answered Here
Round off scaled values to integers and you're done.
As I said in my comment - this behavior is quire weird as once 20 is reached your div will start trembling/bouncing and will throw your user in a epileptic shock.
let scrollCount = 0;
let direction = 1;
window.addEventListener("mousewheel", function (e) {
if (e.wheelDelta < 0) {
scrollCount += direction
if (scrollCount === 20 || scrollCount === -20) {
direction *= -1
}
}
else if (e.wheelDelta > 0) {
scrollCount -= direction
if (scrollCount === 20 || scrollCount === -20) {
direction *= -1
}
}
let x = scrollCount * window.innerWidth
let y = 30 * window.innerHeight
// moveEye(irisLeft, x, y)
// moveEye(irisRight, x, y)
console.log(scrollCount)
});

Categories