Fix problems with pathfinding to some map locations and add go-to on click

succesor method fixed
This commit is contained in:
Michał Czekański 2020-04-26 17:58:22 +02:00
parent 31d2bf0009
commit 1255ab8e16
2 changed files with 63 additions and 50 deletions

View File

@ -1,5 +1,3 @@
from copy import copy
from src.entities.Entity import Entity from src.entities.Entity import Entity
from src.entities.Player import Movement, Rotations from src.entities.Player import Movement, Rotations
from src.AI.AStarNode import AStarNode from src.AI.AStarNode import AStarNode
@ -30,20 +28,26 @@ class AutomaticMovement:
if self.movesList is not None: if self.movesList is not None:
if len(self.movesList) > 0: if len(self.movesList) > 0:
self.nextMove = self.movesList[0] self.nextMove = self.movesList[0]
else:
self.actualTarget = None
self.nextMove = None
else: else:
self.actualTarget = None self.actualTarget = None
def updatePlayerCoords(self): def updatePlayerCoords(self):
if self.actualTarget is not None: if self.actualTarget is not None and self.nextMove is not None:
self.player.move(self.nextMove) self.player.move(self.nextMove)
self.movesList.remove(self.nextMove) self.movesList.remove(self.nextMove)
if len(self.movesList) != 0: if len(self.movesList) != 0:
self.nextMove = self.movesList[0] self.nextMove = self.movesList[0]
else: else:
self.movesList = None
self.nextMove = None self.nextMove = None
self.actualTarget = None self.actualTarget = None
def a_Star(self): def a_Star(self):
print("A* in progress ...")
self.testCount = 0 self.testCount = 0
fringe = PriorityQueue() fringe = PriorityQueue()
@ -55,21 +59,18 @@ class AutomaticMovement:
fringe.put((startingPriority, self.testCount, AStarNode(None, None, startingState))) fringe.put((startingPriority, self.testCount, AStarNode(None, None, startingState)))
self.testCount += 1 self.testCount += 1
while True: while True:
print("DEBUG: A* in progress")
if fringe.empty(): if fringe.empty():
# target is unreachable # target is unreachable
self.movesList = None
self.nextMove = None
print("PATH NOT FOUND") print("PATH NOT FOUND")
return None return None
elem: AStarNode = fringe.get()[2] elem: AStarNode = fringe.get()[2]
if self.goalTest(elem.state): if self.goalTest(elem.state):
print("PATH FOUND")
movesList = [] movesList = []
if isinstance(self.actualTarget, Entity): if isinstance(self.actualTarget, Entity) or self.actualTarget in self.map.collidables:
elem = elem.parent elem = elem.parent
while elem.action is not None: while elem.action is not None:
@ -79,37 +80,46 @@ class AutomaticMovement:
movesList.reverse() movesList.reverse()
return movesList return movesList
# debug
print("DEBUG")
print("ACTUAL STATE: {}".format(elem.state))
print("HOW TO GET HERE:")
temp = elem
while temp.action is not None:
print(temp.action)
temp = temp.parent
print("POSSIBLE MOVEMENTS FROM HERE:")
for el in self.succesor(elem.state):
print(el)
print("*" * 20)
explored.append(elem) explored.append(elem)
for (movement, newState) in self.succesor(elem.state): for (movement, newState) in self.succesor(elem.state):
# Sprawdzam czy nie jest poza mapa newNode = AStarNode(elem, movement, newState)
coordsWithUiOffset = [newState[0] + self.leftUiWidth, newState[1]] newPriority = self.priority(newNode)
if 0 <= newState[0] <= self.map.width - self.moveOffset and 0 <= newState[ # Check if state is not in fringe queue ... # ... and is not in explored list
1] <= self.map.height - self.moveOffset: if not any(newNode.state == node[2].state for node in fringe.queue) \
# if self.map.getTileOnCoord(coordsWithUiOffset) is not None: and not any(newNode.state == node.state for node in explored):
newNode = AStarNode(elem, movement, newState) # there can't be nodes with same priority
newPriority = self.priority(newNode) fringe.put((newPriority, self.testCount, newNode))
self.testCount += 1
# Check if state is not in fringe queue ... # ... and is not in explored list # If state is in fringe queue ...
if not any(newNode.state == node[2].state for node in fringe.queue) \ elif any(newNode.state == node[2].state for node in fringe.queue):
and not any(newNode.state == node.state for node in explored): node: AStarNode
# there can't be nodes with same priority for (pr, count, node) in fringe.queue:
fringe.put((newPriority, self.testCount, newNode)) # Compare nodes
self.testCount += 1 if node.state == newNode.state and node.action == newNode.action:
# If state is in fringe queue ... # ... and if it has priority > newPriority
elif any(newNode.state == node[2].state for node in fringe.queue): if pr > newPriority:
node: AStarNode # Replace it with new priority
for (pr, count, node) in fringe.queue: fringe.queue.remove((pr, count, node))
# Compare nodes fringe.put((newPriority, count, node))
if node.state == newNode.state and node.action == newNode.action: self.testCount += 1
# ... and if it has priority > newPriority break
if pr > newPriority:
# Replace it with new priority
fringe.queue.remove((pr, count, node))
fringe.put((newPriority, count, node))
self.testCount += 1
break
def succesor(self, elemState): def succesor(self, elemState):
''' '''
@ -120,31 +130,25 @@ class AutomaticMovement:
(Movement.ROTATE_L, self.newStateAfterAction(elemState, Movement.ROTATE_L))] (Movement.ROTATE_L, self.newStateAfterAction(elemState, Movement.ROTATE_L))]
stateAfterForward = self.newStateAfterAction(elemState, Movement.FORWARD) stateAfterForward = self.newStateAfterAction(elemState, Movement.FORWARD)
if 0 <= stateAfterForward[0] <= self.map.width - self.moveOffset and 0 <= stateAfterForward[ if 0 <= stateAfterForward[0] <= self.map.width and 0 <= stateAfterForward[1] <= self.map.height:
1] <= self.map.height - self.moveOffset:
coordsWithUiOffset = [stateAfterForward[0] + self.leftUiWidth, stateAfterForward[1]] coordsWithUiOffset = [stateAfterForward[0] + self.leftUiWidth, stateAfterForward[1]]
facingEntity = self.map.getEntityOnCoord(coordsWithUiOffset) facingEntity = self.map.getEntityOnCoord(coordsWithUiOffset)
if facingEntity is not None: if facingEntity is not None:
if facingEntity.id == self.actualTarget.id: if isinstance(self.actualTarget, Entity):
result.append((Movement.FORWARD, stateAfterForward)) if facingEntity.id == self.actualTarget.id:
result.append((Movement.FORWARD, stateAfterForward))
elif self.map.collision(coordsWithUiOffset[0], coordsWithUiOffset[1]) and \
self.targetCoords[0] == stateAfterForward[0] and self.targetCoords[1] == stateAfterForward[1]:
result.append((Movement.FORWARD, stateAfterForward))
elif not self.map.collision(coordsWithUiOffset[0], coordsWithUiOffset[1]): elif not self.map.collision(coordsWithUiOffset[0], coordsWithUiOffset[1]):
result.append((Movement.FORWARD, stateAfterForward)) result.append((Movement.FORWARD, stateAfterForward))
return result return result
def goalTest(self, coords): def goalTest(self, coords):
# with left ui width
coordsWithUiOffset = [coords[0] + self.leftUiWidth, coords[1]]
entity = self.map.getEntityOnCoord(coordsWithUiOffset)
'''if entity is not None:
if entity.id == self.actualTarget.id:
return True'''
if coords[0] == self.targetCoords[0] and coords[1] == self.targetCoords[1]: if coords[0] == self.targetCoords[0] and coords[1] == self.targetCoords[1]:
return True return True
return False return False
def approximateDistanceFromTarget(self, tileX, tileY): def approximateDistanceFromTarget(self, tileX, tileY):
@ -168,7 +172,6 @@ class AutomaticMovement:
state[1] - y state[1] - y
state[2] - rotation state[2] - rotation
''' '''
def newStateAfterAction(self, state, action: Movement): def newStateAfterAction(self, state, action: Movement):
newX = state[0] newX = state[0]

View File

@ -38,6 +38,16 @@ class EventManager:
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
self.game.running = False self.game.running = False
if event.type == pygame.MOUSEBUTTONUP:
pos = pygame.mouse.get_pos()
# get a list of all sprites that are under the mouse cursor
clicked_sprites = [s for s in self.game.map.collidables if s.rect.collidepoint(pos)]
# do something with the clicked sprites...
if len(clicked_sprites) > 0:
self.game.movement.gotoToTarget(Random().choice(clicked_sprites))
self.game.screen.ui.updateBasedOnPygameEvent(event) self.game.screen.ui.updateBasedOnPygameEvent(event)
self.keyTimeout += self.keyTimer.tick() self.keyTimeout += self.keyTimer.tick()
if self.keyTimeout >= TIMEOUT: if self.keyTimeout >= TIMEOUT:
@ -95,7 +105,7 @@ class EventManager:
if keys[pygame.K_u]: if keys[pygame.K_u]:
while True: while True:
try: try:
self.game.movement.gotoToTarget(self.game.map.entities[Random().randint(0, len(self.game.map.entities))]) self.game.movement.gotoToTarget(Random().choice(self.game.map.entities))
break break
except IndexError: except IndexError:
pass pass