Exemplo n.º 1
0
 def getMouseRay(self, collRay=False):
     ray = CollisionRay()
     ray.setFromLens(self.camNode, self.getMouse())
     if collRay:
         return ray
     else:
         return Ray(ray.getOrigin(), ray.getDirection())
Exemplo n.º 2
0
class MouseCollision:
    def __init__(self, game):

        self.game = game

        self.c_trav = CollisionTraverser()

        self.mouse_groundHandler = CollisionHandlerQueue()
        self.mouse_ground_ray = CollisionRay()
        self.mouse_ground_col = CollisionNode('mouseRay')

        self.mouse_ground_ray.setOrigin(0, 0, 0)
        self.mouse_ground_ray.setDirection(0, -1, 0)

        self.mouse_ground_col.addSolid(self.mouse_ground_ray)
        self.mouse_ground_col.setFromCollideMask(CollideMask.bit(0))
        self.mouse_ground_col.setIntoCollideMask(CollideMask.allOff())

        self.mouse_ground_col_np = self.game.camera.attachNewNode(
            self.mouse_ground_col)

        self.c_trav.addCollider(self.mouse_ground_col_np,
                                self.mouse_groundHandler)

        self.game.taskMgr.add(self.update, 'updateMouse')

    def update(self, task):

        if self.game.mouseWatcherNode.hasMouse():
            if self.game.ship.model:

                mouse_pos = self.game.mouseWatcherNode.getMouse()

                self.mouse_ground_ray.setFromLens(self.game.camNode,
                                                  mouse_pos.getX(),
                                                  mouse_pos.getY())

                near_point = render.getRelativePoint(
                    self.game.camera, self.mouse_ground_ray.getOrigin())
                near_vec = render.getRelativeVector(
                    self.game.camera, self.mouse_ground_ray.getDirection())

                self.game.ship.shipPoint.setPos(
                    self.PointAtY(self.game.ship.model.getY(), near_point,
                                  near_vec))

        return task.cont

    def PointAtY(self, y, point, vec):
        return point + vec * ((y - point.getY()) / vec.getY())
Exemplo n.º 3
0
class MouseCollision:
    def __init__(self, game):

        self.game = game

        self.c_trav = CollisionTraverser()

        self.mouse_groundHandler = CollisionHandlerQueue()
        self.mouse_ground_ray = CollisionRay()
        self.mouse_ground_col = CollisionNode('mouseRay')

        self.mouse_ground_ray.setOrigin(0, 0, 0)
        self.mouse_ground_ray.setDirection(0, -1, 0)

        self.mouse_ground_col.addSolid(self.mouse_ground_ray)
        self.mouse_ground_col.setFromCollideMask(CollideMask.bit(0))
        self.mouse_ground_col.setIntoCollideMask(CollideMask.allOff())

        self.mouse_ground_col_np = self.game.camera.attachNewNode(self.mouse_ground_col)

        self.c_trav.addCollider(self.mouse_ground_col_np, self.mouse_groundHandler)

        self.game.taskMgr.add(self.update, 'updateMouse')

    def update(self, task):

        if self.game.mouseWatcherNode.hasMouse():
            if self.game.ship.model:

                mouse_pos = self.game.mouseWatcherNode.getMouse()

                self.mouse_ground_ray.setFromLens(self.game.camNode, mouse_pos.getX(), mouse_pos.getY())

                near_point = render.getRelativePoint(self.game.camera, self.mouse_ground_ray.getOrigin())
                near_vec = render.getRelativeVector(self.game.camera, self.mouse_ground_ray.getDirection())

                self.game.ship.shipPoint.setPos(self.PointAtY(self.game.ship.model.getY(), near_point, near_vec))

        return task.cont

    def PointAtY(self, y, point, vec):
        return point + vec * ((y - point.getY()) / vec.getY())
Exemplo n.º 4
0
    def _get_collision(self, node, debug=False):
        mx = self.mouseWatcherNode.getMouseX()
        my = self.mouseWatcherNode.getMouseY()
        if debug:
            print "mouse:", (mx, my)

        # get the origin and direction of the ray extending from the
        # camera to the mouse pointer
        cm = np.array(self.cam.getNetTransform().getMat())
        cr = CollisionRay()
        cr.setFromLens(self.cam.node(), (mx, my))
        cp = np.hstack([cr.getOrigin(), 1])
        cd = np.hstack([cr.getDirection(), 0])
        cp = np.dot(cm.T, cp)[:3]
        cd = np.dot(cm.T, cd)[:3]
        if cd[2] > -1:
            cd[2] = -1
        if debug:
            print "direction:", cd
            print "origin:", cp

        # point on the plane, z-axis
        pz = node.getPos(self.render)[2]
        sz = node.getScale(self.render)[2] / 2.0
        p0 = np.array([0, 0, pz + sz])
        if debug:
            print "p0:", p0

        # this is the intersection equation that we want to solve,
        # where s is the point on the line that intersects
        #     e_z(cp + s*cd - p0) = 0
        s = (p0[2] - cp[2]) / cd[2]
        if debug:
            print "s:", s

        # transform the collision point from line coordinates to world
        # coordinates
        cv = cp + s * cd
        if debug:
            print "collision:", cv

        return cv
Exemplo n.º 5
0
    def _get_collision(self, node, debug=False):
        mx = self.mouseWatcherNode.getMouseX()
        my = self.mouseWatcherNode.getMouseY()
        if debug:
            print "mouse:", (mx, my)

        # get the origin and direction of the ray extending from the
        # camera to the mouse pointer
        cm = np.array(self.cam.getNetTransform().getMat())
        cr = CollisionRay()
        cr.setFromLens(self.cam.node(), (mx, my))
        cp = np.hstack([cr.getOrigin(), 1])
        cd = np.hstack([cr.getDirection(), 0])
        cp = np.dot(cm.T, cp)[:3]
        cd = np.dot(cm.T, cd)[:3]
        if cd[2] > -1:
            cd[2] = -1
        if debug:
            print "direction:", cd
            print "origin:", cp

        # point on the plane, z-axis
        pz = node.getPos(self.render)[2]
        sz = node.getScale(self.render)[2] / 2.0
        p0 = np.array([0, 0, pz + sz])
        if debug:
            print "p0:", p0

        # this is the intersection equation that we want to solve,
        # where s is the point on the line that intersects
        #     e_z(cp + s*cd - p0) = 0
        s = (p0[2] - cp[2]) / cd[2]
        if debug:
            print "s:", s

        # transform the collision point from line coordinates to world
        # coordinates
        cv = cp + s * cd
        if debug:
            print "collision:", cv

        return cv
Exemplo n.º 6
0
class World(DirectObject):
    def __init__(self):
        #This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking",
                                  style=1, fg=(1, 1, 1, 1),
                                  pos=(0.8, -0.95), scale=.07)
        self.escapeEvent = OnscreenText(
            text="ESC: Quit",
            style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.95),
            align=TextNode.ALeft, scale=.05)
        self.mouse1Event = OnscreenText(
            text="Left-click and drag: Pick up and drag piece",
            style=1, fg=(1, 1, 1, 1), pos=(-1.3, 0.90),
            align=TextNode.ALeft, scale=.05)

        self.accept('escape', sys.exit)  #Escape quits
        base.disableMouse()  #Disble mouse camera control
        camera.setPosHpr(0, -13.75, 6, 0, -25, 0)  #Set the camera
        self.setupLights()  #Setup default lighting

        #Since we are using collision detection to do picking, we set it up like
        #any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  #Make a traverser
        self.pq = CollisionHandlerQueue()  #Make a handler
        #Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  #Make our ray
        self.pickerNode.addSolid(self.pickerRay)  #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        #Now we create the chess board and its pieces

        #We will attach all of the squares to their own root. This way we can do the
        #collision pass just on the sqaures and save the time of checking the rest
        #of the scene
        self.squareRoot = render.attachNewNode("squareRoot")

        #For each square
        self.squares = [None for i in range(64)]
        self.pieces = dict((i, None) for i in range(64))  #MOD
        for i in range(64):
            #Load, parent, color, and position the model (a single square polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))
            #Set the model itself to be collideable with the ray. If this model was
            #any more complex than a single polygon, you should set up a collision
            #sphere around it instead. But for single polygons this works fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            #Set a tag on the square's node so we can look up what square this is
            #later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            #We will use this variable as a pointer to whatever piece is currently
            #in this square

        #The order of pieces on a chessboard from white's perspective. This list
        #contains the constructor functions for the piece classes defined below
        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        for i in range(8, 16):
            #Load the white pawns
            self.pieces[i] = Pawn(i, WHITE)
        for i in range(48, 56):
            #load the black pawns
            self.pieces[i] = Pawn(i, PIECEBLACK)
        for i in range(8):
            #Load the special pieces for the front row and color them white
            self.pieces[i] = pieceOrder[i](i, WHITE)
            #Load the special pieces for the back row and color them black
            self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK)

        #This will represent the index of the currently highlited square
        self.hiSq = False
        #This wil represent the index of the square where currently dragged piece
        #was grabbed from
        self.dragging = False

        #Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.grabPiece)  #left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  #releasing places it

    #This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def mouseTask(self, task):
        #This task deals with the highlighting and dragging based on the mouse

        #First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

        #Check to see if we can access the mouse. We need it to do anything else
        if base.mouseWatcherNode.hasMouse():
            #get the mouse position
            mpos = base.mouseWatcherNode.getMouse()

            #Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            #If we are dragging something, set the position of the object
            #to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                #Gets the point described by pickerRay.getOrigin(), which is relative to
                #camera, relative instead to render
                nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
                #Same thing with the direction of the ray
                nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

            #Do the actual collision pass (Do it only on the squares for
            #efficiency purposes)
            self.picker.traverse(self.squareRoot)
            if self.pq.getNumEntries() > 0:
                #if we have hit something, sort the hits so that the closest
                #is first, and highlight that node
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                #Set the highlight on the picked square
                self.squares[i].setColor(HIGHLIGHT)
                self.hiSq = i

        return Task.cont

    def grabPiece(self):
        #If a square is highlighted and it has a piece, set it to dragging mode
        if (self.hiSq is not False and
                self.pieces[self.hiSq]):
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        #Letting go of a piece. If we are not on a square, return it to its original
        #position. Otherwise, swap it with the piece in the new square
        if self.dragging is not False:  #Make sure we really are dragging something
            #We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                self.pieces[self.dragging].obj.setPos(
                    SquarePos(self.dragging))
            else:
                #Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)

        #We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  #This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 45, -45))
        directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Exemplo n.º 7
0
class MouseHandler (DirectObject):
    def __init__(self):
        self.accept('mouse1', self.onMouse1Down, [])  # Left click
        self.accept('mouse1-up', self.onMouse1Up, [])
        self.accept('mouse3', self.onMouse3Down, [])  # Right click

        self.showCollisions = False

        pickerNode = CollisionNode('mouseRay')
        pickerNP = camera.attachNewNode(pickerNode)
        pickerNode.setFromCollideMask(cardBuilder.cardCollisionMask)
        self.pickerRay = CollisionRay()
        pickerNode.addSolid(self.pickerRay)
        base.cTrav.addCollider(pickerNP, base.handler)
        if self.showCollisions:
            base.cTrav.showCollisions(render)
        base.disableMouse()

        self.activeCard = None
        self._targeting = False

        self._dragging = None

        # Counts down between clicks to detect double click
        self.doubleClickTimer = -1.0
        self.doubleClickInterval = 1.0

        self.line = attackLine.Line()

    @property
    def targeting(self):
        return self._targeting

    @targeting.setter
    def targeting(self, value):
        self._targeting = value
        if self._targeting:
            base.guiScene.showTargeting()
        else:
            base.guiScene.hideTargeting()

    def startTargeting(self, targetDesc, callback=None):
        base.targetDesc = targetDesc
        self.targeting = True
        if callback is not None:
            base.targetCallback = callback

    def getObjectClickedOn(self):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            base.cTrav.traverse(render)
            if (base.handler.getNumEntries() > 0):
                base.handler.sortEntries()
                pickedObj = base.handler.getEntry(0).getIntoNodePath()
                pickedObj = pickedObj.findNetPythonTag('zone')
                if pickedObj == self.dragging and base.handler.getNumEntries() > 1:
                    for entry in base.handler.getEntries():
                        n = entry.getIntoNodePath().findNetPythonTag('zone')
                        if n != self.dragging and n.parent != self.dragging:
                            return n

                    # If we don't find another object, do nothing
                    # TODO: Every object should only have 1 collider to make this easier

                return pickedObj

    def doClick(self):
        pickedObj = self.getObjectClickedOn()

        if self.dragging:
            return

        if self.targeting and pickedObj is not None:
            base.targetCallback(pickedObj)
        elif pickedObj and not pickedObj.isEmpty():
            zone = pickedObj.getPythonTag('zone')
            if zone is base.player.hand and not base.gameState.hasMulliganed:
                c = pickedObj.getPythonTag('card')
                if c in base.toMulligan:
                    base.toMulligan.remove(c)
                    base.audioMaster.mulliganSelectSound.play()
                else:
                    base.toMulligan.append(c)
                    base.audioMaster.mulliganDeselectSound.play()
                base.zoneMaker.makeMulliganHand()
            elif zone is base.player.hand:
                self.dragging = pickedObj
            elif zone is base.player.facedowns:
                c = pickedObj.getPythonTag('card')
                if self.activeCard:
                    self.activeCard = None
                elif c.requiresTarget:
                    self.startTargeting(c.targetDesc)
                    def callback(target):
                        base.revealFacedown(pickedObj, target)
                        base.finishTargeting()
                    base.targetCallback = callback
                else:
                    base.revealFacedown(pickedObj)
            elif zone is base.player.faceups:
                c = pickedObj.getPythonTag('card')
                if not c.hasAttacked:
                    self.activeCard = pickedObj
            elif zone is base.enemy.facedowns and self.activeCard:
                base.attack(self.activeCard, pickedObj)
                self.activeCard = None
            elif zone == base.enemy.faceups and self.activeCard:
                base.attack(self.activeCard, pickedObj)
                self.activeCard = None
            elif zone is base.enemy.face and self.activeCard:
                base.attack(self.activeCard, pickedObj)
                self.activeCard = None
        else:
            self.activeCard = None

    @property
    def dragging(self):
        return self._dragging

    @dragging.setter
    def dragging(self, obj):
        if obj is None:
            self._dragging.removeNode()
            base.zoneMaker.makePlayerHand()  # Put the card back
        else:
            obj.reparentTo(base.zoneMaker.scene)
            obj.setHpr(0, -90, 0)

        self._dragging = obj

    def stopDragging(self):
        """
        Stop dragging the card and play it if it's in the drop zone
        """
        # Borders of the drop zone
        # If you drop the card outside the drop zone,
        # the action is cancelled
        pos = self._dragging.getPos()
        if inDropZone(pos):
            try:
                target = None
                c = self.dragging.getPythonTag('card')
                if c.fast:
                    pickedObj = self.getObjectClickedOn()
                    if pickedObj is not None and pickedObj != self.dragging:
                        target = pickedObj
                    elif c.requiresTarget:
                        # don't fizzle if no valid target
                        self.dragging = None
                        return

                base.playCard(self._dragging, target)
            except IllegalMoveError as e:
                print(e)
        self.dragging = None

    def onMouse1Down(self):
        if self._dragging is not None:
            self.stopDragging()
            self.doubleClickTimer = -1
        elif self.doubleClickTimer <= 0:
            self.doubleClickTimer = 0.2
            try:
                self.doClick()
            except IllegalMoveError as e:
                print(e)

    def onMouse1Up(self):
        if self._dragging and self.doubleClickTimer <= 0:
            self.stopDragging()

    def onMouse3Down(self):
        if self.targeting:
            base.targetCallback(None)

        if self.dragging:
            self.dragging = None

    def mouseToXYPlane(self):
        mpos = base.mouseWatcherNode.getMouse()
        # See the Panda3d chess example
        self.pickerRay.setFromLens(
            base.camNode, mpos.getX(), mpos.getY())
        # Get a vector relative to the camera position
        nearPoint = render.getRelativePoint(
            camera, self.pickerRay.getOrigin())
        nearVec = render.getRelativeVector(
            camera, self.pickerRay.getDirection())

        return PointAtZ(.5, nearPoint, nearVec)

    def mouseOverTask(self):
        if base.mouseWatcherNode.hasMouse():
            if self.doubleClickTimer > 0:
                # Count down based on how long it took to draw the last frame
                self.doubleClickTimer -= globalClock.getDt()

            if hasattr(self, '_activeObj') and self._activeObj is not None:
                zone = self._activeObj.getPythonTag('card').zone
                if zone is base.player.facedowns or zone is base.enemy.facedowns:
                    zoneMaker.hideCard(self._activeObj)

                base.zoneMaker.unfocusCard()
                self._activeObj = None

            if self.dragging is not None:
                # Drag the card in the XY plane
                self.dragging.setPos(self.mouseToXYPlane())
            elif base.gameState.hasMulliganed:
                pickedObj = self.getObjectClickedOn()
                if pickedObj:
                    card = pickedObj.getPythonTag('card')
                    if card is not None and not pickedObj.getPythonTag('disableFocus'):
                        self._activeObj = pickedObj
                        if card.zone in (
                                base.enemy.hand,
                                base.player.facedowns,
                                base.enemy.facedowns):
                            zoneMaker.showCard(pickedObj)
                        base.zoneMaker.focusCard(pickedObj)

                if self.activeCard:
                    basePos = (pickedObj.getPos(base.render)
                        if pickedObj is not None and not pickedObj.isEmpty()
                        else self.mouseToXYPlane()),
                    self.line.draw(
                        start=self.activeCard.getPos(base.render),
                        end=basePos)
                else:
                    self.line.clear()
class LocationSeeker:
    def __init__(self, avatar, minDistance, maxDistance, shadowScale=1):
        self.dropShadowPath = 'phase_3/models/props/square_drop_shadow.bam'
        self.rejectSoundPath = 'phase_4/audio/sfx/ring_miss.ogg'
        self.moveShadowTaskName = 'Move Shadow'
        self.locationSelectedName = 'Location Selected'
        self.dropShadow = None
        self.shadowScale = shadowScale
        self.rejectSfx = loader.loadSfx(self.rejectSoundPath)
        self.avatar = avatar
        self.cameraNode = None
        self.cameraRay = None
        self.cameraNP = None
        self.shadowNP = None
        self.shadowRay = None
        self.minDistance = minDistance
        self.maxDistance = maxDistance
        self.legacyMode = False
        self.collHdlFl = CollisionHandlerQueue()
        self.moveShadowEventName = 'LocationSeeker-MoveShadow'
        return

    def startSeeking(self):
        if not self.avatar:
            return
        self.cleanupShadow()
        self.buildShadow()
        scale = self.dropShadow.getScale()
        if scale < 1.0:
            self.maxDistance += 40
        x, y, z = self.avatar.getPos(render)
        self.dropShadow.reparentTo(render)
        self.dropShadow.setPos(x, y + 5, z + 2)
        self.cameraNode = CollisionNode('coll_camera')
        self.cameraNode.setFromCollideMask(CIGlobals.WallBitmask)
        self.cameraRay = CollisionRay()
        self.cameraNode.addSolid(self.cameraRay)
        self.cameraNP = camera.attachNewNode(self.cameraNode)
        base.cTrav.addCollider(self.cameraNP, CollisionHandlerQueue())
        if not self.legacyMode:
            shadowNode = CollisionNode('coll_shadow')
            self.shadowRay = CollisionRay(0, 0, 6, 0, 0, -1)
            shadowNode.addSolid(self.shadowRay)
            shadowNode.setFromCollideMask(CIGlobals.FloorBitmask)
            self.shadowNP = self.dropShadow.attachNewNode(shadowNode)
            base.cTrav.addCollider(self.shadowNP, self.collHdlFl)
        base.taskMgr.add(self.__moveShadow, self.moveShadowTaskName)
        self.avatar.acceptOnce('mouse1', self.locationChosen)

    def stopSeeking(self):
        base.taskMgr.remove(self.moveShadowTaskName)

    def __moveShadow(self, task):
        if base.mouseWatcherNode.hasMouse():
            prevPos = self.dropShadow.getPos(render)

            def PointAtZ(z, point, vec):
                if vec.getZ() != 0:
                    return point + vec * ((z - point.getZ()) / vec.getZ())
                return self.getLocation()

            mouse = base.mouseWatcherNode.getMouse()
            self.cameraRay.setFromLens(base.camNode, mouse.getX(),
                                       mouse.getY())
            nearPoint = render.getRelativePoint(camera,
                                                self.cameraRay.getOrigin())
            nearVec = render.getRelativeVector(camera,
                                               self.cameraRay.getDirection())
            self.dropShadow.setPos(PointAtZ(0.5, nearPoint, nearVec))
            if (prevPos - self.dropShadow.getPos(render)).length() >= 0.25:
                messenger.send(self.moveShadowEventName)
            if self.legacyMode:
                self.dropShadow.setZ(base.localAvatar.getZ(render) + 0.5)
            elif self.collHdlFl.getNumEntries() > 0:
                self.dropShadow.setZ(
                    self.collHdlFl.getEntry(0).getSurfacePoint(render).getZ() +
                    0.5)
        return Task.cont

    def locationChosen(self):
        base.taskMgr.remove(self.moveShadowTaskName)
        distance = self.avatar.getDistance(self.dropShadow)
        x, y, z = self.getLocation()
        if distance >= self.minDistance and distance <= self.maxDistance:
            gag = self.avatar.getBackpack().getActiveGag()
            self.avatar.sendUpdate('setDropLoc', [gag.getID(), x, y, z])
            messenger.send(self.locationSelectedName)
        else:
            self.rejectSfx.play()
            self.avatar.acceptOnce('mouse1', self.locationChosen)
            base.taskMgr.add(self.__moveShadow, self.moveShadowTaskName)

    def buildShadow(self):
        self.cleanupShadow()
        if not self.dropShadowPath or not self.avatar:
            return
        self.dropShadow = loader.loadModel(self.dropShadowPath)
        self.dropShadow.setScale(self.shadowScale)
        self.dropShadow.setName('LocationSeeker_Shadow')

    def setShadowType(self, isCircle=False, scale=1):
        if not isCircle:
            self.dropShadowPath = 'phase_3/models/props/square_drop_shadow.bam'
        else:
            self.dropShadowPath = 'phase_3/models/props/drop_shadow.bam'
        self.shadowScale = scale

    def getDropShadow(self):
        return self.dropShadow

    def getLocation(self):
        if self.dropShadow:
            return self.dropShadow.getPos(render)
        return self.avatar.getPos(render)

    def getLocationSelectedName(self):
        return self.locationSelectedName

    def getShadowMovedName(self):
        return self.moveShadowEventName

    def cleanupShadow(self):
        if self.dropShadow:
            self.dropShadow.removeNode()
            self.dropShadow = None
            if self.cameraNode:
                self.cameraNP.removeNode()
                self.cameraNP = None
                self.cameraNode = None
                self.cameraRay = None
                self.shadowNP.removeNode()
                self.shadowRay = None
                self.shadowNP = None
                self.shadowSphNP = None
        return

    def cleanup(self):
        if self.avatar:
            base.taskMgr.remove(self.moveShadowTaskName)
            self.avatar.ignore('mouse1')
            self.cleanupShadow()
            self.rejectSfx.stop()
            self.rejectSfx = None
            self.avatar = None
            self.dropShadowPath = None
            self.rejectSoundPath = None
            self.locationSelectedName = None
            self.moveShadowTaskName = None
            self.moveShadowEventName = None
            self.collHdlFl = None
            del self.collHdlFl
            del self.minDistance
            del self.maxDistance
            del self.legacyMode
            del self.dropShadow
            del self.cameraNP
            del self.cameraNode
            del self.cameraRay
            del self.shadowNP
            del self.shadowRay
            del self.shadowSphNP
            del self.shadowScale
            del self.rejectSfx
            del self.avatar
            del self.dropShadowPath
            del self.rejectSoundPath
            del self.locationSelectedName
            del self.moveShadowTaskName
            del self.moveShadowEventName
        return
Exemplo n.º 9
0
class World(DirectObject):
  mySound = base.loader.loadSfx("trial.mp3")
#Used for adding a virus at a randomly generated position 
  def random_vgen(self):
    print 'I am in random'
    for i in range(0,5):
      
      self.a[random.randint(0,7)][random.randint(0,7)] = 1
  

  def initializer(self,level):
    
  
    self.turns = 0
      
##   Level Definition 
    
    def levelone():
        self.a[4][4] = 1
        self.a[4][5] = 1
        self.a[4][6] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[4][6] = 1
        self.a[5][5] = 1
    def leveltwo():
        self.a[4][3] = 1
        self.a[4][5] = 1
        self.a[4][7] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[2][2] = 1
        self.a[5][3] = 1
        self.a[1][2] = 1

    def levelthree():
        self.a[4][4] = 1
        self.a[4][5] = 1
        self.a[4][6] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[4][6] = 1
        self.a[5][5] = 1
        self.a[4][3] = 1
        self.a[4][5] = 1
        self.a[4][7] = 1
        self.a[5][2] = 1
        self.a[3][5] = 1
        self.a[2][2] = 1
        self.a[5][3] = 1


    options = {1: levelone,
               2: leveltwo,
               3: levelthree
            
            }

    options[level]()
    
    print self.a
    temp = []
    count = 0
    for element in reversed(self.a):
        for ele in element:
            #print 'cheking element is 1 : ' + str(ele)
            if ele == 1:
                temp.append(count)
                self.pieces[count] = Monster(count,WHITE)
                #self.squares[count].setColor(HIGHLIGHT)
            count = count + 1
    self.list=temp
    
  def showscore(self):
        try:
            self.score.destroy()
        except:
            pass
        self.score = OnscreenText(text = 'Number of Turns : %s'%(self.turns), pos = (0.5, 0.95), scale = 0.07, mayChange = True)
  def menuscreen(self):
      
      # Callback function to set  text
    def setText():
        b.destroy()
        helptext.destroy()
        
    
    # Add button
    b = DirectButton(text = ("START", "START", "START", "disabled"), scale=0.15, command=setText, pos=(0,0,0.85))

    helptext = OnscreenText(text ='''
    STORY:
    Hello Mad Scientist!
    You are so close to finding the cure to aids!
    You understood the behaviour and can finally manipulate the virus to kill itself!
    But time is running out!
    You have a red and white blood cell sample infected with AIDS Virus.

    INSTRUCTIONS:
    The AIDS Virus obeys the Conway's Game of Life. Who would have guessed?
    1.  If virus is surrounded by more than 3 viruses, it dies of suffocation
    2.  If virus is surrounded by less than 2 viruses, it dies of underpopulation
    3.  If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned due to breeding.

    AIM:
    To kill all the viruses, by moving one of them every turn.

    ''', pos = (-0.90,0.72),frame = (123,123,123,1), wordwrap = 25, align = TextNode.ALeft, bg = (0.23,0.243,0.13,0.9))

  def endscreen(self):     
    def restart():
        taskMgr.remove(self.mouseTask)
        for i in range(64):
            self.squares[i].setColor(SquareColor(i))
        scorecard.destroy()
        restartb.destroy()
        end.destroy()
        nextlevelb.destroy()
        self.reference.destroy()
        self.mySound.stop()
        try:            
            self.score.destroy()
        except:
            pass
        print 'restarting'
        print self.a
        print self.list
  
            
        World()
        
    def quitgame():
        sys.exit()

    def nextLevel():
        self.currlevel = self.currlevel + 1
        nextlevelb.destroy()
        scorecard.destroy()
        restartb.destroy()
        end.destroy()
        self.score.destroy()
        self.initializer(self.currlevel)

    

    # Add button

    scorecard = OnscreenText(text = 'You finished it in %s turns! '%(self.turns),frame = (123,123,123,0), wordwrap = 25, bg = (0.2,0,0.8,1))

    nextlevelb = DirectButton(text = ("NEXT LEVEL", "NEXT LEVEL", "NEXT LEVEL", "disabled"), scale=0.15, command=nextLevel, pos=(0,0,-0.15))
    restartb = DirectButton(text = ("RESTART", "RESTART", "RESTART", "disabled"), scale=0.15, command=restart, pos=(0,0,-0.35))
    end = DirectButton(text = ("QUIT", "QUIT", "QUIT", "disabled"), scale=0.15, command=quitgame, pos=(0,0,-0.55))
    if self.currlevel == self.maxlevel:
      nextlevelb.destroy()


  def __init__(self):
    #music
    
    
    self.mySound.play()
      

    print 'I am being initialized'
    
          
    self.menuscreen()
    self.list = []
    self.turns = 0
    self.maxlevel = 3
    self.currlevel = 1
    self.a =[[0 for x in range(8)] for y in range(8)]
    
    
        
    #This code puts the standard title and instruction text on screen
    self.title = OnscreenText(text="Game of Life : Help in ending AIDS!",
                              style=1, fg=(1,1,1,1),
                              pos=(0,-0.95), scale = .07)
    self.escapeEvent = OnscreenText( 
      text="ESC: Quit",
      style=1, fg=(1,1,1,1), pos=(-1.3, 0.95),
      align=TextNode.ALeft, scale = .05)
##    self.mouse1Event = OnscreenText(
##      text="Left-click and drag: Pick up virus and drag it to a new bloodcell",
##      style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
##      align=TextNode.ALeft, scale = .05)
##    
    
        
    
    self.accept('escape', sys.exit)              #Escape quits
    
    base.disableMouse()                          #Disble mouse camera control
    camera.setPosHpr(0, -13.75, 6, 0, -25, 0)    #Set the camera
    self.setupLights()                           #Setup default lighting
    
    #Since we are using collision detection to do picking, we set it up like
    #any other collision detection system with a traverser and a handler
    self.picker = CollisionTraverser()            #Make a traverser
    self.pq     = CollisionHandlerQueue()         #Make a handler
    #Make a collision node for our picker ray
    self.pickerNode = CollisionNode('mouseRay')
    #Attach that node to the camera since the ray will need to be positioned
    #relative to it
    self.pickerNP = camera.attachNewNode(self.pickerNode)
    #Everything to be picked will use bit 1. This way if we were doing other
    #collision we could seperate it
    self.pickerNode.setFromCollideMask(BitMask32.bit(1))
    self.pickerRay = CollisionRay()               #Make our ray
    self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
    #Register the ray as something that can cause collisions
    self.picker.addCollider(self.pickerNP, self.pq)
    #self.picker.showCollisions(render)

    #We will attach all of the squares to their own root. This way we can do the
    #collision pass just on the sqaures and save the time of checking the rest
    #of the scene
    self.squareRoot = render.attachNewNode("squareRoot")
    
    #For each square
    self.squares = [None for i in range(64)]
    self.pieces = [None for i in range(64)]

    
    for i in range(64):
      #Load, parent, color, and position the model (a single square polygon)
      self.squares[i] = loader.loadModel("models/square")
      self.squares[i].reparentTo(self.squareRoot)
      self.squares[i].setPos(SquarePos1(i))
      self.squares[i].setColor(SquareColor(i))
      #Set the model itself to be collideable with the ray. If this model was
      #any more complex than a single polygon, you should set up a collision
      #sphere around it instead. But for single polygons this works fine.
      self.squares[i].find("**/polygon").node().setIntoCollideMask(
        BitMask32.bit(1))
      #Set a tag on the square's node so we can look up what square this is
      #later during the collision pass
      self.squares[i].find("**/polygon").node().setTag('square', str(i))

      #We will use this variable as a pointer to whatever piece is currently
      #in this square

    
    self.initializer(self.currlevel)
    
    
          

    

    #This will represent the index of the currently highlited square
    self.hiSq = False
    #This wil represent the index of the square where currently dragged piece
    #was grabbed from
    self.dragging = False

    #Start the task that handles the picking
    self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
    #self.trial = taskMgr.add(self.trial,'trial')
    self.accept("mouse1", self.grabPiece)       #left-click grabs a piece
    self.accept("mouse1-up", self.releasePiece) #releasing places it
    
   

  #This function swaps the positions of two pieces
  def swapPieces(self, fr, to):
    temp = self.pieces[fr]
    self.pieces[fr] = self.pieces[to]
    self.pieces[to] = temp
    if self.pieces[fr]:
      print 'imma swapping'  
      self.pieces[fr].square = fr
      print fr
      print SquarePos(fr)
      try:
          self.pieces[fr].obj.setPos(SquarePos(fr))
      except:
          pass
      print 'done'
    if self.pieces[to]:
      self.pieces[to].square = to
      try:
          self.pieces[to].obj.setPos(SquarePos(to))
      except:
          pass
  def trial(self):
      self.turns = self.turns + 1
      try:
        self.reference.destroy()
      except:
        pass
      self.reference = OnscreenText( 
      text='''
Reference:
virus is surrounded by more than 3 viruses, it dies
virus is surrounded by less than 2 viruses, it dies
If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned.
'''  ,
      style=1, fg=(1,1,1,1), pos=(-1, 0.95),
      align=TextNode.ALeft, scale = .05)
      
      
      self.showscore()
      a = self.a
      while True:
          for i in self.list:
              #insert deletion code
              print 'imma deleting the sq : ' + str(i)
              self.pieces[i].obj.delete()
              
              self.squares[i].setColor(SquareColor(i))
          count = 0
          a=[[([[sum(b[y1][x1] for b in [[[((-1<x2+dx<len(a[0])) and (-1<y2+dy<len(a))) and a[y2+dy][x2+dx] or 0 for x2 in range(len(a[0]))] for y2 in range(len(a))] for (dx,dy) in [(dx,dy) for dx in [-1,0,1] for dy in [-1,0,1] if (dy!=0 or dx!=0)]]) for x1 in range(len(a[0]))] for y1 in range(len(a))][y][x]== 3 or ([[sum(c[y3][x3] for c in [[[((-1<x4+dx<len(a[0])) and (-1<y4+dy<len(a))) and a[y4+dy][x4+dx] or 0 for x4 in range(len(a[0]))] for y4 in range(len(a))] for (dx,dy) in [(dx,dy) for dx in [-1,0,1] for dy in [-1,0,1] if (dy!=0 or dx!=0)]]) for x3 in range(len(a[0]))] for y3 in range(len(a))][y][x] == 2 and a[y][x]==1)) and 1 or 0 for x in range(len(a[0]))] for y in range(len(a))]
          lis = []
          #insert a random virus at a probability of 1/5
          diceroll = random.randint(0,5)
          if diceroll == 2:
            
            self.random_vgen()
          for element in reversed(a):
              
              for ele in element:
                  #print 'cheking element is 1 : ' + str(ele)
                  if ele == 1:
                      lis.append(count)
                  count = count + 1
          print lis  
          self.list = lis
          
          self.a = a
          print self.list
          
          for i in self.list:
              self.pieces[i] = Monster(i,WHITE)
              #self.squares[i].setColor(HIGHLIGHT)
          print 'leaving trial'  
          if len(self.list)==0:
              self.endscreen()
          break
        
      return
  def mouseTask(self, task):
    #This task deals with the highlighting and dragging based on the mouse
    
    #First, clear the current highlight
    if self.hiSq is not False:
      self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
      self.hiSq = False
      
    #Check to see if we can access the mouse. We need it to do anything else
    if base.mouseWatcherNode.hasMouse():
      #get the mouse position
      mpos = base.mouseWatcherNode.getMouse()
      
      #Set the position of the ray based on the mouse position
      self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
      
      #If we are dragging something, set the position of the object
      #to be at the appropriate point over the plane of the board
      if self.dragging is not False:
        #Gets the point described by pickerRay.getOrigin(), which is relative to
        #camera, relative instead to render
        nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
        #Same thing with the direction of the ray
        nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
        try:
            self.pieces[self.dragging].obj.setPos(PointAtZ(.5, nearPoint, nearVec))
        except:
            pass
      #Do the actual collision pass (Do it only on the squares for
      #efficiency purposes)
      self.picker.traverse(self.squareRoot)
      if self.pq.getNumEntries() > 0:
        #if we have hit something, sort the hits so that the closest
        #is first, and highlight that node
        self.pq.sortEntries()
        i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
        #Set the highlight on the picked square
        self.squares[i].setColor(HIGHLIGHT)
        self.hiSq = i
        #print 'selected is ' + str(i)

    return Task.cont

  def grabPiece(self):
    #If a square is highlighted and it has a piece, set it to dragging mode
    if (self.hiSq is not False and
      self.pieces[self.hiSq]):
      self.dragging = self.hiSq
      self.hiSq = False
    
  def releasePiece(self):
    #Letting go of a piece. If we are not on a square, return it to its original
    #position. Otherwise, swap it with the piece in the new square
    if self.dragging is not False:   #Make sure we really are dragging something
      #We have let go of the piece, but we are not on a square
      if self.hiSq is False:
        try:
            self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
        except:
            pass
      else:
        #Otherwise, swap the pieces
        self.swapPieces(self.dragging, self.hiSq)
        #self.draggin is the from
        print self.list
        print 'you picked this, so Imma deleting this ' + str(self.dragging)
        #deletion of i after picking it up.
        try:
            self.list.remove(self.dragging)
        except:
            pass
        temp2 = []
        temp2 = SquarePosTuple(self.dragging)
        self.a[temp2[0]][temp2[1]] = 0
        
        i = self.hiSq
        print self.list
        print 'highlighted sq is ' + str(i)
        templis = []
        templis = SquarePosTuple(i)
        print templis
        self.list.append(i)
        print self.list
        print templis
        self.a[templis[0]][templis[1]] = 1

        
        
        for line in self.a:
            print line
        self.trial()
        
    #We are no longer dragging anything
    self.dragging = False

  def setupLights(self):    #This function sets up some default lighting
    ambientLight = AmbientLight( "ambientLight" )
    ambientLight.setColor( Vec4(.8, .8, .8, 1) )
    directionalLight = DirectionalLight( "directionalLight" )
    directionalLight.setDirection( Vec3( 0, 45, -45 ) )
    directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) )
    render.setLight(render.attachNewNode( directionalLight ) )
    render.setLight(render.attachNewNode( ambientLight ) )
Exemplo n.º 10
0
class ChessboardDemo(ShowBase):
    def calculatePossiblePositions(self, startingPos, movementArray):
        possibleIndexes = []
        multiplierArray = [[7, 8, 9], [-1, 1], [-9, -8, -7]]
        for i in range(0, 3):
            for j in range(0, 3):
                if (i == 1 and j == 2):
                    continue
                for k in range(1, movementArray[i][j] + 1):
                    possibleIndex = startingPos + k * multiplierArray[i][j]
                    if possibleIndex < 64 and possibleIndex >= 0:
                        possibleIndexes.append(startingPos +
                                               k * multiplierArray[i][j])
        return list(set(possibleIndexes))

    def getAllCollidingPositions(self, startingPos, possibleEndPositions):
        collisions = []
        for possibleEndPosition in possibleEndPositions:
            if (not isinstance(self.pieces[possibleEndPosition], type(None))):
                if (self.pieces[possibleEndPosition].obj.getColor() ==
                        self.turn):
                    collisions.append(possibleEndPosition)
        return collisions

    def getDirectionMultiplier(self, startingPos, endPos):
        temp = endPos - startingPos
        if temp < 0:
            if temp % -8 == 0:
                return -8
            elif temp % -9 == 0:
                return -9
            elif temp % -7 == 0:
                return -7
            else:
                return -1
        else:
            if temp % 8 == 0:
                return 8
            elif temp % 7 == 0:
                return 7
            elif temp % 9 == 0:
                return 9
            else:
                return 1

    def checkCollisionInLine(self, startingPos, endPos, collidingPositions):
        if endPos in collidingPositions:
            return True
        else:
            directionalMultiplier = self.getDirectionMultiplier(
                startingPos, endPos)
            positionsOnTheLine = []
            temp = startingPos + directionalMultiplier
            while temp != endPos:
                positionsOnTheLine.append(temp)
                temp += directionalMultiplier

            for position in positionsOnTheLine:
                if (isinstance(self.pieces[position], Piece)):
                    return True
            return False

    def checkIfRoutePossible(self, startingPos, endPos, movementArray):
        if (isinstance(self.pieces[startingPos], Knight)):
            endPositions = []
            for i in movementArray:
                endPositions.append(startingPos + i)

            if endPos in endPositions:
                return True
            else:
                return False
        if (self.turn == PIECEBLACK and isinstance(self.movingPiece, Pawn)):
            movementArray = list(reversed(movementArray))
        listOfPossiblePositions = self.calculatePossiblePositions(
            startingPos, movementArray)
        #listOfPossiblePositions.remove(startingPos)
        listOfCollidingPositions = self.getAllCollidingPositions(
            startingPos, listOfPossiblePositions)
        if endPos in listOfPossiblePositions:
            if not self.checkCollisionInLine(startingPos, endPos,
                                             listOfCollidingPositions):
                return True

        return False

    def __init__(self):
        ShowBase.__init__(self)
        self.turn = WHITE
        self.movingPiece = None
        self.isMovementPossible = False

        self.escapeEvent = OnscreenText(text="ESC: Quit",
                                        parent=base.a2dTopLeft,
                                        style=1,
                                        fg=(1, 1, 1, 1),
                                        pos=(0.06, -0.1),
                                        align=TextNode.ALeft,
                                        scale=.05)
        self.mouse1Event = OnscreenText(
            text="Left-click and drag: Pick up and drag piece",
            parent=base.a2dTopLeft,
            align=TextNode.ALeft,
            style=1,
            fg=(1, 1, 1, 1),
            pos=(0.06, -0.16),
            scale=.05)

        self.accept('escape', sys.exit)  # Escape quits
        self.disableMouse()  # Disble mouse camera control
        camera.setPosHpr(0, -12, 8, 0, -35, 0)
        self.setupLights()

        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        self.pickerNode = CollisionNode('mouseRay')
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)

        self.squareRoot = render.attachNewNode("squareRoot")
        # For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]
        for i in range(64):
            # Load, parent, color, and position the model (a single square
            # polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))

            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        for i in range(8, 16):
            # Load the white pawns
            self.pieces[i] = Pawn(i, WHITE)
        for i in range(48, 56):
            # load the black pawns
            self.pieces[i] = Pawn(i, PIECEBLACK)
        for i in range(8):
            # Load the special pieces for the front row and color them white
            self.pieces[i] = pieceOrder[i](i, WHITE)
            # Load the special pieces for the back row and color them black
            self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK)

        # This will represent the index of the currently highlited square
        self.hiSq = False
        # This wil represent the index of the square where currently dragged piece
        # was grabbed from
        self.dragging = False

        # Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.grabPiece)  # left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  # releasing places it

    # This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def trashPiece(self, index):
        self.pieces[index].obj.setPos(trash())
        self.pieces[index] = None

    def mouseTask(self, task):

        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

        if self.mouseWatcherNode.hasMouse():
            # get the mouse position
            mpos = self.mouseWatcherNode.getMouse()

            # Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY())

            # If we are dragging something, set the position of the object
            # to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                # Gets the point described by pickerRay.getOrigin(), which is relative to
                # camera, relative instead to render
                nearPoint = render.getRelativePoint(camera,
                                                    self.pickerRay.getOrigin())
                # Same thing with the direction of the ray
                nearVec = render.getRelativeVector(
                    camera, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

            self.picker.traverse(self.squareRoot)
            if self.pq.getNumEntries() > 0:
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                # Set the highlight on the picked square

                if (self.dragging != False
                        or (isinstance(self.pieces[i], Piece)
                            and self.pieces[i].obj.getColor() == self.turn)):
                    if (isinstance(self.movingPiece, Piece)):
                        if (isinstance(self.pieces[i], Piece) and
                                self.pieces[i].obj.getColor() != self.turn):
                            movementTable = self.movingPiece.getMovementTableBattle(
                            )
                        else:
                            movementTable = self.movingPiece.getMovmentTableNoBattle(
                            )
                        if (self.checkIfRoutePossible(self.movingPieceIndex, i,
                                                      movementTable)):
                            self.squares[i].setColor(HIGHLIGHT_POSITIVE)
                            self.isMovementPossible = True
                        else:
                            self.squares[i].setColor(HIGHLIGHT_NEGATIVE)
                            self.isMovementPossible = False
                    self.hiSq = i

        return Task.cont

    def grabPiece(self):
        if self.hiSq is not False and self.pieces[self.hiSq]:
            self.movingPiece = self.pieces[self.hiSq]
            self.movingPieceIndex = self.hiSq
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        if self.dragging is not False:
            if self.hiSq is False or not self.isMovementPossible or (
                    isinstance(self.pieces[self.dragging], Piece)
                    and isinstance(self.pieces[self.hiSq], Piece)
                    and self.pieces[self.dragging].obj.getColor()
                    == self.pieces[self.hiSq].obj.getColor()):
                self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
            else:
                # Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)
                if (isinstance(self.pieces[self.dragging], Piece)
                        and self.dragging != self.hiSq
                        and self.pieces[self.dragging].obj.getColor() !=
                        self.pieces[self.hiSq].obj.getColor()):
                    self.trashPiece(self.dragging)
                    print('trashed')

                if (not isinstance(self.movingPiece, type(None))
                        and self.movingPiece.isPawn()
                        and self.dragging != self.hiSq):
                    self.movingPiece.setFirstMove(False)
                self.isCheck(self.hiSq)
                self.changeTurn()

        self.dragging = False
        self.movingPiece = None
        self.movingPieceIndex = -1

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))

    def changeTurn(self):
        if self.turn == WHITE:
            self.turn = PIECEBLACK
        else:
            self.turn = WHITE

    def isCheck(self, index):
        kingIndex = 0
        for i in range(0, 64):
            if (isinstance(self.pieces[i], King)
                    and self.pieces[i].obj.getColor() != self.turn):
                kingIndex = i
        for j in range(0, 64):
            if (isinstance(self.pieces[index], Piece)
                    and self.pieces[index].obj.getColor() == self.turn):
                if (self.checkIfRoutePossible(
                        index, kingIndex,
                        self.pieces[index].getMovementTableBattle())):
                    global check
                    print("CHECK FOUND")
                    label = "white"
                    if self.turn == WHITE:
                        label = "black"
                    check = OnscreenText(text="Check on " + label + " king",
                                         parent=base.a2dTopLeft,
                                         align=TextNode.ALeft,
                                         style=1,
                                         fg=(1, 1, 1, 1),
                                         pos=(0.06, -0.26),
                                         scale=.05)
                elif (not isinstance(check, type(None))):
                    print("Should remove now")
                    check.destroy()
                    check = None
