puzzle racer WIP

puzzle-racer-road-translate
Thibault Duplessis 2021-03-12 10:34:57 +01:00
parent d31d9fa864
commit 13151fb96d
12 changed files with 94 additions and 29 deletions

View File

@ -19,7 +19,7 @@ final class RacerJson(stormJson: StormJson, sign: StormSign, lightUserSync: Ligh
Json
.obj("name" -> p.name, "moves" -> p.moves)
.add("userId" -> p.userId)
.add("title" -> user.map(_.title))
.add("title", user.map(_.title))
}
// full race data

View File

@ -40,7 +40,7 @@ case class RacerRace(
def startsInMillis = startsAt.map(d => d.getMillis - nowMillis)
def hasStarted = startsInMillis.pp.exists(_ <= 0)
def hasStarted = startsInMillis.exists(_ <= 0)
lazy val moves = puzzles.foldLeft(0) { case (m, p) =>
m + p.line.size / 2

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -1,16 +1,31 @@
$car-width: 4rem;
$car-ratio: 0.328;
@font-face {
font-family: 'racer-car';
font-style: normal;
font-weight: 400;
src: url('../images/racer/racer.woff2') format('woff2');
}
.racer__race {
@extend %box-neat;
background: $c-bg-box;
// background-image: url(../images/grain.png);
background-image: url(../images/racer/road1.jpg);
background-size: 102px;
padding: 2vh 2vw;
font-size: 0.9em;
.racer--ongoing & {
animation: road-scroll 2000s linear infinite;
}
&__track {
display: flex;
border-bottom: 2px solid $c-border;
// border-bottom: 2px solid $c-border;
margin-right: 10ch;
margin-top: 0.5rem;
}
@ -19,26 +34,37 @@ $car-ratio: 0.328;
@extend %flex-center-nowrap;
flex: 0 0 auto;
transition: padding 1s;
transition: padding 2s;
margin-left: -0.5rem;
&__name {
margin-left: 1ch;
color: $c-font-dim;
white-space: nowrap;
}
&__car {
flex: 0 0 $car-width;
font-family: 'racer-car';
height: #{$car-width * $car-ratio};
background-image: img-url('racer/race-car2.svg');
background-size: contain;
background-repeat: no-repeat;
background-position: bottom right;
font-size: $car-width;
line-height: 0;
text-shadow: -1px 1px 2px #000;
animation: lightSpeedInLeft 0.8s ease-out;
}
}
}
$c-bg-position-y: 3px;
@keyframes road-scroll {
from {
background-position: 0 $c-bg-position-y;
}
to {
background-position: -10000% $c-bg-position-y;
}
}
@keyframes lightSpeedInLeft {
from {
transform: translateX(-100%) skewX(30deg);
@ -59,12 +85,29 @@ $car-ratio: 0.328;
}
}
@for $i from 0 through 9 {
.car-#{$i} {
@if $theme-dark {
filter: hue-rotate(#{$i * 36 * 7 % 360}deg) brightness(2);
} @else {
filter: hue-rotate(#{$i * 36 * 7 % 360}deg);
}
$car-colors: (
0: hsl(274, 100%, 59%),
1: hsl(240, 100%, 67%),
2: #008000,
3: #b22222,
4: hsl(16, 80%, 62%),
5: #9acd32,
6: #ff4500,
7: #2e8b57,
8: #daa520,
9: hsl(32, 75%, 47%),
);
@each $index, $color in $car-colors {
.car-#{$index} {
color: #{$color};
}
}
// @for $i from 0 through 9 {
// .car-#{$i} {
// @if $theme-dark {
// filter: hue-rotate(#{$i * 36 * 7 % 360}deg) brightness(2);
// } @else {
// filter: hue-rotate(#{$i * 36 * 7 % 360}deg);
// }
// }
// }

View File

@ -3,7 +3,8 @@ import { Config } from 'puz/interfaces';
const config: Config = {
// all times in seconds
clock: {
initial: 1 * 60,
initial: 99 * 60,
// initial: 1 * 60,
// initial: 10,
malus: 5,
},

View File

@ -27,12 +27,6 @@ export default class StormCtrl {
constructor(opts: RacerOpts, redraw: (data: RacerData) => void) {
this.data = opts.data;
// this.data.players = [];
// for (let i = 0; i < 10; i++)
// this.data.players.push({
// name: `Player${i}`,
// moves: Math.round((this.data.race.moves / 9) * i),
// });
this.race = this.data.race;
this.pref = opts.pref;
this.redraw = () => redraw(this.data);
@ -57,6 +51,7 @@ export default class StormCtrl {
lichess.socket = new lichess.StrongSocket(`/racer/${this.race.id}`, false);
lichess.pubsub.on('socket.in.racerState', this.serverUpdate);
this.startCountdown();
this.simulate();
console.log(this.race);
}
@ -180,4 +175,17 @@ export default class StormCtrl {
const g = this.ground();
return g && f(g);
};
private simulate = () => {
this.data.players = [];
for (let i = 0; i < 10; i++)
this.data.players.push({
name: `Player${i}`,
moves: 0,
});
setInterval(() => {
if (this.isRacing()) this.data.players[Math.floor(Math.random() * 10)].moves++;
this.redraw();
}, 150);
};
}

View File

@ -15,7 +15,10 @@ export default function (ctrl: RacerCtrl): VNode {
return h(
'div.racer.racer-app.racer--play',
{
class: playModifiers(ctrl.run),
class: {
...playModifiers(ctrl.run),
'racer--ongoing': ctrl.isRacing(),
},
},
renderPlay(ctrl)
);

View File

@ -2,19 +2,29 @@ import { h } from 'snabbdom';
import RacerCtrl from '../ctrl';
import { Player, Race } from '../interfaces';
export const renderRace = (ctrl: RacerCtrl) => h('div.racer__race', ctrl.players().map(renderTrack(ctrl.race)));
// to [0,1]
type RelativeMoves = (moves: number) => number;
const renderTrack = (race: Race) => (player: Player, index: number) =>
export const renderRace = (ctrl: RacerCtrl) => {
const players = ctrl.players();
const minMoves = players.reduce((m, p) => (p.moves < m ? p.moves : m), 999) / 2;
const maxMoves = players.reduce((m, p) => (p.moves > m ? p.moves : m), 30);
const delta = maxMoves - minMoves;
const relative: RelativeMoves = moves => (moves - minMoves) / delta;
return h('div.racer__race', players.map(renderTrack(relative)));
};
const renderTrack = (relative: RelativeMoves) => (player: Player, index: number) =>
h(
'div.racer__race__track',
h(
'div.racer__race__player',
{
attrs: {
style: `padding-left:${(95 * player.moves) / race.moves}%`,
style: `padding-left:${relative(player.moves) * 95}%`,
},
},
[h(`div.racer__race__player__car.car-${index}`), h('span.racer__race__player__name', playerLink(player))]
[h(`div.racer__race__player__car.car-${index}`, [0]), h('span.racer__race__player__name', playerLink(player))]
)
);

View File

@ -1,4 +1,3 @@
@import 'font';
@import 'play-again';
@import 'high';

View File

@ -1,4 +1,5 @@
@import '../../../common/css/plugin';
@import '../../../common/css/component/slist';
@import '../../../puz/css/font';
@import '../dashboard';

View File

@ -765,7 +765,7 @@ chessground@^4.4:
merge "1.2.0"
mithril "github:ornicar/mithril.js#v1.0.1"
chessground@^7.11.1:
chessground@^7.11.0, chessground@^7.11.1:
version "7.11.1"
resolved "https://registry.yarnpkg.com/chessground/-/chessground-7.11.1.tgz#7e126d660d63025f9bf27371a8778e2baeeb1b57"
integrity sha512-IwGSEZBsQlquHyudv1Y5EwlfTXrz0CEWisJuEim2W3eX07IBpYUsr0ChTD35du+Cr0x1+e6GbCLY3hVejKG7ow==