Compare commits

..

No commits in common. "eb6b4b987c65c2d171578650d9fbd5867b4089af" and "dfb6594ec599e212c5d34fcc3cecbebe93a7b8f7" have entirely different histories.

10 changed files with 67 additions and 218 deletions

View File

@ -2,29 +2,25 @@
My school project My school project
## Loading games ## Load levels
You can load a game by passing the name of the game as an argument: You can load a level by pass the path to the level as an argument, see example:
```sh ```sh
python3 main.py triangle python3 main.py maps/triangle.json
``` ```
Game can be loaded only if it is located in the games/ directory. ## Controls
If no game is specified then "squareroom" will be loaded.
## Controls (might be overriden by games)
| Descripton | Key | | Descripton | Key |
|----------------------------------------|:---:| |------------------------------------|:---:|
| Move forward | W | | Move forwards | W |
| Move backwards | D | | Move backwards | D |
| Strafe left | Q | | Strafe left | Q |
| Strafe right | E | | Strafe right | E |
| Turn 180 degrees | R | | Turn exactly 180 degrees | R |
| Toggle FPS cap | F1 | | Toggle FPS cap | F1 |
| Create a wall | F2 | | Create a wall | F2 |
| Toggle debug info | F3 | | Toggle debug info | F3 |
| Print current position to the terminal | F4 | | Print to terminal current position | F4 |
| Save level to `./levels` folder | F5 | | Save level to `./levels` folder | F5 |

View File

@ -1,57 +0,0 @@
import pygame
from engineevents import EngineEvent
from constants import ROT, IROT, OFFSET, I
from gyro import GyroVector
from levels import open_level, save_level, make_wall
from alert import Alert
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

View File

@ -22,7 +22,7 @@ class DrawnSegment:
self.color = color self.color = color
@jit#(cache=True,parallel=True) @jit#(cache=True,parallel=True)
def draw(level,gPlayer,fov,res,dscale): def draw(level,gPlayer,fov,res):
EMPTYDRAWN = DrawnSegment(0, BLACK) EMPTYDRAWN = DrawnSegment(0, BLACK)
drawn = [EMPTYDRAWN] * res drawn = [EMPTYDRAWN] * res
irot = exp(fov/res*I) irot = exp(fov/res*I)
@ -37,7 +37,7 @@ def draw(level,gPlayer,fov,res,dscale):
continue continue
if cDot(rot,MobiusAdd(cInt,-gPlayer.cPos)) > 0: if cDot(rot,MobiusAdd(cInt,-gPlayer.cPos)) > 0:
continue continue
rDist = MobiusDist(cInt,gPlayer.cPos) * dscale rDist = MobiusDist(cInt,gPlayer.cPos)*1.1
if j.isFinite and not cBetween(Poincare2Klein(j.pointA),Poincare2Klein(j.pointB),Poincare2Klein(cInt)): if j.isFinite and not cBetween(Poincare2Klein(j.pointA),Poincare2Klein(j.pointB),Poincare2Klein(cInt)):
continue continue
if m is None: if m is None:

View File

@ -1,11 +0,0 @@
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,)
class EngineEventProcessingError(Exception):
pass

View File

@ -1,4 +0,0 @@
from engineevents import EngineEvent
def init(aoEngineEvents):
aoEngineEvents.append(EngineEvent('level', lambda _: []))

View File

@ -1,17 +0,0 @@
import importlib.resources as impr
import sys
import json
import serialize
from engineevents import EngineEvent
def init(aoEngineEvents):
curm = sys.modules[__name__]
files = impr.files(curm)
level = None
with files.joinpath("squareroom.json").open('r') as leveldir:
level = json.loads(leveldir.read(), object_hook=serialize.object_hook)
aoEngineEvents.append(EngineEvent(
'level',
lambda _: level,
tsArguments=()
))

View File

@ -1 +0,0 @@
[{"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": 0.6, "imag": 0.0}, "pointB": {"__type__": "complex", "real": 0.0, "imag": 0.6}, "color": [255, 0, 0]}, {"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": 0.6, "imag": 0.0}, "pointB": {"__type__": "complex", "real": 0.0, "imag": -0.6}, "color": [0, 255, 0]}, {"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": -0.6, "imag": 0.0}, "pointB": {"__type__": "complex", "real": 0.0, "imag": -0.6}, "color": [0, 0, 255]}, {"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": -0.6, "imag": 0.0}, "pointB": {"__type__": "complex", "real": 0.0, "imag": 0.6}, "color": [255, 255, 0]}]

View File

@ -1,17 +0,0 @@
import importlib.resources as impr
import sys
import json
import serialize
from engineevents import EngineEvent
def init(aoEngineEvents):
curm = sys.modules[__name__]
files = impr.files(curm)
level = None
with files.joinpath("triangle.json").open('r') as leveldir:
level = json.loads(leveldir.read(), object_hook=serialize.object_hook)
aoEngineEvents.append(EngineEvent(
'level',
lambda _: level,
tsArguments=()
))

View File

@ -1 +0,0 @@
[{"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": 0.38529100476842437, "imag": 0.0}, "pointB": {"__type__": "complex", "real": -0.2372040619364459, "imag": 0.36629343026935063}, "color": [255, 0, 0]}, {"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": -0.2372040619364459, "imag": 0.36629343026935063}, "pointB": {"__type__": "complex", "real": -0.22354939429564802, "imag": -0.26820653903460523}, "color": [0, 255, 0]}, {"__type__": "objSegment", "isFinite": true, "pointA": {"__type__": "complex", "real": -0.22354939429564802, "imag": -0.26820653903460523}, "pointB": {"__type__": "complex", "real": 0.39868528559672944, "imag": 0.017873216691274733}, "color": [0, 0, 255]}]