Exemplo n.º 11
0
class World(DirectObject):
	def __init__(self, mode, ip=None):
		
		if mode==CLIENT and not ip:
			#Don't let this happen.
			print "WTF programmer"
			sys.exit()
		
		#current dialog box
		self.d = None
		
		#top-left of screen; contains instructions on how to exit the game.
		self.quitInstructions = OnscreenText(text='Press ESC to exit.', pos=(-1, 0.95), scale=0.05, fg=(1,1,1,1), bg=(0,0,0,0), mayChange=False)
		
		#bottom of screen
		self.turnIndicator = OnscreenText(text='', pos=(0,-0.8), scale=0.1, fg=(1,1,1,1), bg=(0,0,0,0), mayChange=True)
		
		#Saving some values, some default values
		self.mode = mode
		self.player = {SERVER: PIECEWHITE, CLIENT: PIECEBLACK}[self.mode]
		self.ip = ip
		
		#Panda3D, by default, allows for camera control with the mouse.
		base.disableMouse()
		
		self.setupMouse()
		self.setupBoard()
		self.setupCamera()
		self.setupPieces()
		self.setupNetwork()
		self.setupLights()
		
		#some internal state for making clicky moves
		self.hiSq = None
		self.dragOrigin = None
		
		#keyboard, mouse
		self.mouseTask = taskMgr.add(self.tskMouse, 'mouseTask')
		self.accept('mouse1', self.handleClick)
		self.accept('f2', lambda: base.setFrameRateMeter(True))
		self.accept('f3', lambda: base.setFrameRateMeter(False))
		self.accept('escape', sys.exit)
		
		
		#first turn
		self.turn = PIECEWHITE
	
	#### INITIALIZATION ####
	
	def setupBoard(self):
		#We will attach all of the squares to their own root. This way we can do the
		#collision pass just on the sqaures and save the time of checking the rest
		#of the scene
		self.squareRoot = render.attachNewNode("squareRoot")

		#For each square
		self.squares = dict(((i,j), None) for i in range(8) for j in range(8))
		for place in self.squares:
			#Load, parent, color, and position the model (a single square polygon)
			self.squares[place] = loader.loadModel("models/square")
			self.squares[place].reparentTo(self.squareRoot)
			self.squares[place].setPos(SquarePos(place))
			self.squares[place].setColor(SquareColor(place))
			#Set the model itself to be collideable with the ray. If this model was
			#any more complex than a single polygon, you should set up a collision
			#sphere around it instead. But for single polygons this works fine.
			self.squares[place].find("**/polygon").node().setIntoCollideMask(
			  BitMask32.bit(1))
			#Set a tag on the square's node so we can look up what square this is
			#later during the collision pass
			self.squares[place].find("**/polygon").node().setTag('square', ' '.join(map(str,place)))
			self.squares[place].setTransparency(TransparencyAttrib.MAlpha)

	def setupPieces(self):
		#Default dictionaries work decently well as an easy two-dimensional array.
		self.pieces = defaultdict(lambda: None)
		
		#The order of pieces on a chessboard from white's perspective
		pieceOrder = [Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook]
		
		for i in xrange(8):
			#load white pawns
			self.pieces[i, 1] = Pawn((i,1), PIECEWHITE)
			
			#load black pawns
			self.pieces[i, 6] = Pawn((i, 6), PIECEBLACK)
			
			#load white specials
			self.pieces[i, 0] = pieceOrder[i]((i,0), PIECEWHITE)
			
			#load black specials
			self.pieces[i, 7] = pieceOrder[i]((i,7), PIECEBLACK)
		for p in self.pieces.values():
			p.obj.setTransparency(TransparencyAttrib.MAlpha)
	
	# TODO: Notice when the other side disconnects
	def setupNetwork(self):
		if self.mode == CLIENT:
			self.setupClient(self.ip)
		else:
			self.setupServer()
	
	# A lot of the below two methods is boilerplate straight from Panda3D documentation.
	def setupServer(self):
		self.cManager = QueuedConnectionManager()
		self.cListener = QueuedConnectionListener(self.cManager, 0)
		self.cReader = QueuedConnectionReader(self.cManager, 0)
		self.cWriter = ConnectionWriter(self.cManager,0)
		
		self.oppConnection = None
		port = 15905 # Chosen by fair dice roll.
		             # Guaranteed to be random.
		backlog = 1000
		tcpSocket = self.cManager.openTCPServerRendezvous(port, backlog)
		
		self.cListener.addConnection(tcpSocket)
		
		def tskListenerPoll(task):
			if self.cListener.newConnectionAvailable() and not self.oppConnection:
				rendezvous = PointerToConnection()
				addr = NetAddress()
				newCon = PointerToConnection()
				
				if self.cListener.getNewConnection(rendezvous, addr, newCon):
					newConnection = newCon.p()
					print "Received connection from %s" % newConnection.getAddress()
					self.oppConnection = newConnection
					self.cReader.addConnection(newConnection)
					
					#server starts the game
					self.turnIndicator['text'] = 'Your turn!'
					self.showVisibleSquares()
					
					#remove the dialog node from below
					if self.d: self.d.removeNode()
					
					return Task.done
			if not self.d: self.d = DirectDialog(text="Waiting for client to connect...", buttonTextList=[], buttonValueList=[])
			return Task.cont
			
		taskMgr.add(tskListenerPoll, "Poll the connection listener")
		taskMgr.add(self.tskReaderPoll, "Poll the connection reader")
	
	def setupClient(self, ip):
		self.cManager = QueuedConnectionManager()
		self.cReader = QueuedConnectionReader(self.cManager, 0)
		self.cWriter = ConnectionWriter(self.cManager,0)
		
		self.oppConnection = None
		
		port = 15905
		timeout = 3000
		myConnection = self.cManager.openTCPClientConnection(ip, port, timeout)
		if myConnection:
			self.cReader.addConnection(myConnection)
			self.oppConnection = myConnection
			
			taskMgr.add(self.tskReaderPoll, "Poll the connection reader")
			self.showVisibleSquares()
		else:
			self.d = OkDialog(text="Could not connect to server at '%s'" % ip, command=sys.exit)
	
	# Makes sure player gets a decent view of the game board, and *not* of the hidden pieces below the board. Shhhh...
	def setupCamera(self):
		if self.player == PIECEWHITE:
			camera.setPos(0, -13.75, 8)
			camera.lookAt(self.squareRoot)
			camera.setH(0)
		else:
			camera.setPos(0, 13.75, 8)
			camera.lookAt(self.squareRoot)
			camera.setH(180)
	
	# Adds some ambient lights and a directional light
	def setupLights(self):
		#This is one area I know hardly anything about. I really don't know how to get this to behave nicely.
		#The black pieces are hardly distinguishable.
		ambientLight = AmbientLight( "ambientLight" )
		ambientLight.setColor( Vec4(.8, .8, .8, 1) )
		directionalLight = DirectionalLight( "directionalLight" )
		directionalLight.setDirection( Vec3( 0, 45, -45 ) )
		directionalLight.setColor( Vec4( 0.2, 0.2, 0.2, 1 ) )
		render.setLight(render.attachNewNode( directionalLight ) )
		render.setLight(render.attachNewNode( ambientLight ) )
	
	# Sets up collision detection for the mouse cursor.
	def setupMouse(self):
		#Since we are using collision detection to do picking, we set it up like
		#any other collision detection system with a traverser and a handler
		self.picker = CollisionTraverser()            #Make a traverser
		self.pq     = CollisionHandlerQueue()         #Make a handler
		#Make a collision node for our picker ray
		self.pickerNode = CollisionNode('mouseRay')
		#Attach that node to the camera since the ray will need to be positioned
		#relative to it
		self.pickerNP = camera.attachNewNode(self.pickerNode)
		#Everything to be picked will use bit 1. This way if we were doing other
		#collision we could seperate it
		self.pickerNode.setFromCollideMask(BitMask32.bit(1))
		self.pickerRay = CollisionRay()               #Make our ray
		self.pickerNode.addSolid(self.pickerRay)      #Add it to the collision node
		#Register the ray as something that can cause collisions
		self.picker.addCollider(self.pickerNP, self.pq)
	
	#### TASKS ####
	
	# Checks for incoming data on the connection
	def tskReaderPoll(self, task):
		if self.cReader.dataAvailable():
			datagram = NetDatagram()
			if self.cReader.getData(datagram):
				self.receiveData(datagram)
		return Task.cont
	
	# Runs every frame, checks whether the mouse is highlighting something or another
	def tskMouse(self, task):
		#This task deals with the highlighting and dragging based on the mouse
		
		#First, clear the current highlight
		if self.hiSq:
			self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
			self.hiSq = None
			
		#Check to see if we can access the mouse. We need it to do anything else
		if base.mouseWatcherNode.hasMouse():
			#get the mouse position
			mpos = base.mouseWatcherNode.getMouse()
			
			#Set the position of the ray based on the mouse position
			self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())
			
			#If we are dragging something, set the position of the object
			#to be at the appropriate point over the plane of the board
			if self.dragOrigin:
				#camera, relative instead to render
				#Gets the point described by pickerRay.getOrigin(), which is relative to
				nearPoint = render.getRelativePoint(camera, self.pickerRay.getOrigin())
				#Same thing with the direction of the ray
				nearVec = render.getRelativeVector(camera, self.pickerRay.getDirection())
				self.pieces[self.dragOrigin].obj.setPos(
					PointAtZ(.5, nearPoint, nearVec))

			#Do the actual collision pass (Do it only on the squares for
			#efficiency purposes)
			self.picker.traverse(self.squareRoot)
			if self.pq.getNumEntries() > 0:
				#if we have hit something, sort the hits so that the closest
				#is first, and highlight that node
				self.pq.sortEntries()
				p = tuple(map(int, (self.pq.getEntry(0).getIntoNode().getTag('square')).split()))
				
				if self.pieces[p] and self.pieces[p].color == self.turn == self.player and not self.dragOrigin or self.dragOrigin and self.pieces[self.dragOrigin].isValidMove(p, self.pieces):
					#Set the highlight on the picked square
					self.hiSq = p
					self.squares[self.hiSq].setColor(HIGHLIGHT)
			    
		return Task.cont		
	
	def handleClick(self):
		# Disabled when a dialog box is on-screen. Pay attention to what I'm telling you, user!
		if not self.d:
			if self.dragOrigin:
				self.releasePiece()
			else:
				self.grabPiece()
	
	# Comes from handleClick
	def grabPiece(self):
		#If a square is highlighted and it has a piece, set it to dragging mode
		if self.hiSq and self.pieces[self.hiSq] and self.pieces[self.hiSq].color == self.turn:
			self.dragOrigin = self.hiSq
			self.hiSq = None
	
	def releasePiece(self):
		#Letting go of a piece. If we are not on a square, return it to its original
		#position.
		if self.dragOrigin:   #Make sure we really are dragging something
			if self.hiSq and self.hiSq != self.dragOrigin and self.pieces[self.dragOrigin].isValidMove(self.hiSq, self.pieces):
				
				# Verify that this doesn't put the king in check
				# Make backup of the pieces dictionary
				oldPieces = self.pieces.copy()
				
				self.pieces[self.hiSq] = self.pieces[self.dragOrigin]
				self.pieces[self.dragOrigin] = None
				
				if self.inCheck(self.turn):
					self.pieces = oldPieces
					self.pieces[self.dragOrigin].obj.setPos(SquarePos(self.dragOrigin))
					print "Invalid move -- King is in check"
					
					def closeDialog():
						self.d.removeNode()
					self.d = OkDialog(text="That move would put your King in check!", command=closeDialog)
				else:
					self.pieces = oldPieces
					
					self.makeMove(self.dragOrigin, self.hiSq, dt=0, callback=self.showVisibleSquares).start()
					self.sendMove(self.dragOrigin, self.hiSq)
					self.squares[self.dragOrigin].setColor(SquareColor(self.dragOrigin))
					
					#no longer our turn
					self.turnIndicator['text'] = ''
			else:
				self.pieces[self.dragOrigin].obj.setPos(SquarePos(self.dragOrigin))
				print "Invalid move"
			  
		#We are no longer dragging anything
		self.dragOrigin = False
	
	#### CHESS UPDATES ####
	
	# Moves a piece from one space to another.
	# This should be called to update internal state, whether the piece is already in the correct location or not.
	# Also handles captures.
	def makeMove(self, fr, to, dt=1, callback=None):
		print "Making move %s -> %s" % (str(fr), str(to))
		frP = self.pieces[fr]
		toP = self.pieces[to]
		
		if not frP:
			return False
		if toP and frP.color == toP.color:
			return False
		if not frP.isValidMove(to, self.pieces):
			return False
		
		# Callback function for the movement.
		# Updates pieces' internal state, as well as the true state of the board (self.pieces)
		def updateState():
			self.destroy(toP)
			frP.square = to
			frP.haveMoved = True
			self.pieces[fr] = None
			self.pieces[to] = frP
			self.turn = flip[self.turn]
			
			if self.inCheck(self.player):
				def dismiss(val):
					self.d.removeNode()
				self.d = OkDialog(text="You are in check!", command=dismiss)

		s = Sequence(
			frP.obj.posInterval(dt, self.squares[to].getPos()),
			Func(updateState)
		)
		if callback: s.append(Func(callback))
		return s
	
	# Removes the piece. This method is passed a Piece object, not a location!
	# Possible improvements: Particle effects! :D
	def destroy(self, piece):
		if piece:
			piece.obj.removeNode()
		
	# Determines whether the player specified by "color" is in check at the current time
	# Future improvements: Calculate the same thing for possible future moves (i.e. if I move here am I therefore in check?)
	def inCheck(self, color):
		#find the king
		kingPlace = [p for p in self.pieces if self.pieces[p] and self.pieces[p].color == color and self.pieces[p].model == "models/king"][0]
		for p in self.pieces:
			if self.pieces[p] and self.pieces[p].color != color and self.pieces[p].isValidMove(kingPlace, self.pieces):
				return True
		return False

	# Currently unused, but could be useful in an (extremely primitive) AI in the future.
	# I ran out of time to put it in this version.
	def makeRandomMove(self):
		move = None
		while not move:
			chosenPiece = random.choice([(x,y) for (x,y) in self.pieces if 0 <= x < 8 and 0 <= y < 8 and self.pieces[x,y] and self.pieces[x,y].color == self.turn])
			if not self.pieces[chosenPiece].validMoves(self.pieces):
				continue
			destSquare = random.choice([s for s in self.pieces[chosenPiece].validMoves(self.pieces)])
			move = (chosenPiece, destSquare)
		self.makeMove(*move).start()
	
	#### VISIBILITY UPDATES ####
	
	def isVisible(self, sq):
		return self.squares[sq].getColorScale()[3] == 1.0
		
	# The next two methods deal with hiding and showing the squares of the board.
	def hideSquare(self, sq, dt="default", callback=None):
			
		if self.squares[sq] and self.isVisible(sq):
			if dt == "default": dt = 1.0
			
			par = Parallel(
				LerpFunctionInterval(self.squares[sq].setAlphaScale, toData=0.0, fromData=1.0, duration=dt),
			)
			if self.pieces[sq]:
				par.append(LerpFunctionInterval(self.pieces[sq].obj.setAlphaScale, toData=0.0, fromData=1.0, duration=dt))
			s = Sequence(par)
			if callback: s.append(Func(callback))
			return s
		else:
			s = Sequence()
			if callback: s.append(Func(callback))
			return s
	
	def showSquare(self, sq, dt="default", callback=None):
			
		if self.squares[sq] and not self.isVisible(sq):
			if dt == "default": dt = 1.0
			
			par = Parallel(
				LerpFunctionInterval(self.squares[sq].setAlphaScale, toData=1.0, fromData=0.0, duration=dt),
			)
			if self.pieces[sq]:
				par.append(LerpFunctionInterval(self.pieces[sq].obj.setAlphaScale, toData=1.0, fromData=0.0, duration=dt))
			s = Sequence(par)
			if callback: s.append(Func(callback))
			return s
		else:
			s = Sequence()
			if callback: s.append(Func(callback))
			return s

	# Shows the path that a piece takes on its way IF any part of it is visible to the current player
	def showPathIfVisible(self, fr, to):
		if self.pieces[fr]:
			path = set()
			showSquareSequences = Parallel()
			if self.pieces[fr]:
				path.update(self.pieces[fr].path(to))
			if any(self.isVisible(sq) for sq in path):
				for sq in path:
					showSquareSequences.append(self.showSquare(sq))
			return showSquareSequences
		else:
			return Parallel()
	# Shows the path that a piece takes on its path from its origin to its destination
	def showPath(self, fr, to):
		path = set()
		showSquareSequences = Parallel()
		if self.pieces[fr]:
			path.update(self.pieces[fr].path(to))
		for sq in path:
			showSquareSequences.append(self.showSquare(sq))
		return showSquareSequences
	
	# Updates the board to show only the squares that are visible at the current time.
	def showVisibleSquares(self, dt="default"):
		visibles = defaultdict(lambda: False)
		for p in [(x,y) for (x,y) in self.pieces if 0 <= x < 8 and 0 <= y < 8]:
			if self.pieces[p]:
				if self.pieces[p].color == self.player:
					for s in self.pieces[p].visibleSquares(self.pieces):
						visibles[s] = True

		par = Parallel()
		for s in self.squares:
			if visibles[s]:
				par.append(self.showSquare(s, dt))
			else:
				par.append(self.hideSquare(s, dt))
		par.start()
		return par
	
	#### NETWORK I/O ####
	def sendMove(self, fr, to):
		dg = PyDatagram()
		dg.addUint8(fr[0])
		dg.addUint8(fr[1])
		dg.addUint8(to[0])
		dg.addUint8(to[1])
		
		print "Sent move (%d, %d) -> (%d, %d)" % (fr[0], fr[1], to[0], to[1])
		self.cWriter.send(dg, self.oppConnection)
	
	def receiveData(self, dg):
		dg = PyDatagramIterator(dg)
		fr = (dg.getUint8(), dg.getUint8())
		to = (dg.getUint8(), dg.getUint8())
		print "Received move %s -> %s" % (fr, to)

		def indicate():
			self.turnIndicator['text'] = 'Your turn!'
			self.sfx = loader.loadSfx('audio/ding.wav')
			self.sfx.play()

		seq = Sequence()
		seq.append(self.showPathIfVisible(fr, to))
		seq.append(self.makeMove(fr, to))
		seq.append(Func(indicate))
		seq.append(Func(self.showVisibleSquares))

		seq.start()
