DistributedCartesianGridAI.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from pandac.PandaModules import *
  2. from direct.task import Task
  3. import DistributedNodeAI
  4. import CartesianGridBase
  5. class DistributedCartesianGridAI(DistributedNodeAI.DistributedNodeAI,
  6. CartesianGridBase.CartesianGridBase):
  7. notify = directNotify.newCategory("DistributedCartesianGridAI")
  8. RuleSeparator = ":"
  9. def __init__(self, air, startingZone, gridSize, gridRadius, style="Cartesian"):
  10. DistributedNodeAI.DistributedNodeAI.__init__(self, air)
  11. self.style = style
  12. self.startingZone = startingZone
  13. self.gridSize = gridSize
  14. self.gridRadius = gridRadius
  15. # Keep track of all AI objects added to the grid
  16. self.gridObjects = {}
  17. self.updateTaskStarted = 0
  18. def delete(self):
  19. DistributedNodeAI.DistributedNodeAI.delete(self)
  20. self.stopUpdateGridTask()
  21. def isGridParent(self):
  22. # If this distributed object is a DistributedGrid return 1. 0 by default
  23. return 1
  24. def getParentingRules(self):
  25. self.notify.debug("calling getter")
  26. rule = ("%i%s%i%s%i" % (self.startingZone, self.RuleSeparator,
  27. self.gridSize, self.RuleSeparator,
  28. self.gridRadius))
  29. return [self.style, rule]
  30. # Reparent and setLocation on av to DistributedOceanGrid
  31. def addObjectToGrid(self, av, useZoneId=-1):
  32. self.notify.debug("setting parent to grid %s" % self)
  33. avId = av.doId
  34. # Create a grid parent
  35. #gridParent = self.attachNewNode("gridParent-%s" % avId)
  36. #self.gridParents[avId] = gridParent
  37. self.gridObjects[avId] = av
  38. # Put the avatar on the grid
  39. self.handleAvatarZoneChange(av, useZoneId)
  40. if not self.updateTaskStarted:
  41. self.startUpdateGridTask()
  42. def removeObjectFromGrid(self, av):
  43. # TODO: WHAT LOCATION SHOULD WE SET THIS TO?
  44. #av.wrtReparentTo(self.parentNP)
  45. #av.setLocation(self.air.districtId, 1000)
  46. # Remove grid parent for this av
  47. avId = av.doId
  48. if self.gridObjects.has_key(avId):
  49. del self.gridObjects[avId]
  50. # Stop task if there are no more av's being managed
  51. if len(self.gridObjects) == 0:
  52. self.stopUpdateGridTask()
  53. #####################################################################
  54. # updateGridTask
  55. # This task is similar to the processVisibility task for the local client.
  56. # A couple differences:
  57. # - we are not doing setInterest on the AI (that is a local client specific call).
  58. # - we assume that the moving objects on the grid are parented to a gridParent,
  59. # and are broadcasting their position relative to that gridParent. This
  60. # makes the task's math easy. Just check to see when our position goes
  61. # out of the current grid cell. When it does, call handleAvatarZoneChange
  62. def startUpdateGridTask(self):
  63. self.stopUpdateGridTask()
  64. self.updateTaskStarted = 1
  65. taskMgr.add(self.updateGridTask, self.taskName("updateGridTask"))
  66. def stopUpdateGridTask(self):
  67. taskMgr.remove(self.taskName("updateGridTask"))
  68. self.updateTaskStarted = 0
  69. def updateGridTask(self, task=None):
  70. # Run through all grid objects and update their parents if needed
  71. for avId in self.gridObjects:
  72. av = self.gridObjects[avId]
  73. pos = av.getPos()
  74. if ((pos[0] < 0 or pos[1] < 0) or
  75. (pos[0] > self.cellWidth or pos[1] > self.cellWidth)):
  76. # we are out of the bounds of this current cell
  77. self.handleAvatarZoneChange(av)
  78. # Do this every second, not every frame
  79. if (task):
  80. task.delayTime = 1.0
  81. return Task.again
  82. def handleAvatarZoneChange(self, av, useZoneId=-1):
  83. # Calculate zone id
  84. # Get position of av relative to this grid
  85. if (useZoneId == -1):
  86. pos = av.getPos(self)
  87. zoneId = self.getZoneFromXYZ(pos)
  88. else:
  89. # zone already calculated, position of object might not
  90. # give the correct zone
  91. pos = None
  92. zoneId = useZoneId
  93. if not self.isValidZone(zoneId):
  94. self.notify.warning("%s handleAvatarZoneChange %s: not a valid zone (%s) for pos %s" %
  95. (self.doId, av.doId, zoneId, pos))
  96. return
  97. # Set the location on the server.
  98. # setLocation will update the gridParent
  99. av.b_setLocation(self.doId, zoneId)