class Menu: """Ecran dans lequel on a une input_box permettant d'entrer un pseudo puis d'essayer de se connecter à une session. """ def __init__(self, client, message=None): self.client = client self.inputbox = InputBox(client.window_width / 2 - 100, client.window_height / 2 - 12, self.launch) self.inputbox.isWriting = True self.logger = Logger() if(not message is None): self.logger.add_message(message, (255, 0, 0)) self.logger.add_message("Please enter a username") self.main_loop() def main_loop(self): while(True): self.handle_keyboard_input() self.draw_frame() self.client.clock.tick(REFRESH_TICKRATE) def handle_keyboard_input(self): keys = pygame.key.get_pressed() self.inputbox.handle_continuous_pressed_keys(keys) for event in pygame.event.get(): if(event.type == pygame.QUIT): self.stop() if(event.type == pygame.KEYDOWN): if(event.key == pygame.K_ESCAPE): self.stop() self.inputbox.handle_input_event(event) def draw_frame(self): self.client.window.fill((0, 0, 0)) self.inputbox.draw(self.client.window) self.logger.draw(self.client.window) pygame.display.update() def stop(self): pygame.quit() exit(0) def launch(self, text): """Fonction pour lancer une partie multijoueur. On vérifie la validité du pseudo avant de lancer la partie """ if(not re.match('^[a-z]+$', text) or len(text) > 10): self.logger.add_message("The username must be composed of only lower case letters and be less than 10 characters") pass else: multiplayer_game.MultiplayerGame(self.client, text)
class MultiplayerGame: def __init__(self, client, username): self.client = client self.logger = Logger() self.score_displayer = Score(username) self.inputbox = InputBox(5, self.client.window_width - 30, self.send_message) self.username = username self.is_socket_connected_to_server = False self.session_state = "nosession" # Indicate whether we not connected, requested connection or in a session self.socket = None self.arena = Arena(self.client.window_width, self.client.window_height) # Creation de l'arene self.main_player = Player("player.png", self.username, to_display=True) self.last_newcom = 0 self.arena.players[username] = self.main_player self.main_loop() def main_loop(self): while (True): self.handle_server_coms() self.handle_keyboard_input() self.enitities_update() self.draw_frame() self.client.clock.tick( REFRESH_TICKRATE ) # Limite le nombre de mise a jour par seconde def handle_server_coms(self): if (not self.is_socket_connected_to_server): self.logger.add_message("Connecting to server...") self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.socket.connect((HOST, PORT)) except ConnectionRefusedError: menu.Menu(self.client, "Connection to server failed") self.logger.add_message("Connection successful.") self.is_socket_connected_to_server = True if (self.session_state == "nosession"): self.logger.add_message("Trying to join a session...") self.session_state = "request" send_serveur.connect(self.socket, self.username) elif (self.session_state == "jeu"): # send_serveur.newpos(self.socket, self.main_player.pos) if (time.time() - self.last_newcom > 1 / SERVER_TICKRATE): send_serveur.newcom(self.socket, self.main_player.command_angle, self.main_player.command_thrust, self.main_player.hasShoot) self.main_player.hasShoot = False self.last_newcom = time.time() # Commands sent, reset self.main_player.command_angle = 0 self.main_player.command_thrust = 0 self.handle_server_responses() def handle_server_responses(self): try: data = self.socket.recv(8192, socket.MSG_DONTWAIT) except BlockingIOError: # Nothing to read return commands = data.decode().split("\n") commands = [cmd.split("/") for cmd in commands] # print(commands) for cmd in commands: if (cmd[0] == "WELCOME"): self.apply_command_welcome(cmd) elif (cmd[0] == "DENIED"): self.apply_command_denied(cmd) elif (cmd[0] == "NEWPLAYER"): self.apply_command_newplayer(cmd) elif (cmd[0] == "PLAYERLEFT"): self.apply_command_playerleft(cmd) elif (cmd[0] == "SESSION"): self.apply_command_session(cmd) elif (cmd[0] == "WINNER"): self.apply_command_winner(cmd) elif (cmd[0] == "TICK"): self.apply_command_tick(cmd) elif (cmd[0] == "TICK2"): self.apply_command_tick2(cmd) elif (cmd[0] == "NEWOBJ"): self.apply_command_newobj(cmd) elif (cmd[0] == "RECEPTION"): self.apply_command_reception(cmd) elif (cmd[0] == "PRECEPTION"): self.apply_command_preception(cmd) def apply_command_welcome(self, cmd): phase = cmd[1] scores = cmd[2] coord = cmd[3] obs_coords = cmd[4] if (phase == "attente"): self.logger.add_message("Waiting to start session") self.logger.add_message("Type /race to start a race next") self.session_state = "attente" elif (phase == "jeu" or phase == "ingame_race"): self.logger.add_message("Joining a game") self.session_state = "jeu" goals_coord = coord.split("|") goalx, goaly = parse_coord(goals_coord[0]) if (len(goals_coord) == 2): nextgoalx, nextgoaly = parse_coord(goals_coord[1]) self.arena.next_goal = Goal(nextgoalx, nextgoaly, True) else: self.arena.next_goal = None self.arena.goal = Goal(goalx, goaly) self.main_player.to_display = False # Wait to get coord before displaying for s in scores.split("|"): [name, score] = s.split(":") if (name in self.arena.players): self.arena.players[name].score = int(score) else: new_player = Player("enemy.png", name) new_player.score = int(score) self.arena.players[name] = new_player if (len(obs_coords) > 0): for o in obs_coords.split("|"): pos = parse_coord(o) self.arena.obstacles.append(Obstacle(pos[0], pos[1])) def apply_command_denied(self, cmd): self.logger.add_message("Joining session failed") menu.Menu(self.client, "This username is already taken, please choose another") def apply_command_newplayer(self, cmd): user = cmd[1] self.logger.add_message(user + " joins the game") self.arena.players[user] = Player("enemy.png", user) def apply_command_playerleft(self, cmd): user = cmd[1] self.logger.add_message(user + " left the game") if (user in self.arena.players): del self.arena.players[user] def apply_command_session(self, cmd): coords = cmd[1] coord = cmd[2] obs_coords = cmd[3] self.logger.add_message("Session starting !") players_coords = coords.split("|") for p in players_coords: [name, pos] = p.split(":") pos = parse_coord(pos) if (name in self.arena.players): self.arena.players[name].reset() self.arena.players[name].moveTo(pos[0], pos[1]) self.arena.players[name].to_display = True else: self.arena.players[name] = Player("enemy.png", name, pos, True) goals_coord = coord.split("|") goalx, goaly = parse_coord(goals_coord[0]) if (len(goals_coord) == 2): nextgoalx, nextgoaly = parse_coord(goals_coord[1]) self.arena.next_goal = Goal(nextgoalx, nextgoaly, True) self.arena.goal = Goal(goalx, goaly) if (len(obs_coords) > 0): for o in obs_coords.split("|"): pos = parse_coord(o) self.arena.obstacles.append(Obstacle(pos[0], pos[1])) self.session_state = "jeu" def apply_command_winner(self, cmd): scores = cmd[1] for s in scores.split("|"): [name, score] = s.split(":") self.arena.players[name].score = int(score) if (int(score) == WIN_CAP): winner = name if (self.username == winner): self.logger.add_message( "End of game, congratulations you are the winner !!") else: self.logger.add_message("End of game, winner is : " + winner) self.logger.add_message("A new game will restart soon") self.session_state = "attente" self.arena.goal = None self.arena.obstacles.clear() self.arena.attacks.clear() # Don't display other player if not ingame for p in self.arena.players.values(): if (not p.username == self.username): p.to_display = False def apply_command_tick(self, cmd): coords = cmd[1] self.arena.attacks.clear() players_coords = coords.split("|") for p in players_coords: [name, vals] = p.split(":") pos, vector, direction = parse_coord(vals) player = self.arena.players[name] player.moveTo(pos[0], pos[1]) player.direction = direction player.vector = vector player.to_display = True def apply_command_tick2(self, cmd): self.apply_command_tick(cmd) self.arena.attacks.clear() coords = cmd[2] for a in coords.split("|"): pos = parse_coord(a) self.arena.attacks.append(Attack(pos[0], pos[1], pos[2])) def apply_command_newobj(self, cmd): coord = cmd[1] scores = cmd[2] for s in scores.split("|"): [name, score] = s.split(":") self.arena.players[name].score = int(score) goals_coord = coord.split("|") goalx, goaly = parse_coord(goals_coord[0]) if (len(goals_coord) == 2): nextgoalx, nextgoaly = parse_coord(goals_coord[1]) self.arena.next_goal = Goal(nextgoalx, nextgoaly, True) else: self.arena.next_goal = None self.arena.goal = Goal(goalx, goaly) def apply_command_reception(self, cmd): message = cmd[1] self.logger.add_message(message, (255, 0, 0)) def apply_command_preception(self, cmd): message = cmd[1] user = cmd[2] self.logger.add_message("From " + user + " : " + message, (255, 105, 180)) def handle_keyboard_input(self): keys = pygame.key.get_pressed() if (not self.inputbox.isWriting): if (keys[pygame.K_q] or keys[pygame.K_LEFT]): self.main_player.anticlock() elif (keys[pygame.K_d] or keys[pygame.K_RIGHT]): self.main_player.clock() else: self.inputbox.handle_continuous_pressed_keys(keys) for event in pygame.event.get(): if (event.type == pygame.QUIT): self.stop() if (event.type == pygame.KEYDOWN): if (not self.inputbox.isWriting): if (event.key == pygame.K_SPACE): self.main_player.thrust() if (event.key == pygame.K_e): self.main_player.shoot() if (event.key == pygame.K_ESCAPE): self.stop() self.inputbox.handle_input_event(event) def enitities_update(self): self.arena.update( ) # Updates every players in the arena including the main_player def draw_frame(self): self.client.window.fill( (0, 0, 0)) # Efface tout ce qui est sur la fenetre self.arena.draw(self.client.window) # Dessine toutes les entites self.logger.draw(self.client.window) self.score_displayer.draw(self.arena.players, self.client.window) self.inputbox.draw(self.client.window) pygame.display.update() # Met a jour la fenetre def stop(self): if (not self.socket is None): self.socket.close() pygame.quit() exit(0) def send_message(self, text): words = text.split(" ") if (len(words) >= 3 and words[0] == "/w" and len(words[1]) > 0 and len(words[2]) > 0): msg = " ".join(words[2:]) self.logger.add_message("To " + words[1] + " : " + msg, (255, 105, 180)) send_serveur.sendpmsg(self.socket, words[1], msg) elif (len(words) == 1 and words[0] == "/race"): self.logger.add_message("The next session will be a race") send_serveur.sendrace(self.socket) else: self.logger.add_message(text, (255, 0, 0)) send_serveur.sendmsg(self.socket, text)