You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1364 lines
40 KiB
1364 lines
40 KiB
4 years ago
|
let ctrl = false,
|
||
|
alt = false,
|
||
|
shift = false,
|
||
|
fpson = true,
|
||
|
moving = false,
|
||
|
over = false,
|
||
|
keyhold = false;
|
||
|
let lastClick = undefined;
|
||
|
let animating = true;
|
||
|
let flags = 0x0;
|
||
|
var uTime = 0,
|
||
|
startTime = Date.now();
|
||
|
let lastTime = Date.now(),
|
||
|
rotTime = 0;
|
||
|
var lastFrameTime = 0;
|
||
|
let oldDocument;
|
||
|
let fullscreen = false,
|
||
|
btntoggled = false;
|
||
|
let movescene = true;
|
||
|
let oldparents = {};
|
||
|
var tr, div;
|
||
|
let canvas_originalsize;
|
||
|
let Sph = [];
|
||
|
let SphTr = [];
|
||
|
let SphDletaR = [];
|
||
|
let selected = false,
|
||
|
selection = -1,
|
||
|
dragging = false;
|
||
|
let overall_trans = matrix_identity(),
|
||
|
overall_ground, ground_m = matrix_identity();
|
||
|
var rebuild = [true, true],
|
||
|
presentation = false,
|
||
|
sRotation = matrix_identity();
|
||
|
var state = new State(0), state1 = new State(1);
|
||
|
state1.death = (hitter)=>{if(!state1.dead){state1.defaultDeath();channel=5;show_magic = true;}};
|
||
|
state.death = (hitter)=>{if(!state.dead){state.defaultDeath();channel=6;}};
|
||
|
state1.hitID = 9;
|
||
|
var facing = 1;
|
||
|
let curr_mouse_pos = [-10, -10, -10];
|
||
|
var updateVideoTextures = false;
|
||
|
var show_magic = false;
|
||
|
var slider_dl = 0;
|
||
|
var donut_eaten = false;
|
||
|
var Boxing = true;
|
||
|
var gamestart = false;
|
||
|
let int_fxydL = 0, trace = [];//[x, y, tijp[o'm]]
|
||
|
//schema.height = screen.height * .9;
|
||
|
var channel = 3, channel_disp = -1;
|
||
|
let difficulty_levels = {
|
||
|
hard: {
|
||
|
flex : .1,
|
||
|
freq : 25,
|
||
|
speed: .8,
|
||
|
th : 2.,
|
||
|
startTimer : 15,
|
||
|
punchSpeed: 10,
|
||
|
original : 0
|
||
|
},
|
||
|
medium: {
|
||
|
flex : .07,
|
||
|
freq : 200,
|
||
|
speed: .4,
|
||
|
th : 1.8,
|
||
|
startTimer : 5,
|
||
|
punchSpeed: 5,
|
||
|
original : 1
|
||
|
},
|
||
|
easy: {
|
||
|
flex : .03,
|
||
|
freq : 400,
|
||
|
speed: .2,
|
||
|
th : 1.5,
|
||
|
startTimer : 4,
|
||
|
punchSpeed: 8,
|
||
|
original: 2
|
||
|
}
|
||
|
}, dl_orig = [difficulty_levels.hard, difficulty_levels.medium, difficulty_levels.easy];
|
||
|
var difficulty = deepcopy(difficulty_levels.medium);
|
||
|
state1.set_stepSize(difficulty.speed);
|
||
|
state1.turnStep = difficulty.flex;
|
||
|
state1.delta_l = [4, -5];
|
||
|
for (let i = 0; i < ns; ++i) {
|
||
|
SphTr[i] = matrix_identity();
|
||
|
SphDletaR[i] = 0;
|
||
|
}
|
||
|
|
||
|
function ev_supersample(e) {
|
||
|
let multiplier = insamp.value;
|
||
|
let w = parseInt(canvas1.style.width) * multiplier;
|
||
|
let h = parseInt(canvas1.style.height) * multiplier;
|
||
|
canvas1.height = h;
|
||
|
canvas1.width = w;
|
||
|
gl.viewport(0, 0, w, h);
|
||
|
//gl.clearRect(0, 0, w, h);
|
||
|
}
|
||
|
|
||
|
function toggleFullscreen(element) {
|
||
|
if (fullscreen) {
|
||
|
if (document.exitFullscreen)
|
||
|
document.exitFullscreen();
|
||
|
else if (document.webkitExitFullscreen)
|
||
|
document.webkitExitFullscreen();
|
||
|
else if (document.mozCancelFullScreen)
|
||
|
document.mozCancelFullScreen();
|
||
|
else if (document.msExitFullscreen)
|
||
|
document.msExitFullscreen();
|
||
|
fullscreen = false;
|
||
|
bnfs.innerText = "Fullscreen";
|
||
|
} else {
|
||
|
if (element.requestFullscreen)
|
||
|
element.requestFullscreen();
|
||
|
else if (element.webkitRequestFullscreen)
|
||
|
element.webkitRequestFullscreen();
|
||
|
else if (element.msRequestFullscreen)
|
||
|
element.msRequestFullscreen();
|
||
|
fullscreen = true;
|
||
|
bnfs.innerText = "Exit Fullscreen";
|
||
|
}
|
||
|
}
|
||
|
bnfs.onclick = function (e) {
|
||
|
if (e === "no")
|
||
|
;
|
||
|
else
|
||
|
btntoggled = true;
|
||
|
if (fullscreen) {
|
||
|
oldparents[controls].appendChild(controls);
|
||
|
oldparents[canvas1].appendChild(canvas1);
|
||
|
canvas1.style.width = canvas_originalsize[0];
|
||
|
canvas1.style.height = canvas_originalsize[1];
|
||
|
howitworks.hidden = false;
|
||
|
} else {
|
||
|
div = document.createElement("div");
|
||
|
tr = document.createElement("table").insertRow();
|
||
|
tr.style.backgroundColor = "white";
|
||
|
let size = Math.min(screen.availHeight, screen.availWidth);
|
||
|
canvas_originalsize = [canvas1.style.width, canvas1.style.height, canvas1.width, canvas1.height];
|
||
|
canvas1.style.height = canvas1.style.width = size;
|
||
|
howitworks.hidden = true;
|
||
|
oldparents[controls] = controls.parentNode;
|
||
|
oldparents[canvas1] = canvas1.parentNode;
|
||
|
|
||
|
let td1 = tr.insertCell();
|
||
|
td1.appendChild(canvas1);
|
||
|
let td2;
|
||
|
td2 = tr.insertCell();
|
||
|
td2.style.verticalAlign = "top";
|
||
|
td2.appendChild(controls);
|
||
|
|
||
|
div.appendChild(tr);
|
||
|
document.body.appendChild(div);
|
||
|
}
|
||
|
toggleFullscreen(div);
|
||
|
ev_supersample();
|
||
|
}
|
||
|
mov.onclick = function (_) {
|
||
|
movescene = !movescene;
|
||
|
if (!movescene) {
|
||
|
mov.innerText = "Move Scene";
|
||
|
mov.style.width = "170px";
|
||
|
} else {
|
||
|
mov.innerText = "Move Lighting";
|
||
|
mov.style.width = "180px";
|
||
|
}
|
||
|
}
|
||
|
document.addEventListener("webkitfullscreenchange", () => {
|
||
|
if (!btntoggled && fullscreen) bnfs.onclick("no");
|
||
|
btntoggled = false;
|
||
|
});
|
||
|
document.addEventListener("fullscreenchange", () => {
|
||
|
if (!btntoggled && fullscreen) bnfs.onclick("no");
|
||
|
btntoggled = false;
|
||
|
});
|
||
|
clrsel.onclick = function (_) {
|
||
|
setUniform("1i", "sel", -1);
|
||
|
selected = false;
|
||
|
selection = -1;
|
||
|
}
|
||
|
reset.onclick = function (_) {
|
||
|
clrsel.onclick();
|
||
|
if (!animating)
|
||
|
pause_resume();
|
||
|
flags = 0;
|
||
|
moving = false;
|
||
|
gamestart = false;
|
||
|
donut_eaten = false;
|
||
|
//slider_dl = 0;
|
||
|
mousedx = mousedy = mousedz = 0;
|
||
|
positionsupdated = true;
|
||
|
for (let i = 0; i < ns; ++i) {
|
||
|
SphTr[i] = matrix_identity();
|
||
|
SphDletaR[i] = 0;
|
||
|
}
|
||
|
sRotation = matrix_identity();
|
||
|
startTime = lastTime = Date.now();
|
||
|
uTime = rotTime = 0;
|
||
|
state.delta_l = [0, 0];
|
||
|
facing = 1;
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
}
|
||
|
bns.onclick = function (e) {
|
||
|
if (ins.value > 0 && ins.value <= ns && cns != ins.value) {
|
||
|
cns = ins.value;
|
||
|
fragmentShaderDefs = '\n const int cns = ' + cns + ';';
|
||
|
if (typeof canvas1.setShaders === "function")
|
||
|
canvas1.setShaders(vs, editor.getSession().getValue());
|
||
|
}
|
||
|
}
|
||
|
bnsamp.onclick = ev_supersample;
|
||
|
// SET UP THE EDITABLE TEXT AREA ON THE LEFT SIDE.
|
||
|
ace.require("ace/ext/language_tools");
|
||
|
var editor = ace.edit("ace", {
|
||
|
mode: "ace/mode/glsl",
|
||
|
theme: "ace/theme/crimson_editor"
|
||
|
});
|
||
|
editor.setOptions({
|
||
|
enableBasicAutocompletion: true,
|
||
|
enableSnippets: true,
|
||
|
enableLiveAutocompletion: true,
|
||
|
fontSize: 14,
|
||
|
fontFamily: "monaco, menlo, ubuntu mono, consolas, source-code-pro",
|
||
|
fixedWidthGutter: true,
|
||
|
showGutter: true,
|
||
|
showPrintMargin: false,
|
||
|
});
|
||
|
editor.setAutoScrollEditorIntoView(true);
|
||
|
if (fs != undefined)
|
||
|
editor.getSession().setValue(fs);
|
||
|
editor.session.on('change', function (delta) {
|
||
|
if (typeof canvas1.setShaders === "function") {
|
||
|
canvas1.setShaders(vs, editor.getSession().getValue());
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
}
|
||
|
});
|
||
|
// REPARSE THE SHADER PROGRAM AFTER EVERY KEYSTROKE.
|
||
|
delete editor.KeyBinding;
|
||
|
let ttt = -1
|
||
|
let pause_resume = function () {
|
||
|
ttt += .1;
|
||
|
if (animating)
|
||
|
lastTime = Date.now();
|
||
|
else
|
||
|
startTime += Date.now() - lastTime;
|
||
|
animating = !animating;
|
||
|
};
|
||
|
canvas1.addEventListener('click', function (ev) {
|
||
|
if (!(shift && alt) && lastClick && Date.now() - lastClick < 200)
|
||
|
pause_resume();
|
||
|
lastClick = Date.now();
|
||
|
});
|
||
|
pause.onclick = pause_resume;
|
||
|
canvas1.addEventListener('mouseover', function (e) {
|
||
|
over = true;
|
||
|
if (e.offsetX > 0 && e.offsetY > 0)
|
||
|
{
|
||
|
curr_mouse_pos = [2 * e.offsetX / parseInt(canvas1.style.width) - 1,
|
||
|
1 - 2 * e.offsetY / parseInt(canvas1.style.height), 0
|
||
|
];
|
||
|
controls_hitTest(curr_mouse_pos);
|
||
|
}
|
||
|
else over = false;
|
||
|
});
|
||
|
canvas1.addEventListener('mousedown', function (e) {
|
||
|
moving = true;
|
||
|
rotTime = uTime;
|
||
|
presentation = false;
|
||
|
mouselastX = mouselastY = undefined;
|
||
|
controls_hitTest(curr_mouse_pos, true);
|
||
|
});
|
||
|
canvas1.addEventListener('mousemove', function (e) {
|
||
|
curr_mouse_pos = [2 * e.offsetX / parseInt(canvas1.style.width) - 1,
|
||
|
1 - 2 * e.offsetY / parseInt(canvas1.style.height), 0
|
||
|
];
|
||
|
controls_hitTest(curr_mouse_pos);
|
||
|
let dx, dy;
|
||
|
if(!(mouselastX == undefined || mouselastY == undefined)){
|
||
|
dx = (mouselastX - e.offsetX),
|
||
|
dy = (mouselastY - e.offsetY);
|
||
|
int_fxydL += sqrt(dx*dx + dy*dy);
|
||
|
if(int_fxydL > 20)
|
||
|
{
|
||
|
int_fxydL = 0;
|
||
|
trace.push([curr_mouse_pos[0], curr_mouse_pos[1], 1]);
|
||
|
}
|
||
|
}
|
||
|
if (!(mouselastX == undefined || mouselastY == undefined) && !near_magician) {
|
||
|
if (movescene) {
|
||
|
sRotation = matrix_multiply(matrix_rotateX(-dy / 60), sRotation);
|
||
|
sRotation = matrix_multiply(matrix_rotateY(-dx / 60), sRotation);
|
||
|
} else if (!selected) {
|
||
|
mousedx -= dx / 60;
|
||
|
mousedy -= dy / 60;
|
||
|
positionsupdated = true;
|
||
|
} else if (dragging) {
|
||
|
let m = matrix_rotateY(-mousedx);
|
||
|
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||
|
let dv = matrix_multiply(m, [2 * -dx / parseInt(canvas1.style.width),
|
||
|
2 * dy / parseInt(canvas1.style.height), 0, 1
|
||
|
]).slice(0, 3);
|
||
|
SphTr[selection] = matrix_multiply(SphTr[selection], matrix_translate(dv[0], dv[1], dv[2]));
|
||
|
}
|
||
|
}
|
||
|
mouselastX = e.offsetX;
|
||
|
mouselastY = e.offsetY;
|
||
|
});
|
||
|
canvas1.addEventListener('mouseup', function (e) {
|
||
|
moving = false;
|
||
|
dragging = false;
|
||
|
if(slider)slider.dragging = false;
|
||
|
});
|
||
|
canvas1.addEventListener('mouseout', function (e) {
|
||
|
const mask = 0x8;
|
||
|
flags &= !mask;
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
over = false;
|
||
|
moving = false;
|
||
|
});
|
||
|
canvas1.addEventListener('wheel', function (e) {
|
||
|
if (!selected) {
|
||
|
mousedz += e.wheelDelta / 600;
|
||
|
positionsupdated = true;
|
||
|
} else {
|
||
|
SphDletaR[selection] += e.wheelDelta / 800;
|
||
|
}
|
||
|
});
|
||
|
canvas1.scroll(function (e) {
|
||
|
e.stopPropagation();
|
||
|
});
|
||
|
let rtswitch = function () {
|
||
|
if(channel_disp != 4){
|
||
|
channel = 4
|
||
|
rtx.src = './RTXon.svg';
|
||
|
}
|
||
|
else {
|
||
|
channel = 2;
|
||
|
rtx.src = './RTXoff.svg';
|
||
|
}
|
||
|
}
|
||
|
var requestAnimationFrame = window.requestAnimationFrame ||
|
||
|
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
|
||
|
let fpscounter = function (time) {
|
||
|
if (start === undefined)
|
||
|
start = time;
|
||
|
else
|
||
|
fps.innerHTML = Math.round(10000 / (time - start)) / 10 + ' fps';
|
||
|
start = time;
|
||
|
if (fpson)
|
||
|
; //requestAnimationFrame(fpscounter);
|
||
|
else {
|
||
|
start = undefined;
|
||
|
fps.innerHTML = '';
|
||
|
}
|
||
|
};
|
||
|
document.addEventListener('keydown', (e) => {
|
||
|
if (e.code.startsWith('Shift'))
|
||
|
shift = true;
|
||
|
if (e.code.startsWith('Control'))
|
||
|
ctrl = true;
|
||
|
if (e.code.startsWith('Alt'))
|
||
|
alt = true;
|
||
|
else if (ctrl && alt && e.code == 'KeyT') {
|
||
|
const mask = 0x1;
|
||
|
flags = flags & !mask | (!(flags & mask) ? mask : 0);
|
||
|
setUniform('1i', 'flags', flags);
|
||
|
} else if (ctrl && e.code == 'KeyS') {
|
||
|
let a = document.createElement('a');
|
||
|
a.href = "data:text/plain," + encodeURIComponent(editor.getSession().getValue());
|
||
|
a.download = 'shader.frag';
|
||
|
a.click();
|
||
|
} else if (ctrl && alt && e.code == 'KeyR')
|
||
|
rtswitch();
|
||
|
else if (ctrl && alt && e.code == 'KeyN') {
|
||
|
reset.onclick();
|
||
|
} else if (ctrl && alt && e.code == 'KeyP')
|
||
|
pause_resume();
|
||
|
else if (ctrl && alt && e.code == 'KeyF')
|
||
|
if (!fpson) {
|
||
|
fpson = true;
|
||
|
requestAnimationFrame(fpscounter);
|
||
|
}
|
||
|
else
|
||
|
fpson = false;
|
||
|
|
||
|
if (e.code == 'ArrowUp' || e.code == 'ArrowDown' || e.code == 'ArrowLeft' ||
|
||
|
e.code == 'ArrowRight' || e.code == 'KeyW' || e.code == 'KeyS') {
|
||
|
let oldfacing = facing;
|
||
|
switch (e.code) {
|
||
|
case 'ArrowUp':
|
||
|
facing = -2;
|
||
|
break;
|
||
|
case 'ArrowDown':
|
||
|
facing = 2;
|
||
|
break;
|
||
|
case 'ArrowLeft':
|
||
|
facing = -1;
|
||
|
break;
|
||
|
case 'ArrowRight':
|
||
|
facing = 1;
|
||
|
break;
|
||
|
case 'KeyW':
|
||
|
break;
|
||
|
case 'KeyS':
|
||
|
break;
|
||
|
}
|
||
|
if(facing !=2)
|
||
|
state.figure_rot = (pi*(facing/2));
|
||
|
else state.figure_rot = 0;
|
||
|
if(!keyhold || oldfacing != facing)
|
||
|
{
|
||
|
state.running = 20;
|
||
|
state.dir_sdl = 0;
|
||
|
keyhold = true;
|
||
|
}
|
||
|
else
|
||
|
state.running = state.running > 5? state.running:5;
|
||
|
rebuild[0] = true;
|
||
|
}
|
||
|
if (fullscreen && selected) {
|
||
|
if (e.code == 'KeyF' || e.code == 'KeyB') {
|
||
|
let m = matrix_rotateY(-mousedx);
|
||
|
m = matrix_multiply(m, matrix_rotateX(-mousedy));
|
||
|
m = const_multiply((fl + 1 + mousedz) / (fl + 1), m);
|
||
|
|
||
|
switch (e.code) {
|
||
|
case 'KeyB':
|
||
|
var dv = matrix_multiply(m, [0, 0, -0.1, 1]).slice(0, 3);
|
||
|
m = matrix_translate(dv[0], dv[1], dv[2]);
|
||
|
break;
|
||
|
case 'KeyF':
|
||
|
var dv = matrix_multiply(m, [0, 0, 0.1, 1]).slice(0, 3);
|
||
|
m = matrix_translate(dv[0], dv[1], dv[2]);
|
||
|
break;
|
||
|
}
|
||
|
SphTr[selection] = matrix_multiply(SphTr[selection], m);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
if(e.code == 'KeyF'&&Boxing){
|
||
|
state.start_punch();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
document.addEventListener('keyup', (e) => {
|
||
|
keyhold = false;
|
||
|
if (e.code.startsWith('Control'))
|
||
|
ctrl = false;
|
||
|
if (e.code.startsWith('Alt'))
|
||
|
alt = false;
|
||
|
if (e.code.startsWith('Shift'))
|
||
|
shift = false;
|
||
|
});
|
||
|
let squareMesh = (w = 1, h = 1, dir = 1, id = -1)=> new Float32Array([id, -w, h, 0, 0, 0, dir, id, w, h, 0, 0, 0, dir, id, -w, -h, 0, 0, 0, dir, id, w, -h, 0, 0, 0, dir]);
|
||
|
let sphereMesh = createMesh(8, 8, uvToSphere, 0, 16.45);
|
||
|
let sphereMesh25 = createMesh(25, 25, uvToSphere, 0, 16.45);
|
||
|
let tubeMesh = createMesh(64, 2, uvToTube, 0, 1);
|
||
|
let diskMesh = createMesh(16, 2, uvToDisk, 0, 1);
|
||
|
let tubeMesh2 = createMesh(16, 2, uvToTube, 0, 2);
|
||
|
let diskNMesh2 = createMesh(16, 2, uvToDisk, -1, 2);
|
||
|
let diskPMesh2 = createMesh(16, 2, uvToDisk, 1, 2);
|
||
|
let tubeMesh3 = createMesh(16, 2, uvToTube, 0, 3);
|
||
|
let diskNMesh3 = createMesh(16, 2, uvToDisk, -1, 3);
|
||
|
let diskPMesh3 = createMesh(16, 2, uvToDisk, 1, 3);
|
||
|
let diskNMesh = createMesh(16, 2, uvToDisk, -1, 1);
|
||
|
let diskPMesh = createMesh(16, 2, uvToDisk, 1, 1);
|
||
|
let cylinderMesh = glueMeshes(glueMeshes(tubeMesh, diskPMesh), diskNMesh);
|
||
|
let cylinderMesh2 = glueMeshes(glueMeshes(tubeMesh2, diskPMesh2), diskNMesh2);
|
||
|
let cylinderMesh3 = glueMeshes(glueMeshes(tubeMesh3, diskPMesh3), diskNMesh3);
|
||
|
let torusMash = createMesh(32, 32, uvToTorus, 1, 18);
|
||
|
let head = createCube(1.5, 1, 1, 4);
|
||
|
|
||
|
let objects = [];
|
||
|
let addObject = (obj, mat, i) => {
|
||
|
objects[i].push([obj, mat]);
|
||
|
};
|
||
|
let clearObject = (i) => {
|
||
|
delete objects[i];
|
||
|
objects[i] = [];
|
||
|
};
|
||
|
|
||
|
|
||
|
let star1 = [],
|
||
|
star = [];
|
||
|
let sakura = [],
|
||
|
stars = [],
|
||
|
nstars = 25;
|
||
|
let star2 = [],
|
||
|
newstar, star4;
|
||
|
const curvex = matrix_multiply(hermiteMat, [-.3, .8, .6, .5]);
|
||
|
const curvey = matrix_multiply(hermiteMat, [-.2, .5, .7, .2]);
|
||
|
const curvez = matrix_multiply(hermiteMat, [-.5, .2, .3, .8]);
|
||
|
let adt = [];
|
||
|
var near_magician = false;
|
||
|
let build_objects = (state, i) => {
|
||
|
if(state.head === undefined)
|
||
|
{
|
||
|
state.head = head.slice();
|
||
|
state.cylinderMesh = cylinderMesh.slice();
|
||
|
state.cylinderMesh2 = cylinderMesh2.slice();
|
||
|
state.cylinderMesh3 = cylinderMesh3.slice();
|
||
|
if(state.idx == 0)
|
||
|
{
|
||
|
changeID(12, state.head);
|
||
|
changeID(6, state.cylinderMesh);
|
||
|
changeID(8, state.cylinderMesh2);
|
||
|
changeID(10, state.cylinderMesh3);
|
||
|
}
|
||
|
}
|
||
|
let lh,lf,rh,rf,dh,dl, head_rot = 0;
|
||
|
if(!state.dead){
|
||
|
if (state.running === 0)
|
||
|
rebuild[i] = false;
|
||
|
res = state.next();
|
||
|
lh=res.lh;lf=res.lf;rh=res.rh;rf=res.rf;dh=res.dh;dl=res.dl;
|
||
|
if(state.dir_sdl > 0){
|
||
|
state.delta_l = plus(state.delta_l, const_multiply(dl, state.direction_l));
|
||
|
state.dir_sdl -= dl;
|
||
|
state.running = 1;
|
||
|
}else
|
||
|
state.delta_l[abs(facing) - 1] += Math.sign(facing) * dl;
|
||
|
if(state.idx === 0)
|
||
|
if(sqlen(state.delta_l[0] - 8, state.delta_l[1] + 6)< 6)
|
||
|
{
|
||
|
if(!near_magician){
|
||
|
near_magician = true;
|
||
|
movescene = false;
|
||
|
button_magic.enabled = true;
|
||
|
pushStatus('Show me some magic');
|
||
|
changeID(14, ground);
|
||
|
}
|
||
|
} else if(near_magician) {
|
||
|
restoreStatus();
|
||
|
changeID(-1, ground);
|
||
|
near_magician = false;movescene = true;button_magic.enabled = false;
|
||
|
} else if(!donut_eaten && sqlen(state.delta_l[0] - 6, state.delta_l[1] - 6) < 5){
|
||
|
donut_eaten = true;
|
||
|
state.life += 1;
|
||
|
pushStatus('Yum');
|
||
|
}
|
||
|
state.delta_height = dh;
|
||
|
} else {
|
||
|
rh = lh = pi/2;
|
||
|
lf = rf = 0;
|
||
|
if(state.wiggle_t > 0){
|
||
|
state.running = 1;
|
||
|
state.wiggle_t -= .025;
|
||
|
if(state.wiggle_t > 2)
|
||
|
head_rot = wiggle(state.wiggle_t-2);
|
||
|
}
|
||
|
}
|
||
|
clearObject(i);
|
||
|
const punch = state.dead?1:state.punch();
|
||
|
let overall_rot = 0, overall_death_trans = [0,0];
|
||
|
if(state.dead && state.death_t > 0){
|
||
|
state.death_t -= .025;
|
||
|
const t = jCurve(1-state.death_t);
|
||
|
overall_rot = -t*pi/2;
|
||
|
overall_death_trans[0] = 2.3*sin(overall_rot);
|
||
|
overall_death_trans[1] = -2.3*(1-cos(overall_rot));
|
||
|
rebuild[state.idx] = true;
|
||
|
}else if (state.dead){
|
||
|
overall_rot = -pi/2;
|
||
|
overall_death_trans[0] = -2.3;
|
||
|
overall_death_trans[1] = -2.3;
|
||
|
}
|
||
|
M.save();
|
||
|
M.translate(0, overall_death_trans[0], overall_death_trans[1]);
|
||
|
M.rotateX(overall_rot);
|
||
|
M.save();
|
||
|
M.translate(0, 1, 0);
|
||
|
M.rotateY(head_rot);
|
||
|
addObject(state.head, M.value(),i);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0.5, 0.2, 0.3);
|
||
|
M.rotateX((pi / 4)*punch);
|
||
|
M.translate(0, 0, .5);
|
||
|
M.save();
|
||
|
M.translate(0, 0, .4);
|
||
|
M.rotateX((-0.53 * pi)*punch);
|
||
|
M.scale(0.2, 0.2, 0.4);
|
||
|
M.translate(0, 0, 1);
|
||
|
addObject(state.cylinderMesh2, M.value(),i);
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(state.cylinderMesh2, M.value(),i);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-0.5, 0.2, 0.3);
|
||
|
M.rotateX(pi / 4);
|
||
|
M.translate(0, 0, .5);
|
||
|
M.save();
|
||
|
M.translate(0, 0, .4);
|
||
|
M.rotateX(-0.55 * pi);
|
||
|
M.scale(0.2, 0.2, 0.4);
|
||
|
M.translate(0, 0, 1);
|
||
|
addObject(state.cylinderMesh2, M.value(),i);
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(state.cylinderMesh2, M.value(),i);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0.3, -1, 0.);
|
||
|
M.rotateX(lh);
|
||
|
M.translate(0, 0, .5);
|
||
|
M.save();
|
||
|
M.translate(0, 0, .45);
|
||
|
M.rotateX(lf);
|
||
|
M.scale(0.2, 0.2, 0.6);
|
||
|
M.translate(0, 0, 1);
|
||
|
addObject(state.cylinderMesh3, M.value(),i);
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(state.cylinderMesh3, M.value(),i);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-0.3, -1, 0.);
|
||
|
M.rotateX(rh);
|
||
|
M.translate(0, 0, .5);
|
||
|
M.save();
|
||
|
M.translate(0, 0, .45);
|
||
|
M.rotateX(rf);
|
||
|
M.scale(0.2, 0.2, 0.6);
|
||
|
M.translate(0, 0, 1);
|
||
|
addObject(state.cylinderMesh3, M.value(),i);
|
||
|
M.restore();
|
||
|
M.scale(0.2, 0.2, 0.5);
|
||
|
addObject(state.cylinderMesh3, M.value(),i);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.rotateX(pi / 2);
|
||
|
M.scale(0.5, 0.5, 1);
|
||
|
addObject(state.cylinderMesh, M.value(),i);
|
||
|
M.restore();
|
||
|
|
||
|
M.restore();
|
||
|
if (state.running < 0)
|
||
|
rebuild[i] = false
|
||
|
};
|
||
|
|
||
|
let build_splines = () => {
|
||
|
star = [], star1 = [], star2 = [], star4 = [], newstar = [], adt = [], sakura = [];
|
||
|
var n = 11,
|
||
|
innerN = Math.ceil((paths[0].length * n) / paths[1].length);
|
||
|
for (let j = 0; j < paths[0].length; ++j) {
|
||
|
let xf = paths[0][j][0],
|
||
|
yf = paths[0][j][1];
|
||
|
for (var k = 0; k <= n; ++k) {
|
||
|
let t = k / n;
|
||
|
star1.push([7, dot(xf, [t * t * t, t * t, t, 1]),
|
||
|
dot(yf, [t * t * t, t * t, t, 1]),
|
||
|
0, 0, 0, 1
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (let j = 13; j >= 0; j--) {
|
||
|
let xf = paths[1][j][0],
|
||
|
yf = paths[1][j][1];
|
||
|
for (var k = innerN - 1; k >= 0; --k) {
|
||
|
let t = k / (innerN - 1);
|
||
|
star2.push([7, dot(xf, [t * t * t, t * t, t, 1]),
|
||
|
dot(yf, [t * t * t, t * t, t, 1]),
|
||
|
0, 0, 0, 1
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
for (let j = paths[1].length - 1; j > 12; --j) {
|
||
|
let xf = paths[1][j][0],
|
||
|
yf = paths[1][j][1];
|
||
|
for (var k = innerN; k >= 0; --k) {
|
||
|
let t = k / innerN;
|
||
|
star2.push([7, dot(xf, [t * t * t, t * t, t, 1]),
|
||
|
dot(yf, [t * t * t, t * t, t, 1]),
|
||
|
0, 0, 0, 1
|
||
|
]);
|
||
|
}
|
||
|
}
|
||
|
for (let i = 0; i < star1.length; ++i) {
|
||
|
concat(star, star1[i]);
|
||
|
concat(star, star2[i]);
|
||
|
}
|
||
|
n = 25;
|
||
|
for (let l = 2; l < 6; ++l) {
|
||
|
adt[l - 2] = [];
|
||
|
for (let j = 0; j < paths[l].length; ++j) {
|
||
|
let xf = paths[l][j][0],
|
||
|
yf = paths[l][j][1];
|
||
|
for (var k = 0; k <= n; ++k) {
|
||
|
let t = k / n;
|
||
|
adt[l - 2].push(10 + l, dot(xf, [t * t * t, t * t, t, 1]),
|
||
|
-dot(yf, [t * t * t, t * t, t, 1]),
|
||
|
0, 0, 0, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
n = 10;
|
||
|
for (let l = 6; l < 13; ++l) {
|
||
|
sakura[l - 6] = [];
|
||
|
for (let j = 0; j < paths[l].length; ++j) {
|
||
|
let xf = paths[l][j][0],
|
||
|
yf = paths[l][j][1];
|
||
|
for (var k = 0; k <= n; ++k) {
|
||
|
let t = k / n;
|
||
|
sakura[l - 6].push(10, dot(xf, [t * t * t, t * t, t, 1]),
|
||
|
dot(yf, [t * t * t, t * t, t, 1]),
|
||
|
0, 0, 0, 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for(let i = 0; i < 7; ++ i){
|
||
|
sakura[i] = new Float32Array(thicken_contour(.8, sakura[i]));
|
||
|
}
|
||
|
star4 = star.slice();
|
||
|
newstar = star.slice()
|
||
|
for (let i = 0; i < star.length; i += 7) {
|
||
|
star4[i] = 9;
|
||
|
newstar[i] = 8;
|
||
|
}
|
||
|
for (let i = 0; i < nstars; ++i) {
|
||
|
stars.push(star.slice());
|
||
|
startz.push(.6 * Math.random());
|
||
|
random_rot.push(0);
|
||
|
random_rot_pos.push(0);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
var M = new Matrix();
|
||
|
var buildsplines = true;
|
||
|
let magician = false,
|
||
|
magician_neck = false,
|
||
|
magician_houki = false,
|
||
|
body = false,
|
||
|
leg = false,
|
||
|
hand = false;
|
||
|
let sa2 = [
|
||
|
1.6, 0.4, .9, 1., .3, .2, -.4, .8,
|
||
|
-.8, -.1, -1.4, .5, -1.6, -.5
|
||
|
],
|
||
|
fsa2 = [
|
||
|
[matrix_multiply(bezierMat, [sa2[0], sa2[2], sa2[4], sa2[6]]),
|
||
|
matrix_multiply(bezierMat, [sa2[1], sa2[3], sa2[5], sa2[7]])
|
||
|
],
|
||
|
[matrix_multiply(bezierMat, [sa2[6], sa2[8], sa2[10], sa2[12]]),
|
||
|
matrix_multiply(bezierMat, [sa2[7], sa2[9], sa2[11], sa2[13]])
|
||
|
]
|
||
|
],
|
||
|
random_rot = [0, 0, 0, 0, 0, 0, 0],
|
||
|
random_rot_pos = [0, 0, 0, 0, 0, 0, 0],
|
||
|
startz = [];
|
||
|
|
||
|
let division = -1;
|
||
|
let changeID = (id, obj) => {
|
||
|
for (let i = 0; i < obj.length; i += 7) obj[i] = id;
|
||
|
}
|
||
|
|
||
|
let rtx_update = () => {
|
||
|
Sph[0] = [0,0.05*Math.cos(uTime + 1.),.045*Math.cos(uTime), 1,.15];
|
||
|
Sph[1] = [0,0,0,1,.25];
|
||
|
Sph[2] = [.22*Math.sin(uTime*1.2),0.05,.22*Math.cos(uTime*1.2),1,.05];
|
||
|
Sph[3] = [.9*Math.sin(uTime*.4),0.,.9*Math.cos(uTime*.4),1,.25];
|
||
|
Sph[4] = [0.5*Math.sin(uTime*1.),0.08*Math.sin(uTime *0.9),.5*Math.cos(uTime*1.),1,.12];
|
||
|
|
||
|
for(let i = 0; i < ns; ++ i)
|
||
|
{
|
||
|
let trsph = matrix_multiply(SphTr[i], Sph[i]);
|
||
|
trsph[3] = Sph[i][4];
|
||
|
setUniform('4fv', 'Sph['+ i + ']', trsph);
|
||
|
}
|
||
|
}
|
||
|
let draw_magician = (gl) => {
|
||
|
magician = magician ? magician : createMeshFromSpline(13, 32, 4, 4, 0, (i, _, oid) => {
|
||
|
if (oid == 4 && i == 10) return 3;
|
||
|
else if (oid == 3 && i == 16) return 2;
|
||
|
else if (oid == 2 && i == 23) return 1;
|
||
|
});
|
||
|
magician_neck = magician_neck ? magician_neck : createMeshFromSpline(14, 32, 4, 5, -.2);
|
||
|
magician_houki = magician_houki ? magician_houki : createMeshFromSpline(15, 32, 4, 6);
|
||
|
body = body ? body : createMeshFromSpline(16, 32, 4, 7, 0, (i, tmp) => {
|
||
|
if (division < 0 && i == 25) division = tmp.length;
|
||
|
});
|
||
|
leg = leg ? leg : createMeshFromSpline(17, 32, 4, 8);
|
||
|
hand = hand ? hand : createMeshFromSpline(18, 32, 4, 9, .015);
|
||
|
|
||
|
M.save();
|
||
|
M.scale(0.6);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(body.slice(0, division));
|
||
|
drawMesh(body.slice(division - 7), gl.LINE_LOOP);
|
||
|
M.save();
|
||
|
M.translate(0, 0, -1.05);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(magician);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(0, 0, -.53);
|
||
|
M.scale(.1);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(magician_neck);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-1, 0, 0);
|
||
|
M.scale(2);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(magician_houki);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-.06, 0, .85);
|
||
|
M.rotateY(0.02);
|
||
|
M.scale(1.2);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(leg);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(.06, 0, .85);
|
||
|
M.rotateY(-0.02);
|
||
|
M.scale(1.2);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(leg);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-.35, 0, -.1);
|
||
|
M.rotateY(-pi / 6);
|
||
|
M.scale(.82);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(hand);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(.35, 0, -.1);
|
||
|
M.rotateY(pi / 6);
|
||
|
M.scale(.82);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(hand);
|
||
|
M.restore();
|
||
|
M.restore();
|
||
|
}
|
||
|
let draw_deco = (gl) => {
|
||
|
|
||
|
M.save();
|
||
|
M.translate(-.7,.75,0);
|
||
|
//M.rotateZ(pi);
|
||
|
M.scale(0.6)
|
||
|
setM(M.value());
|
||
|
|
||
|
for(let l = 2; l < 6; ++l)
|
||
|
drawMesh(new Float32Array(adt[l-2]),gl.LINE_LOOP);
|
||
|
M.restore();
|
||
|
if(state.life >=.5)
|
||
|
{
|
||
|
M.save();
|
||
|
// M.scale(sin(uTime/2));
|
||
|
M.translate(-.23, .7, 0);
|
||
|
|
||
|
M.rotateZ(sin(uTime/6) + 0.2);
|
||
|
M.scale(0.4);
|
||
|
setM(M.value());
|
||
|
for(let l = 0; l < 5; ++l)
|
||
|
drawMesh(sakura[l],gl.TRIANGLE_STRIP);
|
||
|
M.restore();
|
||
|
}
|
||
|
if(state.life >= 1.5 )
|
||
|
{
|
||
|
M.save();
|
||
|
M.translate(0.2, .7, 0);
|
||
|
|
||
|
M.rotateZ(sin(uTime/6) + 0.2);
|
||
|
M.scale(0.4);
|
||
|
setM(M.value());
|
||
|
for(let l = 0; l < 5; ++l)
|
||
|
drawMesh(sakura[l],gl.TRIANGLE_STRIP);
|
||
|
M.restore();
|
||
|
}
|
||
|
if (state.life > 2.5)
|
||
|
{
|
||
|
M.save();
|
||
|
M.translate(.7, .7, 0);
|
||
|
M.rotateZ(sin(uTime/6) + 0.2);
|
||
|
M.scale(0.6);
|
||
|
M.scale(0.995);
|
||
|
M.save();
|
||
|
setM(M.value());
|
||
|
M.restore();
|
||
|
for(let l = 0; l < 5; ++l)
|
||
|
drawMesh(new Float32Array(sakura[l]),gl.TRIANGLE_STRIP);
|
||
|
M.restore();
|
||
|
}
|
||
|
}
|
||
|
let tv;
|
||
|
let make_tv = ()=>{
|
||
|
let screen = squareMesh(1,.5625, 1, -2), scrtr;
|
||
|
let stand = tubeMesh.slice(), standtr;
|
||
|
let base = cylinderMesh.slice(), basetr;
|
||
|
|
||
|
changeID(17, stand);
|
||
|
changeID(17, base);
|
||
|
M.save();
|
||
|
M.translate(0,0,-5.3);
|
||
|
M.rotateX(pi/2);
|
||
|
M.scale(8);
|
||
|
scrtr = M.value();
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.scale(.07, .07 ,.9);
|
||
|
standtr = M.value();
|
||
|
M.restore();
|
||
|
|
||
|
M.save();
|
||
|
M.translate(0,0,.9)
|
||
|
M.scale(1.7, 1.7 ,.03);
|
||
|
basetr = M.value()
|
||
|
M.restore();
|
||
|
tv = [[screen, scrtr], [stand, standtr], [base,basetr]];
|
||
|
}
|
||
|
let touch_screen;
|
||
|
let shader1_inited = false;
|
||
|
let draw_tv = (gl) => {
|
||
|
if(!tv) make_tv();
|
||
|
if(!touch_screen) {
|
||
|
touch_screen = new Button(()=>{
|
||
|
if(channel_disp == 4){
|
||
|
let i = hitTest(touch_screen.P);
|
||
|
if (i >= 0) {
|
||
|
dragging = true;
|
||
|
selected = true;
|
||
|
selection = i;
|
||
|
} else if (selected = true) {
|
||
|
dragging = false;
|
||
|
selected = false;
|
||
|
selection = i;
|
||
|
}
|
||
|
}
|
||
|
}, tv[0][0], 'square');
|
||
|
touch_screen.hover = (e)=>{ movescene = (e&&channel_disp == 4)?false:true;touch_screen.hovering =!movescene;};
|
||
|
}
|
||
|
M.save();
|
||
|
M.translate(-3, -2.2, -6);
|
||
|
M.rotateY(.6);
|
||
|
M.rotateX(pi/2);
|
||
|
tv.forEach((obj, i) => {
|
||
|
let m = matrix_multiply(sRotation, matrix_multiply(overall_ground,matrix_multiply(M.value(),obj[1])));
|
||
|
if(i == 0)
|
||
|
touch_screen.updateMatrix(m);
|
||
|
if(channel_disp == 4 && i == 0){
|
||
|
gl.useProgram(gl.shaders[1]);
|
||
|
gl.program = gl.shaders[1];
|
||
|
setM(m);
|
||
|
if(positionsupdated)
|
||
|
updatePositions();
|
||
|
setUniform('1f', 'uTime', uTime);
|
||
|
if(selection >= 0)
|
||
|
setUniform("1i", "sel", selection);
|
||
|
else
|
||
|
setUniform("1i", "sel", -1);
|
||
|
|
||
|
var offset = 0;
|
||
|
let attribs = [
|
||
|
.05,.05,.1, .5,.5,1., 1.,.5,.5,20., 0., .0, 1.3,
|
||
|
.1,.05,.05, 1.,.5,.5, 1.,.5,.5,10., .3,1.,1.3,
|
||
|
.1,.05,.05, .71,.71,.71, .71,.71,.71,10., 0.3,.0,1.5,
|
||
|
.1,.1,.1, .71,.71,.71, .71,.71,.71,10., 0.05,0., 1.,
|
||
|
.0,.0,.0, .0,.0,.0, .0,.0,.0,40., 0.,.85,1.5
|
||
|
]
|
||
|
for(let i = 0; i < ns; i++){
|
||
|
setUniform('3fv', 'Ambient['+i+']', attribs.slice(offset, offset += 3));
|
||
|
setUniform('3fv', 'Diffuse['+i+']', attribs.slice(offset, offset += 3));
|
||
|
setUniform('4fv', 'Specular['+i+']', attribs.slice(offset, offset += 4));
|
||
|
setUniform('1fv', 'ks['+i+']', attribs.slice(offset, offset += 1));
|
||
|
setUniform('1fv', 'kr['+i+']', attribs.slice(offset, offset += 1));
|
||
|
setUniform('1fv', 'kf['+i+']', attribs.slice(offset, offset += 1));
|
||
|
}
|
||
|
|
||
|
Sph[0] = [0,0.05*Math.cos(uTime + 1.),.045*Math.cos(uTime), 1,.15];
|
||
|
Sph[1] = [0,0,0,1,.25];
|
||
|
Sph[2] = [.22*Math.sin(uTime*1.2),0.05,.22*Math.cos(uTime*1.2),1,.05];
|
||
|
Sph[3] = [.9*Math.sin(uTime*.4),0.,.9*Math.cos(uTime*.4),1,.25];
|
||
|
Sph[4] = [0.5*Math.sin(uTime*1.),0.08*Math.sin(uTime *0.9),.5*Math.cos(uTime*1.),1,.12];
|
||
|
if(!shader1_inited){
|
||
|
//initTextures(gl, gl.program);
|
||
|
shader1_inited = true;
|
||
|
}
|
||
|
for(let i = 0; i < ns + 2; ++ i){
|
||
|
textures[i] = i;
|
||
|
gl.activeTexture(gl.TEXTURE0 + i);
|
||
|
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||
|
}
|
||
|
gl.uniform1iv(gl.getUniformLocation(gl.shaders[1], 'uSampler'), textures);
|
||
|
|
||
|
for(let i = 0; i < ns; ++ i)
|
||
|
{
|
||
|
let trsph = matrix_multiply(SphTr[i], Sph[i]);
|
||
|
trsph[3] = Sph[i][4];
|
||
|
setUniform('4fv', 'Sph['+ i + ']', trsph);
|
||
|
}
|
||
|
drawMesh(obj[0]);
|
||
|
gl.useProgram(gl.shaders[0]);
|
||
|
gl.program = gl.shaders[0];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
setM(m);
|
||
|
for(let i = 0; i < ns + 2; ++ i){
|
||
|
textures[i] = i;
|
||
|
gl.activeTexture(gl.TEXTURE0 + i);
|
||
|
gl.bindTexture(gl.TEXTURE_2D, texture[i]);
|
||
|
}
|
||
|
gl.uniform1iv(gl.getUniformLocation(gl.shaders[1], 'uSampler'), textures);
|
||
|
|
||
|
drawMesh(obj[0]);
|
||
|
}
|
||
|
});
|
||
|
M.restore();
|
||
|
}
|
||
|
let initialize=(lv) => {
|
||
|
difficulty = deepcopy(lv);
|
||
|
state1.set_stepSize(difficulty.speed);
|
||
|
state1.turnStep = difficulty.flex;
|
||
|
state1.delta_l = [4, -5];
|
||
|
channel = 3;state.initialize();state1.initialize();reset.onclick();state1.delta_l = [4,-5];
|
||
|
};
|
||
|
let tv_ctrl = new Button(()=>{initialize(difficulty_levels.hard);});
|
||
|
let tv_ctrl1 = new Button(()=>{initialize(difficulty_levels.medium);});
|
||
|
let tv_ctrl2 = new Button(()=>{initialize(difficulty_levels.easy);});
|
||
|
|
||
|
var ground = squareMesh();
|
||
|
let trace_star;
|
||
|
let drawTrace = (gl)=>{
|
||
|
if(!trace_star) trace_star = new Float32Array(star);
|
||
|
let newtrace = [];
|
||
|
trace.forEach((tr, _)=>{
|
||
|
M.save();
|
||
|
M.translate(tr[0], tr[1], 0);
|
||
|
M.scale(tr[2]*.07);
|
||
|
const newid = 16 + (1-pow(10, tr[2])/10)*.5
|
||
|
for(let i = 0; i < trace_star.length; i += 7)
|
||
|
trace_star[i] = newid;
|
||
|
setM(M.value());
|
||
|
drawMesh(trace_star);
|
||
|
M.restore();
|
||
|
tr[2] -= .05;
|
||
|
if(tr[2] > 0)
|
||
|
newtrace.push(tr);
|
||
|
});
|
||
|
trace = newtrace;
|
||
|
}
|
||
|
function setTVCtrl() {
|
||
|
|
||
|
let setup_control = (control, str, id) =>{
|
||
|
control.resetShape(sphereMesh);
|
||
|
changeID(id +.15, control.getShape());
|
||
|
control.hover = (e = true) =>{
|
||
|
if(e){
|
||
|
if(status_history.len <= 2)
|
||
|
pushStatus(str);
|
||
|
else updateStatus(str);
|
||
|
control.hovering = true;
|
||
|
changeID(id, control.getShape());
|
||
|
} else {
|
||
|
restoreStatus();
|
||
|
changeID(id + .15, control.getShape());
|
||
|
control.hovering = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
setup_control(tv_ctrl, 'Difficulty Level: Hard.', 8);
|
||
|
setup_control(tv_ctrl1, 'Difficulty Level: Medium.', 9);
|
||
|
setup_control(tv_ctrl2, 'Difficulty Level: Easy.', 10);
|
||
|
}
|
||
|
let drawstars = ()=>{
|
||
|
for (let i = 0; i < nstars; ++i) {
|
||
|
M.save()
|
||
|
let f_idx = (uTime / (abs(sin(i * 1234)) * 8 + 10)) % 2,
|
||
|
t = f_idx - Math.floor(f_idx);
|
||
|
f_idx -= t;
|
||
|
let curr_mat = [t * t * t, t * t, t, 1];
|
||
|
M.translate(1.2 * sin(sin(uTime / (i + 2) + i + 8) * .9 + dot(fsa2[f_idx][0], curr_mat) * 5 + startz[Math.floor(2 * startz[i] * nstars) % nstars]), 1.2 * cos(i + sin(uTime / (i / 2 + 18) + 12) * .1 + startz[nstars - i - 1] + dot(fsa2[f_idx][1], curr_mat) * startz[(nstars + i) % nstars] * .4 + i * sin(random_rot_pos[i] / 30) / pi), .65 * startz[i] + .3 * sin(random_rot_pos[i] / 20));
|
||
|
let epsilon = 1 / (i * 2 + 20);
|
||
|
let random = () => {
|
||
|
var u = 0,
|
||
|
v = 0;
|
||
|
while (u === 0) u = Math.random(); //Converting [0,1) to (0,1)
|
||
|
while (v === 0) v = Math.random();
|
||
|
return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v) / pi;
|
||
|
}
|
||
|
if ((window.performance.now() + i * (2 + abs(random()))) % 69 < 2) {
|
||
|
changeID(Math.ceil(Math.random() * 20) - 5, stars[i])
|
||
|
}
|
||
|
random_rot[i] += random() * epsilon;
|
||
|
random_rot_pos[i] += .5 + abs(random()) / (pi + i);
|
||
|
//setM(M.value);
|
||
|
M.rotateZ(sin(random_rot_pos[i] / 10) * pi);
|
||
|
M.rotateX(.1 * sin(random_rot_pos[i] / (i + 50)) * pi);
|
||
|
M.rotateY(.1 * sin(random_rot_pos[i] / (i * 2 + 50)) * pi);
|
||
|
|
||
|
M.scale(0.2 + startz[i] * .2);
|
||
|
setM(M.value());
|
||
|
drawMesh(new Float32Array(stars[i]));
|
||
|
M.restore();
|
||
|
}
|
||
|
}
|
||
|
let slider, slider_body, button_magic = new Button(()=>{
|
||
|
show_magic = !show_magic;
|
||
|
if(show_magic)
|
||
|
changeID(4.1, button_magic.shape);
|
||
|
else
|
||
|
changeID(16.15, button_magic.shape);
|
||
|
});
|
||
|
let make_slider = () => {
|
||
|
slider = createCube(9,.05,.05,12);
|
||
|
slider_body = createCube(.4,.14,.7,12);
|
||
|
button_magic.resetShape(sphereMesh25);
|
||
|
button_magic.hover=(e) => {
|
||
|
id = button_magic.shape[0];
|
||
|
if(id < 5)
|
||
|
id = e?4.1:4.2;
|
||
|
else
|
||
|
id = e?16.15:16.45;
|
||
|
if(e){
|
||
|
if(!button_magic.hovering){
|
||
|
changeID(id, button_magic.shape);
|
||
|
button_magic.hovering = true;
|
||
|
}
|
||
|
} else
|
||
|
{
|
||
|
if(button_magic.hovering){
|
||
|
changeID(id, button_magic.shape);
|
||
|
button_magic.hovering = false;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
if(!near_magician)
|
||
|
button_magic.enabled = false;
|
||
|
};
|
||
|
let draw_slider = ()=>{
|
||
|
if(isNaN(slider_dl))
|
||
|
slider_dl = 0;
|
||
|
M.save();
|
||
|
M.translate(2, -3, 7);
|
||
|
setM(matrix_multiply(sRotation,matrix_multiply(overall_ground,M.value())));
|
||
|
drawMesh(slider);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-2.5 + slider_dl, -3, 7);
|
||
|
setM(matrix_multiply(sRotation,matrix_multiply(overall_ground,M.value())));
|
||
|
drawMesh(slider_body);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(-6, -3, 7);
|
||
|
button_magic.updateMatrix(matrix_multiply(sRotation,matrix_multiply(overall_ground,M.value())));
|
||
|
button_magic.draw();
|
||
|
M.restore();
|
||
|
};
|
||
|
var iMesh = [], tMesh, tMesh2, eMesh;
|
||
|
function createEar(){
|
||
|
M.save();
|
||
|
M.scale(.5,.5,.35);
|
||
|
M.rotateX(pi/2);
|
||
|
eMesh = createMeshFromSpline(19, 32, 4, 1, .0);
|
||
|
transform_mesh(M.value(), eMesh);
|
||
|
M.restore();
|
||
|
}
|
||
|
function createTail(){
|
||
|
let tail = [
|
||
|
2.37,1.48,
|
||
|
109.39,18.21,
|
||
|
96.13,88.3,
|
||
|
|
||
|
96.13,88.3,
|
||
|
126.44,94.93,
|
||
|
118.86,135.21,
|
||
|
|
||
|
118.86,135.21,
|
||
|
148.54,135.21,
|
||
|
146.96,164.7,
|
||
|
|
||
|
146.96,164.7,
|
||
|
172.85,168.17,
|
||
|
169.38,184.27,
|
||
|
|
||
|
169.38,184.27,
|
||
|
124.87,179.22,
|
||
|
131.34,148.2,
|
||
|
|
||
|
131.34,148.2,
|
||
|
99.92, 148.2,
|
||
|
105.66,115.13,
|
||
|
|
||
|
105.66,115.13,
|
||
|
63.62,117.02,
|
||
|
75.2,68.93,
|
||
|
|
||
|
75.2,68.93,
|
||
|
12.78,62.41,
|
||
|
2.37,1.48,
|
||
|
|
||
|
96.13,88.3,
|
||
|
118.86,135.21,
|
||
|
75.2,68.93,
|
||
|
|
||
|
], tx_max = -1000, tx_min = 1000, ty_max= -1000, ty_min = 1000;
|
||
|
for(let i = 0; i < tail.length; i += 2){
|
||
|
tx_max = tx_max > tail[i]?tx_max:tail[i];
|
||
|
tx_min = tx_min < tail[i]?tx_min:tail[i];
|
||
|
ty_max = Math.max(ty_max, tail[i+1]);
|
||
|
ty_min = Math.min(ty_min, tail[i+1]);
|
||
|
}
|
||
|
let tx_scale = tx_max - tx_min, ty_scale = ty_max - ty_min;
|
||
|
let t_scale = Math.max(tx_scale, ty_scale);
|
||
|
for(let i = 0; i < tail.length; i += 2){
|
||
|
tail[i] = (tail[i] - tx_min) / t_scale;
|
||
|
tail[i + 1] = (tail[i + 1] - ty_min) / t_scale;
|
||
|
}
|
||
|
let l = tail.length / 2;
|
||
|
tMesh = new Float32Array(2*l*7), tMesh2 = new Float32Array(2*l*7);
|
||
|
for(let i = 0; i < l; ++ i)
|
||
|
{
|
||
|
tMesh[i*7] = 1;
|
||
|
tMesh[i*7+1] = tail[i*2];
|
||
|
tMesh[i*7+2] = tail[i*2 + 1];
|
||
|
tMesh[i*7+3] = .03;
|
||
|
tMesh[i*7+4] = 0;
|
||
|
tMesh[i*7+5] = 0;
|
||
|
tMesh[i*7+6] = -1;
|
||
|
|
||
|
tMesh[l*7+i*7] = 1;
|
||
|
tMesh[l*7+i*7+1] = tail[i*2];
|
||
|
tMesh[l*7+i*7+2] = tail[i*2 + 1];
|
||
|
tMesh[l*7+i*7+3] = -.03;
|
||
|
tMesh[l*7+i*7+4] = 0;
|
||
|
tMesh[l*7+i*7+5] = 0;
|
||
|
tMesh[l*7+i*7+6] = 1;
|
||
|
|
||
|
tMesh2[i*14] = 1;
|
||
|
tMesh2[i*14+1] = tail[i*2];
|
||
|
tMesh2[i*14+2] = tail[i*2 + 1];
|
||
|
tMesh2[i*14+3] = .03;
|
||
|
tMesh2[i*14+4] = 0;
|
||
|
tMesh2[i*14+5] = 0;
|
||
|
tMesh2[i*14+6] = -1;
|
||
|
tMesh2[i*14 + 7] = 1;
|
||
|
tMesh2[i*14+8] = tail[i*2];
|
||
|
tMesh2[i*14+9] = tail[i*2 + 1];
|
||
|
tMesh2[i*14+10] = -.03;
|
||
|
tMesh2[i*14+11] = 0;
|
||
|
tMesh2[i*14+12] = 0;
|
||
|
tMesh2[i*14+13] = 1;
|
||
|
}
|
||
|
}
|
||
|
function updateImplicitShapes(){
|
||
|
let divs = 100;
|
||
|
let params = [
|
||
|
|
||
|
[
|
||
|
[[-.3,0.13,.43], .07],
|
||
|
[[-.3,0.1,.4], .09],
|
||
|
[[-.3,-.08,.22], .09],
|
||
|
[[-.25,0,.2], .14],
|
||
|
[[-.25,-.1,.15], .14],
|
||
|
[[-.2,-0.05,.15], .15],[[-.2, .15, -0.05], .15],
|
||
|
[[-.2,-.08,.12], .15],[[-.20, .12, -0.08], .15],
|
||
|
],[
|
||
|
[[-.3, .43, 0.12], .07],
|
||
|
[[-.3, .4, 0.1], .09],
|
||
|
[[-.3, .22, -0.08], .09],
|
||
|
[[-.25, .2, 0], .14],
|
||
|
[[-.25, .15, -0.1], .14],
|
||
|
[[-.2,-0.05,.15], .15],[[-.2, .15, -0.05], .15],
|
||
|
[[-.2, .15, -0.05], .15],[[-.20, .12, -0.08], .15],
|
||
|
],
|
||
|
[
|
||
|
[[-.2,-.21, .09], .2],[[-.2,.09, -.21], .2],
|
||
|
[[-.15,-.08, -.08], .2],
|
||
|
[[-.0,-0.12,0.12],.165],[[-.0,.12,-.12],.165],
|
||
|
[[.05,-0.14,.01],.17],[[.05,0.01,-.14],.17],
|
||
|
|
||
|
[[.15,-0.1,0.04],.17],[[.15,.04,-.1],.17],
|
||
|
|
||
|
[[.45,0.04,0.04],.2],
|
||
|
// [[.5,.06, .06], .18],
|
||
|
], //body
|
||
|
[
|
||
|
[[.35,0.06,0.06],.1],
|
||
|
[[.45,0.18,0.],.16],[[.45,0.,0.18],.16],
|
||
|
// [[.5,0.1,0.1],.1],
|
||
|
[[.55,0.0,0.0],.16],
|
||
|
[[.5,0.16,0.16],.1],
|
||
|
[[.65,0.12,0.0],.16],[[.65,0.0,0.12],.16]
|
||
|
|
||
|
], //head
|
||
|
];
|
||
|
params.forEach((p, i)=>{
|
||
|
iMesh[i] = implicitSurfaceTriangleMesh(implicitFunction, divs,
|
||
|
p,1);
|
||
|
});
|
||
|
}
|
||
|
function animate(gl) {
|
||
|
buildsplines &&= build_splines();// || setTVCtrl();
|
||
|
if(iMesh.length == 0) updateImplicitShapes();
|
||
|
if(tMesh === undefined) createTail();
|
||
|
if(eMesh === undefined) createEar();
|
||
|
if (animating) {
|
||
|
uTime = (Date.now() - startTime) / 1000;
|
||
|
} else {
|
||
|
uTime = (lastTime - startTime) / 1000;
|
||
|
//setUniform('1f', 'uTime', uTime);
|
||
|
}
|
||
|
gl.enable(gl.DEPTH_TEST);
|
||
|
let orig_rot = sRotation.slice();
|
||
|
sRotation = matrix_multiply(matrix_translate(-.3, 0,0), orig_rot);
|
||
|
|
||
|
M.save();
|
||
|
M.scale(0.1);
|
||
|
M.rotateX(.6);
|
||
|
M.rotateZ(.35);
|
||
|
overall_ground = M.value();
|
||
|
|
||
|
M.translate(state.delta_l[0], -state.delta_height, state.delta_l[1]);
|
||
|
M.rotateY(state.curr_figure_rot);
|
||
|
overall_trans = M.value();
|
||
|
M.restore();
|
||
|
|
||
|
|
||
|
M.save();
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
iMesh.forEach( (mesh, _)=>
|
||
|
{
|
||
|
drawMesh(mesh);
|
||
|
});
|
||
|
|
||
|
M.restore();
|
||
|
|
||
|
|
||
|
M.save();
|
||
|
M.scale(.8);
|
||
|
M.translate(.1, -.62, -.62);
|
||
|
M.rotateX(.8);
|
||
|
M.rotateY(pi);
|
||
|
M.rotateZ(-.1);
|
||
|
M.translate(-.5, -.5,0);
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(tMesh, gl.TRIANGLES);
|
||
|
drawMesh(tMesh2);
|
||
|
|
||
|
M.restore();
|
||
|
|
||
|
M.save();
|
||
|
M.translate(1., .1, -.15);
|
||
|
M.rotateY(-.5*pi);
|
||
|
M.rotateX(-.5*pi);
|
||
|
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(eMesh);
|
||
|
M.restore();
|
||
|
M.save();
|
||
|
M.translate(.9, -.1, .35);
|
||
|
M.rotateY(-1.*pi);
|
||
|
M.rotateX(-.5*pi);
|
||
|
M.rotateZ(.2*pi);
|
||
|
|
||
|
setM(matrix_multiply(sRotation, M.value()));
|
||
|
drawMesh(eMesh);
|
||
|
M.restore();
|
||
|
gl.disable(gl.DEPTH_TEST);
|
||
|
drawTrace(gl);
|
||
|
sRotation = orig_rot;
|
||
|
}
|