Spaghetti code, not working

This commit is contained in:
Michał Czekański 2020-04-26 03:59:09 +02:00
parent 39b689d8f0
commit deeba7c740
4 changed files with 135 additions and 51 deletions

View File

@ -10,16 +10,27 @@ from src.game.TerrainTile import TerrainTile
class AutomaticMovement: class AutomaticMovement:
def __init__(self, player, gameMap): def __init__(self, player, gameMap, leftUiWidth):
self.map = gameMap self.map = gameMap
self.player = player self.player = player
self.nextMove = None self.nextMove = None
self.movesList = None self.movesList = None
self.actualTarget = None self.actualTarget = None
self.moveOffset = self.player.rect.w self.moveOffset = self.player.rect.w
self.leftUiWidth = leftUiWidth
self.targetCoords = None
self.testCount = 0
def gotoToTarget(self, target: Entity): 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): def updatePlayerCoords(self):
if self.actualTarget is not None: if self.actualTarget is not None:
@ -32,50 +43,85 @@ class AutomaticMovement:
self.actualTarget = None self.actualTarget = None
def a_Star(self): def a_Star(self):
self.testCount = 0
fringe = PriorityQueue() fringe = PriorityQueue()
explored = [] 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 startingPriority = 0
fringe.put((startingPriority, AStarNode(None, None, startingState)))
fringe.put((startingPriority, self.testCount, AStarNode(None, None, startingState)))
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.movesList = None
self.nextMove = 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): if self.goalTest(elem.state):
result = [] movesList = []
p = elem.parent p = elem.parent
while p is not None: while p is not None:
result.append((elem.parent, elem.action)) movesList.append(elem.action)
return result p = elem.parent
return movesList
explored.append(elem) explored.append(elem)
for (movement, newState) in self.succesor(elem.state): for (movement, newState) in self.succesor(elem.state):
newNode = AStarNode(elem, movement, newState) # Sprawdzam czy nie jest poza mapa
newPriority = self.priority(newNode) coordsWithUiOffset = [newState[0] + self.leftUiWidth, newState[1]]
# Check if state is not in fringe queue ... # DEBUG
if not any(newNode.state == node[1].state for node in fringe.queue): if movement == Movement.FORWARD:
# ... and is not in explored list a = 1
if not any(newNode.state == node[1].state for node in explored): a+=1
fringe.put((newPriority, newNode))
# If state is in fringe queue ... if 0 <= newState[0] <= self.map.width - self.moveOffset and 0 <= newState[1] <= self.map.height - self.moveOffset:
else: #if self.map.getTileOnCoord(coordsWithUiOffset) is not None:
node: AStarNode newNode = AStarNode(elem, movement, newState)
for (pr, node) in fringe.queue: newPriority = self.priority(newNode)
# Compare nodes
if node.state == newNode.state and node.parent is newNode.parent and node.action == newNode.action: # Check if state is not in fringe queue ... # ... and is not in explored list
# ... and if it has priority > newPriority if not any(newNode.state == node[2].state for node in fringe.queue) \
if pr > newPriority: and not any(newNode.state == node.state for node in explored):
# Replace it with new priority # there can't be nodes with same priority
fringe.queue.remove((pr, node)) '''
fringe.put((newPriority, node)) 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): def succesor(self, elemState):
''' '''
@ -86,29 +132,42 @@ 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)
facingEntity = self.map.getEntityOnCoord(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]]
if facingEntity is not None: facingEntity = self.map.getEntityOnCoord(coordsWithUiOffset)
result.append((Movement.FORWARD, stateAfterForward)) if facingEntity is None:
result.append((Movement.FORWARD, stateAfterForward))
return result return result
def goalTest(self, coords): 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 True
return False return False
def approximateDistanceFromTarget(self, tileX, tileY): 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): 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): 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 state[0] - x
@ -117,20 +176,26 @@ class AutomaticMovement:
''' '''
def newStateAfterAction(self, state, action: Movement): def newStateAfterAction(self, state, action: Movement):
newState = copy(state)
newX = state[0]
newY = state[1]
newRotation = state[2]
if action == Movement.FORWARD: if action == Movement.FORWARD:
if state[2] == Rotations.NORTH: if state[2] == Rotations.NORTH:
newState[1] -= self.moveOffset newY -= self.moveOffset
elif state[2] == Rotations.EAST.value: elif state[2] == Rotations.EAST:
newState[0] += self.moveOffset newX += self.moveOffset
elif state[2] == Rotations.SOUTH.value: elif state[2] == Rotations.SOUTH:
newState[1] += self.moveOffset newY += self.moveOffset
elif state[2] == Rotations.WEST.value: elif state[2] == Rotations.WEST:
newState[0] -= self.moveOffset newX -= self.moveOffset
elif action == Movement.ROTATE_L: elif action == Movement.ROTATE_L:
newState[2] = Rotations((state[2] + 1) % 4) newRotation = Rotations((state[2].value - 1) % 4)
elif action == Movement.ROTATE_R: 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 return newState

View File

@ -1,3 +1,4 @@
from random import Random
from time import sleep from time import sleep
import pygame import pygame
@ -90,5 +91,8 @@ class EventManager:
if keys[pygame.K_d]: if keys[pygame.K_d]:
self.player.move(Movement.ROTATE_R) 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))])

View File

@ -5,7 +5,7 @@ from os import path
from src.AI.AutomaticMovement import AutomaticMovement from src.AI.AutomaticMovement import AutomaticMovement
from src.game.EventManager import EventManager 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.game.Map import Map
from src.entities.Player import Player from src.entities.Player import Player
@ -51,10 +51,17 @@ class Game:
mapFile = Path(str(filesPath) + "/data/mapdata/") mapFile = Path(str(filesPath) + "/data/mapdata/")
self.map = Map(path.join(mapFile, 'map.txt'), self.screen) self.map = Map(path.join(mapFile, 'map.txt'), self.screen)
self.player = Player((6, 2), self.map.tileSize) 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.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() self.mainLoop()
@ -64,5 +71,6 @@ class Game:
self.ingameTimer.updateTime(self.pgTimer.tick()) self.ingameTimer.updateTime(self.pgTimer.tick())
self.spritesList.update() self.spritesList.update()
self.eventManager.handleEvents() self.eventManager.handleEvents()
self.movement.updatePlayerCoords()
self.spritesList.draw(self.screen.pygameScreen) self.spritesList.draw(self.screen.pygameScreen)
pygame.display.flip() pygame.display.flip()

View File

@ -19,6 +19,8 @@ class Map:
self.terrainTilesList = [] self.terrainTilesList = []
self.collidables = pygame.sprite.Group() self.collidables = pygame.sprite.Group()
self.entities = []
with open(filename, 'rt') as f: with open(filename, 'rt') as f:
for line in f: for line in f:
self.terrain.append(line) self.terrain.append(line)
@ -101,27 +103,32 @@ class Map:
def getEntityOnCoord(self, coord): def getEntityOnCoord(self, coord):
result = None result = None
for entity in self.collidables: for entity in self.entities:
if entity.rect.x == coord[0] and entity.rect.y == coord[1]: if entity.rect.x == coord[0] and entity.rect.y == coord[1]:
result = entity result = entity
return result return result
def getTileOnCoord(self, coord): def getTileOnCoord(self, coord):
result = None result = None
for entity in self.: for entity in self.terrainTilesList:
if entity.rect.x == coord[0] and entity.rect.y == coord[1]: if entity.rect.x == coord[0] and entity.rect.y == coord[1]:
result = entity result = entity
return result 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.screen.draw(entity, Locations.MAP, 0, 0)
self.collidables.add(entity) self.collidables.add(entity)
if not DONTADD:
self.entities.append(entity)
def removeSpriteFromMap(self, entity): def removeSpriteFromMap(self, entity):
if self.collidables.has(entity): if self.collidables.has(entity):
self.collidables.remove(entity) self.collidables.remove(entity)
self.screen.removeSprite(entity) self.screen.removeSprite(entity)
self.entities.remove(entity)
# add object to map.collidables list to be collidable # add object to map.collidables list to be collidable
def collision(self, x, y): def collision(self, x, y):
for b in self.collidables: for b in self.collidables: