commit 873f5251016d792927b8672b1fc22a2d725675dd Author: The-Tysonator Date: Sun Apr 23 20:37:17 2023 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc6664a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_STORE +venv/ \ No newline at end of file diff --git a/assets/backgrounds/background_cave.png b/assets/backgrounds/background_cave.png new file mode 100755 index 0000000..8dfa2ee Binary files /dev/null and b/assets/backgrounds/background_cave.png differ diff --git a/assets/backgrounds/background_menu.png b/assets/backgrounds/background_menu.png new file mode 100755 index 0000000..b0e9325 Binary files /dev/null and b/assets/backgrounds/background_menu.png differ diff --git a/assets/blocks/block_cave.png b/assets/blocks/block_cave.png new file mode 100755 index 0000000..8442ba5 Binary files /dev/null and b/assets/blocks/block_cave.png differ diff --git a/assets/blocks/dirt_cave.png b/assets/blocks/dirt_cave.png new file mode 100755 index 0000000..c7be9fe Binary files /dev/null and b/assets/blocks/dirt_cave.png differ diff --git a/assets/buttons/ipaddress.png b/assets/buttons/ipaddress.png new file mode 100755 index 0000000..fe69c62 Binary files /dev/null and b/assets/buttons/ipaddress.png differ diff --git a/assets/buttons/menu.png b/assets/buttons/menu.png new file mode 100755 index 0000000..145cbdb Binary files /dev/null and b/assets/buttons/menu.png differ diff --git a/assets/buttons/online.png b/assets/buttons/online.png new file mode 100755 index 0000000..e7d8c57 Binary files /dev/null and b/assets/buttons/online.png differ diff --git a/assets/buttons/port.png b/assets/buttons/port.png new file mode 100755 index 0000000..ae67b28 Binary files /dev/null and b/assets/buttons/port.png differ diff --git a/assets/buttons/survival.png b/assets/buttons/survival.png new file mode 100755 index 0000000..fa6c38a Binary files /dev/null and b/assets/buttons/survival.png differ diff --git a/assets/fonts/Blocky.ttf b/assets/fonts/Blocky.ttf new file mode 100755 index 0000000..cd6e4c9 Binary files /dev/null and b/assets/fonts/Blocky.ttf differ diff --git a/assets/leveldata/level_data.txt b/assets/leveldata/level_data.txt new file mode 100755 index 0000000..26d1e6e Binary files /dev/null and b/assets/leveldata/level_data.txt differ diff --git a/assets/players/player.png b/assets/players/player.png new file mode 100755 index 0000000..f92aaab Binary files /dev/null and b/assets/players/player.png differ diff --git a/client.py b/client.py new file mode 100755 index 0000000..bfbf248 --- /dev/null +++ b/client.py @@ -0,0 +1,358 @@ +# Stop Imports +if __name__ == "__main__": + # Imports + import pygame + import pickle + import threading + import sys + import os + import re + from inputs import Button + from inputs import GetInputs + from inputs import IpAddressInput + from inputs import PortInput + from inputs import NameInput + from network import Client + # Pygame Setup + screen_width = 1280 + screen_height = 700 + screen = pygame.display.set_mode((screen_width, screen_height)) + pygame.display.set_caption("Shooty Arena") + clock = pygame.time.Clock() + font = pygame.font.SysFont(None, 12) + text = font.render("", False, (0, 0, 0)) + # Variables + menu_main = True + menu_online = False + menu_offline = False + menu_custom = False + menu_settings = False + online = False + offline = False + custom = False + ip_address_input = None + port_input = None + ip_address = None + port = None + network = None + facing = 1 + require_name = True + name = None + # Load Images + def resource_path(relative_path): + try: + base_path = sys._MEIPASS + except Exception: + base_path = os.path.abspath(".") + return os.path.join(base_path, relative_path) + cave_image_menu_background_url = resource_path("assets/backgrounds/background_menu.png") + cave_image_menu_background = pygame.image.load(cave_image_menu_background_url).convert() + cave_image_game_background_url = resource_path("assets/backgrounds/background_cave.png") + cave_image_game_background = pygame.image.load(cave_image_game_background_url).convert() + cave_image_dirt_url = resource_path("assets/blocks/dirt_cave.png") + cave_image_dirt = pygame.image.load(cave_image_dirt_url).convert() + cave_image_block_url = resource_path("assets/blocks/block_cave.png") + cave_image_block = pygame.image.load(cave_image_block_url).convert() + cave_image_player_url = resource_path("assets/players/player.png") + cave_image_player = pygame.image.load(cave_image_player_url).convert() + cave_image_player_flipped = pygame.transform.flip(cave_image_player, True, False).convert() + cave_image_online_url = resource_path("assets/buttons/online.png") + cave_image_online = pygame.image.load(cave_image_online_url).convert() + cave_image_survival_url = resource_path("assets/buttons/survival.png") + cave_image_survival = pygame.image.load(cave_image_survival_url).convert() + cave_image_menu_url = resource_path("assets/buttons/menu.png") + cave_image_menu = pygame.image.load(cave_image_menu_url).convert() + cave_image_ip_address_url = resource_path("assets/buttons/ipaddress.png") + cave_image_ip_address = pygame.image.load(cave_image_ip_address_url).convert_alpha() + cave_image_port_url = resource_path("assets/buttons/port.png") + cave_image_port = pygame.image.load(cave_image_port_url).convert_alpha() + # Create Buttons + cave_button_online = Button(screen, cave_image_online, 480, 450) + cave_button_online_two = Button(screen, cave_image_online, 580, 450) + cave_button_survival = Button(screen, cave_image_survival, 700, 450) + cave_button_menu = Button(screen, cave_image_menu, 1150, 30) + cave_button_ip_address = Button(screen, cave_image_ip_address, 5, 5) + cave_button_port = Button(screen, cave_image_port, 50, 50) + # Create Input Fields + input_ip_address = IpAddressInput() + input_port = PortInput() + input_name = NameInput() + # Generate World Data + pickle_in_url = resource_path("assets/leveldata/level_data.txt") + pickle_in = open(pickle_in_url, "rb") + tile_list = pickle.load(pickle_in) + world_data = [] + tile_size = 20 + row_count = 0 + for row in tile_list: + column_count = 0 + for tile in row: + # Dirt + if tile == 1: + block = cave_image_dirt + tile = pygame.transform.scale(block, (tile_size, tile_size)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + # Down + if tile == 2: + block = cave_image_block + tile = pygame.transform.scale(block, (tile_size, tile_size)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + # Left + if tile == 3: + block = cave_image_block + block = pygame.transform.rotate(block, 270) + tile = pygame.transform.scale(block, (tile_size, tile_size)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + # Right + if tile == 4: + block = cave_image_block + block = pygame.transform.rotate(block, 90) + tile = pygame.transform.scale(block, (20,20)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + column_count+=1 + row_count+=1 + # Bullet Class + class Bullet(object): + # Init + def __init__(self, x, y, radius, color, facing): + self.x = x + self.y = y + self.radius = radius + self.color = color + self.facing = facing + self.vel = 20 * facing + # Draw + def draw(self, screen): + pygame.draw.circle(screen, self.color, (self.x, self.y), self.radius) + # Game Loop + run = True + pygame.font.init() + pygame.init() + font = pygame.font.SysFont("../assets/fonts/Blocky.tff", 40) + font_player = pygame.font.SysFont("../assets/fonts/Blocky.tff", 18) + while run: + # Tick + clock.tick(60) + # Main Menu + if menu_main: + # Background + screen.blit(cave_image_menu_background, (0, 0)) + # Online Button + if cave_button_online.draw(): + menu_main = False + menu_online = True + # Survival Button + if cave_button_survival.draw(): + pass + # Print Text + screen.blit(text, (530, 550)) + # Online Menu + if menu_online: + screen.blit(cave_image_game_background, (0, 0)) + require_name = True + if require_name: + input_name.update(events) + screen.blit(input_name.get_surface(), (650, 300)) + text = font.render("Choose a name: ", True, (255, 255, 0)) + screen.blit(text, (400, 300)) + if input_name.get_text(): + pattern = re.compile("[A-Za-z0-9]+") + valid_name = pattern.fullmatch(input_name.get_text()) + if cave_button_online_two.draw(): + if valid_name: + try: + print("tye") + port = int(9306) + ip_address = "127.0.0.1" + network = Client(ip_address, port) + message = network.receive_string() + print("rec") + if message == "!JOIN": + text = font.render("", True, (255, 255, 0)) + menu_online = False + online = True + player_name = f"{input_name.get_text()}" + network.send_string(player_name) + require_name = False + elif message == "!FULL": + text = font.render("Server Full", True, (255, 255, 0)) + except: + text = font.render("Server Not Found", True, (255, 255, 0)) + if not valid_name: + text2 = font.render("Please only use letters and numbers.", True, (255, 255, 0)) + screen.blit(text2, (375, 375)) + if cave_button_menu.draw(): + text = font.render("", True, (255, 255, 0)) + menu_online = False + menu_main = True + # Online Game + if online: + # Background + screen.blit(cave_image_game_background, (0, 0)) + # World + for tile in world_data: + screen.blit(tile[0], (tile[1].x, tile[1].y - 20)) + # Menu Button + if cave_button_menu.draw(): + network.send_string("!DISSCONNECT") + text = font.render("", True, (255, 255, 0)) + online = False + menu_main = True + if online: + # Send Inputs To Server + up, left, right, mouse_position, facing = GetInputs(facing) + network.send_string(f"{up}@{left}@{right}@{mouse_position}@{pygame.mouse.get_pressed()}@{facing}") + # Receive Inputs + response = network.receive_string() + all_bullets = network.receive_byte() + score = network.receive_string() + facings = network.receive_string() + names = network.receive_string() + response = response.replace("[","") + response = response.replace("]","") + response = response.replace(" ","") + response = response.split(",") + facings = facings.replace("[","") + facings = facings.replace("]","") + facings = facings.replace(" ","") + facings = facings.split(",") + # Player Coordinates + onex = int(response[0]) + oney = int(response[1]) + twox = int(response[2]) + twoy = int(response[3]) + threex = int(response[4]) + threey = int(response[5]) + fourx = int(response[6]) + foury = int(response[7]) + fivex = int(response[8]) + fivey = int(response[9]) + sixx = int(response[10]) + sixy = int(response[11]) + # Player Names + names = names.replace("[","") + names = names.replace("]","") + names = names.replace("'","") + names = names.replace(" ","") + names = names.split(",") + player_one_name = names[0] + player_two_name = names[1] + player_three_name = names[2] + player_four_name = names[3] + player_five_name = names[4] + player_six_name = names[5] + # Display Player One + if facings[0] == "1": + text = font_player.render(player_one_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (onex - (text_width / 2) + 10, oney - 20)) + screen.blit(cave_image_player, (onex, oney)) + else: + text = font_player.render(player_one_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (onex - (text_width / 2) + 10, oney - 20)) + screen.blit(cave_image_player_flipped, (onex, oney)) + # Display Player Two + if facings[1] == "1": + text = font_player.render(player_two_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (twox - (text_width / 2) + 10, twoy - 20)) + screen.blit(cave_image_player, (twox, twoy)) + else: + text = font_player.render(player_two_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (twox - (text_width / 2) + 10, twoy - 20)) + screen.blit(cave_image_player_flipped, (twox, twoy)) + # Display Player Three + if facings[2] == "1": + text = font_player.render(player_three_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (threex - (text_width / 2) + 10, threey - 20)) + screen.blit(cave_image_player, (threex, threey)) + else: + text = font_player.render(player_three_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (threex - (text_width / 2) + 10, threey - 20)) + screen.blit(cave_image_player_flipped, (threex, threey)) + # Display Player 4 + if facings[3] == "1": + text = font_player.render(player_four_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (fourx - (text_width / 2) + 10, foury - 20)) + screen.blit(cave_image_player, (fourx, foury)) + else: + text = font_player.render(player_four_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (fourx - (text_width / 2) + 10, foury - 20)) + screen.blit(cave_image_player_flipped, (fourx, foury)) + # Display Player 5 + if facings[4] == "1": + text = font_player.render(player_five_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (fivex - (text_width / 2) + 10, fivey - 20)) + screen.blit(cave_image_player, (fivex, fivey)) + else: + text = font_player.render(player_five_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (fivex - (text_width / 2) + 10, fivey - 20)) + screen.blit(cave_image_player_flipped, (fivex, fivey)) + # Display Player 6 + if facings[5] == "1": + text = font_player.render(player_six_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (sixx - (text_width / 2) + 10, sixy - 20)) + screen.blit(cave_image_player, (sixx, sixy)) + else: + text = font_player.render(player_six_name, True, (255, 255, 0)) + text_width = text.get_width() + screen.blit(text, (sixx - (text_width / 2) + 10, sixy - 20)) + screen.blit(cave_image_player_flipped, (sixx, sixy)) + # Display Bullets + bullets = pickle.loads(all_bullets) + for bullet in bullets[0]: + bullet.draw(screen) + for bullet in bullets[1]: + bullet.draw(screen) + for bullet in bullets[2]: + bullet.draw(screen) + for bullet in bullets[3]: + bullet.draw(screen) + for bullet in bullets[4]: + bullet.draw(screen) + for bullet in bullets[5]: + bullet.draw(screen) + # Kill Counter + text = font.render(f"Kills: {score}", False, (255, 255, 0)) + screen.blit(text, (20, 20)) + # Event Handler + events = pygame.event.get() + for event in events: + # QUIT + if event.type == pygame.QUIT: + run = False + # Update Display + pygame.display.update() + # End Of Game Loop + # Final Dissconnection Message + try: + network.send_string("!DISSCONNECT") + except: + pass +else: + exit() diff --git a/inputs.py b/inputs.py new file mode 100755 index 0000000..87568aa --- /dev/null +++ b/inputs.py @@ -0,0 +1,389 @@ +# Only Allow Imports +if __name__ == "__main__": + exit() +else: + # Imports + import pygame + import time + import pygame.locals as pl + import os.path + pygame.font.init() + # Button + class Button(): + # Init + def __init__(self, screen, image, x, y): + self.screen = screen + self.image = image + self.rect = self.image.get_rect() + self.rect.x = x + self.rect.y = y + # Draw + def draw(self): + self.screen.blit(self.image, self.rect) + if self.rect.collidepoint(pygame.mouse.get_pos()): + if pygame.mouse.get_pressed()[0] == 1: + time.sleep(0.1) + return True + return False + # Get Inputs + def GetInputs(facing): + up = 0 + left = 0 + right = 0 + mouse_position = pygame.mouse.get_pos() + key = pygame.key.get_pressed() + if key[pygame.K_w]: + up = 1 + if key[pygame.K_a]: + left = 1 + facing = -1 + if key[pygame.K_d]: + right = 1 + facing = 1 + return up, left, right, mouse_position, facing + # ip_addres + class IpAddressInput: + # Init + def __init__( + # Choose Parameters + self, + initial_string = "", + font_family = "", + font_size = 35, + antialias = False, + text_color = (0, 0, 0), + cursor_color = (0, 0, 1), + repeat_keys_initial_ms = 400, + repeat_keys_interval_ms = 35, + max_string_length = 39, + password = False): + # Rest Of Init + self.antialias = antialias + self.text_color = text_color + self.font_size = font_size + self.max_string_length = max_string_length + self.password = password + self.input_string = initial_string + if not os.path.isfile(font_family): + font_family = pygame.font.match_font(font_family) + self.font_object = pygame.font.Font(font_family, font_size) + self.surface = pygame.Surface((1, 1)) + self.surface.set_alpha(0) + self.keyrepeat_counters = {} + self.keyrepeat_intial_interval_ms = repeat_keys_initial_ms + self.keyrepeat_interval_ms = repeat_keys_interval_ms + self.cursor_surface = pygame.Surface((int(self.font_size / 20 + 1), self.font_size)) + self.cursor_surface.fill(cursor_color) + self.cursor_position = len(initial_string) + self.cursor_visible = True + self.cursor_switch_ms = 500 + self.cursor_ms_counter = 0 + self.clock = pygame.time.Clock() + # Update + def update(self, events): + for event in events: + if event.type == pygame.KEYDOWN: + self.cursor_visible = True + if event.key not in self.keyrepeat_counters: + if not event.key == pl.K_RETURN: + self.keyrepeat_counters[event.key] = [0, event.unicode] + if event.key == pl.K_BACKSPACE: + self.input_string = ( + self.input_string[:max(self.cursor_position - 1, 0)] + + self.input_string[self.cursor_position:] + ) + self.cursor_position = max(self.cursor_position - 1, 0) + elif event.key == pl.K_DELETE: + self.input_string = ( + self.input_string[:self.cursor_position] + + self.input_string[self.cursor_position + 1:] + ) + elif event.key == pl.K_RETURN: + return True + elif event.key == pl.K_RIGHT: + self.cursor_position = min(self.cursor_position + 1, len(self.input_string)) + elif event.key == pl.K_LEFT: + self.cursor_position = max(self.cursor_position - 1, 0) + elif event.key == pl.K_END: + self.cursor_position = len(self.input_string) + elif event.key == pl.K_HOME: + self.cursor_position = 0 + elif len(self.input_string) < self.max_string_length or self.max_string_length == -1: + self.input_string = ( + self.input_string[:self.cursor_position] + + event.unicode + + self.input_string[self.cursor_position:] + ) + self.cursor_position += len(event.unicode) + elif event.type == pl.KEYUP: + if event.key in self.keyrepeat_counters: + del self.keyrepeat_counters[event.key] + for key in self.keyrepeat_counters: + self.keyrepeat_counters[key][0] += self.clock.get_time() # Update clock + if self.keyrepeat_counters[key][0] >= self.keyrepeat_intial_interval_ms: + self.keyrepeat_counters[key][0] = ( + self.keyrepeat_intial_interval_ms + - self.keyrepeat_interval_ms + ) + event_key, event_unicode = key, self.keyrepeat_counters[key][1] + pygame.event.post(pygame.event.Event(pl.KEYDOWN, key=event_key, unicode=event_unicode)) + string = self.input_string + if self.password: + string = "*" * len(self.input_string) + self.surface = self.font_object.render(string, self.antialias, self.text_color) + self.cursor_ms_counter += self.clock.get_time() + if self.cursor_ms_counter >= self.cursor_switch_ms: + self.cursor_ms_counter %= self.cursor_switch_ms + self.cursor_visible = not self.cursor_visible + if self.cursor_visible: + cursor_y_pos = self.font_object.size(self.input_string[:self.cursor_position])[0] + if self.cursor_position > 0: + cursor_y_pos -= self.cursor_surface.get_width() + self.surface.blit(self.cursor_surface, (cursor_y_pos, 0)) + self.clock.tick() + return False + # Other Funtions + def get_surface(self): + return self.surface + def get_text(self): + return self.input_string + def get_cursor_position(self): + return self.cursor_position + def set_text_color(self, color): + self.text_color = color + def set_cursor_color(self, color): + self.cursor_surface.fill(color) + def clear_text(self): + self.input_string = "" + self.cursor_position = 0 + # Class + class PortInput: + # Init + def __init__( + # Choose Parameters + self, + initial_string = "", + font_family = "", + font_size = 35, + antialias = False, + text_color = (0, 0, 0), + cursor_color = (0, 0, 1), + repeat_keys_initial_ms = 400, + repeat_keys_interval_ms = 35, + max_string_length = 39, + password = False): + # Rest Of Init + self.antialias = antialias + self.text_color = text_color + self.font_size = font_size + self.max_string_length = max_string_length + self.password = password + self.input_string = initial_string + if not os.path.isfile(font_family): + font_family = pygame.font.match_font(font_family) + self.font_object = pygame.font.Font(font_family, font_size) + self.surface = pygame.Surface((1, 1)) + self.surface.set_alpha(0) + self.keyrepeat_counters = {} + self.keyrepeat_intial_interval_ms = repeat_keys_initial_ms + self.keyrepeat_interval_ms = repeat_keys_interval_ms + self.cursor_surface = pygame.Surface((int(self.font_size / 20 + 1), self.font_size)) + self.cursor_surface.fill(cursor_color) + self.cursor_position = len(initial_string) + self.cursor_visible = True + self.cursor_switch_ms = 500 + self.cursor_ms_counter = 0 + self.clock = pygame.time.Clock() + # Update + def update(self, events): + for event in events: + if event.type == pygame.KEYDOWN: + self.cursor_visible = True + if event.key not in self.keyrepeat_counters: + if not event.key == pl.K_RETURN: + self.keyrepeat_counters[event.key] = [0, event.unicode] + if event.key == pl.K_BACKSPACE: + self.input_string = ( + self.input_string[:max(self.cursor_position - 1, 0)] + + self.input_string[self.cursor_position:] + ) + self.cursor_position = max(self.cursor_position - 1, 0) + elif event.key == pl.K_DELETE: + self.input_string = ( + self.input_string[:self.cursor_position] + + self.input_string[self.cursor_position + 1:] + ) + elif event.key == pl.K_RETURN: + return True + elif event.key == pl.K_RIGHT: + self.cursor_position = min(self.cursor_position + 1, len(self.input_string)) + elif event.key == pl.K_LEFT: + self.cursor_position = max(self.cursor_position - 1, 0) + elif event.key == pl.K_END: + self.cursor_position = len(self.input_string) + elif event.key == pl.K_HOME: + self.cursor_position = 0 + elif len(self.input_string) < self.max_string_length or self.max_string_length == -1: + self.input_string = ( + self.input_string[:self.cursor_position] + + event.unicode + + self.input_string[self.cursor_position:] + ) + self.cursor_position += len(event.unicode) + elif event.type == pl.KEYUP: + if event.key in self.keyrepeat_counters: + del self.keyrepeat_counters[event.key] + for key in self.keyrepeat_counters: + self.keyrepeat_counters[key][0] += self.clock.get_time() # Update clock + if self.keyrepeat_counters[key][0] >= self.keyrepeat_intial_interval_ms: + self.keyrepeat_counters[key][0] = ( + self.keyrepeat_intial_interval_ms + - self.keyrepeat_interval_ms + ) + event_key, event_unicode = key, self.keyrepeat_counters[key][1] + pygame.event.post(pygame.event.Event(pl.KEYDOWN, key=event_key, unicode=event_unicode)) + string = self.input_string + if self.password: + string = "*" * len(self.input_string) + self.surface = self.font_object.render(string, self.antialias, self.text_color) + self.cursor_ms_counter += self.clock.get_time() + if self.cursor_ms_counter >= self.cursor_switch_ms: + self.cursor_ms_counter %= self.cursor_switch_ms + self.cursor_visible = not self.cursor_visible + if self.cursor_visible: + cursor_y_pos = self.font_object.size(self.input_string[:self.cursor_position])[0] + if self.cursor_position > 0: + cursor_y_pos -= self.cursor_surface.get_width() + self.surface.blit(self.cursor_surface, (cursor_y_pos, 0)) + self.clock.tick() + return False + # Other Funtions + def get_surface(self): + return self.surface + def get_text(self): + return self.input_string + def get_cursor_position(self): + return self.cursor_position + def set_text_color(self, color): + self.text_color = color + def set_cursor_color(self, color): + self.cursor_surface.fill(color) + def clear_text(self): + self.input_string = "" + self.cursor_position = 0 + # Class + class NameInput: + # Init + def __init__( + # Choose Parameters + self, + initial_string = "", + font_family = "", + font_size = 40, + antialias = False, + text_color = (255, 255, 0), + cursor_color = (255, 255, 0), + repeat_keys_initial_ms = 400, + repeat_keys_interval_ms = 35, + max_string_length = 10, + password = False): + # Rest Of Init + self.antialias = antialias + self.text_color = text_color + self.font_size = font_size + self.max_string_length = max_string_length + self.password = password + self.input_string = initial_string + if not os.path.isfile(font_family): + font_family = pygame.font.match_font(font_family) + self.font_object = pygame.font.Font(font_family, font_size) + self.surface = pygame.Surface((1, 1)) + self.surface.set_alpha(0) + self.keyrepeat_counters = {} + self.keyrepeat_intial_interval_ms = repeat_keys_initial_ms + self.keyrepeat_interval_ms = repeat_keys_interval_ms + self.cursor_surface = pygame.Surface((int(self.font_size / 20 + 1), self.font_size)) + self.cursor_surface.fill(cursor_color) + self.cursor_position = len(initial_string) + self.cursor_visible = True + self.cursor_switch_ms = 500 + self.cursor_ms_counter = 0 + self.clock = pygame.time.Clock() + # Update + def update(self, events): + for event in events: + if event.type == pygame.KEYDOWN: + self.cursor_visible = True + if event.key not in self.keyrepeat_counters: + if not event.key == pl.K_RETURN: + self.keyrepeat_counters[event.key] = [0, event.unicode] + if event.key == pl.K_BACKSPACE: + self.input_string = ( + self.input_string[:max(self.cursor_position - 1, 0)] + + self.input_string[self.cursor_position:] + ) + self.cursor_position = max(self.cursor_position - 1, 0) + elif event.key == pl.K_DELETE: + self.input_string = ( + self.input_string[:self.cursor_position] + + self.input_string[self.cursor_position + 1:] + ) + elif event.key == pl.K_RETURN: + return True + elif event.key == pl.K_RIGHT: + self.cursor_position = min(self.cursor_position + 1, len(self.input_string)) + elif event.key == pl.K_LEFT: + self.cursor_position = max(self.cursor_position - 1, 0) + elif event.key == pl.K_END: + self.cursor_position = len(self.input_string) + elif event.key == pl.K_HOME: + self.cursor_position = 0 + elif len(self.input_string) < self.max_string_length or self.max_string_length == -1: + self.input_string = ( + self.input_string[:self.cursor_position] + + event.unicode + + self.input_string[self.cursor_position:] + ) + self.cursor_position += len(event.unicode) + elif event.type == pl.KEYUP: + if event.key in self.keyrepeat_counters: + del self.keyrepeat_counters[event.key] + for key in self.keyrepeat_counters: + self.keyrepeat_counters[key][0] += self.clock.get_time() # Update clock + if self.keyrepeat_counters[key][0] >= self.keyrepeat_intial_interval_ms: + self.keyrepeat_counters[key][0] = ( + self.keyrepeat_intial_interval_ms + - self.keyrepeat_interval_ms + ) + event_key, event_unicode = key, self.keyrepeat_counters[key][1] + pygame.event.post(pygame.event.Event(pl.KEYDOWN, key=event_key, unicode=event_unicode)) + string = self.input_string + if self.password: + string = "*" * len(self.input_string) + self.surface = self.font_object.render(string, self.antialias, self.text_color) + self.cursor_ms_counter += self.clock.get_time() + if self.cursor_ms_counter >= self.cursor_switch_ms: + self.cursor_ms_counter %= self.cursor_switch_ms + self.cursor_visible = not self.cursor_visible + if self.cursor_visible: + cursor_y_pos = self.font_object.size(self.input_string[:self.cursor_position])[0] + if self.cursor_position > 0: + cursor_y_pos -= self.cursor_surface.get_width() + self.surface.blit(self.cursor_surface, (cursor_y_pos, 0)) + self.clock.tick() + return False + # Other Funtions + def get_surface(self): + return self.surface + def get_text(self): + return self.input_string + def get_cursor_position(self): + return self.cursor_position + def set_text_color(self, color): + self.text_color = color + def set_cursor_color(self, color): + self.cursor_surface.fill(color) + def clear_text(self): + self.input_string = "" + self.cursor_position = 0 + \ No newline at end of file diff --git a/level_creation.py b/level_creation.py new file mode 100755 index 0000000..8a88faa --- /dev/null +++ b/level_creation.py @@ -0,0 +1,51 @@ +# Stop Imports +if __name__ == "__main__": + # Imports + import pygame + import pickle + # Tile List Data + tile_list = [ + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 4,], + [3, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,], + [1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4,] + ] + # Save Tile List + pickle_out = open("./leveldata/level_data.txt", "wb") + pickle.dump(tile_list, pickle_out) + pickle_out.close() +# If Imported +else: + exit() \ No newline at end of file diff --git a/network.py b/network.py new file mode 100755 index 0000000..fb9d183 --- /dev/null +++ b/network.py @@ -0,0 +1,105 @@ +# Only Allow Imports +if __name__ == "__main__": + exit() +else: + # Imports + import socket + # Client + class Client(): + # Init + def __init__(self, ip_address, port): + self.HEADER = 100 + self.SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.SOCKET.connect((ip_address, port)) + # Send String + def send_string(self, message): + message = message.encode("utf-8") + message_length = len(message) + message_length = str(message_length).encode("utf-8") + message_length += b" " * (self.HEADER - len(message_length)) + self.SOCKET.send(message_length) + self.SOCKET.send(message) + # Send Byte + def send_byte(self, message): + message_length = len(message) + message_length = str(message_length).encode("utf-8") + message_length += b" " * (self.HEADER - len(message_length)) + self.SOCKET.send(message_length) + self.SOCKET.send(message) + # Receive String + def receive_string(self): + message = bytearray(b'') + message_length = self.SOCKET.recv(self.HEADER).decode("utf-8") + if message_length: + message_length = int(message_length) + received_message_length = 0 + while message_length > received_message_length: + received = self.SOCKET.recv(message_length - received_message_length) + message = message + received + received_message_length += len(received) + message = message.decode("utf-8") + return message + # Receive Byte + def receive_byte(self): + message = bytearray(b'') + message_length = self.SOCKET.recv(self.HEADER).decode("utf-8") + if message_length: + message_length = int(message_length) + received_message_length = 0 + while message_length > received_message_length: + received = self.SOCKET.recv(message_length - received_message_length) + message = message + received + received_message_length += len(received) + return message + # Server + class Server(): + # Init + def __init__(self, ip_address, port): + self.HEADER = 100 + self.SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.SOCKET.bind((ip_address, port)) + self.SOCKET.listen() + # Connection + def receive_connection(self): + connection, address = self.SOCKET.accept() + return connection, address + # Send String + def send_string(self, connection, message): + message = message.encode("utf-8") + message_length = len(message) + message_length = str(message_length).encode("utf-8") + message_length += b" " * (self.HEADER - len(message_length)) + connection.send(message_length) + connection.send(message) + # Send Byte + def send_byte(self, connection, message): + message_length = len(message) + message_length = str(message_length).encode("utf-8") + message_length += b" " * (self.HEADER - len(message_length)) + connection.send(message_length) + connection.send(message) + # Receive String + def receive_string(self, connection): + message = bytearray(b'') + message_length = connection.recv(self.HEADER).decode("utf-8") + if message_length: + message_length = int(message_length) + received_message_length = 0 + while message_length > received_message_length: + received = connection.recv(message_length - received_message_length) + message = message + received + received_message_length += len(received) + message = message.decode("utf-8") + return message + # Receive Byte + def receive_byte(self, connection): + message = bytearray(b'') + message_length = connection.recv(self.HEADER).decode("utf-8") + if message_length: + message_length = int(message_length) + received_message_length = 0 + while message_length > received_message_length: + received = connection.recv(message_length - received_message_length) + message = message + received + received_message_length += len(received) + return message \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3f2928f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +pygame==2.3.0 +urllib3==1.26.15 diff --git a/server.py b/server.py new file mode 100755 index 0000000..6e9d9bb --- /dev/null +++ b/server.py @@ -0,0 +1,335 @@ +# Stop Imports +if __name__ == "__main__": + # Imports + print() + print("Importing Libraries ...") + print() + import pygame + import pickle + import socket + import threading + import time + import random + import urllib3 + from urllib.request import urlopen + import re + from network import Server + print() + # Assgin Variables + print("Assigning Variables ...") + print() + ip_address_local = "ERROR" + ip_address_public = "ERROR" + port = 9306 + clock = pygame.time.Clock() + tile_size = 20 + world_data = [] + full = False + connected_players = [False, False, False, False, False, False] + player_names = [None, None, None, None, None, None] + character = [None, None, None, None, None, None] + player_positions = [[0, - 20], [0, - 20], [0, - 20], [0, - 20], [0, - 20], [0, - 20]] + player_facings = [1, 1, 1, 1, 1, 1] + player_bullets = [[], [], [], [], [], []] + player_scores = [0, 0, 0, 0 ,0, 0] + # Loading Images + print("Loading Images ...") + print() + cave_image_dirt = pygame.image.load("./assets/blocks/dirt_cave.png") + cave_image_block = pygame.image.load("./assets/blocks/block_cave.png") + cave_image_player = "./assets/players/player.png" + # Find Ip Addresses + print("Finding Local Ip Address ...") + print() + try: + ip_address_local = socket.gethostbyname(socket.gethostname()) + except: + pass + print("Finding Public Ip Address ...") + print() + try: + data = str(urlopen("http://checkip.dyndns.com/").read()) + ip_address_public = re.compile(r"Address: (\d+.\d+.\d+.\d+)").search(data).group(1) + except: + pass + # Generate World Data + print("Generating World Data ...") + print() + pickle_in = open("./assets/leveldata/level_data.txt", "rb") + tile_list = pickle.load(pickle_in) + row_count = 0 + for row in tile_list: + column_count = 0 + for tile in row: + # Dirt + if tile == 1: + block = cave_image_dirt + tile = pygame.transform.scale(block, (tile_size, tile_size)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + # Down + if tile == 2: + block = cave_image_block + tile = pygame.transform.scale(block, (tile_size, tile_size)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + # Left + if tile == 3: + block = cave_image_block + block = pygame.transform.rotate(block, 270) + tile = pygame.transform.scale(block, (tile_size, tile_size)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + # Right + if tile == 4: + block = cave_image_block + block = pygame.transform.rotate(block, 90) + tile = pygame.transform.scale(block, (20,20)) + tile_rect = tile.get_rect() + tile_rect.y = row_count * tile_size + tile_rect.x = column_count * tile_size + tile = (tile, tile_rect) + world_data.append(tile) + column_count+=1 + row_count+=1 + # Generate Spawn + print("Defining Functions ...") + print() + def generate_spawn(): + player_x = random.randint(4, 240) * 5 + player_y = - 20 + return player_x, player_y + # Bullets + class Bullet(object): + # Init + def __init__(self, x, y, radius, color, facing): + self.x = x + self.y = y + self.radius = radius + self.color = color + try: + self.facing = int(facing) + except: + self.facing = -1 + self.vel = 20 * self.facing + # Player + class Player(): + # Init + def __init__(self): + self.reset() + self.alive = False + # Update + def update(self, up, left, right, player): + # Change in x and y + dx = 0 + dy = 0 + # Movement + if up == "1" and self.jumped == False and self.in_air == False: + self.vel_y = -15 + self.jumped = True + else: + self.jumped = False + if left == "1": + dx -= 5 + if right == "1": + dx += 5 + # Gravity + self.vel_y += 1.2 + if self.vel_y > 15: + self.vel_y = 15 + dy += self.vel_y + # Collisions + self.in_air = True + for tile in world_data: + # X Axis + if tile[1].colliderect(self.rect.x + dx, self.rect.y, self.width, self.height): + dx = 0 + # Y Axis + if tile[1].colliderect(self.rect.x, self.rect.y + dy, self.width, self.height): + if self.vel_y >= 0: + dy = tile[1].top - self.rect.bottom + self.in_air = False + elif self.vel_y < 0: + dy = tile[1].bottom - self.rect.top + self.vel_y = 0 + # Update Player Location + self.rect.x += dx + self.rect.y += dy + player_location = player_positions[player] + player_location[0] = self.rect.x + player_location[1] = self.rect.y - 20 + return self.rect.x, self.rect.y + # Reset + def reset(self): + player_x, player_y = generate_spawn() + self.image = pygame.image.load(cave_image_player) + self.rect = self.image.get_rect() + self.rect.x = player_x + self.rect.y = player_y + self.width = self.image.get_width() + self.height = self.image.get_height() + self.vel_y = 0 + self.jumped = False + self.in_air = True + # Client + def client(player, connection, address): + # On Connection + print(f"User Connected: {address}, {connection}") + print() + network.send_string(connection, "!JOIN") + name = network.receive_string(connection) + player_names[player] = name + character[player] = Player() + shoot = None + # Game Loop + while True: + # Game Tick + clock.tick(60) + # Receive Message + message = network.receive_string(connection) + # If !DISSCONNECT + if message == "!DISSCONNECT": + break + # Game Code + if message != None: + # Seperate Inputs + data = message.split("@") + input_up = data[0] + input_left = data[1] + input_right = data[2] + input_mouse_position = data[3] + input_mouse_clicks = data[4] + input_leftclick = input_mouse_clicks[1 : 5] + facing = data[5] + # Facing + if facing == "1": + player_facings[player] = 1 + else: + player_facings[player] = 0 + # Player + x, y = character[player].update(input_up, input_left, input_right, player) + # Bullets + playerbullets = player_bullets[player] + if input_leftclick == "Fals": + shoot = True + if input_leftclick == "True" and shoot: + if len(playerbullets) < 3: + playerbullets.append(Bullet(x+20//2, y-10, 3 ,(255,0,0), facing)) + shoot = False + for bullet in playerbullets: + if bullet.x < 1280 and bullet.x > 0: + bullet.x += bullet.vel + else: + playerbullets.pop(playerbullets.index(bullet)) + player_bullets[player] = playerbullets + for bullet in player_bullets[player]: + if bullet.x >= player_positions[0][0] and bullet.x <= player_positions[0][0] + 20: + if bullet.y >= player_positions[0][1] and bullet.y <= player_positions[0][1] + 20: + player_scores[player] += 1 + player_bullets[player].pop(player_bullets[player].index(bullet)) + character[0].reset() + if bullet.x >= player_positions[1][0] and bullet.x <= player_positions[1][0] + 20: + if bullet.y >= player_positions[1][1] and bullet.y <= player_positions[1][1] + 20: + player_scores[player] += 1 + player_bullets[player].pop(player_bullets[player].index(bullet)) + character[1].reset() + if bullet.x >= player_positions[2][0] and bullet.x <= player_positions[2][0] + 20: + if bullet.y >= player_positions[2][1] and bullet.y <= player_positions[2][1] + 20: + player_scores[player] += 1 + player_bullets[player].pop(player_bullets[player].index(bullet)) + character[2].reset() + if bullet.x >= player_positions[3][0] and bullet.x <= player_positions[3][0] + 20: + if bullet.y >= player_positions[3][1] and bullet.y <= player_positions[3][1] + 20: + player_scores[player] += 1 + player_bullets[player].pop(player_bullets[player].index(bullet)) + character[3].reset() + if bullet.x >= player_positions[4][0] and bullet.x <= player_positions[4][0] + 20: + if bullet.y >= player_positions[4][1] and bullet.y <= player_positions[4][1] + 20: + player_scores[player] += 1 + player_bullets[player].pop(player_bullets[player].index(bullet)) + character[4].reset() + if bullet.x >= player_positions[5][0] and bullet.x <= player_positions[5][0] + 20: + if bullet.y >= player_positions[5][1] and bullet.y <= player_positions[5][1] + 20: + player_scores[player] += 1 + player_bullets[player].pop(player_bullets[player].index(bullet)) + character[5].reset() + # Send Data To Client + score = f"{player_scores[player]}" + network.send_string(connection, f"{player_positions}") + network.send_byte(connection, pickle.dumps(player_bullets)) + network.send_string(connection, score) + network.send_string(connection, f"{player_facings}") + network.send_string(connection, f"{player_names}") + # Close Connection + player_location = player_positions[player] + player_location[0] = 0 + player_location[1] = - 20 + player_scores[player] = 0 + player_bullets[player] = [] + connected_players[player] = False + player_names[player] = None + connection.close() + print(f"User Dissconnected: {address}, {connection}") + print() + # Active Connections + def active_connections(): + update_connections = -1 + while True: + connections = threading.activeCount() - 2 + if connections != update_connections: + time.sleep(0.1) + print(f"Active Connections: {connections}") + print(connected_players) + print() + update_connections = connections + # Server + def server(): + # Server Started + print("Server Started ...") + print(f"Local IP: {ip_address_local}") + print(f"Public IP: {ip_address_public}") + print() + # Active Connections + thread = threading.Thread(target = active_connections) + thread.start() + # While Server Is Running + while True: + # Wait For Connection + connection, address = network.receive_connection() + print("jin") + # Find Player Number + player = 0 + for placeholder in connected_players: + placeholder = placeholder + if connected_players[player] == False: + connected_players[player] = True + full = False + break + else: + full = True + player += 1 + # Handle Client + if full == False: + thread = threading.Thread(target = client, args = (player, connection, address)) + thread.start() + else: + print() + print(f"Server Full Connection Failed: {address}, {connection}") + network.send_string(connection, "!FULL") + # Start Server + print("Starting Server ...") + print() + network = Server("127.0.0.1", port) + server() + # Exit +else: + exit()