xxxxxxxxxx
359
let klint_letters;
let klint_sun;
let klint_altar;
let klint_tri;
let phase_start;
let level_start;
let coming;
let in_play;
let finishing;
let score = 0;
let misses = 0;
const MODE_PLAYING = 0;
const MODE_INTRO = 1;
const MODE_OVER = 2;
const MODE_NEXT_LEVEL = 3;
let mode;
const letterpos = [0, 56, 135, 207, 294, 370, 429];
const track_dur = 3;
const finish_dur = 1;
const hit_window = 0.25;
const pieces_per_level = 50;
function preload() {
klint_sun = loadImage("klint_sun.png");
klint_altar = loadImage("klint_altar.png");
klint_tri = loadImage("klint_tri.png");
klint_letters = loadImage("klint_letters.png");
}
function setup() {
createCanvas(500, 800);
// startLevel();
mode = MODE_INTRO;
phase_start = millis() / 1000.0;
}
function startLevel() {
level_start = millis() / 1000.0;
const gran = 0.5;
// Create a new level
let cur_time = level_start + 0.5;
let placed = 0;
function pick(n) {
const ret = [];
while (ret.length < n) {
const n = int(random(7));
if (!ret.includes(n)) {
ret.push(n);
}
}
return ret;
}
coming = [];
in_play = [];
finishing = [];
misses = 0;
score = 0;
while (placed < pieces_per_level) {
let here = 1;
let r = random(1);
if (r > 0.9) {
here = 2;
if (r > 0.98) {
here = 3;
}
}
const ar = pick(here);
for (let a of ar) {
coming.push([a, cur_time]);
}
placed += here;
let upd = 2 * gran;
r = random(1);
if (r < 0.1) {
upd = 4 * gran;
} else if (r < 0.25) {
upd = 3 * gran;
} else if (r > 0.8) {
upd = gran;
}
cur_time += upd;
}
// console.log( coming );
}
function updatePieces() {
const m = millis() / 1000.0;
// Find all pieces that should be put into play.
let idx = 0;
for (; idx < coming.length; ++idx) {
if (coming[idx][1] > m) {
// in the future.
break;
}
}
const nin_play = [];
const nfinishing = [];
// Launch any new pieces.
for (let jdx = 0; jdx < idx; ++jdx) {
// console.log( "Launching piece at " + coming[jdx][1] );
nin_play.push(coming[jdx]);
}
coming = coming.slice(idx);
// Copy over other pieces in play, or move them to the finishing pile.
for (idx = 0; idx < in_play.length; ++idx) {
if (m - in_play[idx][1] < track_dur) {
nin_play.push(in_play[idx]);
} else {
// If this happens, it implies that the player missed the
// piece.
nfinishing.push([in_play[idx][0], m, false]);
++misses;
}
}
// Copy over other finishing pieces.
for (let f of finishing) {
if (m - f[1] < finish_dur) {
nfinishing.push(f);
}
}
in_play = nin_play;
finishing = nfinishing;
}
function drawPiece(i, t) {
const asp = klint_tri.width / klint_tri.height;
const y = lerp(380, 745, t);
const left = lerp(237, 25, t);
const right = lerp(266, width - 25, t);
const w = (right - left) / 7;
const x = left + i * w;
imageMode(CORNER);
image(klint_tri, x, y - w / asp, w, w / asp);
}
function drawPieces() {
const m = millis() / 1000.0;
for (let p of in_play) {
drawPiece(p[0], (m - p[1]) / track_dur);
}
for (let p of finishing) {
const cr = p[2] ? 0 : 255;
const cg = p[2] ? 255 : 0;
const cb = 0;
let delta = m - p[1];
if (delta < 0.25 * finish_dur) {
const t = map(delta, 0, 0.25 * finish_dur, 0, 1);
tint(lerp(255, cr, t), lerp(255, cg, t), lerp(255, cb, t));
drawPiece(p[0], 1);
noTint();
} else {
const t = map(delta, 0.25 * finish_dur, finish_dur, 0, 1);
tint(cr, cg, cb, lerp(255, 0, t));
drawPiece(p[0], 1);
noTint();
}
}
}
function drawScore() {
const dsc = 0.75;
let x = width - 30;
let sc = score;
do {
let res = sc % 6;
const w = letterpos[res + 1] - letterpos[res];
x -= w * dsc;
copy(
klint_letters,
letterpos[res],
0,
int(w),
int(klint_letters.height),
int(x),
30,
int(w * dsc),
int(klint_letters.height * dsc)
);
sc = int(sc / 6);
} while (sc != 0);
const mi = min(misses, 5);
const w = letterpos[mi + 1] - letterpos[mi];
copy(
klint_letters,
letterpos[mi],
0,
int(w),
int(klint_letters.height),
30,
30,
int(w * dsc),
int(klint_letters.height * dsc)
);
// fill(255);
// text( "" + misses, 30, 100 );
}
function draw() {
background(0);
fill(80, 0, 0);
rect(25, height - 80, width - 50, 55);
const m = millis() / 1000.0;
if (mode == MODE_INTRO) {
const t = min(m - phase_start, 2) / 2;
imageMode(CENTER);
push();
translate(width / 2, lerp(1000, width / 2 + 30, t));
scale(0.7);
// rotate(frameCount * 0.01);
image(klint_sun, 0, 0);
pop();
if (m > 2) {
const t2 = (m - phase_start - 2) / 2;
push();
translate(width / 2, lerp(1000, 0.7 * height, t2));
scale(0.9);
image(klint_altar, 0, 0);
pop();
}
if (m - phase_start > 4) {
mode = MODE_PLAYING;
startLevel();
}
} else if (
mode == MODE_NEXT_LEVEL ||
mode == MODE_PLAYING ||
mode == MODE_OVER
) {
imageMode(CENTER);
push();
translate(width / 2, width / 2 + 30);
scale(0.7);
rotate((m - level_start) * 0.25);
image(klint_sun, 0, 0);
pop();
push();
translate(width / 2, 0.7 * height);
scale(0.9);
image(klint_altar, 0, 0);
pop();
if (mode == MODE_PLAYING) {
drawPieces();
drawScore();
} else if (mode == MODE_OVER) {
tint(255, 0, 0);
imageMode(CENTER);
image(klint_tri, width / 2, height / 2, 200, 200);
imageMode(CORNER);
noTint();
} else if (mode == MODE_NEXT_LEVEL) {
tint(0, 255, 0);
imageMode(CENTER);
image(klint_tri, width / 2, height / 2, 200, 200);
imageMode(CORNER);
noTint();
if (m - phase_start > 2) {
mode = MODE_PLAYING;
startLevel();
}
}
}
// Game logic
if (mode == MODE_PLAYING) {
updatePieces();
if (misses >= 6) {
// You lose!
mode = MODE_OVER;
}
if (coming.length == 0 && in_play.length == 0 && finishing.length == 0) {
// Finish the level!
mode = MODE_NEXT_LEVEL;
phase_start = m;
}
}
noStroke();
fill(255);
rect(0, 0, width, 25);
rect(0, height - 25, width, 25);
rect(0, 0, 25, height);
rect(width - 25, 0, 25, height);
stroke(1);
noFill();
rect(0, 0, width, height);
}
/*
function mousePressed()
{
console.log( mouseX, mouseY );
}
*/
function keyPressed() {
if (mode == MODE_PLAYING) {
const i = "zxcvbnm".indexOf(key);
// console.log( i );
if (i == -1) {
return;
}
// OK, user selected a track. See if there's a piece about to finish in
// that track.
const m = millis() / 1000.0;
for (let idx = 0; idx < in_play.length; ++idx) {
if (abs(m - in_play[idx][1] - track_dur) < hit_window) {
// Yesss!
++score;
finishing.push([in_play[idx][0], m, true]);
in_play.splice(idx, 1);
// console.log( 'hit!' );
return;
}
}
// If you get here, you pressed a key when nothing was in play
++misses;
} else if (mode == MODE_OVER) {
if (key == " ") {
mode = MODE_PLAYING;
startLevel();
}
}
}