diff --git a/blup/balance_util.py b/blup/balance_util.py new file mode 100644 index 0000000..915a375 --- /dev/null +++ b/blup/balance_util.py @@ -0,0 +1,130 @@ +""" +this file is part of blup. it provides an easy way +to determine the direction the player is leaning +""" +from enum import Enum +import struct + +Direction = Enum('BalanceDirection', + ['LEFT', 'RIGHT', 'UP', 'DOWN', + 'CENTER', 'QUIT']) + + +def sanitize_threshold(threshold): + """ + function to make sure the threshold is positive + threshold -- the given (untrusted) treshold + """ + if threshold < 0: + threshold = abs(threshold) + return threshold + + +class BalanceSocket(object): + def __init__(self, balance_server_socket): + self.socket = balance_server_socket + + def close(self): + self.socket.close() + + def _get_raw_data(self): + self.socket.send(b'a') + data = self.socket.recv(4) + p0x, p0y, p1x, p1y = struct.unpack('bbbb', data) + return p0x, p0y, p1x, p1y + + +class BalanceUtil(BalanceSocket): + def __init__(self, balance_server_socket, player_id): + """ + BalanceUtil object + balance_socket -- (ip, port) of the balance server + player_id -- id of the player + """ + super(BalanceUtil, self).__init__(balance_server_socket) + self.player_id = player_id + + def _get_raw_player_data(self): + self.socket.send(b'a') + data = self.socket.recv(4) + p0x, p0y, p1x, p1y = struct.unpack('bbbb', data) + if self.player_id == 0: + return p0x, p0y + else: + return p1x, p1y + + def get_player_ready(self): + """ + check if someone is on the board + :return: true if someone is on the board + """ + p_x, p_y = self._get_raw_player_data() + return p_x > -128 or p_y > -128 + + def get_raw_2dir_y(self): + """ + Get raw 2-directional data from the y axis of the board. + e.g. determine how fast the paddle is supposed to move + in balance pong + :return: raw y axis balance value + """ + x_bal, y_bal = self._get_raw_player_data() + return y_bal + + def get_2dir_y(self, threshold): + threshold = sanitize_threshold(threshold) + x_bal, y_bal = self._get_raw_player_data() + if x_bal == -128 or y_bal == -128: + return Direction.QUIT + elif abs(y_bal) < threshold: + return Direction.CENTER + elif y_bal > 0: + return Direction.UP + else: + return Direction.DOWN + + def get_raw_2dir_x(self): + x_bal, y_bal = self._get_raw_player_data() + return x_bal + + def get_2dir_x(self, threshold): + threshold = sanitize_threshold(threshold) + x_bal, y_bal = self._get_raw_player_data() + if x_bal == -128 or y_bal == -128: + return Direction.QUIT + elif abs(x_bal) < threshold: + return Direction.CENTER + elif x_bal > 0: + return Direction.RIGHT + else: + return Direction.LEFT + + def get_raw_4dir(self): + return self._get_raw_player_data() + + def get_4dir(self, threshold): + """ + Get evaluated 4-directional data of the board + e.g. determine the direction and rotation or drop move + in balance tetris + + threshold -- deadzone of the board where nothing is + supposed to happen + :return: Enum Direction value of direction or event + """ + threshold = sanitize_threshold(threshold) + x_bal, y_bal = self._get_raw_player_data() + if x_bal == -128 or y_bal == -128: + return Direction.QUIT + elif abs(x_bal) < threshold and abs(y_bal) < threshold: + return Direction.CENTER + elif abs(x_bal) < abs(y_bal): + if y_bal > 0: + return Direction.UP + else: + return Direction.DOWN + else: + if x_bal > 0: + return Direction.RIGHT + else: + return Direction.LEFT diff --git a/games/balancep0ng.py b/games/balancep0ng.py index cfcb3c0..0f874fa 100755 --- a/games/balancep0ng.py +++ b/games/balancep0ng.py @@ -8,6 +8,7 @@ import os import configparser import socket import struct +import blup.balance_util import blup.frame import blup.output import pong @@ -72,28 +73,14 @@ def convertPixels(dimension, pixels, invert=False): p.append(row) return p -def get_balance_from_sock(sock, player_id): - print('will balance haben...') - sock.send(b'a') - data = sock.recv(4) - p1x, p1y, p2x, p2y = struct.unpack('bbbb', data) - if player_id == 0: - bal = p1y - elif player_id == 1: - bal = p2y - print('balance id=%s balance=%d' % (player_id, bal)) - return bal - class BalanceBoardPlayer(object): - def __init__(self, playground, ownPaddle, wiimote_sock, player_id): + def __init__(self, playground, own_paddle, balance_util): self.__playground = playground - self.__ownPaddle = ownPaddle - self.__wiimote = wiimote_sock + self.__ownPaddle = own_paddle self.__ready = False self.__playground.addGameTickCallback(self.gametickcb) - self.__wiimote_sock = wiimote_sock - self.__player_id = player_id + self.__balance_util = balance_util @property def ownPaddle(self): @@ -104,11 +91,11 @@ class BalanceBoardPlayer(object): return true def gametickcb(self): - bal = get_balance_from_sock(self.__wiimote_sock, self.__player_id) + bal = self.__balance_util.get_raw_2dir_y() if bal == -128: - print("player %d has quit" % (self.__player_id)) - self.__wiimote_sock.close() + print("player %d has quit" % self.__balance_util.player_id) + self.__balance_util.socket.close() sys.exit(1) bal = -bal @@ -120,7 +107,7 @@ class BalanceBoardPlayer(object): bal += MAX_AMPLITUDE pos = int((bal / (2 * MAX_AMPLITUDE)) * self.__playground.height) - print("player %d pos=%d" % (self.__player_id, pos)) + print("player %d pos=%d" % (self.__balance_util.player_id, pos)) if self.__ownPaddle.ypos > pos: self.__ownPaddle.nextMoveUp() @@ -155,24 +142,26 @@ class B4lancePong(object): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(self.__balanceserver) print('connected!') - - while get_balance_from_sock(sock, 0) == -128: + balance_util_p1 = blup.balance_util.BalanceUtil(sock, 0) + balance_util_p2 = blup.balance_util.BalanceUtil(sock, 1) + while not balance_util_p1.get_player_ready(): print('waiting for player...') time.sleep(1) self.__players = [] - self.__players.append(BalanceBoardPlayer(self.__playground, self.__playground.leftPaddle, sock, 0)) + self.__players.append(BalanceBoardPlayer(self.__playground, self.__playground.leftPaddle, balance_util_p1)) if self.__numplayers == 2: - self.__players.append(BalanceBoardPlayer(self.__playground, self.__playground.rightPaddle, sock, 1)) + self.__players.append(BalanceBoardPlayer(self.__playground, self.__playground.rightPaddle, balance_util_p2)) elif self.__numplayers is None: for i in range(5): frame = mk_logo_frame(self.__dimension, onePlayer) self.__out.sendFrame(frame) print('waiting for second player...') - if get_balance_from_sock(sock, 1) > -128: - self.__players.append(BalanceBoardPlayer(self.__playground, self.__playground.rightPaddle, sock, 1)) + if balance_util_p2.get_player_ready(): + self.__players.append(BalanceBoardPlayer(self.__playground, self.__playground.rightPaddle, + balance_util_p2)) break time.sleep(1) diff --git a/games/gamemenu.py b/games/gamemenu.py index 45df2c5..9162ef3 100755 --- a/games/gamemenu.py +++ b/games/gamemenu.py @@ -8,6 +8,7 @@ import argparse import subprocess import socket import struct +import blup.balance_util import blup.frame import blup.output @@ -210,9 +211,8 @@ class TestInput(AbstractInput): return None class BalanceInput(AbstractInput, threading.Thread): - def __init__(self, addr, player_id): - self.addr = addr - self.player_id = player_id + def __init__(self, balance_util): + self.balance_util = balance_util self.evt = None self.lastevt = None self.player_present = False @@ -221,27 +221,13 @@ class BalanceInput(AbstractInput, threading.Thread): self.start() def run(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.connect(self.addr) - except ConnectionRefusedError: - print('could not connect to balance server', file=sys.stderr) - self.evt = InputEvent.QUIT - return self.running = True evt = None oldevt = None lastchange = 0 while self.running: - sock.send(b'a') - data = sock.recv(4) - p0x, p0y, p1x, p1y = struct.unpack('bbbb', data) - if self.player_id == 0: - xbal, ybal = p0x, p0y - elif self.player_id == 1: - xbal, ybal = p1x, p1y - THRESHOLD = 40 + direction = self.balance_util.get_4dir(THRESHOLD) MIN_TIMES = { InputEvent.LEFT: 0.05, InputEvent.RIGHT: 0.05, @@ -249,24 +235,21 @@ class BalanceInput(AbstractInput, threading.Thread): InputEvent.DOWN: 0.05, } if self.player_present: - if xbal == -128 or ybal == -128: + if direction == blup.balance_util.Direction.QUIT: self.evt = InputEvent.QUIT self.player_present = False continue - - if abs(xbal) < THRESHOLD and abs(ybal) < THRESHOLD: + elif direction == blup.balance_util.Direction.CENTER: evt = None - else: - if abs(xbal) < abs(ybal): - if ybal > 0: - evt = InputEvent.UP - else: - evt = InputEvent.DOWN - else: - if xbal > 0: - evt = InputEvent.RIGHT - else: - evt = InputEvent.LEFT + elif direction == blup.balance_util.Direction.UP: + evt = InputEvent.UP + elif direction == blup.balance_util.Direction.DOWN: + evt = InputEvent.DOWN + elif direction == blup.balance_util.Direction.RIGHT: + evt = InputEvent.RIGHT + elif direction == blup.balance_util.Direction.LEFT: + evt = InputEvent.LEFT + if evt != oldevt: lastchange = time.time() oldevt = evt @@ -281,7 +264,7 @@ class BalanceInput(AbstractInput, threading.Thread): #print('player_id=%d event=%s' % (self.player_id, self.evt)) time.sleep(0.005) else: - if xbal != -128 and ybal != -128: + if direction != blup.balance_util.Direction.QUIT: self.evt = InputEvent.STEP_ON self.player_present = True continue @@ -325,8 +308,14 @@ if __name__ == '__main__': inp2 = TestInput() elif args.balance is not None: host, port = args.balance.split(':') - inp1 = BalanceInput((host, int(port)), 0) - inp2 = BalanceInput((host, int(port)), 1) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + sock.connect((host, int(port))) + inp1 = BalanceInput(blup.balance_util.BalanceUtil(sock, 0)) + inp2 = BalanceInput(blup.balance_util.BalanceUtil(sock, 1)) + except ConnectionRefusedError: + print('could not connect to balance server', file=sys.stderr) + sys.exit(1) while True: evt = inp1.get_event() diff --git a/games/ttrs.py b/games/ttrs.py index 82bc623..4945f50 100755 --- a/games/ttrs.py +++ b/games/ttrs.py @@ -8,6 +8,7 @@ import time import enum import math import collections +import blup.balance_util import blup.frame import blup.output import random @@ -233,55 +234,37 @@ class TestTtrsPlayer(TtrsPlayer): class BalanceTtrsPlayer(TtrsPlayer, threading.Thread): - def __init__(self, playground, addr, player_id): + def __init__(self, playground, balance_util): self.playground = playground - self.addr = addr - self.player_id = player_id + self.balance_util = balance_util self.evt = None self.lastevt = None threading.Thread.__init__(self, daemon=True) self.start() def run(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.connect(self.addr) - except ConnectionRefusedError: - print('could not connect to balance server', file=sys.stderr) - self.evt = PlayerEvent.QUIT - return self.running = True evt = None oldevt = None lastchange = 0 while self.running: - sock.send(b'a') - data = sock.recv(4) - p0x, p0y, p1x, p1y = struct.unpack('bbbb', data) - if self.player_id == 0: - xbal, ybal = p0x, p0y - elif self.player_id == 1: - xbal, ybal = p1x, p1y + THRESHOLD = 40 + direction = self.balance_util.get_4dir(THRESHOLD) - #print('player_id=%d xbal=%d ybal=%d' % (self.player_id, xbal, ybal)) - if xbal == -128 or ybal == -128: + if direction == blup.balance_util.Direction.QUIT: self.evt = PlayerEvent.QUIT - - THRESHOLD = 40 - if abs(xbal) < THRESHOLD and abs(ybal) < THRESHOLD: - evt = None + elif direction == blup.balance_util.Direction.LEFT: + evt = PlayerEvent.MOVE_LEFT + elif direction == blup.balance_util.Direction.RIGHT: + evt = PlayerEvent.MOVE_RIGHT + elif direction == blup.balance_util.Direction.UP: + evt = PlayerEvent.ROTATE + elif direction == blup.balance_util.Direction.DOWN: + evt = PlayerEvent.DROP else: - if abs(xbal) < abs(ybal): - if ybal > 0: - evt = PlayerEvent.ROTATE - else: - evt = PlayerEvent.DROP - else: - if xbal > 0: - evt = PlayerEvent.MOVE_RIGHT - else: - evt = PlayerEvent.MOVE_LEFT + evt = None + #print('player_id=%d xbal=%d ybal=%d' % (self.player_id, xbal, ybal)) MIN_TIMES = { PlayerEvent.MOVE_LEFT: 0.1, PlayerEvent.MOVE_RIGHT: 0.1, @@ -307,7 +290,7 @@ class BalanceTtrsPlayer(TtrsPlayer, threading.Thread): def get_event(self): - print('player_id=%d event=%s' % (self.player_id, self.evt)) + print('player_id=%d event=%s' % (self.balance_util.player_id, self.evt)) evt = self.evt self.evt = None return evt @@ -481,13 +464,21 @@ if __name__ == '__main__': seed = random.random() games = [] + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + host, port = args.balance.split(':') + try: + sock.connect((host, int(port))) + except ConnectionRefusedError: + print('could not connect to balance server', file=sys.stderr) + sys.exit(1) + def start_game(player_id, xpos): pg = Playground(10, 16) + balance_util = blup.balance_util.BalanceUtil(sock, player_id) if args.pygame: player = TestTtrsPlayer(pg) elif args.balance is not None: - host, port = args.balance.split(':') - player = BalanceTtrsPlayer(pg, (host, int(port)), player_id) + player = BalanceTtrsPlayer(pg, balance_util) rnd = random.Random(seed) game = TtrsGame(pg, player, rnd) painter.add_game(game, xpos, 0)