Reputation:
I'm making an eCard with falling confetti and fireworks flying up from the bottom of the screen. The logic for both are almost identical:
I make an empty array for fireworks and confetti, and then fill them with objects, using my GetRandom(mix,max) function to create each one with a random value:
//fill confetti object array
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray.push(new Confetti(GetRandom(0,canvas.width), GetRandom(-200,-10), GetRandom(10,30), GetRandom(10,30), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(0,2*Math.PI),GetRandom(50,80)));
}
//fill firework object array
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray.push(new Firework(GetRandom(0,canvas.width), canvas.height, GetRandom(4,20), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(30,100), GetRandom(-10,10), GetRandom(50,200)));
}
Then they are drawn and updated in their specific ways, each one starting by setting context.fillStyle and .strokeStyle as the current object's color value:
//confetti.draw
Draw: function(x, y, width, height, color, rotationAngle) {
context.translate(x,y)
context.rotate(rotationAngle)
context.strokeStyle = color;
context.fillStyle = color;
context.beginPath();
context.rect(0, 0, width, height);
context.fill();
context.closePath();
context.resetTransform();
},
//firework.draw
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color;
context.moveTo(x,y);
context.lineTo(x-swayX,y-speedY);
context.stroke();
},
Then they are each updated:
//confetti.update
Update: function(modifier) {
this.y = this.y + (this.fallSpeed * modifier);
if (this.y > canvas.height) {this.x = GetRandom(0,canvas.width);this.y = GetRandom(-100,0);}
},
//firework.update
Update: function(modifier) {
this.x = this.x - this.swayX;
this.y = this.y - this.speedY;
if (this.y < -10) {this.x = GetRandom(0,canvas.width);this.y = canvas.height;this.speedY = GetRandom(30,100);this.swayX = GetRandom(-10,10)}
},
I have scoured the code over and over and I just can't seem to get a reason as to why the confetti all has random sizes, angles, fallrates, and colors, AND the fireworks all have random swayX and speedY values but all the same colors. The full code is below if anyone wants to run it in full:
//james gossling multimedia for web design spring 2018
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
var GetRandom = function(min, max) {
//set mins and maxes for ball speed to change angle slightly after ball reset
min = min;
max = max;
return Math.floor(Math.random() * (max - min + 1) + min);
};
//game classes go here
var Background = function(context,color) {
this.context = context;
this.color = color;
};
Background.prototype = {
DrawBackground: function() {
//for testing
//console.log('here')
context.strokeStyle = this.color;
context.fillStyle = this.color;
context.beginPath();
context.rect(0,0,canvas.width,canvas.height);
context.stroke(); // invoke stroke
context.fill(); // invoke fill
context.closePath();
},
};
Confetti = function(x, y, width, height, color, rotationAngle, fallSpeed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.rotationAngle = rotationAngle;
this.fallSpeed = fallSpeed;
};
Confetti.prototype = {
Draw: function(x, y, width, height, color, rotationAngle) {
context.translate(x,y)
context.rotate(rotationAngle)
context.strokeStyle = color;
context.fillStyle = color;
context.beginPath();
context.rect(0, 0, width, height);
context.fill();
context.closePath();
context.resetTransform();
},
GetX: function() {
return this.x;
},
GetY: function() {
return this.y;
},
GetWidth: function() {
return this.width;
},
GetHeight: function() {
return this.height;
},
GetColor: function() {
return this.color;
},
GetRotationAngle: function() {
return this.rotationAngle;
},
GetFallSpeed: function() {
return this.fallSpeed;
},
Update: function(modifier) {
this.y = this.y + (this.fallSpeed * modifier);
if (this.y > canvas.height) {this.x = GetRandom(0,canvas.width);this.y = GetRandom(-100,0);}
},
};
var DrawConfetti = function() {
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray[i].Draw(ConfettiArray[i].GetX(),ConfettiArray[i].GetY(),ConfettiArray[i].GetWidth(),ConfettiArray[i].GetHeight(),ConfettiArray[i].GetColor(),ConfettiArray[i].GetRotationAngle());
}
}
var UpdateConfetti = function(modifier) {
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray[i].Update(modifier);
}
};
Firework = function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
this.x = x;
this.y = y;
this.lineWidth = lineWidth;
this.color = color;
this.speedY = speedY;
this.swayX = swayX;
//this.rotationAngle = rotationAngle;
this.blastRadius = blastRadius;
};
Firework.prototype = {
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color;
context.moveTo(x,y);
context.lineTo(x-swayX,y-speedY);
context.stroke();
},
GetX: function() {
return this.x;
},
GetY: function() {
return this.y;
},
GetLineWidth: function() {
return this.lineWidth;
},
GetColor: function() {
return this.color;
},
GetSpeedY: function() {
return this.speedY;
},
GetSwayX: function() {
return this.swayX;
},
GetRotationAngle: function() {
return this.rotationAngle;
},
GetBlastRadius: function() {
return this.blastRadius;
},
Update: function(modifier) {
this.x = this.x - this.swayX;
this.y = this.y - this.speedY;
if (this.y < -10) {this.x = GetRandom(0,canvas.width);this.y = canvas.height;this.speedY = GetRandom(30,100);this.swayX = GetRandom(-10,10)}
},
};
var DrawFireworks = function() {
//create confetti object array
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray[i].Draw(FireworkArray[i].GetX(), FireworkArray[i].GetY(), FireworkArray[i].GetLineWidth(), FireworkArray[i].GetColor(), FireworkArray[i].GetSpeedY(), FireworkArray[i].GetSwayX(), FireworkArray[i].GetBlastRadius());
}
};
var UpdateFireworks = function(modifier) {
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray[i].Update(modifier);
}
};
UncleSam = function() {
};
UncleSam.prototype = {
};
Text = function(context,title,x,y,color) {
this.context = context;
this.title = title;
this.x = x;
this.y = y;
this.color = color;
this.lineWidth = 2;
this.lineHeight =(this.context.measureText('W').width) + Math.pow((this.context.measureText('W').width),2);
this.font = '70pt Times New Roman';
//GET METRICS
this.metrics = this.context.measureText(this.title);
this.width = this.metrics.width;
this.maxWidth = canvas.width;
this.GradChangeSpeed = .5;
this.GradChangeOffset = .3;
this.debugCounter = 0;
};
Text.prototype = {
SetAttributes: function() {
context.font
context.textAlign = 'center'
context.font = this.font;
context.lineWidth = this.lineWidth;
context.lineHeight = this.GetHeight;
context.fillStyle = TextGradient;
context.strokeStyle = this.color;
//shadow attributes
context.shadowColor = undefined;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
},
//GETTTERS SETTERS///////////////////
GetTextX: function() {
return this.x;
},
GetTextY: function() {
return this.y;
},
GetTextLineHeight: function() {
return this.lineHeight;
},
GetTextWidth: function() {
return this.width;
},
//GETTERS SETTERS////////////
SetColorGradient: function() {
TextGradient.addColorStop(0,"red");
TextGradient.addColorStop(this.GradChangeOffset,"white");
TextGradient.addColorStop(.8,"blue");
},
Update: function(modifier) {
this.GradChangeOffset = this.GradChangeOffset + (this.GradChangeSpeed * modifier);
//GRADIENT DEBUGGERS
context.strokeText(this.GradChangeOffset.toFixed(2),canvas.width/2,canvas.height/2);
//GRADIENT DEBUGGERS
if (this.GradChangeOffset > .7 || this.GradChangeOffset < .2) {this.GradChangeSpeed = -(this.GradChangeSpeed);}
},
DrawText: function() {
this.WrapText(this.context, this.title, this.x, this.y, this.maxWidth, this.lineHeight);
},
WrapText: function(context, title, x, y, maxWidth, lineHeight) {
var words = title.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
context.strokeText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
context.strokeText(line, x, y);
},
};
//other functions
var ClearScreen = function() {
context.clearRect(0, 0, canvas.width, canvas.height);
};
var DrawObjects = function() {
ClearScreen();
Background1.DrawBackground();
Text1.SetAttributes();
Text1.SetColorGradient();
Text1.DrawText();
DrawFireworks();
DrawConfetti();
};
var UpdateObjects = function(modifier) {
//Text1.Update(modifier);
UpdateFireworks(modifier);
UpdateConfetti(modifier);
};
var Reset = function() {
};
//MAIN GAME LOOP FXN///////////////////
// The main game loop
var main = function() {
var now = Date.now();
var delta = now - then;
var frameRateAdjust = delta/1000;
DrawObjects(frameRateAdjust);
UpdateObjects(frameRateAdjust);
then = now;
//possibly do RESET
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
//START ECARD
//create variables
var then = Date.now();
var colorChoices = ["red","white","blue","deeppink","orange","limegreen","darkred"];
var NUM_CONFETTI = 25;
var NUM_FIREWORKS = 10;
var NUM_COLORS = colorChoices.length;
//create arrays for objects
var ConfettiArray = [];
var FireworkArray = [];
//create objects
Background1 = new Background(context,'black');
var Text1 = new Text(context,'Happy 4th of July!',canvas.width/2,canvas.height/10,'red');
var TextGradient = context.createLinearGradient(Text1.GetTextX(),Text1.GetTextY(),Text1.GetTextX()+Text1.GetTextWidth(),Text1.GetTextY()+Text1.GetTextLineHeight()/2)
//fill confetti object array
for (i = 0; i < NUM_CONFETTI; i++) {
ConfettiArray.push(new Confetti(GetRandom(0,canvas.width), GetRandom(-200,-10), GetRandom(10,30), GetRandom(10,30), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(0,2*Math.PI),GetRandom(50,80)));
}
//fill firework object array
for (i = 0; i < NUM_FIREWORKS; i++) {
FireworkArray.push(new Firework(GetRandom(0,canvas.width), canvas.height, GetRandom(4,20), colorChoices[GetRandom(0,NUM_COLORS)], GetRandom(30,100), GetRandom(-10,10), GetRandom(50,200)));
}
//start eCard animations
Reset();
main();
Upvotes: 0
Views: 74
Reputation: 54099
The reason is because you are creating one path out of all the firework lines.
//firework.draw
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color; // sets the stroke color
context.moveTo(x,y); // adds another line
context.lineTo(x-swayX,y-speedY);
context.stroke(); // stroke all lines up to this point
},
Each time stroke is called all the firework lines are render up to that point.
The result is that the last stroke call draws all the lines again the color of the last firework.
The fix is simple. Just start a new path with ctx.beginPath()
//firework.draw
Draw: function(x, y, lineWidth, color, speedY, swayX, blastRadius) {
context.fillStyle = color;
context.strokeStyle = color; // sets the stroke color
//========================================================
context.beginPath(); // start a new path
//========================================================
context.moveTo(x,y);
context.lineTo(x-swayX,y-speedY);
context.stroke();
},
Upvotes: 0