Merge branch 'master' into transition1
BIN
docs/assets/images/blinkOverlay.png
Normal file
After Width: | Height: | Size: 470 KiB |
BIN
docs/assets/images/epic.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
docs/assets/images/eye.png
Normal file
After Width: | Height: | Size: 381 B |
BIN
docs/assets/images/eyeDry.png
Normal file
After Width: | Height: | Size: 279 B |
BIN
docs/assets/images/heartBack.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
docs/assets/images/heartCover.png
Normal file
After Width: | Height: | Size: 784 B |
Before Width: | Height: | Size: 9.3 KiB |
BIN
docs/assets/images/tempIcon.png
Normal file
After Width: | Height: | Size: 189 B |
BIN
docs/assets/images/tutArrow.png
Normal file
After Width: | Height: | Size: 191 B |
BIN
docs/assets/images/tutKeyC.png
Normal file
After Width: | Height: | Size: 200 B |
BIN
docs/assets/images/tutKeyX.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
docs/assets/images/tutKeyZ.png
Normal file
After Width: | Height: | Size: 230 B |
BIN
docs/assets/images/tutSelect0.png
Normal file
After Width: | Height: | Size: 209 B |
BIN
docs/assets/images/tutSelect1.png
Normal file
After Width: | Height: | Size: 192 B |
@ -3,16 +3,25 @@ function drawTitleScreenUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var playingUIOffsets = {
|
||||||
|
heart: 100,
|
||||||
|
breath: 100,
|
||||||
|
blink: 100
|
||||||
|
};
|
||||||
|
|
||||||
// UI for playing
|
// UI for playing
|
||||||
function drawPlayingUI() {
|
function drawPlayingUI() {
|
||||||
|
|
||||||
// cartesianRect(0,ch/3*2, cw, ch/3, "#333333")
|
// cartesianRect(0,ch/3*2, cw, ch/3, "#333333")
|
||||||
|
|
||||||
//Heart Rate Monitor
|
//Heart Rate Monitor
|
||||||
heartBeatUI(cw/4*3-8,ch/8*7-8,cw/4,ch/8);
|
heartBeatUI(cw / 4 * 3 - 8, ch / 8 * 7 - 8 + playingUIOffsets.heart, cw / 4, ch / 8);
|
||||||
|
|
||||||
//Respiration Monitor
|
//Respiration Monitor
|
||||||
respiratoryUI(cw/8*5,ch/8*7-8, cw/16, ch/8);
|
respiratoryUI(cw / 8 * 5, ch / 8 * 7 - 8 + playingUIOffsets.breath, cw / 16, ch / 8);
|
||||||
|
|
||||||
|
//Blink eye and overlay
|
||||||
|
blinkUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
//UI for pause screen
|
//UI for pause screen
|
||||||
@ -30,9 +39,9 @@ function drawEndUI() {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function respiratoryUI(x, y, width, height){
|
function respiratoryUI(x, y, width, height) {
|
||||||
cartesianRect(x,y,width,height, "rgb("+noBreathTimer/180*255+","+0+","+0+")");
|
cartesianRect(x, y, width, height, "rgb(" + noBreathTimer / 180 * 255 + "," + 0 + "," + 0 + ")");
|
||||||
cartesianRect(x,y+(height-breath/constants.lifeFuncs.breath.fullBreath*height), width, breath/constants.lifeFuncs.breath.fullBreath*height, "rgb("+255+","+(255-fullBreathTimer/180*255)+","+(255-fullBreathTimer/180*255)+")");
|
cartesianRect(x, y + (height - breath / constants.lifeFuncs.breath.fullBreath * height), width, breath / constants.lifeFuncs.breath.fullBreath * height, "rgb(" + 255 + "," + (255 - fullBreathTimer / 180 * 255) + "," + (255 - fullBreathTimer / 180 * 255) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -43,8 +52,8 @@ function respiratoryUI(x, y, width, height){
|
|||||||
|
|
||||||
//Heart rate monitor history
|
//Heart rate monitor history
|
||||||
let heartBeatHistory = [];
|
let heartBeatHistory = [];
|
||||||
heartBeatHistory.length = constants.ui.heartRate.history_length;
|
heartBeatHistory.length = constants.ui.heartRate.history_length;
|
||||||
heartBeatHistory.fill(0);
|
heartBeatHistory.fill(0);
|
||||||
|
|
||||||
//Shift accumulation
|
//Shift accumulation
|
||||||
let shiftAccum = 0;
|
let shiftAccum = 0;
|
||||||
@ -53,12 +62,12 @@ let shiftAccum = 0;
|
|||||||
let beatTimeElapsed = Infinity;
|
let beatTimeElapsed = Infinity;
|
||||||
|
|
||||||
// Draw heartbeat UI
|
// Draw heartbeat UI
|
||||||
function heartBeatUI(x, y, width, height){
|
function heartBeatUI(x, y, width, height) {
|
||||||
|
|
||||||
//Shift monitor over once a full scrolling unit is accumulated
|
//Shift monitor over once a full scrolling unit is accumulated
|
||||||
shiftAccum += constants.ui.heartRate.scroll_speed;
|
shiftAccum += constants.ui.heartRate.scroll_speed;
|
||||||
if(shiftAccum>=1){
|
if (shiftAccum >= 1) {
|
||||||
shiftAccum%=1;
|
shiftAccum %= 1;
|
||||||
beatTimeElapsed += 0.04;
|
beatTimeElapsed += 0.04;
|
||||||
|
|
||||||
//Remove oldest value
|
//Remove oldest value
|
||||||
@ -69,60 +78,90 @@ function heartBeatUI(x, y, width, height){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//If heart is beaten, reset beat timer.
|
//If heart is beaten, reset beat timer.
|
||||||
if(heartBeat){
|
if (heartBeat) {
|
||||||
beatTimeElapsed = 0;
|
beatTimeElapsed = 0;
|
||||||
heartBeat = false;
|
heartBeat = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Backdrop
|
//Backdrop
|
||||||
rect(x+width/2,y+height/2,width,height,"black");
|
var BackdropColor;
|
||||||
|
if (pressure > 42 && pressure < 60) {
|
||||||
|
BackdropColor = "#0c2605";
|
||||||
|
} else if (pressure > 28 && pressure < 75) {
|
||||||
|
BackdropColor = "#2b2b06";
|
||||||
|
} else {
|
||||||
|
BackdropColor = "#260505";
|
||||||
|
}
|
||||||
|
rect(x + width / 2, y + height / 2, width, height, BackdropColor);
|
||||||
|
img(sprites.heartBack, cw - 107, ch - 46 + playingUIOffsets.heart);
|
||||||
|
|
||||||
//Pressure Meter
|
//Pressure Meter
|
||||||
rect(x+width-8,y+height/2,16,height,"red");
|
rect(x + width - 8, y + height / 2, 16, height, "red");
|
||||||
rect(x+width-8,y+height/2,16,height/2,"yellow");
|
rect(x + width - 8, y + height / 2, 16, height / 2, "yellow");
|
||||||
rect(x+width-8,y+height/2,16,height/6,"green");
|
rect(x + width - 8, y + height / 2, 16, height / 6, "green");
|
||||||
let pressureHeight = Math.max(Math.min(y+height-(pressure/constants.lifeFuncs.cardio.optimalPressure*height/2),y+height),y);
|
let pressureHeight = Math.max(Math.min(y + height - (pressure / constants.lifeFuncs.cardio.optimalPressure * height / 2), y + height), y);
|
||||||
line(x+width-16, pressureHeight,x+width,pressureHeight, 2,"black")
|
line(x + width - 16, pressureHeight, x + width, pressureHeight, 2, "black")
|
||||||
|
|
||||||
//Graph
|
//Graph
|
||||||
for (let index = 0; index < heartBeatHistory.length; index++) {
|
for (let index = 0; index < heartBeatHistory.length; index++) {
|
||||||
const qrsValueAtPosition = heartBeatHistory[index];
|
const qrsValueAtPosition = heartBeatHistory[index];
|
||||||
const qrsValueAtNextPosition = heartBeatHistory[index+1];
|
const qrsValueAtNextPosition = heartBeatHistory[index + 1];
|
||||||
line(x+(index*(width-16)/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtPosition*(width-16)/heartBeatHistory.length), x+((index+1)*(width-16)/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtNextPosition*(width-16)/heartBeatHistory.length),Math.min(3,Math.max(3/beatTimeElapsed,1)), "red");
|
line(x + (index * (width - 16) / heartBeatHistory.length), y + (2 * height / 3) + (qrsValueAtPosition * (width - 16) / heartBeatHistory.length), x + ((index + 1) * (width - 16) / heartBeatHistory.length), y + (2 * height / 3) + (qrsValueAtNextPosition * (width - 16) / heartBeatHistory.length), Math.min(3, Math.max(3 / beatTimeElapsed, 1)), "red");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cover
|
||||||
|
img(sprites.heartCover, cw - 107, ch - 46 + playingUIOffsets.heart);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Determine next value to be added to the graph
|
//Determine next value to be added to the graph
|
||||||
function pushNextBeatValue(){
|
function pushNextBeatValue() {
|
||||||
let nextBeatValue = 0;
|
let nextBeatValue = 0;
|
||||||
|
|
||||||
//Timespan of one "square" on the EKG
|
//Timespan of one "square" on the EKG
|
||||||
const squareSize = constants.ui.heartRate.square_size;
|
const squareSize = constants.ui.heartRate.square_size;
|
||||||
//Length of full complex
|
//Length of full complex
|
||||||
const complexTime = constants.ui.heartRate.complex_width*squareSize;
|
const complexTime = constants.ui.heartRate.complex_width * squareSize;
|
||||||
//Length of PR segment of complex
|
//Length of PR segment of complex
|
||||||
const prTime = constants.ui.heartRate.pr_width*squareSize;
|
const prTime = constants.ui.heartRate.pr_width * squareSize;
|
||||||
//Length of QRS component of complex
|
//Length of QRS component of complex
|
||||||
const qrsTime = constants.ui.heartRate.qrs_width*squareSize;
|
const qrsTime = constants.ui.heartRate.qrs_width * squareSize;
|
||||||
//Length of QT component of complex
|
//Length of QT component of complex
|
||||||
const qtTime = constants.ui.heartRate.qt_width*squareSize;
|
const qtTime = constants.ui.heartRate.qt_width * squareSize;
|
||||||
|
|
||||||
if(beatTimeElapsed<=complexTime) {
|
if (beatTimeElapsed <= complexTime) {
|
||||||
//PR Segment
|
//PR Segment
|
||||||
if (beatTimeElapsed <= prTime) {
|
if (beatTimeElapsed <= prTime) {
|
||||||
nextBeatValue = 0.5*(Math.pow((beatTimeElapsed/squareSize - (prTime/2/squareSize)), 2)) - 2;
|
nextBeatValue = 0.5 * (Math.pow((beatTimeElapsed / squareSize - (prTime / 2 / squareSize)), 2)) - 2;
|
||||||
} else if (beatTimeElapsed > prTime + squareSize && beatTimeElapsed <= prTime + squareSize + (qrsTime / 4)) { //QRS Segment pt. 1
|
} else if (beatTimeElapsed > prTime + squareSize && beatTimeElapsed <= prTime + squareSize + (qrsTime / 4)) { //QRS Segment pt. 1
|
||||||
nextBeatValue = -4 + beatTimeElapsed/squareSize;
|
nextBeatValue = -4 + beatTimeElapsed / squareSize;
|
||||||
} else if (beatTimeElapsed > prTime + squareSize + qrsTime / 4 && beatTimeElapsed <= prTime + squareSize + qrsTime / 2) { //QRS Segment pt. 2
|
} else if (beatTimeElapsed > prTime + squareSize + qrsTime / 4 && beatTimeElapsed <= prTime + squareSize + qrsTime / 2) { //QRS Segment pt. 2
|
||||||
nextBeatValue = -14 * (beatTimeElapsed/squareSize - 4.5) - 0.5;
|
nextBeatValue = -14 * (beatTimeElapsed / squareSize - 4.5) - 0.5;
|
||||||
} else if (beatTimeElapsed > prTime + squareSize + qrsTime / 2 && beatTimeElapsed <= prTime + squareSize + (3*qrsTime / 4)) { //QRS Segment pt. 3
|
} else if (beatTimeElapsed > prTime + squareSize + qrsTime / 2 && beatTimeElapsed <= prTime + squareSize + (3 * qrsTime / 4)) { //QRS Segment pt. 3
|
||||||
nextBeatValue = 7 * (beatTimeElapsed/squareSize - 5) - 6.5;
|
nextBeatValue = 7 * (beatTimeElapsed / squareSize - 5) - 6.5;
|
||||||
} else if (beatTimeElapsed > prTime + squareSize + (3*qrsTime / 4) && beatTimeElapsed <= prTime + squareSize + qrsTime) { //QRS Segment pt. 4
|
} else if (beatTimeElapsed > prTime + squareSize + (3 * qrsTime / 4) && beatTimeElapsed <= prTime + squareSize + qrsTime) { //QRS Segment pt. 4
|
||||||
nextBeatValue = 2 * (beatTimeElapsed/squareSize - 6);
|
nextBeatValue = 2 * (beatTimeElapsed / squareSize - 6);
|
||||||
} else if (beatTimeElapsed > prTime + squareSize*2 + qrsTime && beatTimeElapsed <= prTime + squareSize*2 + qrsTime + qtTime) { //PT Segment
|
} else if (beatTimeElapsed > prTime + squareSize * 2 + qrsTime && beatTimeElapsed <= prTime + squareSize * 2 + qrsTime + qtTime) { //PT Segment
|
||||||
nextBeatValue = 0.5 * Math.pow((beatTimeElapsed/squareSize - (prTime + squareSize*2 + qrsTime + qtTime/2)/squareSize),2) - 3;
|
nextBeatValue = 0.5 * Math.pow((beatTimeElapsed / squareSize - (prTime + squareSize * 2 + qrsTime + qtTime / 2) / squareSize), 2) - 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heartBeatHistory.push(nextBeatValue);
|
heartBeatHistory.push(nextBeatValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function blinkUI() {
|
||||||
|
// eye
|
||||||
|
img(sprites.eye, cw - 350, ch - 40 + playingUIOffsets.blink, 0, 2, 2);
|
||||||
|
var alpha = clamp(eyeDryness / constants.lifeFuncs.blink.dryTime, 0, 1);
|
||||||
|
curCtx.globalAlpha = alpha;
|
||||||
|
img(sprites.eyeDry, cw - 350, ch - 40 + playingUIOffsets.blink, 0, 2, 2);
|
||||||
|
|
||||||
|
// dry overlay
|
||||||
|
if (eyeDryness > constants.lifeFuncs.blink.dryTime) {
|
||||||
|
alpha = (eyeDryness - constants.lifeFuncs.blink.dryTime) / 350;
|
||||||
|
curCtx.globalAlpha = alpha;
|
||||||
|
img(sprites.blinkOverlay, cw / 2, ch / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
curCtx.globalAlpha = 1;
|
||||||
|
}
|
@ -37,25 +37,30 @@ var constants = {
|
|||||||
},
|
},
|
||||||
lifeFuncs:{
|
lifeFuncs:{
|
||||||
breath:{
|
breath:{
|
||||||
fullBreath: 200
|
fullBreath: 200,
|
||||||
|
cough_interval_secs: 4.0
|
||||||
},
|
},
|
||||||
cardio:{
|
cardio:{
|
||||||
optimalPressure: 50
|
optimalPressure: 50
|
||||||
|
},
|
||||||
|
blink: {
|
||||||
|
dryTime: 600
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
player:{
|
player:{
|
||||||
leg_speed: 0.1,
|
leg_speed: 0.1,
|
||||||
movement_divider: 50,
|
movement_divider: 50,
|
||||||
max_movement_speed: 3,
|
max_movement_speed: 3,
|
||||||
width: 30,
|
width: 40,
|
||||||
height: 50,
|
height: 75,
|
||||||
select_range: 10,
|
select_range: 10,
|
||||||
|
leg_length: 75,
|
||||||
hip: {
|
hip: {
|
||||||
offset_x: 15,
|
offset_x: 20,
|
||||||
offset_y: 25
|
offset_y: 35
|
||||||
},
|
},
|
||||||
defaultX: 500,
|
defaultX: 600,
|
||||||
defaultY: -70
|
defaultY: -170
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
@ -5,7 +5,18 @@ page_preloader.show(true);
|
|||||||
images = [
|
images = [
|
||||||
"assets/images/",
|
"assets/images/",
|
||||||
"level.png",
|
"level.png",
|
||||||
"level_2.png"
|
"epic.png",
|
||||||
|
"heartCover.png",
|
||||||
|
"heartBack.png",
|
||||||
|
"blinkOverlay.png",
|
||||||
|
"eye.png",
|
||||||
|
"eyeDry.png",
|
||||||
|
"tutSelect0.png",
|
||||||
|
"tutSelect1.png",
|
||||||
|
"tutArrow.png",
|
||||||
|
"tutKeyZ.png",
|
||||||
|
"tutKeyX.png",
|
||||||
|
"tutKeyC.png"
|
||||||
];
|
];
|
||||||
|
|
||||||
audio = [
|
audio = [
|
||||||
@ -73,10 +84,7 @@ function draw() {
|
|||||||
break;
|
break;
|
||||||
// playing
|
// playing
|
||||||
case globalStates.playing:
|
case globalStates.playing:
|
||||||
camera.zoom = 1;
|
drawPlaying();
|
||||||
drawWorldBlocks();
|
|
||||||
imgIgnoreCutoff(sprites.level_2,0,0,0,4,4);
|
|
||||||
player.draw();
|
|
||||||
break;
|
break;
|
||||||
// paused
|
// paused
|
||||||
case globalStates.paused:
|
case globalStates.paused:
|
||||||
@ -88,7 +96,7 @@ function draw() {
|
|||||||
break;
|
break;
|
||||||
//building - to be used only in development
|
//building - to be used only in development
|
||||||
case globalStates.building:
|
case globalStates.building:
|
||||||
|
imgIgnoreCutoff(sprites.epic,0,0);
|
||||||
buildDraw();
|
buildDraw();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
let breath = 180;
|
let breath = 200;
|
||||||
let fullBreathTimer = 0;
|
let fullBreathTimer = 0;
|
||||||
let noBreathTimer = 0;
|
let noBreathTimer = 0;
|
||||||
let pressure = 50;
|
let pressure = 55;
|
||||||
|
|
||||||
let heartBeat = false;
|
let heartBeat = false;
|
||||||
|
|
||||||
@ -11,26 +11,60 @@ var breathMode = {
|
|||||||
exhale: 1
|
exhale: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
let currentBreathMode = breathMode.exhale;
|
let currentBreathMode = breathMode.inhale;
|
||||||
|
|
||||||
|
|
||||||
|
let eyeDryness = 0;
|
||||||
|
let justBlinked = false;
|
||||||
|
|
||||||
function updateLife() {
|
function updateLife() {
|
||||||
|
|
||||||
if(keyDown[k.z]) {
|
if (playingUIOffsets.breath === 0) {
|
||||||
if(breath === 0) currentBreathMode = breathMode.inhale;
|
if (keyDown[k.x]) {
|
||||||
else if(breath === constants.lifeFuncs.breath.fullBreath) currentBreathMode = breathMode.exhale;
|
if (breath === 0) {
|
||||||
|
currentBreathMode = breathMode.inhale;
|
||||||
|
soundAssets.inhale.play();
|
||||||
|
}
|
||||||
|
else if (breath === constants.lifeFuncs.breath.fullBreath) {
|
||||||
|
currentBreathMode = breathMode.exhale;
|
||||||
|
soundAssets.exhale.play();
|
||||||
|
}
|
||||||
|
if(Date.now() - keyPromptTime > 3000) {
|
||||||
|
--keyPrompts.breath;
|
||||||
|
if(keyPrompts.breath > 0) {
|
||||||
|
keyPromptTime = Date.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
breathe();
|
||||||
}
|
}
|
||||||
|
|
||||||
breathe();
|
if (playingUIOffsets.heart === 0) {
|
||||||
|
if (keyPress[k.c]) {
|
||||||
|
heartbeat();
|
||||||
|
if(Date.now() - keyPromptTime > 1250) {
|
||||||
|
--keyPrompts.beat;
|
||||||
|
if(keyPrompts.beat > 0) {
|
||||||
|
keyPromptTime = Date.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(keyPress[k.x]) {
|
pressure -= 0.1;
|
||||||
heartbeat();
|
if (pressure <= 0) {
|
||||||
|
pressure = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pressure-=0.1;
|
if(playingUIOffsets.blink === 0) {
|
||||||
if(pressure<=0){
|
eyeDryness++;
|
||||||
pressure = 0;
|
|
||||||
|
if (keyPress[k.z]) {
|
||||||
|
blink();
|
||||||
|
if(Date.now() - keyPromptTime > 1250) {
|
||||||
|
--keyPrompts.blink;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,11 +72,12 @@ function breathe() {
|
|||||||
switch (currentBreathMode) {
|
switch (currentBreathMode) {
|
||||||
case breathMode.inhale:
|
case breathMode.inhale:
|
||||||
breath += 1;
|
breath += 1;
|
||||||
if(breath >= constants.lifeFuncs.breath.fullBreath) {
|
if (breath >= constants.lifeFuncs.breath.fullBreath) {
|
||||||
breath = constants.lifeFuncs.breath.fullBreath;
|
breath = constants.lifeFuncs.breath.fullBreath;
|
||||||
fullBreathTimer++;
|
fullBreathTimer++;
|
||||||
if(fullBreathTimer >= 600) {
|
if (fullBreathTimer >= 600) {
|
||||||
//cough and lose breath or something
|
//cough and lose breath or something
|
||||||
|
handleCough();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fullBreathTimer = 0;
|
fullBreathTimer = 0;
|
||||||
@ -50,11 +85,12 @@ function breathe() {
|
|||||||
break;
|
break;
|
||||||
case breathMode.exhale:
|
case breathMode.exhale:
|
||||||
breath -= 2;
|
breath -= 2;
|
||||||
if(breath <= 0) {
|
if (breath <= 0) {
|
||||||
breath = 0;
|
breath = 0;
|
||||||
noBreathTimer++;
|
noBreathTimer++;
|
||||||
if(noBreathTimer >= 300) {
|
if (noBreathTimer >= 300) {
|
||||||
//cough and lose breath or something
|
//cough and lose breath or something
|
||||||
|
handleCough();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
noBreathTimer = 0;
|
noBreathTimer = 0;
|
||||||
@ -63,9 +99,30 @@ function breathe() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Tracker for if we are currently coughing
|
||||||
|
let _nextCoughAllowedTime = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle player coughing without spamming the sound buffer
|
||||||
|
*/
|
||||||
|
function handleCough() {
|
||||||
|
|
||||||
|
// Only cough if we are past the cough time
|
||||||
|
if (getCurrentTimeSeconds() >= _nextCoughAllowedTime) {
|
||||||
|
|
||||||
|
console.log("[LifeFunctions] Coughing")
|
||||||
|
|
||||||
|
// Set the next allowed cough time
|
||||||
|
_nextCoughAllowedTime = getCurrentTimeSeconds() + constants.lifeFuncs.breath.cough_interval_secs;
|
||||||
|
|
||||||
|
// Play the cough audio
|
||||||
|
soundAssets.cough.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function heartbeat() {
|
function heartbeat() {
|
||||||
pressure+=10;
|
pressure += 10;
|
||||||
if(pressure>=100){
|
if (pressure >= 100) {
|
||||||
pressure = 100;
|
pressure = 100;
|
||||||
}
|
}
|
||||||
heartBeat = true;
|
heartBeat = true;
|
||||||
@ -73,3 +130,8 @@ function heartbeat() {
|
|||||||
// Play the heartbeat sound
|
// Play the heartbeat sound
|
||||||
soundAssets.heartbeat.play();
|
soundAssets.heartbeat.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function blink() {
|
||||||
|
eyeDryness = 0;
|
||||||
|
justBlinked = true;
|
||||||
|
}
|
@ -4,10 +4,10 @@ class Player {
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
this.w = constants.player.width;
|
this.w = constants.player.width;
|
||||||
this.h = constants.player.height;
|
this.h = constants.player.height;
|
||||||
this.hipLeft = { x: this.x - constants.player.hip.offset_x, y: this.y + constants.player.hip.offset_y };
|
this.hipLeft = { x: this.x + constants.player.hip.offset_x, y: this.y + constants.player.hip.offset_y };
|
||||||
this.hipRight = { x: this.x + constants.player.hip.offset_x, y: this.y + constants.player.hip.offset_y };
|
this.hipRight = { x: this.x - constants.player.hip.offset_x, y: this.y + constants.player.hip.offset_y };
|
||||||
this.leftLeg = new Leg(this.hipLeft.x, this.hipLeft.y, 50, -Math.PI / 4);
|
this.leftLeg = new Leg(this.hipLeft.x, this.hipLeft.y, constants.player.leg_length, Math.PI*2.5);
|
||||||
this.rightLeg = new Leg(this.hipRight.x, this.hipRight.y, 50, Math.PI / 2);
|
this.rightLeg = new Leg(this.hipRight.x, this.hipRight.y, constants.player.leg_length, Math.PI*2.5);
|
||||||
this.legSelected = "R";
|
this.legSelected = "R";
|
||||||
this.shouldMoveLeg = false;
|
this.shouldMoveLeg = false;
|
||||||
this.collided = false;
|
this.collided = false;
|
||||||
@ -55,17 +55,8 @@ Player.prototype.update = function() {
|
|||||||
var targetPos = mousePosition();
|
var targetPos = mousePosition();
|
||||||
var curLeg = this.getActiveLeg();
|
var curLeg = this.getActiveLeg();
|
||||||
this.hover.active = false;
|
this.hover.active = false;
|
||||||
//left
|
|
||||||
if (distanceToLineSegment(this.leftLeg.x, this.leftLeg.y, this.leftLeg.x2, this.leftLeg.y2, targetPos.x, targetPos.y) < constants.player.select_range) {
|
|
||||||
this.hover.active = true;
|
|
||||||
this.hover.leg = "L";
|
|
||||||
if(mousePress[0]) {
|
|
||||||
this.shouldMoveLeg = true;
|
|
||||||
this.legSelected = "L";
|
|
||||||
this.hover.active = false;
|
|
||||||
}
|
|
||||||
// right
|
// right
|
||||||
} else if (distanceToLineSegment(this.rightLeg.x, this.rightLeg.y, this.rightLeg.x2, this.rightLeg.y2, targetPos.x, targetPos.y) < constants.player.select_range) {
|
if (distanceToLineSegment(this.rightLeg.x, this.rightLeg.y, this.rightLeg.x2, this.rightLeg.y2, targetPos.x, targetPos.y) < constants.player.select_range) {
|
||||||
this.hover.active = true;
|
this.hover.active = true;
|
||||||
this.hover.leg = "R";
|
this.hover.leg = "R";
|
||||||
if(mousePress[0]) {
|
if(mousePress[0]) {
|
||||||
@ -73,10 +64,46 @@ Player.prototype.update = function() {
|
|||||||
this.legSelected = "R";
|
this.legSelected = "R";
|
||||||
this.hover.active = false;
|
this.hover.active = false;
|
||||||
}
|
}
|
||||||
|
//left
|
||||||
|
} else if (distanceToLineSegment(this.leftLeg.x, this.leftLeg.y, this.leftLeg.x2, this.leftLeg.y2, targetPos.x, targetPos.y) < constants.player.select_range) {
|
||||||
|
this.hover.active = true;
|
||||||
|
this.hover.leg = "L";
|
||||||
|
if(mousePress[0]) {
|
||||||
|
this.shouldMoveLeg = true;
|
||||||
|
this.legSelected = "L";
|
||||||
|
this.hover.active = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// god mode
|
||||||
|
// if(keyDown[k.w]) {
|
||||||
|
// this.y-=5;
|
||||||
|
// }
|
||||||
|
// if(keyDown[k.s]) {
|
||||||
|
// this.y+=5;
|
||||||
|
// }
|
||||||
|
// if(keyDown[k.a]) {
|
||||||
|
// this.x-=5;
|
||||||
|
// }
|
||||||
|
// if(keyDown[k.d]) {
|
||||||
|
// this.x+=5;
|
||||||
|
// }
|
||||||
|
|
||||||
centerCameraOn(this.x,this.y);
|
centerCameraOn(this.x,this.y);
|
||||||
|
// camera limits
|
||||||
|
if(camera.x > 898) {
|
||||||
|
camera.x = 898;
|
||||||
|
}
|
||||||
|
if(camera.x < -98) {
|
||||||
|
camera.x = -98;
|
||||||
|
}
|
||||||
|
if(camera.y < 245) {
|
||||||
|
camera.y = 245;
|
||||||
|
}
|
||||||
|
if(camera.y > 350) {
|
||||||
|
camera.y = 350;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -98,7 +125,6 @@ Player.prototype.moveLeg = function(){
|
|||||||
// console.log(curLeg.angle.toPrecision(5),pointTo(curLeg,target).toPrecision(5));
|
// console.log(curLeg.angle.toPrecision(5),pointTo(curLeg,target).toPrecision(5));
|
||||||
var angleDif = turn(curLeg.angle, pointTo(curLeg, target), constants.player.leg_speed) - curLeg.angle;
|
var angleDif = turn(curLeg.angle, pointTo(curLeg, target), constants.player.leg_speed) - curLeg.angle;
|
||||||
curLeg.angle += angleDif;
|
curLeg.angle += angleDif;
|
||||||
// var angle = pointTo(curLeg,target);
|
|
||||||
curLeg.x2 = curLeg.x + curLeg.len * Math.cos(curLeg.angle);
|
curLeg.x2 = curLeg.x + curLeg.len * Math.cos(curLeg.angle);
|
||||||
curLeg.y2 = curLeg.y + curLeg.len * Math.sin(curLeg.angle);
|
curLeg.y2 = curLeg.y + curLeg.len * Math.sin(curLeg.angle);
|
||||||
|
|
||||||
@ -109,15 +135,26 @@ Player.prototype.moveLeg = function(){
|
|||||||
curLeg.x2 = lastX;
|
curLeg.x2 = lastX;
|
||||||
curLeg.y2 = lastY;
|
curLeg.y2 = lastY;
|
||||||
curLeg.angle -= angleDif;
|
curLeg.angle -= angleDif;
|
||||||
|
|
||||||
|
// finer movement
|
||||||
|
angleDif = turn(curLeg.angle, pointTo(curLeg, target), constants.player.leg_speed/8) - curLeg.angle;
|
||||||
|
curLeg.angle += angleDif;
|
||||||
|
curLeg.x2 = curLeg.x + curLeg.len * Math.cos(curLeg.angle);
|
||||||
|
curLeg.y2 = curLeg.y + curLeg.len * Math.sin(curLeg.angle);
|
||||||
|
|
||||||
|
|
||||||
|
// Collision
|
||||||
|
if(collidingWithWorld({x:curLeg.x2,y:curLeg.y2,w:2,h:2})){
|
||||||
|
this.collided = true;
|
||||||
|
curLeg.x2 = lastX;
|
||||||
|
curLeg.y2 = lastY;
|
||||||
|
curLeg.angle -= angleDif;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(collidingWithWorld({x:this.x, y:this.y, w:this.w, h:this.h})){
|
|
||||||
this.x = this.lastBodyX;
|
|
||||||
this.y = this.lastBodyY;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (dist(curLeg, target) > curLeg.len) {
|
if (dist(curLeg, target) > curLeg.len) {
|
||||||
@ -169,7 +206,10 @@ Player.prototype.moveLeg = function(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(collidingWithWorld({x:this.x, y:this.y, w:this.w, h:this.h})){
|
||||||
|
this.x = this.lastBodyX;
|
||||||
|
this.y = this.lastBodyY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.lastBodyX = this.x;
|
this.lastBodyX = this.x;
|
||||||
@ -248,3 +288,7 @@ function distanceToLineSegment(lx1, ly1, lx2, ly2, px, py) {
|
|||||||
|
|
||||||
var player = new Player(constants.player.defaultX, constants.player.defaultY);
|
var player = new Player(constants.player.defaultX, constants.player.defaultY);
|
||||||
|
|
||||||
|
// why does this stop the legs from glitching on the first step???
|
||||||
|
player.rightLeg.angle = -pointTo({ x: player.rightLeg.x2, y: player.rightLeg.y2 }, player.hipRight);
|
||||||
|
player.leftLeg.angle = pointTo({ x: player.leftLeg.x2, y: player.leftLeg.y2 }, player.hipLeft);
|
||||||
|
player.moveLeg();
|
@ -1,8 +1,126 @@
|
|||||||
|
var tutorialStates = {
|
||||||
|
selectLeg:0,
|
||||||
|
placeOnGround:1,
|
||||||
|
goDownStairs:2,
|
||||||
|
getCereal: 3,
|
||||||
|
getMail: 4
|
||||||
|
};
|
||||||
|
|
||||||
|
var tutState = tutorialStates.selectLeg;
|
||||||
|
|
||||||
|
// how many times
|
||||||
|
var keyPrompts = {
|
||||||
|
beat: 2,
|
||||||
|
breath: 2,
|
||||||
|
blink: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
var keyPromptTime;
|
||||||
|
|
||||||
|
var frameCount = 0;
|
||||||
|
|
||||||
function handlePlaying() {
|
function handlePlaying() {
|
||||||
// enter build mode
|
// enter build mode
|
||||||
if(keyPress[k.BACKSLASH]) {
|
if(keyPress[k.BACKSLASH]) {
|
||||||
globalState = globalStates.building;
|
globalState = globalStates.building;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(tutState) {
|
||||||
|
case tutorialStates.selectLeg:
|
||||||
|
if(player.shouldMoveLeg) {
|
||||||
|
tutState = tutorialStates.placeOnGround;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tutorialStates.placeOnGround:
|
||||||
|
if(!player.shouldMoveLeg) {
|
||||||
|
tutState = tutorialStates.goDownStairs;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tutorialStates.goDownStairs:
|
||||||
|
if(player.y > -55) {
|
||||||
|
tutState = tutorialStates.getCereal;
|
||||||
|
keyPromptTime = Date.now();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tutorialStates.getCereal:
|
||||||
|
break;
|
||||||
|
case tutorialStates.getMail:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rise heart ui
|
||||||
|
if(player.y > -55) {
|
||||||
|
if(playingUIOffsets.heart > 0) {
|
||||||
|
--playingUIOffsets.heart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rise breath ui
|
||||||
|
if(player.y > 135) {
|
||||||
|
if(playingUIOffsets.breath > 0) {
|
||||||
|
--playingUIOffsets.breath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rise blink ui
|
||||||
|
if(player.x < -290) {
|
||||||
|
if(playingUIOffsets.blink > 0) {
|
||||||
|
--playingUIOffsets.blink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateLife();
|
updateLife();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawPlaying() {
|
||||||
|
frameCount++;
|
||||||
|
if(!justBlinked) {
|
||||||
|
|
||||||
|
imgIgnoreCutoff(sprites.epic,0,0);
|
||||||
|
// drawWorldBlocks();
|
||||||
|
player.draw();
|
||||||
|
|
||||||
|
// beat key
|
||||||
|
if(keyPrompts.beat > 0 && playingUIOffsets.heart === 0) {
|
||||||
|
if(Date.now() - keyPromptTime > 1250) {
|
||||||
|
img(sprites.tutKeyC,player.x + 70, player.y + (~~(frameCount/10)%2) * 2,0,2,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// breath key
|
||||||
|
if(keyPrompts.breath > 0 && playingUIOffsets.breath === 0) {
|
||||||
|
if(Date.now() - keyPromptTime > 3000) {
|
||||||
|
img(sprites.tutKeyX,player.x + 70, player.y + (~~(frameCount/10)%2) * 2,0,2,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// blink key
|
||||||
|
if(keyPrompts.blink > 0 && playingUIOffsets.blink === 0) {
|
||||||
|
if(Date.now() - keyPromptTime > 4000) {
|
||||||
|
img(sprites.tutKeyZ,player.x + 70, player.y + (~~(frameCount/10)%2) * 2,0,2,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch(tutState) {
|
||||||
|
case tutorialStates.selectLeg:
|
||||||
|
img(sprites["tutSelect"+~~(frameCount/10)%2],(player.leftLeg.x+player.leftLeg.x2)/2,(player.leftLeg.y+player.leftLeg.y2)/2,0,2,2);
|
||||||
|
break;
|
||||||
|
case tutorialStates.placeOnGround:
|
||||||
|
img(sprites["tutSelect"+~~(frameCount/10)%2],500,-40,2,2);
|
||||||
|
break;
|
||||||
|
case tutorialStates.goDownStairs:
|
||||||
|
img(sprites.tutArrow,360+~~(frameCount/10)%2,-30-~~(frameCount/10)%2,0,2,2);
|
||||||
|
break;
|
||||||
|
case tutorialStates.getCereal:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case tutorialStates.getMail:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rect(-camera.x - difx + cw/2,-camera.y - dify + ch/2,cw,ch,"black");
|
||||||
|
justBlinked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,13 +13,16 @@
|
|||||||
// This exists to give nicer names to files
|
// This exists to give nicer names to files
|
||||||
let soundAssetMap = {
|
let soundAssetMap = {
|
||||||
"debug-ding": "./assets/sounds/debug-ding.mp3",
|
"debug-ding": "./assets/sounds/debug-ding.mp3",
|
||||||
"footstep1":"./assets/sounds/footsteps/footstep1.mp3",
|
"footstep1": "./assets/sounds/footsteps/footstep1.mp3",
|
||||||
"footstep2":"./assets/sounds/footsteps/footstep2.mp3",
|
"footstep2": "./assets/sounds/footsteps/footstep2.mp3",
|
||||||
"footstep3":"./assets/sounds/footsteps/footstep3.mp3",
|
"footstep3": "./assets/sounds/footsteps/footstep3.mp3",
|
||||||
"footstep4":"./assets/sounds/footsteps/footstep4.mp3",
|
"footstep4": "./assets/sounds/footsteps/footstep4.mp3",
|
||||||
"footstep5":"./assets/sounds/footsteps/footstep5.mp3",
|
"footstep5": "./assets/sounds/footsteps/footstep5.mp3",
|
||||||
"footstep6":"./assets/sounds/footsteps/footstep6.mp3",
|
"footstep6": "./assets/sounds/footsteps/footstep6.mp3",
|
||||||
"heartbeat":"./assets/sounds/heartbeat.mp3"
|
"heartbeat": "./assets/sounds/heartbeat.mp3",
|
||||||
|
"inhale": "./assets/sounds/breathing/inhale.mp3",
|
||||||
|
"exhale": "./assets/sounds/breathing/exhale.mp3",
|
||||||
|
"cough":"./assets/sounds/cough.mp3"
|
||||||
}
|
}
|
||||||
|
|
||||||
// All available sounds
|
// All available sounds
|
||||||
@ -31,7 +34,10 @@ let soundAssets = {
|
|||||||
footstep4: new SoundSnippet("footstep4", audioAssetType.sfx),
|
footstep4: new SoundSnippet("footstep4", audioAssetType.sfx),
|
||||||
footstep5: new SoundSnippet("footstep5", audioAssetType.sfx),
|
footstep5: new SoundSnippet("footstep5", audioAssetType.sfx),
|
||||||
footstep6: new SoundSnippet("footstep6", audioAssetType.sfx),
|
footstep6: new SoundSnippet("footstep6", audioAssetType.sfx),
|
||||||
heartbeat: new SoundSnippet("heartbeat", audioAssetType.sfx)
|
heartbeat: new SoundSnippet("heartbeat", audioAssetType.sfx),
|
||||||
|
inhale: new SoundSnippet("inhale", audioAssetType.sfx),
|
||||||
|
exhale: new SoundSnippet("exhale", audioAssetType.sfx),
|
||||||
|
cough: new SoundSnippet("cough", audioAssetType.sfx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,10 @@ class SoundSnippet {
|
|||||||
this.audio = new Howl({src:[this.assetPath]});
|
this.audio = new Howl({src:[this.assetPath]});
|
||||||
|
|
||||||
// Create a callback for loading finished
|
// Create a callback for loading finished
|
||||||
this.audio.once("load", callback);
|
this.audio.once("load", () => {
|
||||||
|
console.log(`[SoundSnippet] Loaded asset: ${this.asset_name}`);
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
// Configure a thread for updating the clip volume
|
// Configure a thread for updating the clip volume
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
@ -24,7 +24,7 @@ function drawLevelTransitionUI() {
|
|||||||
|
|
||||||
// draws background sprites
|
// draws background sprites
|
||||||
drawWorldBlocks();
|
drawWorldBlocks();
|
||||||
imgIgnoreCutoff(sprites.level_2,0,0,0,4,4);
|
imgIgnoreCutoff(sprites.epic,0,0);
|
||||||
player.draw();
|
player.draw();
|
||||||
|
|
||||||
// sets alpha to calculated alpha for black
|
// sets alpha to calculated alpha for black
|
||||||
|
@ -3,6 +3,10 @@ function clamp(value, min, max) {
|
|||||||
return Math.min(max, Math.max(min, value));
|
return Math.min(max, Math.max(min, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCurrentTimeSeconds() {
|
||||||
|
return new Date().getTime() / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
// linear interpolation towards somewhere
|
// linear interpolation towards somewhere
|
||||||
function lerp(start, end, amt) { return (1 - amt) * start + amt * end; }
|
function lerp(start, end, amt) { return (1 - amt) * start + amt * end; }
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ class block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create blocks
|
// create blocks
|
||||||
var blockData = [942,-184,94,507,942,191,94,507,372,411,1054,67,-316,369,1214,152,-38,270,86,107,-166,243,125,127,238,320,45,127,273,284,45,127,309,248,45,127,341,215,45,127,377,179,45,127,412,143,45,127,450,107,45,127,603,105,285,196,777,27,285,196,-989,23,175,959,154,-441,2555,51];
|
var blockData = [705,-8,491,64,460,27,74,64,425,64,74,64,389,99,74,64,352,135,74,64,321,167,74,64,285,203,74,64,249,239,74,64,-18,299,3314,111,-43,205,59,90,-44,207,80,63,-168,199,128,108,-168,144,158,25,-978,-101,158,984,14,-398,1958,85,928,-192,58,345,664,-101,25,133,867,-102,25,133,765,-97,185,67];
|
||||||
for (let i = 0, l = blockData.length; i < l; i += 4) {
|
for (let i = 0, l = blockData.length; i < l; i += 4) {
|
||||||
collisionRects.push(new block(blockData[i], blockData[i + 1], blockData[i + 2], blockData[i + 3]));
|
collisionRects.push(new block(blockData[i], blockData[i + 1], blockData[i + 2], blockData[i + 3]));
|
||||||
}
|
}
|
||||||
|
BIN
docs/assets/sounds/breathing/exhale.mp3
Normal file
BIN
docs/assets/sounds/breathing/inhale.mp3
Normal file
BIN
docs/assets/sounds/cough.mp3
Normal file
@ -1,8 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- <link rel="icon" type="image/gif" href="icon.png"/> -->
|
<link rel="icon" type="image/gif" href="assets/images/tempIcon.png"/>
|
||||||
<title>html.aspx</title>
|
<title>error: title is undefined</title>
|
||||||
<style>
|
<style>
|
||||||
html {
|
html {
|
||||||
background-color: var(--theme-webpage-bg_color);
|
background-color: var(--theme-webpage-bg_color);
|
||||||
@ -13,7 +13,6 @@
|
|||||||
top:0;bottom:0;right:0;left:0;
|
top:0;bottom:0;right:0;left:0;
|
||||||
margin:auto;
|
margin:auto;
|
||||||
border: 5px solid var(--theme-webpage-canvas_border);
|
border: 5px solid var(--theme-webpage-canvas_border);
|
||||||
border-radius: 10px;
|
|
||||||
background-color: var(--theme-webpage-canvas_bg);
|
background-color: var(--theme-webpage-canvas_bg);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -21,6 +20,11 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas width="800" height="600" id="game"></canvas>
|
<canvas width="800" height="600" id="game"></canvas>
|
||||||
|
<pre style="position: absolute;left: 0;bottom: 0;"> TODO REMOVE ME
|
||||||
|
z: blink
|
||||||
|
x: breath
|
||||||
|
c: beat heart
|
||||||
|
</pre>
|
||||||
|
|
||||||
<!-- Graphics Library -->
|
<!-- Graphics Library -->
|
||||||
<script src="assets/js/game.js"></script>
|
<script src="assets/js/game.js"></script>
|
||||||
|