From 1255ab8e16011bd4833f93b8647856a61f988dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Czeka=C5=84ski?= Date: Sun, 26 Apr 2020 17:58:22 +0200 Subject: [PATCH] Fix problems with pathfinding to some map locations and add go-to on click succesor method fixed --- src/AI/AutomaticMovement.py | 101 +++++++++++++++++++----------------- src/game/EventManager.py | 12 ++++- 2 files changed, 63 insertions(+), 50 deletions(-) diff --git a/src/AI/AutomaticMovement.py b/src/AI/AutomaticMovement.py index 3ab41b2..6e2d138 100644 --- a/src/AI/AutomaticMovement.py +++ b/src/AI/AutomaticMovement.py @@ -1,5 +1,3 @@ -from copy import copy - from src.entities.Entity import Entity from src.entities.Player import Movement, Rotations from src.AI.AStarNode import AStarNode @@ -30,20 +28,26 @@ class AutomaticMovement: if self.movesList is not None: if len(self.movesList) > 0: self.nextMove = self.movesList[0] + else: + self.actualTarget = None + self.nextMove = None else: self.actualTarget = None 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.movesList.remove(self.nextMove) if len(self.movesList) != 0: self.nextMove = self.movesList[0] else: + self.movesList = None self.nextMove = None self.actualTarget = None def a_Star(self): + print("A* in progress ...") + self.testCount = 0 fringe = PriorityQueue() @@ -55,21 +59,18 @@ class AutomaticMovement: fringe.put((startingPriority, self.testCount, AStarNode(None, None, startingState))) self.testCount += 1 while True: - print("DEBUG: A* in progress") - if fringe.empty(): # target is unreachable - self.movesList = None - self.nextMove = None print("PATH NOT FOUND") return None elem: AStarNode = fringe.get()[2] if self.goalTest(elem.state): + print("PATH FOUND") movesList = [] - if isinstance(self.actualTarget, Entity): + if isinstance(self.actualTarget, Entity) or self.actualTarget in self.map.collidables: elem = elem.parent while elem.action is not None: @@ -79,37 +80,46 @@ class AutomaticMovement: movesList.reverse() 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) for (movement, newState) in self.succesor(elem.state): - # Sprawdzam czy nie jest poza mapa - coordsWithUiOffset = [newState[0] + self.leftUiWidth, newState[1]] + newNode = AStarNode(elem, movement, newState) + newPriority = self.priority(newNode) - if 0 <= newState[0] <= self.map.width - self.moveOffset and 0 <= newState[ - 1] <= self.map.height - self.moveOffset: - # if self.map.getTileOnCoord(coordsWithUiOffset) is not None: - newNode = AStarNode(elem, movement, newState) - newPriority = self.priority(newNode) - - # Check if state is not in fringe queue ... # ... and is not in explored list - if not any(newNode.state == node[2].state for node in fringe.queue) \ - and not any(newNode.state == node.state for node in explored): - # there can't be nodes with same priority - fringe.put((newPriority, self.testCount, newNode)) - self.testCount += 1 - # If state is in fringe queue ... - elif any(newNode.state == node[2].state for node in fringe.queue): - node: AStarNode - for (pr, count, node) in fringe.queue: - # Compare nodes - if node.state == newNode.state and node.action == newNode.action: - # ... and if it has priority > newPriority - if pr > newPriority: - # Replace it with new priority - fringe.queue.remove((pr, count, node)) - fringe.put((newPriority, count, node)) - self.testCount += 1 - break + # Check if state is not in fringe queue ... # ... and is not in explored list + if not any(newNode.state == node[2].state for node in fringe.queue) \ + and not any(newNode.state == node.state for node in explored): + # there can't be nodes with same priority + fringe.put((newPriority, self.testCount, newNode)) + self.testCount += 1 + # If state is in fringe queue ... + elif any(newNode.state == node[2].state for node in fringe.queue): + node: AStarNode + for (pr, count, node) in fringe.queue: + # Compare nodes + if node.state == newNode.state and node.action == newNode.action: + # ... and if it has priority > newPriority + 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): ''' @@ -120,31 +130,25 @@ class AutomaticMovement: (Movement.ROTATE_L, self.newStateAfterAction(elemState, Movement.ROTATE_L))] stateAfterForward = self.newStateAfterAction(elemState, Movement.FORWARD) - if 0 <= stateAfterForward[0] <= self.map.width - self.moveOffset and 0 <= stateAfterForward[ - 1] <= self.map.height - self.moveOffset: + if 0 <= stateAfterForward[0] <= self.map.width and 0 <= stateAfterForward[1] <= self.map.height: coordsWithUiOffset = [stateAfterForward[0] + self.leftUiWidth, stateAfterForward[1]] facingEntity = self.map.getEntityOnCoord(coordsWithUiOffset) if facingEntity is not None: - if facingEntity.id == self.actualTarget.id: - result.append((Movement.FORWARD, stateAfterForward)) + if isinstance(self.actualTarget, Entity): + 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]): result.append((Movement.FORWARD, stateAfterForward)) return result 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]: return True - return False def approximateDistanceFromTarget(self, tileX, tileY): @@ -168,7 +172,6 @@ class AutomaticMovement: state[1] - y state[2] - rotation ''' - def newStateAfterAction(self, state, action: Movement): newX = state[0] diff --git a/src/game/EventManager.py b/src/game/EventManager.py index 2c3a84e..fa7ee64 100644 --- a/src/game/EventManager.py +++ b/src/game/EventManager.py @@ -38,6 +38,16 @@ class EventManager: for event in pygame.event.get(): if event.type == pygame.QUIT: 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.keyTimeout += self.keyTimer.tick() if self.keyTimeout >= TIMEOUT: @@ -95,7 +105,7 @@ class EventManager: if keys[pygame.K_u]: while True: 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 except IndexError: pass