Files
2020-07-29 12:59:12 +02:00

657 lines
20 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from .context import Context
from pygame.locals import *
import pygame
class SimpleManager:
"""Manage a program using the context by many having functions that can be
overloaded to make simple and fast programs.
This process allow the user to think directly about what the program does,
instead of focusing on how to display things.
The way it works is by making the main class of the program inheriting from
this one."""
def __init__(self, name="SimpleManager", **kwargs):
"""Create a context manager with the optional name."""
self.context = Context(name=name, **kwargs)
self.pause = False
def __call__(self):
"""Call the main loop."""
while self.context.open:
self.events()
if not self.pause:
self.update()
self.show()
def events(self):
"""Deal with all the events."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.context.open = False
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
self.context.open = False
if event.key == K_SPACE:
self.pause = not (self.pause)
if event.key == K_f:
self.context.switch() # Set or reverse fullscreen
if event.type == MOUSEBUTTONDOWN:
if event.button == 4:
self.context.draw.plane.zoom([1.1, 1.1])
if event.button == 5:
self.context.draw.plane.zoom([0.9, 0.9])
def update(self):
"""Update the context manager."""
def show(self):
"""Show the context manager."""
self.context.refresh()
self.context.control()
self.context.flip()
class oldManager: # This manager is deprecated
"""Manage a program using the context by many having functions that can be
overloaded to make simple and fast programs.
This process allow the user to think directly about what the program does,
instead of focusing on how to display things.
The way it works is by making the main class of the program inheriting from
this one."""
def __init__(self, context):
"""Create a context manager."""
self.context = context
def __call__(self):
"""Call the main loop."""
self.main()
def main(self):
"""Execute the main loop."""
self.loop()
def loop(self):
"""Main loop."""
while self.context.open:
self.perform()
def perform(self):
"""Execute the content of the main loop."""
self.detect()
self.update()
self.show()
def debug(self):
self.context.console(str(ContextManager.__dict__['react'].__dict__))
def update(self):
"""Update the context manager."""
pass
def show(self):
"""Show the context manager."""
self.context.refresh()
self.context.control()
self.debug()
self.context.flip()
def detect(self):
"""Deal with all the events."""
for event in pygame.event.get():
self.react(event)
def react(self, event):
"""React to a given event."""
self.reactToQuit(event)
if event.type == KEYDOWN:
self.reactToKeyboard(event)
return
def reactToQuit(self, event):
"""Close the context if the quit button is pressed."""
if event.type == pygame.QUIT:
self.context.open = False
def reactToKeyboard(self):
"""React to the keyboards buttons being pressed."""
self.reactToEscape()
def reactToEscape(self):
"""React to the button escape."""
if event.key == K_ESCAPE:
self.context.open = False
class Manager:
def __init__(self, name="Manager", dt=10e-3, **kwargs):
"""Create a manager using a context, this methods it to be overloaded."""
self.context = Context(name=name, **kwargs)
self.count = self.context.count
self.pause = False
self.dt = dt
# Typing stuff
self.typing = False
self.alphabet = "abcdefghijklmnopqrstuvwxyz"
self.caps_numbers = ")!@#$%^&*("
self.numbers = "0123456789"
self.typing = False
self.shiftlock = False
self.capslock = False
self.altlock = False
def __str__(self):
"""Return the string representation of the manager."""
return type(self).__name__ + "(\n{}\n)".format(
"\n".join(map(lambda x: ":".join(map(str, x)), self.__dict__.items())))
def __call__(self):
"""Call the main loop, this method is to be overloaded."""
self.main()
def main(self):
"""Main loop of the simple manager."""
self.setup() # Name choices inspired from processing
while self.context.open:
self.loop()
def setup(self):
"""Code executed before the loop."""
pass
def loop(self):
"""Code executed during the loop."""
self.eventsLoop()
self.updateLoop()
self.showLoop()
def eventsLoop(self):
"""Deal with the events in the loop."""
for event in pygame.event.get():
self.react(event)
def react(self, event):
"""React to the pygame events."""
if event.type == QUIT:
self.switchQuit()
elif event.type == KEYDOWN:
self.reactKeyDown(event.key)
elif event.type == KEYUP:
self.reactKeyUp(event.key)
elif event.type == MOUSEBUTTONDOWN:
self.reactMouseButtonDown(event.button, event.pos)
elif event.type == MOUSEBUTTONUP:
self.reactMouseButtonUp(event.button, event.pos)
elif event.type == MOUSEMOTION:
self.reactMouseMotion(event.pos)
def switchQuit(self):
"""React to a quit event."""
self.context.open = not (self.context.open)
def reactKeyDown(self, key):
"""React to a keydown event."""
self.reactAlways(key)
if self.typing:
self.reactTyping(key)
else:
self.reactMain(key)
def reactKeyUp(self, key):
"""React to a keyup event."""
pass
def reactAlways(self, key):
"""React to a key whether or not the typing mode is on."""
# print(key) for debugging the keys
if key == K_ESCAPE:
self.switchQuit()
if key == K_SLASH or key == K_BACKSLASH:
if not self.typing:
self.context.console("Typing activated.")
self.typing = True
if key == K_BACKQUOTE:
self.switchTyping()
def reactLock(self, key):
"""React to a locking key."""
if key == K_CAPSLOCK:
self.capslock = not (self.capslock)
elif key == K_LSHIFT or key == K_RSHIFT:
self.shiftlock = True
elif key == K_LALT or key == K_RALT:
self.altlock = True
def reactTyping(self, key):
"""React to a typing event."""
self.reactLock(key)
if self.altlock:
self.reactAltCase(key)
elif self.capslock or self.shiftlock:
self.reactUpperCase(key)
else:
self.reactLowerCase(key)
if key == K_SPACE:
self.write(" ")
elif key == 8:
self.delete()
if key == K_LCTRL:
self.context.console.nextArg()
elif key == K_UP:
self.context.console.back()
elif key == K_DOWN:
self.context.console.forward()
elif key == K_RETURN:
self.eval()
self.context.console.nextLine()
def eval(self):
"""Execute a line."""
content = self.context.console.line.content
if content[0] == "/":
for command in content[1:]:
try:
self.context.console(str(eval(command)))
except:
self.context.console("Invalid command.")
if content[0] == "\\":
for command in content[1:]:
try:
exec(command)
self.context.console("Command " + command + " executed.")
except Exception as e:
self.context.console(str(e))
self.context.console.eval()
def reactAltCase(self, key):
"""React when typing with alt key pressed."""
if key == K_e:
self.write("`") # Stupid
elif key == 167:
self.write("´")
def reactLowerCase(self, key):
"""React when typing in lower case."""
d = {K_COMMA: ",", K_PERIOD: ".", K_SEMICOLON: ";", K_LEFTBRACKET: "[",
K_RIGHTBRACKET: "]", 39: "'", 45: "-", K_EQUALS: "="}
if 48 <= key <= 57:
self.write(self.numbers[key - 48])
elif 97 <= key <= 122:
self.write(self.alphabet[key - 97])
elif key in d:
self.write(d[key])
elif key == K_SLASH:
if not self.context.console.line.empty:
self.context.console.nextLine()
self.write("/")
self.context.console.nextArg()
elif key == K_BACKSLASH:
if not self.context.console.line.empty:
self.context.console.nextLine()
self.write("\\")
self.context.console.nextArg()
def reactUpperCase(self, key):
"""React to a key when typing in uppercase."""
d = {59: ":''", 44: "<", 46: ">", 47: "?",
45: "_", 39: "\"", 61: "+"}
if 48 <= key <= 57:
self.write(self.caps_numbers[key - 48])
elif 97 <= key <= 122:
self.write(self.alphabet[key - 97].upper())
elif key in d:
self.write(d[key])
def write(self, c):
"""Write some content."""
self.context.console.lines[-1].content[-1] += c
self.context.console.lines[-1].refresh()
self.shiftlock = False
self.altlock = False
def delete(self, n=1):
"""Delete some content."""
self.context.console.lines[-1].content[-1] = self.context.console.lines[-1].content[-1][:-n]
self.context.console.lines[-1].refresh()
def reactMain(self, key):
"""React as usual when not typing."""
if key == K_f:
self.switchFullscreen()
if key == K_1:
self.switchCapture()
if key == K_2:
self.switchCaptureWriting()
if key == K_3:
self.switchScreenWriting()
if key == K_LALT:
self.switchPause()
def switchTyping(self):
"""Switch the typing mode."""
self.typing = not (self.typing)
if self.typing:
self.context.console("Typing activated.")
self.context.console.nextLine()
else:
self.context.console("Typing deactivated.")
def switchScreenWriting(self):
"""Switch the screen writing mode."""
if self.context.camera.screen_writing:
self.context.camera.screen_writer.release()
self.context.camera.switchScreenWriting()
if self.context.camera.screen_writing:
self.context.console('The screen is being written.')
else:
self.context.console('The screen video has been released')
self.context.console('and is not being written anymore.')
def switchCaptureWriting(self):
"""Switch the capture writing mode."""
if self.context.camera.capture_writing:
self.context.camera.capture_writer.release()
self.context.camera.switchCaptureWriting()
if self.context.camera.capture_writing:
self.context.console('The capture is being written.')
else:
self.context.console('The capture video has been released')
self.context.console('and is not being written anymore.')
def switchPause(self):
"""React to a pause event."""
self.pause = not self.pause
if self.pause:
self.context.console('The system is paused.')
else:
self.context.console('The system is unpaused.')
def switchCapture(self):
"""React to a capture event."""
self.context.camera.switchCapture()
if self.context.camera.capturing:
self.context.console('The camera capture is turned on.')
else:
self.context.console('The camera capture is turned off.')
def switchFullscreen(self):
"""React to a fullscreen event."""
self.context.switch()
if self.context.fullscreen:
self.context.console("The fullscreen mode is set.")
else:
self.context.console("The fullscreen mode is unset.")
def reactMouseButtonDown(self, button, position):
"""React to a mouse button down event."""
if button == 4:
self.context.draw.plane.zoom([1.1, 1.1])
if button == 5:
self.context.draw.plane.zoom([0.9, 0.9])
def reactMouseButtonUp(self, button, position):
"""React to a mouse button up event."""
pass
def reactMouseMotion(self, position):
"""React to a mouse motion event."""
pass
def updateLoop(self):
"""Update the manager while in the loop."""
if not self.pause:
self.update()
self.count()
self.context.camera.write() # Write on the camera writers if they are on
def update(self):
"""Update the components of the manager of the loop. This method is to be
overloaded."""
pass
def showLoop(self):
"""Show the graphical components and deal with the context in the loop."""
if not self.typing: # Ugly fix for easier pratical use
self.context.control()
self.context.clear()
self.context.show()
self.show()
self.showCamera()
self.context.console.show()
self.context.flip()
def show(self):
"""Show the graphical components on the context. This method is to be
overloaded."""
pass
def showCamera(self):
"""Show the camera if active."""
if self.context.camera.capturing:
self.context.camera.show()
def counter():
doc = "The Counter property."
def fget(self):
"""Bind the counter of the manager to the one of the context."""
return self.context.counter
def fset(self, counter):
"""Set the counter of the context."""
self.context.counter = counter
return locals()
counter = property(**counter())
class BodyManager(Manager):
"""Manage the bodies that are given when initalizing the object."""
@classmethod
def createRandomBodies(cls, t, n=5, **kwargs):
"""Create random bodies using their class t.
The bodies of the class t must have a random method."""
bodies = [t.random() for i in range(n)]
return cls(bodies, **kwargs)
def __init__(self, *bodies, following=False, **kwargs):
"""Create a body manager using its bodies and optional arguments for the context."""
super().__init__(**kwargs)
self.bodies = bodies
self.following = following
def update(self):
"""Update the bodies."""
self.updateFollowers()
self.updateBodies()
def updateFollowers(self):
"""Update the bodies that are followers."""
# This is not implemented correctly for now."""
p = self.context.point()
if self.following:
for body in self.bodies:
body.follow(p)
def updateBodies(self):
"""Update the bodies individually."""
for body in self.bodies:
body.update(self.dt)
def show(self):
"""Show the bodies."""
self.showBodies()
def showBodies(self):
"""Show all the bodies individually."""
for body in self.bodies:
body.show(self.context)
class EntityManager(Manager):
"""Create a manager that deals with entities."""
def __init__(self, *entities, dt=0.1, friction=0.1, **kwargs):
"""Create an entity manager using the list of entities and optional
arguments for the manager."""
super().__init__(**kwargs)
self.entities = list(entities)
self.dt = dt
self.friction = friction
def update(self):
"""Update all entities."""
for entity in self.entities:
entity.update(self.dt)
def show(self):
"""Show all entities."""
for entity in self.entities:
entity.show(self.context)
def reactKeyDown(self, key):
"""Make all entities react to the keydown event."""
super().reactKeyDown(key)
for entity in self.entities:
entity.reactKeyDown(key)
def reactMouseMotion(self, position):
"""Make all entities react to the mouse motion."""
position = self.context.getFromScreen(tuple(position))
for entity in self.entities:
entity.reactMouseMotion(position)
def reactMouseButtonDown(self, button, position):
"""Make all entities react to the mouse button down event."""
position = self.context.getFromScreen(tuple(position))
for entity in self.entities:
entity.reactMouseButtonDown(button, position)
def spread(self, n=10):
"""Spread randomly the bodies."""
for entity in self.entities:
entity.motion *= n
def setFriction(self, friction):
"""Set the friction of all entities to the given friction."""
for entity in self.entities:
entity.setFriction(friction)
class BlindManager(Manager):
"""Ugly way to make a manager without camera."""
def __init__(self, camera=False, **kwargs):
super().__init__(camera=camera, **kwargs)
class AbstractManager(Manager):
"""Manager that deals with abstract objects."""
def __init__(self, *group, **kwargs):
"""Create a group of abstract (geometrical) objects."""
super().__init__(**kwargs)
self.group = list(group)
def show(self):
"""Show the objects of the group."""
for e in self.group:
e.show(self.context)
class GameManager(Manager):
"""Base class Manager for games."""
def __init__(self, game, controller=None, **kwargs):
super().__init__(**kwargs)
self.game = game
self.controller = controller
self.context.units = [10, 10]
def update(self):
if self.controller:
player = self.getPlayer()
if player and not self.game.won:
self.context.position = player.position
self.game.update()
def showLoop(self):
"""Show the graphical components and deal with the context in the loop."""
if not self.typing: # Ugly fix for easier practical use
# self.context.control()
pass
if self.game.won:
self.context.control()
self.context.clear()
self.show()
self.showCamera()
self.context.console.show()
self.context.flip()
def show(self):
self.game.show(self.context)
def reactKeyDown(self, key):
super().reactKeyDown(key)
self.game.reactKeyDown(key)
def reactMouseMotion(self, position):
position = self.context.getFromScreen(position)
self.game.reactMouseMotion(position)
def reactMouseButtonDown(self, button, position):
position = self.context.getFromScreen(position)
self.game.reactMouseButtonDown(button, position)
def getPlayer(self):
return self.game.control(self.controller)
class ActivityManager(Manager):
"""Activity manager inspired from android studio"""
def __init__(self, activities, **kwargs):
super().__init__(**kwargs)
self.activities = activities
self.index = 0
def show(self):
self.activity.show(self.context)
def update(self):
self.activity.update(self.dt)
def reactKeyUp(self, key):
self.activity.onKeyUp(key)
def reactKeyDown(self, key):
self.activity.onKeyDown(key)
def reactMouseButtonDown(self, button, position):
position = self.context.getFromScreen(position)
self.activity.onMouseButtonDown(button, position)
def reactMouseMotion(self, position):
position = self.context.getFromScreen(position)
self.activity.onMouseMotion(position)
def getActivity(self):
return self.activities[self.index]
def setActivity(self, activity):
self.activities[self.index] = activity
activity = property(getActivity, setActivity)
if __name__ == "__main__":
from .entity import Entity
m = EntityManager.random(build=False)
print(m)
# cm()