#!/usr/bin/env python3 from numba import jit from time import time_ns, sleep from cmath import exp, pi from math import acos import pygame import pygame.freetype from gyro import * from lines import * def deg2rad(rA): return rA/180*PI I = complex(0,1) WHITE = (255,255,255) BLACK = (0,0,0) OFFSET = 0.015625 PI = pi ROT = cNorm(exp(deg2rad(2)*I)) IROT = 1/ROT F = 5 * 10**7 F_ = 10**9 bCap = True gOrigin = GyroVector(0,1) SKY = (127,127,255) GROUND = (102, 51, 0) class Segment: def __init__(self,bA,cA,cB,trColor): self.isFinite = bA self.pointA = cA self.pointB = cB self.color = trColor class DrawnSegment: def __init__(self,height,color): self.height = height self.color = color level = [ Segment(True,.6,I*.6,(255,0,0)), Segment(True,.6,-I*.6,(0,255,0)), Segment(True,-.6,-I*.6,(0,0,255)), Segment(True,-.6,I*.6,(255,255,0)) ] def draw(level,gPlayer,fov,res): drawn = list() irot = exp(fov/res*I) iprot = gPlayer.cRot for i in range(res): m = DrawnSegment(0,BLACK) rot = irot**(i-(res/2)) * iprot for j in level: try: # Function "LineIntersection" faults from time to time cInt = MobiusInt(j.pointA,j.pointB,gPlayer.cPos,rot) except ZeroDivisionError: continue if cDot(rot,MobiusAdd(cInt,-gPlayer.cPos)) > 0: continue rDist = MobiusDist(cInt,gPlayer.cPos)*1.1 if not (j.isFinite and cBetween(j.pointA,j.pointB,cInt)): continue if (1 - m.height) > rDist: m = DrawnSegment(1-rDist,j.color) drawn.append(m) return drawn def cap(rN): if rN < 0: return 0 return rN 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(acos(gPlayer.cRot.real) / pi * 180), font_fg, font_bg)[0] return fps_surf, cPos_surf, cRot_surf def make_wall(wall_buffer): if (len(wall_buffer) != 2): print('Warning: wall buffer not contains 2 points.') return level.append( Segment(True, wall_buffer[0], wall_buffer[1], (23,74,183)) ) def mainLoop(): gPlayer = GyroVector(0,1) display = pygame.display.set_mode((1280,720)) clock = pygame.time.Clock() fontSize = 18 debugInfo = True wall_buffer = [] while True: for event in pygame.event.get(): if event.type == pygame.QUIT: return True if event.type == pygame.KEYDOWN: if event.key == pygame.K_r: gPlayer.cRot *= -1 if event.key == pygame.K_F3: debugInfo = not debugInfo if event.key == pygame.K_F1: global bCap bCap = not bCap if event.key == pygame.K_F2: if (len(wall_buffer) == 1): wall_buffer.append(gPlayer.cPos) make_wall(wall_buffer) wall_buffer.clear() else: wall_buffer.append(gPlayer.cPos) keys = pygame.key.get_pressed() if keys[pygame.K_d]: gPlayer.rotate(ROT) if keys[pygame.K_a]: gPlayer.rotate(IROT) if keys[pygame.K_q]: gPlayer += GyroVector(OFFSET * gPlayer.cRot*I, 1) if keys[pygame.K_e]: gPlayer -= GyroVector(OFFSET * gPlayer.cRot*I, 1) if keys[pygame.K_w]: gPlayer -= GyroVector(OFFSET * gPlayer.cRot, 1) if keys[pygame.K_s]: gPlayer += GyroVector(OFFSET * gPlayer.cRot, 1) 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((1 - cap(i.height)) * 360),8,int(cap(i.height) * 1280))) n += 4 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.rect(display, BLACK, (0, 100, 200, 200)) for i in level: a = complex(Poincare2Klein(i.pointA)) b = complex(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)) 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")