...

points

:root { /* Variables encargadas de sumar y mostrar los puntos de las dianas normales y especiales. */ --bullseye-points: 1; --bullseye-points-str: '1'; --bullseye-special-points: 3; --bullseye-special-points-str: '3'; /* Inicializamos el contador de puntos a 0. */ counter-reset: points; } /* Incrementamos el valor del contador en tantos puntos como hayamos definido * en nuestra variable cuando el checkbox está marcado. */ .bullseye-input:checked { --points: var(--bullseye-points); counter-increment: points var(--points); } /* Cuando la diana es especial, sobreescribimos el número puntos a sumar en el contador. */ .bullseye-input.special:checked { --points: var(--bullseye-special-points); } /* Mostramos el número de puntos en el :after de la diana. */ .bullseye:after { --points-str: var(--bullseye-points-str); content: '+' var(--points-str); } /* Cuando la diana es especial, sobreescribimos los puntos a mostrar en el :after de la diana. */ .bullseye.special:after { --points-str: var(--bullseye-special-points-str); } /* Mostramos el número de puntos en el marcador. */ #score:before { content: counter(points); } @import url('https://fonts.googleapis.com/css?family=Press+Start+2P') :root { ... -bg-color: blue; --text-color: white; --accent-color: lime; ... } body { /* Evitamos que las dianas provoquen la aparición de la barra de scroll cuando están fuera del viewport. */ overflow: hidden; /* Nuestra querida fuente retro. */ font-family: 'Press Start 2P', sans-serif; color: var(--text-color); background-color: var(--bg-color); /* Evitamos que el usuario seleccione partes de la web sin querer mientras hace clic con el ratón. */ user-select: none; } #score { /* Posicionamos el marcador en la parte baja del viewport. */ position: absolute; bottom: 2rem; left: 0; right: 0; color: var(--accent-color); /* Añadimos una sombra retro. */ text-shadow: 2px 2px 0px red; /* Permitimos que el jugador pueda hacer clic sobre una diana que está pasando por debajo del contador. */ pointer-events: none; } :root { ... --bullseye-size: 7rem; --bullseye-shadow-size: 1rem; --bullseye-total-size: calc(var(--bullseye-size) + var(--bullseye-shadow-size) * 2); --bullseye-color: red; --bullseye-special-color: gold; ... } /* Ocultamos los checkbox. */ .bullseye-input { ... opacity: 0; } .bullseye { ... /* Cambiamos el position para posicionar absolutamente los pseudo elementos. */ position: relative; } .bullseye-input:checked + .bullseye { /* Cuando una diana se ha marcado, ya no permitimos que se desmarque. */ pointer-events: none; } /* El pseudo elemento :before es la diana. */ .bullseye:before { /* Definimos la variable que dará el color al radial-gradient. */ --color: var(--bullseye-color); content: ''; /* Definimos el tamaño de las dianas */ width: var(--bullseye-size); height: var(--bullseye-size); /* Hacemos la diana circular. */ border-radius: 50%; /* Definimos el radial-gradient con el color que le hemos especificado. */ background-image: radial-gradient(closest-side, var(--color) 20%, white 0, white 40%, var(--color) 0, var(--color) 60%, white 0, white 80%, var(--color) 0); box-shadow: 4px 4px var(--bullseye-shadow-size) rgba(0, 0, 0, 0.4); } .bullseye.special:before { /* En las dianas especiales sobreescribimos el color que se usa en el radial-gradient. */ --color: var(--bullseye-special-color); } /* Cuando hemos acertado sobre una diana, cambiamos el color del radial-gradient * a grey, hacemos que desaparezca con opacity y disminuimos un poco su tamaño * con una animación. */ .bullseye-input:checked + .bullseye:before { --color: grey; animation: bullseye-fadeout 0.8s ease-in-out forwards; } /* El pseudo elemento :after es el "+1" que aparece cuando acertamos en una diana. */ .bullseye:after { /* Creamos una variable con los puntos a mostrar. */ --points-str: var(--bullseye-points-str); /* Mostramos el número de puntos que corresponden a esta diana. */ content: '+' var(--points); /* Posicionamos el elemento en el centro de la diana. */ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); /* Le añadimos una sombra molona. */ text-shadow: 2px 2px 0px var(--accent-color); } /* Cuando es una diana especial sobreescribimos los puntos a mostrar. */ .bullseye.special:after { --points-str: var(--bullseye-special-points-str); } /* Cuando el jugador acierta sobre una diana, le añadimos una animación para que aparezca el "+1". */ .bullseye-input:checked + .bullseye:after { animation: points-up 1.5s forwards; } :root { --total-bullseye: 8; --bullseye-animation-duration: 2.7s; --score-delay: calc(var(--bullseye-animation-duration) * var(--total-bullseye)); } .bullseye { ... position: absolute; top: calc(-1 * var(--bullseye-total-size)); /* He preferido poner las propiedades de animation por separado para mayor claridad. */ animation-name: bullseye-movement; animation-timing-function: ease-out; animation-duration: var(--bullseye-animation-duration); /* Añadimos un delay a la animación de cada diana correspondiente a su índice multiplicado * por la duración de la animación de caída. * */ animation-delay: calc(var(--bullseye-animation-duration) * (var(--index) - 1)); } /* Definimos la variable índice de cada diana y le asignamos una posición arbitraria * para dar una sensación de aleatoriedad. */ .bullseye:nth-of-type(1) { --index: 1; left: 70%; } ... .bullseye:nth-of-type(8) { --index: 8; left: 85%; } /* Cuando el jugador acierte en la diana, paramos la animación de caída manera que se * quede parada. Esto sumado al afecto fadeout que le hemos añadido antes dá un efecto molón. */ .bullseye-input:checked + .bullseye { animation-play-state: paused; ... } /* Añadimos la animación al marcador. Nótese el delay que hemos calculado * en el bloque de variables. Importante añadir forwards para que la animación * se quede en su estado final al acabar. */ #score { ... animation: score-end 0.4s ease-in-out var(--score-delay) forwards; } :root { ... /* Definimos nuestro cursor apuntando a una imagen con la función url(), tal y como * haríamos en background-image. Antes del SVG añadimos "data:image/svg+xml;utf8," * para que el navegador sepa que se trata de una imagen de tipo SVG. */ cursor: url('data:image/svg+xml;utf8,<svg ... fill="%2353FF45"/></svg>') 21 21, crosshair; } *, *:before, *:after { /* Hacemos que todos los elementos hereden el cursor que hemos definido. * Si no lo hiciéramos, los <label> seguirían teniendo el cursor por defecto. */ cursor: inherit; } #search { background-color: red; } #search:target { background-color: blue; } /* El enlace de empezar partida hacemos que ocupe toda la pantalla. */ #start { position: fixed; top: 0; right: 0; bottom: 0; left: 0; ... color: var(--text-color); text-shadow: 2px 2px 0 red; background-color: var(--bg-color); } /* Cuando el jugador hace clic en el enlace ocultamos el enlace para mostrar el juego. */ #stage:target #start { display: none; } /* Animamos el texto de #start con un efecto de pulso. */ .start-text { animation: pulse 1.2s ease-out infinite; } /* Activamos la animación de las dianas cuando el jugador ha hecho clic en #start. Empieza el juego. */ #stage:target .bullseye { animation-name: bullseye-movement; } /* Activamos la animación del marcador cuando el jugador ha hecho clic en #start. */ #stage:target #score { animation: score-end 0.4s ease-in-out var(--score-delay) forwards; }

Comentarios

Entradas populares