1801d2b9fb
UD/AI + Client boots up.
530 lines
20 KiB
Python
530 lines
20 KiB
Python
from panda3d.core import *
|
|
from toontown.toonbase.ToonBaseGlobal import *
|
|
from direct.gui.DirectGui import *
|
|
from panda3d.core import *
|
|
from direct.gui.DirectScrolledList import *
|
|
from direct.distributed.ClockDelta import *
|
|
from toontown.toontowngui import TTDialog
|
|
import math
|
|
from direct.task.Task import Task
|
|
from toontown.toonbase import ToontownGlobals
|
|
from direct.distributed import DistributedObject
|
|
from direct.directnotify import DirectNotifyGlobal
|
|
from direct.fsm import ClassicFSM
|
|
from direct.fsm import State
|
|
from toontown.toon import Toon
|
|
from direct.showbase import RandomNumGen
|
|
from toontown.toonbase import TTLocalizer
|
|
import random
|
|
import random
|
|
import pickle
|
|
from direct.showbase import PythonUtil
|
|
from . import GameSprite
|
|
from math import pi
|
|
from . import GardenProgressMeter
|
|
|
|
class GardenDropGame(DirectObject.DirectObject):
|
|
|
|
def __init__(self):
|
|
self.acceptErrorDialog = None
|
|
self.doneEvent = 'game Done'
|
|
self.sprites = []
|
|
self.load()
|
|
thing = self.model.find('**/item_board')
|
|
self.block = self.model1.find('**/minnieCircle')
|
|
self.colorRed = (1, 0, 0, 1)
|
|
self.colorBlue = (0, 0, 1, 1)
|
|
self.colorGreen = (0, 1, 0, 1)
|
|
self.colorGhostRed = (1, 0, 0, 0.5)
|
|
self.colorGhostBlue = (0, 0, 1, 0.5)
|
|
self.colorGhostGreen = (0, 1, 0, 0.5)
|
|
self.colorWhite = (1, 1, 1, 1)
|
|
self.colorBlack = (0, 0, 0, 1.0)
|
|
self.colorShadow = (0, 0, 0, 0.5)
|
|
self.lastTime = None
|
|
self.running = 0
|
|
self.massCount = 0
|
|
self.foundCount = 0
|
|
self.maxX = 0.47
|
|
self.minX = -0.47
|
|
self.maxZ = 0.65
|
|
self.minZ = -0.1
|
|
self.newBallX = 0.0
|
|
self.newBallZ = 0.6
|
|
self.rangeX = self.maxX - self.minX
|
|
self.rangeZ = self.maxZ - self.minZ
|
|
size = 0.085
|
|
sizeZ = size * 0.8
|
|
gX = int(self.rangeX / size)
|
|
gZ = int(self.rangeZ / sizeZ)
|
|
self.maxX = self.minX + gX * size
|
|
self.maxZ = self.minZ + gZ * sizeZ
|
|
self.controlOffsetX = 0.0
|
|
self.controlOffsetZ = 0.0
|
|
self.queExtent = 3
|
|
print('Grid Dimensions X%s Z%s' % (gX, gZ))
|
|
self.grid = []
|
|
self.gridDimX = gX
|
|
self.gridDimZ = gZ
|
|
self.gridBrick = False
|
|
base.gardenGame = self
|
|
for countX in range(self.gridDimX):
|
|
newRow = []
|
|
for countZ in range(self.gridDimZ):
|
|
offset = 0
|
|
if countZ % 2 == 0:
|
|
offset = size / 2
|
|
newRow.append([None, countX * size + self.minX + offset, countZ * sizeZ + self.minZ])
|
|
|
|
self.grid.append(newRow)
|
|
|
|
self.controlSprite = None
|
|
self.cogSprite = self.addUnSprite(self.block, posX=0.25, posZ=0.5)
|
|
self.cogSprite.setColor(self.colorShadow)
|
|
for ball in range(0, 3):
|
|
place = random.random() * self.rangeX
|
|
newSprite = self.addSprite(self.block, size=0.5, posX=self.minX + place, posZ=0.0, found=1)
|
|
self.stickInGrid(newSprite, 1)
|
|
|
|
self.queBall = self.addSprite(self.block, posX=0.25, posZ=0.5, found=0)
|
|
self.queBall.setColor(self.colorWhite)
|
|
self.queBall.isQue = 1
|
|
self.matchList = []
|
|
self.newBallTime = 1.0
|
|
self.newBallCountUp = 0.0
|
|
self.cogX = 0
|
|
self.cogZ = 0
|
|
self.__run()
|
|
return
|
|
|
|
def findGrid(self, x, z, force = 0):
|
|
currentClosest = None
|
|
currentDist = 10000000
|
|
for countX in range(self.gridDimX):
|
|
for countZ in range(self.gridDimZ):
|
|
testDist = self.testPointDistanceSquare(x, z, self.grid[countX][countZ][1], self.grid[countX][countZ][2])
|
|
if self.grid[countX][countZ][0] == None and testDist < currentDist and (force or self.hasNeighbor(countX, countZ)):
|
|
currentClosest = self.grid[countX][countZ]
|
|
self.closestX = countX
|
|
self.closestZ = countZ
|
|
currentDist = testDist
|
|
|
|
return currentClosest
|
|
|
|
def hasNeighbor(self, cellX, cellZ):
|
|
gotNeighbor = 0
|
|
if cellZ % 2 == 0:
|
|
if self.testGridfull(self.getValidGrid(cellX - 1, cellZ)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX + 1, cellZ)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX, cellZ + 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX + 1, cellZ + 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX, cellZ - 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX + 1, cellZ - 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX - 1, cellZ)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX + 1, cellZ)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX, cellZ + 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX - 1, cellZ + 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX, cellZ - 1)):
|
|
gotNeighbor = 1
|
|
elif self.testGridfull(self.getValidGrid(cellX - 1, cellZ - 1)):
|
|
gotNeighbor = 1
|
|
return gotNeighbor
|
|
|
|
def clearMatchList(self):
|
|
for entry in self.matchList:
|
|
gridEntry = self.grid[entry[0]][entry[1]]
|
|
sprite = gridEntry[0]
|
|
gridEntry[0] = None
|
|
sprite.markedForDeath = 1
|
|
|
|
return
|
|
|
|
def createMatchList(self, x, z):
|
|
self.matchList = []
|
|
self.fillMatchList(x, z)
|
|
|
|
def fillMatchList(self, cellX, cellZ):
|
|
if (cellX, cellZ) in self.matchList:
|
|
return
|
|
self.matchList.append((cellX, cellZ))
|
|
colorType = self.grid[cellX][cellZ][0].colorType
|
|
if cellZ % 2 == 0:
|
|
if self.getColorType(cellX - 1, cellZ) == colorType:
|
|
self.fillMatchList(cellX - 1, cellZ)
|
|
if self.getColorType(cellX + 1, cellZ) == colorType:
|
|
self.fillMatchList(cellX + 1, cellZ)
|
|
if self.getColorType(cellX, cellZ + 1) == colorType:
|
|
self.fillMatchList(cellX, cellZ + 1)
|
|
if self.getColorType(cellX + 1, cellZ + 1) == colorType:
|
|
self.fillMatchList(cellX + 1, cellZ + 1)
|
|
if self.getColorType(cellX, cellZ - 1) == colorType:
|
|
self.fillMatchList(cellX, cellZ - 1)
|
|
if self.getColorType(cellX + 1, cellZ - 1) == colorType:
|
|
self.fillMatchList(cellX + 1, cellZ - 1)
|
|
else:
|
|
if self.getColorType(cellX - 1, cellZ) == colorType:
|
|
self.fillMatchList(cellX - 1, cellZ)
|
|
if self.getColorType(cellX + 1, cellZ) == colorType:
|
|
self.fillMatchList(cellX + 1, cellZ)
|
|
if self.getColorType(cellX, cellZ + 1) == colorType:
|
|
self.fillMatchList(cellX, cellZ + 1)
|
|
if self.getColorType(cellX - 1, cellZ + 1) == colorType:
|
|
self.fillMatchList(cellX - 1, cellZ + 1)
|
|
if self.getColorType(cellX, cellZ - 1) == colorType:
|
|
self.fillMatchList(cellX, cellZ - 1)
|
|
if self.getColorType(cellX - 1, cellZ - 1) == colorType:
|
|
self.fillMatchList(cellX - 1, cellZ - 1)
|
|
|
|
def testGridfull(self, cell):
|
|
if not cell:
|
|
return 0
|
|
elif cell[0] != None:
|
|
return 1
|
|
else:
|
|
return 0
|
|
return
|
|
|
|
def getValidGrid(self, x, z):
|
|
if x < 0 or x >= self.gridDimX:
|
|
return None
|
|
elif z < 0 or z >= self.gridDimZ:
|
|
return None
|
|
else:
|
|
return self.grid[x][z]
|
|
return None
|
|
|
|
def getColorType(self, x, z):
|
|
if x < 0 or x >= self.gridDimX:
|
|
return -1
|
|
elif z < 0 or z >= self.gridDimZ:
|
|
return -1
|
|
elif self.grid[x][z][0] == None:
|
|
return -1
|
|
else:
|
|
return self.grid[x][z][0].colorType
|
|
return
|
|
|
|
def findGridCog(self):
|
|
self.cogX = 0
|
|
self.cogZ = 0
|
|
self.massCount = 0
|
|
for row in self.grid:
|
|
for cell in row:
|
|
if cell[0] != None:
|
|
self.cogX += cell[1]
|
|
self.cogZ += cell[2]
|
|
self.massCount += 1
|
|
|
|
if self.massCount > 0:
|
|
self.cogX = self.cogX / self.massCount
|
|
self.cogZ = self.cogZ / self.massCount
|
|
self.cogSprite.setX(self.cogX)
|
|
self.cogSprite.setZ(self.cogZ)
|
|
else:
|
|
self.doOnClearGrid()
|
|
return
|
|
|
|
def doOnClearGrid(self):
|
|
secondSprite = self.addSprite(self.block, posX=self.newBallX, posZ=0.0, found=1)
|
|
secondSprite.addForce(0, 1.55 * pi)
|
|
self.stickInGrid(secondSprite, 1)
|
|
|
|
def findGrid2(self, x, z):
|
|
rangeX = self.maxX - self.minX
|
|
rangeZ = self.maxZ - self.minZ
|
|
framedX = x - self.minX
|
|
framedZ = z - self.minZ
|
|
tileDimX = rangeX / self.gridDimX
|
|
tileDimZ = rangeZ / self.gridDimZ
|
|
tileX = int(framedX / tileDimX)
|
|
tileZ = int(framedZ / tileDimZ)
|
|
print('find Grid tileX%s tileZ%s' % (tileX, tileZ))
|
|
return (tileX, tileZ)
|
|
|
|
def findPos(self, x, z):
|
|
rangeX = self.maxX - self.minX
|
|
rangeZ = self.maxZ - self.minZ
|
|
tileDimX = rangeX / self.gridDimX
|
|
tileDimZ = rangeZ / self.gridDimZ
|
|
posX = tileDimX * x + self.minX
|
|
posZ = tileDimZ * z + self.minZ
|
|
print('find Pos X%s Z%s' % (posX, posZ))
|
|
return (posX, posZ)
|
|
|
|
def placeIntoGrid(self, sprite, x, z):
|
|
if self.grid[x][z][0] == None:
|
|
self.grid[x][z][0] = sprite
|
|
sprite.setActive(0)
|
|
newX, newZ = self.findPos(x, z)
|
|
sprite.setX(newX)
|
|
sprite.setZ(newZ)
|
|
print('Setting Final Pos X%s Z%s' % (newX, newZ))
|
|
else:
|
|
self.placeIntoGrid(sprite, x + 1, z - 1)
|
|
return
|
|
|
|
def stickInGrid(self, sprite, force = 0):
|
|
if sprite.isActive and not sprite.isQue:
|
|
gridCell = self.findGrid(sprite.getX(), sprite.getZ(), force)
|
|
if gridCell:
|
|
gridCell[0] = sprite
|
|
sprite.setActive(0)
|
|
sprite.setX(gridCell[1])
|
|
sprite.setZ(gridCell[2])
|
|
self.createMatchList(self.closestX, self.closestZ)
|
|
if len(self.matchList) >= 3:
|
|
self.clearMatchList()
|
|
self.findGridCog()
|
|
|
|
def stickInGrid2(self, sprite):
|
|
if sprite.isActive and not sprite.isQue:
|
|
tileX, tileZ = self.findGrid(sprite.getX(), sprite.getZ())
|
|
self.placeIntoGrid(sprite, tileX, tileZ)
|
|
sprite.isActive = 0
|
|
|
|
def load(self):
|
|
model = loader.loadModel('phase_5.5/models/gui/package_delivery_panel')
|
|
model1 = loader.loadModel('phase_3.5/models/gui/matching_game_gui')
|
|
self.model = model
|
|
self.model1 = model1
|
|
background = model.find('**/bg')
|
|
itemBoard = model.find('**/item_board')
|
|
self.frame = DirectFrame(scale=1.1, relief=DGG.FLAT, frameSize=(-0.5,
|
|
0.5,
|
|
-0.45,
|
|
-0.05), frameColor=(0.737, 0.573, 0.345, 1.0))
|
|
self.background = DirectFrame(self.frame, image=background, image_scale=0.05, relief=None, pos=(0, 1, 0))
|
|
self.itemBoard = DirectFrame(parent=self.frame, image=itemBoard, image_scale=0.05, image_color=(0.922, 0.922, 0.753, 1), relief=None, pos=(0, 1, 0))
|
|
gui2 = loader.loadModel('phase_3/models/gui/quit_button')
|
|
self.quitButton = DirectButton(parent=self.frame, relief=None, image=(gui2.find('**/QuitBtn_UP'), gui2.find('**/QuitBtn_DN'), gui2.find('**/QuitBtn_RLVR')), pos=(0.5, 1.0, -0.42), scale=0.9, text='Exit Mini Game', text_font=ToontownGlobals.getSignFont(), text0_fg=(1, 1, 1, 1), text1_fg=(1, 1, 1, 1), text2_fg=(1, 1, 1, 1), text_scale=0.045, text_pos=(0, -0.01), command=self.__handleExit)
|
|
return
|
|
|
|
def unload(self):
|
|
self.frame.destroy()
|
|
del self.frame
|
|
if self.acceptErrorDialog:
|
|
self.acceptErrorDialog.cleanup()
|
|
self.acceptErrorDialog = None
|
|
taskMgr.remove('gameTask')
|
|
self.ignoreAll()
|
|
return
|
|
|
|
def show(self):
|
|
self.frame.show()
|
|
|
|
def hide(self):
|
|
self.frame.hide()
|
|
|
|
def __handleExit(self):
|
|
self.__acceptExit()
|
|
|
|
def __acceptExit(self, buttonValue = None):
|
|
if hasattr(self, 'frame'):
|
|
self.hide()
|
|
self.unload()
|
|
messenger.send(self.doneEvent)
|
|
|
|
def addSprite(self, image, size = 0.5, posX = 0, posZ = 0, found = 0):
|
|
nodeObj = DirectLabel(parent=self.frame, relief=None, image=image, pos=(posX, 0.0, posZ), scale=size, image_color=(1.0, 1.0, 1.0, 1))
|
|
colorChoice = random.choice(list(range(0, 3)))
|
|
newSprite = GameSprite.GameSprite(nodeObj, colorChoice, found)
|
|
self.sprites.append(newSprite)
|
|
if found:
|
|
self.foundCount += 1
|
|
return newSprite
|
|
|
|
def addUnSprite(self, image, size = 0.5, posX = 0, posZ = 0):
|
|
nodeObj = DirectLabel(parent=self.frame, relief=None, image=image, pos=(posX, 0.0, posZ), scale=size, image_color=(1.0, 1.0, 1.0, 1))
|
|
newSprite = GameSprite.GameSprite(nodeObj)
|
|
newSprite = GameSprite.GameSprite(nodeObj)
|
|
return newSprite
|
|
|
|
def __run(self, cont = 1):
|
|
if self.lastTime == None:
|
|
self.lastTime = globalClock.getRealTime()
|
|
timeDelta = globalClock.getRealTime() - self.lastTime
|
|
self.lastTime = globalClock.getRealTime()
|
|
self.newBallCountUp += timeDelta
|
|
if base.mouseWatcherNode.hasMouse():
|
|
x = base.mouseWatcherNode.getMouseX()
|
|
y = base.mouseWatcherNode.getMouseY()
|
|
self.queBall.setX(x)
|
|
self.queBall.setZ(y)
|
|
for sprite in self.sprites:
|
|
sprite.run(timeDelta)
|
|
if sprite.getX() > self.maxX:
|
|
sprite.setX(self.maxX)
|
|
sprite.velX = -sprite.velX
|
|
if sprite.getX() < self.minX:
|
|
sprite.setX(self.minX)
|
|
sprite.velX = -sprite.velX
|
|
if sprite.getZ() > self.maxZ:
|
|
sprite.setZ(self.maxZ)
|
|
sprite.velZ = -sprite.velZ
|
|
if sprite.getZ() < self.minZ:
|
|
self.stickInGrid(sprite, 1)
|
|
if sprite.isActive:
|
|
sprite.addForce(timeDelta * 0.9, pi * 1.5)
|
|
|
|
self.queBall.velX = (self.queBall.getX() - self.queBall.prevX) / timeDelta
|
|
self.queBall.velZ = (self.queBall.getZ() - self.queBall.prevZ) / timeDelta
|
|
self.__colTest()
|
|
for sprite in self.sprites:
|
|
if sprite.markedForDeath:
|
|
if sprite.foundation:
|
|
self.foundCount -= 1
|
|
self.sprites.remove(sprite)
|
|
sprite.delete()
|
|
|
|
if self.controlSprite == None:
|
|
self.addControlSprite(self.newBallX, self.newBallZ)
|
|
self.newBallCountUp = 0.0
|
|
if self.newBallCountUp >= self.newBallTime:
|
|
self.addControlSprite(self.newBallX, self.newBallZ)
|
|
self.newBallCountUp = 0.0
|
|
if not self.controlSprite.isActive:
|
|
self.controlSprite = None
|
|
if self.foundCount <= 0:
|
|
self.__handleWin()
|
|
if cont and not self.running:
|
|
taskMgr.add(self.__run, 'gameTask')
|
|
self.running = 1
|
|
return Task.cont
|
|
|
|
def __handleWin(self):
|
|
GardenProgressMeter.GardenProgressMeter()
|
|
self.__handleExit()
|
|
|
|
def addControlSprite(self, x = 0.0, z = 0.0):
|
|
newSprite = self.addSprite(self.block, posX=x, posZ=z)
|
|
self.controlSprite = newSprite
|
|
|
|
def __colTest(self):
|
|
if not hasattr(self, 'tick'):
|
|
self.tick = 0
|
|
self.tick += 1
|
|
if self.tick > 5:
|
|
self.tick = 0
|
|
sizeSprites = len(self.sprites)
|
|
for movingSpriteIndex in range(len(self.sprites)):
|
|
for testSpriteIndex in range(movingSpriteIndex, len(self.sprites)):
|
|
movingSprite = self.getSprite(movingSpriteIndex)
|
|
testSprite = self.getSprite(testSpriteIndex)
|
|
if testSprite and movingSprite:
|
|
if movingSpriteIndex != testSpriteIndex and (movingSprite.isActive or testSprite.isActive):
|
|
if movingSprite.isQue or testSprite.isQue:
|
|
if self.testDistance(movingSprite.nodeObj, testSprite.nodeObj) < self.queExtent * (movingSprite.size + testSprite.size):
|
|
self.push(movingSprite, testSprite)
|
|
elif self.testDistance(movingSprite.nodeObj, testSprite.nodeObj) < movingSprite.size + testSprite.size:
|
|
if not (movingSprite.isActive and testSprite.isActive):
|
|
self.__collide(movingSprite, testSprite)
|
|
if self.tick == 5:
|
|
pass
|
|
|
|
def getSprite(self, spriteIndex):
|
|
if spriteIndex >= len(self.sprites) or self.sprites[spriteIndex].markedForDeath:
|
|
return None
|
|
else:
|
|
return self.sprites[spriteIndex]
|
|
return None
|
|
|
|
def testDistance(self, nodeA, nodeB):
|
|
distX = nodeA.getX() - nodeB.getX()
|
|
distZ = nodeA.getZ() - nodeB.getZ()
|
|
distC = distX * distX + distZ * distZ
|
|
dist = math.sqrt(distC)
|
|
return dist
|
|
|
|
def testPointDistance(self, x1, z1, x2, z2):
|
|
distX = x1 - x2
|
|
distZ = z1 - z2
|
|
distC = distX * distX + distZ * distZ
|
|
dist = math.sqrt(distC)
|
|
if dist == 0:
|
|
dist = 1e-10
|
|
return dist
|
|
|
|
def testPointDistanceSquare(self, x1, z1, x2, z2):
|
|
distX = x1 - x2
|
|
distZ = z1 - z2
|
|
distC = distX * distX + distZ * distZ
|
|
if distC == 0:
|
|
distC = 1e-10
|
|
return distC
|
|
|
|
def angleTwoSprites(self, sprite1, sprite2):
|
|
x1 = sprite1.getX()
|
|
z1 = sprite1.getZ()
|
|
x2 = sprite2.getX()
|
|
z2 = sprite2.getZ()
|
|
x = x2 - x1
|
|
z = z2 - z1
|
|
angle = math.atan2(-x, z)
|
|
return angle + pi * 0.5
|
|
|
|
def angleTwoPoints(self, x1, z1, x2, z2):
|
|
x = x2 - x1
|
|
z = z2 - z1
|
|
angle = math.atan2(-x, z)
|
|
return angle + pi * 0.5
|
|
|
|
def __collide(self, move, test):
|
|
queHit = 0
|
|
if move.isQue:
|
|
que = move
|
|
hit = test
|
|
queHit = 1
|
|
elif test.isQue:
|
|
que = test
|
|
hit = move
|
|
queHit = 1
|
|
else:
|
|
test.velX = 0
|
|
test.velZ = 0
|
|
move.velX = 0
|
|
move.velZ = 0
|
|
test.collide()
|
|
move.collide()
|
|
self.stickInGrid(move)
|
|
self.stickInGrid(test)
|
|
if queHit:
|
|
forceM = 0.1
|
|
distX = que.getX() - hit.getX()
|
|
distZ = que.getZ() - hit.getZ()
|
|
|
|
def push(self, move, test):
|
|
queHit = 0
|
|
if move.isQue:
|
|
que = move
|
|
hit = test
|
|
queHit = 1
|
|
elif test.isQue:
|
|
que = test
|
|
hit = move
|
|
queHit = 1
|
|
if queHit:
|
|
forceM = 0.1
|
|
dist = self.testDistance(move.nodeObj, test.nodeObj)
|
|
if abs(dist) < self.queExtent * que.size and abs(dist) > 0:
|
|
scaleSize = self.queExtent * que.size * 0.5
|
|
distFromPara = abs(abs(dist) - scaleSize)
|
|
force = (scaleSize - distFromPara) / scaleSize * (dist / abs(dist))
|
|
angle = self.angleTwoSprites(que, hit)
|
|
if angle < 0:
|
|
angle = angle + 2 * pi
|
|
if angle > pi * 2.0:
|
|
angle = angle - 2 * pi
|
|
newAngle = pi * 1.0
|
|
if angle > pi * 1.5 or angle < pi * 0.5:
|
|
newAngle = pi * 0.0
|
|
hit.addForce(forceM * force, newAngle)
|