Exemplo n.º 12
0
class ChessboardDemo():
    def __init__(self, mission):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        self.mission = mission
        self.player = mission.player
        self.menu = mission.menu
        self.state = 0
        self.frame = DirectFrame(frameColor=(0.1, 0.1, 0.1, 0.5),
                                 frameSize=(-2, 2, -2, 2),
                                 pos=(0, 0, 0))
        self.frame.hide()
        self.dr2 = base.win.makeDisplayRegion()
        #self.dr2.setActive(False)
        # self.frame.attachNewNode(self.dr2.node())
        #self.dr2.setActive(False)
        self.dr2.setClearColorActive(True)
        self.dr2.setClearColor(VBase4(0.1, 0.1, 0.1, 1))
        self.dr2.setClearDepthActive(True)
        # base.win.setClearColor(VBase4(0.1,0.1,0.1,1))
        # base.win.setClearDepthActive()
        # base.win.setClearDepth(1)
        self.render2 = NodePath("render2")
        self.camNode = Camera("cam2")
        self.cam2 = self.render2.attachNewNode(self.camNode)
        self.dr2.setCamera(self.cam2)
        self.cam2.setPosHpr(0, -18, 10, 0, -30, 0)

        # Escape quits
        base.disableMouse()  # Disble mouse camera control
        # camera.setPosHpr(0, -12, 8, 0, -35, 0)  # Set the camera
        self.setupLights()  # Setup default lighting

        # Since we are using collision detection to do picking, we set it up like
        # any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it
        # self.pickerNP = camera.attachNewNode(self.pickerNode)
        self.pickerNP = self.cam2.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        # collision we could separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        # self.picker.showCollisions(render)

        # Now we create the chess board and its pieces

        # We will attach all of the squares to their own root. This way we can do the
        # collision pass just on the squares and save the time of checking the rest
        # of the scene
        self.squareRoot = self.render2.attachNewNode("squareRoot")

        # For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]
        for i in range(64):
            # Load, parent, color, and position the model (a single square
            # polygon)
            # self.squares[i] = loader.loadModel("../res/models/Scene3/Scene3Cat/hall/square")
            self.squares[i] = loader.loadModel(
                "res/models/Scene3/Scene3Cat/hall/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))
            # Set the model itself to be collideable with the ray. If this model was
            # any more complex than a single polygon, you should set up a collision
            # sphere around it instead. But for single polygons this works
            # fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            # Set a tag on the square's node so we can look up what square this is
            # later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            # We will use this variable as a pointer to whatever piece is currently
            # in this square

        # The order of pieces on a chessboard from white's perspective. This list
        # contains the constructor functions for the piece classes defined
        # below
        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        self.pieces[40] = Queen(self, 40, WHITE)
        self.pieces[51] = Bishop(self, 51, PIECEBLACK)
        self.pieces[33] = Knight(self, 33, PIECEBLACK)
        self.pieces[9] = Rook(self, 9, PIECEBLACK)
        self.pieces[20] = Rook(self, 20, PIECEBLACK)
        # This will represent the index of the currently highlited square
        self.hiSq = False
        # This wil represent the index of the square where currently dragged piece
        # was grabbed from
        self.dragging = False

        # self.eight = OnscreenText(text="8", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                           pos=(-0.9, 0.35), scale=.07)
        # self.seven = OnscreenText(text="7", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                           pos=(-0.93, 0.27), scale=.07)
        # self.six = OnscreenText(text="6", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                         pos=(-0.97, 0.18), scale=.07)
        # self.five = OnscreenText(text="5", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                          pos=(-1.02, 0.1), scale=.07)
        # self.four = OnscreenText(text="4", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                          pos=(-1.06, 0.02), scale=.07)
        # self.three = OnscreenText(text="3", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                           pos=(-1.12, -0.1), scale=.07)
        # self.two = OnscreenText(text="2", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                         pos=(-1.16, -0.18), scale=.07)
        # self.one = OnscreenText(text="1", style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
        #                         pos=(-1.23, -0.32), scale=.07)
        x = -0.91
        y = 0.33
        dx = 0.04
        dy = 0.09
        self.eight = OnscreenText(text="8",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(x, y),
                                  scale=.07)
        x -= dx
        y -= dy
        self.seven = OnscreenText(text="7",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(x, y),
                                  scale=.07)
        x -= dx
        y -= dy
        self.six = OnscreenText(text="6",
                                style=1,
                                fg=(1, 1, 1, 1),
                                shadow=(0, 0, 0, 1),
                                pos=(x, y),
                                scale=.07)
        x -= dx
        y -= dy
        self.five = OnscreenText(text="5",
                                 style=1,
                                 fg=(1, 1, 1, 1),
                                 shadow=(0, 0, 0, 1),
                                 pos=(x, y),
                                 scale=.07)
        x -= dx
        y -= dy
        self.four = OnscreenText(text="4",
                                 style=1,
                                 fg=(1, 1, 1, 1),
                                 shadow=(0, 0, 0, 1),
                                 pos=(x, y),
                                 scale=.07)
        x -= dx
        y -= dy
        self.three = OnscreenText(text="3",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  shadow=(0, 0, 0, 1),
                                  pos=(x, y),
                                  scale=.07)
        x -= dx
        y -= dy
        self.two = OnscreenText(text="2",
                                style=1,
                                fg=(1, 1, 1, 1),
                                shadow=(0, 0, 0, 1),
                                pos=(x, y),
                                scale=.07)
        x -= dx
        y -= dy
        self.one = OnscreenText(text="1",
                                style=1,
                                fg=(1, 1, 1, 1),
                                shadow=(0, 0, 0, 1),
                                pos=(x, y),
                                scale=.07)

        self.A = OnscreenText(text="A",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-1.05, -0.5),
                              scale=.07)
        self.B = OnscreenText(text="B",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-0.75, -0.5),
                              scale=.07)
        self.C = OnscreenText(text="C",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-0.45, -0.5),
                              scale=.07)
        self.D = OnscreenText(text="D",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(-0.15, -0.5),
                              scale=.07)
        self.E = OnscreenText(text="E",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(0.15, -0.5),
                              scale=.07)
        self.F = OnscreenText(text="F",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(0.45, -0.5),
                              scale=.07)
        self.G = OnscreenText(text="G",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(0.75, -0.5),
                              scale=.07)
        self.H = OnscreenText(text="H",
                              style=1,
                              fg=(1, 1, 1, 1),
                              shadow=(0, 0, 0, 1),
                              pos=(1.05, -0.5),
                              scale=.07)
        self.A.reparentTo(self.frame)
        self.B.reparentTo(self.frame)
        self.C.reparentTo(self.frame)
        self.D.reparentTo(self.frame)
        self.E.reparentTo(self.frame)
        self.F.reparentTo(self.frame)
        self.G.reparentTo(self.frame)
        self.H.reparentTo(self.frame)
        self.one.reparentTo(self.frame)
        self.two.reparentTo(self.frame)
        self.three.reparentTo(self.frame)
        self.four.reparentTo(self.frame)
        self.five.reparentTo(self.frame)
        self.six.reparentTo(self.frame)
        self.seven.reparentTo(self.frame)
        self.eight.reparentTo(self.frame)
        self.hide()
        # Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        base.accept("mouse1", self.grabPiece)  # left-click grabs a piece
        base.accept("mouse1-up", self.releasePiece)  # releasing places it
        base.accept("escape", self.hide)

    def hide(self):
        self.frame.hide()
        self.dr2.setActive(False)
        self.A.hide()
        self.B.hide()
        self.C.hide()
        self.D.hide()
        self.E.hide()
        self.F.hide()
        self.G.hide()
        self.H.hide()
        self.one.hide()
        self.two.hide()
        self.three.hide()
        self.four.hide()
        self.five.hide()
        self.six.hide()
        self.seven.hide()
        self.eight.hide()
        base.accept("escape", self.menu.game.pauseGame)
        base.accept("mouse1", self.player.__setattr__, ["LeftButton", 1])
        base.accept("mouse1-up", self.player.__setattr__, ["LeftButton", 0])
        self.mission.resume()
        self.player.initTask()

    def show(self):
        self.frame.show()
        self.dr2.setActive(True)
        self.A.show()
        self.B.show()
        self.C.show()
        self.D.show()
        self.E.show()
        self.F.show()
        self.G.show()
        self.H.show()
        self.one.show()
        self.two.show()
        self.three.show()
        self.four.show()
        self.five.show()
        self.six.show()
        self.seven.show()
        self.eight.show()
        base.accept("escape", self.hide)

    # This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def mouseTask(self, task):
        # This task deals with the highlighting and dragging based on the mouse

        # First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

        # Check to see if we can access the mouse. We need it to do anything
        # else
        if base.mouseWatcherNode.hasMouse():
            # get the mouse position
            mpos = base.mouseWatcherNode.getMouse()

            # Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(self.camNode, mpos.getX(), mpos.getY())

            # If we are dragging something, set the position of the object
            # to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                # Gets the point described by pickerRay.getOrigin(), which is relative to
                # camera, relative instead to render
                # nearPoint = render.getRelativePoint(
                #     camera, self.pickerRay.getOrigin())
                nearPoint = render.getRelativePoint(self.cam2,
                                                    self.pickerRay.getOrigin())
                # Same thing with the direction of the ray
                # nearVec = render.getRelativeVector(
                #     camera, self.pickerRay.getDirection())
                nearVec = render.getRelativeVector(
                    self.cam2, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

            # Do the actual collision pass (Do it only on the squares for
            # efficiency purposes)
            self.picker.traverse(self.squareRoot)
            if self.pq.getNumEntries() > 0:
                # if we have hit something, sort the hits so that the closest
                # is first, and highlight that node
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                # Set the highlight on the picked square
                self.squares[i].setColor(HIGHLIGHT)
                self.hiSq = i

        return Task.cont

    def grabPiece(self):
        # If a square is highlighted and it has a piece, set it to dragging
        # mode
        if self.hiSq is not False and self.pieces[self.hiSq]:
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        # Letting go of a piece. If we are not on a square, return it to its original
        # position. Otherwise, swap it with the piece in the new square
        # Make sure we really are dragging something

        if self.dragging is not False:
            # We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
            else:
                if self.state == 0:
                    if self.dragging == 51 and self.hiSq == 58:
                        self.swapPieces(self.dragging, self.hiSq)
                        self.swapPieces(40, 32)
                        self.state = self.state + 1
                        self.mission.manager.GoodsIta[
                            'studydoor_box'].state = 'unlockedOpen'
                        self.mission.manager.GoodsIta[
                            'studydoor_box'].OpenDoor()
                        self.menu.infoDialog.show()
                        self.menu.infoLabel['text'] = '似乎传来咔嚓一声开锁的声音'
                        self.mission.skip()
                        self.hide()
                    else:
                        self.pieces[self.dragging].obj.setPos(
                            SquarePos(self.dragging))
                        if self.dragging != self.hiSq:
                            self.player.EROSION += 10
                        self.player.erosionUpdateTemp()

                elif self.state == 1:
                    if self.dragging == 33 and self.hiSq == 18:
                        self.swapPieces(self.dragging, self.hiSq)
                        self.state = self.state + 1
                        self.mission.manager.GoodsIta[
                            'chessdoor_box'].state = 'unlockedOpen'
                        self.mission.manager.GoodsIta[
                            'chessdoor_box'].OpenDoor()
                        self.mission.menu.infoDialog.show()
                        self.mission.menu.infoLabel['text'] = '棋盘上弹出一张纸条「pass。这又不是\n' \
                                                              '真的国际象棋,我选择PASS你又能怎样?\n' \
                                                              '你是无法将死我的。」'
                        self.mission.skip()
                        self.hide()
                    else:
                        self.pieces[self.dragging].obj.setPos(
                            SquarePos(self.dragging))
                        if self.dragging != self.hiSq:
                            self.player.EROSION += 10
                        self.player.erosionUpdateTemp()
                elif self.state == 2:
                    if self.dragging == 20 and self.hiSq == 36:
                        self.swapPieces(self.dragging, self.hiSq)
                        self.state = self.state + 1
                        self.mission.manager.GoodsIta[
                            'exit_box'].state = 'unlockedOpen'
                        self.mission.menu.infoDialog.show()
                        self.mission.menu.infoLabel[
                            'text'] = '可恶 失策了……这里居然…还有一个城堡么…'
                        self.mission.skip()
                        if self.mission.hiddenState:
                            self.mission.end('hiddenEnd')
                        self.hide()
                    else:
                        self.pieces[self.dragging].obj.setPos(
                            SquarePos(self.dragging))
                        if self.dragging != self.hiSq:
                            self.player.EROSION += 10
                        self.player.erosionUpdateTemp()
                elif self.state == 3:
                    self.pieces[self.dragging].obj.setPos(
                        SquarePos(self.dragging))
        # We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))

    def initPos(self, state):
        if state == 0:
            self.pieces[40] = Queen(self, 40, WHITE)
            self.pieces[51] = Bishop(self, 51, PIECEBLACK)
            self.pieces[33] = Knight(self, 33, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[20] = Rook(self, 20, PIECEBLACK)
        elif state == 1:
            self.pieces[32] = Queen(self, 32, WHITE)
            self.pieces[58] = Bishop(self, 58, PIECEBLACK)
            self.pieces[33] = Knight(self, 33, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[20] = Rook(self, 20, PIECEBLACK)
        elif state == 2:
            self.pieces[32] = Queen(self, 32, WHITE)
            self.pieces[58] = Bishop(self, 58, PIECEBLACK)
            self.pieces[18] = Knight(self, 18, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[20] = Rook(self, 20, PIECEBLACK)
        elif state == 3:
            self.pieces[32] = Queen(self, 32, WHITE)
            self.pieces[58] = Bishop(self, 58, PIECEBLACK)
            self.pieces[18] = Knight(self, 18, PIECEBLACK)
            self.pieces[9] = Rook(self, 9, PIECEBLACK)
            self.pieces[36] = Rook(self, 36, PIECEBLACK)
Exemplo n.º 13
0
class ChessboardDemo(ShowBase):
    def __init__(self, client):
        ShowBase.__init__(self)
        self.client = client

        # This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking",
                                  style=1, fg=(1, 1, 1, 1), shadow=(0, 0, 0, 1),
                                  pos=(0.8, -0.95), scale = .07)
        self.escapeEvent = OnscreenText(
            text="ESC: Quit", parent=base.a2dTopLeft,
            style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.1),
            align=TextNode.ALeft, scale = .05)
        self.mouse1Event = OnscreenText(
            text="Left-click and drag: Pick up and drag piece",
            parent=base.a2dTopLeft, align=TextNode.ALeft,
            style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.16), scale=.05)

        self.accept('escape', sys.exit)  # Escape quits
        self.disableMouse()  # Disable mouse camera control
        camera.setPosHpr(0, -12, 8, 0, -35, 0)  # Set the camera
        self.setupLights()  # Setup default lighting

        # Since we are using collision detection to do picking, we set it up
        # like any other collision detection system with a traverser and a
        # handler
        self.picker = CollisionTraverser()  # Make a traverser
        self.pq = CollisionHandlerQueue()  # Make a handler
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be
        # positioned relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing
        # other collisions we could separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  # Make our ray
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        # self.picker.showCollisions(render)

        # Now we create the chess board and its pieces

        # We will attach all of the squares to their own root. This way we can
        # do the collision pass just on the squares and save the time of
        # checking the rest of the scene
        self.square_root = render.attachNewNode("square_root")

        # For each square
        self.squares = [None for i in range(64)]
        for i in range(64):
            # Load, parent, color, and position the model (a single square
            # polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.square_root)
            self.squares[i].setPos(square_pos(i))
            self.squares[i].setColor(square_color(i))
            # Set the model itself to be collidable with the ray. If this model
            # is any more complex than a single polygon, you should set up a
            # collision sphere around it instead. But for single polygons this
            # works fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            # Set a tag on the square's node so we can look up what square it is
            # later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            # We will use this variable as a pointer to whatever piece is
            # currently in this square

        # This will represent the index of the currently highlighted square
        self.hiSq = False
        # Represents the index of the square where currently dragged piece
        # was grabbed from
        self.dragging = False

        # Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.grab_piece)  # left-click grabs a piece
        self.accept("mouse1-up", self.release_piece)  # releasing places it

    def swap_pieces(self, fr, to):
        # Get the objects from the square references
        fr_model, fr_do = self.model_at(fr), self.piece_at(fr)
        to_model, to_do = self.model_at(to), self.piece_at(to)

        # Handle the from model
        fr_model.setPos(square_pos(to))
        fr_do.square = to
        self.client._save(fr_do)

        # Handle the to model if it exists
        if to_do:
            to_model.setPos(square_pos(fr))
            to_do.square = fr
            self.client._save(to_do)

    def mouseTask(self, task):
        # This task deals with the highlighting and dragging based on the mouse

        # First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(square_color(self.hiSq))
            self.hiSq = False

        # Check to see if we can access the mouse. We need it to do anything
        # else
        if self.mouseWatcherNode.hasMouse():
            # get the mouse position
            mouse_pos = self.mouseWatcherNode.getMouse()

            # Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(
                self.camNode, mouse_pos.getX(), mouse_pos.getY())

            # If we are dragging something, set the position of the object
            # to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                # Gets the point described by pickerRay.getOrigin(), which is
                # relative to camera, relative instead to render
                nearPoint = render.getRelativePoint(
                    camera, self.pickerRay.getOrigin())
                # Same thing with the direction of the ray
                nearVec = render.getRelativeVector(
                    camera, self.pickerRay.getDirection())
                model = self.model_at(self.dragging)
                model.setPos(
                    point_at_z(.5, nearPoint, nearVec))

            # Do the actual collision pass (Do it only on the squares for
            # efficiency purposes)
            # noinspection PyArgumentList
            self.picker.traverse(self.square_root)
            if self.pq.getNumEntries() > 0:
                # if we have hit something, sort the hits so that the closest
                # is first, and highlight that node
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                # Set the highlight on the picked square
                self.squares[i].setColor(HIGHLIGHT)
                self.hiSq = i

        return Task.cont

    def piece_at(self, square):
        for p in self.client.objects:
            if p.square == square:
                return p
        return None

    def model_at(self, square):
        for p in self.client.objects:
            if p.square == square:
                return self.client.models[p.id]
        return None

    def grab_piece(self):
        # If a square is highlighted and it has a piece, set it to dragging
        # mode
        if self.hiSq is not False and self.piece_at(self.hiSq):
            self.dragging = self.hiSq
            self.hiSq = False

    def release_piece(self):
        # If we are not on a square, return it to its original position.
        # Otherwise, swap it with the piece in the new square
        # Make sure we really are dragging something
        if self.dragging is not False:
            # We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                model = self.model_at(self.dragging)
                model.setPos(
                    square_pos(self.dragging))
            else:
                # Otherwise, swap the pieces
                self.swap_pieces(self.dragging, self.hiSq)

        # We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  # This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor((.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(LVector3(0, 45, -45))
        directionalLight.setColor((0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Exemplo n.º 14
0
class World(DirectObject):
    def __init__(self):
        #This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Panda3D: Tutorial - Mouse Picking",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  pos=(0.8, -0.95),
                                  scale=.07)
        self.escapeEvent = OnscreenText(text="ESC: Quit",
                                        style=1,
                                        fg=(1, 1, 1, 1),
                                        pos=(-1.3, 0.95),
                                        align=TextNode.ALeft,
                                        scale=.05)
        self.mouse1Event = OnscreenText(
            text="Left-click and drag: Pick up and drag piece",
            style=1,
            fg=(1, 1, 1, 1),
            pos=(-1.3, 0.90),
            align=TextNode.ALeft,
            scale=.05)

        self.accept('escape', sys.exit)  #Escape quits
        base.disableMouse()  #Disble mouse camera control
        camera.setPosHpr(0, -13.75, 6, 0, -25, 0)  #Set the camera
        self.setupLights()  #Setup default lighting

        #Since we are using collision detection to do picking, we set it up like
        #any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  #Make a traverser
        self.pq = CollisionHandlerQueue()  #Make a handler
        #Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  #Make our ray
        self.pickerNode.addSolid(self.pickerRay)  #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        #Now we create the chess board and its pieces

        #We will attach all of the squares to their own root. This way we can do the
        #collision pass just on the sqaures and save the time of checking the rest
        #of the scene
        self.squareRoot = render.attachNewNode("squareRoot")

        #For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]
        for i in range(64):
            #Load, parent, color, and position the model (a single square polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos(i))
            self.squares[i].setColor(SquareColor(i))
            #Set the model itself to be collideable with the ray. If this model was
            #any more complex than a single polygon, you should set up a collision
            #sphere around it instead. But for single polygons this works fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            #Set a tag on the square's node so we can look up what square this is
            #later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            #We will use this variable as a pointer to whatever piece is currently
            #in this square

        #The order of pieces on a chessboard from white's perspective. This list
        #contains the constructor functions for the piece classes defined below
        pieceOrder = (Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook)

        for i in range(8, 16):
            #Load the white pawns
            self.pieces[i] = Pawn(i, WHITE)
        for i in range(48, 56):
            #load the black pawns
            self.pieces[i] = Pawn(i, PIECEBLACK)
        for i in range(8):
            #Load the special pieces for the front row and color them white
            self.pieces[i] = pieceOrder[i](i, WHITE)
            #Load the special pieces for the back row and color them black
            self.pieces[i + 56] = pieceOrder[i](i + 56, PIECEBLACK)

        #This will represent the index of the currently highlited square
        self.hiSq = False
        #This wil represent the index of the square where currently dragged piece
        #was grabbed from
        self.dragging = False

        #Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        self.accept("mouse1", self.grabPiece)  #left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  #releasing places it

    #This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            self.pieces[fr].square = fr
            self.pieces[fr].obj.setPos(SquarePos(fr))
        if self.pieces[to]:
            self.pieces[to].square = to
            self.pieces[to].obj.setPos(SquarePos(to))

    def mouseTask(self, task):
        #This task deals with the highlighting and dragging based on the mouse

        #First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

        #Check to see if we can access the mouse. We need it to do anything else
        if base.mouseWatcherNode.hasMouse():
            #get the mouse position
            mpos = base.mouseWatcherNode.getMouse()

            #Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            #If we are dragging something, set the position of the object
            #to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                #Gets the point described by pickerRay.getOrigin(), which is relative to
                #camera, relative instead to render
                nearPoint = render.getRelativePoint(camera,
                                                    self.pickerRay.getOrigin())
                #Same thing with the direction of the ray
                nearVec = render.getRelativeVector(
                    camera, self.pickerRay.getDirection())
                self.pieces[self.dragging].obj.setPos(
                    PointAtZ(.5, nearPoint, nearVec))

            #Do the actual collision pass (Do it only on the squares for
            #efficiency purposes)
            self.picker.traverse(self.squareRoot)
            if self.pq.getNumEntries() > 0:
                #if we have hit something, sort the hits so that the closest
                #is first, and highlight that node
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                #Set the highlight on the picked square
                self.squares[i].setColor(HIGHLIGHT)
                self.hiSq = i

        return Task.cont

    def grabPiece(self):
        #If a square is highlighted and it has a piece, set it to dragging mode
        if (self.hiSq is not False and self.pieces[self.hiSq]):
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        #Letting go of a piece. If we are not on a square, return it to its original
        #position. Otherwise, swap it with the piece in the new square
        if self.dragging is not False:  #Make sure we really are dragging something
            #We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                self.pieces[self.dragging].obj.setPos(SquarePos(self.dragging))
            else:
                #Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)

        #We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  #This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 45, -45))
        directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Exemplo n.º 15
0
class World(ShowBase):

	def __init__(self):
		ShowBase.__init__(self)

		#PStatClient.connect()

		#self.lookPoint = NodePath(PandaNode("floater"))
		self.lookPoint = self.loader.loadModel("models/cone")
		self.lookPoint.reparentTo(render)

		self.menu = StartMenu(self)
		#self.bar = Bar()

		#self.messenger.toggleVerbose()


		#sys.exit()
		#pdb.set_trace()

		# Window change event handler
		#self.windowEventSetup()



	def setup(self):

		print("Init Levels...")
		self.initLevels()

		print("Init World...")
		self.initWorld("yard")

		print("Init Items...")
		self.initItems()

		print("Init Actors...")
		self.initActors()

		print("Init GUI ...")
		self.initGui()

		print("Init Lights...")
		self.initLights()

		print("Init Collisions...")
		self.initCollision()

		print("Init Tasks...")
		self.initTasks()

		print("Launching World")

		# Accept the control keys
		#self.accept("h", self.crono.start)

	def initItems(self):

		with open('items/items.json') as items_file:
			self.items = json.load(items_file)

	def initActors(self):

		self.player = Player(self, 20, 10, 10, 10, 10, 10) #app, hp, mana, strength, dexterity, vigor, magic):

		self.enemies = []
		self.npcs = []

		#Creating AI World

		self.AIworld = AIWorld(render)

		"""self.foe1 = Enemy(self, 100, 50, 5, 2, "bug") #(self, app, hp, mana, speed, attackSpeed, name):
		self.nasgul = Enemy(self, 100, 50, 5, 2, "nasgul")

		self.npc1 = Npc(self, 100, 50, 5, 2, "guy2")
		self.npc2 = Npc(self, 100, 50, 5, 2, "ralph")

		self.enemies.append(self.foe1)
		self.enemies.append(self.nasgul)

		self.npcs.append(self.npc1)
		self.npcs.append(self.npc2)"""


	def initGui(self):

		# Load the models.

		self.inventory = Inventory(self)
		self.status = Status(self)
		self.skills = Skills(self)

		#self.statusBar = self.loader.loadModel("models/statusbar")


		##self.statusBar.setDepthTest(True)
		#self.statusBar.setDepthWrite(True)


		# Reparent the model to render2d.
		#self.statusBar.reparentTo(self.render2d)


		#self.statusBar.setScale(0.15, 0.15, 0.15)
		#self.statusBar.setPos(-0.95, 0, 0.65)


		#self.crono = Crono(self)
		##self.cursorpos = CursorPos(self)
		#self.playerpos = PlayerPos(self)

		#self.crono.draw(0.7, -0.85)
		#self.cursorpos.draw(0.0, -0.85)
		#self.playerpos.draw(-0.7, -0.85)


		self.accept("i", self.inventory.toggle)
		self.accept("c", self.status.toggle)
		self.accept("k", self.skills.toggle)

	def initTasks(self):

		#self.taskMgr.add(self.crono.task, "cronoTask")
		#self.taskMgr.add(self.cursorpos.task, "cursorposTask")

		###self.taskMgr.add(self.playerpos.task, "playerposTask")

		self.taskMgr.add(self.checkCollision, "collisionTask")

		#self.taskMgr.add(self.player.update, "updateTask")
		self.taskMgr.add(self.player.move, "moveTask")
		self.taskMgr.add(self.player.updateCamera, "playerCameraTask",priority=1)
		"""
		#self.taskMgr.add(self.foe1.update, "bugTask",priority=1)
		#self.taskMgr.add(self.nasgul.update, "nasgulTask",priority=1)

		#self.taskMgr.add(self.npc1.update, "npc1Task",priority=1)
		#self.taskMgr.add(self.npc2.update, "npc2Task",priority=1)
		"""
		self.taskMgr.add(self.update, 'update')

	def initLights(self):
		# Create some lighting

		#self.environ.ls()

		#print(self.environ.findAllMatches("**/Spot"))

		ambientLight = AmbientLight("ambientLight")
		ambientLight.setColor(Vec4(0.8, 0.8, 0.8, 0.65))

		"""
		directionalLight = DirectionalLight("directionalLight")
		directionalLight.setDirection(Vec3(-10, -10, 5))
		directionalLight.showFrustum()
		directionalLight.setColor(Vec4(1, 1, 1, 1))
		directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
		dirnp = render.attachNewNode(directionalLight)
		dirnp.setPos(10, 0, 6)
		"""

		plight1 = PointLight('plight1')
		plight1.setColor(VBase4(1, 1, 1, 1))
		plight1.showFrustum()
		#plight1.setShadowCaster(True)
		plnp1 = render.attachNewNode(plight1)
		plnp1.setPos(26.71, -33.2, 26)

		plight2 = PointLight('plight2')
		plight2.setColor(VBase4(1, 1, 1, 1))
		plight2.showFrustum()
		plnp2 = render.attachNewNode(plight2)
		plnp2.setPos(-25, 25, 25)

		slight = Spotlight('slight')
		slight.setColor(VBase4(1, 1, 1, 1))
		lens = PerspectiveLens()
		lens.setFilmSize(1, 1)  # Or whatever is appropriate for your scene
		slight.setLens(lens)
		slight.setShadowCaster(True, 512, 512)
		slight.showFrustum()
		slnp = render.attachNewNode(slight)
		slnp.setPos(0, 0, 100)

		slnp.lookAt(Vec3(0,0,0))

		render.setLight(slnp)
		render.setLight(plnp1)
		render.setLight(plnp2)
		#render.setLight(render.attachNewNode(ambientLight))

		#render.setLight(dirnp)

		render.setShaderAuto()

		#render.setLight(render.attachNewNode(directionalLight))

		"""
		self.light = render.attachNewNode(Spotlight("Spot"))
		self.light.node().setScene(render)
		self.light.node().setShadowCaster(True)
		self.light.node().showFrustum()
		self.light.node().getLens().setFov(40)
		self.light.node().getLens().setNearFar(10,100)
		render.setLight(self.light)
		"""

	def initLevels(self):
		with open('levels/levels.json') as levels_file:
			self.levels = json.load(levels_file)

	def initWorld(self, level):

		self.environ = self.loader.loadModel(self.levels["levels"][level]["model"])
		#self.environ.setScale(20, 20, 20)
		#self.environ.setHpr(0, 0, 0)
		self.environ.setPos(0, 0, 0)

		self.playerStartPos = self.environ.find("**/startPos").getPos()

		# Reparent the model to render

		self.environ.reparentTo(render)
		#self.environ.ls()
		self.accept("q", self.changeMap)

	def destroyWorld(self):

		self.environ.detachNode()
		self.environ.removeNode()

	def changeMap(self):#, levelName):
		self.destroyWorld()
		self.initWorld("yard")

	def update(self, task):
		dt = globalClock.getDt()

		self.AIworld.update()
		return task.cont

	def setKey(self, key, value):
		self.keyMap[key] = value

	def windowEventSetup( self ):
		# accept the window event's
		self.accept( 'window-event', self.windowEventHandler)
		# create a window event yourself
		#messenger.send( 'window-event', [self.win] )

	def windowEventHandler( self, window=None ):
		wp = window.getProperties()

		print("Window changed")
		print("X = %s" % wp.getXSize())
		print("Y = %s" % wp.getYSize())
		self.setResolution( wp.getXSize(), wp.getYSize() )

	def setResolution( self, w, h ):
		wp = WindowProperties()
		wp.setSize( w, h )

		if os.name == 'posix':
			self.openMainWindow()
			self.graphicsEngine.openWindows()
		self.win.requestProperties( wp )

	# Define a procedure to move the camera.
	def spinCameraTask(self, task):
		angleDegrees = task.time * 6.0
		angleRadians = angleDegrees * (pi / 180.0)
		self.camera.setPos(40 * sin(angleRadians), -10.0 * cos(angleRadians), 3)
		self.camera.setHpr(angleDegrees, 0, 0)
		return Task.cont

	def initCollision(self):


		self.enemyGroundRay = []
		self.enemyGroundCol = []
		self.enemyGroundColNp = []
		self.enemyGroundHandler = []

		self.npcGroundRay = []
		self.npcGroundCol = []
		self.npcGroundColNp = []
		self.npcGroundHandler = []

		self.cTrav = CollisionTraverser()


		self.playerGroundRay = CollisionRay()
		self.playerGroundRay.setOrigin(0, 0, 9)
		self.playerGroundRay.setDirection(0, 0, -1)
		self.playerGroundCol = CollisionNode('playerRay')
		self.playerGroundCol.addSolid(self.playerGroundRay)
		self.playerGroundCol.setFromCollideMask(CollideMask.bit(0))
		self.playerGroundCol.setIntoCollideMask(CollideMask.allOff())
		self.playerGroundColNp = self.player.moveFloater.attachNewNode(self.playerGroundCol)
		self.playerGroundHandler = CollisionHandlerQueue()
		self.cTrav.addCollider(self.playerGroundColNp, self.playerGroundHandler)

		self.mouseGroundRay = CollisionRay()
		self.mouseGroundRay.setOrigin(0, 0, 9)
		self.mouseGroundRay.setDirection(0, 0, -1)
		self.mouseGroundCol = CollisionNode('mouseRay')
		self.mouseGroundCol.addSolid(self.mouseGroundRay)
		self.mouseGroundCol.setFromCollideMask(CollideMask.bit(0))
		self.mouseGroundCol.setIntoCollideMask(CollideMask.allOff())
		self.mouseGroundColNp = self.camera.attachNewNode(self.mouseGroundCol)
		self.mouseGroundHandler = CollisionHandlerQueue()
		self.cTrav.addCollider(self.mouseGroundColNp, self.mouseGroundHandler)

		# Uncomment this line to see the collision rays
		#self.playerGroundColNp.show()
		#self.mouseGroundColNp.show()

		# Uncomment this line to show a visual representation of the
		# collisions occuring
		#self.cTrav.showCollisions(render)


		i = 0
		for enemy in self.enemies:

			self.enemyGroundRay.append(CollisionRay())
			self.enemyGroundRay[i].setOrigin(0, 0, 9)
			self.enemyGroundRay[i].setDirection(0, 0, -1)

			self.enemyGroundCol.append(CollisionNode('%sRay' % enemy.name))
			self.enemyGroundCol[i].addSolid(self.enemyGroundRay[i])
			self.enemyGroundCol[i].setFromCollideMask(CollideMask.bit(0))
			self.enemyGroundCol[i].setIntoCollideMask(CollideMask.allOff())

			self.enemyGroundColNp.append(enemy.enemyActor.attachNewNode(self.enemyGroundCol[i]))
			self.enemyGroundHandler.append(CollisionHandlerQueue())
			self.cTrav.addCollider(self.enemyGroundColNp[i], self.enemyGroundHandler[i])

			#self.enemyGroundColNp.show()
			i += 1

		i = 0
		for npc in self.npcs:

			self.npcGroundRay.append(CollisionRay())
			self.npcGroundRay[i].setOrigin(0, 0, 9)
			self.npcGroundRay[i].setDirection(0, 0, -1)

			self.npcGroundCol.append(CollisionNode('%sRay' % npc.name))
			self.npcGroundCol[i].addSolid(self.npcGroundRay[i])
			self.npcGroundCol[i].setFromCollideMask(CollideMask.bit(0))
			self.npcGroundCol[i].setIntoCollideMask(CollideMask.allOff())

			self.npcGroundColNp.append(npc.npcActor.attachNewNode(self.npcGroundCol[i]))
			self.npcGroundHandler.append(CollisionHandlerQueue())
			self.cTrav.addCollider(self.npcGroundColNp[i], self.npcGroundHandler[i])

			#self.npcGroundColNp.show()
			i += 1

	def checkCollision(self, task):

		startpos = self.player.moveFloater.getPos()

		entries = list(self.playerGroundHandler.getEntries())
		entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

		for entry in entries:
			if entry > 0 and entries[0].getIntoNode().getName() == "Ground":
				self.player.moveFloater.setZ(entry.getSurfacePoint(render).getZ())
			else:
				self.player.moveFloater.setPos(startpos)

		if self.mouseWatcherNode.hasMouse():

			mpos = self.mouseWatcherNode.getMouse()

			self.mouseGroundRay.setFromLens(self.camNode, mpos.getX(), mpos.getY())


			nearPoint = render.getRelativePoint(self.camera, self.mouseGroundRay.getOrigin())
			nearVec = render.getRelativeVector(self.camera, self.mouseGroundRay.getDirection())
			try:
				self.lookPoint.setPos(PointAtZ(self.player.moveFloater.getZ(), nearPoint, nearVec))
			except:
				pass

		i = 0

		for enemy in self.enemies:
			startpos = enemy.enemyActor.getPos()

			entries = list(self.enemyGroundHandler[i].getEntries())
			entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

			for entry in entries:
				if entry > 0: # and entries[0].getIntoNode().getName() == "Ground":
					enemy.enemyActor.setZ(entry.getSurfacePoint(render).getZ())
				else:
					enemy.enemyActor.setPos(startpos)
			i += 1


		i = 0
		for npc in self.npcs:
			startpos = npc.npcActor.getPos()

			entries = list(self.npcGroundHandler[i].getEntries())
			entries.sort(key=lambda x: x.getSurfacePoint(render).getZ())

			for entry in entries:
				if entry > 0: # and entries[0].getIntoNode().getName() == "Ground":
					npc.npcActor.setZ(entry.getSurfacePoint(render).getZ())
				else:
					npc.npcActor.setPos(startpos)
			i += 1

		return task.cont
Exemplo n.º 16
0
class World(DirectObject):
    mySound = base.loader.loadSfx("trial.mp3")

    #Used for adding a virus at a randomly generated position
    def random_vgen(self):
        print 'I am in random'
        for i in range(0, 5):

            self.a[random.randint(0, 7)][random.randint(0, 7)] = 1

    def initializer(self, level):

        self.turns = 0

        ##   Level Definition

        def levelone():
            self.a[4][4] = 1
            self.a[4][5] = 1
            self.a[4][6] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[4][6] = 1
            self.a[5][5] = 1

        def leveltwo():
            self.a[4][3] = 1
            self.a[4][5] = 1
            self.a[4][7] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[2][2] = 1
            self.a[5][3] = 1
            self.a[1][2] = 1

        def levelthree():
            self.a[4][4] = 1
            self.a[4][5] = 1
            self.a[4][6] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[4][6] = 1
            self.a[5][5] = 1
            self.a[4][3] = 1
            self.a[4][5] = 1
            self.a[4][7] = 1
            self.a[5][2] = 1
            self.a[3][5] = 1
            self.a[2][2] = 1
            self.a[5][3] = 1

        options = {1: levelone, 2: leveltwo, 3: levelthree}

        options[level]()

        print self.a
        temp = []
        count = 0
        for element in reversed(self.a):
            for ele in element:
                #print 'cheking element is 1 : ' + str(ele)
                if ele == 1:
                    temp.append(count)
                    self.pieces[count] = Monster(count, WHITE)
                    #self.squares[count].setColor(HIGHLIGHT)
                count = count + 1
        self.list = temp

    def showscore(self):
        try:
            self.score.destroy()
        except:
            pass
        self.score = OnscreenText(text='Number of Turns : %s' % (self.turns),
                                  pos=(0.5, 0.95),
                                  scale=0.07,
                                  mayChange=True)

    def menuscreen(self):

        # Callback function to set  text
        def setText():
            b.destroy()
            helptext.destroy()

        # Add button
        b = DirectButton(text=("START", "START", "START", "disabled"),
                         scale=0.15,
                         command=setText,
                         pos=(0, 0, 0.85))

        helptext = OnscreenText(text='''
    STORY:
    Hello Mad Scientist!
    You are so close to finding the cure to aids!
    You understood the behaviour and can finally manipulate the virus to kill itself!
    But time is running out!
    You have a red and white blood cell sample infected with AIDS Virus.

    INSTRUCTIONS:
    The AIDS Virus obeys the Conway's Game of Life. Who would have guessed?
    1.  If virus is surrounded by more than 3 viruses, it dies of suffocation
    2.  If virus is surrounded by less than 2 viruses, it dies of underpopulation
    3.  If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned due to breeding.

    AIM:
    To kill all the viruses, by moving one of them every turn.

    ''',
                                pos=(-0.90, 0.72),
                                frame=(123, 123, 123, 1),
                                wordwrap=25,
                                align=TextNode.ALeft,
                                bg=(0.23, 0.243, 0.13, 0.9))

    def endscreen(self):
        def restart():
            taskMgr.remove(self.mouseTask)
            for i in range(64):
                self.squares[i].setColor(SquareColor(i))
            scorecard.destroy()
            restartb.destroy()
            end.destroy()
            nextlevelb.destroy()
            self.reference.destroy()
            self.mySound.stop()
            try:
                self.score.destroy()
            except:
                pass
            print 'restarting'
            print self.a
            print self.list

            World()

        def quitgame():
            sys.exit()

        def nextLevel():
            self.currlevel = self.currlevel + 1
            nextlevelb.destroy()
            scorecard.destroy()
            restartb.destroy()
            end.destroy()
            self.score.destroy()
            self.initializer(self.currlevel)

        # Add button

        scorecard = OnscreenText(text='You finished it in %s turns! ' %
                                 (self.turns),
                                 frame=(123, 123, 123, 0),
                                 wordwrap=25,
                                 bg=(0.2, 0, 0.8, 1))

        nextlevelb = DirectButton(text=("NEXT LEVEL", "NEXT LEVEL",
                                        "NEXT LEVEL", "disabled"),
                                  scale=0.15,
                                  command=nextLevel,
                                  pos=(0, 0, -0.15))
        restartb = DirectButton(text=("RESTART", "RESTART", "RESTART",
                                      "disabled"),
                                scale=0.15,
                                command=restart,
                                pos=(0, 0, -0.35))
        end = DirectButton(text=("QUIT", "QUIT", "QUIT", "disabled"),
                           scale=0.15,
                           command=quitgame,
                           pos=(0, 0, -0.55))
        if self.currlevel == self.maxlevel:
            nextlevelb.destroy()

    def __init__(self):
        #music

        self.mySound.play()

        print 'I am being initialized'

        self.menuscreen()
        self.list = []
        self.turns = 0
        self.maxlevel = 3
        self.currlevel = 1
        self.a = [[0 for x in range(8)] for y in range(8)]

        #This code puts the standard title and instruction text on screen
        self.title = OnscreenText(text="Game of Life : Help in ending AIDS!",
                                  style=1,
                                  fg=(1, 1, 1, 1),
                                  pos=(0, -0.95),
                                  scale=.07)
        self.escapeEvent = OnscreenText(text="ESC: Quit",
                                        style=1,
                                        fg=(1, 1, 1, 1),
                                        pos=(-1.3, 0.95),
                                        align=TextNode.ALeft,
                                        scale=.05)
        ##    self.mouse1Event = OnscreenText(
        ##      text="Left-click and drag: Pick up virus and drag it to a new bloodcell",
        ##      style=1, fg=(1,1,1,1), pos=(-1.3, 0.90),
        ##      align=TextNode.ALeft, scale = .05)
        ##

        self.accept('escape', sys.exit)  #Escape quits

        base.disableMouse()  #Disble mouse camera control
        camera.setPosHpr(0, -13.75, 6, 0, -25, 0)  #Set the camera
        self.setupLights()  #Setup default lighting

        #Since we are using collision detection to do picking, we set it up like
        #any other collision detection system with a traverser and a handler
        self.picker = CollisionTraverser()  #Make a traverser
        self.pq = CollisionHandlerQueue()  #Make a handler
        #Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        #Attach that node to the camera since the ray will need to be positioned
        #relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        #Everything to be picked will use bit 1. This way if we were doing other
        #collision we could seperate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()  #Make our ray
        self.pickerNode.addSolid(self.pickerRay)  #Add it to the collision node
        #Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        #We will attach all of the squares to their own root. This way we can do the
        #collision pass just on the sqaures and save the time of checking the rest
        #of the scene
        self.squareRoot = render.attachNewNode("squareRoot")

        #For each square
        self.squares = [None for i in range(64)]
        self.pieces = [None for i in range(64)]

        for i in range(64):
            #Load, parent, color, and position the model (a single square polygon)
            self.squares[i] = loader.loadModel("models/square")
            self.squares[i].reparentTo(self.squareRoot)
            self.squares[i].setPos(SquarePos1(i))
            self.squares[i].setColor(SquareColor(i))
            #Set the model itself to be collideable with the ray. If this model was
            #any more complex than a single polygon, you should set up a collision
            #sphere around it instead. But for single polygons this works fine.
            self.squares[i].find("**/polygon").node().setIntoCollideMask(
                BitMask32.bit(1))
            #Set a tag on the square's node so we can look up what square this is
            #later during the collision pass
            self.squares[i].find("**/polygon").node().setTag('square', str(i))

            #We will use this variable as a pointer to whatever piece is currently
            #in this square

        self.initializer(self.currlevel)

        #This will represent the index of the currently highlited square
        self.hiSq = False
        #This wil represent the index of the square where currently dragged piece
        #was grabbed from
        self.dragging = False

        #Start the task that handles the picking
        self.mouseTask = taskMgr.add(self.mouseTask, 'mouseTask')
        #self.trial = taskMgr.add(self.trial,'trial')
        self.accept("mouse1", self.grabPiece)  #left-click grabs a piece
        self.accept("mouse1-up", self.releasePiece)  #releasing places it

    #This function swaps the positions of two pieces
    def swapPieces(self, fr, to):
        temp = self.pieces[fr]
        self.pieces[fr] = self.pieces[to]
        self.pieces[to] = temp
        if self.pieces[fr]:
            print 'imma swapping'
            self.pieces[fr].square = fr
            print fr
            print SquarePos(fr)
            try:
                self.pieces[fr].obj.setPos(SquarePos(fr))
            except:
                pass
            print 'done'
        if self.pieces[to]:
            self.pieces[to].square = to
            try:
                self.pieces[to].obj.setPos(SquarePos(to))
            except:
                pass

    def trial(self):
        self.turns = self.turns + 1
        try:
            self.reference.destroy()
        except:
            pass
        self.reference = OnscreenText(text='''
Reference:
virus is surrounded by more than 3 viruses, it dies
virus is surrounded by less than 2 viruses, it dies
If dead empty cell, is surrounded by exactly 3 viruses, a new virus is spawned.
''',
                                      style=1,
                                      fg=(1, 1, 1, 1),
                                      pos=(-1, 0.95),
                                      align=TextNode.ALeft,
                                      scale=.05)

        self.showscore()
        a = self.a
        while True:
            for i in self.list:
                #insert deletion code
                print 'imma deleting the sq : ' + str(i)
                self.pieces[i].obj.delete()

                self.squares[i].setColor(SquareColor(i))
            count = 0
            a = [[([[
                sum(b[y1][x1]
                    for b in [[[(
                        (-1 < x2 + dx < len(a[0])) and
                        (-1 < y2 + dy < len(a))) and a[y2 + dy][x2 + dx] or 0
                                for x2 in range(len(a[0]))]
                               for y2 in range(len(a))]
                              for (dx, dy) in [(dx, dy) for dx in [-1, 0, 1]
                                               for dy in [-1, 0, 1] if
                                               (dy != 0 or dx != 0)]])
                for x1 in range(len(a[0]))
            ] for y1 in range(len(a))][y][x] == 3 or ([[
                sum(c[y3][x3]
                    for c in [[[(
                        (-1 < x4 + dx < len(a[0])) and
                        (-1 < y4 + dy < len(a))) and a[y4 + dy][x4 + dx] or 0
                                for x4 in range(len(a[0]))]
                               for y4 in range(len(a))]
                              for (dx, dy) in [(dx, dy) for dx in [-1, 0, 1]
                                               for dy in [-1, 0, 1] if
                                               (dy != 0 or dx != 0)]])
                for x3 in range(len(a[0]))
            ] for y3 in range(len(a))][y][x] == 2 and a[y][x] == 1)) and 1 or 0
                  for x in range(len(a[0]))] for y in range(len(a))]
            lis = []
            #insert a random virus at a probability of 1/5
            diceroll = random.randint(0, 5)
            if diceroll == 2:

                self.random_vgen()
            for element in reversed(a):

                for ele in element:
                    #print 'cheking element is 1 : ' + str(ele)
                    if ele == 1:
                        lis.append(count)
                    count = count + 1
            print lis
            self.list = lis

            self.a = a
            print self.list

            for i in self.list:
                self.pieces[i] = Monster(i, WHITE)
                #self.squares[i].setColor(HIGHLIGHT)
            print 'leaving trial'
            if len(self.list) == 0:
                self.endscreen()
            break

        return

    def mouseTask(self, task):
        #This task deals with the highlighting and dragging based on the mouse

        #First, clear the current highlight
        if self.hiSq is not False:
            self.squares[self.hiSq].setColor(SquareColor(self.hiSq))
            self.hiSq = False

        #Check to see if we can access the mouse. We need it to do anything else
        if base.mouseWatcherNode.hasMouse():
            #get the mouse position
            mpos = base.mouseWatcherNode.getMouse()

            #Set the position of the ray based on the mouse position
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            #If we are dragging something, set the position of the object
            #to be at the appropriate point over the plane of the board
            if self.dragging is not False:
                #Gets the point described by pickerRay.getOrigin(), which is relative to
                #camera, relative instead to render
                nearPoint = render.getRelativePoint(camera,
                                                    self.pickerRay.getOrigin())
                #Same thing with the direction of the ray
                nearVec = render.getRelativeVector(
                    camera, self.pickerRay.getDirection())
                try:
                    self.pieces[self.dragging].obj.setPos(
                        PointAtZ(.5, nearPoint, nearVec))
                except:
                    pass
            #Do the actual collision pass (Do it only on the squares for
            #efficiency purposes)
            self.picker.traverse(self.squareRoot)
            if self.pq.getNumEntries() > 0:
                #if we have hit something, sort the hits so that the closest
                #is first, and highlight that node
                self.pq.sortEntries()
                i = int(self.pq.getEntry(0).getIntoNode().getTag('square'))
                #Set the highlight on the picked square
                self.squares[i].setColor(HIGHLIGHT)
                self.hiSq = i
                #print 'selected is ' + str(i)

        return Task.cont

    def grabPiece(self):
        #If a square is highlighted and it has a piece, set it to dragging mode
        if (self.hiSq is not False and self.pieces[self.hiSq]):
            self.dragging = self.hiSq
            self.hiSq = False

    def releasePiece(self):
        #Letting go of a piece. If we are not on a square, return it to its original
        #position. Otherwise, swap it with the piece in the new square
        if self.dragging is not False:  #Make sure we really are dragging something
            #We have let go of the piece, but we are not on a square
            if self.hiSq is False:
                try:
                    self.pieces[self.dragging].obj.setPos(
                        SquarePos(self.dragging))
                except:
                    pass
            else:
                #Otherwise, swap the pieces
                self.swapPieces(self.dragging, self.hiSq)
                #self.draggin is the from
                print self.list
                print 'you picked this, so Imma deleting this ' + str(
                    self.dragging)
                #deletion of i after picking it up.
                try:
                    self.list.remove(self.dragging)
                except:
                    pass
                temp2 = []
                temp2 = SquarePosTuple(self.dragging)
                self.a[temp2[0]][temp2[1]] = 0

                i = self.hiSq
                print self.list
                print 'highlighted sq is ' + str(i)
                templis = []
                templis = SquarePosTuple(i)
                print templis
                self.list.append(i)
                print self.list
                print templis
                self.a[templis[0]][templis[1]] = 1

                for line in self.a:
                    print line
                self.trial()

        #We are no longer dragging anything
        self.dragging = False

    def setupLights(self):  #This function sets up some default lighting
        ambientLight = AmbientLight("ambientLight")
        ambientLight.setColor(Vec4(.8, .8, .8, 1))
        directionalLight = DirectionalLight("directionalLight")
        directionalLight.setDirection(Vec3(0, 45, -45))
        directionalLight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        render.setLight(render.attachNewNode(directionalLight))
        render.setLight(render.attachNewNode(ambientLight))
Exemplo n.º 17
0
class LocationSeeker:

    def __init__(self, avatar, minDistance, maxDistance, shadowScale = 1):
        self.dropShadowPath = 'phase_3/models/props/square_drop_shadow.bam'
        self.rejectSoundPath = 'phase_4/audio/sfx/ring_miss.mp3'
        self.moveShadowTaskName = 'Move Shadow'
        self.locationSelectedName = 'Location Selected'
        self.dropShadow = None
        self.shadowScale = shadowScale
        self.rejectSfx = loader.loadSfx(self.rejectSoundPath)
        self.avatar = avatar
        self.cameraNode = None
        self.cameraRay = None
        self.cameraNP = None
        self.shadowNP = None
        self.shadowRay = None
        self.minDistance = minDistance
        self.maxDistance = maxDistance
        self.legacyMode = False
        self.collHdlFl = CollisionHandlerQueue()
        return

    def startSeeking(self):
        if not self.avatar:
            return
        self.cleanupShadow()
        self.buildShadow()
        scale = self.dropShadow.getScale()
        if scale < 1.0:
            self.maxDistance += 40
        x, y, z = self.avatar.getPos(render)
        self.dropShadow.reparentTo(render)
        self.dropShadow.setPos(x, y + 5, z + 2)
        self.cameraNode = CollisionNode('coll_camera')
        self.cameraNode.setFromCollideMask(CIGlobals.WallBitmask)
        self.cameraRay = CollisionRay()
        self.cameraNode.addSolid(self.cameraRay)
        self.cameraNP = camera.attachNewNode(self.cameraNode)
        base.cTrav.addCollider(self.cameraNP, CollisionHandlerQueue())
        if not self.legacyMode:
            shadowNode = CollisionNode('coll_shadow')
            self.shadowRay = CollisionRay(0, 0, 6, 0, 0, -1)
            shadowNode.addSolid(self.shadowRay)
            shadowNode.setFromCollideMask(CIGlobals.FloorBitmask)
            self.shadowNP = self.dropShadow.attachNewNode(shadowNode)
            base.cTrav.addCollider(self.shadowNP, self.collHdlFl)
        base.taskMgr.add(self.__moveShadow, self.moveShadowTaskName)
        self.avatar.acceptOnce('mouse1', self.locationChosen)

    def stopSeeking(self):
        base.taskMgr.remove(self.moveShadowTaskName)

    def __moveShadow(self, task):
        if base.mouseWatcherNode.hasMouse():

            def PointAtZ(z, point, vec):
                if vec.getZ() != 0:
                    return point + vec * ((z - point.getZ()) / vec.getZ())
                else:
                    return self.getLocation()

            mouse = base.mouseWatcherNode.getMouse()
            self.cameraRay.setFromLens(base.camNode, mouse.getX(), mouse.getY())
            nearPoint = render.getRelativePoint(camera, self.cameraRay.getOrigin())
            nearVec = render.getRelativeVector(camera, self.cameraRay.getDirection())
            self.dropShadow.setPos(PointAtZ(0.5, nearPoint, nearVec))
            if self.legacyMode:
                self.dropShadow.setZ(base.localAvatar.getZ(render) + 0.5)
            elif self.collHdlFl.getNumEntries() > 0:
                self.dropShadow.setZ(self.collHdlFl.getEntry(0).getSurfacePoint(render).getZ() + 0.5)
        return Task.cont

    def locationChosen(self):
        base.taskMgr.remove(self.moveShadowTaskName)
        distance = self.avatar.getDistance(self.dropShadow)
        x, y, z = self.getLocation()
        if distance >= self.minDistance and distance <= self.maxDistance:
            gag = self.avatar.getBackpack().getActiveGag()
            self.avatar.sendUpdate('setDropLoc', [gag.getID(),
             x,
             y,
             z])
            messenger.send(self.locationSelectedName)
        else:
            self.rejectSfx.play()
            self.avatar.acceptOnce('mouse1', self.locationChosen)
            base.taskMgr.add(self.__moveShadow, self.moveShadowTaskName)

    def buildShadow(self):
        self.cleanupShadow()
        if not self.dropShadowPath or not self.avatar:
            return
        self.dropShadow = loader.loadModel(self.dropShadowPath)
        self.dropShadow.setScale(self.shadowScale)

    def setShadowType(self, isCircle = False, scale = 1):
        if not isCircle:
            self.dropShadowPath = 'phase_3/models/props/square_drop_shadow.bam'
        else:
            self.dropShadowPath = 'phase_3/models/props/drop_shadow.bam'
        self.shadowScale = scale

    def getLocation(self):
        if self.dropShadow:
            return self.dropShadow.getPos(render)
        return self.avatar.getPos(render)

    def getLocationSelectedName(self):
        return self.locationSelectedName

    def cleanupShadow(self):
        if self.dropShadow:
            self.dropShadow.removeNode()
            self.dropShadow = None
            if self.cameraNode:
                self.cameraNP.removeNode()
                self.cameraNP = None
                self.cameraNode = None
                self.cameraRay = None
                self.shadowNP.removeNode()
                self.shadowRay = None
                self.shadowNP = None
                self.shadowSphNP = None
        return

    def cleanup(self):
        if self.avatar:
            base.taskMgr.remove(self.moveShadowTaskName)
            self.avatar.ignore('mouse1')
            self.cleanupShadow()
            self.rejectSfx.stop()
            self.rejectSfx = None
            self.avatar = None
            self.dropShadowPath = None
            self.rejectSoundPath = None
            self.locationSelectedName = None
            self.moveShadowTaskName = None
            del self.shadowScale
        return