I have a 3D Render of moving cubes, they are different colors, so it's like a rainbow. But I want to know if there is a way to make the squares pulse colors.
https://repl.it/#AlexanderLuna/R-A-I-N-B-O-W#index.html
colorMode(HSB, nums.x * nums.y, 1, 1) Is your answere.
Apply it in the update function and play around with the colors by altering 'nums.x * nums.y' values.
Use a timer or a simple tick (you can simply do tick++ in the update function) as a modifier until it reaches a certain iteration and then reset (or jump the value). You should get the desired effect.
Okey.. apparently I'm procrastinating and spent the last hour playing around with your Repl..
This might not be exactly what you're after, but maybe it'll help some..
class Cube {
constructor(x_, y_, z_, size_, offset_) {
this.x = x_;
this.y = y_;
this.z = z_;
this.size = size_;
this.offset = offset_;
this.angle = 0;
this.tick = 1; // starting point
this.hueSpeed = 2; // tick modifier
}
update(f) {
this.y = map(f(this.angle + this.offset), -1, 1, this.size / 2, height - this.size / 2);
this.angle += 0.05;
colorMode(HSB, this.tick, 1, 1);
/**
* The request is there to simply regulate the frequency of the tick a bit..
* Though we do need to cancel the previous request if hadn't yet fired
* Which I'm apparently to lazy to do atm
*/
window.requestAnimationFrame((e)=>{
this.tick += this.hueSpeed;
(this.tick > 150 || this.tick < 2) && (this.hueSpeed *= -1);
});
}
render() {
push();
stroke(0);
translate(this.x, this.y, this.z);
box(this.size);
pop();
}
}
This is the cube.js script file, the only one altered.
Related
I have created the collision check function for my player to every time when the object (in this case vector - circle) touches the player (also a vector - circle) the game is over.
I have managed to create a logic and there is a collision check working, however it's not calculating the actual distance between elements (instead of ending game when they actually touch its ending when they are some distance from each other.
Both objects are moving - obstacle is moving x+=6 and the player is following the coursor so the speed varies.
I have tried adjusting distance slightly and I have managed to end the game when the x of obstacle is touch x of the player but could not managed actually to when boarders touch. I attach the code I have below;
class Player {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(500, 500);
this.mag = 3;
this.velLerp = 0.1;
}
update() {
let mouse = createVector(mouseX - width / 2,
mouseY - height / 2);
mouse.setMag(this.mag);
this.vel.lerp(mouse, this.velLerp);
this.pos.add(this.vel);
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
console.log("GAME OVER");
return true;
}
The issue is caused by the fact that the movement of the circles is 3 (this.mag) pixel. You just get the exact point of contact by chance. Most time they are intersecting.
If a collision is detected, change the player's position slightly by an offset of this.r + obstacle.r - d:
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
let shift = p5.Vector.sub(this.pos, obstacle.pos);
shift.setMag(this.r + obstacle.r - d);
this.pos.add(shift);
console.log("GAME OVER");
return true;
}
}
Im am creating a COVID-19 simulator where every circle in the simulation is a person. When two persons hit each other, i want the direction that they "bounce" off each other to be random. Currently i just mirror the current speed, which means the the persons follow a pre defined path, even when bouncing of each other.
This is my "move" function
move() {
if (this.willMove) {
this.xPos += this.xSpeed;
this.yPos += this.ySpeed;
}
}
This where i do my collision detection
collision(other) {
let distance = dist(this.xPos, this.yPos, other.xPos, other.yPos);
if (distance < this.personRadius + other.personRadius) {
this.changeDirection();
return true;
} else {
return false;
}
}
The things handeling the changing of direction:
changeDirection() {
this.mirrorXSpeed();
this.mirrorYSpeed();
}
mirrorXSpeed() {
this.xSpeed = this.xSpeed * -1;
}
mirrorYSpeed() {
this.ySpeed = this.ySpeed * -1;
}
I have tried multiplying the speed by -0.95, but this just decreases the speed.
The full project can be found here: https://github.com/perkynades/Simulation-of-COVID19/tree/part1
This might help, it will make all the people bounce in a random direction when called.
You will have to add this.speed to your person constructor, and make sure angle mode is set to radians.
changeDirection() {
//This next line will change the speed by a random amount,
//delete it if you don't like it,
//or change the range for a different behavior
this.speed += random(1,3) * random([-1,1])
let ang = random(PI * 2)
this.changeXSpeed(ang);
this.changeYSpeed(ang);
}
changeXSpeed(ang) {
this.xSpeed = this.speed * cos(ang);
}
changeYSpeed(ang) {
this.ySpeed = this.speed * sin(ang);
}
}
If you want a more realistic bounce, I would check out Chris courses video on Collision detection it gives a natural fell to circle on circle collisions, and even though it is not all P5.js, it is was very helpful to me and I hope that it will be for you too.
UPDATE: I wanted to let you know that I'd solved this problem, if not necessarily answered my own question. Rather than trying to target the element of the push array, I did this:
In
var ground=[], water=[], enemies=[], environment=[];
I added
tokens=[];
to the end.
Then I wrote a new function, updateTokens:
function updateTokens() {
for (var i = 0; i < tokens.length; i++) {
tokens[i].update();
tokens[i].draw();
if (player.minDist(tokens[i]) <= player.width - platformWidth / 2) {
gameOver();
}
}
if (tokens[0] && tokens[0].x < - platformWidth) {
tokens.splice(0, 1);
}
}
(The 'gameOver();' function is just for testing purposes).
Then I added 'spawnTokensSprites();' to the spawnSprites(); function.
Next, I wrote a new function to spawnTokensSprites:
function spawnTokensSprites() {
if (score > 0 && rand(0, 20) === 0 && platformHeight < 3 {
if (Math.random() > 0.5) {
tokens.push(new Sprite(
canvas.width + platformWidth % player.speed,
platformBase - platformHeight * platformSpacer - platformWidth,
'tokens'
));
}
}
}
Then I added 'updateTokens();' to the animate function, and finally, I added 'tokens=[]' to the 'startGame()' function.
So there it is. Not the answer to the original question, but a working solution to the problem I had. I hope this can help someone else, which is why I updated my post.
---------------------------------------------------------
I'm well out of my depth here. I've been following this tutorial to make an HTML5 canvas game. It's great, and I've learned loads, but I'm totally stuck.
I have a vector for sprites
function Sprite(x, y, type) {
this.x = x;
this.y = y;
this.width = platformWidth;
this.height = platformWidth;
this.type = type;
Vector.call(this, x, y, 0, 0);
this.update = function () {
this.dx = -player.speed;
this.advance();
};
this.draw = function () {
ctx.save();
ctx.translate(0.5, 0.5);
ctx.drawImage(assetLoader.imgs[this.type], this.x, this.y);
ctx.restore();
};
}
Sprite.prototype = Object.create(Vector.prototype);
from which all sprites inherit. To generate 'token' sprites, I use this function:
function spawnEnvironmentSprites() {
if (score > 0 && rand(0, 20) === 0 && platformHeight < 3) {
if (Math.random() > 0.5) {
environment.push(new Sprite(
canvas.width + platformWidth % player.speed,
platformBase - platformHeight * 2 * platformSpacer - platformWidth,
'tokens'
));
}
else if (platformLength > 2) {
environment.push(new Sprite(
canvas.width + platformWidth % player.speed,
platformBase - platformHeight * 1.5 * platformSpacer - platformWidth,
'tokens'
));
}
}
}
Which draws the sprites to the screen. What I cannot do is single these type of sprites out from the array for collision detection. I've tried to use an 'if' statement from the 'updateEnemies' function:
if (player.minDist(enemies[i]) <= player.width - platformWidth/2) {
gameOver();
}
}
within the 'updateEnvironment' function, where I substitute 'enemies' for 'environment', but because I don't know how to specify 'tokens' from 'environment', using this line results in no environment sprites being drawn to the canvas, including platforms. Earlier today, I tried including 'tokens' in 'enemySprites', which worked in so much as when the player collided, the gameOver() function ran, but I couldn't then figure out how to give 'tokens' different behaviour (ie. Score increase rather than gameOver). I should mention that the sprites are called this way because of the assetLoader function I've used.
So long story short, how can I collide with 'tokens' and have everything else behave as it should?
Thanks in advance.
EDIT: Sorry, I forgot to mention that the array for environment is declared in a variable that looks like this:
var ground = [], water = [], enemies = [], environment = [];
Thanks.
UPDATE: Ok, I still haven't sorted this out but I've made a change that I think will make things a bit easier for you to help me with(!)
I've removed 'tokens' from the 'spawnEnvironmentSprites()' function and added a condition to 'spawnEnemySprites' that pushes 'tokens'. This means they now have the same behaviour as my other 'enemies' i.e.. gameOver() is run upon collision detection. My question now is, how do I target 'tokens' in this line of code so that I can give that collision different behaviour? I'd like the 'token' sprite to disappear and the score to increase, but I don't know how to target just the 'tokens' part of the array. The line that deals with the collisions is:
if (player.minDist(enemies[i]) <= player.width - platformWidth/2) {
gameOver();
}
}
Can you help? Thanks in advance.
I am trying to draw birds whose wings oscillate based on their velocity. Simply put, the faster my birds fly, the faster their wings should oscillate.
My complete code is below and it doesn't do what I want. What I've done to create the oscillation is make flyingFactor vary based on the magnitude of velocity in my displayAndMoveWings function. However when I draw everything I find that, because velocity changes all the time (i.e. triggered by the random acceleration force in the draw function), so does flyingFactor and means that my birds' wings don't oscillate at all and look very buggy.
Any way to make it work? I want my birds' wings to look like they naturally oscillate, only faster and slower as my birds accelerate or decelerate.
Thank you so much in advance!
angleMode = "degrees";
var Bird = function(m,x,y){
this.mass = m;
this.position = new PVector(x,y);
this.velocity = new PVector(0,0);
this.acceleration = new PVector(0,0);
};
Bird.prototype.applyForce = function(force) {
var f = PVector.div(force, this.mass);
this.acceleration.add(f);
};
Bird.prototype.update = function() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.mult(0);
this.velocity.limit(3);
};
Bird.prototype.displayAndMoveWings = function() {
this.start=-110;
this.stop = this.start + 110;
this.flyingFactor=cos(360+frameCount*this.velocity.mag()*10)*20;
stroke(0, 0, 0);
strokeWeight(2);
noFill();
arc(this.position.x,this.position.y,this.mass,this.mass,this.start-this.flyingFactor,this.stop-this.flyingFactor);
arc(this.position.x+this.mass,this.position.y,this.mass,this.mass,this.start+this.flyingFactor-70,this.stop+this.flyingFactor-70);
};
Bird.prototype.checkEdges = function() {
if (this.position.x > width) {
this.position.x = 0;
} else if (this.position.x < 0) {
this.position.x = width;
}
if (this.position.y > height) {
this.position.y = 0;
} else if (this.position.y < 0) {
this.position.y = height;
}
};
var bird1 = new Bird(15, width/2, height/2);
var draw = function() {
background(255, 255, 255);
bird1.update();
bird1.displayAndMoveWings();
var randomAcceleration = new PVector(random(-3,3),random(-3,3));
bird1.checkEdges();
bird1.applyForce(randomAcceleration);
};
I think I may have found a hack... Before my displayAndMoveWings function I created a new global variable called whatIsVelocity. Then in displayAndMoveWings I wrote the following:
if (frameCount % 60 === 0){
whatIsVelocity = this.velocity.mag();
}
this.flyingFactor=cos(360+frameCount*whatIsVelocity*10)*20;
Effectively what this does is pull the velocity every 60 frames (approximately 2 seconds) and introduces that velocity into flyingFactor, meaning that it doesn't get recalculated every frame like in my previous code above. Not super pretty but it achieves my purpose.
I'm building a game using the canvas element powered by JavaScript. Part of my player class includes an update() method which is called once per tick. In this method, I'm doing some math to update the players velocity based on keyboard input and also to move the player. Here's a chunk of that code:
// Gradually make the players velocity 0
if(this.xv > 0) {
this.xv -= 0.1;
} else if(this.xv < 0) {
this.xv += 0.1;
}
if(this.yv > 0) {
this.yv -= 0.1;
} else if(this.yv < 0) {
this.yv += 0.1;
}
// Update player position based on velocity
this.x += this.xv;
this.y += this.yv;
// Update velocity based on keyboard inputs
if(keyState[87]) {
this.yv -= 0.5;
}
if(keyState[65]) {
this.xv -= 0.5;
}
if(keyState[83]) {
this.yv += 0.5;
}
if(keyState[68]) {
this.xv += 0.5;
}
Now in theory this should all work okay, if the player holds down the W key for 4 ticks their velocity will be 2, and then after 40 more ticks their velocity will be reduced down to 0.
This doesn't work in practice though, as JavaScript doesn't seem to be entirely accurate when it comes to working with floating point numbers. If I console.log() the velocity variables each game tick I get this kind of output:
x: -1.0241807402167069e-14 y: -1.379452108096757e-14
x: 0.09999999999998976 y: 0.09999999999998621
x: -1.0241807402167069e-14 y: -1.379452108096757e-14
x: 0.09999999999998976 y: 0.09999999999998621
So there's two things that look wrong here, one is that JavaScript never calculates the velocity with good precision, and the other is when the velocity is negative it's always at least -1, which is a problem because the player sprite will now move at 1 pixel per tick.
How can I get more accurate calculations for this task?
I recommend using an "exponential decay" approach to smoothing out your velocity transitions. Instead of the conditional block you currently use to reduce the velocity to zero, I'd use the following:
this.xv *= 0.9;
this.yv *= 0.9;
Note that this caps your maximum velocity at ten times your constant acceleration, and that changing the rate of decay will change that multiplier. This might be okay, but if it's not, you can tweak the equations to ease into a target velocity:
var p = 0.9;
var q = 1.0 - p;
this.xv = this.xv * p + this.txv * q;
this.yv = this.yv * p + this.tyv * q;
Disclaimer: This has no real basis in Newtonian physics; it's just something I came up with to help smooth out state transitions in a robot. But it worked great for me, and hopefully will for you, too.