158 lines
5.4 KiB
Python
158 lines
5.4 KiB
Python
from panda3d.core import VBase3
|
|
from direct.showbase.RandomNumGen import RandomNumGen
|
|
|
|
class MazeBase:
|
|
|
|
def __init__(self, model, mazeData, cellWidth, parent = None):
|
|
if parent is None:
|
|
parent = render
|
|
self.width = mazeData['width']
|
|
self.height = mazeData['height']
|
|
self.originTX = mazeData['originX']
|
|
self.originTY = mazeData['originY']
|
|
self.collisionTable = mazeData['collisionTable']
|
|
self._initialCellWidth = cellWidth
|
|
self.cellWidth = self._initialCellWidth
|
|
self.maze = model
|
|
self.maze.setPos(0, 0, 0)
|
|
self.maze.reparentTo(parent)
|
|
self.maze.stash()
|
|
return
|
|
|
|
def destroy(self):
|
|
self.maze.removeNode()
|
|
del self.maze
|
|
|
|
def onstage(self):
|
|
self.maze.unstash()
|
|
|
|
def offstage(self):
|
|
self.maze.stash()
|
|
|
|
def setScale(self, xy = 1, z = 1):
|
|
self.maze.setScale(VBase3(xy, xy, z))
|
|
self.cellWidth = self._initialCellWidth * xy
|
|
|
|
def isWalkable(self, tX, tY, rejectList = ()):
|
|
if tX <= 0 or tY <= 0 or tX >= self.width or tY >= self.height:
|
|
return 0
|
|
return not self.collisionTable[tY][tX] and not self.collisionTable[tY - 1][tX] and not self.collisionTable[tY][tX - 1] and not self.collisionTable[tY - 1][tX - 1] and (tX, tY) not in rejectList
|
|
|
|
def tile2world(self, TX, TY):
|
|
return [(TX - self.originTX) * self.cellWidth, (TY - self.originTY) * self.cellWidth]
|
|
|
|
def world2tile(self, x, y):
|
|
return [int(x / self.cellWidth + self.originTX), int(y / self.cellWidth + self.originTY)]
|
|
|
|
def world2tileClipped(self, x, y):
|
|
coords = [int(x / self.cellWidth + self.originTX), int(y / self.cellWidth + self.originTY)]
|
|
coords[0] = min(max(coords[0], 0), self.width - 1)
|
|
coords[1] = min(max(coords[1], 0), self.height - 1)
|
|
return coords
|
|
|
|
def doOrthoCollisions(self, oldPos, newPos):
|
|
offset = newPos - oldPos
|
|
WALL_OFFSET = 1.0
|
|
curX = oldPos[0]
|
|
curY = oldPos[1]
|
|
curTX, curTY = self.world2tile(curX, curY)
|
|
|
|
def calcFlushCoord(curTile, newTile, centerTile):
|
|
EPSILON = 0.01
|
|
if newTile > curTile:
|
|
return (newTile - centerTile) * self.cellWidth - EPSILON - WALL_OFFSET
|
|
else:
|
|
return (curTile - centerTile) * self.cellWidth + WALL_OFFSET
|
|
|
|
offsetX = offset[0]
|
|
offsetY = offset[1]
|
|
WALL_OFFSET_X = WALL_OFFSET
|
|
if offsetX < 0:
|
|
WALL_OFFSET_X = -WALL_OFFSET_X
|
|
WALL_OFFSET_Y = WALL_OFFSET
|
|
if offsetY < 0:
|
|
WALL_OFFSET_Y = -WALL_OFFSET_Y
|
|
newX = curX + offsetX + WALL_OFFSET_X
|
|
newY = curY
|
|
newTX, newTY = self.world2tile(newX, newY)
|
|
if newTX != curTX:
|
|
if self.collisionTable[newTY][newTX] == 1:
|
|
offset.setX(calcFlushCoord(curTX, newTX, self.originTX) - curX)
|
|
newX = curX
|
|
newY = curY + offsetY + WALL_OFFSET_Y
|
|
newTX, newTY = self.world2tile(newX, newY)
|
|
if newTY != curTY:
|
|
if self.collisionTable[newTY][newTX] == 1:
|
|
offset.setY(calcFlushCoord(curTY, newTY, self.originTY) - curY)
|
|
offsetX = offset[0]
|
|
offsetY = offset[1]
|
|
newX = curX + offsetX + WALL_OFFSET_X
|
|
newY = curY + offsetY + WALL_OFFSET_Y
|
|
newTX, newTY = self.world2tile(newX, newY)
|
|
if self.collisionTable[newTY][newTX] == 1:
|
|
cX = calcFlushCoord(curTX, newTX, self.originTX)
|
|
cY = calcFlushCoord(curTY, newTY, self.originTY)
|
|
if abs(cX - curX) < abs(cY - curY):
|
|
offset.setX(cX - curX)
|
|
else:
|
|
offset.setY(cY - curY)
|
|
return oldPos + offset
|
|
|
|
def createRandomSpotsList(self, numSpots, randomNumGen):
|
|
randomNumGen = RandomNumGen(randomNumGen)
|
|
width = self.width
|
|
height = self.height
|
|
halfWidth = int(width / 2)
|
|
halfHeight = int(height / 2)
|
|
quadrants = [(0,
|
|
0,
|
|
halfWidth - 1,
|
|
halfHeight - 1),
|
|
(halfWidth,
|
|
0,
|
|
width - 1,
|
|
halfHeight - 1),
|
|
(0,
|
|
halfHeight,
|
|
halfWidth - 1,
|
|
height - 1),
|
|
(halfWidth,
|
|
halfHeight,
|
|
width - 1,
|
|
height - 1)]
|
|
spotsTaken = []
|
|
|
|
def getEmptySpotInQuadrant(quadrant):
|
|
tX = -1
|
|
tY = -1
|
|
while tX < 0 or not self.isWalkable(tX, tY, spotsTaken):
|
|
tX = randomNumGen.randint(quadrant[0], quadrant[2])
|
|
tY = randomNumGen.randint(quadrant[1], quadrant[3])
|
|
|
|
spot = (tX, tY)
|
|
spotsTaken.append(spot)
|
|
return spot
|
|
|
|
def getSpotList(length):
|
|
randomNumGen.shuffle(quadrants)
|
|
l = []
|
|
remaining = length
|
|
for quadrant in quadrants:
|
|
for u in xrange(int(length / 4)):
|
|
l.append(getEmptySpotInQuadrant(quadrant))
|
|
|
|
remaining -= int(length / 4)
|
|
|
|
for u in xrange(remaining):
|
|
quadrant = quadrants[randomNumGen.randint(0, len(quadrants) - 1)]
|
|
l.append(getEmptySpotInQuadrant(quadrant))
|
|
|
|
return l
|
|
|
|
if type(numSpots) == tuple or type(numSpots) == list:
|
|
spots = []
|
|
for i in numSpots:
|
|
spots.append(getSpotList(i))
|
|
|
|
return spots
|
|
return getSpotList(numSpots)
|