Skip to content

A Python game demonstrating light refraction across different materials

Notifications You must be signed in to change notification settings

ManuPer3z/LightRefractionGame

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 

Repository files navigation

LightRefractionGame

A Python game demonstrating light refraction across different materials

import pygame_gui
from pygame_gui.elements import UITextEntryLine, UIButton, UILabel, UIDropDownMenu
import pygame
import math
import sys
import time
import traceback
import random
import os
import sys

if getattr(sys, 'frozen', False):
    # Estamos en un ejecutable compilado con PyInstaller
    bundle_dir = sys._MEIPASS
else:
    # Estamos en el script original de Python
    bundle_dir = os.path.dirname(os.path.abspath(__file__))

Inicializar Pygame

pygame.init()

Configuración de pantalla

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Juego de refracción")

Colores

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

Fuente de texto

font = pygame.font.Font(None, 36)

def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)


def ley_snell(n1, n2, angulo_incidente):
    angulo_incidente = math.radians(angulo_incidente)
    angulo_refractado = math.asin(n1 * math.sin(angulo_incidente) / n2)
    return math.degrees(angulo_refractado)

def game_loop():
    game_over = False
    while not game_over:
        n1 = 1.0  # Índice de refracción del aire (valor inicial)
        n2 = 1.5  # Índice de refracción del vidrio (valor inicial)

        angulo_incidente = random.randint(0, 90)  # Generar un ángulo de incidencia aleatorio entre 0 y 90 grados
        angulo_refractado_real = ley_snell(n1, n2, angulo_incidente)

        intentos = 3
        win = False
        error_margin = 2

        manager = pygame_gui.UIManager((WIDTH, HEIGHT))

        text_input = UITextEntryLine(pygame.Rect(20, 260, 150, 30), manager)

        # Crear un botón para reiniciar el juego
        restart_button = UIButton(pygame.Rect(20, 300, 150, 30), 'Reiniciar', manager)
        restart_button.hide()

        # Crear una etiqueta y un menú desplegable para seleccionar el medio
        medium_label = UILabel(pygame.Rect(20, 160, 150, 30), "Medio inicial", manager)
        mediums = {
            "Aire": 1.0,
            "Agua": 1.33,
            "Espacio": 1.0,
            "Personalizado": -1
        }
        medium_dropdown = UIDropDownMenu(list(mediums.keys()), "Aire", pygame.Rect(180, 160, 150, 30), manager)

        # Crear una etiqueta y un menú desplegable para seleccionar el tipo de vidrio
        glass_type_label = UILabel(pygame.Rect(20, 200, 150, 30), "Tipo de vidrio", manager)
        glass_types = {
            "Vidrio común": 1.5,
            "Vidrio flint": 1.6,
            "Vidrio crown": 1.52,
            "Personalizado": -1
        }
        glass_type_dropdown = UIDropDownMenu(list(glass_types.keys()), "Vidrio común", pygame.Rect(180, 200, 150, 30), manager)

        # Crear una etiqueta y un campo de entrada de texto para el índice de refracción personalizado del medio
        custom_medium_label = UILabel(pygame.Rect(350, 160, 200, 30), "n1 personalizado", manager)
        custom_medium_label.hide()
        custom_medium_entry = UITextEntryLine(pygame.Rect(560, 160, 150, 30), manager)
        custom_medium_entry.hide()

        # Crear una etiqueta y un campo de entrada de texto para el índice de refracción personalizado del vidrio
        custom_glass_label = UILabel(pygame.Rect(350, 200, 200, 30), "n2 personalizado", manager)
        custom_glass_label.hide()
        custom_glass_entry = UITextEntryLine(pygame.Rect(560, 200, 150, 30), manager)
        custom_glass_entry.hide()

        clock = pygame.time.Clock()

        game_loop_running = True
        while game_loop_running:
            time_delta = clock.tick(60) / 1000.0
            screen.fill(WHITE)
            events = pygame.event.get()

            light_beam_image_path = resource_path("snell.png")
            light_beam_image = pygame.image.load(light_beam_image_path)
            screen.blit(light_beam_image, (420, 90))


            for event in events:
                if event.type == pygame.QUIT:
                    game_over = True
                    game_loop_running = False

                manager.process_events(event)

                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN:
                        if intentos > 0:
                            try:
                                angulo_adivinado = int(text_input.get_text())
                                if abs(angulo_adivinado - angulo_refractado_real) <= error_margin:
                                    win = True
                                    game_loop_running = False
                                else:
                                    intentos -= 1
                                    if intentos == 0:
                                        restart_button.show()
                            except ValueError:
                                # El usuario ingresó un valor no válido
                                pass
                            text_input.set_text('')

                if event.type == pygame.USEREVENT:
                    if event.user_type == pygame_gui.UI_DROP_DOWN_MENU_CHANGED:
                        # Mostrar u ocultar campos de índice de refracción personalizado según la selección del menú desplegable
                        if event.ui_element == medium_dropdown:
                            if medium_dropdown.selected_option == "Personalizado":
                                custom_medium_label.show()
                                custom_medium_entry.show()
                            else:
                                custom_medium_label.hide()
                                custom_medium_entry.hide()
                        elif event.ui_element == glass_type_dropdown:
                            if glass_type_dropdown.selected_option == "Personalizado":
                                custom_glass_label.show()
                                custom_glass_entry.show()
                            else:
                                custom_glass_label.hide()
                                custom_glass_entry.hide()

                    if event.user_type == pygame_gui.UI_BUTTON_PRESSED:
                        if event.ui_element == restart_button:
                            # Reiniciar el juego sin llamar a game_loop() recursivamente
                            game_loop_running = False

            manager.update(time_delta)

            # Actualizar el índice de refracción del medio seleccionado
            if medium_dropdown.selected_option == "Personalizado":
                try:
                    n1 = float(custom_medium_entry.get_text())
                except ValueError:
                    # El usuario ingresó un valor no válido
                    pass
            else:
                n1 = mediums[medium_dropdown.selected_option]

            # Actualizar el índice de refracción del vidrio seleccionado
            if glass_type_dropdown.selected_option == "Personalizado":
                try:
                    n2 = float(custom_glass_entry.get_text())
                except ValueError:
                    # El usuario ingresó un valor no válido
                    pass
            else:
                n2 = glass_types[glass_type_dropdown.selected_option]

            # Recalcular el ángulo refractado
            angulo_refractado_real = ley_snell(n1, n2, angulo_incidente)

            # Actualizar la interfaz
            texto = font.render("La luz pasa del medio (n1={:.2f}) al vidrio (n2={:.2f}).".format(n1, n2), True, BLACK)
            screen.blit(texto, (20, 20))

            texto = font.render(f"Ángulo de incidencia: {angulo_incidente} grados", True, BLACK)
            screen.blit(texto, (20, 60))

            texto = font.render(f"Intentos restantes: {intentos}", True, BLACK)
            screen.blit(texto, (20, 100))

            if win:
                texto = font.render(f"¡Felicidades! Has adivinado el ángulo de refracción. El ángulo real es {angulo_refractado_real:.2f} grados.", True, BLACK)
                screen.blit(texto, (20, 140))
                restart_button.show()
            elif intentos == 0:
                texto = font.render(f"Has perdido. El ángulo de refracción real era {angulo_refractado_real:.2f} grados.", True, BLACK)
                screen.blit(texto, (20, 140))

            manager.draw_ui(screen)
            pygame.display.flip()

game_loop()
pygame.quit()

About

A Python game demonstrating light refraction across different materials

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages