new fire sim working fine

master
Eliza Moscovskaya 1 month ago
parent 4d82dc76da
commit e522b73dd1

@ -31,6 +31,7 @@ class Config:
# ===== Симулятор робота ===== # ===== Симулятор робота =====
MAP_WIDTH = 800 MAP_WIDTH = 800
MAP_HEIGHT = 600 MAP_HEIGHT = 600
BORDER_THICKNESS = 10
MAP_OBSTACLES = [ MAP_OBSTACLES = [
(200, 150, 100, 200), (200, 150, 100, 200),
(500, 300, 150, 50), (500, 300, 150, 50),
@ -41,7 +42,7 @@ class Config:
ROBOT_IMAGE_PATH = 'robot.png' # или None ROBOT_IMAGE_PATH = 'robot.png' # или None
INITIAL_HP = 100 INITIAL_HP = 100
INITIAL_CHARGE = 100 INITIAL_FIRE_CHARGE = 4
COLLISION_DAMAGE = 10 COLLISION_DAMAGE = 10
# Конус перед роботом # Конус перед роботом

@ -63,6 +63,7 @@ def main():
landmarks = result['landmarks'] landmarks = result['landmarks']
# Статический жест # Статический жест
special = special_detector.predict(landmarks)
# Вкл/выкл управления жестами # Вкл/выкл управления жестами
if special == 'cross' and cross_cooldown == 0: if special == 'cross' and cross_cooldown == 0:
@ -93,11 +94,13 @@ def main():
if dynamic_gesture: if dynamic_gesture:
last_dynamic = dynamic_gesture last_dynamic = dynamic_gesture
dynamic_counter = 30 dynamic_counter = 30
'''
if dynamic_gesture == 'wave_left': if dynamic_gesture == 'wave_left':
robot.reset_position() robot.reset_position()
elif dynamic_gesture == 'wave_right': elif dynamic_gesture == 'wave_right':
robot.restart_game() robot.restart()
'''
# Отрисовка # Отрисовка
vis = detector.draw_landmarks(frame, result['pose_landmarks']) vis = detector.draw_landmarks(frame, result['pose_landmarks'])

@ -19,7 +19,18 @@ class DummySimRobot(RobotController):
self.clock = pygame.time.Clock() self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont(None, 28) self.font = pygame.font.SysFont(None, 28)
self.obstacles = config.MAP_OBSTACLES border_thickness = config.BORDER_THICKNESS
if border_thickness > 0:
border_obstacles = [
(0, 0, self.width, border_thickness),
(0, self.height - border_thickness, self.width, border_thickness),
(0, 0, border_thickness, self.height),
(self.width - border_thickness, 0, border_thickness, self.height)
]
self.obstacles = list(config.MAP_OBSTACLES) + border_obstacles
else:
self.obstacles = list(config.MAP_OBSTACLES)
self.start = config.START_POS self.start = config.START_POS
self.finish = config.FINISH_POS self.finish = config.FINISH_POS
self.robot_radius = config.ROBOT_RADIUS self.robot_radius = config.ROBOT_RADIUS
@ -34,8 +45,8 @@ class DummySimRobot(RobotController):
self.max_hp = config.INITIAL_HP self.max_hp = config.INITIAL_HP
self.hp = self.max_hp self.hp = self.max_hp
self.max_charge = config.INITIAL_CHARGE self.max_fire_charge = config.INITIAL_FIRE_CHARGE
self.charge = self.max_charge self.charge = self.max_fire_charge
self.collision_damage = config.COLLISION_DAMAGE self.collision_damage = config.COLLISION_DAMAGE
self.extinguish_radius = config.EXTINGUISH_RADIUS self.extinguish_radius = config.EXTINGUISH_RADIUS
self.extinguish_angle = math.radians(config.EXTINGUISH_ANGLE) self.extinguish_angle = math.radians(config.EXTINGUISH_ANGLE)
@ -43,9 +54,18 @@ class DummySimRobot(RobotController):
self.fires = [] self.fires = []
self.num_fires = config.NUM_FIRES self.num_fires = config.NUM_FIRES
self.fire_radius = config.FIRE_RADIUS
self.score = 0 self.score = 0
self.game_over = False self.game_over = False
self.won = False self.won = False
self.extinguish_active = False
self.extinguish_timer = 0
self.extinguish_cooldown = 0
self.extinguish_cone_length = 80
self.invincibility_timer = 0
self.x, self.y = self.start self.x, self.y = self.start
self.angle = 0.0 self.angle = 0.0
@ -57,17 +77,41 @@ class DummySimRobot(RobotController):
def _generate_fires(self): def _generate_fires(self):
self.fires.clear() self.fires.clear()
attempts = 0 attempts = 0
while len(self.fires) < self.num_fires and attempts < 1000: margin = 30 # минимальное расстояние между центрами костров
fx = random.randint(self.robot_radius, self.width - self.robot_radius)
fy = random.randint(self.robot_radius, self.height - self.robot_radius) while len(self.fires) < self.num_fires and attempts < 2000:
fx = random.randint(self.robot_radius + 10, self.width - self.robot_radius - 10)
fy = random.randint(self.robot_radius + 10, self.height - self.robot_radius - 10)
# Проверка: не на препятствии
if self._point_collides_with_obstacle(fx, fy, self.robot_radius): if self._point_collides_with_obstacle(fx, fy, self.robot_radius):
attempts += 1
continue
# Проверка: не слишком близко к старту
if math.hypot(fx - self.start[0], fy - self.start[1]) < self.robot_radius * 3:
attempts += 1
continue continue
if math.hypot(fx - self.start[0], fy - self.start[1]) < self.robot_radius * 2:
# Проверка: не слишком близко к финишу
if math.hypot(fx - self.finish[0], fy - self.finish[1]) < self.robot_radius * 3:
attempts += 1
continue continue
if math.hypot(fx - self.finish[0], fy - self.finish[1]) < self.robot_radius * 2:
# Проверка: не пересекается с уже существующими кострами
overlap = False
for fire in self.fires:
if math.hypot(fx - fire.x, fy - fire.y) < 2 * self.fire_radius + margin:
overlap = True
break
if overlap:
attempts += 1
continue continue
self.fires.append(Fire(fx, fy, 15))
self.fires.append(Fire(fx, fy, self.fire_radius))
attempts += 1 attempts += 1
print(f"Сгенерировано {len(self.fires)} очагов возгорания")
def _point_collides_with_obstacle(self, x, y, radius): def _point_collides_with_obstacle(self, x, y, radius):
for ox, oy, ow, oh in self.obstacles: for ox, oy, ow, oh in self.obstacles:
@ -81,6 +125,7 @@ class DummySimRobot(RobotController):
self.linear_speed = max(-1.0, min(1.0, v)) self.linear_speed = max(-1.0, min(1.0, v))
self.angular_speed = max(-1.0, min(1.0, w)) self.angular_speed = max(-1.0, min(1.0, w))
'''
def send_fire_ext_burst_cmd(self): def send_fire_ext_burst_cmd(self):
if self.charge <= 0: if self.charge <= 0:
return False return False
@ -91,36 +136,72 @@ class DummySimRobot(RobotController):
self.score += self.score_per_fire self.score += self.score_per_fire
return True return True
return False return False
'''
def _is_fire_in_front(self, fire):
dx = fire.x - self.x def send_fire_ext_burst_cmd(self):
dy = fire.y - self.y if self.extinguish_cooldown > 0 or self.extinguish_active:
dist = math.hypot(dx, dy) return False
if dist > self.extinguish_radius: if self.charge <= 0:
return False return False
angle_to_fire = math.atan2(dy, dx)
angle_diff = abs(angle_to_fire - self.angle) self.extinguish_active = True
angle_diff = min(angle_diff, 2*math.pi - angle_diff) self.extinguish_timer = 30
return angle_diff < self.extinguish_angle / 2 self.extinguish_cooldown = 10
self.charge -= 1
cone_len = self.extinguish_cone_length
cone_angle_half = self.extinguish_angle / 2
extinguished = False
for fire in self.fires[:]:
dx = fire.x - self.x
dy = fire.y - self.y
dist = math.hypot(dx, dy)
if dist > cone_len:
continue
angle_to_fire = math.atan2(dy, dx)
angle_diff = angle_to_fire - self.angle
angle_diff = (angle_diff + math.pi) % (2*math.pi) - math.pi #[-π, π]
if abs(angle_diff) <= cone_angle_half:
self.fires.remove(fire)
self.score += self.score_per_fire
extinguished = True
break
return extinguished
def update(self, dt=1/30.0): def update(self, dt=1/30.0):
if self.game_over or self.won: if self.game_over or self.won:
return return
if self.invincibility_timer > 0:
self.invincibility_timer -= 1
if self.extinguish_timer > 0:
self.extinguish_timer -= 1
if self.extinguish_timer == 0:
self.extinguish_active = False
if self.extinguish_cooldown > 0:
self.extinguish_cooldown -= 1
# Движение
self.angle += self.angular_speed * dt * 2 self.angle += self.angular_speed * dt * 2
dx = self.linear_speed * math.cos(self.angle) * dt * 100 dx = self.linear_speed * math.cos(self.angle) * dt * 100
dy = self.linear_speed * math.sin(self.angle) * dt * 100 dy = self.linear_speed * math.sin(self.angle) * dt * 100
new_x = self.x + dx new_x = self.x + dx
new_y = self.y + dy new_y = self.y + dy
new_x = max(self.robot_radius, min(self.width - self.robot_radius, new_x)) # Проверка: столкновение
new_y = max(self.robot_radius, min(self.height - self.robot_radius, new_y))
if self._point_collides_with_obstacle(new_x, new_y, self.robot_radius): if self._point_collides_with_obstacle(new_x, new_y, self.robot_radius):
self.hp -= self.collision_damage if self.invincibility_timer == 0:
self.hp -= self.collision_damage
self.invincibility_timer = 30
else: else:
self.x, self.y = new_x, new_y self.x, self.y = new_x, new_y
# Конец игры?
if math.hypot(self.x - self.finish[0], self.y - self.finish[1]) < self.robot_radius: if math.hypot(self.x - self.finish[0], self.y - self.finish[1]) < self.robot_radius:
self.won = True self.won = True
if self.hp <= 0: if self.hp <= 0:
@ -128,26 +209,53 @@ class DummySimRobot(RobotController):
def draw(self): def draw(self):
self.screen.fill((255,255,255)) self.screen.fill((255,255,255))
# Препятствия
for ox, oy, ow, oh in self.obstacles: for ox, oy, ow, oh in self.obstacles:
pygame.draw.rect(self.screen, (100,100,100), (ox, oy, ow, oh)) pygame.draw.rect(self.screen, (100,100,100), (ox, oy, ow, oh))
# Финиш
pygame.draw.circle(self.screen, (0,200,0), (int(self.finish[0]), int(self.finish[1])), self.robot_radius, 3) pygame.draw.circle(self.screen, (0,200,0), (int(self.finish[0]), int(self.finish[1])), self.robot_radius, 3)
# Костры
for fire in self.fires: for fire in self.fires:
pygame.draw.circle(self.screen, (255,0,0), (int(fire.x), int(fire.y)), fire.radius) pygame.draw.circle(self.screen, (255,0,0), (int(fire.x), int(fire.y)), fire.radius)
pygame.draw.circle(self.screen, (255,100,0), (int(fire.x), int(fire.y)), fire.radius-3) pygame.draw.circle(self.screen, (255,100,0), (int(fire.x), int(fire.y)), fire.radius-3)
if self.robot_image: # Конус тушения
rotated = pygame.transform.rotate(self.robot_image, -math.degrees(self.angle)) if self.extinguish_active:
rect = rotated.get_rect(center=(int(self.x), int(self.y))) cone_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
self.screen.blit(rotated, rect) num_points = 20
points = [(self.x, self.y)]
half_angle = self.extinguish_angle / 2
cone_len = self.extinguish_cone_length
for i in range(num_points + 1):
angle = self.angle - half_angle + (self.extinguish_angle) * (i / num_points)
x = self.x + cone_len * math.cos(angle)
y = self.y + cone_len * math.sin(angle)
points.append((x, y))
if len(points) > 2:
pygame.draw.polygon(cone_surface, (0, 200, 255, 80), points)
self.screen.blit(cone_surface, (0, 0))
# Робот
if self.invincibility_timer > 0 and (self.invincibility_timer % 6 < 3):
pass
else: else:
nose = (self.x + self.robot_radius * math.cos(self.angle), if self.robot_image:
self.y + self.robot_radius * math.sin(self.angle)) rotated = pygame.transform.rotate(self.robot_image, -math.degrees(self.angle))
left = (self.x + self.robot_radius * math.cos(self.angle + 2.5), rect = rotated.get_rect(center=(int(self.x), int(self.y)))
self.y + self.robot_radius * math.sin(self.angle + 2.5)) self.screen.blit(rotated, rect)
right = (self.x + self.robot_radius * math.cos(self.angle - 2.5), else:
self.y + self.robot_radius * math.sin(self.angle - 2.5)) nose = (self.x + self.robot_radius * math.cos(self.angle),
pygame.draw.polygon(self.screen, (0,0,255), [nose, left, right]) self.y + self.robot_radius * math.sin(self.angle))
left = (self.x + self.robot_radius * math.cos(self.angle + 2.5),
self.y + self.robot_radius * math.sin(self.angle + 2.5))
right = (self.x + self.robot_radius * math.cos(self.angle - 2.5),
self.y + self.robot_radius * math.sin(self.angle - 2.5))
pygame.draw.polygon(self.screen, (0,0,255), [nose, left, right])
# Статистика
hp_text = self.font.render(f"HP: {self.hp}", True, (0,0,0)) hp_text = self.font.render(f"HP: {self.hp}", True, (0,0,0))
charge_text = self.font.render(f"Charge: {self.charge}", True, (0,0,0)) charge_text = self.font.render(f"Charge: {self.charge}", True, (0,0,0))
score_text = self.font.render(f"Score: {self.score}", True, (0,0,0)) score_text = self.font.render(f"Score: {self.score}", True, (0,0,0))
@ -156,7 +264,8 @@ class DummySimRobot(RobotController):
self.screen.blit(charge_text, (10, 40)) self.screen.blit(charge_text, (10, 40))
self.screen.blit(score_text, (10, 70)) self.screen.blit(score_text, (10, 70))
self.screen.blit(fires_text, (10, 100)) self.screen.blit(fires_text, (10, 100))
# Конец игры
if self.game_over: if self.game_over:
msg = self.font.render("GAME OVER Press R to restart", True, (255,0,0)) msg = self.font.render("GAME OVER Press R to restart", True, (255,0,0))
self.screen.blit(msg, (self.width//2 - 150, self.height//2)) self.screen.blit(msg, (self.width//2 - 150, self.height//2))
@ -195,6 +304,10 @@ class DummySimRobot(RobotController):
self.score = 0 self.score = 0
self.game_over = False self.game_over = False
self.won = False self.won = False
self.invincibility_timer = 0
self.extinguish_active = False
self.extinguish_timer = 0
self.extinguish_cooldown = 0
self._generate_fires() self._generate_fires()
def reset_position(self): def reset_position(self):

Loading…
Cancel
Save