From 44a42ba4c86acebca118a1b69be55644e5611e83 Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Sat, 18 Apr 2020 04:36:23 -0400 Subject: [PATCH 1/3] Heartrate monitor --- .gitignore | 5 ++- docs/assets/js/UI/ui.js | 54 ++++++++++++++++++++------ docs/assets/js/constants.js | 11 +++--- docs/assets/js/game.js | 5 ++- docs/assets/js/player/lifeFunctions.js | 5 +-- docs/assets/js/playing/playing.js | 2 + docs/index.html | 8 ++-- 7 files changed, 63 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 2f41c87..10c4a25 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ docs/_site/* docs/.sass-cache/* docs/.jekyll-cache/* -docs/node_modules \ No newline at end of file +docs/node_modules + +# idea +.idea \ No newline at end of file diff --git a/docs/assets/js/UI/ui.js b/docs/assets/js/UI/ui.js index a2dfd21..5a8175a 100644 --- a/docs/assets/js/UI/ui.js +++ b/docs/assets/js/UI/ui.js @@ -1,23 +1,33 @@ +//Colors + // UI for title screen -function drawTitleScreenUI() {}; +function drawTitleScreenUI() { +} // UI for level transition -function drawLevelTransitionUI() {}; +function drawLevelTransitionUI() { +} // UI for playing -function drawPlayingUI() {}; +function drawPlayingUI() { + heartBeatUI(cw/4*3-8,ch/8*7-8,cw/4,ch/8); +} //UI for pause screen -function drawPausedUI() {}; +function drawPausedUI() { +} //UI for game end -function drawEndUI() {}; +function drawEndUI() { +} // Construct a rectangular UI function rectUI() {}; //Heart rate monitor history -var heartBeatHistory = [].fill(0,0, constants.ui.heartRate.history_length); +var heartBeatHistory = [] + heartBeatHistory.length = constants.ui.heartRate.history_length; + heartBeatHistory.fill(0); //Shift accumulation var shiftAccum = 0; @@ -31,6 +41,7 @@ function heartBeatUI(x, y, width, height){ shiftAccum += constants.ui.heartRate.scroll_speed; if(shiftAccum>=1){ shiftAccum%=1; + beatTimeElapsed += 0.04; heartBeatHistory.shift(); pushNextBeatValue(); } @@ -39,19 +50,38 @@ function heartBeatUI(x, y, width, height){ beatTimeElapsed = 0; } + rect(x+width/2,y+height/2,width,height,"black"); for (let index = 0; index < heartBeatHistory.length; index++) { const qrsValueAtPosition = heartBeatHistory[index]; - line(x+index, y+(2*height/3), x+index, y+(2*height/3)+qrsValueAtPosition); + const qrsValueAtNextPosition = heartBeatHistory[index+1]; + line(x+(index*width/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtPosition*width/heartBeatHistory.length), x+((index+1)*width/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtNextPosition*width/heartBeatHistory.length), "red"); } } function pushNextBeatValue(){ - var nextBeatValue; + var nextBeatValue = 0; - beatTimeElapsed %= constants.ui.heartRate.complex_width; - if(beatTimeElapsed<=constants.ui.heartRate.pr_width){ - nextBeatValue = -0.25((x - 1.5)**2) + 0.5625; - } else if (beatTimeElapsed >= constants.ui.heartRate.pr_width + 1 && beatTimeElapsed <= constants.ui.heartRate.pr_width + 1 + constants.ui.heartRate.qrs_width/4) { + const squareSize = constants.ui.heartRate.square_size; + const complexTime = constants.ui.heartRate.complex_width*squareSize; + const prTime = constants.ui.heartRate.pr_width*squareSize; + const qrsTime = constants.ui.heartRate.qrs_width*squareSize; + const qtTime = constants.ui.heartRate.qt_width*squareSize; + + + if(beatTimeElapsed<=complexTime) { + if (beatTimeElapsed <= prTime) { + nextBeatValue = 0.5*(Math.pow((beatTimeElapsed/squareSize - (prTime/2/squareSize)), 2)) - 2; + } else if (beatTimeElapsed > prTime + squareSize && beatTimeElapsed <= prTime + squareSize + (qrsTime / 4)) { + nextBeatValue = -4 + beatTimeElapsed/squareSize; + } else if (beatTimeElapsed > prTime + squareSize + qrsTime / 4 && beatTimeElapsed <= prTime + squareSize + qrsTime / 2) { + nextBeatValue = -14 * (beatTimeElapsed/squareSize - 4.5) - 0.5; + } else if (beatTimeElapsed > prTime + squareSize + qrsTime / 2 && beatTimeElapsed <= prTime + squareSize + (3*qrsTime / 4)) { + nextBeatValue = 7 * (beatTimeElapsed/squareSize - 5) - 6.5; + } else if (beatTimeElapsed > prTime + squareSize + (3*qrsTime / 4) && beatTimeElapsed <= prTime + squareSize + qrsTime) { + nextBeatValue = 2 * (beatTimeElapsed/squareSize - 6); + } else if (beatTimeElapsed > prTime + squareSize*2 + qrsTime && beatTimeElapsed <= prTime + squareSize*2 + qrsTime + qtTime) { + nextBeatValue = 0.5 * Math.pow((beatTimeElapsed/squareSize - (prTime + squareSize*2 + qrsTime + qtTime/2)/squareSize),2) - 3; + } } heartBeatHistory.push(nextBeatValue); diff --git a/docs/assets/js/constants.js b/docs/assets/js/constants.js index 4570ac8..d5d7b7e 100644 --- a/docs/assets/js/constants.js +++ b/docs/assets/js/constants.js @@ -26,11 +26,12 @@ var constants = { history_length: 100, //300 squares/min - scroll_speed: 0.13333, - pr_width: 0.16, - qrs_width: 0.1, - qt_width: 0.39, - complex_width: 0.65 + scroll_speed: 0.8, + square_size: 0.08, + pr_width: 4, + qrs_width: 2, + qt_width: 5, + complex_width: 18 } }, legs:{ diff --git a/docs/assets/js/game.js b/docs/assets/js/game.js index dbbfc67..02bb89b 100644 --- a/docs/assets/js/game.js +++ b/docs/assets/js/game.js @@ -350,9 +350,10 @@ function circle(x,y,r,color) { function line(x1, y1, x2, y2, color) { curCtx.beginPath(); - curCtx.style = color; + curCtx.strokeStyle = color; curCtx.moveTo(x1 + camera.x + difx, y1 + camera.y + dify); - curCtx.lineTo(x2 + camera.x + difx, y2 + camera.y + dify); + curCtx.lineTo(x2 + camera.x + difx , y2 + camera.y + dify); + curCtx.stroke(); } function shape(x,y,relitivePoints,color) { diff --git a/docs/assets/js/player/lifeFunctions.js b/docs/assets/js/player/lifeFunctions.js index deb1cd0..c0edc9b 100644 --- a/docs/assets/js/player/lifeFunctions.js +++ b/docs/assets/js/player/lifeFunctions.js @@ -8,13 +8,13 @@ var timeSinceLastBeat = 0; function updateLife() { - if(keyDown[k.Z]) { + if(keyDown[k.z]) { breathe(); } else { breath--; } - if(keyPress[k.X]) { + if(keyPress[k.x]) { heartbeat(); } else { timeSinceLastBeat++; @@ -38,7 +38,6 @@ function breathe() { }; function heartbeat() { - timeSinceLastBeat = 0; }; \ No newline at end of file diff --git a/docs/assets/js/playing/playing.js b/docs/assets/js/playing/playing.js index 995b15f..006c491 100644 --- a/docs/assets/js/playing/playing.js +++ b/docs/assets/js/playing/playing.js @@ -3,4 +3,6 @@ function handlePlaying() { if(keyPress[k.BACKSLASH]) { globalState = globalStates.building; } + + updateLife(); } \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 051e7d8..ce9f65c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -33,13 +33,13 @@ + --> + - + + From 138f27a6916eec26934169851470e4a3437b34e2 Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Sat, 18 Apr 2020 05:15:44 -0400 Subject: [PATCH 2/3] Heartrate monitor optimizations & comments --- docs/assets/js/UI/ui.js | 38 ++++++++++++++++++-------- docs/assets/js/player/lifeFunctions.js | 12 ++++---- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/docs/assets/js/UI/ui.js b/docs/assets/js/UI/ui.js index 5a8175a..de9eb84 100644 --- a/docs/assets/js/UI/ui.js +++ b/docs/assets/js/UI/ui.js @@ -25,32 +25,42 @@ function drawEndUI() { function rectUI() {}; //Heart rate monitor history -var heartBeatHistory = [] +let heartBeatHistory = [] heartBeatHistory.length = constants.ui.heartRate.history_length; heartBeatHistory.fill(0); //Shift accumulation -var shiftAccum = 0; +let shiftAccum = 0; //Beat progression -var beatTimeElapsed = 0; +let beatTimeElapsed = 0; // Draw heartbeat UI function heartBeatUI(x, y, width, height){ + //Shift monitor over once a full scrolling unit is accumulated shiftAccum += constants.ui.heartRate.scroll_speed; if(shiftAccum>=1){ shiftAccum%=1; beatTimeElapsed += 0.04; + + //Remove oldest value heartBeatHistory.shift(); + + //Append new value pushNextBeatValue(); } - if(timeSinceLastBeat===0){ + //If heart is beaten, reset beat timer. + if(heartBeat){ beatTimeElapsed = 0; + heartBeat = false; } + //Backdrop rect(x+width/2,y+height/2,width,height,"black"); + + //Graph for (let index = 0; index < heartBeatHistory.length; index++) { const qrsValueAtPosition = heartBeatHistory[index]; const qrsValueAtNextPosition = heartBeatHistory[index+1]; @@ -58,28 +68,34 @@ function heartBeatUI(x, y, width, height){ } } +//Determine next value to be added to the graph function pushNextBeatValue(){ - var nextBeatValue = 0; + let nextBeatValue = 0; + //Timespan of one "square" on the EKG const squareSize = constants.ui.heartRate.square_size; + //Length of full complex const complexTime = constants.ui.heartRate.complex_width*squareSize; + //Length of PR segment of complex const prTime = constants.ui.heartRate.pr_width*squareSize; + //Length of QRS component of complex const qrsTime = constants.ui.heartRate.qrs_width*squareSize; + //Length of QT component of complex const qtTime = constants.ui.heartRate.qt_width*squareSize; - if(beatTimeElapsed<=complexTime) { + //PR Segment if (beatTimeElapsed <= prTime) { nextBeatValue = 0.5*(Math.pow((beatTimeElapsed/squareSize - (prTime/2/squareSize)), 2)) - 2; - } else if (beatTimeElapsed > prTime + squareSize && beatTimeElapsed <= prTime + squareSize + (qrsTime / 4)) { + } else if (beatTimeElapsed > prTime + squareSize && beatTimeElapsed <= prTime + squareSize + (qrsTime / 4)) { //QRS Segment pt. 1 nextBeatValue = -4 + beatTimeElapsed/squareSize; - } else if (beatTimeElapsed > prTime + squareSize + qrsTime / 4 && beatTimeElapsed <= prTime + squareSize + qrsTime / 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; - } else if (beatTimeElapsed > prTime + squareSize + qrsTime / 2 && beatTimeElapsed <= prTime + squareSize + (3*qrsTime / 4)) { + } else if (beatTimeElapsed > prTime + squareSize + qrsTime / 2 && beatTimeElapsed <= prTime + squareSize + (3*qrsTime / 4)) { //QRS Segment pt. 3 nextBeatValue = 7 * (beatTimeElapsed/squareSize - 5) - 6.5; - } else if (beatTimeElapsed > prTime + squareSize + (3*qrsTime / 4) && beatTimeElapsed <= prTime + squareSize + qrsTime) { + } else if (beatTimeElapsed > prTime + squareSize + (3*qrsTime / 4) && beatTimeElapsed <= prTime + squareSize + qrsTime) { //QRS Segment pt. 4 nextBeatValue = 2 * (beatTimeElapsed/squareSize - 6); - } else if (beatTimeElapsed > prTime + squareSize*2 + qrsTime && beatTimeElapsed <= prTime + squareSize*2 + qrsTime + qtTime) { + } 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; } } diff --git a/docs/assets/js/player/lifeFunctions.js b/docs/assets/js/player/lifeFunctions.js index c0edc9b..9fdf42f 100644 --- a/docs/assets/js/player/lifeFunctions.js +++ b/docs/assets/js/player/lifeFunctions.js @@ -1,9 +1,9 @@ -var breath = 180; -var fullBreathTimer = 0; -var heartRate = 60; +let breath = 180; +let fullBreathTimer = 0; +let heartRate = 60; -var timeSinceLastBeat = 0; +let heartBeat = false; function updateLife() { @@ -16,8 +16,6 @@ function updateLife() { if(keyPress[k.x]) { heartbeat(); - } else { - timeSinceLastBeat++; } }; @@ -38,6 +36,6 @@ function breathe() { }; function heartbeat() { - timeSinceLastBeat = 0; + heartBeat = true; }; \ No newline at end of file From f3332786d363260a2ffa4bd62e628cf1c3bc1220 Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Sat, 18 Apr 2020 06:02:20 -0400 Subject: [PATCH 3/3] Simple Breath Gauge --- docs/assets/js/UI/ui.js | 32 ++++++++++++++++++++------ docs/assets/js/constants.js | 5 ++++ docs/assets/js/game.js | 8 ++++++- docs/assets/js/player/lifeFunctions.js | 6 ++--- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/docs/assets/js/UI/ui.js b/docs/assets/js/UI/ui.js index de9eb84..5350b2e 100644 --- a/docs/assets/js/UI/ui.js +++ b/docs/assets/js/UI/ui.js @@ -1,5 +1,3 @@ -//Colors - // UI for title screen function drawTitleScreenUI() { } @@ -10,7 +8,12 @@ function drawLevelTransitionUI() { // UI for playing function drawPlayingUI() { + + //Heart Rate Monitor heartBeatUI(cw/4*3-8,ch/8*7-8,cw/4,ch/8); + + //Respiration Monitor + respiratoryUI(cw/8*5,ch/8*7-8, cw/16, ch/8); } //UI for pause screen @@ -21,11 +24,26 @@ function drawPausedUI() { function drawEndUI() { } -// Construct a rectangular UI -function rectUI() {}; + +/*** + * + * RESPIRATORY UI + * + */ + +function respiratoryUI(x, y, width, height){ + cartesianRect(x,y,width,height, "black"); + cartesianRect(x,y+(height-breath/constants.lifeFuncs.breath.fullBreath*height), width, breath/constants.lifeFuncs.breath.fullBreath*height, "teal"); +} + +/*** + * + * HEART RATE MONITOR UI + * + */ //Heart rate monitor history -let heartBeatHistory = [] +let heartBeatHistory = []; heartBeatHistory.length = constants.ui.heartRate.history_length; heartBeatHistory.fill(0); @@ -33,7 +51,7 @@ let heartBeatHistory = [] let shiftAccum = 0; //Beat progression -let beatTimeElapsed = 0; +let beatTimeElapsed = Infinity; // Draw heartbeat UI function heartBeatUI(x, y, width, height){ @@ -64,7 +82,7 @@ function heartBeatUI(x, y, width, height){ for (let index = 0; index < heartBeatHistory.length; index++) { const qrsValueAtPosition = heartBeatHistory[index]; const qrsValueAtNextPosition = heartBeatHistory[index+1]; - line(x+(index*width/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtPosition*width/heartBeatHistory.length), x+((index+1)*width/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtNextPosition*width/heartBeatHistory.length), "red"); + line(x+(index*width/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtPosition*width/heartBeatHistory.length), x+((index+1)*width/heartBeatHistory.length), y+(2*height/3)+(qrsValueAtNextPosition*width/heartBeatHistory.length),Math.min(3,Math.max(3/beatTimeElapsed,1)), "red"); } } diff --git a/docs/assets/js/constants.js b/docs/assets/js/constants.js index d5d7b7e..c4ef125 100644 --- a/docs/assets/js/constants.js +++ b/docs/assets/js/constants.js @@ -34,6 +34,11 @@ var constants = { complex_width: 18 } }, + lifeFuncs:{ + breath:{ + fullBreath: 200 + } + }, legs:{ size:{ maximumMovement: 30 diff --git a/docs/assets/js/game.js b/docs/assets/js/game.js index 02bb89b..262094c 100644 --- a/docs/assets/js/game.js +++ b/docs/assets/js/game.js @@ -341,6 +341,11 @@ function rect(x,y,w,h,color) { curCtx.fillRect(x-(w/2)+camera.x+difx,y-(h/2)+camera.y+dify,w,h); } +function cartesianRect(x,y,w,h,color) { + curCtx.fillStyle = color; + curCtx.fillRect(x+camera.x+difx,y+camera.y+dify,w,h); +} + function circle(x,y,r,color) { curCtx.beginPath(); curCtx.arc(x+camera.x+difx, y+camera.y+dify, r, 0, 2 * Math.PI, false); @@ -348,9 +353,10 @@ function circle(x,y,r,color) { curCtx.fill(); } -function line(x1, y1, x2, y2, color) { +function line(x1, y1, x2, y2, weight, color) { curCtx.beginPath(); curCtx.strokeStyle = color; + curCtx.lineWidth = weight; curCtx.moveTo(x1 + camera.x + difx, y1 + camera.y + dify); curCtx.lineTo(x2 + camera.x + difx , y2 + camera.y + dify); curCtx.stroke(); diff --git a/docs/assets/js/player/lifeFunctions.js b/docs/assets/js/player/lifeFunctions.js index 9fdf42f..0cd075e 100644 --- a/docs/assets/js/player/lifeFunctions.js +++ b/docs/assets/js/player/lifeFunctions.js @@ -17,14 +17,13 @@ function updateLife() { if(keyPress[k.x]) { heartbeat(); } - }; function breathe() { breath += 5; - if(breath >= 200) { - breath = 200; + if(breath >= constants.lifeFuncs.breath.fullBreath) { + breath = constants.lifeFuncs.breath.fullBreath; fullBreathTimer++; if(fullBreathTimer >= 60) { //cough and lose breath or something @@ -37,5 +36,4 @@ function breathe() { function heartbeat() { heartBeat = true; - }; \ No newline at end of file