I am trying to merge the coins into master but there is a conflict. I am unable to save the game.js file either because sublime is yelling at me for having a syntax error that I can't figure out, please help
enter image description here
here is all the code with bugs as per sublime text 3:
// Canvas Asteroids
//
// Copyright (c) 2010 Doug McInnes
//
KEY_CODES = {
'32': 'space',
'37': 'left',
'38': 'up',
'39': 'right',
'40': 'down',
'70': 'f',
'71': 'g',
'72': 'h',
'77': 'm',
'80': 'p'
}
KEY_STATUS = { keyDown:false };
for (code in KEY_CODES) {
KEY_STATUS[KEY_CODES[code]] = false;
}
$(window).keydown(function (e) {
KEY_STATUS.keyDown = true;
if (KEY_CODES[e.keyCode]) {
e.preventDefault();
KEY_STATUS[KEY_CODES[e.keyCode]] = true;
}
}).keyup(function (e) {
KEY_STATUS.keyDown = false;
if (KEY_CODES[e.keyCode]) {
e.preventDefault();
KEY_STATUS[KEY_CODES[e.keyCode]] = false;
}
});
GRID_SIZE = 60;
Matrix = function (rows, columns) {
var i, j;
this.data = new Array(rows);
for (i = 0; i < rows; i++) {
this.data[i] = new Array(columns);
}
this.configure = function (rot, scale, transx, transy) {
var rad = (rot * Math.PI)/180;
var sin = Math.sin(rad) * scale;
var cos = Math.cos(rad) * scale;
this.set(cos, -sin, transx,
sin, cos, transy);
};
this.set = function () {
var k = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
this.data[i][j] = arguments[k];
k++;
}
}
}
this.multiply = function () {
var vector = new Array(rows);
for (i = 0; i < rows; i++) {
vector[i] = 0;
for (j = 0; j < columns; j++) {
vector[i] += this.data[i][j] * arguments[j];
}
}
return vector;
};
};
Sprite = function () {
this.init = function (name, points) {
this.name = name;
this.points = points;
this.vel = {
x: 0,
y: 0,
rot: 0
};
this.acc = {
x: 0,
y: 0,
rot: 0
};
};
this.children = {};
this.color = 'black';
this.solid = false;
this.visible = false;
this.reap = false;
this.bridgesH = true;
this.bridgesV = true;
this.collidesWith = [];
this.x = 0;
this.y = 0;
this.rot = 0;
this.scale = 1;
this.currentNode = null;
this.nextSprite = null;
this.preMove = null;
this.postMove = null;
this.run = function(delta) {
this.move(delta);
this.updateGrid();
this.context.save();
this.configureTransform();
this.draw();
var canidates = this.findCollisionCanidates();
this.matrix.configure(this.rot, this.scale, this.x, this.y);
this.checkCollisionsAgainst(canidates);
this.context.restore();
if (this.bridgesH && this.currentNode && this.currentNode.dupe.horizontal) {
this.x += this.currentNode.dupe.horizontal;
this.context.save();
this.configureTransform();
this.draw();
this.checkCollisionsAgainst(canidates);
this.context.restore();
if (this.currentNode) {
this.x -= this.currentNode.dupe.horizontal;
}
}
if (this.bridgesV && this.currentNode && this.currentNode.dupe.vertical) {
this.y += this.currentNode.dupe.vertical;
this.context.save();
this.configureTransform();
this.draw();
this.checkCollisionsAgainst(canidates);
this.context.restore();
if (this.currentNode) {
this.y -= this.currentNode.dupe.vertical;
}
}
if (this.bridgesH && this.bridgesV &&
this.currentNode &&
this.currentNode.dupe.vertical &&
this.currentNode.dupe.horizontal) {
this.x += this.currentNode.dupe.horizontal;
this.y += this.currentNode.dupe.vertical;
this.context.save();
this.configureTransform();
this.draw();
this.checkCollisionsAgainst(canidates);
this.context.restore();
if (this.currentNode) {
this.x -= this.currentNode.dupe.horizontal;
this.y -= this.currentNode.dupe.vertical;
}
}
};
this.move = function (delta) {
if (!this.visible) return;
this.transPoints = null; // clear cached points
if ($.isFunction(this.preMove)) {
this.preMove(delta);
}
#torazaburo Thank you, you are right. JSLint was the problem all worked when I removed the package from Sublime Text 3.
#torazaburo
should work identically as property names. This seems to be a bug in
JSLint, which is notoriously picky.
Related
I have been trying to make a nodal graph visualizer, but I am having trouble getting the lines to display behind the nodal points. I have already tried to use context.globalCompositeOperation, but to no avail. I have tried to implement rendering it in the order I wanted it to be drawn. Here is the full code for the project:
var canvas = document.querySelector('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext('2d');
var nodes = [];
var has_clicked = false;
var user_has_picked_up_object = false;
var picked_up_id;
class Vector2 {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
document.onmousemove = function(e){
mouse_pos.x = e.pageX;
mouse_pos.y = e.pageY;
}
document.onmousedown = function(e) {
has_clicked = true;
}
document.addEventListener('mouseup', function(e) {
has_clicked = false;
user_has_picked_up_object = false;
})
var mouse_pos = new Vector2(0, 0);
class Connection {
constructor(node1, node2) {
this.node1 = node1;
this.node2 = node2;
this.isDrawn = false;
}
}
function DistSQ(p1, p2) {
return Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2);
}
class Node {
constructor(pos, id) {
this.pos = pos;
this.radius = 10;
this.radius_squared = 100;
this.connections = [];
this.id = id;
}
AddConnection(conn) {
this.connections.push(conn);
}
RemoveConnection(conn) {
return this.connections.pop(conn);
}
UpdatePosition() {
if(DistSQ(this.pos, mouse_pos) < this.radius_squared && has_clicked) {
if(user_has_picked_up_object && picked_up_id == this.id) {
this.pos = mouse_pos;
}
else {
user_has_picked_up_object = true;
picked_up_id = this.id;
}
}
else {
this.pos = new Vector2(this.pos.x, this.pos.y);
}
}
}
function DrawLines(conns) {
c.beginPath();
c.lineWidth = 1;
c.strokeStyle = 'black';
conns.forEach(element => {
c.moveTo(element.node1.pos.x, element.node1.pos.y);
c.lineTo(element.node2.pos.x, element.node2.pos.y);
});
c.stroke();
}
function DrawCircles(nds) {
c.beginPath();
c.lineWidth = 1;
nds.forEach(element => {
c.strokeStyle = 'black';
c.moveTo(element.pos.x+element.radius, element.pos.y);
c.arc(element.pos.x, element.pos.y, element.radius, 0, 2 * Math.PI, false);
});
c.stroke();
}
function Update() {
requestAnimationFrame(Update);
c.clearRect(0, 0, window.innerWidth, window.innerHeight);
for(var i = 0; i < nodes.length; i++) {
nodes[i].UpdatePosition();
DrawLines(nodes[i].connections);
}
DrawCircles(nodes);
}
function Initialize() {
for(var y = 0, i = 0; y < 5; y++) {
for(var x = 0; x < 5; x++, i++) {
nodes.push(new Node(new Vector2(x*20+20, y*20+20), i));
}
}
for(var i = 1; i < nodes.length; i++) {
nodes[i].AddConnection(new Connection(nodes[i], nodes[i-1]));
}
Update();
}
Initialize();
Thanks to #enxaneta, for giving me the solution to this problem, so I copied his answer here:
The lines are behind the circles- In your function DrawCircles add c.fillStyle = "white";c.fill() – enxaneta
I have the following code for making a 2048 game with a onkeydown function to detect when user presses arrow keys. I thought the code is executed in sequential order but the onkeydown doesn't work if i put it at the end but only works if i put it first, even before canvas and tiles array declaration. How can i fix this so the order of execution makes more sense to me.
<script type="text/javascript">
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
var Tile = function(x, y) {
this.x = x;
this.y = y;
this.value = "";
}
Tile.prototype.draw = function() {
ctx.fillStyle = "green";
ctx.fillRect(this.x, this.y, 100, 100);
}
Tile.prototype.setX = function(x) {
this.x = x;
}
Tile.prototype.setY = function(y) {
this.y = y;
}
Tile.prototype.getY = function() {
return this.y;
}
Tile.prototype.getX = function() {
return this.x;
}
var tiles = [];
for(let i = 1; i <= 4; i++) {
for(let j = 1; j <= 4; j++) {
tiles.push(new Tile(j * 110, i * 110));
}
}
for(let i = 0; i <= tiles.length; i++) {
tiles[i].draw();
}
document.onkeydown = function(e) {
e.preventDefault();
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (e.keyCode == '38') {
for(let i = 0; i < tiles.length; i++) {
tiles[i].setY(tiles[i].getY() - 50);
tiles[i].draw();
}
}
else if (e.keyCode == '40') {
for(let i = 0; i < tiles.length; i++) {
tiles[i].setY(tiles[i].getY() + 50);
tiles[i].draw();
}
}
else if (e.keyCode == '37') {
for(let i = 0; i < tiles.length; i++) {
tiles[i].setX(tiles[i].getX() - 50);
tiles[i].draw();
}
}
else if (e.keyCode == '39') {
for(let i = 0; i < tiles.length; i++) {
tiles[i].setX(tiles[i].getX() + 50);
tiles[i].draw();
}
}
};
</script>
This is a question from javascript.
if (game.ship.livesPool.getPool[0].getDamaged())
I got an error on this getDamaged() function as undefined inside another function.
game = new Game();
game is defined outside this function as a global variable.
this.ship = new Ship();
ship is defined inside Game class.
this.livesPool = new Pool();
var pool = [];
this.getPool = function(){
return pool;
}
livesPool is defined inside Pool class. pool is an array defined in Pool class.
getPool function will return this array.
pool[i] = new Lives();
each of the pool[i] will be assigned Lives object in Pool class.
this.getDamaged = function(){
return this.damaged;
}
getDamaged() function is defined this way inside Lives class.
Why does it show me that this function is undefined?
Game class
function Game() {
this.init = function () {
// Obtain the canvas from HTML
this.bgCanvas = document.getElementById('background');
this.shipCanvas = document.getElementById('ship');
this.mainCanvas = document.getElementById('main');
// Load the context
/* Just one of them passing to conditional statement is enough to test
* the availability
*/
if (this.bgCanvas.getContext) {
this.bgContext = this.bgCanvas.getContext('2d');
this.shipContext = this.shipCanvas.getContext('2d');
this.mainContext = this.mainCanvas.getContext('2d');
Background.prototype.context = this.bgContext;
Background.prototype.canvasHeight = this.bgCanvas.height;
Background.prototype.canvasWidth = this.bgCanvas.width;
Ship.prototype.context = this.shipContext;
Ship.prototype.canvasHeight = this.shipCanvas.height;
Ship.prototype.canvasWidth = this.shipCanvas.width;
Lives.prototype.context = this.shipContext;
Lives.prototype.canvasHeight = this.shipCanvas.height;
Lives.prototype.canvasWidth = this.shipCanvas.width;
Bullet.prototype.context = this.mainContext;
Bullet.prototype.canvasHeight = this.mainCanvas.height;
Bullet.prototype.canvasWidth = this.mainCanvas.width;
Bullet.prototype.bossContext = this.shipContext;
Enemy.prototype.context = this.mainContext;
Enemy.prototype.canvasHeight = this.mainCanvas.height;
Enemy.prototype.canvasWidth = this.mainCanvas.width;
Boss.prototype.context = this.shipContext;
Boss.prototype.canvasHeight = this.shipCanvas.height;
Boss.prototype.canvasWidth = this.shipCanvas.width;
// Define background in the game
this.background = new Background();
this.background.init(0, 0, imageRepository.background.width, imageRepository.background.height);
// Define ship in the game
this.ship = new Ship();
var shipStartX = this.shipCanvas.width / 2 - imageRepository.ship.width / 2;
var shipStartY = this.shipCanvas.height / 4 * 3 + imageRepository.ship.height / 2;
this.ship.init(shipStartX, shipStartY, imageRepository.ship.width, imageRepository.ship.height);
this.ship.type = "ship";
this.ship.hasExplored = false;
// Define enemy pools in the game
this.enemyPool = new Pool(10);
this.enemyPool.init("enemy");
this.boss = new Boss();
return true;
}
else {
return false;
}
};
this.runGame = function () {
this.ship.draw();
animate();
};
this.restart = function () {
this.bgContext.clearRect(0, 0, this.bgCanvas.width, this.bgCanvas.height);
this.mainContext.clearRect(0, 0, this.mainCanvas.width, this.mainCanvas.height);
this.shipContext.clearRect(0, 0, this.shipCanvas.width, this.shipCanvas.height);
this.enemyPool.init("enemy");
var shipStartX = this.shipCanvas.width / 2 - imageRepository.ship.width / 2;
var shipStartY = this.shipCanvas.height / 4 * 3 + imageRepository.ship.height / 2;
this.ship.x = shipStartX;
this.ship.y = shipStartY;
this.ship.hasExplored = false;
this.ship.bulletPool.init("bullet");
score = 0;
displayedScore = 0;
bossExist = false;
this.boss.life = 100;
this.boss.bulletPool.init("boss_bullet");
this.boss.fireRate = 0;
while(this.ship.livesPool.getSize() < 3){
this.ship.livesPool.increaseLives();
}
document.getElementById('game-over').style.display = "none";
this.runGame();
};
this.start = function () {
gameStarted = true;
document.getElementById('main-menu').style.display = 'none';
document.getElementById('score-board').style.display = 'block';
};
this.backHome = function () {
gameStarted = false;
document.getElementById('game-over').style.display = 'none';
document.getElementById('score-board').style.display = 'none';
document.getElementById('main-menu').style.display = 'block';
this.restart();
};
}
Ship class.
function Ship() {
this.speed = 5;
this.bulletPool = new Pool(maxNumOfBullets);
this.bulletPool.init("bullet");
this.bulletSoundPool = new SoundPool(maxNumOfBullets);
this.bulletSoundPool.init("bullet");
this.livesPool = new Pool(3);
this.livesPool.init("lives");
this.hasExplored = false;
this.life = 3;
var fireRate = 15;
var counter = 0;
this.draw = function () {
if (this.livesPool.getSize() <= 0) {
this.context.clearRect(this.x, this.y, this.width, this.height);
}
else {
this.context.drawImage(imageRepository.ship, this.x, this.y);
}
}
this.move = function () {
counter++;
// Determine if the action is move action
if (KEY_STATUS.left || KEY_STATUS.right ||
KEY_STATUS.down || KEY_STATUS.up) {
// The ship moved, so erase it's current image so it can
// be redrawn in it's new location
this.context.clearRect(this.x, this.y, this.width, this.height);
// Update x and y according to the direction to move and
// redraw the ship. Change the else if's to if statements
// to have diagonal movement.
if (KEY_STATUS.left) {
this.x -= this.speed
if (this.x <= 0) // Keep player within the screen
this.x = 0;
} else if (KEY_STATUS.right) {
this.x += this.speed
if (this.x >= this.canvasWidth - this.width)
this.x = this.canvasWidth - this.width;
} else if (KEY_STATUS.up) {
this.y -= this.speed
if (this.y <= this.canvasHeight / 4 * 3)
this.y = this.canvasHeight / 4 * 3;
} else if (KEY_STATUS.down) {
this.y += this.speed
if (this.y >= this.canvasHeight - this.height)
this.y = this.canvasHeight - this.height;
}
}
this.draw();
if (KEY_STATUS.space && counter >= fireRate) {
this.fire();
counter = 0;
}
};
this.fire = function () {
this.bulletPool.getTwo(this.x + imageRepository.ship.width / 10, this.y, 3);
this.bulletSoundPool.get();
};
}
Pool class.
function Pool(maxSize) {
var size = maxSize;
var pool = [];
var type = "";
// This design enables us to not need to create an object each loop
this.init = function (obj) {
if (obj === "bullet") {
type = "bullet";
for (var i = 0; i < size; i++) {
var bullet = new Bullet("bullet");
bullet.init(0, 0, imageRepository.bullet.width, imageRepository.bullet.height);
bullet.collidableWith = "enemy";
bullet.type = "bullet";
pool[i] = bullet;
}
}
else if (obj === "enemy") {
type = "enemy";
for (var i = 0; i < size; i++) {
var enemy = null;
var rand = Math.floor(Math.random() * 10);
if (rand < 8) {
enemy = new Enemy("enemy", 0, 10);
enemy.init(0, 0, imageRepository.enemy.width, imageRepository.enemy.height);
}
else {
enemy = new Enemy("enemy2", 2, 15);
enemy.init(0, 0, imageRepository.enemy2.width, imageRepository.enemy2.height);
}
enemy.collidableWith = "ship";
enemy.type = "enemy";
pool[i] = enemy;
}
}
else if (obj === "boss_bullet") {
type = "boss_bullet";
for (var i = 0; i < size; i++) {
var bullet = new Bullet("boss_bullet");
bullet.init(0, 0, imageRepository.boss_bullet.width, imageRepository.boss_bullet.height);
bullet.collidableWith = "ship";
bullet.type = "bullet";
pool[i] = bullet;
}
}
else if (obj === "lives") {
type = "lives";
for (var i = 0; i < size; i++) {
var lives = new Lives();
lives.init(imageRepository.background.width - ((i + 1) * imageRepository.lives.width) - 10,
imageRepository.background.height - imageRepository.lives.height - 10,
imageRepository.lives.width, imageRepository.lives.height);
pool[i] = lives;
}
}
};
// Return pool attribute for usage in checking collision
this.getPool = function () {
var res = [];
for (var i = 0; i < pool.length; i++) {
if (pool[i].alive) {
res.push(pool[i]);
}
}
return res;
};
this.get = function (x, y, speed) {
if (pool[size - 1] instanceof Bullet) {
if (!pool[size - 1].alive) {
pool[size - 1].spawn(x, y, speed);
pool.unshift(pool.pop());
}
}
else if (pool[size - 1] instanceof Enemy) {
if (!pool[size - 1].alive) {
if (!(pool[0].alive && pool[0].y <= pool[0].height)) {
pool[size - 1].spawn(x, y, speed);
pool.unshift(pool.pop());
}
}
}
};
this.getTwo = function (x, y, speed) {
if (type === "bullet") {
if (!pool[size - 1].alive && !pool[size - 2].alive) {
this.get(x, y, speed);
this.get(x + (imageRepository.ship.width * 8) / 10
- imageRepository.bullet.width, y, speed);
}
}
else if (type === "boss_bullet") {
if (!pool[size - 1].alive && !pool[size - 2].alive) {
this.get(x, y, speed);
// This will have the center of boss as the center between two bullets
// x + 2 * (imageRepository.boss.width / 2 - x) - imageRepository.boss_bullet.width
this.get(x + imageRepository.boss.width * 3 / 5 - imageRepository.boss_bullet.width,
y, speed);
console.log(x);
console.log(x + imageRepository.boss.width * 3 / 5 - imageRepository.boss_bullet.width);
}
}
};
this.animate = function () {
for (var i = 0; i < size; i++) {
if (pool[i].alive) {
if (pool[i].draw()) {
pool[i].clear();
pool.push((pool.splice(i, 1))[0]);
}
}
else
break;
}
};
this.getSize = function () {
return size;
};
this.setSize = function (input) {
size = input;
};
this.decreaseLives = function () {
if (size >= 1) {
if (pool[size - 1] instanceof Lives) {
pool[size - 1].setDamaged(true);
size--;
}
}
};
this.increaseLives = function(){
if (pool[size - 1] instanceof Lives){
pool[size - 1].setDamaged(true);
size++;
}
};
}
Lives class.
function Lives() {
this.alive = true;
this.damaged = false;
this.draw = function () {
this.context.clearRect(this.x, this.y, this.width, this.height);
this.context.drawImage(imageRepository.lives, this.x, this.y);
if (this.damaged)
return true;
}
this.clear = function () {
alive = false;
this.x = -1 * this.width;
this.y = -1 * this.height;
}
this.getDamaged = function(){
return this.damaged;
}
this.setDamaged = function(input){
this.damaged = input;
}
}
getPool is a function, you need to call it:
if (game.ship.livesPool.getPool()[0].getDamaged())
// ^^
So I wanted to stream things that aren't only mp3 files.
Things like youtube for example.
Ignore the rest of the code other than the audio part of it. This is a visualizer that I'm revamping from a dude that made a really nice audio visualizer.
How would I go about making it play youtube files and direct links that are streaming links. What I wanted to do was add a list of random songs so it would stream a song off of every single one rather than me uploading 100 songs to my domain and wasting space.
(function() {
var ALPHA, AudioAnalyser, COLORS, MP3_PATH, NUM_BANDS, NUM_PARTICLES, Particle, SCALE, SIZE, SMOOTHING, SPEED, SPIN;
NUM_PARTICLES = 150;
NUM_BANDS = 128;
SMOOTHING = 0.5;
var MP3_PATH = ['website.com/Song.mp3', 'website.com/Song2.mp3', 'website.com/Song3.mp3'];
SCALE = {
MIN: 5.0,
MAX: 20.0
};
SPEED = {
MIN: 0.2,
MAX: 1.0
};
ALPHA = {
MIN: 0.8,
MAX: 0.9
};
SPIN = {
MIN: 0.001,
MAX: 0.005
};
SIZE = {
MIN: 0.5,
MAX: 0.90
};
COLORS = ['#69D2E7', '#1B676B', '#BEF202', '#EBE54D', '#00CDAC', '#1693A5', '#F9D423', '#FF4E50', '#E7204E', '#0CCABA', '#FF006F'];
AudioAnalyser = (function() {
AudioAnalyser.AudioContext = self.AudioContext || self.webkitAudioContext;
AudioAnalyser.enabled = AudioAnalyser.AudioContext != null;
function AudioAnalyser(audio, numBands, smoothing) {
var src;
this.audio = audio != null ? audio : new Audio();
this.numBands = numBands != null ? numBands : 256;
this.smoothing = smoothing != null ? smoothing : 0.3;
if (typeof this.audio === 'string') {
src = this.audio;
this.audio = new Audio();
this.audio.crossOrigin = "anonymous";
this.audio.controls = true;
this.audio.src = src;
}
this.context = new AudioAnalyser.AudioContext();
this.jsNode = this.context.createScriptProcessor(2048, 1, 1);
this.analyser = this.context.createAnalyser();
this.analyser.smoothingTimeConstant = this.smoothing;
this.analyser.fftSize = this.numBands * 2;
this.bands = new Uint8Array(this.analyser.frequencyBinCount);
this.audio.addEventListener('canplay', (function(_this) {
return function() {
_this.source = _this.context.createMediaElementSource(_this.audio);
_this.source.connect(_this.analyser);
_this.analyser.connect(_this.jsNode);
_this.jsNode.connect(_this.context.destination);
_this.source.connect(_this.context.destination);
return _this.jsNode.onaudioprocess = function() {
_this.analyser.getByteFrequencyData(_this.bands);
if (!_this.audio.paused) {
return typeof _this.onUpdate === "function" ? _this.onUpdate(_this.bands) : void 0;
}
};
};
})(this));
}
AudioAnalyser.prototype.start = function() {
return this.audio.play();
};
AudioAnalyser.prototype.stop = function() {
return this.audio.pause();
};
return AudioAnalyser;
})();
Particle = (function() {
function Particle(x1, y1) {
this.x = x1 != null ? x1 : 0;
this.y = y1 != null ? y1 : 0;
this.reset();
}
Particle.prototype.reset = function() {
this.level = 1 + floor(random(4));
this.scale = random(SCALE.MIN, SCALE.MAX);
this.alpha = random(ALPHA.MIN, ALPHA.MAX);
this.speed = random(SPEED.MIN, SPEED.MAX);
this.color = random(COLORS);
this.size = random(SIZE.MIN, SIZE.MAX);
this.spin = random(SPIN.MAX, SPIN.MAX);
this.band = floor(random(NUM_BANDS));
if (random() < 0.5) {
this.spin = -this.spin;
}
this.smoothedScale = 0.0;
this.smoothedAlpha = 0.0;
this.decayScale = 0.0;
this.decayAlpha = 0.0;
this.rotation = random(TWO_PI);
return this.energy = 0.0;
};
Particle.prototype.move = function() {
this.rotation += this.spin;
return this.y -= this.speed * this.level;
};
Particle.prototype.draw = function(ctx) {
var alpha, power, scale;
power = exp(this.energy);
scale = this.scale * power;
alpha = this.alpha * this.energy * 1.5;
this.decayScale = max(this.decayScale, scale);
this.decayAlpha = max(this.decayAlpha, alpha);
this.smoothedScale += (this.decayScale - this.smoothedScale) * 0.3;
this.smoothedAlpha += (this.decayAlpha - this.smoothedAlpha) * 0.3;
this.decayScale *= 0.985;
this.decayAlpha *= 0.975;
ctx.save();
ctx.beginPath();
ctx.translate(this.x + cos(this.rotation * this.speed) * 250, this.y);
ctx.rotate(this.rotation);
ctx.scale(this.smoothedScale * this.level, this.smoothedScale * this.level);
ctx.moveTo(this.size * 0.5, 0);
ctx.lineTo(this.size * -0.5, 0);
ctx.lineWidth = 1;
ctx.lineCap = 'round';
ctx.globalAlpha = this.smoothedAlpha / this.level;
ctx.strokeStyle = this.color;
ctx.stroke();
return ctx.restore();
};
return Particle;
})();
Sketch.create({
particles: [],
setup: function() {
var analyser, error, i, intro, j, particle, ref, warning, x, y;
for (i = j = 0, ref = NUM_PARTICLES - 1; j <= ref; i = j += 1) {
x = random(this.width);
y = random(this.height * 2);
particle = new Particle(x, y);
particle.energy = random(particle.band / 350);
this.particles.push(particle);
}
if (AudioAnalyser.enabled) {
try {
analyser = new AudioAnalyser(random(MP3_PATH), NUM_BANDS, SMOOTHING);
analyser.onUpdate = (function(_this) {
return function(bands) {
var k, len, ref1, results;
ref1 = _this.particles;
results = [];
for (k = 0, len = ref1.length; k < len; k++) {
particle = ref1[k];
results.push(particle.energy = bands[particle.band] / 350);
}
return results;
};
})(this);
analyser.start();
document.body.appendChild(analyser.audio);
intro = document.getElementById('intro');
intro.style.display = 'none';
if (/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)) {
warning = document.getElementById('warning2');
return warning.style.display = 'block';
}
} catch (_error) {
error = _error;
}
} else {
warning = document.getElementById('warning1');
return warning.style.display = 'block';
}
},
draw: function() {
var j, len, particle, ref, results;
this.globalCompositeOperation = 'lighter';
ref = this.particles;
results = [];
for (j = 0, len = ref.length; j < len; j++) {
particle = ref[j];
if (particle.y < -particle.size * particle.level * particle.scale * 2) {
particle.reset();
particle.x = random(this.width);
particle.y = this.height + particle.size * particle.scale * particle.level;
}
particle.move();
results.push(particle.draw(this));
}
return results;
}
});
}).call(this);
I need some expert help. When I make canvas background transparent the line colors the whole canvas (shown in code below).
How do I stop/fix this? I want the line stay as a single line that doesn't color the canvas.
Math.clamp = function(x, min, max) {
return x < min ? min : (x > max ? max : x);
};
// canvas settings
var viewWidth = window.innerWidth,
viewHeight = window.innerHeight,
drawingCanvas = document.getElementById("drawing_canvas"),
ctx,
timeStep = (10 / 100),
time = 0;
var lineTension = 0.067,
lineDamping = 0.068,
waveSpreadFactor = 0.1;
var previousMousePosition = {
x: 0,
y: 0
},
currentMousePosition = {
x: 0,
y: 0
},
actualMousePosition = {
x: 0,
y: 0
};
var line,
lineSegmentCount = 64,
lineMaxForce = 32,
lineStrokeGradient;
var audioCtx,
nodeCount = 64,
oscillatorNodes = [],
gainNodes = [];
var segmentsPerNode = lineSegmentCount / nodeCount;
function initGui() {
}
function goBananas() {
lineTension = 0.2;
line.anchors[Math.floor(Math.random() * line.anchors.length)].
vel = lineMaxForce;
}
function resetLine() {
line.reset();
for (var i = 0; i < nodeCount; i++) {
oscillatorNodes[i].detune.value = 100;
gainNodes[i].gain.value = 0;
}
lineTension = 0.0025;
lineDamping = 0.05;
waveSpreadFactor = 0.1;
}
function initDrawingCanvas() {
drawingCanvas.width = viewWidth;
drawingCanvas.height = viewHeight;
window.addEventListener('resize', resizeHandler);
window.addEventListener('mousemove', mouseMoveHandler);
setInterval(updateMousePosition, (1000 / 30));
ctx = drawingCanvas.getContext('2d');
ctx.lineWidth = 5;
line = new Line(0, viewHeight * 0.5, viewWidth, lineSegmentCount);
// line.anchors[0].vel = viewHeight * 0.25;
lineStrokeGradient = ctx.createLinearGradient(0, 0, 0, viewHeight);
lineStrokeGradient.addColorStop(0, '#0ff');
}
function initWebAudio() {
audioCtx = new(window.AudioContext || window.webkitAudioContext)();
for (var i = 0; i < nodeCount; i++) {
var oscillatorNode = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillatorNode.connect(gainNode);
gainNode.connect(audioCtx.destination);
gainNode.gain.value = 0;
oscillatorNode.type = 'saw';
oscillatorNode.detune.value = 200;
oscillatorNode.frequency.value = 1200 * (i / 60);
oscillatorNode.start();
oscillatorNodes[i] = oscillatorNode;
gainNodes[i] = gainNode;
}
}
function resizeHandler() {
drawingCanvas.width = viewWidth = window.innerWidth;
drawingCanvas.height = viewHeight = window.innerHeight;
if (ctx) {
ctx.lineWidth = 4;
line.resize(viewWidth, viewHeight * 0.5);
}
}
function mouseMoveHandler(event) {
actualMousePosition.x = Math.floor(event.clientX);
actualMousePosition.y = Math.floor(event.clientY);
}
function updateMousePosition() {
previousMousePosition.x = currentMousePosition.x;
previousMousePosition.y = currentMousePosition.y;
currentMousePosition.x = actualMousePosition.x;
currentMousePosition.y = actualMousePosition.y;
}
function update() {
var px = Math.min(previousMousePosition.x, currentMousePosition.x),
py = Math.min(previousMousePosition.y, currentMousePosition.y),
pw = Math.max(1, Math.abs(previousMousePosition.x - currentMousePosition.x)),
ph = Math.max(1, Math.abs(previousMousePosition.y - currentMousePosition.y)),
force = Math.clamp(currentMousePosition.y -
previousMousePosition.y, -lineMaxForce, lineMaxForce);
var pixels = ctx.getImageData(px, py, pw, ph),
data = pixels.data;
for (var i = 0; i < data.length; i += 3) {
var r = data[i + 0],
g = data[i + 1],
b = data[i + 2],
x = (i % ph) + px;
if (r + g + b > 0) {
line.ripple(x, force);
}
}
line.update();
for (var j = 0; j < gainNodes.length; j++) {
var anchor = line.anchors[j * segmentsPerNode],
gain = Math.clamp(Math.abs(anchor.vel) / viewHeight * 0.5, 0, 3),
detune = Math.clamp(anchor.pos / viewHeight * 100, 0, 300);
gainNodes[j].gain.value = gain;
oscillatorNodes[j].detune.value = detune;
}
}
function draw() {
ctx.strokeStyle = lineStrokeGradient;
line.draw();
}
window.onload = function() {
initDrawingCanvas();
initWebAudio();
initGui();
requestAnimationFrame(loop);
};
function loop() {
update();
draw();
time += timeStep;
requestAnimationFrame(loop);
}
Line = function(x, y, length, segments) {
this.x = x;
this.y = y;
this.length = length;
this.segments = segments;
this.segmentLength = this.length / this.segments;
this.anchors = [];
for (var i = 0; i <= this.segments; i++) {
this.anchors[i] = {
target: this.y,
pos: this.y,
vel: 0,
update: function() {
var dy = this.pos - this.target,
acc = -lineTension * dy - lineDamping * this.vel;
this.pos += this.vel;
this.vel += acc;
},
reset: function() {
this.pos = this.target;
this.vel = 0;
}
};
}
};
Line.prototype = {
resize: function(length, targetY) {
this.length = length;
this.segmentLength = this.length / this.segments;
for (var i = 0; i <= this.segments; i++) {
this.anchors[i].target = targetY;
}
},
reset: function() {
for (var i = 0; i <= this.segments; i++) {
this.anchors[i].reset();
}
},
ripple: function(origin, amplitude) {
var i = Math.floor((origin - this.x) / this.segmentLength);
if (i >= 0 && i <= this.segments) {
this.anchors[i].vel = amplitude;
}
},
update: function() {
var lDeltas = [],
rDeltas = [],
i;
for (i = 0; i <= this.segments; i++) {
this.anchors[i].update();
}
for (i = 0; i <= this.segments; i++) {
if (i > 0) {
lDeltas[i] = waveSpreadFactor * (this.anchors[i].pos - this.anchors[i - 1].pos);
this.anchors[i - 1].vel += lDeltas[i];
}
if (i < this.segments) {
rDeltas[i] = waveSpreadFactor * (this.anchors[i].pos - this.anchors[i + 1].pos);
this.anchors[i + 1].vel += rDeltas[i];
}
}
for (i = 0; i <= this.segments; i++) {
if (i > 0) {
this.anchors[i - 1].pos += lDeltas[i];
}
if (i < this.segments) {
this.anchors[i + 1].pos += rDeltas[i];
}
}
},
draw: function() {
ctx.beginPath();
for (var i = 0; i <= this.segments; i++) {
ctx.lineTo(
this.x + this.segmentLength * i,
this.anchors[i].pos
);
}
ctx.stroke();
}
};
From the code you posted, the problem seems to be a missing
ctx.clearRect(0, 0, viewWidth, viewHeight)
at the beginning of your "draw" function.
See a working example here