From f09dc71eda2a5a4ab3bdbf34ebfe7c7d7256bff5 Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 14 Jun 2025 22:30:07 +0200 Subject: [PATCH 1/4] aim --- .../shelved.patch | 135 +++++++++++++++ .../shelved.patch | 0 ...heckout_at_12_06_2025__20_36__Changes_.xml | 4 + .idea/workspace.xml | 155 ++++++++++++++++++ game.py | 1 + npc.py | 8 +- player.py | 28 +++- 7 files changed, 321 insertions(+), 10 deletions(-) create mode 100644 .idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch create mode 100644 .idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]1/shelved.patch create mode 100644 .idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch new file mode 100644 index 0000000..d66649e --- /dev/null +++ b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch @@ -0,0 +1,135 @@ +Index: game.py +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\"\"\"Game module\"\"\"\n\nimport queue\nimport threading\nimport time\nfrom datetime import datetime\n\n\nimport uuid\n\nimport psutil\nimport pygame\nimport socketio\n\nfrom bullet import Bullet\nfrom inputs import InputManager, PLAYER_KEYMAPS\nfrom player import Player\nfrom npc import NPC\n\nfrom config import GAME_FPS, CLIENT_REFRESH_COEF, INFO_TIMER, GATEWAY_ADDRESS\n\n\nclass AbstractGame:\n \"\"\"Abstract game ancestor\"\"\"\n\n def __init__(self, **kwargs):\n self.input_manager = InputManager()\n\n self.screen = kwargs[\"screen\"]\n self.clock = pygame.time.Clock()\n self.running = True\n self.tick = 1 * GAME_FPS\n self.players = {}\n self.npcs = [] # todo DICT by id????\n\n self.bullets = []\n self.player_bullets = []\n self.npc_bullets = []\n self.last_shot_times = {}\n self.shoot_cooldown = 250\n self.npc_last_shot_times = {}\n self.npc_shoot_cooldown = 150\n\n def try_shoot(self, uid, target_pos):\n now = pygame.time.get_ticks()\n last_shot = self.last_shot_times.get(uid, 0)\n if now - last_shot >= self.shoot_cooldown:\n player = self.players[uid]\n bullet = player.shoot(target_pos, color=player.color)\n self.player_bullets.append(bullet)\n self.last_shot_times[uid] = now\n\n def try_npc_shoot(self, npc):\n now = pygame.time.get_ticks()\n npc_id = id(npc)\n last_shot = self.npc_last_shot_times.get(npc_id, 0)\n if now - last_shot >= self.npc_shoot_cooldown:\n target = npc.get_shot_target(self.players.values())\n if target:\n bullet = Bullet(npc.rect.centerx, npc.rect.centery,\n target.rect.centerx, target.rect.centery,\n color=(255, 0, 0))\n self.npc_bullets.append(bullet)\n self.npc_last_shot_times[npc_id] = now\n\n\n def short_uid(self, length=8):\n \"\"\"Helper uid function\"\"\"\n return uuid.uuid4().hex[:length]\n\n def handle_events(self):\n \"\"\"Handles events and interruptions\"\"\"\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n print(\"Pressed quitting!\")\n self.running = False\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n raise NotImplementedError\n\n\n def update_players(self, **kwargs):\n \"\"\"Handles players updates\"\"\"\n\n for player in self.players.values():\n player.update(inputs = self.input_manager.get_inputs(player.uid), **kwargs)\n self.input_manager.clear_inputs(player.uid)\n\n\n def update_npcs(self, **kwargs):\n \"\"\"Handles npcs updates\"\"\"\n\n for npc in self.npcs:\n npc.update(players = self.players, **kwargs)\n self.try_npc_shoot(npc)\n\n\n def render_all(self):\n \"\"\"Draws itself\"\"\"\n self.screen.fill((0, 0, 0))\n\n for player in self.players.values():\n player.draw(self.screen)\n\n for npc in self.npcs:\n npc.draw(self.screen)\n\n for bullet in self.player_bullets:\n bullet.draw(self.screen)\n\n for bullet in self.npc_bullets:\n bullet.draw(self.screen)\n\n def update_bullets(self):\n \"\"\"Update bullets position\"\"\"\n for bullet_list in [self.player_bullets, self.npc_bullets]:\n for bullet in bullet_list[:]:\n bullet.update()\n if bullet.is_off_screen():\n bullet_list.remove(bullet)\n\n\n def run(self):\n \"\"\"Running loop\"\"\"\n while self.running:\n self.handle_events()\n self.handle_key_events()\n\n self.update_players()\n self.update_npcs()\n self.update_bullets()\n\n self.render_all()\n pygame.display.flip()\n self.clock.tick(self.tick)\n\n print(\"Closing game ....\")\n\n\nclass SingleGame(AbstractGame):\n \"\"\"Single player game\"\"\"\n\n PLAYER1 = \"Player1\"\n #PLAYER2 = \"Player2\"\n\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n\n pl1 = Player(self.PLAYER1) # todo some better init\n pl1.set_coords(20,20)\n self.players[self.PLAYER1] = pl1\n\n self.input_manager.add_keymap(self.PLAYER1, PLAYER_KEYMAPS[\"wasd\"])\n\n #pl2 = Player(self.PLAYER2) # experimental player 2\n #pl2.set_coords(100, 20)\n #pl2.color = (0,0,255)\n #self.players[self.PLAYER2] = pl2\n\n #self.input_manager.add_keymap(self.PLAYER2, PLAYER_KEYMAPS[\"arrows\"])\n\n self.npcs.append(NPC(400, 400))\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n\n keys = pygame.key.get_pressed()\n mouse_buttons = pygame.mouse.get_pressed()\n\n for key in PLAYER_KEYMAPS[\"wasd\"].keys():\n if keys[key]:\n self.input_manager.add_input(self.PLAYER1, key)\n\n #for key in PLAYER_KEYMAPS[\"arrows\"].keys():\n #if keys[key]:\n #self.input_manager.add_input(self.PLAYER2, key)\n\n if mouse_buttons[0]:\n self.try_shoot(self.PLAYER1, pygame.mouse.get_pos())\n\n\nclass MultiGameHost(AbstractGame):\n \"\"\"Multi-player game, role host\"\"\"\n\n PLAYER1 = \"HOST\" # todo some short id\n PLAYER1_NAME = \"Libor\" # todo config?\n\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n\n pl1 = Player(self.PLAYER1)\n pl1.set_coords(20,20)\n pl1.set_name(self.PLAYER1_NAME)\n self.players[self.PLAYER1] = pl1\n\n self.input_manager.add_keymap(self.PLAYER1, PLAYER_KEYMAPS[\"wasd\"])\n\n self.npcs.append(NPC(400, 400))\n\n self.client_thread = None\n self.info_thread = None\n self.socket_thread = None\n self.socket_queue = queue.Queue()\n\n self.sio = socketio.Client()\n self.sio.on('message', self.message)\n self.sio.on('info', self.info)\n\n self.sio.on('move', self.move)\n\n def run(self):\n \"\"\"Running loop\"\"\"\n\n # sio běží v neblokujícím vlákně\n self.client_thread = threading.Thread(target=self.start_client, daemon=True)\n self.client_thread.start()\n\n self.info_thread = threading.Thread(target=self.start_info, daemon=True)\n self.info_thread.start()\n\n self.socket_thread = threading.Thread(target=self.start_socket, daemon=True)\n self.socket_thread.start()\n\n while self.running:\n\n if not self.sio.connected:\n print(\"Connecting to server\") # todo better gui!\n else:\n self.handle_events()\n self.handle_key_events()\n\n self.update_players()\n self.update_npcs()\n self.update_bullets()\n self.send_all_positions()\n\n self.render_all()\n pygame.display.flip()\n\n self.clock.tick(self.tick)\n\n print(\"Closing game!\")\n self.info_thread.join()\n self.socket_thread.join()\n self.sio.disconnect()\n self.client_thread.join()\n\n\n\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n\n keys = pygame.key.get_pressed()\n mouse_buttons = pygame.mouse.get_pressed()\n\n for key in PLAYER_KEYMAPS[\"wasd\"].keys():\n if keys[key]:\n self.input_manager.add_input(self.PLAYER1, key)\n\n if mouse_buttons[0]:\n self.try_shoot(self.PLAYER1, pygame.mouse.get_pos())\n\n\n def start_socket(self):\n \"\"\" Vlákno pro komunikaci přes socket, které bude odebírat data z fronty \"\"\"\n while self.running:\n try:\n while not self.socket_queue.empty(): # Zpracuj všechny dostupné zprávy\n name, data = self.socket_queue.get_nowait()\n # print(\"emitted\", name )\n self.sio.emit(name, data)\n\n except queue.Empty:\n pass # Pokud fronta je prázdná, čekáme\n\n time.sleep(0.01)\n\n def start_info(self):\n \"\"\"Info heartbeat thread\"\"\"\n while self.running:\n time.sleep(INFO_TIMER) # Pauza 1 sekunda\n if self.sio.connected:\n print(\"heartbeat!\")\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n self.sio.emit(\"info\")\n\n def start_client(self):\n \"\"\"SIO connection thread\"\"\"\n headers = {\"role\": \"host\", \"uid\": self.PLAYER1, \"name\": self.PLAYER1_NAME }\n self.sio.connect(GATEWAY_ADDRESS, headers=headers, transports=[\"websocket\"])\n self.sio.wait()\n\n def send_all_positions(self):\n \"\"\"Position synchronizing method\"\"\"\n\n player_data = [player.get_transport_data() for player in self.players.values()]\n\n npc_data = [] # todo :)\n\n self.socket_queue.put((\"game_state\", {\"players\": player_data, \"npcs\": npc_data}))\n\n\n def message(self, msg):\n \"\"\"Message handler\"\"\"\n print(\"Got new message!\", msg)\n\n def info(self, msg):\n \"\"\"Info handler\"\"\"\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n print(\"Got info!\", msg)\n\n for client in msg.get(\"clientList\", []): # add missing players\n uid = client[\"uid\"]\n if uid not in self.players:\n\n print(\"New player\", client.get(\"name\"))\n new_player = Player(uid)\n new_player.set_coords(20, 20)\n new_player.set_name(client.get(\"name\"))\n self.players[uid] = new_player\n\n def move(self, data):\n \"\"\"Incoming move handler\"\"\"\n # print(data, \"Got move!\", data)\n self.input_manager.add_inputs(data[\"uid\"], data[\"inputs\"])\n\n\nclass MultiGameClient(AbstractGame):\n \"\"\"Multi-player game, role client\"\"\"\n\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n\n self.player1_id = self.short_uid()\n self.player1_name = \"Some player\" # todo config?\n pl1 = Player(self.player1_id)\n pl1.set_coords(20,20)\n pl1.set_name(self.player1_name)\n self.players[self.player1_id] = pl1\n\n self.input_manager.add_keymap(self.player1_id, PLAYER_KEYMAPS[\"wasd\"])\n\n self.npcs.append(NPC(400, 400))\n\n self.client_thread = None\n self.socket_thread = None\n self.socket_queue = queue.Queue()\n\n self.sio = socketio.Client(\n reconnection=True,\n reconnection_attempts=20,\n reconnection_delay=0.1,\n reconnection_delay_max=5\n )\n\n # sio handlers\n self.sio.on('message', self.message)\n self.sio.on('info', self.info)\n self.sio.on('game_state', self.game_state)\n\n # sio info block\n self.sio.on(\"connect\", lambda: print(\"connected\"))\n self.sio.on(\"disconnect\", lambda x: print(\"disconnected\", x))\n self.sio.on(\"reconnect\", lambda x: print(\"reconnected\", x))\n self.sio.on(\"reconnect_error\", lambda x: print(\"reconnect-error\", x))\n\n\n def run(self):\n \"\"\"Running loop\"\"\"\n\n # sio běží v neblokujícím vlákně\n self.client_thread = threading.Thread(target=self.start_client, daemon=True)\n self.client_thread.start()\n\n self.socket_thread = threading.Thread(target=self.start_socket, daemon=True)\n self.socket_thread.start()\n\n cnt = 0\n\n while self.running:\n\n if not self.sio.connected:\n self.screen.fill((0, 0, 0))\n pygame.display.flip()\n print(\"Connecting to server\") # todo some nice screen, add some waiting for host\n else:\n self.handle_events()\n self.handle_key_events()\n self.update_bullets()\n self.send_key_events()\n\n # no drawing, only from game_state event!\n\n cnt += 1\n if cnt > (200 * CLIENT_REFRESH_COEF):\n cpu = psutil.cpu_percent()\n print(f\"CPU: {cpu}\")\n print(\"heartbeat!\")\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n self.sio.emit(\"info\")\n cnt = 0\n\n # todo: rychlejsi tick, protoze se updatuje eventem\n # ale pozor na zahlceni socketu\n self.clock.tick(self.tick * CLIENT_REFRESH_COEF)\n\n print(\"Closing game!\")\n self.sio.disconnect()\n self.client_thread.join()\n\n def start_socket(self):\n \"\"\" Vlákno pro komunikaci přes socket, které bude odebírat data z fronty \"\"\"\n while self.running:\n try:\n while not self.socket_queue.empty(): # Zpracuj všechny dostupné zprávy\n name, data = self.socket_queue.get_nowait()\n # print(\"emitted\", name )\n if self.sio.connected:\n self.sio.emit(name, data)\n\n except queue.Empty:\n pass # Pokud fronta je prázdná, čekáme\n\n time.sleep(0.02)\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n\n keys = pygame.key.get_pressed()\n mouse_buttons = pygame.mouse.get_pressed()\n\n for key in PLAYER_KEYMAPS[\"wasd\"].keys():\n if keys[key]:\n self.input_manager.add_input(self.player1_id, key)\n\n if mouse_buttons[0]:\n self.try_shoot(self.PLAYER1, pygame.mouse.get_pos())\n\n def send_key_events(self):\n \"\"\"Send key presses to socket\"\"\"\n\n inputs = self.input_manager.get_inputs(self.player1_id)\n self.input_manager.clear_inputs(self.player1_id)\n if len(inputs) > 0:\n# self.sio.emit(\"move\", {\"uid\": self.PLAYER1, \"inputs\": inputs})\n self.socket_queue.put((\"move\", {\"uid\": self.player1_id, \"inputs\": inputs}))\n\n def start_client(self):\n \"\"\"Sio connect thread\"\"\"\n\n # todo posílat color v hexa\n\n headers = {\"role\": \"client\", \"uid\": self.player1_id, \"name\": self.player1_name}\n self.sio.connect(GATEWAY_ADDRESS, wait_timeout=5, headers=headers, transports=[\"websocket\"])\n\n self.sio.wait()\n\n def message(self, msg):\n \"\"\"Message handler\"\"\"\n print(\"Got new message!\", msg)\n\n def info(self, msg):\n \"\"\"Info handler\"\"\"\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n print(\"Got info!\", msg)\n\n for client in msg.get(\"clientList\", []): # add missing players\n uid = client[\"uid\"]\n if uid not in self.players:\n\n print(\"New player\", client.get(\"name\"))\n new_player = Player(uid)\n new_player.set_coords(20, 20)\n new_player.set_name(client.get(\"name\"))\n self.players[uid] = new_player\n\n def game_state(self, data):\n \"\"\"Incoming game state handler\"\"\"\n # print(data, \"Got new game state!\", data)\n\n for player_data in data[\"players\"]:\n if player_data[\"uid\"] in self.players:\n pl = self.players.get(player_data[\"uid\"])\n pl.update_data(player_data)\n # self.update_npcs()\n\n self.render_all()\n\n pygame.display.flip()\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/game.py b/game.py +--- a/game.py (revision 66a2f5de9ffb6ec19bf108b79b51e22c5f47eeb4) ++++ b/game.py (date 1749753078762) +@@ -41,6 +41,25 @@ + self.npc_last_shot_times = {} + self.npc_shoot_cooldown = 150 + ++ def check_bullet_collisions(self): ++ for bullet in self.npc_bullets[:]: ++ for player in self.players.values(): ++ if bullet.rect.colliderect(player.rect): ++ player.health -= 10 ++ if player.health < 0: ++ player.health = 0 ++ self.npc_bullets.remove(bullet) ++ break ++ ++ for bullet in self.player_bullets[:]: ++ for npc in self.npcs[:]: ++ if bullet.rect.colliderect(npc.rect): ++ npc.health -= 10 ++ if npc.health < 0: ++ npc.health = 0 ++ self.player_bullets.remove(bullet) ++ break ++ + def try_shoot(self, uid, target_pos): + now = pygame.time.get_ticks() + last_shot = self.last_shot_times.get(uid, 0) +@@ -130,6 +149,7 @@ + self.update_players() + self.update_npcs() + self.update_bullets() ++ self.check_bullet_collisions() + + self.render_all() + pygame.display.flip() +@@ -222,6 +242,7 @@ + self.socket_thread = threading.Thread(target=self.start_socket, daemon=True) + self.socket_thread.start() + ++ + while self.running: + + if not self.sio.connected: +@@ -233,6 +254,7 @@ + self.update_players() + self.update_npcs() + self.update_bullets() ++ self.check_bullet_collisions() + self.send_all_positions() + + self.render_all() +Index: npc.py +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\"\"\"NPC module\"\"\"\nimport math\n\nimport pygame\n\nfrom config import NPC_SPEED\nfrom bullet import Bullet\n\nclass NPC:\n \"\"\"NPC common class\"\"\"\n def __init__(self, x, y):\n self.rect = pygame.Rect(x, y, 20, 20)\n\n def update(self, **kwargs):\n \"\"\"Updates self position according to players\"\"\"\n nearest_player = self.find_closest_player(self, kwargs[\"players\"].values())\n\n\n if self.rect.x < nearest_player.rect.x:\n self.rect.x += NPC_SPEED\n elif self.rect.x > nearest_player.rect.x:\n self.rect.x -= NPC_SPEED\n if self.rect.y < nearest_player.rect.y:\n self.rect.y += NPC_SPEED\n elif self.rect.y > nearest_player.rect.y:\n self.rect.y -= NPC_SPEED\n\n def get_shot_target(self, players):\n return self.find_closest_player(self, players)\n\n # def shoot(self, target):\n # bullet = Bullet(self.rect.centerx, self.rect.centery,\n # target.rect.centerx, target.rect.centery,\n # color=(255, 0, 0))\n # self.bullets.append(bullet)\n\n def draw(self, screen):\n \"\"\"Draws itself\"\"\"\n pygame.draw.rect(screen, (255, 0, 0), self.rect)\n\n\n def distance(self, rect1, rect2):\n \"\"\"Helper function for distance computing\"\"\"\n return math.hypot(rect1.x - rect2.x, rect1.y - rect2.y)\n\n def find_closest_player(self, npc, players):\n \"\"\"Function for NPC to find which player to chase, not optimized\"\"\"\n closest = None\n min_dist = float('inf')\n\n for player in players:\n dist = self.distance(npc.rect, player.rect)\n if dist < min_dist:\n min_dist = dist\n closest = player\n\n return closest\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/npc.py b/npc.py +--- a/npc.py (revision 66a2f5de9ffb6ec19bf108b79b51e22c5f47eeb4) ++++ b/npc.py (date 1749751148158) +@@ -11,6 +11,9 @@ + def __init__(self, x, y): + self.rect = pygame.Rect(x, y, 20, 20) + ++ self.health = 100 ++ self.max_health = 100 ++ + def update(self, **kwargs): + """Updates self position according to players""" + nearest_player = self.find_closest_player(self, kwargs["players"].values()) +@@ -34,9 +37,18 @@ + # color=(255, 0, 0)) + # self.bullets.append(bullet) + ++ def draw_lifebar(self,screen): ++ bar_width = self.rect.width ++ bar_heigth = 5 ++ fill = (self.health/self.max_health) * bar_width ++ ++ pygame.draw.rect(screen,(255,0,0),(self.rect.x,self.rect.y - 10,bar_width, bar_heigth)) ++ pygame.draw.rect(screen, (0, 255, 0), (self.rect.x, self.rect.y - 10, fill, bar_heigth)) ++ + def draw(self, screen): + """Draws itself""" + pygame.draw.rect(screen, (255, 0, 0), self.rect) ++ self.draw_lifebar(screen) + + + def distance(self, rect1, rect2): +Index: player.py +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\"\"\"Player module\"\"\"\n\nimport pygame\nfrom config import PLAYER_WIDTH, PLAYER_HEIGHT, PLAYER_SPEED, SCREEN_WIDTH, SCREEN_HEIGHT\nfrom enums import KeyType\nfrom bullet import Bullet\nimport random\n\nclass Player:\n \"\"\"Player class init\"\"\"\n def __init__(self, uid):\n\n self.uid = uid\n self.rect = pygame.Rect(0, 0, PLAYER_WIDTH, PLAYER_HEIGHT)\n self.color = (0, 255, 0)\n self.name = \"Player1\"\n self.speed = PLAYER_SPEED\n\n\n def set_coords(self, x, y):\n \"\"\"Coords setter\"\"\"\n self.rect = pygame.Rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT)\n\n def set_name(self, name):\n \"\"\"Name setter\"\"\"\n self.name = name\n\n\n def get_transport_data(self):\n \"\"\"Prepare data for data event\"\"\"\n return {\"uid\": self.uid, \"x\": self.rect.x, \"y\": self.rect.y}\n\n def update_data(self, transport_data):\n \"\"\"Update self position from data event\"\"\"\n self.rect.x = transport_data[\"x\"]\n self.rect.y = transport_data[\"y\"]\n\n def update(self, **kwargs):\n \"\"\"Update self position from move intention\"\"\"\n\n inp = kwargs[\"inputs\"]\n mouse_pos = kwargs.get(\"mouse_pos\",(self.rect.centerx,self.rect.centery))\n\n if KeyType.LEFT.name in inp:\n self.rect.x -= self.speed\n if KeyType.RIGHT.name in inp:\n self.rect.x += self.speed\n if KeyType.UP.name in inp:\n self.rect.y -= self.speed\n if KeyType.DOWN.name in inp:\n self.rect.y += self.speed\n\n # overflow corrections\n self.rect.x = max(self.rect.x, 0)\n self.rect.y = max(self.rect.y, 0)\n self.rect.x = min(self.rect.x, SCREEN_WIDTH - PLAYER_WIDTH)\n self.rect.y = min(self.rect.y, SCREEN_HEIGHT - PLAYER_HEIGHT)\n\n\n\n def shoot(self, target_pos=None, color=None):\n if target_pos is None:\n target_pos = (400, 300)\n\n if color is None:\n color = self.color\n\n bullet = Bullet(self.rect.centerx, self.rect.centery, *target_pos, color=color)\n return bullet\n\n def draw(self, screen):\n \"\"\"Draws itself\"\"\"\n pygame.draw.rect(screen, self.color, self.rect)\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/player.py b/player.py +--- a/player.py (revision 66a2f5de9ffb6ec19bf108b79b51e22c5f47eeb4) ++++ b/player.py (date 1749751094222) +@@ -16,6 +16,9 @@ + self.name = "Player1" + self.speed = PLAYER_SPEED + ++ self.health = 100 ++ self.max_health = 100 ++ + + def set_coords(self, x, y): + """Coords setter""" +@@ -68,6 +71,15 @@ + bullet = Bullet(self.rect.centerx, self.rect.centery, *target_pos, color=color) + return bullet + ++ def draw_lifebar(self,screen): ++ bar_width = self.rect.width ++ bar_heigth = 5 ++ fill = (self.health/self.max_health) * bar_width ++ ++ pygame.draw.rect(screen,(255,0,0),(self.rect.x,self.rect.y - 10,bar_width, bar_heigth)) ++ pygame.draw.rect(screen,(0, 255, 0),(self.rect.x, self.rect.y - 10, fill, bar_heigth)) ++ + def draw(self, screen): + """Draws itself""" + pygame.draw.rect(screen, self.color, self.rect) ++ self.draw_lifebar(screen) diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]1/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]1/shelved.patch new file mode 100644 index 0000000..e69de29 diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml new file mode 100644 index 0000000..d52213d --- /dev/null +++ b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..1ceadb3 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + { + "lastFilter": { + "state": "OPEN", + "assignee": "Ren6436" + } +} + { + "selectedUrlAndAccountId": { + "url": "https://github.com/dracek/uuPyGame.git", + "accountId": "bbc4e1cb-aa98-4684-86cc-3d43099966ad" + } +} + { + "associatedIndex": 4 +} + + + + { + "keyToString": { + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.git.unshallow": "true", + "git-widget-placeholder": "lifebar", + "last_opened_file_path": "/Users/traum/pyGame" + } +} + + + + + + + + + + + 1745221181550 + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/game.py b/game.py index c890bee..f0dc673 100644 --- a/game.py +++ b/game.py @@ -31,6 +31,7 @@ def __init__(self, **kwargs): self.npc_last_shot_times = {} self.npc_shoot_cooldown = 500 + def try_npc_shoot(self, npc): now = pygame.time.get_ticks() npc_id = id(npc) diff --git a/npc.py b/npc.py index ce4f7b3..8853e83 100644 --- a/npc.py +++ b/npc.py @@ -9,6 +9,9 @@ class NPC: def __init__(self, x, y): self.rect = pygame.Rect(x, y, 20, 20) + self.health = 100 + self.max_health = 100 + def update(self, **kwargs): """Updates self position according to players""" nearest_player = self.find_closest_player(self, kwargs["players"].values()) @@ -26,11 +29,6 @@ def update(self, **kwargs): def get_shot_target(self, players): return self.find_closest_player(self, players) - # def shoot(self, target): - # bullet = Bullet(self.rect.centerx, self.rect.centery, - # target.rect.centerx, target.rect.centery, - # color=(255, 0, 0)) - # self.bullets.append(bullet) def draw(self, screen): """Draws itself""" diff --git a/player.py b/player.py index 7b7f191..314c7b9 100644 --- a/player.py +++ b/player.py @@ -1,5 +1,5 @@ """Player module""" - +import math import pygame from config import PLAYER_WIDTH, PLAYER_HEIGHT, PLAYER_SPEED, SCREEN_WIDTH, SCREEN_HEIGHT @@ -20,6 +20,7 @@ def __init__(self, uid): self.is_moving = False self.facing = Facing.RIGHT + self.shoot_cooldown = 250 self.last_shot_time = pygame.time.get_ticks() @@ -59,21 +60,38 @@ def update(self, **kwargs): self.rect.x = min(self.rect.x, SCREEN_WIDTH - PLAYER_WIDTH) self.rect.y = min(self.rect.y, SCREEN_HEIGHT - PLAYER_HEIGHT) + def distance(self, rect1, rect2): + """Helper function for distance computing""" + return math.hypot(rect1.x - rect2.x, rect1.y - rect2.y) + + def find_closest_npc(self, npcs): + closest = None + min_dist = float('inf') + + for npc in npcs: + dist = self.distance(self.rect, npc.rect) + if dist < min_dist: + min_dist = dist + closest = npc + + return closest + def shoot(self, npcs): """Try to shoot, does not fire in cooldown""" now = pygame.time.get_ticks() - if now - self.last_shot_time >= self.shoot_cooldown: + target = self.find_closest_npc(npcs) + if target is None: + return None - #if target_pos is None:# todo targetting here. - target_pos = (400, 300) - + target_pos = (target.rect.centerx, target.rect.centery) bullet = Bullet(self.rect.centerx, self.rect.centery, *target_pos, color=self.color) self.last_shot_time = now return bullet + def draw(self, screen): """Draws itself""" pygame.draw.rect(screen, self.color, self.rect) From 2cbe7df089a3b6d060a9c8dc468d1a87a56a0a0d Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 14 Jun 2025 22:38:44 +0200 Subject: [PATCH 2/4] upd --- .../shelved.patch | 135 ------------------ .../shelved.patch | 0 ...heckout_at_12_06_2025__20_36__Changes_.xml | 4 - 3 files changed, 139 deletions(-) delete mode 100644 .idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch delete mode 100644 .idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]1/shelved.patch delete mode 100644 .idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch deleted file mode 100644 index d66649e..0000000 --- a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]/shelved.patch +++ /dev/null @@ -1,135 +0,0 @@ -Index: game.py -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP -<+>\"\"\"Game module\"\"\"\n\nimport queue\nimport threading\nimport time\nfrom datetime import datetime\n\n\nimport uuid\n\nimport psutil\nimport pygame\nimport socketio\n\nfrom bullet import Bullet\nfrom inputs import InputManager, PLAYER_KEYMAPS\nfrom player import Player\nfrom npc import NPC\n\nfrom config import GAME_FPS, CLIENT_REFRESH_COEF, INFO_TIMER, GATEWAY_ADDRESS\n\n\nclass AbstractGame:\n \"\"\"Abstract game ancestor\"\"\"\n\n def __init__(self, **kwargs):\n self.input_manager = InputManager()\n\n self.screen = kwargs[\"screen\"]\n self.clock = pygame.time.Clock()\n self.running = True\n self.tick = 1 * GAME_FPS\n self.players = {}\n self.npcs = [] # todo DICT by id????\n\n self.bullets = []\n self.player_bullets = []\n self.npc_bullets = []\n self.last_shot_times = {}\n self.shoot_cooldown = 250\n self.npc_last_shot_times = {}\n self.npc_shoot_cooldown = 150\n\n def try_shoot(self, uid, target_pos):\n now = pygame.time.get_ticks()\n last_shot = self.last_shot_times.get(uid, 0)\n if now - last_shot >= self.shoot_cooldown:\n player = self.players[uid]\n bullet = player.shoot(target_pos, color=player.color)\n self.player_bullets.append(bullet)\n self.last_shot_times[uid] = now\n\n def try_npc_shoot(self, npc):\n now = pygame.time.get_ticks()\n npc_id = id(npc)\n last_shot = self.npc_last_shot_times.get(npc_id, 0)\n if now - last_shot >= self.npc_shoot_cooldown:\n target = npc.get_shot_target(self.players.values())\n if target:\n bullet = Bullet(npc.rect.centerx, npc.rect.centery,\n target.rect.centerx, target.rect.centery,\n color=(255, 0, 0))\n self.npc_bullets.append(bullet)\n self.npc_last_shot_times[npc_id] = now\n\n\n def short_uid(self, length=8):\n \"\"\"Helper uid function\"\"\"\n return uuid.uuid4().hex[:length]\n\n def handle_events(self):\n \"\"\"Handles events and interruptions\"\"\"\n for event in pygame.event.get():\n if event.type == pygame.QUIT:\n print(\"Pressed quitting!\")\n self.running = False\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n raise NotImplementedError\n\n\n def update_players(self, **kwargs):\n \"\"\"Handles players updates\"\"\"\n\n for player in self.players.values():\n player.update(inputs = self.input_manager.get_inputs(player.uid), **kwargs)\n self.input_manager.clear_inputs(player.uid)\n\n\n def update_npcs(self, **kwargs):\n \"\"\"Handles npcs updates\"\"\"\n\n for npc in self.npcs:\n npc.update(players = self.players, **kwargs)\n self.try_npc_shoot(npc)\n\n\n def render_all(self):\n \"\"\"Draws itself\"\"\"\n self.screen.fill((0, 0, 0))\n\n for player in self.players.values():\n player.draw(self.screen)\n\n for npc in self.npcs:\n npc.draw(self.screen)\n\n for bullet in self.player_bullets:\n bullet.draw(self.screen)\n\n for bullet in self.npc_bullets:\n bullet.draw(self.screen)\n\n def update_bullets(self):\n \"\"\"Update bullets position\"\"\"\n for bullet_list in [self.player_bullets, self.npc_bullets]:\n for bullet in bullet_list[:]:\n bullet.update()\n if bullet.is_off_screen():\n bullet_list.remove(bullet)\n\n\n def run(self):\n \"\"\"Running loop\"\"\"\n while self.running:\n self.handle_events()\n self.handle_key_events()\n\n self.update_players()\n self.update_npcs()\n self.update_bullets()\n\n self.render_all()\n pygame.display.flip()\n self.clock.tick(self.tick)\n\n print(\"Closing game ....\")\n\n\nclass SingleGame(AbstractGame):\n \"\"\"Single player game\"\"\"\n\n PLAYER1 = \"Player1\"\n #PLAYER2 = \"Player2\"\n\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n\n pl1 = Player(self.PLAYER1) # todo some better init\n pl1.set_coords(20,20)\n self.players[self.PLAYER1] = pl1\n\n self.input_manager.add_keymap(self.PLAYER1, PLAYER_KEYMAPS[\"wasd\"])\n\n #pl2 = Player(self.PLAYER2) # experimental player 2\n #pl2.set_coords(100, 20)\n #pl2.color = (0,0,255)\n #self.players[self.PLAYER2] = pl2\n\n #self.input_manager.add_keymap(self.PLAYER2, PLAYER_KEYMAPS[\"arrows\"])\n\n self.npcs.append(NPC(400, 400))\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n\n keys = pygame.key.get_pressed()\n mouse_buttons = pygame.mouse.get_pressed()\n\n for key in PLAYER_KEYMAPS[\"wasd\"].keys():\n if keys[key]:\n self.input_manager.add_input(self.PLAYER1, key)\n\n #for key in PLAYER_KEYMAPS[\"arrows\"].keys():\n #if keys[key]:\n #self.input_manager.add_input(self.PLAYER2, key)\n\n if mouse_buttons[0]:\n self.try_shoot(self.PLAYER1, pygame.mouse.get_pos())\n\n\nclass MultiGameHost(AbstractGame):\n \"\"\"Multi-player game, role host\"\"\"\n\n PLAYER1 = \"HOST\" # todo some short id\n PLAYER1_NAME = \"Libor\" # todo config?\n\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n\n pl1 = Player(self.PLAYER1)\n pl1.set_coords(20,20)\n pl1.set_name(self.PLAYER1_NAME)\n self.players[self.PLAYER1] = pl1\n\n self.input_manager.add_keymap(self.PLAYER1, PLAYER_KEYMAPS[\"wasd\"])\n\n self.npcs.append(NPC(400, 400))\n\n self.client_thread = None\n self.info_thread = None\n self.socket_thread = None\n self.socket_queue = queue.Queue()\n\n self.sio = socketio.Client()\n self.sio.on('message', self.message)\n self.sio.on('info', self.info)\n\n self.sio.on('move', self.move)\n\n def run(self):\n \"\"\"Running loop\"\"\"\n\n # sio běží v neblokujícím vlákně\n self.client_thread = threading.Thread(target=self.start_client, daemon=True)\n self.client_thread.start()\n\n self.info_thread = threading.Thread(target=self.start_info, daemon=True)\n self.info_thread.start()\n\n self.socket_thread = threading.Thread(target=self.start_socket, daemon=True)\n self.socket_thread.start()\n\n while self.running:\n\n if not self.sio.connected:\n print(\"Connecting to server\") # todo better gui!\n else:\n self.handle_events()\n self.handle_key_events()\n\n self.update_players()\n self.update_npcs()\n self.update_bullets()\n self.send_all_positions()\n\n self.render_all()\n pygame.display.flip()\n\n self.clock.tick(self.tick)\n\n print(\"Closing game!\")\n self.info_thread.join()\n self.socket_thread.join()\n self.sio.disconnect()\n self.client_thread.join()\n\n\n\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n\n keys = pygame.key.get_pressed()\n mouse_buttons = pygame.mouse.get_pressed()\n\n for key in PLAYER_KEYMAPS[\"wasd\"].keys():\n if keys[key]:\n self.input_manager.add_input(self.PLAYER1, key)\n\n if mouse_buttons[0]:\n self.try_shoot(self.PLAYER1, pygame.mouse.get_pos())\n\n\n def start_socket(self):\n \"\"\" Vlákno pro komunikaci přes socket, které bude odebírat data z fronty \"\"\"\n while self.running:\n try:\n while not self.socket_queue.empty(): # Zpracuj všechny dostupné zprávy\n name, data = self.socket_queue.get_nowait()\n # print(\"emitted\", name )\n self.sio.emit(name, data)\n\n except queue.Empty:\n pass # Pokud fronta je prázdná, čekáme\n\n time.sleep(0.01)\n\n def start_info(self):\n \"\"\"Info heartbeat thread\"\"\"\n while self.running:\n time.sleep(INFO_TIMER) # Pauza 1 sekunda\n if self.sio.connected:\n print(\"heartbeat!\")\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n self.sio.emit(\"info\")\n\n def start_client(self):\n \"\"\"SIO connection thread\"\"\"\n headers = {\"role\": \"host\", \"uid\": self.PLAYER1, \"name\": self.PLAYER1_NAME }\n self.sio.connect(GATEWAY_ADDRESS, headers=headers, transports=[\"websocket\"])\n self.sio.wait()\n\n def send_all_positions(self):\n \"\"\"Position synchronizing method\"\"\"\n\n player_data = [player.get_transport_data() for player in self.players.values()]\n\n npc_data = [] # todo :)\n\n self.socket_queue.put((\"game_state\", {\"players\": player_data, \"npcs\": npc_data}))\n\n\n def message(self, msg):\n \"\"\"Message handler\"\"\"\n print(\"Got new message!\", msg)\n\n def info(self, msg):\n \"\"\"Info handler\"\"\"\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n print(\"Got info!\", msg)\n\n for client in msg.get(\"clientList\", []): # add missing players\n uid = client[\"uid\"]\n if uid not in self.players:\n\n print(\"New player\", client.get(\"name\"))\n new_player = Player(uid)\n new_player.set_coords(20, 20)\n new_player.set_name(client.get(\"name\"))\n self.players[uid] = new_player\n\n def move(self, data):\n \"\"\"Incoming move handler\"\"\"\n # print(data, \"Got move!\", data)\n self.input_manager.add_inputs(data[\"uid\"], data[\"inputs\"])\n\n\nclass MultiGameClient(AbstractGame):\n \"\"\"Multi-player game, role client\"\"\"\n\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n\n self.player1_id = self.short_uid()\n self.player1_name = \"Some player\" # todo config?\n pl1 = Player(self.player1_id)\n pl1.set_coords(20,20)\n pl1.set_name(self.player1_name)\n self.players[self.player1_id] = pl1\n\n self.input_manager.add_keymap(self.player1_id, PLAYER_KEYMAPS[\"wasd\"])\n\n self.npcs.append(NPC(400, 400))\n\n self.client_thread = None\n self.socket_thread = None\n self.socket_queue = queue.Queue()\n\n self.sio = socketio.Client(\n reconnection=True,\n reconnection_attempts=20,\n reconnection_delay=0.1,\n reconnection_delay_max=5\n )\n\n # sio handlers\n self.sio.on('message', self.message)\n self.sio.on('info', self.info)\n self.sio.on('game_state', self.game_state)\n\n # sio info block\n self.sio.on(\"connect\", lambda: print(\"connected\"))\n self.sio.on(\"disconnect\", lambda x: print(\"disconnected\", x))\n self.sio.on(\"reconnect\", lambda x: print(\"reconnected\", x))\n self.sio.on(\"reconnect_error\", lambda x: print(\"reconnect-error\", x))\n\n\n def run(self):\n \"\"\"Running loop\"\"\"\n\n # sio běží v neblokujícím vlákně\n self.client_thread = threading.Thread(target=self.start_client, daemon=True)\n self.client_thread.start()\n\n self.socket_thread = threading.Thread(target=self.start_socket, daemon=True)\n self.socket_thread.start()\n\n cnt = 0\n\n while self.running:\n\n if not self.sio.connected:\n self.screen.fill((0, 0, 0))\n pygame.display.flip()\n print(\"Connecting to server\") # todo some nice screen, add some waiting for host\n else:\n self.handle_events()\n self.handle_key_events()\n self.update_bullets()\n self.send_key_events()\n\n # no drawing, only from game_state event!\n\n cnt += 1\n if cnt > (200 * CLIENT_REFRESH_COEF):\n cpu = psutil.cpu_percent()\n print(f\"CPU: {cpu}\")\n print(\"heartbeat!\")\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n self.sio.emit(\"info\")\n cnt = 0\n\n # todo: rychlejsi tick, protoze se updatuje eventem\n # ale pozor na zahlceni socketu\n self.clock.tick(self.tick * CLIENT_REFRESH_COEF)\n\n print(\"Closing game!\")\n self.sio.disconnect()\n self.client_thread.join()\n\n def start_socket(self):\n \"\"\" Vlákno pro komunikaci přes socket, které bude odebírat data z fronty \"\"\"\n while self.running:\n try:\n while not self.socket_queue.empty(): # Zpracuj všechny dostupné zprávy\n name, data = self.socket_queue.get_nowait()\n # print(\"emitted\", name )\n if self.sio.connected:\n self.sio.emit(name, data)\n\n except queue.Empty:\n pass # Pokud fronta je prázdná, čekáme\n\n time.sleep(0.02)\n\n def handle_key_events(self):\n \"\"\"Handles key presses\"\"\"\n\n keys = pygame.key.get_pressed()\n mouse_buttons = pygame.mouse.get_pressed()\n\n for key in PLAYER_KEYMAPS[\"wasd\"].keys():\n if keys[key]:\n self.input_manager.add_input(self.player1_id, key)\n\n if mouse_buttons[0]:\n self.try_shoot(self.PLAYER1, pygame.mouse.get_pos())\n\n def send_key_events(self):\n \"\"\"Send key presses to socket\"\"\"\n\n inputs = self.input_manager.get_inputs(self.player1_id)\n self.input_manager.clear_inputs(self.player1_id)\n if len(inputs) > 0:\n# self.sio.emit(\"move\", {\"uid\": self.PLAYER1, \"inputs\": inputs})\n self.socket_queue.put((\"move\", {\"uid\": self.player1_id, \"inputs\": inputs}))\n\n def start_client(self):\n \"\"\"Sio connect thread\"\"\"\n\n # todo posílat color v hexa\n\n headers = {\"role\": \"client\", \"uid\": self.player1_id, \"name\": self.player1_name}\n self.sio.connect(GATEWAY_ADDRESS, wait_timeout=5, headers=headers, transports=[\"websocket\"])\n\n self.sio.wait()\n\n def message(self, msg):\n \"\"\"Message handler\"\"\"\n print(\"Got new message!\", msg)\n\n def info(self, msg):\n \"\"\"Info handler\"\"\"\n now = datetime.now()\n print(now.strftime(\"%H:%M:%S.%f\")[:-3])\n print(\"Got info!\", msg)\n\n for client in msg.get(\"clientList\", []): # add missing players\n uid = client[\"uid\"]\n if uid not in self.players:\n\n print(\"New player\", client.get(\"name\"))\n new_player = Player(uid)\n new_player.set_coords(20, 20)\n new_player.set_name(client.get(\"name\"))\n self.players[uid] = new_player\n\n def game_state(self, data):\n \"\"\"Incoming game state handler\"\"\"\n # print(data, \"Got new game state!\", data)\n\n for player_data in data[\"players\"]:\n if player_data[\"uid\"] in self.players:\n pl = self.players.get(player_data[\"uid\"])\n pl.update_data(player_data)\n # self.update_npcs()\n\n self.render_all()\n\n pygame.display.flip()\n -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/game.py b/game.py ---- a/game.py (revision 66a2f5de9ffb6ec19bf108b79b51e22c5f47eeb4) -+++ b/game.py (date 1749753078762) -@@ -41,6 +41,25 @@ - self.npc_last_shot_times = {} - self.npc_shoot_cooldown = 150 - -+ def check_bullet_collisions(self): -+ for bullet in self.npc_bullets[:]: -+ for player in self.players.values(): -+ if bullet.rect.colliderect(player.rect): -+ player.health -= 10 -+ if player.health < 0: -+ player.health = 0 -+ self.npc_bullets.remove(bullet) -+ break -+ -+ for bullet in self.player_bullets[:]: -+ for npc in self.npcs[:]: -+ if bullet.rect.colliderect(npc.rect): -+ npc.health -= 10 -+ if npc.health < 0: -+ npc.health = 0 -+ self.player_bullets.remove(bullet) -+ break -+ - def try_shoot(self, uid, target_pos): - now = pygame.time.get_ticks() - last_shot = self.last_shot_times.get(uid, 0) -@@ -130,6 +149,7 @@ - self.update_players() - self.update_npcs() - self.update_bullets() -+ self.check_bullet_collisions() - - self.render_all() - pygame.display.flip() -@@ -222,6 +242,7 @@ - self.socket_thread = threading.Thread(target=self.start_socket, daemon=True) - self.socket_thread.start() - -+ - while self.running: - - if not self.sio.connected: -@@ -233,6 +254,7 @@ - self.update_players() - self.update_npcs() - self.update_bullets() -+ self.check_bullet_collisions() - self.send_all_positions() - - self.render_all() -Index: npc.py -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP -<+>\"\"\"NPC module\"\"\"\nimport math\n\nimport pygame\n\nfrom config import NPC_SPEED\nfrom bullet import Bullet\n\nclass NPC:\n \"\"\"NPC common class\"\"\"\n def __init__(self, x, y):\n self.rect = pygame.Rect(x, y, 20, 20)\n\n def update(self, **kwargs):\n \"\"\"Updates self position according to players\"\"\"\n nearest_player = self.find_closest_player(self, kwargs[\"players\"].values())\n\n\n if self.rect.x < nearest_player.rect.x:\n self.rect.x += NPC_SPEED\n elif self.rect.x > nearest_player.rect.x:\n self.rect.x -= NPC_SPEED\n if self.rect.y < nearest_player.rect.y:\n self.rect.y += NPC_SPEED\n elif self.rect.y > nearest_player.rect.y:\n self.rect.y -= NPC_SPEED\n\n def get_shot_target(self, players):\n return self.find_closest_player(self, players)\n\n # def shoot(self, target):\n # bullet = Bullet(self.rect.centerx, self.rect.centery,\n # target.rect.centerx, target.rect.centery,\n # color=(255, 0, 0))\n # self.bullets.append(bullet)\n\n def draw(self, screen):\n \"\"\"Draws itself\"\"\"\n pygame.draw.rect(screen, (255, 0, 0), self.rect)\n\n\n def distance(self, rect1, rect2):\n \"\"\"Helper function for distance computing\"\"\"\n return math.hypot(rect1.x - rect2.x, rect1.y - rect2.y)\n\n def find_closest_player(self, npc, players):\n \"\"\"Function for NPC to find which player to chase, not optimized\"\"\"\n closest = None\n min_dist = float('inf')\n\n for player in players:\n dist = self.distance(npc.rect, player.rect)\n if dist < min_dist:\n min_dist = dist\n closest = player\n\n return closest\n -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/npc.py b/npc.py ---- a/npc.py (revision 66a2f5de9ffb6ec19bf108b79b51e22c5f47eeb4) -+++ b/npc.py (date 1749751148158) -@@ -11,6 +11,9 @@ - def __init__(self, x, y): - self.rect = pygame.Rect(x, y, 20, 20) - -+ self.health = 100 -+ self.max_health = 100 -+ - def update(self, **kwargs): - """Updates self position according to players""" - nearest_player = self.find_closest_player(self, kwargs["players"].values()) -@@ -34,9 +37,18 @@ - # color=(255, 0, 0)) - # self.bullets.append(bullet) - -+ def draw_lifebar(self,screen): -+ bar_width = self.rect.width -+ bar_heigth = 5 -+ fill = (self.health/self.max_health) * bar_width -+ -+ pygame.draw.rect(screen,(255,0,0),(self.rect.x,self.rect.y - 10,bar_width, bar_heigth)) -+ pygame.draw.rect(screen, (0, 255, 0), (self.rect.x, self.rect.y - 10, fill, bar_heigth)) -+ - def draw(self, screen): - """Draws itself""" - pygame.draw.rect(screen, (255, 0, 0), self.rect) -+ self.draw_lifebar(screen) - - - def distance(self, rect1, rect2): -Index: player.py -IDEA additional info: -Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP -<+>\"\"\"Player module\"\"\"\n\nimport pygame\nfrom config import PLAYER_WIDTH, PLAYER_HEIGHT, PLAYER_SPEED, SCREEN_WIDTH, SCREEN_HEIGHT\nfrom enums import KeyType\nfrom bullet import Bullet\nimport random\n\nclass Player:\n \"\"\"Player class init\"\"\"\n def __init__(self, uid):\n\n self.uid = uid\n self.rect = pygame.Rect(0, 0, PLAYER_WIDTH, PLAYER_HEIGHT)\n self.color = (0, 255, 0)\n self.name = \"Player1\"\n self.speed = PLAYER_SPEED\n\n\n def set_coords(self, x, y):\n \"\"\"Coords setter\"\"\"\n self.rect = pygame.Rect(x, y, PLAYER_WIDTH, PLAYER_HEIGHT)\n\n def set_name(self, name):\n \"\"\"Name setter\"\"\"\n self.name = name\n\n\n def get_transport_data(self):\n \"\"\"Prepare data for data event\"\"\"\n return {\"uid\": self.uid, \"x\": self.rect.x, \"y\": self.rect.y}\n\n def update_data(self, transport_data):\n \"\"\"Update self position from data event\"\"\"\n self.rect.x = transport_data[\"x\"]\n self.rect.y = transport_data[\"y\"]\n\n def update(self, **kwargs):\n \"\"\"Update self position from move intention\"\"\"\n\n inp = kwargs[\"inputs\"]\n mouse_pos = kwargs.get(\"mouse_pos\",(self.rect.centerx,self.rect.centery))\n\n if KeyType.LEFT.name in inp:\n self.rect.x -= self.speed\n if KeyType.RIGHT.name in inp:\n self.rect.x += self.speed\n if KeyType.UP.name in inp:\n self.rect.y -= self.speed\n if KeyType.DOWN.name in inp:\n self.rect.y += self.speed\n\n # overflow corrections\n self.rect.x = max(self.rect.x, 0)\n self.rect.y = max(self.rect.y, 0)\n self.rect.x = min(self.rect.x, SCREEN_WIDTH - PLAYER_WIDTH)\n self.rect.y = min(self.rect.y, SCREEN_HEIGHT - PLAYER_HEIGHT)\n\n\n\n def shoot(self, target_pos=None, color=None):\n if target_pos is None:\n target_pos = (400, 300)\n\n if color is None:\n color = self.color\n\n bullet = Bullet(self.rect.centerx, self.rect.centery, *target_pos, color=color)\n return bullet\n\n def draw(self, screen):\n \"\"\"Draws itself\"\"\"\n pygame.draw.rect(screen, self.color, self.rect)\n -Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP -<+>UTF-8 -=================================================================== -diff --git a/player.py b/player.py ---- a/player.py (revision 66a2f5de9ffb6ec19bf108b79b51e22c5f47eeb4) -+++ b/player.py (date 1749751094222) -@@ -16,6 +16,9 @@ - self.name = "Player1" - self.speed = PLAYER_SPEED - -+ self.health = 100 -+ self.max_health = 100 -+ - - def set_coords(self, x, y): - """Coords setter""" -@@ -68,6 +71,15 @@ - bullet = Bullet(self.rect.centerx, self.rect.centery, *target_pos, color=color) - return bullet - -+ def draw_lifebar(self,screen): -+ bar_width = self.rect.width -+ bar_heigth = 5 -+ fill = (self.health/self.max_health) * bar_width -+ -+ pygame.draw.rect(screen,(255,0,0),(self.rect.x,self.rect.y - 10,bar_width, bar_heigth)) -+ pygame.draw.rect(screen,(0, 255, 0),(self.rect.x, self.rect.y - 10, fill, bar_heigth)) -+ - def draw(self, screen): - """Draws itself""" - pygame.draw.rect(screen, self.color, self.rect) -+ self.draw_lifebar(screen) diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]1/shelved.patch b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025,_20_36_[Changes]1/shelved.patch deleted file mode 100644 index e69de29..0000000 diff --git a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml deleted file mode 100644 index d52213d..0000000 --- a/.idea/shelf/Uncommitted_changes_before_Checkout_at_12_06_2025__20_36__Changes_.xml +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file From a338c6d157e673f3f74ca64ea4c0a0f292680fbb Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 14 Jun 2025 22:40:25 +0200 Subject: [PATCH 3/4] upd --- .idea/workspace.xml | 155 -------------------------------------------- 1 file changed, 155 deletions(-) delete mode 100644 .idea/workspace.xml diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 1ceadb3..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - { - "lastFilter": { - "state": "OPEN", - "assignee": "Ren6436" - } -} - { - "selectedUrlAndAccountId": { - "url": "https://github.com/dracek/uuPyGame.git", - "accountId": "bbc4e1cb-aa98-4684-86cc-3d43099966ad" - } -} - { - "associatedIndex": 4 -} - - - - { - "keyToString": { - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.git.unshallow": "true", - "git-widget-placeholder": "lifebar", - "last_opened_file_path": "/Users/traum/pyGame" - } -} - - - - - - - - - - - 1745221181550 - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 0f09eb408ac0f147266f91bd4eb427207abd4ea7 Mon Sep 17 00:00:00 2001 From: Ren Date: Sat, 14 Jun 2025 22:42:00 +0200 Subject: [PATCH 4/4] upd --- npc.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/npc.py b/npc.py index 8853e83..948b93f 100644 --- a/npc.py +++ b/npc.py @@ -9,8 +9,6 @@ class NPC: def __init__(self, x, y): self.rect = pygame.Rect(x, y, 20, 20) - self.health = 100 - self.max_health = 100 def update(self, **kwargs): """Updates self position according to players"""