dev-jakklu #5
@ -1,13 +1,12 @@
|
||||
from survival.enums import Direction
|
||||
from survival.settings import DIRECTION_CHANGE_DELAY
|
||||
|
||||
|
||||
class PositionComponent:
|
||||
def __init__(self, pos, grid_pos):
|
||||
def __init__(self, pos, grid_pos, direction=Direction.DOWN):
|
||||
self.position = pos
|
||||
self.grid_position = grid_pos
|
||||
self.direction = Direction.DOWN
|
||||
self.direction_change_timer = DIRECTION_CHANGE_DELAY
|
||||
self.direction = direction
|
||||
self.direction_change_timer = 0
|
||||
|
||||
def rotate_left(self):
|
||||
return Direction.rotate_left(self.direction)
|
||||
|
88
survival/graph_search.py
Normal file
88
survival/graph_search.py
Normal file
@ -0,0 +1,88 @@
|
||||
from enum import Enum
|
||||
|
||||
from survival import GameMap
|
||||
from survival.components.position_component import PositionComponent
|
||||
from survival.enums import Direction
|
||||
|
||||
|
||||
class Action(Enum):
|
||||
ROTATE_LEFT = 0
|
||||
ROTATE_RIGHT = 1
|
||||
MOVE = 2
|
||||
|
||||
|
||||
class State:
|
||||
def __init__(self, position, direction):
|
||||
self.position = position
|
||||
self.direction = direction
|
||||
|
||||
|
||||
class Node:
|
||||
def __init__(self, state: State, parent=None, action=None):
|
||||
self.state = state
|
||||
self.parent = parent
|
||||
self.action = action
|
||||
|
||||
|
||||
def get_moved_position(position, direction):
|
||||
vector = Direction.get_vector(direction)
|
||||
return position[0] + vector[0], position[1] + vector[1]
|
||||
|
||||
|
||||
def get_states(state: State, game_map: GameMap):
|
||||
states = list()
|
||||
|
||||
states.append((Action.ROTATE_LEFT, State(state.position, state.direction.rotate_left(state.direction))))
|
||||
states.append((Action.ROTATE_RIGHT, State(state.position, state.direction.rotate_right(state.direction))))
|
||||
|
||||
target_state = get_moved_position(state.position, state.direction)
|
||||
if not game_map.is_colliding(target_state):
|
||||
states.append((Action.MOVE, State(target_state, state.direction)))
|
||||
|
||||
return states
|
||||
|
||||
|
||||
def graph_search(game_map: GameMap, start: PositionComponent, goal: tuple):
|
||||
fringe = list()
|
||||
explored = list()
|
||||
|
||||
explored_states = set()
|
||||
fringe_states = set()
|
||||
|
||||
start = State(start.grid_position, start.direction)
|
||||
fringe.append(Node(start))
|
||||
fringe_states.add((tuple(start.position), start.direction))
|
||||
|
||||
while True:
|
||||
# No solutions found
|
||||
if not any(fringe):
|
||||
return []
|
||||
|
||||
node = fringe.pop(0)
|
||||
fringe_states.remove((tuple(node.state.position), node.state.direction))
|
||||
|
||||
# Check goal
|
||||
if node.state.position == goal:
|
||||
actions = [node.action]
|
||||
parent = node.parent
|
||||
|
||||
while parent is not None:
|
||||
if parent.action is not None:
|
||||
actions.append(parent.action)
|
||||
parent = parent.parent
|
||||
|
||||
actions.reverse()
|
||||
return actions
|
||||
|
||||
explored.append(node)
|
||||
explored_states.add((tuple(node.state.position), node.state.direction))
|
||||
|
||||
# Get all possible states
|
||||
for state in get_states(node.state, game_map):
|
||||
sub_state = (tuple(state[1].position), state[1].direction)
|
||||
if sub_state not in fringe_states and sub_state not in explored_states:
|
||||
new_node = Node(state=state[1],
|
||||
parent=node,
|
||||
action=state[0])
|
||||
fringe.append(new_node)
|
||||
fringe_states.add((tuple(new_node.state.position), new_node.state.direction))
|
@ -19,8 +19,7 @@ class InputSystem(esper.Processor):
|
||||
if mouse[0] == 1:
|
||||
pos = pygame.mouse.get_pos()
|
||||
pos = (pos[0] - self.camera.camera.left, pos[1] - self.camera.camera.top)
|
||||
if self.world.has_component(ent, PathfindingComponent):
|
||||
self.world.remove_component(ent, PathfindingComponent)
|
||||
if not self.world.has_component(ent, PathfindingComponent):
|
||||
self.world.add_component(ent, PathfindingComponent(pos))
|
||||
|
||||
if self.world.has_component(ent, MovingComponent):
|
||||
|
@ -4,6 +4,7 @@ from survival.components.movement_component import MovementComponent
|
||||
from survival.components.moving_component import MovingComponent
|
||||
from survival.components.position_component import PositionComponent
|
||||
from survival.enums import Direction
|
||||
from survival.graph_search import graph_search, Action
|
||||
from survival.pathfinding import breadth_first_search
|
||||
from survival.systems.input_system import PathfindingComponent
|
||||
|
||||
@ -17,26 +18,45 @@ class PathfindingMovementSystem(esper.Processor):
|
||||
for ent, (pos, pathfinding, movement) in self.world.get_components(PositionComponent, PathfindingComponent,
|
||||
MovementComponent):
|
||||
if pathfinding.path is None:
|
||||
pathfinding.path = breadth_first_search(self.game_map, pos.grid_position, pathfinding.target_grid_pos)
|
||||
pathfinding.path = graph_search(self.game_map, pos, pathfinding.target_grid_pos)
|
||||
|
||||
if len(pathfinding.path) < 1 and pathfinding.current_target is None:
|
||||
if len(pathfinding.path) < 1:
|
||||
self.world.remove_component(ent, PathfindingComponent)
|
||||
continue
|
||||
|
||||
if self.world.has_component(ent, MovingComponent):
|
||||
if self.world.has_component(ent, MovingComponent) or self.world.has_component(ent, DirectionChangeComponent):
|
||||
continue
|
||||
|
||||
if pathfinding.current_target is None:
|
||||
target = pathfinding.path.pop(0)
|
||||
action = pathfinding.path.pop(0)
|
||||
|
||||
if action == Action.ROTATE_LEFT:
|
||||
self.world.add_component(ent, DirectionChangeComponent(Direction.rotate_left(pos.direction)))
|
||||
elif action == Action.ROTATE_RIGHT:
|
||||
self.world.add_component(ent, DirectionChangeComponent(Direction.rotate_right(pos.direction)))
|
||||
else:
|
||||
target = pathfinding.current_target
|
||||
|
||||
vector = (target[0] - pos.grid_position[0], target[1] - pos.grid_position[1])
|
||||
direction = Direction.from_vector(vector)
|
||||
if direction != pos.direction:
|
||||
pathfinding.current_target = target
|
||||
self.world.add_component(ent, DirectionChangeComponent(direction))
|
||||
continue
|
||||
|
||||
pathfinding.current_target = None
|
||||
self.world.add_component(ent, MovingComponent())
|
||||
|
||||
# if pathfinding.path is None:
|
||||
# pathfinding.path = breadth_first_search(self.game_map, pos.grid_position, pathfinding.target_grid_pos)
|
||||
#
|
||||
# if len(pathfinding.path) < 1 and pathfinding.current_target is None:
|
||||
# self.world.remove_component(ent, PathfindingComponent)
|
||||
# continue
|
||||
#
|
||||
# if self.world.has_component(ent, MovingComponent):
|
||||
# continue
|
||||
#
|
||||
# if pathfinding.current_target is None:
|
||||
# target = pathfinding.path.pop(0)
|
||||
# else:
|
||||
# target = pathfinding.current_target
|
||||
#
|
||||
# vector = (target[0] - pos.grid_position[0], target[1] - pos.grid_position[1])
|
||||
# direction = Direction.from_vector(vector)
|
||||
# if direction != pos.direction:
|
||||
# pathfinding.current_target = target
|
||||
# self.world.add_component(ent, DirectionChangeComponent(direction))
|
||||
# continue
|
||||
#
|
||||
# pathfinding.current_target = None
|
||||
# self.world.add_component(ent, MovingComponent())
|
||||
|
Loading…
Reference in New Issue
Block a user