CursosEmpresasBlogLiveConfPrecios

Sistema de tiempo y puntajes

Clase 17 de 24 • Taller Práctico de JavaScript: ¡Crea tu Primer Videojuego!

Clase anteriorSiguiente clase

Contenido del curso

Introducción

  • 1
    Programemos un juego con JavaScript

    Programemos un juego con JavaScript

    17:13 min

Canvas

  • 2
    ¿Qué es canvas en JavaScript?

    ¿Qué es canvas en JavaScript?

    18:37 min
  • 3
    Tamaño del canvas y sus elementos

    Tamaño del canvas y sus elementos

    17:37 min
  • 4
    Canvas responsive

    Canvas responsive

    12:37 min

Mapa del juego

  • 5
    ¿Qué es un array bidimensional?

    ¿Qué es un array bidimensional?

    05:48 min
  • 6
    Arreglos multidimensionales en JavaScript

    Arreglos multidimensionales en JavaScript

    23:38 min
  • 7
    Refactor del mapa de juego

    Refactor del mapa de juego

    20:48 min

Movimientos del jugador

  • 8
    Eventos y botones

    Eventos y botones

    14:14 min
  • 9
    Objeto playerPosition

    Objeto playerPosition

    11:34 min
  • 10
    Limpieza de movimientos

    Limpieza de movimientos

    09:53 min
  • 11
    No te salgas del mapa

    No te salgas del mapa

    11:15 min

Colisiones

  • 12
    Detectando colisiones fijas

    Detectando colisiones fijas

    13:29 min
  • 13
    Detectando colisiones con arrays

    Detectando colisiones con arrays

    14:11 min
  • 14
    Victoria: subiendo de nivel

    Victoria: subiendo de nivel

    07:50 min
  • 15
    Derrota: perdiendo vidas

    Derrota: perdiendo vidas

    11:45 min

Bonus: adictividad

  • 16
    Sistema de vidas y corazones

    Sistema de vidas y corazones

    13:02 min
  • 17
    Sistema de tiempo y puntajes

    Sistema de tiempo y puntajes

    Viendo ahora
  • 18
    ¿Qué es localStorage?

    ¿Qué es localStorage?

    07:33 min
  • 19
    Guardando records del jugador

    Guardando records del jugador

    18:35 min

Deploy

  • 20
    Depurando errores del juego

    Depurando errores del juego

    23:16 min
  • 21
    Desplegando el juego a GitHub Pages

    Desplegando el juego a GitHub Pages

    07:39 min

Próximos pasos

  • 22
    Reto: reinicio del juego

    Reto: reinicio del juego

    03:36 min
  • 23
    Reto: timeouts de victoria o derrota

    Reto: timeouts de victoria o derrota

    04:14 min
  • 24
    ¿Quieres un simulador laboral?

    ¿Quieres un simulador laboral?

    06:53 min
Tomar examen

Escuelas

  • Desarrollo Web
    • Fundamentos del Desarrollo Web Profesional
    • Diseño y Desarrollo Frontend
    • Desarrollo Frontend con JavaScript
    • Desarrollo Frontend con Vue.js
    • Desarrollo Frontend con Angular
    • Desarrollo Frontend con React.js
    • Desarrollo Backend con Node.js
    • Desarrollo Backend con Python
    • Desarrollo Backend con Java
    • Desarrollo Backend con PHP
    • Desarrollo Backend con Ruby
    • Bases de Datos para Web
    • Seguridad Web & API
    • Testing Automatizado y QA para Web
    • Arquitecturas Web Modernas y Escalabilidad
    • DevOps y Cloud para Desarrolladores Web
  • English Academy
    • Inglés Básico A1
    • Inglés Básico A2
    • Inglés Intermedio B1
    • Inglés Intermedio Alto B2
    • Inglés Avanzado C1
    • Inglés para Propósitos Específicos
    • Inglés de Negocios
  • Marketing Digital
    • Fundamentos de Marketing Digital
    • Marketing de Contenidos y Redacción Persuasiva
    • SEO y Posicionamiento Web
    • Social Media Marketing y Community Management
    • Publicidad Digital y Paid Media
    • Analítica Digital y Optimización (CRO)
    • Estrategia de Marketing y Growth
    • Marketing de Marca y Comunicación Estratégica
    • Marketing para E-commerce
    • Marketing B2B
    • Inteligencia Artificial Aplicada al Marketing
    • Automatización del Marketing
    • Marca Personal y Marketing Freelance
    • Ventas y Experiencia del Cliente
    • Creación de Contenido para Redes Sociales
  • Inteligencia Artificial y Data Science
    • Fundamentos de Data Science y AI
    • Análisis y Visualización de Datos
    • Machine Learning y Deep Learning
    • Data Engineer
    • Inteligencia Artificial para la Productividad
    • Desarrollo de Aplicaciones con IA
    • AI Software Engineer
  • Ciberseguridad
    • Fundamentos de Ciberseguridad
    • Hacking Ético y Pentesting (Red Team)
    • Análisis de Malware e Ingeniería Forense
    • Seguridad Defensiva y Cumplimiento (Blue Team)
    • Ciberseguridad Estratégica
  • Liderazgo y Habilidades Blandas
    • Fundamentos de Habilidades Profesionales
    • Liderazgo y Gestión de Equipos
    • Comunicación Avanzada y Oratoria
    • Negociación y Resolución de Conflictos
    • Inteligencia Emocional y Autogestión
    • Productividad y Herramientas Digitales
    • Gestión de Proyectos y Metodologías Ágiles
    • Desarrollo de Carrera y Marca Personal
    • Diversidad, Inclusión y Entorno Laboral Saludable
    • Filosofía y Estrategia para Líderes
  • Diseño de Producto y UX
    • Fundamentos de Diseño UX/UI
    • Investigación de Usuarios (UX Research)
    • Arquitectura de Información y Usabilidad
    • Diseño de Interfaces y Prototipado (UI Design)
    • Sistemas de Diseño y DesignOps
    • Redacción UX (UX Writing)
    • Creatividad e Innovación en Diseño
    • Diseño Accesible e Inclusivo
    • Diseño Asistido por Inteligencia Artificial
    • Gestión de Producto y Liderazgo en Diseño
    • Diseño de Interacciones Emergentes (VUI/VR)
    • Desarrollo Web para Diseñadores
    • Diseño y Prototipado No-Code
  • Contenido Audiovisual
    • Fundamentos de Producción Audiovisual
    • Producción de Video para Plataformas Digitales
    • Producción de Audio y Podcast
    • Fotografía y Diseño Gráfico para Contenido Digital
    • Motion Graphics y Animación
    • Contenido Interactivo y Realidad Aumentada
    • Estrategia, Marketing y Monetización de Contenidos
  • Desarrollo Móvil
    • Fundamentos de Desarrollo Móvil
    • Desarrollo Nativo Android con Kotlin
    • Desarrollo Nativo iOS con Swift
    • Desarrollo Multiplataforma con React Native
    • Desarrollo Multiplataforma con Flutter
    • Arquitectura y Patrones de Diseño Móvil
    • Integración de APIs y Persistencia Móvil
    • Testing y Despliegue en Móvil
    • Diseño UX/UI para Móviles
  • Diseño Gráfico y Arte Digital
    • Fundamentos del Diseño Gráfico y Digital
    • Diseño de Identidad Visual y Branding
    • Ilustración Digital y Arte Conceptual
    • Diseño Editorial y de Empaques
    • Motion Graphics y Animación 3D
    • Diseño Gráfico Asistido por Inteligencia Artificial
    • Creatividad e Innovación en Diseño
  • Programación
    • Fundamentos de Programación e Ingeniería de Software
    • Herramientas de IA para el trabajo
    • Matemáticas para Programación
    • Programación con Python
    • Programación con JavaScript
    • Programación con TypeScript
    • Programación Orientada a Objetos con Java
    • Desarrollo con C# y .NET
    • Programación con PHP
    • Programación con Go y Rust
    • Programación Móvil con Swift y Kotlin
    • Programación con C y C++
    • Administración Básica de Servidores Linux
  • Negocios
    • Fundamentos de Negocios y Emprendimiento
    • Estrategia y Crecimiento Empresarial
    • Finanzas Personales y Corporativas
    • Inversión en Mercados Financieros
    • Ventas, CRM y Experiencia del Cliente
    • Operaciones, Logística y E-commerce
    • Gestión de Proyectos y Metodologías Ágiles
    • Aspectos Legales y Cumplimiento
    • Habilidades Directivas y Crecimiento Profesional
    • Diversidad e Inclusión en el Entorno Laboral
    • Herramientas Digitales y Automatización para Negocios
  • Blockchain y Web3
    • Fundamentos de Blockchain y Web3
    • Desarrollo de Smart Contracts y dApps
    • Finanzas Descentralizadas (DeFi)
    • NFTs y Economía de Creadores
    • Seguridad Blockchain
    • Ecosistemas Blockchain Alternativos (No-EVM)
    • Producto, Marketing y Legal en Web3
  • Recursos Humanos
    • Fundamentos y Cultura Organizacional en RRHH
    • Atracción y Selección de Talento
    • Cultura y Employee Experience
    • Gestión y Desarrollo de Talento
    • Desarrollo y Evaluación de Liderazgo
    • Diversidad, Equidad e Inclusión
    • AI y Automatización en Recursos Humanos
    • Tecnología y Automatización en RRHH
  • Finanzas e Inversiones
    • Fundamentos de Finanzas Personales y Corporativas
    • Análisis y Valoración Financiera
    • Inversión y Mercados de Capitales
    • Finanzas Descentralizadas (DeFi) y Criptoactivos
    • Finanzas y Estrategia para Startups
    • Inteligencia Artificial Aplicada a Finanzas
    • Domina Excel
    • Financial Analyst
    • Conseguir trabajo en Finanzas e Inversiones
  • Startups
    • Fundamentos y Validación de Ideas
    • Estrategia de Negocio y Product-Market Fit
    • Desarrollo de Producto y Operaciones Lean
    • Finanzas, Legal y Fundraising
    • Marketing, Ventas y Growth para Startups
    • Cultura, Talento y Liderazgo
    • Finanzas y Operaciones en Ecommerce
    • Startups Web3 y Blockchain
    • Startups con Impacto Social
    • Expansión y Ecosistema Startup
  • Cloud Computing y DevOps
    • Fundamentos de Cloud y DevOps
    • Administración de Servidores Linux
    • Contenerización y Orquestación
    • Infraestructura como Código (IaC) y CI/CD
    • Amazon Web Services
    • Microsoft Azure
    • Serverless y Observabilidad
    • Certificaciones Cloud (Preparación)
    • Plataforma Cloud GCP

Platzi y comunidad

  • Platzi Business
  • Live Classes
  • Lanzamientos
  • Executive Program
  • Trabaja con nosotros
  • Podcast

Recursos

  • Manual de Marca

Soporte

  • Preguntas Frecuentes
  • Contáctanos

Legal

  • Términos y Condiciones
  • Privacidad
  • Tyc promociones
Reconocimientos
Reconocimientos
Logo reconocimientoTop 40 Mejores EdTech del mundo · 2024
Logo reconocimientoPrimera Startup Latina admitida en YC · 2014
Logo reconocimientoPrimera Startup EdTech · 2018
Logo reconocimientoCEO Ganador Medalla por la Educación T4 & HP · 2024
Logo reconocimientoCEO Mejor Emprendedor del año · 2024
De LATAM conpara el mundo
YoutubeInstagramLinkedInTikTokFacebookX (Twitter)Threads
        Rubén Ernesto Aragón Gil

        Rubén Ernesto Aragón Gil

        student•
        hace 3 años

        Minuto 3:48

          Juan Castro

          Juan Castro

          teacher•
          hace 3 años

          ALGUIEN ENTENDIÓ POR FIN

          Jesus Marquez Martini

          Jesus Marquez Martini

          student•
          hace 3 años

          la moskeramienta

        marco antonio

        marco antonio

        student•
        hace 3 años

        Le construí un format para que se lea mejor ;)

        timeformat.jpg


        también decidí agregarle un timer al contiue no mas para que vea mas bonito  
        //contect const canvas = document.querySelector('#game'); const btnArriba = document.querySelector('#arriba'); const btnAbajo = document.querySelector('#abajo'); const btnDer = document.querySelector('#derecha'); const btnIzq = document.querySelector('#izquierda'); const viewlive = document.querySelector('#lives'); const viewTime = document.querySelector('#time'); const juego = canvas.getContext('2d'); //signals: window.addEventListener('load', loadEvent); window.addEventListener('resize', resizeEvent); let posJugador = undefined; let mapa = Array(); let nivel = 0; let prePosJugador = undefined; let celda_t = 0; let nivel_actual = undefined; let puntoDePartida = Number(0); let canvas_t = 0; var actualizado = Boolean(false); let explociones = Array(); let vidas = 3; let timeStart = undefined; let timeInterval = undefined; let playerTime = 0; const re_iniciar = {'select': 'si', 'resetStart': 'indeciso','exec' : false}; function loadEvent(){ viewTime.innerHTML = '0:0:0'; timeEvent(); resizeEvent();} function resizeEvent(){ actualizado = false; canvas_t = (window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight) *.75 ; canvas.setAttribute('width', canvas_t); canvas.setAttribute('height',canvas_t); celda_t = canvas_t / 10; juego.textAlign='end'; juego.font = font_t() +'px arial'; liveEvent(); update();} function font_t(){ return celda_t - celda_t / 10;} function liveEvent(){ const corazon = Array(vidas).fill(emojis['HEART']); viewlive.innerHTML = corazon.join('');} function timeFormat(time_msec){ const time = ~~(time_msec /1000); const min = (time / 60) | 0; const sec = time - (min * 60); const msec = ((time_msec / 10) | 0) - (time * 100); return min +':'+ ((sec < 10 ? '0' : 0) + sec) + ':' + ((msec < 10 ? '0' : 0) + msec);} function paintTimeEvent(){ playerTime = Date.now() - timeStart; viewTime.innerHTML = timeFormat(playerTime);} function timeEvent(var_function = paintTimeEvent){ if(!timeInterval){ timeStart = Date.now(); timeInterval = setInterval(var_function, 100);} else{ clearInterval(timeInterval); timeStart = undefined; timeInterval = undefined;}} function resetStartEvent(){ posJugador = prePosJugador = undefined; nivel = 0; nivel_actual = undefined; puntoDePartida = 0; vidas = 3; actualizado = false; explociones = Array(); re_iniciar['select'] = 'si'; re_iniciar['exec'] = false; re_iniciar['resetStart'] = 'indeciso'; timeEvent(); liveEvent(); playerTime = 0; update();} function update(){ if(re_iniciar['exec']){paintScreenFinal(); return;} cargarMapa(); clear(); paintEvent(); paintEventPlayer(); paintEventExplosion(); actualizado = true;} function cargarMapa(){ if(nivel_actual == nivel || Victoria()) return; nivel_actual = nivel; mapa = map[nivel].match(/[IOX-]/g);} function clear(){ if(!actualizado) { juego.clearRect(0,0, canvas_t, canvas_t); return;} if(posJugador == prePosJugador) return; clearRect(posJugador); clearRect(prePosJugador);} function clearRect(indice){ const x = posX(indice ) - celda_t / 10; const y = posY(indice ) + celda_t / 5; juego.clearRect(x - 1 ,y , - celda_t, - (celda_t + 1));} function posY(indice){ return (~~(indice/10) + 1) * celda_t - celda_t / 5; } function posX(indice){ return (indice - (~~(indice/10) * 10) + 1) * celda_t + celda_t / 10;} function paintEvent(){ if(!actualizado) mapa.forEach((char, idx) => { if(char == 'O' && posJugador == undefined) puntoDePartida = posJugador = idx; juego.fillText(emojis[char], posX(idx), posY(idx) );});} function paintEventPlayer(){ if(victoryEvent()) paintScreenEvent(); else { if(posJugador != undefined && prePosJugador != posJugador){ juego.fillText(emojis[mapa[prePosJugador]],posX(prePosJugador),posY(prePosJugador)); if(!gameOverEvent()) juego.fillText(emojis['PLAYER'], posX(posJugador),posY(posJugador)); else paintScreenEvent();}}} function gameOverEvent(){ if(vidas && mapa[posJugador] == 'X'){ explociones.push(posJugador); --vidas; liveEvent(); juego.fillText(emojis['BOMB_COLLISION'],posX(posJugador),posY(posJugador)); posJugador = puntoDePartida;} if(gameFinishEvent()) { explociones = Array(); return true;} /*juego terminado*/ return false; /*continuar con el juego*/} function paintEventExplosion(){ if(!explociones.length) return; explociones.forEach((pos) =>{ clearRect(pos); juego.fillText(emojis['BOMB_COLLISION'],posX(pos),posY(pos));});} function victoryEvent(){ if(mapa[posJugador] != 'I') return false; else if(nivel < map.length) ++nivel; explociones = Array(); if(gameFinishEvent()) return true;/*juego terminado*/ posJugador = prePosJugador = undefined; actualizado = false; update(); return false;/*continuar con el juego*/} function Victoria(){return nivel >= map.length;} function gameFinishEvent(){ if(!(nivel >= map.length) == (vidas <= 0) && !re_iniciar['exec']) { timeEvent(); re_iniciar['exec'] = true;} return !(nivel >= map.length) == (vidas <= 0);} function paintScreenEvent(){ if(!re_iniciar['exec']) return; paintScreen(Victoria() ? 'WIN': 'GAME_OVER'); paintScreenFinal();} function paintScreenFinal(){ if(!re_iniciar['exec']) return; if(!actualizado) paintScreen(Victoria() ? 'WIN': 'GAME_OVER'); if(!timeInterval && !Victoria() && re_iniciar['select'] != 'exit') { timeEvent(paintScreenFinal);} const media = canvas_t / 2; const media_alta = media - font_t() + 1; const media_baja = media + font_t() - 1; let color, backgroundColor, text = 'continuar', y = media_alta; if(Victoria()){ color = '#ffd700'; backgroundColor = '#01433A';} else { color = '#FF2F22'; backgroundColor = '#211A27';} if(re_iniciar['resetStart'] == 'no' || re_iniciar['select'] == 'exit'){ if(actualizado)paintScreen(Victoria() ? 'WIN': 'GAME_OVER'); if(timeStart) timeEvent(); text = Victoria() ? 'Has Ganado' : 'Game Over'; y = media + (font_t() / 2); re_iniciar['select'] = 'exit';} else if(re_iniciar['resetStart'] == 'si') { timeEvent(); resetStartEvent(); return;} else{ if(timeStart){ const contador = 10 - (((Date.now() - timeStart) / 1000) | 0); text = text + ' ' + contador; if(contador < 0){ timeEvent(); re_iniciar['resetStart'] = 'no'; update(); return;}} paintScreen(Victoria() ? 'WIN': 'GAME_OVER'); paintRectText('', '' , backgroundColor,'center',media, media); paintRectText('', '' , backgroundColor,'center',media, media_baja); let siCa = color, siCb = backgroundColor; let noCa = color, noCb = backgroundColor; if(re_iniciar['select'] == 'no'){ noCa = backgroundColor; noCb = color;} else { siCa = backgroundColor; siCb = color;} paintRectText('no', noCa, noCb,'center',media + font_t(), media + (font_t() / 2)); paintRectText('si', siCa, siCb,'center',media - font_t(), media + (font_t() / 2));} paintRectText('', '' , backgroundColor,'center',media, y); paintRectText(text, color , '','center',media, y);} function paintScreen(emoji){ juego.clearRect(0,0, canvas_t, canvas_t); mapa.forEach((char, idx) =>{ if(char == 'X') char = emoji; juego.fillText(emojis[char],posX(idx),posY(idx));});} function paintRectText(txt, color = '', backgroundColor = '', aling = 'center', x = 0,y = 0){ if(aling) juego.textAlign = aling; if(backgroundColor){ const rect = rectBgText(txt, x, y, aling); juego.fillStyle = backgroundColor; juego.fillRect(rect['x'], rect['y'], rect['width'], rect['height']);} if(color) juego.fillStyle = color; if(txt) juego.fillText(txt, x, y); juego.textAlign = 'end';} function rectBgText(txt, x = 0, y = 0, align=''){ const height = font_t(); const width = txt == ''|| txt == ' ' ? canvas_t : (font_t()*.75)* txt.length; let px = x; let py = y - (height - (height / 6)); if(align == 'center'){px = x - (width / 2);} else if(align != 'left')px = x - width; return {'width': width, 'height':height, 'x': px, 'y' : py};} //signals: window.addEventListener('keydown',keyMov); btnArriba.addEventListener('click', movArriba); btnAbajo.addEventListener('click', movAbajo); btnDer.addEventListener('click', movDer); btnIzq.addEventListener('click', movIzq); //slots: function keyMov(event){ switch(event.keyCode){ //enter S N Y case 13: case 83: case 78: case 89: selectOptionEvent(event.keyCode); break;//selecionar opciones case 37: movIzq(); break;//izquierda case 38: movArriba(); break;//arriba case 39: movDer(); break; //derecha case 40: movAbajo(); break;//abajo default: break;}} function selectOptionEvent(key){ if(key == 83 || key == 89) re_iniciar['resetStart'] = 'si'; else if(key == 78) re_iniciar['resetStart'] = 'no'; else re_iniciar['resetStart'] = re_iniciar['select']; update();} function movArriba(){ prePosJugador = posJugador; posJugador -= 10; if(posJugador < 0) posJugador = prePosJugador; update();} function movAbajo(){ prePosJugador = posJugador; posJugador += 10; if(posJugador >= 100) posJugador = prePosJugador; update();} function movDer(){ if(re_iniciar['exec']) re_iniciar['select'] = 'no'; else{ prePosJugador = posJugador; const pered = (~~(posJugador / 10)) *10 + 10; ++posJugador; if(posJugador >= pered) posJugador = prePosJugador;} update();} function movIzq(){ if(re_iniciar['exec']) re_iniciar['select'] = 'si'; else{ prePosJugador = posJugador; const pered = ~~(posJugador /10) * 10; --posJugador; if(posJugador < pered) posJugador = prePosJugador;} update();}
          Juan Castro

          Juan Castro

          teacher•
          hace 3 años

          Me encanta la idea del counter hacia atrás para reanudar el juego. :clap:

        Juan Jose Sepulveda Calderon

        Juan Jose Sepulveda Calderon

        student•
        hace 3 años

        Date.now()

        El método estático Date.now() devuelve el número de milisegundos transcurridos desde el 1 de enero de 1970 a las 00:00:00 UTC. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now

        Eliezer Hernandez

        Eliezer Hernandez

        student•
        hace 3 años
        Desarrolle una función que de al tiempo en milisegundos, un formato en el que se puede apreciar las horas, minutos, segundos y centisegundos a partir de los milisegundos; tal cual como lo haría un cronómetro.
        carbon (1).png
          Diego Hanssel Perez

          Diego Hanssel Perez

          student•
          hace 3 años

          Hola Eliezer, que fue lo que guardaste en ms? me gusto mucho tu solución y me gustaría implementarla.

          Eliezer Hernandez

          Eliezer Hernandez

          student•
          hace 3 años

          Hola @diego-hanssel-perez, disculpa la demora de mi respuesta. “ms” son los milisegundos, por lo que le puedes pasar a la funcion el tiempo en milisegundos como argumento y la function se encargara de llevar el tiempo representado en esa unidad(ms) al formato que todos solemos utilizar para representar el tiempo de forma mas legible, mostrando las horas, minutos, segundos y centisegundos como se ve arriba en el gif de la misma manera que lo hace un relog digital.

          Ejemplo: -1000 milisegundos equivalen a 1 segundo por lo que deberia verse de la siguiente manera 00:00:01:00. -250000 milisegundos equivalen a 4 minutos con 10 segundos exactos por lo que deberia verse 00:04:10:00. . Si gustas puedes mejorar la función yo realmente no lo hice en su momento porque me encontraba realmente corto de tiempo, por ejemplo la función tiene muchos “magics numbers” que estoy seguro de que más de uno no tendrá claro el contexto de estos números, también podrías sustituir el uso del metodo slice por algún otro metodo lo que podría dar una idea más clara de porque lo estoy usando por ejemplo por el metodo padStart:

          function formatTime(ms){ const cs = parseInt(ms/10) % 100 const seg = parseInt(ms/1000) % 60 const min = parseInt(ms/60000) % 60 const hr = parseInt(ms/3600000) % 24 const csStr = `${cs}`.padStart(2,"0") const segStr = `${seg}`.padStart(2,"0") const minStr = `${min}`.padStart(2,"0") const hrStr = `${hr}`.padStart(2,"0") return`${hrStr}:${minStr}:${segStr}:${csStr}` }

          Gracias por comentar y espero haber resultado de ayuda compañero, nos vemos mas adelante en proximos cursos o en este mismo aporte si tienes alguna pregunta mas no dudes escribirla. Un saludo.

        César Augusto Cortés Labrada

        César Augusto Cortés Labrada

        student•
        hace 3 años

        Utilicé una conversión para que se vea mejor el tiempo.

        function showTime(){ textTime.innerText = +((Date.now()-timeStart)/1000); }

        Además especifiqué en la etiqueta <p> que el tiempo es en segundos. Este curso está super.

        Cristian Zapata

        Cristian Zapata

        student•
        hace 3 años

        Con formato fácil:

        Se crea una función:

        function formatTime(ms){ const cs = parseInt(ms/10) % 100 const seg = parseInt(ms/1000) % 60 const min = parseInt(ms/60000) % 60 const csStr = `${cs}`.padStart(2,"0") const segStr = `${seg}`.padStart(2,"0") const minStr = `${min}`.padStart(2,"0") return`${minStr}:${segStr}:${csStr}` }

        Se modifica el string de showTime():

        function showTime(){ spanTime.innerHTML = formatTime(Date.now()-timeStart); }

        Time: mm:ss:ms

        Nestor Luis Álvarez Rojas

        Nestor Luis Álvarez Rojas

        student•
        hace 3 años

        ¡Que maravilloso profesor eres, Juan!

        Jorge Alejandro Suárez Rivera

        Jorge Alejandro Suárez Rivera

        student•
        hace 2 años

        Yo lo que hice fué cambiar el formato de tiempo a como se conoce normalmente ya que como aparece sin dos puntos ni nada de eso no me parece legible, entonces mi solución es que el tiempo tenga esto

        function showTime() { const time = Date.now() - timeStart; const minutes = Math.floor(time / 60000); const seconds = Math.floor((time % 60000) / 1000); const milliseconds = time % 1000; spanTime.innerHTML = `${minutes}:${seconds}.${milliseconds}`; }

        eso es lo que cambiaria en la función de showTime, el código completo es este obviamente sin contar lo de las próximas clases

        const canvas = document.getElementById('game'); const game = canvas.getContext('2d'); const btnUp = document.getElementById('up'); const btnLeft = document.getElementById('left'); const btnRight = document.getElementById('right'); const btnDown = document.getElementById('down'); const spanLives = document.getElementById('lives'); const spanTime = document.getElementById('time'); let canvasSize; let elementsSize; let level = 0; let lives = 3; let timeStart; let timePlayer; let timeInterval; const playerPos = { x: undefined, y: undefined, }; const finishPos = { x: undefined, y: undefined, } let enemiesPos = []; window.addEventListener("load", setCanvasSize); window.addEventListener("resize", setCanvasSize); function setCanvasSize() { if (window.innerHeight > window.innerWidth) { canvasSize = window.innerWidth * 0.8; } else { canvasSize = window.innerHeight * 0.8; } canvas.setAttribute('width', canvasSize); canvas.setAttribute('height', canvasSize); elementsSize = canvasSize / 10; startGame(); } function startGame() { game.font = (elementsSize - 12) + 'px Verdana'; game.textAlign = 'end'; game.textBaseline = 'bottom'; const map = maps[level]; if (!map) { gameWin(); return; } if(!timeStart) { timeStart=Date.now();timeInterval=setInterval(showTime,100); } const mapRows = map.trim().split('\n'); const mapRowCols = mapRows.map(row => row.trim().split('')); showLives(); enemiesPos = []; game.clearRect(0,0, canvasSize, canvasSize); mapRowCols.forEach((row, rowI) => { row.forEach((col, colI) => { const emoji = emojis[col]; const posX = elementsSize * (colI + 1); const posY = elementsSize * (rowI + 1); if(col == "O"){ if (!playerPos.x && !playerPos.y) { playerPos.x = posX; playerPos.y = posY; } } else if(col == "I"){ finishPos.x = posX; finishPos.y = posY; } else if (col == 'X') { enemiesPos.push({ x: posX, y: posY, }); } game.fillText(emoji, posX, posY); }); }); movePlayer(); } function movePlayer(){ const giftColX = playerPos.x.toFixed(2) == finishPos.x.toFixed(2); const giftColY = playerPos.y.toFixed(2) == finishPos.y.toFixed(2); const giftCol = giftColX && giftColY; if (giftCol) { levelWin(); } const enemiesCol = enemiesPos.find( enemy => { const enemyColX = enemy.x.toFixed(2) == playerPos.x.toFixed(2); const enemyColY = enemy.y.toFixed(2) == playerPos.y.toFixed(2); return enemyColX && enemyColY; }); if (enemiesCol) { levelFail(); } game.fillText(emojis['PLAYER'], playerPos.x, playerPos.y); } function levelWin() { console.log('Subiste de nivel'); level++; startGame(); } function levelFail() { console.log('Chocaste'); lives--; timeStart=undefined; console.log(lives); if (lives <= 0) { level = 0; lives = 3; } playerPos.x = undefined; playerPos.y = undefined; startGame(); } function gameWin() { console.log('¡Terminaste el juego!'); clearInterval(timeInterval); } function showLives() { spanLives.innerHTML = emojis["HEART"].repeat(lives) } function showTime() { const time = Date.now() - timeStart; const minutes = Math.floor(time / 60000); const seconds = Math.floor((time % 60000) / 1000); const milliseconds = time % 1000; spanTime.innerHTML = `${minutes}:${seconds}.${milliseconds}`; } window.addEventListener('keydown', moveKeysDir); btnUp.addEventListener('click', moveUp); btnLeft.addEventListener('click', moveLeft); btnRight.addEventListener('click', moveRight); btnDown.addEventListener('click', moveDown); function moveKeysDir(event){ if (event.code == "KeyW" || event.code == "ArrowUp") { moveUp(); } else if (event.code == "KeyA" || event.code == "ArrowLeft") { moveLeft(); } else if (event.code == "KeyD" || event.code == "ArrowRight") { moveRight(); } else if (event.code == "KeyS" || event.code == "ArrowDown") { moveDown(); } } function moveUp(){ if ((playerPos.y - elementsSize) < elementsSize ) { } else { playerPos.y -= elementsSize; startGame(); } } function moveLeft(){ if ((playerPos.x - elementsSize) < elementsSize ) { } else { playerPos.x -= elementsSize; startGame(); } } function moveRight(){ if ((playerPos.x + elementsSize) > canvasSize ) { } else { playerPos.x += elementsSize; startGame(); } } function moveDown(){ if ((playerPos.y + elementsSize) > canvasSize ) { } else { playerPos.y += elementsSize; startGame(); } }
        Raúl Adolfo Sánchez Rodríguez

        Raúl Adolfo Sánchez Rodríguez

        student•
        hace 2 años

        Solución a contador de tiempo de juego a partir de minuto 11:40 de la clase

        1. Solución

        2. Paso a paso

          Slide1.png
          Slide2.png
          Slide3.png
          Slide4.png
          Slide5.png
          Slide6.png
          Slide7.png
          Slide8.png
          Slide9.png
          Slide10.png
          Slide11.png
          Slide12.png
          Slide13.png
          Slide14.png
          Slide15.png
          Slide16.png
          Slide17.png
          Slide18.png
          Slide19.png
          Slide20.png
          Slide21.png
          Slide22.png
          Slide23.png

        Miguel Angel Hernandez Colombo

        Miguel Angel Hernandez Colombo

        student•
        hace 3 años

        hice los tres niveles en 10 segundos ajajajajaj

        Hector Maluy Fernandez

        Hector Maluy Fernandez

        student•
        hace 3 años

        ¿Sería lo mismo si a timeStart lo seteas a null o a false en lugar de undefined?

          Juan Castro

          Juan Castro

          teacher•
          hace 3 años

          Yep

          Oscar Gutiérrez

          Oscar Gutiérrez

          student•
          hace 2 años

          Si ya que tanto undefined como null o 0 (entre otros) son valores falsy lo que significa que representa un valor falso en un contexto booleano

        Raúl Adolfo Sánchez Rodríguez

        Raúl Adolfo Sánchez Rodríguez

        student•
        hace 2 años

        Función global: clearInterval( )

        _

        clearInterval-function.png
        Adhemar Duran Gahuincha

        Adhemar Duran Gahuincha

        student•
        hace 3 años

        En la función levelFail se debería aumentar:

        if (lives <= 0) { level = 0; lives = 3; clearInterval(timeInterval); timeStart = undefined; }

        Para evitar una memory leak.

          Oscar Israel Román Quispe

          Oscar Israel Román Quispe

          student•
          hace 2 años

          Muy bien. Tu aporte sirve para evitar que el contador siga contando cuando el jugador gane los 3 mapas luego de reiniciado los mapas (muerto 3 veces).

        Mauricio Combariza

        Mauricio Combariza

        student•
        hace 3 años

        La variable fecha incluye el tiempo en milisegundos por lo que una diferencia entre la fecha en que inicio y en la que termino, puede ser la medida de tiempo.

        // Al iniciar el juego, se guarda el tiempo actual startTime = new Date();

        Esta se coloca en movePlayer cuando sale de O, y esta sería la función de winLevel:

        function winLevel() { const endTime = new Date(); const elapsedSeconds = Math.floor((endTime.getTime() - (startTime as Date).getTime()) / 1000); console.log('Ganaste eeee'); console.log('Tiempo transcurrido:', elapsedSeconds, 'segundos'); if (level >= 0 && level < maps.length -1) { level += 1 mapaActual = [] startGame() } else { console.error('Fin del juego Ganaste!!'); } }
        David Alvarez

        David Alvarez

        student•
        hace 3 años

        Para insertar emojies usar tecla de Windows y .

        Jonathan Meixueiro

        Jonathan Meixueiro

        student•
        hace 3 años

        Reinventando la rueda para formatear el timer 😅

        function showTime() { const msToSec = (Date.now() - timeStart) / 1000; const milliseconds = (String(msToSec - Math.floor(msToSec)).split('.')[1]).substring(0,2); const milliInterval = Date.now() - timeStart; let seconds = Math.floor(milliInterval / 1000); let minutes = Math.floor(seconds / 60); seconds = (seconds % 60) < 10 ? `0${seconds % 60}` : seconds % 60; minutes = (minutes % 60) < 10 ? `0${minutes % 60}` : minutes % 60; spanTime.innerHTML = `${minutes}:${seconds}:${milliseconds}`; }
        Miguel Enrique Velásquez Millán

        Miguel Enrique Velásquez Millán

        student•
        hace 3 años

        ¿Hay alguna razón especial por la que usamos Date.now()? 🤔. · Lo pregunto porque pienso que quizás sería mucho más sencillo contabilizar el tiempo de los jugadores directamente con el setInterval en vez de estar usando el Date.now(), je je.

          Juan Castro

          Juan Castro

          teacher•
          hace 3 años

          ¿Cómo lo harías con setInterval? :o

          Miguel Enrique Velásquez Millán

          Miguel Enrique Velásquez Millán

          student•
          hace 3 años

          Así~

          let totalGameTime = 0; let currentTimer = null; const timeShown = document.querySelector("#time"); function startTimer() { currentTimer = setInterval( () => { totalGameTime++; timeShown.innerText = totalGameTime; }, 1000 ); }

          Pienso que de esta forma tendríamos un contador que muestra en pantalla el tiempo que ha transcurrido de la partida actual solo usando el setInterval, je je. · ¿El Date.now() tiene alguna cosita especial que lo haga más eficiente o algo así? Yo en mi código usé este forma ya que me parece más sencillita, je je. Incluso luego le di un formato al totalGameTime con otra función para que se viera más bonito~

        Alejandro Ramos

        Alejandro Ramos

        student•
        hace 3 años

        Y como le damo formato al tiempo ;_;

          Oscar Gutiérrez

          Oscar Gutiérrez

          student•
          hace 2 años

          Depende del tipo de formato que quieras darle. Por ejemplo si quieres que se muestre los segundos solamente, podrías utilizar la siguiente sintaxis:

          spanTime.innerHTML = ((Date.now() - timeStart) / 1000).toFixed(0);
        Antonio Mateos Mariscal

        Antonio Mateos Mariscal

        student•
        hace 2 años

        Para añadir mayor dificultad al juego, en lugar de crear un cronómetro, he decidido poner un temporizador en el que el tiempo vaya hacia atrás y cuando llegue a 0 el jugador pierda la partida.

        Para ello, he creado las variables:

        let totalTime; let timeInterval;

        He añadido el siguiente condicional dentro de la función startGame:

        if (!timeInterval) { timeInterval = setInterval(showTime, 100); }

        Y he creado la siguiente función, en la que establezco el tiempo inicial multiplicando el número total de mapas por 5 segundos cada uno, y posteriormente se van restando 10 al tiempo total cada 10 milisegundos hasta llegar a 0, momento en el que limpio el canvas con clearRect y reinicio los valores de la posición del jugador, del tiempo total, el nivel y el número de vidas:

        function showTime() { if (!totalTime) { totalTime = maps.length * 500; } else { if (totalTime > 10) { totalTime -= 10; } else { game.clearRect(0, 0, canvasSize, canvasSize); playerPosition.col = undefined; playerPosition.row = undefined; totalTime = null; level = 0; lives = 3; startGame(); } } spanTime.innerText = totalTime; }
        Raúl Adolfo Sánchez Rodríguez

        Raúl Adolfo Sánchez Rodríguez

        student•
        hace 2 años

        Contador de tiempo utilizando ++setInterval++ y ++clearInterval++

        1. Resultado
          _
        2. Paso a paso
          Mejora-1.png
          Mejora-2.png
          Mejora-3.png
          Mejora-4.png
          Mejora-5.png
          Mejora-6.png
          Mejora-7.png
          Mejora-8.png
          Mejora-9.png
          Mejora-10.png
          Mejora-11.png
          Mejora-12.png
          Mejora-13.png
          Mejora-14.png
          Mejora-15.png
          Mejora-16.png
          Mejora-17.png
          Mejora-18.png