From deeba7c740ea90783bcfd79853ecc3067bd395db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Czeka=C5=84ski?= Date: Sun, 26 Apr 2020 03:59:09 +0200 Subject: [PATCH] Spaghetti code, not working --- src/AI/AutomaticMovement.py | 155 +++++++++++++++++++++++++----------- src/game/EventManager.py | 4 + src/game/Game.py | 14 +++- src/game/Map.py | 13 ++- 4 files changed, 135 insertions(+), 51 deletions(-) diff --git a/src/AI/AutomaticMovement.py b/src/AI/AutomaticMovement.py index e298cbd..160eb34 100644 --- a/src/AI/AutomaticMovement.py +++ b/src/AI/AutomaticMovement.py @@ -10,16 +10,27 @@ from src.game.TerrainTile import TerrainTile class AutomaticMovement: - def __init__(self, player, gameMap): + def __init__(self, player, gameMap, leftUiWidth): self.map = gameMap self.player = player self.nextMove = None self.movesList = None self.actualTarget = None self.moveOffset = self.player.rect.w + self.leftUiWidth = leftUiWidth + self.targetCoords = None + + self.testCount = 0 def gotoToTarget(self, target: Entity): - self.actualTarget = target + if self.actualTarget is None: + self.actualTarget = target + self.targetCoords = (self.actualTarget.rect.x - self.leftUiWidth, self.actualTarget.rect.y) + self.movesList = self.a_Star() + if self.movesList is not None: + self.nextMove = self.movesList[0] + else: + self.actualTarget = None def updatePlayerCoords(self): if self.actualTarget is not None: @@ -32,50 +43,85 @@ class AutomaticMovement: self.actualTarget = None def a_Star(self): + self.testCount = 0 + fringe = PriorityQueue() explored = [] - startingState = (self.player.x, self.player.y, self.player.rotation) + startingState = (self.player.rect.x - self.leftUiWidth, self.player.rect.y, self.player.rotation) startingPriority = 0 - fringe.put((startingPriority, AStarNode(None, None, startingState))) + + + 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() + + + + elem: AStarNode = fringe.get()[2] + + print("CURRENT STATE: {}, ACTION: {}".format(elem.state, elem.action)) + for (pr, count, node) in fringe.queue: + print("PR: {}, ST: {}, AC: {}".format(pr, node.state, node.action)) if self.goalTest(elem.state): - result = [] + movesList = [] p = elem.parent while p is not None: - result.append((elem.parent, elem.action)) - return result + movesList.append(elem.action) + p = elem.parent + return movesList explored.append(elem) for (movement, newState) in self.succesor(elem.state): - newNode = AStarNode(elem, movement, newState) - newPriority = self.priority(newNode) + # Sprawdzam czy nie jest poza mapa + coordsWithUiOffset = [newState[0] + self.leftUiWidth, newState[1]] - # Check if state is not in fringe queue ... - if not any(newNode.state == node[1].state for node in fringe.queue): - # ... and is not in explored list - if not any(newNode.state == node[1].state for node in explored): - fringe.put((newPriority, newNode)) - # If state is in fringe queue ... - else: - node: AStarNode - for (pr, node) in fringe.queue: - # Compare nodes - if node.state == newNode.state and node.parent is newNode.parent and node.action == newNode.action: - # ... and if it has priority > newPriority - if pr > newPriority: - # Replace it with new priority - fringe.queue.remove((pr, node)) - fringe.put((newPriority, node)) + # DEBUG + if movement == Movement.FORWARD: + a = 1 + a+=1 + + 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 + ''' + while any(newPriority == item[0] for item in fringe.queue): + newPriority -= 1''' + 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): ''' @@ -86,29 +132,42 @@ class AutomaticMovement: (Movement.ROTATE_L, self.newStateAfterAction(elemState, Movement.ROTATE_L))] stateAfterForward = self.newStateAfterAction(elemState, Movement.FORWARD) - facingEntity = self.map.getEntityOnCoord(stateAfterForward) - - if facingEntity is not None: - result.append((Movement.FORWARD, stateAfterForward)) + if 0 <= stateAfterForward[0] <= self.map.width - self.moveOffset and 0 <= stateAfterForward[1] <= self.map.height - self.moveOffset: + coordsWithUiOffset = [stateAfterForward[0] + self.leftUiWidth, stateAfterForward[1]] + facingEntity = self.map.getEntityOnCoord(coordsWithUiOffset) + if facingEntity is None: + result.append((Movement.FORWARD, stateAfterForward)) return result def goalTest(self, coords): - entity = self.map.getEntityOnCoord(coords) - if entity.id == self.actualTarget.id: + # 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): - return abs(tileX - self.actualTarget.x) + abs(tileY - self.actualTarget.y) + return abs(tileX - self.targetCoords[0]) + abs(tileY - self.targetCoords[1]) def stepCost(self, terrainTile: TerrainTile): - return terrainTile.cost + + # TODO: Nie znajduje terraina na ktorym stoi player + if terrainTile is None: + return 0 + #return terrainTile.cost + return 0 def priority(self, elem: AStarNode): - return self.approximateDistanceFromTarget(elem.state[0], elem.state[1]) + self.stepCost(self.map.getTileOnCoord(elem.state)) + coordsWithUiOffset = [elem.state[0] + self.leftUiWidth, elem.state[1]] + return self.approximateDistanceFromTarget(elem.state[0], elem.state[1]) + self.stepCost(self.map.getTileOnCoord(coordsWithUiOffset)) ''' state[0] - x @@ -117,20 +176,26 @@ class AutomaticMovement: ''' def newStateAfterAction(self, state, action: Movement): - newState = copy(state) + + newX = state[0] + newY = state[1] + newRotation = state[2] if action == Movement.FORWARD: if state[2] == Rotations.NORTH: - newState[1] -= self.moveOffset - elif state[2] == Rotations.EAST.value: - newState[0] += self.moveOffset - elif state[2] == Rotations.SOUTH.value: - newState[1] += self.moveOffset - elif state[2] == Rotations.WEST.value: - newState[0] -= self.moveOffset + newY -= self.moveOffset + elif state[2] == Rotations.EAST: + newX += self.moveOffset + elif state[2] == Rotations.SOUTH: + newY += self.moveOffset + elif state[2] == Rotations.WEST: + newX -= self.moveOffset elif action == Movement.ROTATE_L: - newState[2] = Rotations((state[2] + 1) % 4) + newRotation = Rotations((state[2].value - 1) % 4) elif action == Movement.ROTATE_R: - newState[2] = Rotations((state[2] - 1) % 4) + newRotation = Rotations((state[2].value + 1) % 4) + + + newState = (newX, newY, newRotation) return newState diff --git a/src/game/EventManager.py b/src/game/EventManager.py index 066b81e..08c8a59 100644 --- a/src/game/EventManager.py +++ b/src/game/EventManager.py @@ -1,3 +1,4 @@ +from random import Random from time import sleep import pygame @@ -90,5 +91,8 @@ class EventManager: if keys[pygame.K_d]: self.player.move(Movement.ROTATE_R) + if keys[pygame.K_u]: + self.game.movement.gotoToTarget(self.game.map.entities[Random().randint(0, len(self.game.map.entities))]) + diff --git a/src/game/Game.py b/src/game/Game.py index 73e7c47..7d9d400 100644 --- a/src/game/Game.py +++ b/src/game/Game.py @@ -5,7 +5,7 @@ from os import path from src.AI.AutomaticMovement import AutomaticMovement from src.game.EventManager import EventManager -from src.game.Screen import Screen +from src.game.Screen import Screen, Locations from src.game.Map import Map from src.entities.Player import Player @@ -51,10 +51,17 @@ class Game: mapFile = Path(str(filesPath) + "/data/mapdata/") self.map = Map(path.join(mapFile, 'map.txt'), self.screen) self.player = Player((6, 2), self.map.tileSize) - self.map.addEntity(self.player) + self.map.addEntity(self.player, DONTADD=True) self.eventManager = EventManager(self, self.player) - self.movement = AutomaticMovement(self.player, self.map) + self.movement = AutomaticMovement(self.player, self.map, self.screen.getUiWidth(Locations.LEFT_UI)) + + + testTarget = self.map.entities[0] + if testTarget is self.player: + testTarget = self.map.entities[1] + + self.movement.gotoToTarget(testTarget) self.mainLoop() @@ -64,5 +71,6 @@ class Game: self.ingameTimer.updateTime(self.pgTimer.tick()) self.spritesList.update() self.eventManager.handleEvents() + self.movement.updatePlayerCoords() self.spritesList.draw(self.screen.pygameScreen) pygame.display.flip() diff --git a/src/game/Map.py b/src/game/Map.py index 6fee562..78ce03a 100644 --- a/src/game/Map.py +++ b/src/game/Map.py @@ -19,6 +19,8 @@ class Map: self.terrainTilesList = [] self.collidables = pygame.sprite.Group() + self.entities = [] + with open(filename, 'rt') as f: for line in f: self.terrain.append(line) @@ -101,27 +103,32 @@ class Map: def getEntityOnCoord(self, coord): result = None - for entity in self.collidables: + for entity in self.entities: if entity.rect.x == coord[0] and entity.rect.y == coord[1]: result = entity return result def getTileOnCoord(self, coord): result = None - for entity in self.: + for entity in self.terrainTilesList: if entity.rect.x == coord[0] and entity.rect.y == coord[1]: result = entity return result - def addEntity(self, entity): + # TODO: REMOVE DONT ADD + def addEntity(self, entity, DONTADD=False): self.screen.draw(entity, Locations.MAP, 0, 0) self.collidables.add(entity) + if not DONTADD: + self.entities.append(entity) def removeSpriteFromMap(self, entity): if self.collidables.has(entity): self.collidables.remove(entity) self.screen.removeSprite(entity) + self.entities.remove(entity) + # add object to map.collidables list to be collidable def collision(self, x, y): for b in self.collidables: