#!/usr/bin/env python3 from math import copysign, pi, acos import sys import pygame import pygame.freetype from gyro import GyroVector, Poincare2Klein from levels import open_level, save_level, make_wall from constants import I, WHITE, BLACK, IROT, ROT, OFFSET from draw import draw from alert import Alert gOrigin = GyroVector(0,1) SKY = (127,127,255) GROUND = (102, 51, 0) def renderDebugInfo(gPlayer, clock, fontSize = 18): font = pygame.freetype.Font(None, fontSize) font_fg = (255, 255, 255) font_bg = (255, 255, 255, 80) fps_surf = font.render("FPS: " + str(int(clock.get_fps())), font_fg, font_bg)[0] cPos_surf = font.render("cPos: " + str(gPlayer.cPos), font_fg, font_bg)[0] cRot_surf = font.render("cRot: " + str(copysign(acos(gPlayer.cRot.real),gPlayer.cRot.imag) / pi * 180), font_fg, font_bg)[0] return fps_surf, cPos_surf, cRot_surf def nonzerocap(n): if n <= 0: return 1 return n class EngineEvent: def __init__(self, sVariableToModify, fLambda, tsArguments=None): self.sVariableToModify = sVariableToModify self.fLambda = fLambda if tsArguments is not None: self.tsArguments = tsArguments else: self.tsArguments = (sVariableToModify,) def defaultcontrols(): aoEngineEvents = list() for event in pygame.event.get(): if event.type == pygame.QUIT: aoEngineEvents.append(EngineEvent("bCont", lambda _: False)) if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].rotate(-1), tsArguments=("gPlayer",))) if event.key == pygame.K_F3: aoEngineEvents.append(EngineEvent("debugInfo", lambda args: not args[0])) if event.key == pygame.K_F1: aoEngineEvents.append(EngineEvent("bCap", lambda args: not args[0])) if event.key == pygame.K_F2: def fX(args): #0: wall_buffer #1: gPlayer #2: level if (len(args[0]) == 1): args[0].append(args[1].cPos) make_wall(args[0], args[2]) args[0].clear() else: args[0].append(args[1].cPos) aoEngineEvents.append(EngineEvent(None, fX, tsArguments=("wall_buffer", "gPlayer", "level") )) if event.key == pygame.K_F5: #0: level #1: alert_append #2: display def fX(args): filename = save_level(args[0]) alert = Alert(f"File saved as {filename}", args[2]) args[1](alert, 5) aoEngineEvents.append(EngineEvent(None, fX, tsArguments=("level", "alert_append", "display") )) if event.key == pygame.K_F4: aoEngineEvents.append(EngineEvent(None, lambda args: print(args[0].cPos), tsArguments=("gPlayer",))) keys = pygame.key.get_pressed() if keys[pygame.K_d]: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].rotate( ROT), tsArguments=("gPlayer",))) if keys[pygame.K_a]: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].rotate(IROT), tsArguments=("gPlayer",))) if keys[pygame.K_q]: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].__iadd__(GyroVector(OFFSET * args[0].cRot*I, 1)), tsArguments=("gPlayer",))) if keys[pygame.K_e]: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].__isub__(GyroVector(OFFSET * args[0].cRot*I, 1)), tsArguments=("gPlayer",))) if keys[pygame.K_w]: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].__isub__(GyroVector(OFFSET * args[0].cRot , 1)), tsArguments=("gPlayer",))) if keys[pygame.K_s]: aoEngineEvents.append(EngineEvent(None, lambda args: args[0].__iadd__(GyroVector(OFFSET * args[0].cRot , 1)), tsArguments=("gPlayer",))) return aoEngineEvents def mainLoop(): bCap = True bCont = True gPlayer = GyroVector(0,1) display = pygame.display.set_mode((1280,720)) clock = pygame.time.Clock() fontSize = 18 debugInfo = True wall_buffer = [] alerts = [] aoEngineEvents = [] fvControl_ao = defaultcontrols def alert_append(alert, delay): if len(alerts) >= 1: alerts.pop() alerts.append(alert) alert.start_hide_thread(alerts, delay) try: level = open_level(sys.argv[1]) except IndexError: level = open_level("maps/squareroom.json") while bCont: aoEngineEvents = fvControl_ao() state = { 'bCap': bCap, 'bCont': bCont, 'gPlayer': gPlayer, 'display': display, 'fontSize': fontSize, 'debugInfo': debugInfo, 'wall_buffer': wall_buffer, 'alerts': alerts, 'alert_append': alert_append, 'aoEngineEvents': aoEngineEvents, 'level': level } for i in aoEngineEvents: if i.sVariableToModify == "bCont": bCont = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments))) if i.sVariableToModify == "debugInfo": debugInfo = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments))) if i.sVariableToModify == "gPlayer": gPlayer = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments))) if i.sVariableToModify == "bCap": bCap = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments))) if i.sVariableToModify is None: i.fLambda(list(map(lambda oX: state[oX], i.tsArguments))) display.fill(WHITE) drawn = draw(level,gPlayer,pi/4,320) pygame.draw.rect(display,SKY, (0,0,1280,360)) pygame.draw.rect(display,GROUND, (0,360,1280,360)) n = 0 for i in drawn: pygame.draw.rect(display,i.color, (n,int((nonzerocap(i.dist)) * 360),8,int((1 -nonzerocap(i.dist)) * 1280))) n += 4 gPlayer.normalize() if debugInfo: fps_surf, cPos_surf, cRot_surf = renderDebugInfo(gPlayer, clock, fontSize) display.blit(fps_surf, (0, 0)) display.blit(cPos_surf, (0, fps_surf.get_height())) display.blit(cRot_surf, (0, fps_surf.get_height() + fontSize)) pygame.draw.circle(display, BLACK, (100, 200), 100) for i in level: a = Poincare2Klein(i.pointA) b = Poincare2Klein(i.pointB) pygame.draw.line(display, i.color, (a.real * 100 + 100, (a.imag * 100 + 200)), (b.real * 100 + 100, (b.imag * 100 + 200))) c = complex(Poincare2Klein(gPlayer.cPos)) pygame.draw.rect(display, WHITE, (c.real * 100 + 95, (c.imag * 100 + 195), 10, 10)) for alert in alerts: alert.draw(display) pygame.display.update() if bCap: clock.tick(60) else: clock.tick() return True def main(): pygame.init() pygame.display.set_caption('P3HE') if not pygame.get_init(): return False retstatus = mainLoop() return retstatus if __name__ == "__main__": if not main(): print("An error occured")