コード例 #1
0
class Box(GameObject):
	disableGracePeriod = 20
	
	def __init__(self, world, parent, color, pos, dir, size, density, unglueThreshold=None, shatterLimit=None, shatterThreshold=None):
		GameObject.__init__(self, world)

		if unglueThreshold == None: unglueThreshold = 20
		if shatterLimit == None: shatterLimit = 0
		if shatterThreshold == None: shatterThreshold = 30

		self.size = size
		self.density = density
		self.dir = dir
		self.parent = parent
		self.color = color = makeVec4Color(color)
		
		self.node = parent.attachNewNode("")
		self.node.setPos(*pos)
		self.node.setColorScale(color)
		self.node.setScale(*size)
		self.node.lookAt(self.node, *dir)

		self.model = loader.loadModel("models/box.egg")
		self.model.reparentTo(self.node)
		self.model.setScale(2.0)
		self.model.setPos(-1.0, -1.0, -1.0)

		self.applyTexture()

		self.mass = OdeMass()
		self.mass.setBox(density, Vec3(*size) * 2)
		self.body = OdeBody(world.world)
		self.body.setMass(self.mass)
		self.body.setPosition(self.node.getPos())
		self.body.setQuaternion(self.node.getQuat())
		self.body.setData(self)
		self.geom = OdeBoxGeom(world.space, Vec3(*size) * 2.0)
		self.geom.setBody(self.body)
		world.space.setSurfaceType(self.geom, world.surfaces["box"])

		# Adjust collision bitmasks.
		self.geom.setCategoryBits(GameObject.bitmaskBox)
		self.geom.setCollideBits(GameObject.bitmaskAll & ~GameObject.bitmaskTileGlued)

		# Tile, cement and shatter variables.
		self.tiles = []
		self.cements = []
		self.disableCount = 0
		self.unglueThreshold = unglueThreshold
		self.shatterLimit = shatterLimit
		self.shatterThreshold = shatterThreshold

	def applyTexture(self):
		self.texture = loader.loadTexture("media/brick_wall.tga")
		self.texture.setWrapU(Texture.WMRepeat)
		self.texture.setWrapV(Texture.WMRepeat)
		self.model.setTexture(self.texture, 1)
		self.model.setTexScale(TextureStage.getDefault(), max(self.size[0], self.size[1]), self.size[2])

	def addTile(self, tile):
		if tile not in self.tiles:
			self.tiles.append(tile)

	def removeTile(self, tile):
		if tile in self.tiles:
			self.tiles.remove(tile)

	def addCement(self, cement):
		if cement not in self.cements:
			self.cements.append(cement)

	def removeCement(self, cement):
		if cement in self.cements:
			self.cements.remove(cement)

	def destroy(self):
		for tile in self.tiles:
			tile.unglue()
		for cement in self.cements:
			cement.destroy()
		GameObject.destroy(self)

	def makeTiles(self, xNeg=False, xPos=False, yNeg=False, yPos=False, zNeg=False, zPos=False, thickness=0.1, unglueThreshold=None, shatterLimit=None, shatterThreshold=None):
		if xNeg: Tile(self, self.color, (-1,0,0), thickness, self.density, unglueThreshold, shatterLimit, shatterThreshold)
		if xPos: Tile(self, self.color, ( 1,0,0), thickness, self.density, unglueThreshold, shatterLimit, shatterThreshold)
		if yNeg: Tile(self, self.color, (0,-1,0), thickness, self.density, unglueThreshold, shatterLimit, shatterThreshold)
		if yPos: Tile(self, self.color, (0, 1,0), thickness, self.density, unglueThreshold, shatterLimit, shatterThreshold)
		if zNeg: Tile(self, self.color, (0,0,-1), thickness, self.density, unglueThreshold, shatterLimit, shatterThreshold)
		if zPos: Tile(self, self.color, (0,0, 1), thickness, self.density, unglueThreshold, shatterLimit, shatterThreshold)

	def onCollision(self, otherBody, entry):
		if otherBody.isEmpty():
			return
		self.disableCount = 0
		speed = otherBody.getData().body.getLinearVel()
		#if otherBody.getData().__class__ == Bullet: print speed.length(), self.shatterThreshold, self.shatterLimit #######
		if self.active and speed.length() >= self.shatterThreshold and self.shatterLimit > 0:
			adj = otherBody.getData().body.getMass().getMagnitude() / self.body.getMass().getMagnitude()
			speedMag = speed.length() * adj
			speedBase = ((speed * adj) + (self.body.getLinearVel() * 2) / 3)
			self.shatter(speedMag, speedBase)

	def shatter(self, speedMag, speedBase):
		#print 'box shatter' #########
		self.destroy()
		taskMgr.add(self.spawnTask, "box-spawn", extraArgs=[speedMag, speedBase])

		# Graphic (camera shake) and sound effects
		self.world.game.cameraHandler.shake((0,0,2), 0.1)
		sound = base.loader.loadSfx("media/shatter.wav")
		sound.setVolume(1.5)
		sound.play()

	def spawnTask(self, speedMag, speedBase):
		pos = self.node.getPos()
		size = Vec3(self.size) / 2
		w = 1
		for i in [-w, w]:
			for j in [-w, w]:
				for k in [-w, w]:
					box = Box(self.world, self.parent, self.color,
						(pos[0] + (i * size[0]), pos[1] + (j * size[1]), pos[2] + (k * size[2])),
						self.dir, size, self.density, self.unglueThreshold, self.shatterLimit - 1, self.shatterThreshold * 1)
					speed = (speedBase * (1.5 + random())) + (Vec3(i,j,k) * speedMag * (1 + random()))
					speed = speed / 2.0
					box.body.setLinearVel(speed)
					box.body.setAngularVel(speedMag * random(), speedMag * random(), speedMag * random())
					taskMgr.add(box.disableOnStopTask, "box-disableOnStop")

	def disableOnStopTask(self, task):
		if self.body.getLinearVel().length() > 0.1 or self.body.getAngularVel().length() > 0.1:
			self.disableCount = 0
			return task.cont
		elif self.disableCount < Box.disableGracePeriod:
			self.disableCount += 1
			return task.cont
		else:
			self.visibleAfterDestroy = True
			if DEBUG: self.node.setColorScale(1.0, 2.0, 1.0, 0.5)
			self.destroy()
			return task.done