Subscribe to Tech With Tim!
Download Code
You can download the code from the direct link or by copying the code listed below into appropriate files.
Direct: Download Now
client.py
import pygame from network import Network import pickle pygame.font.init() width = 700 height = 700 win = pygame.display.set_mode((width, height)) pygame.display.set_caption("Client") class Button: def __init__(self, text, x, y, color): self.text = text self.x = x self.y = y self.color = color self.width = 150 self.height = 100 def draw(self, win): pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height)) font = pygame.font.SysFont("comicsans", 40) text = font.render(self.text, 1, (255,255,255)) win.blit(text, (self.x + round(self.width/2) - round(text.get_width()/2), self.y + round(self.height/2) - round(text.get_height()/2))) def click(self, pos): x1 = pos[0] y1 = pos[1] if self.x <= x1 <= self.x + self.width and self.y <= y1 <= self.y + self.height: return True else: return False def redrawWindow(win, game, p): win.fill((128,128,128)) if not(game.connected()): font = pygame.font.SysFont("comicsans", 80) text = font.render("Waiting for Player...", 1, (255,0,0), True) win.blit(text, (width/2 - text.get_width()/2, height/2 - text.get_height()/2)) else: font = pygame.font.SysFont("comicsans", 60) text = font.render("Your Move", 1, (0, 255,255)) win.blit(text, (80, 200)) text = font.render("Opponents", 1, (0, 255, 255)) win.blit(text, (380, 200)) move1 = game.get_player_move(0) move2 = game.get_player_move(1) if game.bothWent(): text1 = font.render(move1, 1, (0,0,0)) text2 = font.render(move2, 1, (0, 0, 0)) else: if game.p1Went and p == 0: text1 = font.render(move1, 1, (0,0,0)) elif game.p1Went: text1 = font.render("Locked In", 1, (0, 0, 0)) else: text1 = font.render("Waiting...", 1, (0, 0, 0)) if game.p2Went and p == 1: text2 = font.render(move2, 1, (0,0,0)) elif game.p2Went: text2 = font.render("Locked In", 1, (0, 0, 0)) else: text2 = font.render("Waiting...", 1, (0, 0, 0)) if p == 1: win.blit(text2, (100, 350)) win.blit(text1, (400, 350)) else: win.blit(text1, (100, 350)) win.blit(text2, (400, 350)) for btn in btns: btn.draw(win) pygame.display.update() btns = [Button("Rock", 50, 500, (0,0,0)), Button("Scissors", 250, 500, (255,0,0)), Button("Paper", 450, 500, (0,255,0))] def main(): run = True clock = pygame.time.Clock() n = Network() player = int(n.getP()) print("You are player", player) while run: clock.tick(60) try: game = n.send("get") except: run = False print("Couldn't get game") break if game.bothWent(): redrawWindow(win, game, player) pygame.time.delay(500) try: game = n.send("reset") except: run = False print("Couldn't get game") break font = pygame.font.SysFont("comicsans", 90) if (game.winner() == 1 and player == 1) or (game.winner() == 0 and player == 0): text = font.render("You Won!", 1, (255,0,0)) elif game.winner() == -1: text = font.render("Tie Game!", 1, (255,0,0)) else: text = font.render("You Lost...", 1, (255, 0, 0)) win.blit(text, (width/2 - text.get_width()/2, height/2 - text.get_height()/2)) pygame.display.update() pygame.time.delay(2000) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False pygame.quit() if event.type == pygame.MOUSEBUTTONDOWN: pos = pygame.mouse.get_pos() for btn in btns: if btn.click(pos) and game.connected(): if player == 0: if not game.p1Went: n.send(btn.text) else: if not game.p2Went: n.send(btn.text) redrawWindow(win, game, player) def menu_screen(): run = True clock = pygame.time.Clock() while run: clock.tick(60) win.fill((128, 128, 128)) font = pygame.font.SysFont("comicsans", 60) text = font.render("Click to Play!", 1, (255,0,0)) win.blit(text, (100,200)) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() run = False if event.type == pygame.MOUSEBUTTONDOWN: run = False main() while True: menu_screen()
server.py
import socket from _thread import * import pickle from game import Game server = "10.11.250.207" port = 5555 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.bind((server, port)) except socket.error as e: str(e) s.listen(2) print("Waiting for a connection, Server Started") connected = set() games = {} idCount = 0 def threaded_client(conn, p, gameId): global idCount conn.send(str.encode(str(p))) reply = "" while True: try: data = conn.recv(4096).decode() if gameId in games: game = games[gameId] if not data: break else: if data == "reset": game.resetWent() elif data != "get": game.play(p, data) conn.sendall(pickle.dumps(game)) else: break except: break print("Lost connection") try: del games[gameId] print("Closing Game", gameId) except: pass idCount -= 1 conn.close() while True: conn, addr = s.accept() print("Connected to:", addr) idCount += 1 p = 0 gameId = (idCount - 1)//2 if idCount % 2 == 1: games[gameId] = Game(gameId) print("Creating a new game...") else: games[gameId].ready = True p = 1 start_new_thread(threaded_client, (conn, p, gameId))
game.py
class Game: def __init__(self, id): self.p1Went = False self.p2Went = False self.ready = False self.id = id self.moves = [None, None] self.wins = [0,0] self.ties = 0 def get_player_move(self, p): """ :param p: [0,1] :return: Move """ return self.moves[p] def play(self, player, move): self.moves[player] = move if player == 0: self.p1Went = True else: self.p2Went = True def connected(self): return self.ready def bothWent(self): return self.p1Went and self.p2Went def winner(self): p1 = self.moves[0].upper()[0] p2 = self.moves[1].upper()[0] winner = -1 if p1 == "R" and p2 == "S": winner = 0 elif p1 == "S" and p2 == "R": winner = 1 elif p1 == "P" and p2 == "R": winner = 0 elif p1 == "R" and p2 == "P": winner = 1 elif p1 == "S" and p2 == "P": winner = 0 elif p1 == "P" and p2 == "S": winner = 1 return winner def resetWent(self): self.p1Went = False self.p2Went = False
network.py
import socket import pickle class Network: def __init__(self): self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server = "10.11.250.207" self.port = 5555 self.addr = (self.server, self.port) self.p = self.connect() def getP(self): return self.p def connect(self): try: self.client.connect(self.addr) return self.client.recv(2048).decode() except: pass def send(self, data): try: self.client.send(str.encode(data)) return pickle.loads(self.client.recv(2048*2)) except socket.error as e: print(e)