-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.py
97 lines (82 loc) · 3.13 KB
/
client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# = Client Singleton ==========================================================
"""
The Client class is a singleton and must be accessed via the get_client
function. The client object represents the interface through which the player
interacts with the game. It is implemented as a hierarchy of driver objects,
each of which manages a different mode of gameplay. The central client handles
the routing of commands and delegates drawing to the sub-drivers.
The curses library is used extensively for both input and output.
"""
# - Dependencies ---------------------------------
# Python Modules
import threading
import curses
# Local Modules
from config import *
from bindings import KEY_BINDINGS
from driver import Driver
from driver_title import Title
# - Client access function -----------------------
client = None
def get_client(*arguments):
"""
Retrieves the client singleton.
The Client class should not be instanced directly.
"""
global client
# Generate a client if necessary
if(client is None and arguments[0]):
client = Client(arguments[0])
# Return the client
return client
# - Definition and initialization ----------------
class Client(Driver):
"""
The Client class is a singleton and should be accessed via the get_client
function. The client object manages all input and output via the curses
library. The client is implemented as a hierarchy of "driver" objects, each
managing input and output for a distinct aspect of gameplay.
"""
def __init__(self, screen):
super().__init__()
self.key_command = None
self.last_command = None
# Show Title
self.focus(Title())
# Setup Input Thread
self.finished = threading.Event()
def input_loop(screen):
while(True):
# Get character code from player
key_code = screen.getch()
# Handle "quit" code (Ctrl+C)
if(key_code is WINDOWS_INTERRUPT):
self.finished.set()
# Translate code into Command, and execute
self.last_command = chr(key_code)
if(key_code in KEY_BINDINGS):
self.command(KEY_BINDINGS[key_code])
thread_input = threading.Thread(
target=input_loop,
name="Input Loop",
daemon=True,
args=(screen,))
thread_input.start()
# - Keyboard handling ----------------------------
def command(self, which):
"""Routes player commands to the appropriate sub-driver."""
self.key_command = which
return super().command(which)
def key_clear(self):
"""Clears all pressed keys so commands don't recur."""
self.key_command = None
# - Display --------------------------------------
def display(self, screen, *args):
"""Clears the screen delegates drawing to the focused sub-driver."""
screen.clear()
# Do own drawing first, then draw children on top
# Draw Children
result = super().display(screen, *args)
# Write buffer to screen
screen.refresh()
return result