137
main.py
View File

@ -2,21 +2,20 @@
from math import copysign, pi, acos from math import copysign, pi, acos
import sys import sys
import os
from importlib import import_module
import pygame import pygame
import pygame.freetype import pygame.freetype
from gyro import GyroVector, Poincare2Klein from gyro import GyroVector, Poincare2Klein
from levels import open_level, save_level, make_wall
from constants import I, WHITE, BLACK, IROT, ROT, OFFSET from constants import I, WHITE, BLACK, IROT, ROT, OFFSET
from draw import draw, DrawnSegment from draw import draw
from alert import Alert from alert import Alert
from engineevents import EngineEvent, EngineEventProcessingError
from defaultcontrols import defaultcontrols
gOrigin = GyroVector(0,1) gOrigin = GyroVector(0,1)
SKY = (127,127,255)
GROUND = (102, 51, 0)
def renderDebugInfo(gPlayer, clock, fontSize = 18): def renderDebugInfo(gPlayer, clock, fontSize = 18):
font = pygame.freetype.Font(None, fontSize) font = pygame.freetype.Font(None, fontSize)
@ -33,11 +32,7 @@ def nonzerocap(n):
if n <= 0: return 1 if n <= 0: return 1
return n return n
def mainLoop(): def mainLoop():
sky = (127,127,255)
ground = (102, 51, 0)
bCap = True bCap = True
bCont = True bCont = True
gPlayer = GyroVector(0,1) gPlayer = GyroVector(0,1)
@ -47,10 +42,6 @@ def mainLoop():
debugInfo = True debugInfo = True
wall_buffer = [] wall_buffer = []
alerts = [] alerts = []
aoEngineEvents = []
fvControl_ao = defaultcontrols
level = []
iDistScale = 1.1
def alert_append(alert, delay): def alert_append(alert, delay):
if len(alerts) >= 1: if len(alerts) >= 1:
@ -59,87 +50,58 @@ def mainLoop():
alerts.append(alert) alerts.append(alert)
alert.start_hide_thread(alerts, delay) alert.start_hide_thread(alerts, delay)
def processevents():
nonlocal bCap
nonlocal bCont
nonlocal gPlayer
nonlocal display
nonlocal fontSize
nonlocal debugInfo
nonlocal wall_buffer
nonlocal alerts
nonlocal alert_append
nonlocal aoEngineEvents
nonlocal level
nonlocal sky
nonlocal ground
nonlocal iDistScale
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,
'sky': sky,
'ground': ground,
'iDistScale': iDistScale
}
for i in aoEngineEvents:
if i.sVariableToModify == "bCap":
bCap = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "bCont":
bCont = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "gPlayer":
gPlayer = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "fontSize":
fontSize = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "wall_buffer":
wall_buffer = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "alerts":
alerts = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "sky":
sky = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "ground":
ground = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "debugInfo":
debugInfo = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "level":
level = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify == "iDistScale":
iDistScale = i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
elif i.sVariableToModify is None:
i.fLambda(list(map(lambda oX: state[oX], i.tsArguments)))
else:
raise EngineEventProcessingError('Unknown variable: ' + i.sVariableToModify)
aoEngineEvents.clear()
try: try:
game = import_module('games.' + sys.argv[1]) level = open_level(sys.argv[1])
except IndexError: except IndexError:
game = import_module("games.squareroom") level = open_level("maps/squareroom.json")
game.init(aoEngineEvents)
processevents()
while bCont: while bCont:
aoEngineEvents = fvControl_ao() for event in pygame.event.get():
processevents() if event.type == pygame.QUIT:
display.fill(WHITE) bCont = False
if len(level) != 0: if event.type == pygame.KEYDOWN:
drawn = draw(level,gPlayer,pi/4,320,iDistScale) if event.key == pygame.K_r:
gPlayer.cRot *= -1
if event.key == pygame.K_F3:
debugInfo = not debugInfo
if event.key == pygame.K_F1:
bCap = not bCap
if event.key == pygame.K_F2:
if (len(wall_buffer) == 1):
wall_buffer.append(gPlayer.cPos)
make_wall(wall_buffer, level)
wall_buffer.clear()
else: else:
drawn = [DrawnSegment(0, BLACK)] * 320 wall_buffer.append(gPlayer.cPos)
pygame.draw.rect(display,sky, (0,0,1280,360)) if event.key == pygame.K_F5:
pygame.draw.rect(display,ground, (0,360,1280,360)) filename = save_level(level)
alert = Alert(f"File saved as {filename}", display)
alert_append(alert, 5)
if event.key == pygame.K_F4:
print(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 n = 0
for i in drawn: for i in drawn:
pygame.draw.rect(display,i.color, (n,int((nonzerocap(i.dist)) * 360),4,int((1 -nonzerocap(i.dist)) * 1280))) pygame.draw.rect(display,i.color, (n,int((nonzerocap(i.dist)) * 360),8,int((1 -nonzerocap(i.dist)) * 1280)))
n += 4 n += 4
gPlayer.normalize() gPlayer.normalize()
if debugInfo: if debugInfo:
@ -175,6 +137,5 @@ def main():
return retstatus return retstatus
if __name__ == "__main__": if __name__ == "__main__":
sys.path.append(os.path.realpath(__file__))
if not main(): if not main():
print("An error occured") print("An error occured")