Related
A last issue i have in this code is that i am not sure how to create color change effect as 8 directional.
I can only map a mouseX to make it lerpColor horizontally or vertically .
But how do i make it work through moving both mouseX and mouseY?
I had it in shift_Color method within the class. I tried to state that within a certain dist(), lerpColor. But now it only showing black color rather than the changing color effect.
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(243, 243, 243);
//background(backCol);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let a = 0; a < cubes.length; a++) {
cubes[a].update();
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 30;
this.stroke = 70;
this.gap = 110
this.shift1 = color(96);
this.shift2 = color(244);
}
update() {
this.shape();
this.shift_Color();
}
shape() {
push();
stroke(this.stroke);
//fill(this.shift1);
this.shift_Color();
translate(this.x - width / 2, this.y - height / 2, 0);
this.magnetic()
box(this.size);
pop();
}
shift_Color() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.shift1 = color(96);
this.shift2 = color(244);
this.shiftX = map(mouseX - width/2,this.gap,distance,0,1.0);
this.change = lerpColor(this.shift1, this.shift2, this.shiftX);
fill(this.change);
} else {
fill(this.shift1);
}
}
magnetic() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.attract = atan2(mouseY - this.y, mouseX - this.x);
rotateX(this.attract);
rotateY(this.attract);
} else {
rotateX(millis() / 1000);
rotateY(millis() / 1000);
}
}
}
If I understood your question properly, there are two problems in your code.
The first is the fact that because you are trying to map the distance between mouse and the cube to number between 0 and 1, you should write lerpColor(this.shift2, this.shift1, this.shiftX) instead of lerpColor(this.shift1, this.shift2, this.shiftX), since this.shift2 is the lighter color and will be the inner color.
Another problem is when mapping the change variable, change should be calculated based on the distance between mouse and the cube (which is the distance variable), not mouseX or mouseY. Solution is to simply do map(distance, 0, this.gap, 0, 1);.
let cubes = [];
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
backCol = color(243, 243, 243);
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
let xPos = map(i, 0, 9, 50, width - 50);
let yPos = map(j, 0, 9, 50, height - 50);
cubes.push(new Cubes(xPos, yPos));
}
}
}
function draw() {
background(backCol);
noFill();
for (let cube of cubes) {
cube.update();
}
}
class Cubes {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 30;
this.stroke = 70;
this.gap = 110
this.shift1 = color(96);
this.shift2 = color(244);
}
update() {
this.shape();
this.shift_Color();
}
shape() {
push();
stroke(this.stroke);
//fill(this.shift1);
this.shift_Color();
translate(this.x - width / 2, this.y - height / 2, 0);
this.magnetic()
box(this.size);
pop();
}
shift_Color() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.shiftX = map(distance, 0, this.gap, 0, 1);
// this.shiftX = map(mouseX - width/2,this.gap,distance,0,1.0);
this.change = lerpColor(this.shift2, this.shift1, this.shiftX);
// this.change = lerpColor(this.shift1, this.shift2, this.shiftX);
fill(this.change);
} else {
fill(this.shift1);
}
}
magnetic() {
let distance = dist(mouseX, mouseY, this.x, this.y);
if (distance < this.gap) {
this.attract = atan2(mouseY - this.y, mouseX - this.x);
rotateX(this.attract);
rotateY(this.attract);
} else {
rotateX(millis() / 1000);
rotateY(millis() / 1000);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
I also modified some of your code. Like the line
this.shift1 = color(96);
this.shift2 = color(244);
which is not needed currently since neither of these variable changes during execution.
I am working on a project on Khan Academy in which I have to create a game with at least 3 levels. I have developed most of the game but when I tried to proceed from one level to next the game somehow stops.
Here is the full project:
Project Link
/**
* Contains 3 levels
*
*
* Changed Ground
* Brown rectangle is replaced with Dirt Block.
*
* Scoring system changed
* Collecting Good sticks gets 1 point.
* Collecting Bad sticks gets -1 point. (i.e. loses point).
* Hitting rocks will lose 1 point.
*
**/
var level = 0;
var nosOfSticks = 5;
var target = 0;
var speed = 1;
var endLevel = false;
var buttonClicked = false;
var levelButtonEnabled = false;
var startButtonEnabled = true;
var Beaver = function(x, y) { // Beaver Constructor
this.x = x;
this.y = y;
this.img = getImage("creatures/Hopper-Happy");
this.sticks = 0;
};
Beaver.prototype.draw = function() { // Draw function to draw beaver
fill(255, 0, 0);
this.x = constrain(this.x, 0, width-40);
this.y = constrain(this.y, 0, height-50);
image(this.img, this.x, this.y, 40, 40);
};
Beaver.prototype.hop = function() { // Hop function to make beaver hop
this.img = getImage("creatures/Hopper-Jumping");
this.y -= speed * 5;
};
Beaver.prototype.hopLeft = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.x -= speed * 5;
};
Beaver.prototype.hopRight = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.x += speed * 5;
};
Beaver.prototype.fall = function() { // fall function makes beaver fall on the ground
this.img = getImage("creatures/Hopper-Happy");
this.y += speed * 5;
};
Beaver.prototype.checkForStickGrab = function(stick) { // function that checks sticks grab
if ((stick.x >= this.x && stick.x <= (this.x + 40)) &&
(stick.y >= this.y && stick.y <= (this.y + 40))) {
stick.y = -400;
this.sticks++;
}
};
Beaver.prototype.checkForBadStickGrab = function(badstick) { // function that checks badsticks grab
if ((badstick.x >= this.x && badstick.x <= (this.x + 40)) &&
(badstick.y >= this.y && badstick.y <= (this.y + 40))) {
badstick.y = -400;
this.sticks--;
}
};
Beaver.prototype.checkForRockHit = function(rock) { // function that checks rocks hit
if ((rock.x >= this.x - 40 && rock.x <= (this.x + 40)) &&
(rock.y >= this.y - 30 && rock.y <= (this.y + 40))) {
rock.x = -400;
this.sticks--;
}
};
// Drawing Sticks
var Stick = function(x, y) { // Stick constructor
this.x = x;
this.y = y;
};
Stick.prototype.draw = function() { // Draw function to draw sticks
fill(0, 0, 0);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
var Badstick = function(x, y) { // Bad Sticks constructor
Stick.call(this, x, y);
};
//Badstick.prototype = Object.create(Stick);
Badstick.prototype.draw = function() { //Draw function to draw badsticks
fill(255, 0, 13);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
// Drawings Rocks
var Rock = function(x, y) { // rocks constructor
this.x = x;
this.y = y;
this.img = getImage("cute/Rock");
};
Rock.prototype.draw = function(x, y) { // function to draw rocks
fill(0, 0, 0);
image(this.img, this.x, this.y, 40, 40);
};
var beaver = new Beaver(200, 300);
var sticks = [];
for (var i = 0; i < nosOfSticks; i++) {
sticks.push(new Stick(i * 100 + 400, random(20, 260)));
}
var badSticks = [];
for (var i = 0; i < nosOfSticks/2; i++) {
badSticks.push(new Badstick(i * 200 + 400, random(20, 270)));
}
var rocks = [];
for ( var i = 0; i < nosOfSticks * 0.375; i++) {
rocks.push(new Rock(random(0, 375), i * random() - (i * 100)));
}
var grassXs = [];
for (var i = 0; i < 25; i++) {
grassXs.push(i*20);
}
var blockXs = [];
for (var i = 0; i < 25; i++) {
blockXs.push(i*20);
}
var Button = function (x, y, w, h, color, text, size, font, textcolor, best) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.text = text;
this.size = size;
this.font = font;
this.textcolor = textcolor;
this.best = best;
};
Button.prototype.draw = function() {
rectMode(CORNER);
fill(this.color);
rect(this.x, this.y, this.w, this.h);
fill(this.textcolor);
stroke(this.textcolor);
textFont(this.font, this.size);
text(this.text, this.x + (this.w/2 - this.w/2.5), this.y + (this.h/2 + this.size/2.5));
/*textFont(this.font, this.size / 2);
text("Best : " + this.best, this.x + 10, this.y + 90);*/
};
Button.prototype.clicked = function() {
if(mouseIsPressed && mouseX >= this.x && mouseX <= this.x + this.w && mouseY >= this.y && mouseY <= this.y + this.h ) {
return true;
}
};
var nextButton = new Button(315, 360, 75, 30, color(0, 255, 0), "Next Level", 12, "Aerial Bold", color(0, 0, 0));
var startButton = new Button(315, 360, 75, 30, color(0, 255, 0), "Start Again", 12, "Aerial Bold", color(0, 0, 0));
var playButton = new Button(140, 250, 120, 50, color(0, 0, 0), "PLAY", 40, "Aerial Bold", color(255, 255, 255));
var level1Button = new Button(30, 120, 100, 100, color(0, 0, 0), "Level 1", 25, "Aerial Bold", color(255, 255, 255));
var level2Button = new Button(140, 120, 100, 100, color(0, 0, 0), "Level 2", 25, "Aerial Bold", color(255, 255, 255));
var level3Button = new Button(250, 120, 100, 100, color(0, 0, 0), "Level 3", 25, "Aerial Bold", color(255, 255, 255));
var drawWin = function() {
fill(255, 0, 0);
textSize(36);
text("YOU WIN!!!!", 100, 200);
nextButton.draw();
};
var drawLoss = function() {
fill(255, 0, 0);
textSize(36);
text("YOU LOSE!!!!", 100, 200);
startButton.draw();
};
var movement = function() {
if (keyIsPressed) {
if(keyCode === UP) {
beaver.hop();
} /*else if(keyCode === LEFT) {
beaver.hopLeft();
} else if(keyCode === RIGHT) {
beaver.hopRight();
} */
} else { beaver.fall();}
};
var drawScore = function() {
fill(0, 255, 0);
textSize(18);
text("Score: " + beaver.sticks, 10, 390);
};
var isWin = function() {
if(beaver.sticks >= target) {
drawWin();
speed = 1;
return true;
}
};
var isLoss = function() {
if (beaver.sticks < target ) {
speed = 1;
drawLoss();
return true;
}
};
var drawBackground = function() {
//static
speed = 1;
background(227, 254, 255);
stroke(0, 0, 0);
rectMode(CORNER);
rect(0, height*0.90, width, height*0.10);
for (var i = 0; i < grassXs.length; i++) {
image(getImage("cute/GrassBlock"), grassXs[i], height*0.85, 35, 20);
image(getImage("cute/DirtBlock"), grassXs[i], height*0.85, 35, 60);
grassXs[i] -= speed;
if (grassXs[i] <= - 20) {
grassXs[i] = width;
}
}
};
var drawSticks = function() {
for (var i = 0; i < sticks.length; i++) {
sticks[i].draw();
beaver.checkForStickGrab(sticks[i]);
sticks[i].x -= speed;
}
};
var drawBadSticks = function() {
for (var i = 0; i < badSticks.length; i++) {
badSticks[i].draw();
beaver.checkForBadStickGrab(badSticks[i]);
badSticks[i].x -= speed;
}
};
var drawRocks = function() {
for (var i = 0; i < rocks.length; i++) {
rocks[i].draw();
beaver.checkForRockHit(rocks[i]);
rocks[i].y += speed;
}
};
var drawLevel = function() {
speed = 1;
drawBackground();
if (level === 1) {
target = 1;
drawSticks();
}
if (level === 2) {
target = 1;
drawSticks();
drawBadSticks();
}
if (level === 3) {
target = 1;
drawBadSticks();
drawSticks();
drawRocks();
}
beaver.draw();
movement();
drawScore();
if (sticks[nosOfSticks - 1].x < -5) {
isWin();
isLoss();
}
};
var drawLevels = function() {
level = "l";
background(0, 0, 0);
level1Button.draw();
level2Button.draw();
level3Button.draw();
if (level1Button.clicked() && level === "l") {
level = 1;
drawLevel();
} else if (level2Button.clicked() && level === "l") {
level = 2;
drawLevel();
} else if (level3Button.clicked() && level === "l") {
level = 3;
drawLevel();
}
};
var drawStart = function() {
level = 0;
background(0);
text("Hoppy Beaver", 75, 50);
text("Extreme", 120, 100);
playButton.draw();
if (playButton.clicked() && level === 0) {
levelButtonEnabled = false;
drawLevels();
}
};
//drawStart();
mouseClicked = function() {
if (nextButton.clicked() || startButton.clicked()) {
if (beaver.sticks >= 1) {
if (level === 0) {
level = 1;
sticks = [];
draw();
isWin = false;
}
if (level === 1) {
level = 2;
sticks = [];
draw();
isWin = false;
}
if (level === 2) {
level = 3;
sticks = [];
draw();
isWin = false;
}
if (level === 3) {
level = 1;
sticks = [];
isWin = false;
draw();
}
} else if (beaver.sticks < 1) {
if (level === 1) {
level = 1;
sticks = [];
drawLevel();
isLoss = false;
}
if (level === 2) {
level = 2;
sticks = [];
drawLevel();
isLoss = false;
}
if (level === 3) {
level = 3;
sticks = [];
drawLevel();
isLoss = false;
}
}
}
};
draw = function() {
speed = 1;
if (level === 1) {
drawLevel();
} else if (level === 2) {
drawLevel();
} else if (level === 3) {
drawLevel();
} else if (level === "l") {
drawLevels();
} else { drawStart(); }
};
welcome to stackoverflow. The problem with your code is this bit right here in the drawLevel function.
if (sticks[nosOfSticks - 1].x < -5) {
isWin();
isLoss();
}
At the start of your program you initialize the sticks array with some stick objects in line 124. When level 1 ends and the next button is clicked, you set the sticks array to an empty array sticks=[] in the mouseClicked function.However, you never re-add anything into the sticks array. Thus, when that block of code runs, the element at position nosOfSticks-1 is undefined, leading to your problem.My suggestion is to make a for loop after sticks=[] to refill the sticks array just like in line 124.
Good Luck!
Also, take a look at this guide for debugging help, how to debug small programs.
Learning Javascript and stack in small game example.
So why println(beaver.holes) has "NaN" value ??? It must be normal number without flouting point.
var Beaver = function(x, y) {
this.x = x;
this.y = y;
this.img = getImage("creatures/Hopper-Happy");
this.sticks = 0;
};
Beaver.prototype.draw = function() {
fill(255, 0, 0);
this.y = constrain(this.y, 0, height-50);
image(this.img, this.x, this.y, 40, 40);
};
Beaver.prototype.hop = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.y -= 5;
};
Beaver.prototype.fall = function() {
this.img = getImage("creatures/Hopper-Happy");
this.y += 5;
};
Beaver.prototype.checkForStickGrab = function(stick) {
if ((stick.x >= this.x && stick.x <= (this.x + 40)) &&
(stick.y >= this.y && stick.y <= (this.y + 40))) {
stick.y = -11;
this.sticks++;
}
};
Beaver.prototype.checkForHoleDrop = function(hole) {
if ((hole.x >= this.x && hole.x<=(this.x +40)) &&
(hole.y >=this.y && hole.y <= (this.y + 40))) {
hole.y = -11;
this.holes++;
}
};
var Stick = function(x, y) {
this.x = x;
this.y = y;
};
var Hole = function(x,y) {
this.x = x;
this.y = y;
};
Hole.prototype.draw = function() {
rectMode(CENTER);
noStroke();
fill(120, 144, 204);
ellipse(this.x,this.y, 51,19);
fill(0, 40, 71);
ellipse(this.x,this.y, 40,15);
};
Stick.prototype.draw = function() {
fill(89, 71, 0);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
var beaver = new Beaver(37, 300);
var sticks = [];
for (var i = 0; i < 40; i++) {
sticks.push(new Stick(i * 44 + 300, random(44, 260)));
}
// holes var
var holes = [];
for (var i = 0;i< 10; i ++) {
holes.push(new Hole(random(33,400)*i + 306, 378));
}
var grassXs = [];
for (var i = 0; i < 25; i++) {
grassXs.push(i*18);
}
draw = function() {
// static
background(227, 254, 255);
fill(130, 79, 43);
rectMode(CORNER);
rect(0, height*0.90, width, height*0.10);
for (var i = 0; i < grassXs.length; i++) {
image(getImage("cute/GrassBlock"), grassXs[i], height*0.85, 20, 20);
grassXs[i] -= 1;
if (grassXs[i] <= -32) {
grassXs[i] = width;
}
}
// making holes
for (var i = 0; i < holes.length; i++) {
holes[i].draw();
beaver.checkForHoleDrop(holes[i]);
holes[i].x -=2;
}
for (var i = 0; i < sticks.length; i++) {
sticks[i].draw();
beaver.checkForStickGrab(sticks[i]);
sticks[i].x -= 2;// value turn speed of sticks
}
So here if we print beaver.holes on screen it will be give us NaN value.
textSize(18);
text("Score: " + beaver.sticks, 20, 30);
textSize(18);
text("Score: " + beaver.holes, 105, 30);
if (beaver.sticks/sticks.length >= 0.95) {
textSize(36);
text("YOU WIN!!!!", 100, 200);
}
if (beaver.hole >41) {
textSize(36);
text("YOU LOSE!!!",100,200);}
//println(beaver.holes/holes.length);
if (keyIsPressed && keyCode === 0) {
beaver.hop();
} else {
beaver.fall();
}
beaver.draw();
};
Looks like holes was never initialized for beaver prototypes.
Try modifying the constructor function to look like so.
var Beaver = function(x, y) {
this.x = x;
this.y = y;
this.img = getImage("creatures/Hopper-Happy");
this.sticks = 0;
this.holes = 0;
};
Performing a ++ operation on an undefined variable returns a NaN result.
I have JavaScript code for a memory game for Khan Academy and I have no idea how to make a tile change color when the mouse is over it. As a test I tried to draw a star on a tile when the mouse was over it in the "if (tiles[i].isUnderMouse(mouseX, mouseY))" in the mouseClicked function but of course that only worked when the mouse is clicked and because the tiles are in a draw function the star would be put behind the new set of tiles after the next click. I don't really even know where to start to do this. Can anyone help me?
//Card face down image variable
var fdImage = image(getImage("avatars/questionmark"), this.x, this.y, this.width, this.width);
var Tile = function(x, y, face) {
this.x = x;
this.y = y;
this.face = face;
this.width = 70;
};
Tile.prototype.drawFaceDown = function() {
fill(214, 247, 202);
strokeWeight(2);
rect(this.x, this.y, this.width, this.width, 10);
image(getImage("avatars/questionmark"), this.x, this.y, this.width, this.width);
this.isFaceUp = false;
};
Tile.prototype.drawFaceUp = function() {
fill(214, 247, 202);
strokeWeight(2);
rect(this.x, this.y, this.width, this.width, 10);
image(this.face, this.x, this.y, this.width, this.width);
this.isFaceUp = true;
};
Tile.prototype.isUnderMouse = function(x, y) {
if ( x >= this.x && x <= this.x + this.width &&
y >= this.y && y <= this.y + this.width ) {
}
return x >= this.x && x <= this.x + this.width &&
y >= this.y && y <= this.y + this.width;
};
// Global config
var NUM_COLS = 5;
var NUM_ROWS = 4;
// Declare an array of all possible faces
var faces = [
//saplings
getImage("avatars/leafers-seed"),
getImage("avatars/leafers-seedling"),
getImage("avatars/leafers-sapling"),
getImage("avatars/leafers-tree"),
getImage("avatars/leafers-ultimate"),
getImage("avatars/piceratops-seed"),
getImage("avatars/piceratops-seedling"),
getImage("avatars/piceratops-sapling"),
getImage("avatars/piceratops-tree"),
getImage("avatars/piceratops-ultimate"),
getImage("avatars/aqualine-seed"),
getImage("avatars/aqualine-seedling"),
getImage("avatars/aqualine-sapling"),
getImage("avatars/aqualine-tree"),
getImage("avatars/aqualine-ultimate"),
//figures
getImage("avatars/marcimus"),
getImage("avatars/mr-pants"),
getImage("avatars/mr-pink"),
getImage("avatars/old-spice-man"),
getImage("avatars/orange-juice-squid"),
getImage("avatars/purple-pi"),
getImage("avatars/spunky-sam"),
//robots
getImage("avatars/robot_female_1"),
getImage("avatars/robot_female_2"),
getImage("avatars/robot_female_3"),
getImage("avatars/robot_male_1"),
getImage("avatars/robot_male_2"),
getImage("avatars/robot_male_3"),
//important figures
getImage("creatures/Hopper-Happy"),
getImage("creatures/Hopper-Cool"),
getImage("creatures/Hopper-Jumping"),
getImage("creatures/OhNoes"),
getImage("creatures/BabyWinston"),
getImage("creatures/Winston"),
//rpg material
getImage("space/beetleship"),
getImage("space/healthheart"),
getImage("space/octopus"),
getImage("space/planet"),
getImage("space/rocketship"),
getImage("space/star"),
];
// Make an array which has 2 of each, then randomize it
var possibleFaces = faces.slice(0);
var selected = [];
for (var i = 0; i < (NUM_COLS * NUM_ROWS) / 2; i++) {
// Randomly pick one from the array of remaining faces
var randomInd = floor(random(possibleFaces.length));
var face = possibleFaces[randomInd];
// Push twice onto array
selected.push(face);
selected.push(face);
// Remove from array
possibleFaces.splice(randomInd, 1);
}
// Now we need to randomize the array
selected.sort(function() {
return 0.5 - Math.random();
});
// Create the tiles
var tiles = [];
for (var i = 0; i < NUM_COLS; i++) {
for (var j = 0; j < NUM_ROWS; j++) {
tiles.push(new Tile(i * 78 + 10, j * 78 + 40, selected.pop()));
}
}
background(255, 255, 255);
// Now draw them face up
for (var i = 0; i < tiles.length; i++) {
tiles[i].drawFaceDown();
}
var flippedTiles = [];
var delayStartFC = null;
var numTries = 0;
mouseClicked = function() {
for (var i = 0; i < tiles.length; i++) {
//
if (tiles[i].isUnderMouse(mouseX, mouseY)) {
//
if (flippedTiles.length < 2 && !tiles[i].isFaceUp) {
tiles[i].drawFaceUp();
flippedTiles.push(tiles[i]);
if (flippedTiles.length === 2) {
numTries++;
if (flippedTiles[0].face === flippedTiles[1].face) {
flippedTiles[0].isMatch = true;
flippedTiles[1].isMatch = true;
}
delayStartFC = frameCount;
loop();
}
}
}
}
var foundAllMatches = true;
for (var i = 0; i < tiles.length; i++) {
foundAllMatches = foundAllMatches && tiles[i].isMatch;
}
if (foundAllMatches) {
fill(0, 0, 0);
textSize(20);
text("You found them all in " + numTries + " tries!", 20, 375);
}
};
draw = function() {
if (delayStartFC && (frameCount - delayStartFC) > 30) {
for (var i = 0; i < tiles.length; i++) {
if (!tiles[i].isMatch) {
tiles[i].drawFaceDown();
}
}
flippedTiles = [];
delayStartFC = null;
noLoop();
}
};
In order to add a hover state to the tiles in this Khan Academy challenge, you must first add a new method to your Tile object
Tile.prototype.hoverState = function() {
fill(150, 247, 202);
strokeWeight(2);
rect(this.x, this.y, this.width, this.width, 10);
image(getImage("avatars/leaf-green"), this.x, this.y, this.width, this.width);
this.isFaceUp = false;
};
Afterwards you will need to use mouseMoved like this:
mouseMoved = function() {
for (var i = 0; i < tiles.length; i++) {
if (tiles[i].isUnderMouse(mouseX, mouseY) && !tiles[i].isFaceUp) {
tiles[i].hoverState();
} else if (tiles[i].isFaceUp) {
tiles[i].drawFaceUp();
} else {
tiles[i].drawFaceDown();
}
}
};
I am trying to create a animation where circles run from right to left. The circles' colours are selected randomly by a function. I have created a fiddle where one circle runs from right to left. Now my function creates a random colour. This function is executed every second and the circle changes its colour every second, instead of a new circle with the random picked colour become created. How can I change it so that it draws a new circle every second on the canvas and doesn't only change the colour of the circle?
This is my function:
function getRandomElement(array) {
if (array.length == 0) {
return undefined;
}
return array[Math.floor(Math.random() * array.length)];
}
var circles = [
'#FFFF00',
'#FF0000',
'#0000FF'
];
function drawcircles() {
ctx.beginPath();
ctx.arc(ballx * 108, canvasHeight / 2, x*5, 0, 2*Math.PI, false);
ctx.fillStyle = getRandomElement(circles);
ctx.fill();
ctx.closePath;
}
Comments on your question:
You are changing the color of the fillStyle to a random color at each frame. This is the reason why it keeps "changing" color. Set it to the color of the circle:
context.fillStyle = circle.color;
make circles with x, y, diameter, bounciness, speed, and color using an array
draw and update them with requestAnimationFrame (mine is a custom function)
My answer:
I made this just last night, where some circles follow the cursor and "bounce" off the edges of the screen. I tested the code and it works.
I might post a link later, but here is all of the code right now...
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas"></canvas>
<script>
var lastTime = 0;
function requestMyAnimationFrame(callback, time)
{
var t = time || 16;
var currTime = new Date().getTime();
var timeToCall = Math.max(0, t - (currTime - lastTime));
var id = window.setTimeout(function(){ callback(currTime + timeToCall); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
}
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = window.innerWidth - 20;
canvas.height = window.innerHeight - 20;
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
var circles = [];
var mouse =
{
x: 0,
y: 0
}
function getCoordinates(x, y)
{
return "(" + x + ", " + y + ")";
}
function getRatio(n, d)
{
// prevent division by 0
if (d === 0 || n === 0)
{
return 0;
}
else
{
return n/d;
}
}
function Circle(x,y,d,b,s,c)
{
this.x = x;
this.y = y;
this.diameter = Math.round(d);
this.radius = Math.round(d/2);
this.bounciness = b;
this.speed = s;
this.color = c;
this.deltaX = 0;
this.deltaY = 0;
this.drawnPosition = "";
this.fill = function()
{
context.beginPath();
context.arc(this.x+this.radius,this.y+this.radius,this.radius,0,Math.PI*2,false);
context.closePath();
context.fill();
}
this.clear = function()
{
context.fillStyle = "#ffffff";
this.fill();
}
this.draw = function()
{
if (this.drawnPosition !== getCoordinates(this.x, this.y))
{
context.fillStyle = this.color;
// if commented, the circle will be drawn if it is in the same position
//this.drawnPosition = getCoordinates(this.x, this.y);
this.fill();
}
}
this.keepInBounds = function()
{
if (this.x < 0)
{
this.x = 0;
this.deltaX *= -1 * this.bounciness;
}
else if (this.x + this.diameter > canvas.width)
{
this.x = canvas.width - this.diameter;
this.deltaX *= -1 * this.bounciness;
}
if (this.y < 0)
{
this.y = 0;
this.deltaY *= -1 * this.bounciness;
}
else if (this.y+this.diameter > canvas.height)
{
this.y = canvas.height - this.diameter;
this.deltaY *= -1 * this.bounciness;
}
}
this.followMouse = function()
{
// deltaX/deltaY will currently cause the circles to "orbit" around the cursor forever unless it hits a wall
var centerX = Math.round(this.x + this.radius);
var centerY = Math.round(this.y + this.radius);
if (centerX < mouse.x)
{
// circle is to the left of the mouse, so move the circle to the right
this.deltaX += this.speed;
}
else if (centerX > mouse.x)
{
// circle is to the right of the mouse, so move the circle to the left
this.deltaX -= this.speed;
}
else
{
//this.deltaX = 0;
}
if (centerY < mouse.y)
{
// circle is above the mouse, so move the circle downwards
this.deltaY += this.speed;
}
else if (centerY > mouse.y)
{
// circle is under the mouse, so move the circle upwards
this.deltaY -= this.speed;
}
else
{
//this.deltaY = 0;
}
this.x += this.deltaX;
this.y += this.deltaY;
this.x = Math.round(this.x);
this.y = Math.round(this.y);
}
}
function getRandomDecimal(min, max)
{
return Math.random() * (max-min) + min;
}
function getRoundedNum(min, max)
{
return Math.round(getRandomDecimal(min, max));
}
function getRandomColor()
{
// array of three colors
var colors = [];
// go through loop and add three integers between 0 and 255 (min and max color values)
for (var i = 0; i < 3; i++)
{
colors[i] = getRoundedNum(0, 255);
}
// return rgb value (RED, GREEN, BLUE)
return "rgb(" + colors[0] + "," + colors[1] + ", " + colors[2] + ")";
}
function createCircle(i)
{
// diameter of circle
var minDiameter = 25;
var maxDiameter = 50;
// bounciness of circle (changes speed if it hits a wall)
var minBounciness = 0.2;
var maxBounciness = 0.65;
// speed of circle (how fast it moves)
var minSpeed = 0.3;
var maxSpeed = 0.45;
// getRoundedNum returns a random integer and getRandomDecimal returns a random decimal
var x = getRoundedNum(0, canvas.width);
var y = getRoundedNum(0, canvas.height);
var d = getRoundedNum(minDiameter, maxDiameter);
var c = getRandomColor();
var b = getRandomDecimal(minBounciness, maxBounciness);
var s = getRandomDecimal(minSpeed, maxSpeed);
// create the circle with x, y, diameter, bounciness, speed, and color
circles[i] = new Circle(x,y,d,b,s,c);
}
function makeCircles()
{
var maxCircles = getRoundedNum(2, 5);
for (var i = 0; i < maxCircles; i++)
{
createCircle(i);
}
}
function drawCircles()
{
var ii = 0;
for (var i = 0; ii < circles.length; i++)
{
if (circles[i])
{
circles[i].draw();
ii++;
}
}
}
function clearCircles()
{
var ii = 0;
for (var i = 0; ii < circles.length; i++)
{
if (circles[i])
{
circles[i].clear();
ii++;
}
}
}
function updateCircles()
{
var ii = 0;
for (var i = 0; ii < circles.length; i++)
{
if (circles[i])
{
circles[i].keepInBounds();
circles[i].followMouse();
ii++;
}
}
}
function update()
{
requestMyAnimationFrame(update,10);
updateCircles();
}
function draw()
{
requestMyAnimationFrame(draw,1000/60);
context.clearRect(0,0,canvas.width,canvas.height);
drawCircles();
}
function handleError(e)
{
//e.preventDefault();
//console.error(" ERROR ------ " + e.message + " ------ ERROR ");
}
window.addEventListener("load", function()
{
window.addEventListener("error", function(e)
{
handleError(e);
});
window.addEventListener("resize", function()
{
canvas.width = window.innerWidth - 20;
canvas.height = window.innerHeight - 20;
});
window.addEventListener("mousemove", function(e)
{
mouse.x = e.layerX || e.offsetX;
mouse.y = e.layerY || e.offsetY;
});
makeCircles();
update();
draw();
});
</script>
</body>
</html>