mirror of
https://github.com/Project-Redacted/Gayme.git
synced 2025-05-24 11:54:53 +00:00
Path finding
This commit is contained in:
parent
b9f02c8268
commit
a32720cedb
30 changed files with 216 additions and 0 deletions
144
npc.py
Normal file
144
npc.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
from sprite_object import *
|
||||
from random import randint, random, choice
|
||||
|
||||
class NPC(AnimatedSprite):
|
||||
def __init__(self, game, path='resources/sprites/npc/soldier/0.png', pos=(10.5, 5.5),
|
||||
scale=0.6, shift=0.38, animation_time=180):
|
||||
super().__init__(game, path, pos, scale, shift, animation_time)
|
||||
self.attack_images = self.get_images(self.path + '/attack')
|
||||
self.death_images = self.get_images(self.path + '/death')
|
||||
self.idle_images = self.get_images(self.path + '/idle')
|
||||
self.pain_images = self.get_images(self.path + '/pain')
|
||||
self.walk_images = self.get_images(self.path + '/walk')
|
||||
|
||||
self.attack_dist = randint(3, 6)
|
||||
self.speed = 0.02
|
||||
self.size = 10
|
||||
self.health = 100
|
||||
self.attack_damage = 10
|
||||
self.accuracy = 0.15
|
||||
self.alive = True
|
||||
self.pain = False
|
||||
self.ray_cast_value = False
|
||||
self.player_search_trigger = False
|
||||
|
||||
def update(self):
|
||||
self.check_animation_time()
|
||||
self.get_sprite()
|
||||
self.run_logic()
|
||||
if DEBUG_MODE:
|
||||
self.draw_ray_cast()
|
||||
|
||||
def check_wall(self, x, y):
|
||||
return (x, y) not in self.game.map.world_map
|
||||
|
||||
def check_collision(self, dx, dy):
|
||||
if self.check_wall(int(self.x + dx * self.size), int(self.y)):
|
||||
self.x += dx
|
||||
if self.check_wall(int(self.x), int(self.y + dy * self.size)):
|
||||
self.y += dy
|
||||
|
||||
def movement(self):
|
||||
next_pos = self.game.pathfinding.get_path(self.map_pos, self.game.player.map_pos)
|
||||
next_x, next_y = next_pos
|
||||
if DEBUG_MODE:
|
||||
pg.draw.rect(self.game.screen, 'blue', (100 * next_x, 100 * next_y, 100, 100))
|
||||
if next_pos not in self.game.object_handler.npc_positions:
|
||||
angle = math.atan2(next_y + 0.5 - self.y, next_x + 0.5 - self.x)
|
||||
dx = math.cos(angle) * self.speed
|
||||
dy = math.sin(angle) * self.speed
|
||||
self.check_collision(dx, dy)
|
||||
|
||||
def attack(self):
|
||||
if self.animation_trigger:
|
||||
pass
|
||||
|
||||
def run_logic(self):
|
||||
if self.alive:
|
||||
self.ray_cast_value = self.ray_cast_player_npc()
|
||||
self.animate(self.idle_images)
|
||||
if self.ray_cast_value:
|
||||
self.player_search_trigger = True
|
||||
|
||||
if self.dist < self.attack_dist:
|
||||
self.animate(self.attack_images)
|
||||
self.attack()
|
||||
else:
|
||||
self.animate(self.walk_images)
|
||||
self.movement()
|
||||
elif self.player_search_trigger:
|
||||
self.animate(self.walk_images)
|
||||
self.movement()
|
||||
|
||||
@property
|
||||
def map_pos(self):
|
||||
return int(self.x), int(self.y)
|
||||
|
||||
def ray_cast_player_npc(self):
|
||||
if self.game.player.map_pos == self.map_pos:
|
||||
return True
|
||||
|
||||
wall_dist_v, wall_dist_h = 0, 0
|
||||
player_dist_v, player_dist_h = 0, 0
|
||||
|
||||
ox, oy = self.game.player.pos
|
||||
x_map, y_map = self.game.player.map_pos
|
||||
|
||||
ray_angle = self.theta
|
||||
sin_a = math.sin(ray_angle)
|
||||
cos_a = math.cos(ray_angle)
|
||||
|
||||
# horizontal
|
||||
y_horz, dy = (y_map + 1, 1) if sin_a > 0 else (y_map - 1e-6, -1)
|
||||
|
||||
depth_horz = (y_horz - oy) / sin_a
|
||||
x_horz = ox + depth_horz * cos_a
|
||||
|
||||
delta_depth = dy / sin_a
|
||||
dx = delta_depth * cos_a
|
||||
|
||||
for i in range(MAX_DEPTH):
|
||||
tile_horz = int(x_horz), int(y_horz)
|
||||
if tile_horz == self.map_pos:
|
||||
player_dist_h = depth_horz
|
||||
break
|
||||
if tile_horz in self.game.map.world_map:
|
||||
wall_dist_h = depth_horz
|
||||
break
|
||||
x_horz += dx
|
||||
y_horz += dy
|
||||
depth_horz += delta_depth
|
||||
|
||||
# verticals
|
||||
x_vert, dx = (x_map + 1, 1) if cos_a > 0 else (x_map - 1e-6, -1)
|
||||
|
||||
depth_vert = (x_vert - ox) / cos_a
|
||||
y_vert = oy + depth_vert * sin_a
|
||||
|
||||
delta_depth = dx / cos_a
|
||||
dy = delta_depth * sin_a
|
||||
|
||||
for i in range(MAX_DEPTH):
|
||||
tile_vert = int(x_vert), int(y_vert)
|
||||
if tile_vert == self.map_pos:
|
||||
player_dist_v = depth_vert
|
||||
break
|
||||
if tile_vert in self.game.map.world_map:
|
||||
wall_dist_v = depth_vert
|
||||
break
|
||||
x_vert += dx
|
||||
y_vert += dy
|
||||
depth_vert += delta_depth
|
||||
|
||||
player_dist = max(player_dist_v, player_dist_h)
|
||||
wall_dist = max(wall_dist_v, wall_dist_h)
|
||||
|
||||
if 0 < player_dist < wall_dist or not wall_dist:
|
||||
return True
|
||||
return False
|
||||
|
||||
def draw_ray_cast(self):
|
||||
pg.draw.circle(self.game.screen, 'red', (100 * self.x, 100 * self.y), 15)
|
||||
if self.ray_cast_player_npc():
|
||||
pg.draw.line(self.game.screen, 'orange', (100 * self.game.player.x, 100 * self.game.player.y),
|
||||
(100 * self.x, 100 * self.y), 2)
|
Loading…
Add table
Add a link
Reference in a new issue