Sound pulse caught, better docs
parent
92226732c8
commit
d6b422be3c
13
README.md
13
README.md
|
@ -23,6 +23,10 @@ With these installed we're prep'ed & ready!
|
|||
|
||||
## 2. Game usage & capabilities ##
|
||||
|
||||
There are two options to run the game:
|
||||
|
||||

|
||||
|
||||
### 2.1 Local gameplay ###
|
||||
|
||||
Run the game fullscreen locally like:
|
||||
|
@ -51,6 +55,9 @@ Then to run a game server instance use
|
|||
|
||||
#### On a gameserver: Make sure, inbound TCP & UDP traffic to port 5050 is not blocked by your firewall or router! ####
|
||||
|
||||
* To connect a player successfully, make sure the server is up & ready (past splash screen ...).
|
||||
* Also, don't start players simultaneously (either one may fail to connect - try again ... ;).
|
||||
|
||||
To connect player #1, use
|
||||
|
||||
./cl1.sh
|
||||
|
@ -108,8 +115,8 @@ After some 2-5s this effect will disappear. Currently, there is no clean initial
|
|||
|
||||
## 4. Outlook ##
|
||||
|
||||
Streaming synchronization needs improvement.
|
||||
* Streaming synchronization needs improvement.
|
||||
|
||||
Sounds sometimes get lost, need to work on this one ...
|
||||
* Maybe HTTP streaming shall be moved to raw TCP streaming ...
|
||||
|
||||
Maybe, HTTP streaming shall be moved to raw TCP streaming ...
|
||||
* Game mechanics: Maybe introduce an incubation time? Or let infection die over time ...
|
||||
|
|
|
@ -9,9 +9,6 @@ Pandemic Pong Game Engine
|
|||
|
||||
import time
|
||||
from random import random
|
||||
import struct # Packing/unpacking
|
||||
import threading, socket, socketserver
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer # TODO: May be replaced by raw TCP server?!
|
||||
|
||||
from playsound import playsound
|
||||
|
||||
|
@ -19,178 +16,7 @@ import game_objects.pong_constants as pgc # Pong global constants
|
|||
import game_objects.pong_globalvars as pgv # Pong global variables
|
||||
from game_objects.pong_player import PongPlayer
|
||||
from game_objects.pong_object import PongObject
|
||||
|
||||
TCP_PACKET_SIZE = struct.calcsize(pgc.TCP_TRANSFER_FORMAT) # Size of receiver buffer
|
||||
|
||||
# Local structure ref. (TODO: Should become an object really ...)
|
||||
sendgame = None
|
||||
sendplayer1 = None
|
||||
sendplayer2 = None
|
||||
sendball = None
|
||||
|
||||
|
||||
def init_send_structures(game, player1, player2, ball):
|
||||
"""Make handler data accessible"""
|
||||
global sendgame, sendplayer1, sendplayer2, sendball
|
||||
|
||||
# Only used as refs.
|
||||
sendgame = game
|
||||
sendplayer1 = player1
|
||||
sendplayer2 = player2
|
||||
sendball = ball
|
||||
|
||||
|
||||
class ViewServer:
|
||||
"""View server (one only instantiated)"""
|
||||
|
||||
def __init__(self):
|
||||
self.tcpClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.tcpClientSocket.connect((socket.gethostname(), pgc.PANDEMIC_PONG_PORT))
|
||||
self.tcpClientSocket.send("GET / HTTP/1.1\r\n\r\n".encode()) # Initiate streaming on server
|
||||
# Will return:
|
||||
# HTTP/1.0 200 OK
|
||||
# Server: BaseHTTP/0.6
|
||||
# Python/3.8.5
|
||||
# Date: Mon, 30 Nov 2020 09:59:52 GMT
|
||||
# Content-type: application/octet-stream
|
||||
# <CR/LF><CR/LF><CR/LF>
|
||||
msg = self.tcpClientSocket.recv(130).decode() # Skip server header
|
||||
print("Searching stream packet start ... ", end="")
|
||||
self.tcpClientSocket.setblocking(False) # Do not block ...
|
||||
iCount = 0
|
||||
while True: # Hunting ffa0 (little endian: a0, ff!)
|
||||
data = self.tcpClientSocket.recv(1)
|
||||
if data == b'\xa0':
|
||||
data = self.tcpClientSocket.recv(1)
|
||||
if data == b'\xff':
|
||||
break
|
||||
iCount += 1 # Count retries
|
||||
if iCount > TCP_PACKET_SIZE: # Somethin's wrong here ...
|
||||
raise BlockingIOError # Well, some error ...
|
||||
|
||||
data = self.tcpClientSocket.recv(TCP_PACKET_SIZE-2) # Skip complete packet
|
||||
print("detected! Receiving stream ...")
|
||||
|
||||
def receive_data(self):
|
||||
try:
|
||||
data = self.tcpClientSocket.recv(TCP_PACKET_SIZE)
|
||||
if len(data) < 1:
|
||||
print("Server side close detected.")
|
||||
return -1 # Indicate abortion
|
||||
# Datatype
|
||||
# Game: state, delay, p1_game, p2_game, playsound
|
||||
# Player1: player_index, state, x, y, delta_x, delta_y, color, delay
|
||||
# Player2: player_index, state, x, y, delta_x, delta_y, color, delay
|
||||
# Ball: x, y, w, h, delta_x, delta_y, color, delay, playsound
|
||||
datatype, sendgame.state, sendgame.delay, sendgame.p1_game, sendgame.p2_game, sendgame.playsound, sendplayer1.player_index, sendplayer1.state, sendplayer1.x, sendplayer1.y, sendplayer1.delta_x, sendplayer1.delta_y, sendplayer1.color, sendplayer1.delay, sendplayer1.score, sendplayer2.player_index, sendplayer2.state, sendplayer2.x, sendplayer2.y, sendplayer2.delta_x, sendplayer2.delta_y, sendplayer2.color, sendplayer2.delay, sendplayer2.score, sendball.x, sendball.y, sendball.w, sendball.h, sendball.delta_x, sendball.delta_y, sendball.color, sendball.delay, sendball.playsound = struct.unpack(pgc.TCP_TRANSFER_FORMAT, data)
|
||||
if sendgame.playsound != pgc.NOSOUND:
|
||||
playsound(pgc.sounds[sendgame.playsound])
|
||||
sendgame.playsound = pgc.NOSOUND
|
||||
if sendball.playsound != pgc.NOSOUND:
|
||||
playsound(pgc.sounds[sendball.playsound])
|
||||
sendball.playsound = pgc.NOSOUND
|
||||
return 1 # OK
|
||||
except BlockingIOError: # Always on empty receives ...
|
||||
return 0 # OK, empty queue
|
||||
except:
|
||||
return 0 #print("Receive error")
|
||||
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
"""Simple streaming (even to browsers)"""
|
||||
|
||||
def do_GET(self):
|
||||
"""HTTP-GET may be called from standard web browser to test ..."""
|
||||
global sendgame, sendplayer1, sendplayer2, sendball
|
||||
|
||||
if self.path != '/': # Webserver: localhost:8000/ !
|
||||
self.send_error(404, "Object not found")
|
||||
return
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'application/octet-stream') # We will stream binary data
|
||||
self.end_headers()
|
||||
|
||||
# Serve up an infinite stream
|
||||
bError = False
|
||||
while bError == False:
|
||||
#msg = "{0:04x}".format(iCounter) # {<varindex>:<formatstr>}
|
||||
try:
|
||||
bData = struct.pack(pgc.TCP_TRANSFER_FORMAT,
|
||||
pgc.PACKETTYPE_ALLDATA,
|
||||
# Game: iiiii
|
||||
sendgame.state,
|
||||
sendgame.delay,
|
||||
sendgame.p1_game,
|
||||
sendgame.p2_game,
|
||||
sendgame.playsound,
|
||||
# Player1: iiffffiii
|
||||
sendplayer1.player_index,
|
||||
sendplayer1.state,
|
||||
sendplayer1.x,
|
||||
sendplayer1.y,
|
||||
sendplayer1.delta_x,
|
||||
sendplayer1.delta_y,
|
||||
sendplayer1.color,
|
||||
sendplayer1.delay,
|
||||
sendplayer1.score,
|
||||
# Player2: iiffffiii
|
||||
sendplayer2.player_index,
|
||||
sendplayer2.state,
|
||||
sendplayer2.x,
|
||||
sendplayer2.y,
|
||||
sendplayer2.delta_x,
|
||||
sendplayer2.delta_y,
|
||||
sendplayer2.color,
|
||||
sendplayer2.delay,
|
||||
sendplayer2.score,
|
||||
# Ball: ffffffiii
|
||||
sendball.x,
|
||||
sendball.y,
|
||||
sendball.w,
|
||||
sendball.h,
|
||||
sendball.delta_x,
|
||||
sendball.delta_y,
|
||||
sendball.color,
|
||||
sendball.delay,
|
||||
sendball.playsound
|
||||
)
|
||||
except struct.error: # Eases testing ...
|
||||
pass #print("sendgame.playsound={} sendball.playsound={}".format(sendgame.playsound, sendball.playsound))
|
||||
|
||||
try:
|
||||
self.wfile.write(bData) # Stream!
|
||||
time.sleep(0.05) # Minimum required on i7/3rd gen. machine
|
||||
except BrokenPipeError:
|
||||
print("Client terminated.")
|
||||
bError = True
|
||||
|
||||
|
||||
class Thread(threading.Thread):
|
||||
"""TCP service streaming game data"""
|
||||
|
||||
def __init__(self, i, game):
|
||||
print("Starting thread #{} ...".format(i))
|
||||
self.game = game
|
||||
threading.Thread.__init__(self)
|
||||
self.i = i
|
||||
self.daemon = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
httpd = HTTPServer(self.game.addr, Handler, False)
|
||||
|
||||
# Prevent the HTTP server from re-binding every handler.
|
||||
# https://stackoverflow.com/questions/46210672/
|
||||
httpd.socket = self.game.tcpsocket
|
||||
httpd.server_bind = self.server_close = lambda self: None
|
||||
print("Thread listening ...")
|
||||
try:
|
||||
httpd.serve_forever() # Never returns ...
|
||||
except BrokenPipeError: # TODO: Not working?! May be removed alltogether?
|
||||
print("Client #{} terminated, respawning ...".format(self.i))
|
||||
Thread(self.i) # Respawn right away, await another client
|
||||
print("run(<thread>) exiting") # Never reached ...
|
||||
|
||||
import game_objects.pong_viewserver as vs # Pong TCP view server
|
||||
|
||||
class PongGame:
|
||||
"""Actual game mechanics (mostly ;)"""
|
||||
|
@ -201,19 +27,13 @@ class PongGame:
|
|||
self.p1_game = 0 # Results (reset)
|
||||
self.p2_game = 0
|
||||
self.playsound = pgc.NOSOUND # Play the provided sound & reset locally
|
||||
if bIsServer == True:
|
||||
# Create ONE socket.
|
||||
self.addr = ('', pgc.PANDEMIC_PONG_PORT)
|
||||
self.tcpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.tcpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.tcpsocket.bind(self.addr)
|
||||
self.tcpsocket.listen(5)
|
||||
[Thread(i, self) for i in range(2)] # Spawn player listeners
|
||||
if bIsServer == True:
|
||||
vs.init_server_socket() # Create the TCP server socket for streaming
|
||||
[vs.Thread(i, self) for i in range(2)] # Spawn player listeners & streams
|
||||
print("Game server started & listening ...")
|
||||
|
||||
def game_fsm(self, player1, player2):
|
||||
"""Game engine state machine"""
|
||||
sendgame.playsound = pgc.NOSOUND # Reset sound state
|
||||
"""Game engine state machine"""
|
||||
|
||||
if (player1.state & pgc.BTN_BASE3) > 0 or (player2.state & pgc.BTN_BASE3) > 0:
|
||||
player1.state = 0 # Don't play me again
|
||||
|
@ -289,6 +109,7 @@ class PongGame:
|
|||
|
||||
if (self.playsound != pgc.NOSOUND) and (pgv.bIsLocal == True): # Local play, sound output right away!
|
||||
playsound(pgc.sounds[self.playsound])
|
||||
self.playsound = pgc.NOSOUND
|
||||
|
||||
return True
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class PongObject:
|
|||
|
||||
def eval_object(self):
|
||||
"""Object movement w/ sound support"""
|
||||
|
||||
|
||||
bChanged = 0
|
||||
sum_x = self.x + self.delta_x
|
||||
sum_y = self.y + self.delta_y
|
||||
|
@ -51,8 +51,7 @@ class PongObject:
|
|||
bChanged = -1 # Miss left
|
||||
elif sum_x + self.w > pgc.GAMEAREA_MAX_X:
|
||||
bChanged = 1 # Miss right
|
||||
|
||||
self.playsound = pgc.NOSOUND
|
||||
|
||||
if sum_y < pgc.GAMEAREA_MIN_Y:
|
||||
sum_y = pgc.GAMEAREA_MIN_Y
|
||||
self.delta_y = -self.delta_y
|
||||
|
@ -67,7 +66,8 @@ class PongObject:
|
|||
|
||||
if (self.playsound != pgc.NOSOUND) and (pgv.bIsLocal == True): # Local play, sound output right away!
|
||||
playsound(pgc.sounds[self.playsound])
|
||||
|
||||
self.playsound = pgc.NOSOUND
|
||||
|
||||
return bChanged
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pong_viewserver.py
|
||||
|
||||
Pandemic Pong View Service (threads)
|
||||
|
||||
"""
|
||||
|
||||
import time
|
||||
from random import random
|
||||
import struct # Packing/unpacking
|
||||
import threading, socket, socketserver
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer # TODO: May be replaced by raw TCP server?!
|
||||
|
||||
from playsound import playsound
|
||||
|
||||
import game_objects.pong_constants as pgc # Pong global constants
|
||||
import game_objects.pong_globalvars as pgv # Pong global variables
|
||||
from game_objects.pong_player import PongPlayer
|
||||
from game_objects.pong_object import PongObject
|
||||
|
||||
TCP_PACKET_SIZE = struct.calcsize(pgc.TCP_TRANSFER_FORMAT) # Size of receiver buffer
|
||||
server_addr = None
|
||||
server_tcpsocket = None
|
||||
|
||||
# Local structure ref. (TODO: Should become an object really ...)
|
||||
sendgame = None
|
||||
sendplayer1 = None
|
||||
sendplayer2 = None
|
||||
sendball = None
|
||||
|
||||
|
||||
def init_send_structures(game, player1, player2, ball):
|
||||
"""Make handler data accessible"""
|
||||
global sendgame, sendplayer1, sendplayer2, sendball
|
||||
|
||||
# Only used as refs.
|
||||
sendgame = game
|
||||
sendplayer1 = player1
|
||||
sendplayer2 = player2
|
||||
sendball = ball
|
||||
|
||||
|
||||
def init_server_socket():
|
||||
"""Create ONE TCP server streaming socket"""
|
||||
global server_addr, server_tcpsocket
|
||||
|
||||
server_addr = ('', pgc.PANDEMIC_PONG_PORT)
|
||||
server_tcpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server_tcpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
server_tcpsocket.bind(server_addr)
|
||||
server_tcpsocket.listen(5)
|
||||
|
||||
|
||||
class ViewServer:
|
||||
"""View server (one only instantiated)"""
|
||||
|
||||
def __init__(self):
|
||||
self.tcpClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.tcpClientSocket.connect((socket.gethostname(), pgc.PANDEMIC_PONG_PORT))
|
||||
self.tcpClientSocket.send("GET / HTTP/1.1\r\n\r\n".encode()) # Initiate streaming on server
|
||||
# Will return:
|
||||
# HTTP/1.0 200 OK
|
||||
# Server: BaseHTTP/0.6
|
||||
# Python/3.8.5
|
||||
# Date: Mon, 30 Nov 2020 09:59:52 GMT
|
||||
# Content-type: application/octet-stream
|
||||
# <CR/LF><CR/LF><CR/LF>
|
||||
msg = self.tcpClientSocket.recv(130).decode() # Skip server header
|
||||
print("Searching stream packet start ... ", end="")
|
||||
self.tcpClientSocket.setblocking(False) # Do not block ...
|
||||
iCount = 0
|
||||
while True: # Hunting ffa0 (little endian: a0, ff!)
|
||||
data = self.tcpClientSocket.recv(1)
|
||||
if data == b'\xa0':
|
||||
data = self.tcpClientSocket.recv(1)
|
||||
if data == b'\xff':
|
||||
break
|
||||
iCount += 1 # Count retries
|
||||
if iCount > TCP_PACKET_SIZE: # Somethin's wrong here ...
|
||||
raise BlockingIOError # Well, some error ...
|
||||
|
||||
data = self.tcpClientSocket.recv(TCP_PACKET_SIZE-2) # Skip complete packet
|
||||
print("detected! Receiving stream ...")
|
||||
|
||||
def receive_data(self):
|
||||
"""Client receiver function"""
|
||||
try:
|
||||
data = self.tcpClientSocket.recv(TCP_PACKET_SIZE)
|
||||
if len(data) < 1:
|
||||
print("Server side close detected.")
|
||||
return -1 # Indicate abortion
|
||||
# Datatype
|
||||
# Game: state, delay, p1_game, p2_game, playsound
|
||||
# Player1: player_index, state, x, y, delta_x, delta_y, color, delay
|
||||
# Player2: player_index, state, x, y, delta_x, delta_y, color, delay
|
||||
# Ball: x, y, w, h, delta_x, delta_y, color, delay, playsound
|
||||
datatype, sendgame.state, sendgame.delay, sendgame.p1_game, sendgame.p2_game, sendgame.playsound, sendplayer1.player_index, sendplayer1.state, sendplayer1.x, sendplayer1.y, sendplayer1.delta_x, sendplayer1.delta_y, sendplayer1.color, sendplayer1.delay, sendplayer1.score, sendplayer2.player_index, sendplayer2.state, sendplayer2.x, sendplayer2.y, sendplayer2.delta_x, sendplayer2.delta_y, sendplayer2.color, sendplayer2.delay, sendplayer2.score, sendball.x, sendball.y, sendball.w, sendball.h, sendball.delta_x, sendball.delta_y, sendball.color, sendball.delay, sendball.playsound = struct.unpack(pgc.TCP_TRANSFER_FORMAT, data)
|
||||
if sendgame.playsound != pgc.NOSOUND: # Client side sound pulse reset
|
||||
playsound(pgc.sounds[sendgame.playsound])
|
||||
sendgame.playsound = pgc.NOSOUND
|
||||
if sendball.playsound != pgc.NOSOUND:
|
||||
playsound(pgc.sounds[sendball.playsound])
|
||||
sendball.playsound = pgc.NOSOUND
|
||||
return 1 # OK
|
||||
except BlockingIOError: # Always on empty receives ...
|
||||
return 0 # OK, empty queue
|
||||
except:
|
||||
return 0 #print("Receive error")
|
||||
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
"""Simple streaming server (even to browsers)"""
|
||||
|
||||
def do_GET(self):
|
||||
"""HTTP-GET may be called from standard web browser to test ..."""
|
||||
global sendgame, sendplayer1, sendplayer2, sendball
|
||||
|
||||
if self.path != '/': # Webserver: localhost:8000/ !
|
||||
self.send_error(404, "Object not found")
|
||||
return
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'application/octet-stream') # We will stream binary data
|
||||
self.end_headers()
|
||||
|
||||
# Serve up an infinite stream
|
||||
bError = False
|
||||
while bError == False:
|
||||
#msg = "{0:04x}".format(iCounter) # {<varindex>:<formatstr>}
|
||||
try:
|
||||
bData = struct.pack(pgc.TCP_TRANSFER_FORMAT,
|
||||
pgc.PACKETTYPE_ALLDATA,
|
||||
# Game: iiiii
|
||||
sendgame.state,
|
||||
sendgame.delay,
|
||||
sendgame.p1_game,
|
||||
sendgame.p2_game,
|
||||
sendgame.playsound,
|
||||
# Player1: iiffffiii
|
||||
sendplayer1.player_index,
|
||||
sendplayer1.state,
|
||||
sendplayer1.x,
|
||||
sendplayer1.y,
|
||||
sendplayer1.delta_x,
|
||||
sendplayer1.delta_y,
|
||||
sendplayer1.color,
|
||||
sendplayer1.delay,
|
||||
sendplayer1.score,
|
||||
# Player2: iiffffiii
|
||||
sendplayer2.player_index,
|
||||
sendplayer2.state,
|
||||
sendplayer2.x,
|
||||
sendplayer2.y,
|
||||
sendplayer2.delta_x,
|
||||
sendplayer2.delta_y,
|
||||
sendplayer2.color,
|
||||
sendplayer2.delay,
|
||||
sendplayer2.score,
|
||||
# Ball: ffffffiii
|
||||
sendball.x,
|
||||
sendball.y,
|
||||
sendball.w,
|
||||
sendball.h,
|
||||
sendball.delta_x,
|
||||
sendball.delta_y,
|
||||
sendball.color,
|
||||
sendball.delay,
|
||||
sendball.playsound
|
||||
)
|
||||
except struct.error: # Eases testing ...
|
||||
pass #print("sendgame.playsound={} sendball.playsound={}".format(sendgame.playsound, sendball.playsound))
|
||||
|
||||
try:
|
||||
self.wfile.write(bData) # Stream!
|
||||
if sendgame.playsound != pgc.NOSOUND: # Server side sound pulse reset
|
||||
sendgame.playsound = pgc.NOSOUND
|
||||
if sendball.playsound != pgc.NOSOUND:
|
||||
sendball.playsound = pgc.NOSOUND
|
||||
time.sleep(0.05) # Minimum required on i7/3rd gen. machine
|
||||
except BrokenPipeError:
|
||||
print("Client terminated.")
|
||||
bError = True
|
||||
|
||||
|
||||
class Thread(threading.Thread):
|
||||
"""TCP service streaming game data"""
|
||||
|
||||
def __init__(self, i, game):
|
||||
print("Starting thread #{} ...".format(i))
|
||||
self.game = game
|
||||
threading.Thread.__init__(self)
|
||||
self.i = i
|
||||
self.daemon = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
"""Called from start() s.a.!"""
|
||||
|
||||
httpd = HTTPServer(server_addr, Handler, False)
|
||||
|
||||
# Prevent the HTTP server from re-binding every handler.
|
||||
# https://stackoverflow.com/questions/46210672/
|
||||
httpd.socket = server_tcpsocket
|
||||
httpd.server_bind = self.server_close = lambda self: None
|
||||
print("Thread listening ...")
|
||||
try:
|
||||
httpd.serve_forever() # Never returns ...
|
||||
except BrokenPipeError: # TODO: Not working?! May be removed alltogether?
|
||||
print("Client #{} terminated, respawning ...".format(self.i))
|
||||
Thread(self.i) # Respawn right away, await another client
|
||||
print("run(<thread>) exiting") # Never reached ...
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("pong_viewserver has no function, call 'pandemic_pong.py'")
|
|
@ -10,6 +10,7 @@ History:
|
|||
21.11.20/KQ Initial version
|
||||
25.11.20/KQ Class based version w/ scaling ;)
|
||||
27.11.20/KQ Client/server variant started
|
||||
02.12.20/KQ Streamlined version published
|
||||
"""
|
||||
|
||||
DEVLOCAL = True # TODO: Adjust for publication to False!!!
|
||||
|
@ -28,8 +29,8 @@ import game_objects.pong_constants as pgc # Pong global constants
|
|||
import game_objects.pong_globalvars as pgv # Pong global variables
|
||||
from game_objects.pong_player import PongPlayer
|
||||
from game_objects.pong_object import PongObject
|
||||
from game_objects.pong_game import PongGame, init_send_structures, ViewServer
|
||||
|
||||
from game_objects.pong_game import PongGame
|
||||
import game_objects.pong_viewserver as vs # Pong TCP view server (threads)
|
||||
|
||||
def draw_buttonstate(x, y, player, painter, scale_x, scale_y):
|
||||
"""View function: Indicate last button pressed (not strictly necessary ...)"""
|
||||
|
@ -114,11 +115,11 @@ class pongWindow(QMainWindow):
|
|||
painter.drawPixmap(self.rect(), self.pic) # Game background
|
||||
|
||||
# Font metrics assume font is monospaced!
|
||||
fntLarge = QFont("Monospace", int(120 * scale_y))
|
||||
fntLarge = QFont("Monospace", int(120 * min(scale_x, scale_y)))
|
||||
fntLarge.setKerning(False)
|
||||
fntLarge.setFixedPitch(True)
|
||||
fm = QFontMetrics(fntLarge)
|
||||
fntMedium = QFont("Monospace", int(40 * scale_y))
|
||||
fntMedium = QFont("Monospace", int(40 * min(scale_x, scale_y)))
|
||||
fntMedium.setKerning(False)
|
||||
fntMedium.setFixedPitch(True)
|
||||
|
||||
|
@ -281,6 +282,7 @@ if __name__ == '__main__':
|
|||
sEventQueue1 = "/dev/input/event" + str(maxEvent-1)
|
||||
sEventQueue2 = "/dev/input/event" + str(maxEvent)
|
||||
|
||||
print("I'm a slow starter, please be patient!") # Caching actually ...
|
||||
try:
|
||||
# Initialize
|
||||
random.seed()
|
||||
|
@ -304,11 +306,11 @@ if __name__ == '__main__':
|
|||
player2 = PongPlayer(sEventQueue1, False, player_index, player_server, pgc.GAMEAREA_MAX_X-40, pgc.GAMEAREA_MAX_Y/2-50, 20, 160)
|
||||
|
||||
# TODO: Pretty ugly patch for handler data access ... (better: separate sender class)
|
||||
init_send_structures(game, player1, player2, ball)
|
||||
vs.init_send_structures(game, player1, player2, ball)
|
||||
|
||||
# 3 View clients permissible
|
||||
if player_index > 0: # i.e. NOT local only
|
||||
viewserver = ViewServer() # Create a view server
|
||||
viewserver = vs.ViewServer() # Create a view server
|
||||
|
||||
except IOError as e:
|
||||
import errno
|
||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 75 KiB |
Loading…
Reference in New Issue