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:
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

View File

@ -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))])

View File

@ -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()

View File

@ -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: