def __init__(self, dim, pos, username, state): self.pos = pos self.username = username self.in_game = False self.state = state self.text = TextBox((int(5 / 8 * dim[0]), dim[1]), self.CTEXT, pos, username, font=Font.f30, marge=True) self.button_invite = Button((int(1 / 4 * dim[0]), dim[1]), self.CBUTTON, (pos[0] + int(5 / 8 * dim[0]), pos[1]), 'Invite', font=Font.f30) self.text_ingame = TextBox((int(1 / 4 * dim[0]), dim[1]), self.CBUTTON, (pos[0] + int(5 / 8 * dim[0]), pos[1]), 'In game', font=Font.f30) self.button_delete = Button((int(1 / 8 * dim[0]), dim[1]), C.LIGHT_GREY, (pos[0] + int(7 / 8 * dim[0]), pos[1]), 'Del', font=Font.f30)
class PlayerBox: def __init__(self, pos, dim_x, color, username): self.pos = pos self.dim = (dim_x, DIM_PY) self.username = username self.textbox = TextBox(self.dim, color, pos, username, font=Font.f50, marge=True, TEXT_COLOR=C.BLACK) def display(self): self.textbox.display()
def __init__(self, pos, dim_x, color, n): self.dim = (dim_x, DIM_TEAMY) self.textbox = TextBox(self.dim,color, pos, f' Team {n}', marge=True, TEXT_COLOR=C.BLACK, centered=False) b_dx = int(1/5*dim_x) self.button_join = Button((b_dx,DIM_TEAMY),C.XLIGHT_GREY,(0,0),'Join',font=Font.f30) self.n = n self.pos = pos self.players = [] self.color = color
class Team: def __init__(self, pos, dim_x, color, n): self.dim = (dim_x, DIM_TEAMY) self.textbox = TextBox(self.dim, color, pos, f' Team {n}', marge=True, TEXT_COLOR=C.BLACK, centered=False) b_dx = int(1 / 5 * dim_x) self.button_join = Button((b_dx, DIM_TEAMY), C.XLIGHT_GREY, (0, 0), 'Join', font=Font.f30) self.n = n self.pos = pos self.players = [] self.color = color def create_player(self, username): y = 0 new_player = PlayerBox((self.pos[0], y), self.dim[0], self.color, username) self.players.append(new_player) def set_pos(self, pos): self.pos = pos self.textbox.set_pos(pos) b_dx = int(1 / 5 * self.dim[0]) self.button_join.set_pos((pos[0] + self.dim[0] - b_dx, pos[1])) cursor_y = DIM_TEAMY for player in self.players: y = self.pos[1] + cursor_y player.textbox.set_pos((pos[0], y)) cursor_y += DIM_PY return cursor_y def check_del_player(self, username): player_to_del = None for player in self.players: if player.username == username: player_to_del = player break if player_to_del != None: self.players.remove(player_to_del) def display(self): self.textbox.display() self.button_join.display() for player in self.players: player.display()
def init(cls, client, pos_y): cls.client = client cls.pos = [POS_X, pos_y] cls.title_n_game = TextBox(DIM_TITLE, C.WHITE, cls.pos, 'Games played') cls.text_n_game = TextBox(DIM_BOX, C.WHITE, (cls.pos[0], cls.pos[1] + DIM_TY), '', font=Font.f30, marge=True) cls.title_n_kill = TextBox(DIM_TITLE, C.WHITE, (cls.pos[0] + DIM_BX, cls.pos[1]), 'Kills') cls.text_n_kill = TextBox(DIM_BOX, C.WHITE, (cls.pos[0] + DIM_BX, cls.pos[1] + DIM_TY), '', font=Font.f30, marge=True) cls.title_n_death = TextBox(DIM_TITLE, C.WHITE, (cls.pos[0] + 2 * DIM_BX, cls.pos[1]), 'Deaths') cls.text_n_death = TextBox( DIM_BOX, C.WHITE, (cls.pos[0] + 2 * DIM_BX, cls.pos[1] + DIM_TY), '', font=Font.f30, marge=True) cls.title_ratio = TextBox(DIM_TITLE, C.WHITE, (cls.pos[0] + 3 * DIM_BX, cls.pos[1]), 'K/D') cls.text_ratio = TextBox( DIM_BOX, C.WHITE, (cls.pos[0] + 3 * DIM_BX, cls.pos[1] + DIM_TY), '', font=Font.f30, marge=True)
def __init__(self, x_dim, pos, username): self.pos = pos self.username = username text = f'Invitation from: {username}' self.text = TextBox((x_dim - MARGE, DIM_TY), C.LIGHT_GREY, pos, text, font=Font.f30) self.button_yes = Button(DIM_DFR_B, C.LIGHT_GREEN, (pos[0] + x_dim - 2 * DIM_DFR_B[0], pos[1]), image=img_vu) self.button_no = Button(DIM_DFR_B, C.LIGHT_RED, (pos[0] + x_dim - DIM_DFR_B[0], pos[1]), image=img_cross)
def __init__(self, x_dim, pos, username): self.pos = pos self.username = username text = f'Friend demand: {username}' self.text = TextBox((x_dim - MARGE, DIM_TY), C.LIGHT_GREY, pos, text, font=Font.f30) self.button_yes = Button(DIM_DFR_B, C.LIGHT_GREEN, (pos[0] + x_dim - MARGE, pos[1]), 'Yes', font=Font.f30) self.button_no = Button(DIM_DFR_B, C.LIGHT_RED, (pos[0] + x_dim - LMARGE, pos[1]), 'No', font=Font.f30)
class Credits: text_gamename = TextBox( DIM_TDEV, C.WHITE, (POS_X, E(200)), "You can propose a name for the game! Use [email protected]" ) text_dev = TextBox(DIM_TDEV, C.WHITE, (POS_X, E(400)), 'Created, developed and designed by Plouc314') text_sourcecode = TextBox( DIM_TDEV, C.WHITE, (POS_X, E(600)), "Source code available on https://github.com/Plouc314/SocketGame") str_img = "Images credits:\nImages made by Those Icons, Freepik, Pixel Buddha\nEucalyp, photo3_idea_studio\n from www.flaticon.com" text_img = TextBox(DIM_TIMG, C.WHITE, (POS_X, E(800)), str_img) @classmethod def display(cls): cls.text_dev.display() cls.text_sourcecode.display() cls.text_gamename.display() cls.text_img.display()
def __init__(self, dim, pos, client): self.pos = pos self.text_box = TextBox((dim[0], dim[1] - E(80)), C.WHITE, pos, marge=True, centered=False, font=Font.f30) self.input_text = InputText((dim[0] - E(120), E(80)), (pos[0], pos[1] + dim[1] - E(80)), C.WHITE, font=Font.f30) self.button_send = Button( DIM_B, C.LIGHT_BLUE, (pos[0] + dim[0] - E(120), pos[1] + dim[1] - E(80)), 'Send', font=Font.f30) self.client = client
def __init__(self, char, username, team_idx, is_client=False, base_weapon=None): self.img = chars[char] self.img = pygame.transform.scale(self.img, self.dim) self.original_img = self.img self.base_weapon = base_weapon self.active_weapon = base_weapon self.username = username self.team_idx = team_idx self.SPAWN_POS = SPAWN_POSITIONS[team_idx] self.text_username = TextBox(DIM_TNAME, TCOLORS[team_idx],[0,0],username, font=Font.f30, marge=True, TEXT_COLOR=C.WHITE) self.pos = list(self.SPAWN_POS) self.health = 100 self.set_corners() self.is_client = is_client # set delayer to jump deco_jump = Delayed(5) self.check_jump_client = deco_jump(self.check_jump_client) self.check_jump_server = deco_jump(self.check_jump_server)
def init(cls, client, Score): cls.client = client cls.Score = Score cls.text_weapons = TextBox(DIM_TITLE, C.WHITE, POS_TITLE, 'Choose your weapon:', font=Font.f100) cls.button_ready = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BSTART, 'Ready') cls.text_are_ready = TextBox(DIM_TEXT, C.WHITE, POS_TW, '0/n players ready', font=Font.f50) cls.button_ak = Button(DIM_BCHOOSEW, C.LIGHT_GREEN, (POS_BCWX, POS_BCWY), '', font=Font.f70, image=img_ak) cls.button_crossbow = Button(DIM_BCHOOSEW, C.LIGHT_GREEN, (POS_BCWX + E(300), POS_BCWY), '', font=Font.f70, image=img_crossbow) cls.button_sniper = Button(DIM_BCHOOSEW, C.LIGHT_GREEN, (POS_BCWX + E(600), POS_BCWY), '', font=Font.f70, image=img_sniper) cls.button_bazooka = Button(DIM_BCHOOSEW, C.LIGHT_GREEN, (POS_BCWX + E(900), POS_BCWY), '', font=Font.f70, image=img_bazooka) cls.n_players = cls.client.n_env_users # now the scope cursor is diplayed pygame.mouse.set_visible(False)
class PlayerResult: def __init__(self, pos, username, kill_count, lives, team_idx): self.pos = pos self.username = username self.kill_count = kill_count self.lives = lives self.team_idx = team_idx self.cadre = Cadre(DIM_PLAYER, C.WHITE, pos, set_transparent=True) self.text_username = TextBox(DIM_NAME, LTCOLORS[team_idx], pos, username, font=Font.f30) self.text_kills = TextBox(DIM_BOX, C.WHITE, (DIM_NAME[0] + pos[0], pos[1]), str(self.kill_count), font=Font.f30) self.text_deaths = TextBox(DIM_BOX, C.WHITE, (DIM_NAME[0] + DIM_BOX[0] + pos[0], pos[1]), str(3 - lives), font=Font.f30) def display(self): self.text_username.display() self.text_kills.display() self.text_deaths.display() self.cadre.display() # display in last to have proper marge
def __init__(self, pos, info, team_idx): self.pos = pos self.text_username = TextBox(DIM_NAME, C.WHITE, pos, 'username', font=Font.f30) self.text_kills = TextBox(DIM_BOX, C.WHITE, (DIM_NAME[0] + pos[0], pos[1]), 'kill(s)', font=Font.f30) self.text_deaths = TextBox(DIM_BOX, C.WHITE, (DIM_NAME[0] + DIM_BOX[0] + pos[0], pos[1]), 'death(s)', font=Font.f30) self.players_results = [] dy = DIM_PLAYERY for i in range(len(info['lives'])): pos = [self.pos[0], self.pos[1] + dy] username = info['players'][i].username kill_count = info['kill_count'][i] lives = info['lives'][i] new_player_res = PlayerResult(pos, username, kill_count, lives, team_idx) self.players_results.append(new_player_res) dy += DIM_PLAYERY
class FriendDemand: def __init__(self, x_dim, pos, username): self.pos = pos self.username = username text = f'Friend demand: {username}' self.text = TextBox((x_dim - MARGE, DIM_TY), C.LIGHT_GREY, pos, text, font=Font.f30) self.button_yes = Button(DIM_DFR_B, C.LIGHT_GREEN, (pos[0] + x_dim - 2 * DIM_DFR_B[0], pos[1]), image=img_vu) self.button_no = Button(DIM_DFR_B, C.LIGHT_RED, (pos[0] + x_dim - DIM_DFR_B[0], pos[1]), image=img_cross) def display(self): self.text.display() self.button_yes.display() self.button_no.display()
class Invitation: def __init__(self, x_dim, pos, username): self.pos = pos self.username = username text = f'Invitation from: {username}' self.text = TextBox((x_dim - MARGE, DIM_TY), C.LIGHT_GREY, pos, text, font=Font.f30) self.button_yes = Button(DIM_DFR_B, C.LIGHT_GREEN, (pos[0] + x_dim - MARGE, pos[1]), 'Yes', font=Font.f30) self.button_no = Button(DIM_DFR_B, C.LIGHT_RED, (pos[0] + x_dim - LMARGE, pos[1]), 'No', font=Font.f30) def display(self): self.text.display() self.button_yes.display() self.button_no.display()
class Friend: CTEXT = C.GREEN CBUTTON = C.LIGHT_GREEN def __init__(self, dim, pos, username, state): self.pos = pos self.username = username self.in_game = False self.state = state self.text = TextBox((int(5 / 8 * dim[0]), dim[1]), self.CTEXT, pos, username, font=Font.f30, marge=True) self.button_invite = Button((int(1 / 4 * dim[0]), dim[1]), self.CBUTTON, (pos[0] + int(5 / 8 * dim[0]), pos[1]), 'Invite', font=Font.f30) self.text_ingame = TextBox((int(1 / 4 * dim[0]), dim[1]), self.CBUTTON, (pos[0] + int(5 / 8 * dim[0]), pos[1]), 'In game', font=Font.f30) self.button_delete = Button((int(1 / 8 * dim[0]), dim[1]), C.LIGHT_GREY, (pos[0] + int(7 / 8 * dim[0]), pos[1]), 'Del', font=Font.f30) def display(self): if self.state == 'conn' or self.state == 'inenv': self.text.set_color(C.GREEN, marge=True) self.button_invite.set_color(C.LIGHT_GREEN, marge=True) else: self.text.set_color(C.RED, marge=True) self.button_invite.set_color(C.LIGHT_RED, marge=True) self.text.display() self.button_delete.display() if self.state == 'inenv': self.text_ingame.display() else: self.button_invite.display()
def __init__(self, dim, pos, client): self.dim = dim self.pos = (pos[0], pos[1] + DIM_TY ) # update pos to don't care about 'add friend' button self.client = client self.usernames = [] self.obj_friends = [] self.DIM_FR = (dim[0], DIM_TY) self.cadre = Cadre((dim[0], dim[1] - DIM_TY), C.WHITE, (pos[0], pos[1] + DIM_TY)) # state normal self.button_add = Button(DIM_BADD, C.LIGHT_BLUE, (pos[0] + dim[0] - MARGE, pos[1]), 'Add friend', font=Font.f30) # state add fr POS_TEXT = (self.pos[0] + E(20), self.pos[1] + 2 * E(20)) self.text_add = TextBox(DIM_LTB, C.WHITE, POS_TEXT, 'Send demand to someone', font=Font.f30) self.textin_add = TextBox(DIM_STB, C.WHITE, (POS_TEXT[0], POS_TEXT[1] + E(100)), 'Enter username:'******'Done', font=Font.f30) self.button_cancel = Button( DIM_B, C.LIGHT_BLUE, (self.pos[0] + E(20), self.pos[1] + self.dim[1] - E(140)), 'Cancel', font=Font.f30) # state fail self.text_fail = TextBox(DIM_LTB, C.WHITE, POS_TEXT, 'Invalid username', font=Font.f50, TEXT_COLOR=C.RED)
def __init__(self, pos, username, kill_count, lives, team_idx): self.pos = pos self.username = username self.kill_count = kill_count self.lives = lives self.team_idx = team_idx self.cadre = Cadre(DIM_PLAYER, C.WHITE, pos, set_transparent=True) self.text_username = TextBox(DIM_NAME, LTCOLORS[team_idx], pos, username, font=Font.f30) self.text_kills = TextBox(DIM_BOX, C.WHITE, (DIM_NAME[0] + pos[0], pos[1]), str(self.kill_count), font=Font.f30) self.text_deaths = TextBox(DIM_BOX, C.WHITE, (DIM_NAME[0] + DIM_BOX[0] + pos[0], pos[1]), str(3 - lives), font=Font.f30)
class Friends: state = NORMAL decal_y = 0 fr_demands = [] invs = [] def __init__(self, dim, pos, client): self.dim = dim self.pos = (pos[0], pos[1] + DIM_TY ) # update pos to don't care about 'add friend' button self.client = client self.usernames = [] self.obj_friends = [] self.DIM_FR = (dim[0], DIM_TY) self.cadre = Cadre((dim[0], dim[1] - DIM_TY), C.WHITE, (pos[0], pos[1] + DIM_TY)) # state normal self.button_add = Button(DIM_BADD, C.LIGHT_BLUE, (pos[0] + dim[0] - MARGE, pos[1]), 'Add friend', font=Font.f30) # state add fr POS_TEXT = (self.pos[0] + E(20), self.pos[1] + 2 * E(20)) self.text_add = TextBox(DIM_LTB, C.WHITE, POS_TEXT, 'Send demand to someone', font=Font.f30) self.textin_add = TextBox(DIM_STB, C.WHITE, (POS_TEXT[0], POS_TEXT[1] + E(100)), 'Enter username:'******'Done', font=Font.f30) self.button_cancel = Button( DIM_B, C.LIGHT_BLUE, (self.pos[0] + E(20), self.pos[1] + self.dim[1] - E(140)), 'Cancel', font=Font.f30) # state fail self.text_fail = TextBox(DIM_LTB, C.WHITE, POS_TEXT, 'Invalid username', font=Font.f50, TEXT_COLOR=C.RED) def add_friend(self, username, state): i = len(self.obj_friends) new_friend = Friend(self.DIM_FR, (self.pos[0], self.pos[1] + i * E(60)), username, state) self.obj_friends.append(new_friend) def check_connected(self): # check for connected/disconnected friends for username, state in self.client.friends.items(): if username in self.usernames: index = self.usernames.index(username) self.obj_friends[index].state = state else: self.usernames.append(username) self.add_friend(username, state) # get potential new friends demands new_friend_demands = self.client.get_demand_fr() for fr_d in new_friend_demands: current_fr_d = FriendDemand(self.dim[0], (self.pos[0], self.decal_y * E(60) + self.pos[1] + self.dim[1] - E(60)), fr_d) self.decal_y += 1 self.fr_demands.append(current_fr_d) # if a friend deleted you, reset friend if self.client.get_del_friend(): self.obj_friends = [] self.usernames = [] # get potential invitation from friends for username in self.client.get_invs(): new_inv = Invitation(self.dim[0], (self.pos[0], self.decal_y * E(60) + self.pos[1] + self.dim[1] - E(60)), username) self.decal_y += 1 self.invs.append(new_inv) def react_events(self, events, pressed): self.check_connected() if self.state == NORMAL: self.react_events_normal(events, pressed) elif self.state == ADD_FR: self.react_events_addfr(events, pressed) elif self.state == FAIL: self.react_events_fail(events, pressed) def react_events_normal(self, events, pressed): self.react_events_frd(events, pressed) self.react_events_invs(events, pressed) if self.button_add.pushed(events): self.state = ADD_FR for friend in self.obj_friends: if friend.button_delete.pushed(events): self.del_friend(friend) if friend.button_invite.pushed(events): if friend.state == 'conn': self.client.invite_friend(friend.username) def react_events_addfr(self, events, pressed): self.input_add.run(events, pressed) if self.button_cancel.pushed(events): self.state = NORMAL self.input_add.text = '' if self.button_done.pushed(events): username = self.input_add.text self.client.demand_friend(username) if self.client.is_dfr_valid != None: # receive a response if self.client.is_dfr_valid: self.state = NORMAL else: self.state = FAIL self.client.is_dfr_valid = None def react_events_frd(self, events, pressed): for frd in self.fr_demands: if frd.button_yes.pushed(events): self.client.return_friend_demand(frd.username, True) self.fr_demands.remove(frd) self.decal_y -= 1 if frd.button_no.pushed(events): self.client.return_friend_demand(frd.username, False) self.fr_demands.remove(frd) self.decal_y -= 1 def react_events_invs(self, events, pressed): for inv in self.invs: if inv.button_yes.pushed(events): self.client.return_inv_fr(inv.username) self.invs.remove(inv) self.decal_y -= 1 if inv.button_no.pushed(events): self.invs.remove(inv) self.decal_y -= 1 def react_events_fail(self, events, pressed): if self.button_done.pushed(events): self.state = NORMAL self.input_add.text = '' def del_friend(self, friend): self.obj_friends = [] self.usernames = [] self.client.del_friend(friend.username) def reset(self): self.usernames = [] self.obj_friends = [] self.fr_demands = [] def display(self): self.cadre.display() if self.state == NORMAL: self.display_normal() elif self.state == ADD_FR: self.display_addfr() elif self.state == FAIL: self.display_fail() def display_normal(self): self.button_add.display() for friend in self.obj_friends: friend.display() for frd in self.fr_demands: frd.display() for inv in self.invs: inv.display() def display_addfr(self): self.text_add.display() self.textin_add.display() self.input_add.display() self.button_done.display() self.button_cancel.display() def display_fail(self): self.button_done.display() self.text_fail.display() def get_obj_friend(self, username): for obj in self.obj_friends: if obj.username == username: return obj
def __init__(self, client): self.client = client self.state = 'main' # state main self.title_main = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Title', font=Font.f100) self.button_login = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BLOG,'Log in') self.button_signup = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BSIGN,'Sign up') # state login self.title_login = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Log in', font=Font.f100) self.text_logusername = TextBox(DIM_TEXTBL,C.WHITE, (X_POS_TEXTBL, Y_POS_TEXTBL), 'Username:'******'Password:'******'Done', font=Font.f30) self.button_back = Button(DIM_NB, C.LIGHT_BLUE, POS_BBACK,'Back', font=Font.f30) # state signup self.title_signup = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Sign up', font=Font.f100) # state fail log self.text_faillog = TextBox(DIM_FAILT, C.WHITE, (X_POS_TEXTBL2, Y_POS_FAILT), 'Invalid username or password', font=Font.f25, TEXT_COLOR=C.RED) # state fail sign self.text_failsign = TextBox(DIM_FAILT, C.WHITE, (X_POS_TEXTBL2, Y_POS_FAILT), 'Username already taken', font=Font.f25, TEXT_COLOR=C.RED) # state logged self.title_logged = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Welcome', font=Font.f100) self.text_username = TextBox(DIM_LOGINP, C.WHITE, (LMARGE, LMARGE),'',marge=True) self.button_play = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BPLAY, 'Play') self.chat_logged = Chat(DIM_CHAT, (MARGE,dim.y-DIM_CHAT[1]-MARGE), self.client) self.friends = Friends(DIM_FR, (dim.x-DIM_FR[0]-MARGE, E(250)), self.client) self.button_disconn = Button(DIM_LI_MAIN_B, C.LIGHT_BLUE, (LMARGE, MARGE+DIM_LOGINP[1]) ,'Disconnect',font=Font.f30) # state env self.title_env = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Env', font=Font.f100) self.text_wating = TextBox(DIM_TWAIT,C.WHITE, POS_TWAIT, 'Waiting for the other players...', font=Font.f30) self.button_exit = Button(DIM_BEXIT, C.LIGHT_BLUE, POS_BEXIT, 'Exit', font=Font.f30) self.teams = Teams self.teams.init(POS_TEAMS,DIM_TEAMS, client)
class Menu: play_pushed = False def __init__(self, client): self.client = client self.state = 'main' # state main self.title_main = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Title', font=Font.f100) self.button_login = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BLOG,'Log in') self.button_signup = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BSIGN,'Sign up') # state login self.title_login = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Log in', font=Font.f100) self.text_logusername = TextBox(DIM_TEXTBL,C.WHITE, (X_POS_TEXTBL, Y_POS_TEXTBL), 'Username:'******'Password:'******'Done', font=Font.f30) self.button_back = Button(DIM_NB, C.LIGHT_BLUE, POS_BBACK,'Back', font=Font.f30) # state signup self.title_signup = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Sign up', font=Font.f100) # state fail log self.text_faillog = TextBox(DIM_FAILT, C.WHITE, (X_POS_TEXTBL2, Y_POS_FAILT), 'Invalid username or password', font=Font.f25, TEXT_COLOR=C.RED) # state fail sign self.text_failsign = TextBox(DIM_FAILT, C.WHITE, (X_POS_TEXTBL2, Y_POS_FAILT), 'Username already taken', font=Font.f25, TEXT_COLOR=C.RED) # state logged self.title_logged = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Welcome', font=Font.f100) self.text_username = TextBox(DIM_LOGINP, C.WHITE, (LMARGE, LMARGE),'',marge=True) self.button_play = Button(DIM_MAIN_B, C.LIGHT_BLUE, POS_BPLAY, 'Play') self.chat_logged = Chat(DIM_CHAT, (MARGE,dim.y-DIM_CHAT[1]-MARGE), self.client) self.friends = Friends(DIM_FR, (dim.x-DIM_FR[0]-MARGE, E(250)), self.client) self.button_disconn = Button(DIM_LI_MAIN_B, C.LIGHT_BLUE, (LMARGE, MARGE+DIM_LOGINP[1]) ,'Disconnect',font=Font.f30) # state env self.title_env = TextBox(DIM_TITLE, C.WHITE, POS_TITLE,'Env', font=Font.f100) self.text_wating = TextBox(DIM_TWAIT,C.WHITE, POS_TWAIT, 'Waiting for the other players...', font=Font.f30) self.button_exit = Button(DIM_BEXIT, C.LIGHT_BLUE, POS_BEXIT, 'Exit', font=Font.f30) self.teams = Teams self.teams.init(POS_TEAMS,DIM_TEAMS, client) def display_main(self): self.title_main.display() self.button_login.display() self.button_signup.display() def display_login(self): self.title_login.display() self.text_logusername.display() self.text_password.display() self.input_username.display() self.input_password.display() self.button_back.display() self.button_done.display() def display_signup(self): self.title_signup.display() self.text_logusername.display() self.text_password.display() self.input_username.display() self.input_password.display() self.button_back.display() self.button_done.display() def display_logged(self): self.title_logged.display() self.text_username.display() self.button_disconn.display() self.button_play.display() self.chat_logged.display() self.friends.display() def display_env(self): self.title_env.display() self.text_username.display() if not self.play_pushed: self.button_play.display() else: self.text_wating.display() self.button_disconn.display() self.button_exit.display() self.chat_logged.display() self.friends.display() self.teams.display() def display_faillog(self): self.display_login() self.text_faillog.display() def display_failsign(self): self.display_signup() self.text_failsign.display() def react_events_main(self, events, pressed): if self.button_login.pushed(events): self.state = 'login' elif self.button_signup.pushed(events): self.state = 'signup' def react_events_login(self, events, pressed): self.input_username.run(events, pressed) self.input_password.run(events, pressed) if self.button_back.pushed(events): self.state = 'main' if self.button_done.pushed(events): username = self.input_username.text password = self.input_password.text if self.client.log(username, password): self.state = 'logged' self.text_username.set_text(username) self.teams.set_username(username) self.chat_logged.activate() else: self.state = 'fail log' def react_events_signup(self, events, pressed): self.input_username.run(events, pressed) self.input_password.run(events, pressed) if self.button_back.pushed(events): self.state = 'main' if self.button_done.pushed(events): username = self.input_username.text password = self.input_password.text if self.client == 1: self.state = 'logged' else: if self.client.sign_up(username, password): self.state = 'logged' self.text_username.set_text(username) self.teams.set_username(username) self.chat_logged.activate() else: self.state = 'fail sign' def react_events_logged(self, events, pressed): self.chat_logged.react_events(events, pressed) if self.button_play.pushed(events): print('play') if self.button_disconn.pushed(events): self.disconn() self.friends.react_events(events, pressed) # check for env if self.client.in_env: self.teams.set_players() # must have receive players connected from server (env) self.state = 'env' def react_events_env(self, events, pressed): self.chat_logged.react_events(events, pressed) self.teams.react_events(events, pressed) if self.button_disconn.pushed(events): self.disconn() self.friends.react_events(events, pressed) if not self.play_pushed: if self.button_play.pushed(events): self.client.env_play() self.play_pushed = True if self.button_exit.pushed(events): self.client.quit_game_or_env() if self.client.in_game_session: start_game(self.client) self.state = 'in game' def disconn(self): self.client.disconn() self.state = 'main' self.input_password.text = '' self.input_username.text = '' self.chat_logged.reset() self.friends.reset() def run(self, events, pressed): if self.state == 'in game': if not self.client.in_game_session: if self.client.in_env: self.state = 'env' else: self.state = 'logged' run_game(pressed, events) elif self.state == 'main': self.display_main() self.react_events_main(events, pressed) elif self.state == 'login': self.display_login() self.react_events_login(events, pressed) elif self.state == 'signup': self.react_events_signup(events, pressed) self.display_signup() elif self.state == 'logged': self.display_logged() self.react_events_logged(events, pressed) elif self.state == 'env': self.display_env() self.react_events_env(events, pressed) if not self.client.in_env: self.state = 'logged' elif self.state == 'fail log': self.display_faillog() self.react_events_login(events, pressed) elif self.state == 'fail sign': self.display_failsign() self.react_events_signup(events, pressed)
class Player: orien = 0 SPEED = E(15) POWER_JUMP = math.sqrt(150) POS_W = scale((50,100), dim.f) dim = DIM_P dead = False client = None # gravity dh = 0 can_jump = False # health bar health_surf = pygame.Surface(DIM_HB) health_surf.fill(C.GREEN) # delay check pos delay = 0 DTIME = 100 def __init__(self, char, username, team_idx, is_client=False, base_weapon=None): self.img = chars[char] self.img = pygame.transform.scale(self.img, self.dim) self.original_img = self.img self.base_weapon = base_weapon self.active_weapon = base_weapon self.username = username self.team_idx = team_idx self.SPAWN_POS = SPAWN_POSITIONS[team_idx] self.text_username = TextBox(DIM_TNAME, TCOLORS[team_idx],[0,0],username, font=Font.f30, marge=True, TEXT_COLOR=C.WHITE) self.pos = list(self.SPAWN_POS) self.health = 100 self.set_corners() self.is_client = is_client # set delayer to jump deco_jump = Delayed(5) self.check_jump_client = deco_jump(self.check_jump_client) self.check_jump_server = deco_jump(self.check_jump_server) @property def x(self): return self.pos[0] @x.setter def x(self, value): self.pos[0] = value self.active_weapon.set_pos((self.pos[0]+self.POS_W[0], self.pos[1]+self.POS_W[1])) @property def y(self): return self.pos[1] @y.setter def y(self, value): self.pos[1] = value self.active_weapon.set_pos((self.pos[0]+self.POS_W[0], self.pos[1]+self.POS_W[1])) def set_weapon(self, weapon): self.active_weapon = weapon self.active_weapon.set_pos((self.pos[0]+self.POS_W[0], self.pos[1]+self.POS_W[1])) def set_corners(self): self.TOPLEFT = self.pos self.TOPRIGHT = (self.pos[0]+self.dim[0],self.pos[1]) self.BOTTOMLEFT = (self.pos[0], self.pos[1]+self.dim[1]) self.BOTTOMRIGHT = (self.pos[0]+self.dim[0],self.pos[1]+self.dim[1]) self.corners = (self.TOPLEFT, self.TOPRIGHT, self.BOTTOMLEFT, self.BOTTOMRIGHT) @Counter.call def react_events_client(self, pressed, events): self.orien = self.get_angle() fire, left, right, jump = 0,0,0,0 for event in events: if event.type == pygame.MOUSEBUTTONDOWN: as_shot = self.active_weapon.fire(self.orien, self.team_idx, self.username) fire = as_shot if pressed[pygame.K_a]: left = 1 self.move_left() if pressed[pygame.K_d]: right = 1 self.move_right() if pressed[pygame.K_SPACE] and self.can_jump: jump = 1 # check if player is moving if not left and not right and self.dh in [0,1]: pos = scale(self.pos, 1/dim.f) # standartize coord else: pos = None self.client.env_game(self.orien, fire, left, right, jump, pos) self.active_weapon.rotate(self.orien) self.active_weapon.update() self.check_jump_client(pressed) def react_events_server(self, comm): if 'angle' in comm.keys(): self.orien = comm['angle'] self.active_weapon.rotate(self.orien) self.active_weapon.update() if 'fire' in comm.keys(): self.active_weapon.fire(self.orien, self.team_idx, self.username, from_server=True) if comm['left']: self.move_left() if comm['right']: self.move_right() self.check_jump_server(comm) # check for a potential position update if 'x' in comm.keys(): self.x = E(comm['x']) self.y = E(comm['y']) def check_jump_client(self, pressed): if pressed[pygame.K_SPACE] and self.can_jump: self.dh = -self.POWER_JUMP self.can_jump = False return True return False def check_jump_server(self, comm): if 'jump' in comm.keys() and self.can_jump: self.dh = -self.POWER_JUMP self.can_jump = False return True return False def get_angle(self): mouse_pos = pygame.mouse.get_pos() weapon_pos = self.active_weapon.rect.center angle = cal_angle(mouse_pos, weapon_pos) return angle def move_left(self): self.x = self.pos[0] - self.SPEED def move_right(self): self.x = self.pos[0] + self.SPEED def collisions(self,platforms): self.set_corners() for platform in platforms: is_col, from_above, new_pos = platform.collision(self.corners) if is_col: self.x = new_pos[0] self.y = new_pos[1] # if was jumping -> stop the jump if self.dh < 0: self.dh = 0 if from_above: # touch ground -> can jump self.dh = 0 self.can_jump = True break self.collision_bordure() def update(self): # gravity self.y = self.pos[1] + E(int(1/2*self.dh*abs(self.dh))) self.dh += 1 def collision_bordure(self): # check screen bordure if self.x < 0: self.x = 0 elif self.x > dim.x - DIM_P[0]: self.x = dim.x - DIM_P[0] if self.y < 0: self.y = 0 elif self.y > dim.y - DIM_P[1]: # touch ground -> can jump self.dh = 0 self.can_jump = True self.y = dim.y - DIM_P[1] def touch_hitbox(self, pos): if pos[1] > self.TOPLEFT[1] and pos[1] < self.BOTTOMLEFT[1]: if pos[0] > self.TOPLEFT[0] and pos[0] < self.TOPRIGHT[0]: return True def get_hit(self, damage, shooter, Score): self.health -= damage # check if player is dead if self.health <= 0: self.health = 1 # temporary set a health -> waiting for the death confirmation Score.is_dead(self, shooter) def display_health(self): # get red part x = int((100-self.health) * DIM_HB[0]/100) red_surf = pygame.Surface((x,DIM_HB[1])) red_surf.fill(C.RED) screen.blit(self.health_surf, (self.pos[0]+E(15),self.pos[1]-E(30))) decal_x = DIM_HB[0] - x screen.blit(red_surf, (self.pos[0]+E(15)+decal_x,self.pos[1]-E(30))) def display_username(self): rect = self.text_username.surf.get_rect() new_pos = (int(self.pos[0] + self.dim[0]/2), self.pos[1] - E(60)) self.text_username.set_pos(new_pos, center=True) self.text_username.display() def display(self): screen.blit(self.img, self.pos) self.display_health() self.display_username() self.active_weapon.display() def respawn(self): self.x = self.SPAWN_POS[0] self.y = self.SPAWN_POS[1] self.dead = False self.health = 100
class Score: text_end = TextBox(DIM_TEXTEND,C.WHITE, POS_TEXTEND,'', font=Font.f100, marge=True) button_back = Button(DIM_BBACK, C.LIGHT_BLUE, POS_BBACK, 'Exit') text_team = TextBox(DIM_TTEAM, C.LIGHT_BROWN, (0,0),'', font=Font.f70, marge=True) text_player = TextBox(DIM_TP, C.LIGHT_BROWN, (0,0),'', font=Font.f50, centered=False, marge=True) text_left = TextBox(DIM_TLEFT, C.WHITE, POS_TLEFT, '',font=Font.f30) scoretable = ScoreTable winner = 0 client_player = None client = None ended = False left_players = {} # dict: username:lifetime @classmethod def set_teams(cls, teams): cls.teams = {} cls.players = [] cls.team_idxs = [] for i, players in teams.items(): cls.team_idxs.append(i) lives = [3 for player in players] have_losts = [False for player in players] kill_count = [0 for player in players] d = {'players':players,'lives':lives, 'have_losts':have_losts, 'kill_count':kill_count} cls.teams[i] = d cls.players.extend(players) cls.n_team = len(cls.teams) cls.losts = [False for _ in range(cls.n_team)] @classmethod def display_lives(cls): cls.display_left_players() dy = 0 for u, team in cls.teams.items(): cls.text_team.set_text(f'Team {u}') cls.text_team.set_color(TCOLORS[u], marge=True) cls.text_team.set_pos((POS_SC[0],POS_SC[1]+dy)) cls.text_team.display() dy += E(100) for i, player in enumerate(team['players']): cls.text_player.set_text(player.username) cls.text_player.set_color(TCOLORS[u], marge=True) cls.text_player.set_pos((POS_SC[0],POS_SC[1]+dy)) cls.text_player.display() for e in range(team['lives'][i]): screen.blit(heart_img, (POS_SC[0]+E(100)+e*E(60),POS_SC[1]+E(5)+dy)) dy += E(80) @classmethod def is_dead(cls, other_player, killer_username): for team in cls.teams.values(): for i, player in enumerate(team['players']): if player is other_player: cls.client.game_dead_player(player.username, killer_username) @classmethod def check_confirmed_death(cls): for info in cls.client.dead_players: dead_player = cls.get_player(info['dead']) for team in cls.teams.values(): for i, player in enumerate(team['players']): if player is dead_player: team_idx, idx = cls.get_index(info['killer']) cls.teams[team_idx]['kill_count'][idx] += 1 #increase kill count of killer player player.dead = True team['lives'][i] -= 1 if team['lives'][i] == 0: team['have_losts'][i] = True else: player.respawn() cls.client.dead_players = [] @classmethod def check_confirmed_hit(cls): for info in cls.client.hit_players: hit_player = cls.get_player(info['username']) hit_player.get_hit(info['damage'], info['shooter'], cls) cls.client.hit_players = [] @classmethod def check_leaving_players(cls): for username in cls.client.ingame_quit_players: team_idx, idx = cls.get_index(username) # change leaving player state to 'have lost' cls.teams[team_idx]['have_losts'][idx] = True cls.teams[team_idx]['lives'][idx] = 0 cls.left_players[username] = LEFT_MSG_LIFETIME cls.client.ingame_quit_players = [] @classmethod def have_lost(cls, other_player): for team in cls.teams.values(): for i, player in enumerate(team['players']): if player is other_player: return team['have_losts'][i] @classmethod def check_win(cls): # update teams status for u, team in cls.teams.items(): lost = True for i in range(len(team['players'])): if not team['have_losts'][i]: lost = False if lost: cls.losts[u] = True # check for one winner n_loser = cls.losts.count(True) if n_loser == cls.n_team - 1: # get the winner for i, v in enumerate(cls.losts): if v == False: cls.winner = cls.team_idxs[i] cls.ended = True # set score table pos_x = E(cposx((500*cls.n_team,0))) cls.scoretable.init((pos_x, POS_SCORETY), cls) # send result to server cls.send_results() cls.text_end.set_text(f'Winner Team {cls.winner}') # set color if cls.winner == cls.client_team: cls.text_end.set_color(C.LIGHT_GREEN, marge=True) else: cls.text_end.set_color(C.LIGHT_RED, marge=True) @classmethod def react_events(cls): cls.check_leaving_players() cls.check_confirmed_hit() cls.check_confirmed_death() for comm in cls.client.game_msgs: username = comm['username'] player = cls.get_player(username) if not cls.client_player is player: try: player.react_events_server(comm) except: print("[ERROR] Can't react to server frame message") cls.client.game_msgs = [] @classmethod def run_end(cls, events, pressed): cls.react_events_end(events, pressed) cls.display_end() @classmethod def react_events_end(cls, events, pressed): if cls.button_back.pushed(events): cls.client.in_game = False cls.client.in_game_session = False cls.client.quit_game_or_env() pygame.mouse.set_visible(True) @classmethod def display_end(cls): cls.text_end.display() cls.button_back.display() cls.scoretable.display() @classmethod def display_left_players(cls): text = '' to_pop = [] for username in cls.left_players.keys(): cls.left_players[username] -= 1 if cls.left_players[username] == 0: to_pop.append(username) else: text += f"{username} left game\n" # remove old left players for username in to_pop: cls.left_players.pop(username) if text != '': # update and display text cls.text_left.set_text(text) cls.text_left.display() @classmethod def get_player(cls, username): for player in cls.players: if player.username == username: return player @classmethod def get_index(cls, username): ''' Return the index of the team and the index of the player in the team (u, i)''' for u, team in cls.teams.items(): for i, player in enumerate(team['players']): if player.username == username: return (u, i) @classmethod def send_results(cls): team_idx, idx = cls.get_index(cls.client_player.username) kills = cls.teams[team_idx]['kill_count'][idx] deaths = 3 - cls.teams[team_idx]['lives'][idx] cls.client.send_results(kills, deaths) @classmethod def reset(cls): cls.winner = 0 cls.client_player = None cls.client = None cls.ended = False cls.teams = {} cls.players = [] cls.losts = []
class Chat: msgs = [] MAX_MSG = 8 def __init__(self, dim, pos, client): self.pos = pos self.text_box = TextBox((dim[0], dim[1] - E(80)), C.WHITE, pos, marge=True, centered=False, font=Font.f30) self.input_text = InputText((dim[0] - E(120), E(80)), (pos[0], pos[1] + dim[1] - E(80)), C.WHITE, font=Font.f30) self.button_send = Button( DIM_B, C.LIGHT_BLUE, (pos[0] + dim[0] - E(120), pos[1] + dim[1] - E(80)), 'Send', font=Font.f30) self.client = client def activate(self): self.client_thread = Thread(target=self.client.loop_msg) self.client_thread.start() def reset(self): self.msgs = [] def display(self): self.text_box.display() self.input_text.display() self.button_send.display() def add_msg(self, username, msg): if len(self.msgs) == self.MAX_MSG: self.msgs.pop(0) new_msg = f'{username}: {msg}' self.msgs.append(new_msg) text = ['\n' for i in range(self.MAX_MSG - 1)] text.insert(0, self.msgs[0]) for i in range(len(self.msgs) - 1): text[i + 1] += self.msgs[i + 1] new_text = cumsum(text, '') self.text_box.set_text(new_text) def react_events(self, events, pressed): self.input_text.run(events, pressed) if self.button_send.pushed(events): msg = self.input_text.text self.input_text.text = '' self.client.send_chat_msg(msg) self.add_msg(self.client.username, msg) for content in self.client.chat_msgs: self.add_msg(content[0], content[1]) self.client.chat_msgs = []
class Score: text_end = TextBox(DIM_TEXTEND, C.WHITE, POS_TEXTEND, '', font=Font.f100, marge=True) button_back = Button(DIM_BBACK, C.LIGHT_BLUE, POS_BBACK, 'Exit') text_team = TextBox(DIM_TTEAM, C.LIGHT_BROWN, (0, 0), '', font=Font.f70, marge=True) text_player = TextBox(DIM_TP, C.LIGHT_BROWN, (0, 0), '', font=Font.f50, centered=False, marge=True) winner = 0 client_player = None client = None ended = False @classmethod def set_teams(cls, teams): cls.teams = {} cls.players = [] cls.team_idxs = [] for i, players in teams.items(): cls.team_idxs.append(i) lives = [3 for player in players] have_losts = [False for player in players] d = {'players': players, 'lives': lives, 'have_losts': have_losts} cls.teams[i] = d cls.players.extend(players) cls.n_team = len(cls.teams) cls.losts = [False for _ in range(cls.n_team)] @classmethod def display_lives(cls): dy = 0 for u, team in cls.teams.items(): cls.text_team.set_text(f'Team {u}') cls.text_team.set_color(TCOLORS[u], marge=True) cls.text_team.set_pos((POS_SC[0], POS_SC[1] + dy)) cls.text_team.display() dy += E(100) for i, player in enumerate(team['players']): cls.text_player.set_text(player.username) cls.text_player.set_color(TCOLORS[u], marge=True) cls.text_player.set_pos((POS_SC[0], POS_SC[1] + dy)) cls.text_player.display() for e in range(team['lives'][i]): screen.blit(heart_img, (POS_SC[0] + E(100) + e * E(60), POS_SC[1] + E(5) + dy)) dy += E(80) @classmethod def is_dead(cls, other_player): for team in cls.teams.values(): for i, player in enumerate(team['players']): if player is other_player: cls.client.game_dead_player(player.username) @classmethod def check_confirmed_death(cls): for username in cls.client.dead_players: dead_player = cls.get_player(username) for team in cls.teams.values(): for i, player in enumerate(team['players']): if player is dead_player: player.dead = True team['lives'][i] -= 1 if team['lives'][i] == 0: team['have_losts'][i] = True else: player.respawn() cls.client.dead_players = [] @classmethod def have_lost(cls, other_player): for team in cls.teams.values(): for i, player in enumerate(team['players']): if player is other_player: return team['have_losts'][i] @classmethod def check_win(cls): # update teams status for u, team in cls.teams.items(): lost = True for i in range(len(team['players'])): if not team['have_losts'][i]: lost = False if lost: cls.losts[u] = True # check for one winner n_loser = cls.losts.count(True) if n_loser == cls.n_team - 1: # get the winner for i, v in enumerate(cls.losts): if v == False: cls.winner = cls.team_idxs[i] cls.ended = True cls.text_end.set_text(f'Winner Team {cls.winner}') # set color if cls.winner == cls.client_team: cls.text_end.set_color(C.LIGHT_GREEN, marge=True) else: cls.text_end.set_color(C.LIGHT_RED, marge=True) @classmethod def get_player(cls, username): for player in cls.players: if player.username == username: return player @classmethod def react_events(cls): cls.check_confirmed_death() for comm in cls.client.game_msgs: username = comm['username'] player = cls.get_player(username) player.react_events_server(comm) cls.client.game_msgs = [] @classmethod def run_end(cls, events, pressed): cls.react_events_end(events, pressed) cls.display_end() @classmethod def react_events_end(cls, events, pressed): if cls.button_back.pushed(events): cls.client.in_game = False cls.client.in_game_session = False cls.client.quit_game_or_env() pygame.mouse.set_visible(True) @classmethod def display_end(cls): cls.text_end.display() cls.button_back.display() @classmethod def reset(cls): cls.winner = 0 cls.client_player = None cls.client = None cls.ended = False cls.teams = {} cls.players = []