Skip to content

Commit

Permalink
Adds max streak functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
lukebatchelor committed Sep 3, 2018
1 parent 986fa93 commit 472f8f7
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 32 deletions.
46 changes: 21 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,21 @@ the whole form the game is inside of and returning us to the first menu.
</div>
```

Finally, the `maxStreak` feature is done very hackily. There's no way we can use counters to solve this problem
without the ability to "reset" them back to a specific value.

The trick to this ended up being generating `60` CSS rules that cover every possible `maxStreak` you can get!

```less
.maxStreakBoard::after {content: "Max streak: 0x";}
.hitbox:checked ~ .maxStreakBoard::after {content: "Max streak: 1x";}
.hitbox:checked + .hitbox:checked ~ .maxStreakBoard::after {content: "Max streak: 2x";}
// ...
```

The really cool part about this is it doesn't interfere with the current counters and because each rule gets more and more specific, they automatically trump eachother correctly!


## Future ideas


Expand All @@ -143,35 +158,16 @@ The game currently generates `400` notes in the level, most of which wont ever b

This would give us a smaller page load, or give us more data we can use for the optimization above!

> This is partially completed now, but could be cleaned up
**Perspective shift**

I played with the idea of doing a Guitar Hero style perspective shift so that the notes appear to be coming out of a vanishing point as they come towards you. I ran into some issues with it, but this should 100% be achievable.

**Highscore/MaxStreak**

I'd love to find a way to be able to store some sort of "Highscore" (in one session) or "Max Streak" (in one game).

I have tried a few ways of achieving maxStreak using counters, and I don't think it's going to be viable.
**High Score**

A better solution would be if we could do something like:

```less
// Simplfied obviously
.hitbox:not(:checked) + .hitbox:checked ~ .streakBoard::after {
display: block;
content: "Max streak: 1x";
}
.hitbox:not(:checked) + .hitbox:checked + .hitbox:checked ~ .streakBoard::after {
display: block;
content: "Max streak: 2x";
}
.hitbox:not(:checked) + .hitbox:checked + .hitbox:checked + .hitbox:checked ~ .streakBoard::after {
display: block;
content: "Max streak: 3x";
}
// ... ...
```
We can apply the same process and `maxStreak` to `highScore`.

The rules get more and more specific as you go, so they would trump each time.
With this change, we'd probably also want to clean up how those elements are shown and hidden.

The hard part here is getting a sibling element we can target that is going to not be moved by the transforming... A hacky solution might be to reverse the animation happening to the level, on the `streakBoard`.
It's very hacky right now.
10 changes: 7 additions & 3 deletions build-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ function randBetween(min, max) {
function createLevel(numElements = 40) {
let curOffset = 0;
let curDomStr = '\n';
for (let i=0; i < numElements; i++) {
while (curOffset < 9000) {
const colNum = randBetween(1,4);
curOffset += randBetween(1,5) * 50;
curDomStr += `<input type="checkbox" class="hitbox col${colNum}" style="top: -${curOffset}px"></input>\n`;
}
return curDomStr;
}

console.log('Generating random level...');

const level = createLevel(400);

const htmlTemplate = `
Expand All @@ -29,7 +31,8 @@ const htmlTemplate = `
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CSS Rhythm Game</title>
<link href="../styles.css" rel="stylesheet"></head>
<link href="./styles.css" rel="stylesheet"></head>
<link href="./max-streak-rules.css" rel="stylesheet"></head>
</head>
<body>
<div class="app">
Expand All @@ -53,6 +56,7 @@ const htmlTemplate = `
<div class="clickGuard"></div>
<div class="level">
${level}
<div class="maxStreakBoard"></div>
</div>
<div class="hitboxIndicator col1"></div>
<div class="hitboxIndicator col2"></div>
Expand All @@ -76,7 +80,7 @@ const htmlTemplate = `
</html>
`;
console.log('Done!');
console.log('Writing to', outputPath);
console.log('Writing to', outputPath, `(${htmlTemplate.length/1000}Kb)`);

fs.writeFileSync(outputPath, htmlTemplate);
console.log('Done!');
19 changes: 19 additions & 0 deletions build-max-streak-rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const fs = require('fs');
const path = require('path');


const outputPath = path.join(__dirname, 'dist', 'max-streak-rules.css');
const MAX_STREAK = 60;
let maxStreakRules = '.maxStreakBoard::after {content: "Max streak: 0x";}\n';

console.log(`Generating ${MAX_STREAK} CSS rules for max streak`);

// Hardcoded for now, but 60 is the max score you can get currently
for (let i =0; i < MAX_STREAK; i++) {
maxStreakRules += `.hitbox:checked ${'+ .hitbox:checked '.repeat(i)}~ .maxStreakBoard::after {content: "Max streak: ${i + 1}x";}\n`
}

fs.writeFileSync(outputPath, maxStreakRules);

console.log('Done');
console.log(`${maxStreakRules.length/1000} Kb`);
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"main": "index.js",
"scripts": {
"dev": "yarn nodemon -e js,css --watch build-html.js --watch styles.less --exec \"yarn build && yarn serve\"",
"build": "mkdir -p dist && node build-html.js && lessc styles.less dist/styles.css",
"build": "mkdir -p dist && node build-html.js && lessc styles.less dist/styles.css && node build-max-streak-rules.js",
"serve": "http-server -c-1 dist/"
},
"keywords": [],
Expand Down
18 changes: 15 additions & 3 deletions styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
@game-height: 400px;
@game-length-easy: 45s;
@game-length-med: 30s;
@game-length-hard: 25s;
@game-length-hard: 20s;

body, html {
height: 100%;
Expand All @@ -12,6 +12,12 @@ body, html {
box-sizing: border-box;
}

.maxStreakBoard {
position: absolute;
top: 240px;
right: 95px;
}

.app {
display: flex;
justify-content: center;
Expand Down Expand Up @@ -81,6 +87,10 @@ input[type="radio"] {
.level {
animation: playing @game-length linear;
}

.maxStreakBoard {
animation: hide 0.1s linear @game-length reverse both;
}
}
}

Expand Down Expand Up @@ -206,14 +216,16 @@ input[type="radio"] {
100% { transform: translateY(9000px); }
}


@keyframes hitAnim {
0% { transform: translateY(0) scale(1); opacity: 1; }
100% { transform: translateY(-100px) scale(2); opacity: 0.3; }
}

@keyframes hide {
0% { opacity: 1; }
100% { opacity: 0; }
0% { color: rgba(0, 0, 0, 1) }
// Very hacky, but this lets us click through the clickGuard when gameOver
100% { color: rgba(0, 0, 0, 0); pointer-events: none; }
}

@keyframes show {
Expand Down

0 comments on commit 472f8f7

Please sign in to comment.