@code-dot-org/dance-party
Advanced tools
Comparing version 0.0.47 to 0.0.49
@@ -7,3 +7,3 @@ module.exports = config => { | ||
{pattern: 'test/integration/index.js'}, | ||
{pattern: 'assets/sprite_sheets/**/*.*', watched: false, included: false, served: true}, | ||
{pattern: 'test/assets/sprite_sheets/**/*.*', watched: false, included: false, served: true}, | ||
], | ||
@@ -10,0 +10,0 @@ preprocessors: { |
{ | ||
"name": "@code-dot-org/dance-party", | ||
"version": "0.0.47", | ||
"version": "0.0.49", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/main.js", |
@@ -65,2 +65,5 @@ module.exports = class DanceAPI { | ||
}, | ||
alternateMoves: (group, n, move1, move2) => { | ||
nativeAPI.alternateMoves(group, n, move1, move2); | ||
}, | ||
layoutSprites: (group, format) => { | ||
@@ -67,0 +70,0 @@ nativeAPI.layoutSprites(group, format); |
@@ -12,2 +12,3 @@ const constants = require('./constants'); | ||
const drawSpiral = require('./shapes/spiral'); | ||
const drawStar = require('./shapes/star'); | ||
const drawStarstruck = require('./shapes/starstruck'); | ||
@@ -285,2 +286,102 @@ const drawSwirl = require('./shapes/swirl'); | ||
// Creates a "ripple" effect where the ripple positions can be random. | ||
let createRipplesEffect = function (isRandomRipple) { | ||
return { | ||
// Determines whether or not the start positions of the ripples are random or centered. | ||
isRandomRipple: isRandomRipple, | ||
// The max width a ripple can be before it disappears. | ||
maxRippleWidth: 575, | ||
// The ripples which are growing. | ||
ripples: [], | ||
// The count of ripples which have been created since the dance started. | ||
rippleCount: 0, | ||
// The timestamp of when the last "draw" happened. | ||
lastDrawTime: new Date(), | ||
// Tracks the last biggest ripple's color so we can set that as the background after it disappears | ||
backgroundColor: colorFromPalette(0), | ||
init: function () { | ||
this.lastDrawTime = new Date(); | ||
this.backgroundColor = colorFromPalette(0); | ||
this.ripples = []; | ||
// If the starting location is random, then the circles might need to be 2x as wide to fill the screen. | ||
if (isRandomRipple) { | ||
this.maxRippleWidth = 1150; | ||
} | ||
// put some initial ripples. | ||
for (let i=0; i<6; i++) { | ||
this.ripples.push(this.createRipple(this.maxRippleWidth * (.85 - (.15*i)), this.isRandomRipple)); | ||
} | ||
}, | ||
draw: function ({isPeak, bpm}) { | ||
let currentTime = new Date(); | ||
let maxRippleWidth = this.maxRippleWidth; | ||
p5.background(this.backgroundColor); | ||
// On each "peak", create a new ripple. | ||
if (isPeak) { | ||
this.ripples.push(this.createRipple(1, this.isRandomRipple)); | ||
} | ||
p5.push(); | ||
p5.noStroke(); | ||
p5.ellipseMode(p5.CENTER); | ||
// calculate how much the ripples have grown and draw them. | ||
let rippleWidthGrowth = this.getRippleGrowth(currentTime, bpm); | ||
for (let i=0; i < this.ripples.length; i++) { | ||
let ripple = this.ripples[i]; | ||
ripple.width += rippleWidthGrowth; | ||
p5.fill(ripple.color); | ||
p5.ellipse(ripple.x, ripple.y, ripple.width); | ||
} | ||
// remove ripples which are too big, and updated the backgroundColor to match the highest one. | ||
let backgroundColor = this.backgroundColor; | ||
this.ripples = this.ripples.filter(function (ripple){ | ||
if (ripple.width < maxRippleWidth) { | ||
return true; | ||
} else { | ||
backgroundColor = ripple.color; | ||
return false; | ||
} | ||
}); | ||
this.backgroundColor = backgroundColor; | ||
p5.pop(); | ||
// keep track of the draw times so we can calculate how much time has passed. | ||
this.lastDrawTime = currentTime; | ||
}, | ||
// creates a object representing the size and position of a ripple given an initial width | ||
createRipple: function (width, isRandom) { | ||
let x = 200; | ||
let y = 200; | ||
if (isRandom) { | ||
x = randomNumber(20, 380); | ||
y = randomNumber(20, 380); | ||
} | ||
return { | ||
x: x, | ||
y: y, | ||
color: colorFromPalette(++this.rippleCount), | ||
width: width, | ||
}; | ||
}, | ||
// calculates the increase in width a ripple will experience depending on the | ||
// amount of time which has passed since the last drawm and the current BPM. | ||
getRippleGrowth: function (currentTime, bpm) { | ||
if (bpm === 0) { | ||
return 0; | ||
} | ||
// Velocity of the ripple width expansion. | ||
let velocity = this.maxRippleWidth/(bpm/60)/1.5; | ||
// Calculate how much time has passed so we know how wide the ripple should be. | ||
let deltaTime = (currentTime - this.lastDrawTime) / 1000; | ||
return Math.floor(velocity * deltaTime); | ||
} | ||
}; | ||
}; | ||
this.ripples = createRipplesEffect(false); | ||
this.ripples_random = createRipplesEffect(true); | ||
this.diamonds = { | ||
@@ -1263,2 +1364,33 @@ hue: 0, | ||
this.exploding_stars = { | ||
stars: [], | ||
resetStars: function () { | ||
for (let i = 0; i < 100; i++) { | ||
let theta = p5.random(0, p5.TWO_PI); | ||
let velocity = p5.random(4,12); | ||
this.stars.push({ | ||
color: randomColor(255, 255, 100), | ||
x: 200, | ||
y: 200, | ||
dx: velocity * p5.cos(theta), | ||
dy: velocity * p5.sin(theta) | ||
}); | ||
} | ||
}, | ||
draw: function () { | ||
p5.angleMode(p5.RADIANS); | ||
p5.noStroke(); | ||
if (this.stars.length === 0) { | ||
this.resetStars(); | ||
} | ||
this.stars.forEach(star => { | ||
p5.fill(star.color); | ||
drawStar(p5, star.x, star.y, 3, 9, 5); | ||
star.x += star.dx; | ||
star.y += star.dy; | ||
}); | ||
this.stars = this.stars.filter(star => star.x > -10 && star.x < 410 && star.y > -10 && star.y < 410); | ||
} | ||
}; | ||
this.galaxy = { | ||
@@ -1357,3 +1489,3 @@ space: [], | ||
this.image.scale(3); | ||
drawSmiley(this.image.drawingContext); | ||
drawSmiley(this.image.drawingContext, 0.8); | ||
}, | ||
@@ -1416,2 +1548,36 @@ draw: function (context) { | ||
this.growing_stars = { | ||
stars: [], | ||
colorIndex: 0, | ||
starSpacing: 30, | ||
numStars: 9, | ||
init: function () { | ||
p5.angleMode(p5.RADIANS); | ||
this.colorIndex = 0; | ||
this.stars = []; | ||
for (var i = 0; i < this.numStars; i++) { | ||
this.stars.push({ | ||
size: this.starSpacing * (this.numStars - i), | ||
colorIndex: this.colorIndex | ||
}); | ||
this.colorIndex++; | ||
} | ||
}, | ||
draw: function () { | ||
for (let star of this.stars) { | ||
p5.fill(colorFromPalette(star.colorIndex)); | ||
drawStar(p5, 200, 200, star.size, star.size * 2.5, 5); | ||
star.size += 1; | ||
} | ||
if (this.stars[0].size > (this.starSpacing * this.numStars)) { | ||
this.stars.shift(); | ||
this.stars.push({size: 0, colorIndex: this.colorIndex}); | ||
this.colorIndex++; | ||
} | ||
} | ||
}; | ||
this.music_notes = { | ||
@@ -1458,2 +1624,36 @@ notes: [], | ||
this.squiggles = { | ||
points: [], | ||
dotSpacing: 3, | ||
amplitude: 40, | ||
period: 400, | ||
dotRadius: 7, | ||
numSquiggles: 8, | ||
init: function () { | ||
this.points = []; | ||
p5.noStroke(); | ||
p5.angleMode(p5.DEGREES); | ||
let numPoints = p5.height / this.dotSpacing; | ||
for (var i = 0; i < numPoints; i++) { | ||
this.points.push({ | ||
x: 0, | ||
y: i * this.dotSpacing, | ||
theta: 360 / this.period * i * this.dotSpacing, | ||
color: lerpColorFromPalette(i / numPoints) | ||
}); | ||
} | ||
}, | ||
draw: function ( {bpm} ) { | ||
p5.background('black'); | ||
for (var i = 0; i < this.numSquiggles; i++) { | ||
this.points.forEach(point => { | ||
p5.fill(point.color); | ||
p5.ellipse(point.x, point.y, this.dotRadius, this.dotRadius); | ||
point.x = (p5.width / (this.numSquiggles - 1) * i) + p5.sin(point.theta) * this.amplitude; | ||
point.theta = (point.theta + bpm / 360) % 360; | ||
}); | ||
} | ||
} | ||
}; | ||
this.music_wave = { | ||
@@ -1498,3 +1698,3 @@ inc: 360/15, | ||
this.imageSmiley.scale(3); | ||
drawSmiley(this.imageSmiley.drawingContext); | ||
drawSmiley(this.imageSmiley.drawingContext, 1.0); | ||
this.emojiTypes.push(this.imageSmiley); | ||
@@ -1523,3 +1723,3 @@ | ||
y: -50, | ||
size: randomNumber(25, 50), | ||
size: randomNumber(50, 90), | ||
image: this.emojiTypes[randomNumber(0, 4)], | ||
@@ -1535,3 +1735,3 @@ }); | ||
p5.push(); | ||
p5.image(emoji.image, emoji.x, emoji.y, emoji.size, emoji.size); | ||
p5.drawingContext.drawImage(emoji.image.elt, emoji.x, emoji.y, emoji.size, emoji.size); | ||
p5.pop(); | ||
@@ -1538,0 +1738,0 @@ } |
@@ -458,2 +458,25 @@ /* eslint-disable no-unused-vars, curly, eqeqeq */ | ||
alternateMoves(group, n, move1, move2) { | ||
// Maximum of 10 events per second | ||
// Our fastest song is 169bpm | ||
// This allows events on eighth-notes in that song. | ||
n = Math.max(0.1, n); | ||
group = this.getGroupByName_(group); | ||
let currentMeasure = this.getCurrentMeasure(); | ||
if (currentMeasure === 0) { | ||
currentMeasure = 1; | ||
} | ||
group.forEach(sprite => { | ||
this.changeMoveLR(sprite, move1, -1); | ||
sprite.alternatingMoveInfo = { | ||
start: currentMeasure, | ||
cadence: n, | ||
move1: move1, | ||
move2: move2, | ||
current: 1 | ||
}; | ||
}); | ||
} | ||
/** | ||
@@ -523,2 +546,3 @@ * Returns a next/prev/rand move | ||
sprite.current_move = move; | ||
sprite.alternatingMoveInfo = undefined; | ||
} | ||
@@ -1143,2 +1167,23 @@ | ||
let currentMeasure = this.getCurrentMeasure(); | ||
this.sprites_.forEach(sprite => { | ||
if (sprite.alternatingMoveInfo) { | ||
let alternatingMoveInfo = sprite.alternatingMoveInfo; | ||
let quotient = Math.floor((currentMeasure - sprite.alternatingMoveInfo.start) / sprite.alternatingMoveInfo.cadence); | ||
if (quotient % 2 == 0) { | ||
if (sprite.alternatingMoveInfo.current != 1) { | ||
this.changeMoveLR(sprite, sprite.alternatingMoveInfo.move1, -1); | ||
sprite.alternatingMoveInfo = alternatingMoveInfo; | ||
sprite.alternatingMoveInfo.current = 1; | ||
} | ||
} else { | ||
if (sprite.alternatingMoveInfo.current != 2) { | ||
this.changeMoveLR(sprite, sprite.alternatingMoveInfo.move2, 1); | ||
sprite.alternatingMoveInfo = alternatingMoveInfo; | ||
sprite.alternatingMoveInfo.current = 2; | ||
} | ||
} | ||
} | ||
}); | ||
this.p5_.background('#fff'); // Clear the canvas. | ||
@@ -1145,0 +1190,0 @@ this.getBackgroundEffect().draw(context); |
@@ -1,2 +0,2 @@ | ||
const ASSET_BASE = "https://curriculum.code.org/images/sprites/dance_20181127/"; | ||
const ASSET_BASE = "https://curriculum.code.org/images/sprites/dance_20191106/"; | ||
@@ -3,0 +3,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
module.exports = function drawSmiley(ctx) { | ||
module.exports = function drawSmiley(ctx, alpha) { | ||
ctx.save(); | ||
@@ -9,3 +9,3 @@ ctx.strokeStyle = 'rgba(0,0,0,0)'; | ||
ctx.fillStyle = "#ffdf40"; | ||
ctx.globalAlpha = 0.8; | ||
ctx.globalAlpha = alpha; | ||
ctx.beginPath(); | ||
@@ -12,0 +12,0 @@ ctx.arc(8.5,8,8,0,6.283185307179586,true); |
@@ -9,3 +9,3 @@ const {createDanceAPI} = require('./createDanceAPI'); | ||
createDanceAPI({ | ||
resourceLoader: new ResourceLoader('/base/assets/sprite_sheets/'), | ||
resourceLoader: new ResourceLoader('/base/test/assets/sprite_sheets/'), | ||
onPuzzleComplete: (result, message) => { | ||
@@ -12,0 +12,0 @@ onPuzzleComplete(result, message); |
@@ -89,3 +89,6 @@ const test = require('tape'); | ||
['music_notes'], | ||
['music_wave'] | ||
['music_wave'], | ||
['ripples'], | ||
['ripples_random'], | ||
['squiggles'] | ||
].forEach(effect => { | ||
@@ -92,0 +95,0 @@ let name = effect[0] + (effect[1] ? ("_" + effect[1]) : ""); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
113053
24268652
166