-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplayer.py
More file actions
147 lines (118 loc) · 4.99 KB
/
Copy pathplayer.py
File metadata and controls
147 lines (118 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""Player module using directional sprite animations"""
import math
import pygame
from config import PLAYER_WIDTH, PLAYER_HEIGHT, PLAYER_SPEED, SCREEN_WIDTH, SCREEN_HEIGHT
from enums import KeyType, Facing
from bullet import Bullet
movement_keys = {KeyType.LEFT.name, KeyType.RIGHT.name, KeyType.UP.name, KeyType.DOWN.name}
class Player:
def __init__(self, uid, assets, pos=(0, 0)):
self.uid = uid
self.assets = assets
self.frames = self.assets.player_frames # Dict: (direction, action) -> [Surface]
self.image = None
self.rect = pygame.Rect(pos[0], pos[1], PLAYER_WIDTH, PLAYER_HEIGHT)
self.name = uid
self.speed = PLAYER_SPEED
self.is_moving = False
self.facing = Facing.DOWN
self.health = 100
self.max_health = 100
self.color = (0, 255, 0)
self.shoot_cooldown = 250
self.damage = 10 # damage dealt per shot
self.last_shot_time = pygame.time.get_ticks()
self.frame_timer = 0
self.frame_index = 0
self.frame_delay = 150 # ms
self.current_action = "walk1"
self.shoot_anim_time = 300 # ms to show shoot frame
self.last_shoot_anim = 0
self.shooting = False # Tracks if we are currently animating a shot
def set_coords(self, x, y):
self.rect.topleft = (x, y)
def set_name(self, name):
self.name = name
def update(self, **kwargs):
inp = kwargs["inputs"]
self.is_moving = any(key in inp for key in movement_keys)
if KeyType.UP.name in inp:
self.rect.y -= self.speed
self.facing = Facing.UP
elif KeyType.DOWN.name in inp:
self.rect.y += self.speed
self.facing = Facing.DOWN
if KeyType.LEFT.name in inp:
self.rect.x -= self.speed
self.facing = Facing.LEFT
elif KeyType.RIGHT.name in inp:
self.rect.x += self.speed
self.facing = Facing.RIGHT
self.rect.x = max(0, min(self.rect.x, SCREEN_WIDTH - self.rect.width))
self.rect.y = max(0, min(self.rect.y, SCREEN_HEIGHT - self.rect.height))
self.animate()
def animate(self):
now = pygame.time.get_ticks()
direction = self.facing.name.lower()
if self.shooting:
if now - self.last_shoot_anim > self.shoot_anim_time:
self.shooting = False
else:
frame = "shoot1" if (now // 150) % 2 == 0 else "shoot2"
key = (direction, frame)
self.image = self.frames.get(key, self.frames.get(("down", "walk1"), [None]))[0]
if self.image:
center = self.rect.center
self.rect = self.image.get_rect(center=center)
return
if self.is_moving:
walk_cycle = ["walk1", "walk2", "walk3"]
index = (now // self.frame_delay) % len(walk_cycle)
action = walk_cycle[index]
else:
action = "walk1"
key = (direction, action)
self.image = self.frames.get(key, self.frames.get(("down", "walk1"), [None]))[0]
if self.image:
center = self.rect.center
self.rect = self.image.get_rect(center=center)
def distance(self, rect1, rect2):
return math.hypot(rect1.centerx - rect2.centerx, rect1.centery - rect2.centery)
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):
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
target_pos = (target.rect.centerx, target.rect.centery - 8)
bullet = Bullet(self.rect.centerx, self.rect.centery, *target_pos, color=self.color)
self.last_shot_time = now
self.shooting = True
self.last_shoot_anim = now
return bullet
def draw_lifebar(self, screen):
bar_width = self.rect.width
bar_height = 5
fill = (self.health / self.max_health) * bar_width
offset = 5
pygame.draw.rect(screen, (255, 0, 0), (self.rect.x + offset, self.rect.y - 10, bar_width, bar_height))
pygame.draw.rect(screen, (0, 255, 0), (self.rect.x + offset, self.rect.y - 10, fill, bar_height))
font = pygame.font.SysFont(None, 24)
name_surface = font.render(self.name, True, self.color)
name_rect = name_surface.get_rect(center=(self.rect.centerx + offset, self.rect.top - 20))
screen.blit(name_surface, name_rect)
def draw(self, screen):
if self.image:
screen.blit(self.image, self.rect)
else:
pygame.draw.rect(screen, self.color, self.rect)
self.draw_lifebar(screen)