Beispiel #1
0
 def Kampf(self,spieler,gegner):
     """Startet einen Kampf zwischen Spieler und Gegner, bis einer der beiden keine Energie mehr hat
     Usereingaben sind moeglich wie Item oder Angriff"""
     aktion = "angriff"
     aktNr = 0
     pos = [0,0]
     keyhandler = DirectObject()
     keyMap = {"angriff":0,"item":0}
     spieler = self.werteBerechnen(spieler)
     
     DirectObject.accept(keyhandler,"a", self.setKey, ["angriff",1])
     DirectObject.accept(keyhandler,"i", self.setKey, ["item",1])
     
     if (keyMap["angriff"]!=0):
         aktion = angriff
     if (keyMap["item"]!=0):
         aktion = item
     if spieler.energie <= 0:
         print "Spieler tot"
         self.active = False
         return [spieler,gegner]
     elif gegner.energie <= 0:
         print "Gegner besiegt"
         self.active = False
         return [spieler,gegner]        
     print "Spieler greift an"
     self.eventhandleSpieler(aktion,spieler,gegner,aktNr,pos)
     aktion = "angriff"
     print "Gegner greift an"
     self.eventhandleGegner(spieler,gegner)
     self.anzeigen(spieler,gegner)
     self.active = True
     return [spieler,gegner]
Beispiel #2
0
    def initPlayerAbilities(self):
        DO = DirectObject()
        DO.accept('1', self.fireAbility, [1])
        DO.accept('2', self.fireAbility, [2])
        DO.accept('3', self.fireAbility, [3])
        DO.accept('4', self.fireAbility, [4])

        self.abilityDict = {'offensive':1, 'defensive':1, 'evasive':1, 'area':1}
Beispiel #3
0
	def finish(self, pos=(0,0,0), minWidth=1):
		"""
		adjust frame for uniform width with siblings
		adjust pos relative to parent or older sibs
		attach stateGraphics
		"""
		me = self.getPythonTag("extras")
		item = me.item
		scale = me.style['font-size']
		kind=item['kind']
		width, height, lineHeight, fram = getTextSize(item['txt'], me.style)
		width = max(width,minWidth)
		arrowhead=.5*lineHeight
		padding = me.style['padding']
		padding = (padding[0]*scale ,padding[1]*scale ,padding[2]*scale ,padding[3]*scale )
		bevel = me.style['bevel']*scale 
		multiLineShim = 0
		if '\n' in item['txt']: multiLineShim = .04 # might need to change this to fit font
		NodePath(self).setPos(pos)
		if kind=='separator':
			sh = me.style['height']*scale 
			frame=(	-padding[0], width+padding[1], -sh/2, sh/2)
		else:
			frame = (fram[0],max(fram[1],fram[0]+minWidth),fram[2],fram[3]) 
			frame=(	frame[0]-padding[0],
					frame[1]+padding[1],
					frame[2]-padding[2]-multiLineShim,
					frame[3]+padding[3])
			stateGraphics = getBackgroundSet(self, frame, arrowhead)
			for state in STATES:
					self.clearStateDef(state) # in case we've been here befor
					self.instanceToStateDef(state, stateGraphics[state])
			DO=DirectObject()
			if not self.clickAccepted: #JUSTIN'S INSERTED CODE
                                DO.accept(self.getEnterEvent(), onEnter, [me.menuRoot.menuRootID, self]) 
                                DO.accept(self.getExitEvent(), onLeave, [me.menuRoot.menuRootID, self])
			if kind in ('button', 'checkBox', 'radioBTN', 'checkAllBTN', 'unCheckAllBTN', 'titleBar', 'close'):
                                if not self.clickAccepted: #JUSTIN'S INSERTED CODE
                                        DO.accept(self.getPressEvent(MouseButton.one()), onPress, [self]) 
                                        DO.accept(self.getReleaseEvent(MouseButton.one()), onRelease, [self]) 
                                        # so we can simulate 'click' with messenger.send('press'+id, ['simClk']):
                                        DO.accept('press'+item['id'], onPress, [self])

                        if not self.clickAccepted: #JUSTIN'S INSERTED CODE
                                self.clickAccepted=True
			self.setActive(True)

		if kind == 'parent':# accomodate arrowheads
			self.setFrame(frame[0], frame[1]+arrowhead*2-bevel, frame[2], frame[3])
		else:
			self.setFrame(frame)
Beispiel #4
0
    def setupMouseCollision(self):
        self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, 0))

        DO = DirectObject()
        DO.accept('mouse1', self.onMouseDown)
        DO.accept('mouse1-up', self.onMouseUp)

        self.collisionHandler = CollisionHandlerQueue()

        self.pickerCollNode = CollisionNode('mouseRay')
        self.pickerNodePath = camera.attachNewNode(self.pickerCollNode)
        self.pickerCollNode.setIntoCollideMask(BitMask32.allOff())
        self.pickerCollNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerCollNode.addSolid(self.pickerRay)
        base.cTrav.addCollider(self.pickerNodePath, self.collisionHandler)

        taskMgr.add(self.moveTask, 'moveTask')
        taskMgr.add(self.attackTask, 'attackTask')
Beispiel #5
0
    def __init__(self, mainRef):
        print("Player instantiated")
        Unit.__init__(self)
        FSM.__init__(self, 'playerFSM')

        self._hudRef = None
        self._mainRef = mainRef
        self._enemyListRef = mainRef.enemyList
        self._ddaHandlerRef = mainRef.DDAHandler
        self._mapHandlerRef = mainRef.mapHandler
        self._stateHandlerRef = mainRef.stateHandler
        self._scenarioHandlerRef = mainRef.scenarioHandler

        self.playerNode = mainRef.mainNode.attachNewNode('playerNode')

        self.initPlayerAttributes()
        self.initPlayerModel()
        self.initPlayerCamera()
        self.initPlayerAbilities()

        self.initPlayerCollisionHandlers()
        self.initPlayerCollisionSolids()

        self.initPlayerDDA()

        # Start mouse picking and movement
        self.mouseHandler = utils.MouseHandler(self)

        # Start player update task
        playerUpdateTask = taskMgr.add(self.playerUpdate, 'playerUpdateTask')

        # Initialize player FSM state
        self.request('Idle')

        DO = DirectObject()
        DO.accept('shift-mouse1', self.onShiftDown)
        DO.accept('shift-up', self.onShiftUp)

        self._shiftButtonDown = False
Beispiel #6
0
def setupDebugHelp(APP):
    def toggleOobe():
        """Switch between free camera (steering with the mouse) and
        the camera controled by the game"""
        APP.oobe()

    def explorer():
        """activates the Panda3D halp tool to explore the
        render Nodepath"""
        APP.render.explore()

    def analyze():
        APP.render.analyze()

    def toggleWireframe():
        """Switch between wired model view and normal view"""
        base.toggleWireframe()

    from time import strftime
    def takeScreenshot():
        # make a screenshot
        path = os.path.join(Settings.settingsPath, "screenshots")
        if not os.path.exists(path):
            os.makedirs(path)
        # create the filename with a name and the actual time
        fn = "Screenshot" + strftime("_%a_%d-%m-%Y_%H:%M:%S") + ".png"
        path = os.path.join(path, fn)
        APP.win.saveScreenshot(Filename.fromOsSpecific(path))
        logging.info(str.format("take Screenshot in: {0}", path))

    # create a DirectObject object to handle the key input by the user
    directobject = DirectObject()
    directobject.accept("f2", analyze)
    directobject.accept("f3", explorer)
    directobject.accept("f4", toggleWireframe)
    directobject.accept("f5", takeScreenshot)
    directobject.accept("f12", toggleOobe)
class DirectEntry(DirectFrame):
    """
    DirectEntry(parent) - Create a DirectGuiWidget which responds
    to keyboard buttons
    """

    directWtext = ConfigVariableBool('direct-wtext', 1)

    AllowCapNamePrefixes = ("Al", "Ap", "Ben", "De", "Del", "Della", "Delle", "Der", "Di", "Du",
                            "El", "Fitz", "La", "Las", "Le", "Les", "Lo", "Los",
                            "Mac", "St", "Te", "Ten", "Van", "Von", )
    ForceCapNamePrefixes = ("D'", "DeLa", "Dell'", "L'", "M'", "Mc", "O'", )

    def __init__(self, parent = None, **kw):
        # Inherits from DirectFrame
        # A Direct Frame can have:
        # - A background texture (pass in path to image, or Texture Card)
        # - A midground geometry item (pass in geometry)
        # - A foreground text Node (pass in text string or Onscreen Text)
        # For a direct entry:
        # Each button has 3 states (focus, noFocus, disabled)
        # The same image/geom/text can be used for all three states or each
        # state can have a different text/geom/image
        # State transitions happen automatically based upon mouse interaction
        optiondefs = (
            # Define type of DirectGuiWidget
            ('pgFunc',          PGEntry,          None),
            ('numStates',       3,                None),
            ('state',           DGG.NORMAL,       None),
            ('entryFont',       None,             DGG.INITOPT),
            ('width',           10,               self.setup),
            ('numLines',        1,                self.setup),
            ('focus',           0,                self.setFocus),
            ('cursorKeys',      1,                self.setCursorKeysActive),
            ('obscured',        0,                self.setObscureMode),
            # Setting backgroundFocus allows the entry box to get keyboard
            # events that are not handled by other things (i.e. events that
            # fall through to the background):
            ('backgroundFocus', 0,                self.setBackgroundFocus),
            # Text used for the PGEntry text node
            # NOTE: This overrides the DirectFrame text option
            ('initialText',     '',               DGG.INITOPT),
            # Command to be called on hitting Enter
            ('command',        None,              None),
            ('extraArgs',      [],                None),
            # Command to be called when enter is hit but we fail to submit
            ('failedCommand',  None,              None),
            ('failedExtraArgs',[],                None),
            # commands to be called when focus is gained or lost
            ('focusInCommand', None,              None),
            ('focusInExtraArgs', [],              None),
            ('focusOutCommand', None,             None),
            ('focusOutExtraArgs', [],             None),
            # Sounds to be used for button events
            ('rolloverSound',   DGG.getDefaultRolloverSound(), self.setRolloverSound),
            ('clickSound',      DGG.getDefaultClickSound(),    self.setClickSound),
            ('autoCapitalize',  0,                self.autoCapitalizeFunc),
            ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None),
            ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None),
            )
        # Merge keyword options with default options
        self.defineoptions(kw, optiondefs)

        # Initialize superclasses
        DirectFrame.__init__(self, parent)

        if self['entryFont'] == None:
            font = DGG.getDefaultFont()
        else:
            font = self['entryFont']

        # Create Text Node Component
        self.onscreenText = self.createcomponent(
            'text', (), None,
            OnscreenText,
            (), parent = hidden,
            # Pass in empty text to avoid extra work, since its really
            # The PGEntry which will use the TextNode to generate geometry
            text = '',
            align = TextNode.ALeft,
            font = font,
            scale = 1,
            # Don't get rid of the text node
            mayChange = 1)

        # We can get rid of the node path since we're just using the
        # onscreenText as an easy way to access a text node as a
        # component
        self.onscreenText.removeNode()

        # Bind command function
        self.bind(DGG.ACCEPT, self.commandFunc)
        self.bind(DGG.ACCEPTFAILED, self.failedCommandFunc)

        self.accept(self.guiItem.getFocusInEvent(), self.focusInCommandFunc)
        self.accept(self.guiItem.getFocusOutEvent(), self.focusOutCommandFunc)

        # listen for auto-capitalize events on a separate object to prevent
        # clashing with other parts of the system
        self._autoCapListener = DirectObject()

        # Call option initialization functions
        self.initialiseoptions(DirectEntry)

        if not hasattr(self, 'autoCapitalizeAllowPrefixes'):
            self.autoCapitalizeAllowPrefixes = DirectEntry.AllowCapNamePrefixes
        if not hasattr(self, 'autoCapitalizeForcePrefixes'):
            self.autoCapitalizeForcePrefixes = DirectEntry.ForceCapNamePrefixes

        # Update TextNodes for each state
        for i in range(self['numStates']):
            self.guiItem.setTextDef(i, self.onscreenText.textNode)

        # Now we should call setup() again to make sure it has the
        # right font def.
        self.setup()

        # Update initial text
        self.unicodeText = 0
        if self['initialText']:
            self.enterText(self['initialText'])

    def destroy(self):
        self.ignoreAll()
        self._autoCapListener.ignoreAll()
        DirectFrame.destroy(self)

    def setup(self):
        self.guiItem.setupMinimal(self['width'], self['numLines'])

    def setFocus(self):
        PGEntry.setFocus(self.guiItem, self['focus'])

    def setCursorKeysActive(self):
        PGEntry.setCursorKeysActive(self.guiItem, self['cursorKeys'])

    def setObscureMode(self):
        PGEntry.setObscureMode(self.guiItem, self['obscured'])

    def setBackgroundFocus(self):
        PGEntry.setBackgroundFocus(self.guiItem, self['backgroundFocus'])

    def setRolloverSound(self):
        rolloverSound = self['rolloverSound']
        if rolloverSound:
            self.guiItem.setSound(DGG.ENTER + self.guiId, rolloverSound)
        else:
            self.guiItem.clearSound(DGG.ENTER + self.guiId)

    def setClickSound(self):
        clickSound = self['clickSound']
        if clickSound:
            self.guiItem.setSound(DGG.ACCEPT + self.guiId, clickSound)
        else:
            self.guiItem.clearSound(DGG.ACCEPT + self.guiId)

    def commandFunc(self, event):
        if self['command']:
            # Pass any extra args to command
            apply(self['command'], [self.get()] + self['extraArgs'])

    def failedCommandFunc(self, event):
        if self['failedCommand']:
            # Pass any extra args
            apply(self['failedCommand'], [self.get()] + self['failedExtraArgs'])

    def autoCapitalizeFunc(self):
        if self['autoCapitalize']:
            self._autoCapListener.accept(self.guiItem.getTypeEvent(), self._handleTyping)
            self._autoCapListener.accept(self.guiItem.getEraseEvent(), self._handleErasing)
        else:
            self._autoCapListener.ignore(self.guiItem.getTypeEvent())
            self._autoCapListener.ignore(self.guiItem.getEraseEvent())

    def focusInCommandFunc(self):
        if self['focusInCommand']:
            apply(self['focusInCommand'], self['focusInExtraArgs'])
        if self['autoCapitalize']:
            self.accept(self.guiItem.getTypeEvent(), self._handleTyping)
            self.accept(self.guiItem.getEraseEvent(), self._handleErasing)

    def _handleTyping(self, guiEvent):
        self._autoCapitalize()
    def _handleErasing(self, guiEvent):
        self._autoCapitalize()

    def _autoCapitalize(self):
        name = self.get().decode('utf-8')
        # capitalize each word, allowing for things like McMutton
        capName = ''
        # track each individual word to detect prefixes like Mc
        wordSoFar = ''
        # track whether the previous character was part of a word or not
        wasNonWordChar = True
        for i in xrange(len(name)):
            character = name[i]
            # test to see if we are between words
            # - Count characters that can't be capitalized as a break between words
            #   This assumes that string.lower and string.upper will return different
            #   values for all unicode letters.
            # - Don't count apostrophes as a break between words
            if ((string.lower(character) == string.upper(character)) and (character != "'")):
                # we are between words
                wordSoFar = ''
                wasNonWordChar = True
            else:
                capitalize = False
                if wasNonWordChar:
                    # first letter of a word, capitalize it unconditionally;
                    capitalize = True
                elif (character == string.upper(character) and
                      len(self.autoCapitalizeAllowPrefixes) and
                      wordSoFar in self.autoCapitalizeAllowPrefixes):
                    # first letter after one of the prefixes, allow it to be capitalized
                    capitalize = True
                elif (len(self.autoCapitalizeForcePrefixes) and
                      wordSoFar in self.autoCapitalizeForcePrefixes):
                    # first letter after one of the force prefixes, force it to be capitalized
                    capitalize = True
                if capitalize:
                    # allow this letter to remain capitalized
                    character = string.upper(character)
                else:
                    character = string.lower(character)
                wordSoFar += character
                wasNonWordChar = False
            capName += character
        self.enterText(capName.encode('utf-8'))

    def focusOutCommandFunc(self):
        if self['focusOutCommand']:
            apply(self['focusOutCommand'], self['focusOutExtraArgs'])
        if self['autoCapitalize']:
            self.ignore(self.guiItem.getTypeEvent())
            self.ignore(self.guiItem.getEraseEvent())

    def set(self, text):
        """ Changes the text currently showing in the typable region;
        does not change the current cursor position.  Also see
        enterText(). """
        
        self.unicodeText = isinstance(text, types.UnicodeType)
        if self.unicodeText:
            self.guiItem.setWtext(text)
        else:
            self.guiItem.setText(text)

    def get(self, plain = False):
        """ Returns the text currently showing in the typable region.
        If plain is True, the returned text will not include any
        formatting characters like nested color-change codes. """

        wantWide = self.unicodeText or self.guiItem.isWtext()
        if not self.directWtext.getValue():
            # If the user has configured wide-text off, then always
            # return an 8-bit string.  This will be encoded if
            # necessary, according to Panda's default encoding.
            wantWide = False

        if plain:
            if wantWide:
                return self.guiItem.getPlainWtext()
            else:
                return self.guiItem.getPlainText()
        else:
            if wantWide:
                return self.guiItem.getWtext()
            else:
                return self.guiItem.getText()

    def setCursorPosition(self, pos):
        if (pos < 0):
            self.guiItem.setCursorPosition(self.guiItem.getNumCharacters() + pos)
        else:
            self.guiItem.setCursorPosition(pos)

    def enterText(self, text):
        """ sets the entry's text, and moves the cursor to the end """
        self.set(text)
        self.setCursorPosition(self.guiItem.getNumCharacters())

    def getFont(self):
        return self.onscreenText.getFont()

    def getBounds(self, state = 0):
        # Compute the width and height for the entry itself, ignoring
        # geometry etc.
        tn = self.onscreenText.textNode
        mat = tn.getTransform()
        align = tn.getAlign()
        lineHeight = tn.getLineHeight()
        numLines = self['numLines']
        width = self['width']

        if align == TextNode.ALeft:
            left = 0.0
            right = width
        elif align == TextNode.ACenter:
            left = -width / 2.0
            right = width / 2.0
        elif align == TextNode.ARight:
            left = -width
            right = 0.0

        bottom = -0.3 * lineHeight - (lineHeight * (numLines - 1))
        top = lineHeight

        self.ll.set(left, 0.0, bottom)
        self.ur.set(right, 0.0, top)
        self.ll = mat.xformPoint(Point3.rfu(left, 0.0, bottom))
        self.ur = mat.xformPoint(Point3.rfu(right, 0.0, top))

        vec_right = Vec3.right()
        vec_up = Vec3.up()
        left = (vec_right[0] * self.ll[0]
              + vec_right[1] * self.ll[1]
              + vec_right[2] * self.ll[2])
        right = (vec_right[0] * self.ur[0]
               + vec_right[1] * self.ur[1]
               + vec_right[2] * self.ur[2])
        bottom = (vec_up[0] * self.ll[0]
                + vec_up[1] * self.ll[1]
                + vec_up[2] * self.ll[2])
        top = (vec_up[0] * self.ur[0]
             + vec_up[1] * self.ur[1]
             + vec_up[2] * self.ur[2])
        self.ll = Point3(left, 0.0, bottom)
        self.ur = Point3(right, 0.0, top)

        # Scale bounds to give a pad around graphics.  We also want to
        # scale around the border width.
        pad = self['pad']
        borderWidth = self['borderWidth']
        self.bounds = [self.ll[0] - pad[0] - borderWidth[0],
                       self.ur[0] + pad[0] + borderWidth[0],
                       self.ll[2] - pad[1] - borderWidth[1],
                       self.ur[2] + pad[1] + borderWidth[1]]
        return self.bounds
Beispiel #8
0
# THE CREDITS TEXT 
ost = OnscreenText(parent=textParent, font=loader.loadFont('cmss12'), 
   text='CREDITS\n\n'+'\n'.join([c*30 for c in string.ascii_letters]), 
   fg=(1,1,1,1),scale=.065) 
ost.setP(-90) 
ost.flattenLight() 

ts=TextureStage('') 
textParent.setTexGen(ts,TexGenAttrib.MWorldPosition) 
textParent.setTexScale(ts,.5,.5) 
textParent.setTexOffset(ts,.5,.5) 
textParent.setTexture(ts,tex) 
b3=textParent.getTightBounds() 
dims=b3[1]-b3[0] 
textParent.posInterval(50,Point3(0,dims[1]+2,0),Point3(0,-1.05,0)).start() 

VPcam = Camera('vpcam') 
VPcam.copyLens(base.cam2d.node().getLens()) 
VPcamNP = dummyParent.attachNewNode(VPcam) 
VPcamNP.setP(-90) 
dr=base.win.makeDisplayRegion() 
dr.setCamera(VPcamNP) 
dr.setSort(1000) 


do=DirectObject() 
do.accept('space',cycleAlpha) 
do.accept('escape',sys.exit) 
globalClock.setMode(ClockObject.MNormal) 
run()
Beispiel #9
0
    terrainNode = NodePath("terrNode")
    terrainNode.reparentTo(render)
    terrainNode.attachNewNode(squareGN)
    terrainNode.setX(-width/2)
    texGrass = loader.loadTexture("textures/envir-ground.jpg")
    terrainNode.setTexture(texGrass)

cHandler.addInPattern("%(rays)ft-into-%(building)it")
cHandler.addOutPattern("%(rays)ft-out-%(building)it")

cHandler.addAgainPattern("ray_again_all%(""rays"")fh%(""building"")ih")

DO=DirectObject()

DO.accept('ray1-into-buildPlayer1', collideInBuilding)
DO.accept('ray1-out-buildPlayer1', collideOutBuilding)

DO.accept('ray_again_all', collideAgainstBuilds)

pickingEnabledOject=None

DO.accept('mouse1', mouseClick, ["down"])
DO.accept('mouse1-up', mouseClick, ["up"])

DO.accept("w",moveCam, ["up"])
DO.accept("s",moveCam, ["down"])
DO.accept("w-up",moveCam, ["stopY"])
DO.accept("s-up",moveCam, ["stopY"])
DO.accept("a",moveCam, ["left"])
DO.accept("d",moveCam, ["right"])
Beispiel #10
0
    base.cam.setY(self.avatar.getY()-self.camdistY)
    if self.steer2d:
      base.cam.setX(self.avatar.getX())
      base.cam.setZ(self.avatar.getZ()+self.camdistZ)
    base.cam.lookAt(self.avatar)

    return Task.cont

#=========================================================================
# Main
#=========================================================================

alight = AmbientLight('alight')
alight.setColor((.3, .3, .3, 1))
alnp = render.attachNewNode(alight)
render.setLight(alnp)

dlight = DirectionalLight('dlight')
lv=.6
dlight.setColor((lv,lv,lv, 1))
dlnp = render.attachNewNode(dlight)
render.setLight(dlnp)
dlnp.setPos(0,-20,35)
dlnp.lookAt(0,0,0)

DO=DirectObject()
DO.accept('c', toggle_collisions)
DO.accept('h', toggle_info)
DO.accept('x', toggle_wire)
DO.accept('escape',sys.exit)
Beispiel #11
0
class PhysicsManager:

    def __init__(self, root_nodepath, world):
        self.world = BulletWorld()
        self.world.setGravity((0, 0, -9.81))

        self._timestep = 1 / world.tick_rate

        # # Seems that this does not function
        # on_contact_added = PythonCallbackObject(self._on_contact_added)
        # self.world.set_contact_added_callback(on_contact_added)
        # on_filter = PythonCallbackObject(self._filter_collision)
        # self.world.set_filter_callback(on_filter)

        self.listener = DirectObject()
        self.listener.accept('bullet-contact-added', self._on_contact_added)
        self.listener.accept('bullet-contact-destroyed', self._on_contact_removed)

        self.tracked_contacts = defaultdict(int)
        self.existing_collisions = set()

        # Debugging info
        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(True)
        debug_node.showBoundingBoxes(False)
        debug_node.showNormals(False)

        # Add to world
        self.debug_nodepath = root_nodepath.attachNewNode(debug_node)
        self.world.set_debug_node(debug_node)
        self.debug_nodepath.show()

    def _on_contact_removed(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] -= 1

    def _on_contact_added(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] += 1

    def _dispatch_collisions(self):
        # Dispatch collisions
        existing_collisions = self.existing_collisions

        for pair, contact_count in self.tracked_contacts.items():
            # If is new collision
            if contact_count > 0 and pair not in existing_collisions:
                existing_collisions.add(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = node_a.get_python_tag("entity")
                entity_b = node_b.get_python_tag("entity")

                if not (entity_a and entity_b):
                    continue

                contact_result = ContactResult(self.world, node_a, node_b)
                entity_a.messenger.send("collision_started", entity=entity_b, contacts=contact_result.contacts_a)
                entity_b.messenger.send("collision_started", entity=entity_a, contacts=contact_result.contacts_b)

            # Ended collision
            elif contact_count == 0 and pair in existing_collisions:
                existing_collisions.remove(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = node_a.get_python_tag("entity")
                entity_b = node_b.get_python_tag("entity")

                if not (entity_a and entity_b):
                    continue

                entity_a.messenger.send("collision_stopped", entity_b)
                entity_b.messenger.send("collision_stopped", entity_a)

    def add_entity(self, entity, component):
        body = component.body
        self.world.attach_rigid_body(body)
        body.set_python_tag("entity", entity)

    def remove_entity(self, entity, component):
        body = component.body
        self.world.remove_rigid_body(body)
        body.clear_python_tag("entity")

    def tick(self):
        self.world.do_physics(self._timestep)
        self._dispatch_collisions()

    def resimulate_pawn(self, pawn):
        pass
Beispiel #12
0
class SCTerminal(SCElement):
    __module__ = __name__

    def __init__(self, linkedEmote = None):
        SCElement.__init__(self)
        self.setLinkedEmote(linkedEmote)
        scGui = loader.loadModel(SCMenu.GuiModelName)
        self.emotionIcon = scGui.find('**/emotionIcon')
        self.setDisabled(False)
        self.__numCharges = -1
        self._handleWhisperModeSV = StateVar(False)
        self._handleWhisperModeFC = None
        return

    def destroy(self):
        self._handleWhisperModeSV.set(False)
        if self._handleWhisperModeFC:
            self._handleWhisperModeFC.destroy()
        self._handleWhisperModeSV.destroy()
        SCElement.destroy(self)

    def privSetSettingsRef(self, settingsRef):
        SCElement.privSetSettingsRef(self, settingsRef)
        if self._handleWhisperModeFC is None:
            self._handleWhisperModeFC = FunctionCall(self._handleWhisperModeSVChanged, self._handleWhisperModeSV)
            self._handleWhisperModeFC.pushCurrentState()
        self._handleWhisperModeSV.set(self.settingsRef is not None and not self.isWhisperable())
        return

    def _handleWhisperModeSVChanged(self, handleWhisperMode):
        if handleWhisperMode:
            self._wmcListener = DirectObject()
            self._wmcListener.accept(self.getEventName(SCWhisperModeChangeEvent), self._handleWhisperModeChange)
        elif hasattr(self, '_wmcListener'):
            self._wmcListener.ignoreAll()
            del self._wmcListener
            self.invalidate()

    def _handleWhisperModeChange(self, whisperMode):
        self.invalidate()

    def handleSelect(self):
        messenger.send(self.getEventName(SCTerminalSelectedEvent))
        if self.hasLinkedEmote() and self.linkedEmoteEnabled():
            messenger.send(self.getEventName(SCTerminalLinkedEmoteEvent), [self.linkedEmote])

    def isWhisperable(self):
        return True

    def getLinkedEmote(self):
        return self.linkedEmote

    def setLinkedEmote(self, linkedEmote):
        self.linkedEmote = linkedEmote
        self.invalidate()

    def hasLinkedEmote(self):
        return self.linkedEmote is not None

    def linkedEmoteEnabled(self):
        if Emote.globalEmote:
            return Emote.globalEmote.isEnabled(self.linkedEmote)

    def getCharges(self):
        return self.__numCharges

    def setCharges(self, nCharges):
        self.__numCharges = nCharges
        if nCharges is 0:
            self.setDisabled(True)

    def isDisabled(self):
        return self.__disabled or self.isWhispering() and not self.isWhisperable()

    def setDisabled(self, bDisabled):
        self.__disabled = bDisabled

    def onMouseClick(self, event):
        if not self.isDisabled():
            SCElement.onMouseClick(self, event)
            self.handleSelect()

    def getMinDimensions(self):
        width, height = SCElement.getMinDimensions(self)
        if self.hasLinkedEmote():
            width += 1.3
        return (width, height)

    def finalize(self, dbArgs = {}):
        if not self.isDirty():
            return
        args = {}
        if self.hasLinkedEmote():
            self.lastEmoteIconColor = self.getEmoteIconColor()
            self.emotionIcon.setColorScale(*self.lastEmoteIconColor)
            args.update({'image': self.emotionIcon,
             'image_pos': (self.width - 0.6, 0, -self.height * 0.5)})
        if self.isDisabled():
            args.update({'rolloverColor': (0, 0, 0, 0),
             'pressedColor': (0, 0, 0, 0),
             'rolloverSound': None,
             'clickSound': None,
             'text_fg': self.getColorScheme().getTextDisabledColor() + (1,)})
        args.update(dbArgs)
        SCElement.finalize(self, dbArgs=args)
        return

    def getEmoteIconColor(self):
        if self.linkedEmoteEnabled() and not self.isWhispering():
            r, g, b = self.getColorScheme().getEmoteIconColor()
        else:
            r, g, b = self.getColorScheme().getEmoteIconDisabledColor()
        return (r,
         g,
         b,
         1)

    def updateEmoteIcon(self):
        if hasattr(self, 'button'):
            self.lastEmoteIconColor = self.getEmoteIconColor()
            for i in range(self.button['numStates']):
                self.button['image%s_image' % i].setColorScale(*self.lastEmoteIconColor)

        else:
            self.invalidate()

    def enterVisible(self):
        SCElement.enterVisible(self)
        if hasattr(self, 'lastEmoteIconColor'):
            if self.getEmoteIconColor() != self.lastEmoteIconColor:
                self.invalidate()

        def handleWhisperModeChange(whisperMode, self = self):
            if self.hasLinkedEmote():
                if self.isVisible() and not self.isWhispering():
                    self.updateEmoteIcon()

        self.accept(self.getEventName(SCWhisperModeChangeEvent), handleWhisperModeChange)

        def handleEmoteEnableStateChange(self = self):
            if self.hasLinkedEmote():
                if self.isVisible() and not self.isWhispering():
                    self.updateEmoteIcon()

        if self.hasLinkedEmote():
            if Emote.globalEmote:
                self.accept(Emote.globalEmote.EmoteEnableStateChanged, handleEmoteEnableStateChange)

    def exitVisible(self):
        SCElement.exitVisible(self)
        self.ignore(self.getEventName(SCWhisperModeChangeEvent))
        if Emote.globalEmote:
            self.ignore(Emote.globalEmote.EmoteEnableStateChanged)

    def getDisplayText(self):
        if self.getCharges() is not -1:
            return self.text + ' (%s)' % self.getCharges()
        else:
            return self.text
Beispiel #13
0
    text="CREDITS\n\n" + "\n".join([c * 30 for c in string.ascii_letters]),
    fg=(1, 1, 1, 1),
    scale=0.065,
)
ost.setP(-90)
ost.flattenLight()

ts = TextureStage("")
textParent.setTexGen(ts, TexGenAttrib.MWorldPosition)
textParent.setTexScale(ts, 0.5, 0.5)
textParent.setTexOffset(ts, 0.5, 0.5)
textParent.setTexture(ts, tex)
b3 = textParent.getTightBounds()
dims = b3[1] - b3[0]
textParent.posInterval(50, Point3(0, dims[1] + 2, 0), Point3(0, -1.05, 0)).loop()

VPcam = Camera("vpcam")
VPcam.copyLens(base.cam2d.node().getLens())
VPcamNP = dummyParent.attachNewNode(VPcam)
VPcamNP.setP(-90)
dr = base.win.makeDisplayRegion()
dr.setCamera(VPcamNP)
dr.setSort(1000)


do = DirectObject()
do.accept("space", cycleAlpha)
do.accept("escape", sys.exit)
globalClock.setMode(ClockObject.MNormal)
run()
class PopupMouseWatcherRegion(MouseWatcherRegion):
    """
    This is an ultra hacky class!
    The correct implementation of PopupMouseWatcherRegion cannot be done in Python.
    This also assumes that m_mouse_watcher is NametagGlobals::_mouse_watcher.
    """
    class _Param:
        def __init__(self, outside=False):
            self.outside = outside

        def isOutside(self):
            return self.outside

        def getButton(self):
            return MouseButton.one()

    MOUSE_WATCHER_SETUP = False

    def __init__(self, obj, name, frame):
        MouseWatcherRegion.__init__(self, '%s-%s' % (name, id(self)), frame)

        self.obj = obj
        self.__inside = False

        if not self.MOUSE_WATCHER_SETUP:
            NametagGlobals._mouse_watcher.setEnterPattern('mouse-enter-%r')
            NametagGlobals._mouse_watcher.setLeavePattern('mouse-leave-%r')
            NametagGlobals._mouse_watcher.setButtonDownPattern(
                'button-down-%r')
            NametagGlobals._mouse_watcher.setButtonUpPattern('button-up-%r')
            self.MOUSE_WATCHER_SETUP = True

        self.slaveObject = DirectObject()
        self.slaveObject.accept(
            self.__getEvent(NametagGlobals._mouse_watcher.getEnterPattern()),
            self.__mouseEnter)
        self.slaveObject.accept(
            self.__getEvent(NametagGlobals._mouse_watcher.getLeavePattern()),
            self.__mouseLeave)
        self.slaveObject.accept(
            self.__getEvent(
                NametagGlobals._mouse_watcher.getButtonDownPattern()),
            self.__buttonDown)
        self.slaveObject.accept(
            self.__getEvent(
                NametagGlobals._mouse_watcher.getButtonUpPattern()),
            self.__buttonUp)

    def __mouseEnter(self, region, extra):
        self.__inside = True
        self.obj.enterRegion(None)

    def __mouseLeave(self, region, extra):
        self.__inside = False
        self.obj.exitRegion(None)

    def __buttonDown(self, region, button):
        if button == 'mouse1':
            self.obj.press(PopupMouseWatcherRegion._Param())

    def __buttonUp(self, region, button):
        if button == 'mouse1':
            self.obj.release(PopupMouseWatcherRegion._Param(not self.__inside))

    def __getEvent(self, pattern):
        return pattern.replace('%r', self.getName())
Beispiel #15
0
#** This is a task function called each frame, where the collision ray position is syncronized with the mouse pointer position and, more important, we traverse our collision traverser to make its routines check the collisions.
def rayupdate(task):
    if base.mouseWatcherNode.hasMouse():
        mpos = base.mouseWatcherNode.getMouse()
        # here the meat: differently from step 6, we do not call setFromLens to shoot our ray in 3d space from the camera lens, but rather we move the ray along the cursor position and shoot a straight ray from there along Y axis. This is because in orthographic view there is no perspective and therefore a ray is shoot parallel to its starting point
        pickerNP.setPos(render2d, mpos[0], 0, mpos[1])
        # and here we run the traverse step, to check the collisions in our scene
        customCtrav.traverse(render2d)
    return task.cont


#** to manage the collision and mouse button events
DO = DirectObject()

#** Let's manage the collision events: as you can see these are the events generated by the patterns defined above, a fixed string this time so no surprises here.
DO.accept('ray-into-cards', collideInCard)
DO.accept('ray-out-cards', collideOutCard)

#** Storage for the object eventually below the mouse pointer
pickingEnabledOject = None

#** Here's how we interact with mouse clicks - see the mouseClick function above
DO.accept('mouse1', mouseClick, ['down'])
DO.accept('mouse1-up', mouseClick, ['up'])

#** And here we start the task that continuously update the ray collider position and make traverse the collision traverser in 2d space
taskMgr.add(rayupdate, "updatePicker")

splash.destroy()
run()
Beispiel #16
0
class Game(ShowBase):
	def __init__(self):
		ShowBase.__init__(self)
		
		#start the time
		self.globalTime = 0
		self.nextEnemy = 1
		
		#setup your collision event handlers, apparently needs a direct object
		
		self.do = DirectObject()
		self.do.accept('unit-into-unit', self.handleUnitIntoCollision)
		self.do.accept('unit-out-unit', self.handleUnitOutCollision)
		self.do.accept('unit-into-cube', self.handleCubeIntoCollision)
		self.do.accept('unit-into-wing', self.handleWingIntoCollision)
		self.do.accept('unit-into-bar', self.handleBarIntoCollision)
		
		#get window properties
		self.winProps = WindowProperties()
		#self.winProps.setFullscreen(True)
		self.winProps.setCursorHidden(True)
		base.win.requestProperties(self.winProps)
		
		self.winProps = base.win.getProperties()
		self.screenHeight = self.winProps.getYSize()
		
		#set up the control scheme
		self.controlScheme = ControlScheme(base.mouseWatcherNode, base.win, \
										[LEFT, RIGHT, UP, DOWN, PAUSE, PULL, PUSH, SWITCH, QUIT])
		
		#disable the automatic task to move the camera
		#(this does not actually disable the mouse)
		base.disableMouse()
		
		#declare null values for variables, fill them in later
		self.environment = None
		self.player = None
		
		#a node for holding all in-game units
		self.unitNodePath = NodePath('unit holder')
		self.unitNodePath.reparentTo(self.render)
		
		#object lists
		self.enemies = []
		self.obstacles = []
		self.projectiles = []
		#list of enemies to be spawned
		self.eSpawnList = []
		
		#not paused by default
		self.paused = False
		self.pauseWasPressed = False
		
		#variables for tracking time
		self.previousFrameTime = 0
		
		#start the collision traverser
		traverser = CollisionTraverser()
		base.cTrav = traverser#run every frame
		self.cTrav = base.cTrav
		#set the check for units accidentally passing through level geometry
		self.cTrav.setRespectPrevTransform(True)
		
		#self.cTrav.showCollisions(self.render)
		#self.cTrav.showCollisions(self.unitNodePath)#show the collisions
		
		#load terrain and enemies
		
		#load the environment, it seems that an x value of zero, a y value of -50 puts the origin point relatively in the middle of the crater
		filename = PARAMS_PATH + "environment.txt"
		self.loadLevelGeom(filename)
		#load the enemies
		filename = PARAMS_PATH + "enemies.txt"
		self.loadLevelEnemies(filename)
		
		#lookup table for actors
		self.actors = {}
		
		#place the player in the environment
		self.player = Player(self.controlScheme, self.camera, self, 0, 0, 0)
		self.player.setName("player")
		self.player.setH(180)
		self.player.reparentTo(self.unitNodePath)
		self.player.nodePath = self.render.find("player")
		self.actors["player"] = self.player
		
		
		#add some lights
		topLight = DirectionalLight("top light")
		topLight.setColor(Vec4(0.5, 0.5, 0.5, 1))
		topLight.setDirection(Vec3(0, -90, 0))
		self.render.setLight(self.render.attachNewNode(topLight))
		
		ambientLight = AmbientLight("ambient light")
		ambientLight.setColor(Vec4(0.5, 0.5, 0.5, 1))
		self.render.setLight(self.render.attachNewNode(ambientLight))
		
		#the distance the camera is from the player
		self.cameraHOffset = 45
		self.cameraVOffset = 10
		
		#add the collision sound
		self.collisionSound = self.loader.loadSfx(SFX_PATH + "collide.wav")
		
		#register the update task
		self.taskMgr.add(self.updateGame, "updateGame")
		
		#add targeting to the world
		self.setupTargeting()
		
		#seed the random number generator
		random.seed()

		# configure the entire GUI
		self.setupGUI()

		# configure the title screen
		self.setupTitleScreen()
	
	def setupGUI(self):
		GUIFont = loader.loadFont(FONTS_PATH + 'orbitron-medium.ttf')
		
		"""
		self.debugText = TextNode('debug')
		self.debugText.setText("")
		self.debugText.setAlign(TextNode.ALeft)
		self.debugText.setFont(GUIFont)
		
		dTextNodePath = aspect2d.attachNewNode(self.debugText)
		dTextNodePath.setScale(0.075)
		dTextNodePath.setPos(-1.2, 0, -0.9)
		"""
		
		#INTRO
		self.introText = TextNode('intro')
		self.introText.setText("")
		self.introText.setAlign(TextNode.ALeft)
		self.introText.setFont(GUIFont)
		self.introText.setCardColor(0.1, 0.1, 0.1, 0.6)
		self.introText.setCardAsMargin(0.5, 0.5, 0.5, 0.5)
		self.introText.setCardDecal(True)
		self.introText.setWordwrap(30.0)
		
		self.iTextNodePath = aspect2d.attachNewNode(self.introText)
		self.iTextNodePath.setScale(0.06)
		self.iTextNodePath.setPos(-1.2, 0, -0.7)
		
		#image is 171 x 323
		self.leftMouseImage = OnscreenImage()
		self.leftMouseImage.setImage(GUI_PATH + "mouse-icon-left.png")
		self.leftMouseImage.setTransparency(1)
		self.leftMousePath = aspect2d.attachNewNode(self.leftMouseImage.node())
		
		self.rightMouseImage = OnscreenImage()
		self.rightMouseImage.setImage(GUI_PATH + "mouse-icon-right.png")
		self.rightMouseImage.setTransparency(1)
		self.rightMousePath = aspect2d.attachNewNode(self.rightMouseImage.node())
		
		self.middleMouseImage = OnscreenImage()
		self.middleMouseImage.setImage(GUI_PATH + "mouse-icon-middle.png")
		self.middleMouseImage.setTransparency(1)
		self.middleMousePath = aspect2d.attachNewNode(self.middleMouseImage.node())
		
		self.leftMousePath.setScale(.105882, 0, .2)
		self.leftMousePath.setPos(1.1, 0, -0.75)
		self.rightMousePath.setScale(.105882, 0, .2)
		self.rightMousePath.setPos(1.1, 0, -0.75)
		self.middleMousePath.setScale(.105882, 0, .2)
		self.middleMousePath.setPos(1.1, 0, -0.75)
		
		self.leftMousePath.hide()
		self.rightMousePath.hide()
		self.middleMousePath.hide()
		
		#HUD
		#image is 365 x 187
		self.attackModeImage = OnscreenImage()
		self.attackModeImage.setImage(GUI_PATH + "mode-area.png")
		self.attackModeImage.setTransparency(1)
		
		modeNodePath = aspect2d.attachNewNode(self.attackModeImage.node())
		modeNodePath.setScale(.136631, 0, .07)
		modeNodePath.setPos(-1.13, 0, 0.88)
		
		self.energyBarImage = OnscreenImage()
		self.energyBarImage.setImage(GUI_PATH + "energy-bar-full.png")
		self.energyBarImage.setTransparency(1)
		
		eBarNodePath = aspect2d.attachNewNode(self.energyBarImage.node())
		eBarNodePath.setScale(.400, 0, .0475)
		eBarNodePath.setPos(-0.66, 0, 0.88)
		
		self.healthBarImage = OnscreenImage()
		self.healthBarImage.setImage(GUI_PATH + "health-bar-full.png")
		self.healthBarImage.setTransparency(1)
		
		hBarNodePath = aspect2d.attachNewNode(self.healthBarImage.node())
		hBarNodePath.setScale(.400, 0, .0475)
		hBarNodePath.setPos(0.85, 0, 0.88)
	
	def setupTitleScreen(self):
		self.titleScreenIsActive = True
		
		#image is 800 x 600
		self.titleImage = OnscreenImage()
		self.titleImage.setImage(GUI_PATH + "title.png")
		
		titleNodePath = aspect2d.attachNewNode(self.titleImage.node())
		titleNodePath.setScale(1.33333, 0, 1)
		titleNodePath.setPos(0, 0, 0)
	
	def updateTitleScreen(self):
		if (self.controlScheme.keyDown(PUSH) or self.controlScheme.keyDown(PULL) or self.controlScheme.keyDown(SWITCH)) and self.titleScreenIsActive:
			self.titleImage.hide()
			self.titleScreenIsActive = False
		elif self.titleScreenIsActive:
			self.titleImage.setImage(GUI_PATH + "title.png")
			self.globalTime=0
		else:
			pass
	
	def calculateBarImage(self, level):
		if level == 0:
			level = "empty"
		elif level == 10:
			level = "full"
		elif level == 1:
			level = "1"
		elif level == 2:
			level = "2"
		elif level == 3:
			level = "3"
		elif level == 4:
			level = "4"
		elif level == 5:
			level = "5"
		elif level == 6:
			level = "6"
		elif level == 7:
			level = "7"
		elif level == 8:
			level = "8"
		elif level == 9:
			level = "9"
		
		return level
	
	def updateGUI(self):
		"""
		self.debugText.setText("Energy: "+str((100*self.player.energy/self.player.maxEnergy))+"%, Health: "+str((100*self.player.health/self.player.maxHealth)))
		"""
		
		self.updateIntro()
		
		if self.player.currentWeapon == AREA:
			modeImg = "mode-area"
		elif self.player.currentWeapon == NARROW:
			modeImg = "mode-narrow"
		
		energyLevel = self.calculateBarImage((100 * (self.player.energy / self.player.maxEnergy)) // 10)
		self.energyBarImage.setImage(GUI_PATH + "energy-bar-" + energyLevel + ".png")
		self.energyBarImage.setTransparency(1)
		
		self.attackModeImage.setImage(GUI_PATH + modeImg + ".png")
		self.attackModeImage.setTransparency(1)
		
		healthLevel = self.calculateBarImage((100 * (self.player.health / self.player.maxHealth)) // 10)
		self.healthBarImage.setImage(GUI_PATH + "health-bar-" + healthLevel + ".png")
		self.healthBarImage.setTransparency(1)
	
	def updateIntro(self):
		modifiedTime = self.globalTime/5
		
		if self.introText is None:
			pass
		elif modifiedTime>=14300 and self.introText is not None:
			self.iTextNodePath.removeNode()
			self.introText = None
		elif modifiedTime<300:		#0-300
			self.introText.setText("Hey are you receiving?")
		elif modifiedTime<800:	#300-800
			self.introText.setText("We recently uncovered the location of an old cruiser wreck from the war.")
		elif modifiedTime<1500:	#800-1500
			self.introText.setText("You're gonna go in there and get the little bits of it that are still worth salvaging.")
		elif modifiedTime<2900:	#1500-2900
			self.introText.setText("Be aware though, this job may not be quite as simple as a grab-and-run. The coordinates have been leaked to some of our old enemies.")
		elif modifiedTime<4200:	#2900-4200
			self.introText.setText("To give you an edge, we've made a few upgrades to your electromagnetic grapple.")
		elif modifiedTime<5300:	#4200-5300
			self.introText.setText("Pull enemies inwards with the right mouse button.")
			self.leftMousePath.hide()
			self.rightMousePath.show()
			self.middleMousePath.hide()
		elif modifiedTime<6400:	#5300-6400
			self.introText.setText("Push enemies away with the left mouse button.")
			self.leftMousePath.show()
			self.rightMousePath.hide()
			self.middleMousePath.hide()
		elif modifiedTime<8500:	#6400-8500
			self.introText.setText("Toggle between your range and narrow electromagnet with the middle mouse button (or spacebar).")
			self.leftMousePath.hide()
			self.rightMousePath.hide()
			self.middleMousePath.show()
		elif modifiedTime<13300:	#8500-13300
			self.introText.setText("You can give a solid kick to anything straight in front of you or just push everything around you away. Try and throw 'em into each other or other wreckage to finish 'em off for good.")
			self.leftMousePath.hide()
			self.rightMousePath.hide()
			self.middleMousePath.hide()
		elif modifiedTime<14300:	#13300-14300
			self.introText.setText("After all, the more salvage left over, the better. Out.")
	
	def loadLevelGeom(self, filename):
		filename = os.path.abspath(filename)
		if not os.path.isfile(filename):
			print "FILE DOES NOT EXIST:"
			exit(1)
		
		#get the lines from the file
		textFileList = open(filename, 'r').readlines()
		
		if len(textFileList) < 1:
			print "FATAL ERROR READING FILE"
			exit(1)
			
		#now split each line into lists
		
		
		for num, val in enumerate(textFileList):
			val = val.rstrip('\n')#strip the newlines
			val = val.strip()
			textFileList[num] = val.split(TEXT_DELIMITER)
		
		
		obstacle = None
		
		for list in textFileList: #go through the list
			if list[0] == TERRAIN_OUTER:#do all the things for the terrain
				#choose the model
				modelVal = list[1]
				modelVal = (MODELS_PATH + modelVal)
				
				self.environment = self.loader.loadModel(modelVal)
				
				self.environment.reparentTo(self.render)
				
				#get the collision geometry for the environment
				#and move it up a bit to allow the character to float above the crater
				self.craterCollision = self.environment.find("**/craterCollisionPlane")
				self.craterCollision.setZ(self.environment.getZ() + 0.15)
				self.environment.setCollideMask(BitMask32.allOff())
				self.craterCollision.setCollideMask(BitMask32(TERRAIN_RAY_MASK))
				
				#self.environment.find( #.find("craterCollisionPlane").setZ(self.environment.getZ() + 10)
				
				#set scale
				scaleVal = list[2].split(',')#split by commas
				self.environment.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2]))
				#set location
				locVal = list[3].split(',')
				self.environment.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#then we have our terrain
				#set rotation
				hprVal = list[4].split(',')
				self.environment.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2]))
				
				
			elif list[0] == TERRAIN_CUBE:
				#choose the model
				modelVal = list[1]
				modelVal = (MODELS_PATH + modelVal)
				#load the model
				obstacle = self.loader.loadModel(modelVal)
				
				obstacle.reparentTo(render)
				#set scale
				scaleVal = list[2].split(',')
				obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2]))
				#set location
				locVal = list[3].split(',')
				obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object
				hprVal = list[4].split(',')
				obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2]))
				
				#set up collisions
				unitCollision = obstacle.find("**/CubeBlock")
				unitCollision.node().setName("cube")
				obstacle.setCollideMask(BitMask32.allOff())
				unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS))
				
				self.obstacles.append(obstacle)
				
			elif list[0] == TERRAIN_WING:
				modelVal = list[1]
				modelVal = (MODELS_PATH + modelVal)
				#load the model
				obstacle = self.loader.loadModel(modelVal)
				
				obstacle.reparentTo(render)
				#set scale
				scaleVal = list[2].split(',')
				obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2]))
				#set location
				locVal = list[3].split(',')
				obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object
				hprVal = list[4].split(',')
				obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2]))
				
				#set up collisions
				unitCollision = obstacle.find("**/wingCollider")
				unitCollision.node().setName("wing")
				obstacle.setCollideMask(BitMask32.allOff())
				unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS))
				
				self.obstacles.append(obstacle)
				
			elif list[0] == TERRAIN_BAR:
				modelVal = list[1]
				modelVal = (MODELS_PATH + modelVal)
				#load the model
				obstacle = self.loader.loadModel(modelVal)
				
				obstacle.reparentTo(render)
				#set scale
				scaleVal = list[2].split(',')
				obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2]))
				#set location
				locVal = list[3].split(',')
				obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object
				hprVal = list[4].split(',')
				obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2]))
				
				#set up collisions
				unitCollision = obstacle.find("**/metalBarCollisionCube")
				unitCollision.node().setName("bar")
				obstacle.setCollideMask(BitMask32.allOff())
				unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS))
				
			elif list[0] == TERRAIN_SHARDS:
				modelVal = list[1]
				modelVal = (MODELS_PATH + modelVal)
				#load the model
				obstacle = self.loader.loadModel(modelVal)
				
				obstacle.reparentTo(render)
				#set scale
				scaleVal = list[2].split(',')
				obstacle.setScale(float(scaleVal[0]), float(scaleVal[1]), float(scaleVal[2]))
				#set location
				locVal = list[3].split(',')
				obstacle.setPos(float(locVal[0]), float(locVal[1]), float(locVal[2]))#the we have our object
				hprVal = list[4].split(',')
				obstacle.setHpr(float(hprVal[0]), float(hprVal[1]), float(hprVal[2]))
				
				#set up collisions
				unitCollision = obstacle.find("**/metalShardCollisionCube")
				unitCollision.node().setName("shard")
				obstacle.setCollideMask(BitMask32.allOff())
				unitCollision.setCollideMask(BitMask32(PLAYER_ENEMY_OBJECTS))
				
			else:
				print "FATAL ERROR READING FILE"
				exit(1)
			
		pass
		
	def loadLevelEnemies(self, filename):
		filename = os.path.abspath(filename)
		if not os.path.isfile(filename):
			print "FILE DOES NOT EXIST:"
			exit(1)
		
		#get the lines from the file and split them
		textFileList = open(filename, 'r').readlines()
		if len(textFileList) < 1:
			print "FATAL ERROR READING FILE"
			exit(1)
		
		for num, val in enumerate(textFileList):
			val = val.rstrip('\n')#strip the newlines
			val = val.strip()
			textFileList[num] = val.split(TEXT_DELIMITER)
		
		currwave = dict()
		currwave["time"] = None
		currwave["enemies"] = []
		currEnem = dict()
		
		for val in textFileList:
			if val[0] == BEGIN_WAVE:
				currwave = dict()
				currwave["time"] = float(val[1])#set your time
				currwave["enemies"] = []
			elif val[0] == RUSH_ENEMY:
				currEnem = dict()
				pos = []
				pos = val[1].split(',')#get the three values for spawning, not floats
				currEnem["type"] = RUSH_ENEMY
				currEnem["xVal"] = float(pos[0])
				currEnem["yVal"] = float(pos[1])
				currEnem["zVal"] = float(pos[2])
				currwave["enemies"].append(dict(currEnem))#copy
			elif val[0] == DRONE_ENEMY:
				currEnem = dict()
				pos = []
				pos = val[1].split(',')#get the three values for spawning, not floats
				currEnem["type"] = DRONE_ENEMY
				currEnem["xVal"] = float(pos[0])
				currEnem["yVal"] = float(pos[1])
				currEnem["zVal"] = float(pos[2])
				currwave["enemies"].append(dict(currEnem))#copy
			elif val[0] == SHOOTING_ENEMY:
				currEnem = dict()
				pos = []
				pos = val[1].split(',')#get the three values for spawning, not floats
				currEnem["type"] = SHOOTING_ENEMY
				currEnem["xVal"] = float(pos[0])
				currEnem["yVal"] = float(pos[1])
				currEnem["zVal"] = float(pos[2])
				currwave["enemies"].append(dict(currEnem))#copy
			elif val[0] == END_WAVE:#then we are done with that wave
				self.eSpawnList.append(dict(currwave))#copy
			else:
				pass#then something was stupid
			
		#now sort your waves with lowest time first	
		self.eSpawnList.sort(key = lambda object: object["time"])
		#and you're done
	
	def updateGame(self, task):
		
		if not self.titleScreenIsActive:
			self.globalTime = self.globalTime + task.time
			elapsedTime = task.time - self.previousFrameTime
			#base.resetPrevTransform(render)#for our high intensity collision detection
		
		if self.controlScheme.keyDown(QUIT):
			exit(0)
		
		if not self.paused and not self.titleScreenIsActive:
			time = elapsedTime
			while time > 0.02:
				self.updateGameComponents(0.02)
				time -= 0.02
			self.updateGameComponents(time)
			
			self.cTrav.traverse(render)
			
			self.spawnEnemies()#globalTime is available
		if self.controlScheme.keyDown(PAUSE):
			if not self.pauseWasPressed:
				self.paused = not self.paused
				self.controlScheme.resetMouse()
				self.pauseWasPressed = True
		else:
			self.pauseWasPressed = False
		
		self.updateGUI()
		self.updateTitleScreen()
		
		self.previousFrameTime = task.time
		
		return task.cont
	
	def updateGameComponents(self, time):
		'''
		Updates the state of the world.
		@precondition: The game isn't paused. 
		'''
		self.updateCamera(time)
		for enemy in self.enemies:
			enemy.update(time)
		for projectile in self.projectiles:
			projectile.update(time)
			
		#check for basic terrain collisions
		self.player.terrainCollisionCheck()
		self.player.update(time)
		for enemy in self.enemies:
			enemy.terrainCollisionCheck()
		for projectile in self.projectiles:
			projectile.terrainCollisionCheck()
		
	def spawnEnemies(self):#now we spawn our enemies
		while((len(self.eSpawnList) > 0) and self.eSpawnList[0]["time"] < self.globalTime):
			for val in self.eSpawnList[0]["enemies"]:
				if val["type"] == RUSH_ENEMY:
					#add an enemy
					tempEnemy = RushEnemy(self, val["xVal"], val["yVal"], val["zVal"])
					self.configureEnemy(tempEnemy)
				elif val["type"] == DRONE_ENEMY:
					#add an enemy
					tempEnemy = DroneEnemy(self, self.player, val["xVal"], val["yVal"], val["zVal"])
					self.configureEnemy(tempEnemy)
				elif val["type"] == SHOOTING_ENEMY:
					#add an enemy
					tempEnemy = ShootingEnemy(self, val["xVal"], val["yVal"], val["zVal"])
					self.configureEnemy(tempEnemy)
				else: 
					pass
				
			del self.eSpawnList[0]#del
			
	
	def configureEnemy(self, tempEnemy):#after making an enemy configure it for the game
		numString = str(self.nextEnemy)
		tempEnemy.setName("enemy" + numString)
		tempEnemy.reparentTo(self.unitNodePath)
		tempEnemy.nodePath = self.render.find("enemy1")
		self.actors["enemy" + numString] = tempEnemy
		self.nextEnemy = self.nextEnemy + 1
		self.enemies.append(tempEnemy)
		
	
	def rotateCamera(self):
		if self.controlScheme.mouseX > self.winProps.getXSize():
			self.camera.setH(-(self.winProps.getXSize() - 20) * 0.5)
		else:
			self.camera.setH(-self.controlScheme.mouseX * 0.5)
	
	def updateCamera(self, elapsedTime):
		#update the camera's heading based on the mouse's x position
		if self.controlScheme.recheckMouse():
			self.camera.setH(-self.controlScheme.mouseX * 0.5)
		else:
			self.rotateCamera()
		
		#update the camera's pitch and vertical position based on the mouse's y position
		self.cameraVOffset = min(self.screenHeight, max(0, self.controlScheme.mouseY)) / self.screenHeight * 25 + 4
		self.cameraHOffset = self.cameraVOffset * 0.8 + 30
		self.camera.setP(atan2(-self.cameraVOffset * 0.7, self.cameraHOffset) \
							* 180 / pi)
		
		#update the camera to point at the player
		self.camera.setPos(self.player.getX() + self.cameraHOffset * sin(self.camera.getH() * pi / 180),
						   self.player.getY() - self.cameraHOffset * cos(self.camera.getH() * pi / 180),
						   self.player.getZ() + 0.3 + self.cameraVOffset)
	
	def selectTarget(self):
		"""Finds the closest shootable object and returns it"""

		#traverse all objects in render
		self.mPickerTraverser.traverse(self.unitNodePath)

		if (self.mCollisionQue.getNumEntries() > 0):
			self.mCollisionQue.sortEntries()
			for i in range(0, self.mCollisionQue.getNumEntries()):
				entry = self.mCollisionQue.getEntry(i)
				pickedObj = entry.getIntoNodePath()
				
				if not pickedObj.isEmpty():
				
					name = pickedObj.getParent().getName()
					
					if name == "render":
						return None
					
					#if the object is shootable, set it as the target
					try:
						if self.actors[name].shootable:
							return self.actors[name]
					except:
						continue
		
		return None
	
	def setupTargeting(self):
		"""Set up the collisions necessary to target enemies and other objects"""
		
		#Since we are using collision detection to do picking, we set it up 
		#any other collision detection system with a traverser and a handler
		self.mPickerTraverser = CollisionTraverser()            #Make a traverser
		#self.mPickerTraverser.showCollisions(self.unitNodePath)
		self.mCollisionQue = CollisionHandlerQueue()

		#create a collision solid ray to detect against
		self.mPickRay = CollisionRay()
		self.mPickRay.setOrigin(self.player.getPos(self.render))
		self.mPickRay.setDirection(self.render.getRelativeVector(self.player, Vec3(0, 1, 0)))
		self.mPickRay2 = CollisionRay()
		self.mPickRay2.setOrigin(self.player.getPos(self.render))
		self.mPickRay2.setDirection(self.render.getRelativeVector(self.player, Vec3(0.06, 1, 0)))
		self.mPickRay3 = CollisionRay()
		self.mPickRay3.setOrigin(self.player.getPos(self.render))
		self.mPickRay3.setDirection(self.render.getRelativeVector(self.player, Vec3(-0.06, 1, 0)))
		self.mPickRay4 = CollisionRay()
		self.mPickRay4.setOrigin(self.player.getPos(self.render))
		self.mPickRay4.setDirection(self.render.getRelativeVector(self.player, Vec3(0, 1, 0.06)))
		self.mPickRay5 = CollisionRay()
		self.mPickRay5.setOrigin(self.player.getPos(self.render))
		self.mPickRay5.setDirection(self.render.getRelativeVector(self.player, Vec3(0, 1, -0.06)))

		#create our collison Node to hold the ray
		self.mPickNode = CollisionNode('pickRay')
		self.mPickNode.setIntoCollideMask(BitMask32.allOff())
		self.mPickNode.addSolid(self.mPickRay)
		self.mPickNode2 = CollisionNode('pickRay2')
		self.mPickNode2.setIntoCollideMask(BitMask32.allOff())
		self.mPickNode2.addSolid(self.mPickRay2)
		self.mPickNode3 = CollisionNode('pickRay3')
		self.mPickNode3.setIntoCollideMask(BitMask32.allOff())
		self.mPickNode3.addSolid(self.mPickRay3)
		self.mPickNode4 = CollisionNode('pickRay4')
		self.mPickNode4.setIntoCollideMask(BitMask32.allOff())
		self.mPickNode4.addSolid(self.mPickRay4)
		self.mPickNode5 = CollisionNode('pickRay5')
		self.mPickNode5.setIntoCollideMask(BitMask32.allOff())
		self.mPickNode5.addSolid(self.mPickRay5)

		#Attach that node to the player since the ray will need to be positioned
		#relative to it, returns a new nodepath		
		#well use the default geometry mask
		#this is inefficent but its for mouse picking only

		self.mPickNP = self.player.attachNewNode(self.mPickNode)
		self.mPickNP2 = self.player.attachNewNode(self.mPickNode2)
		self.mPickNP3 = self.player.attachNewNode(self.mPickNode3)
		self.mPickNP4 = self.player.attachNewNode(self.mPickNode4)
		self.mPickNP5 = self.player.attachNewNode(self.mPickNode5)

		#well use what panda calls the "from" node.  This is really a silly convention
		#but from nodes are nodes that are active, while into nodes are usually passive environments
		#this isnt a hard rule, but following it usually reduces processing

		#Everything to be picked will use bit 1. This way if we were doing other
		#collision we could seperate it, we use bitmasks to determine what we check other objects against
		#if they dont have a bitmask for bit 1 well skip them!
		#self.mPickNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
		self.mPickNode.setFromCollideMask(PLAYER_ENEMY_OBJECTS)
		self.mPickNode2.setFromCollideMask(PLAYER_ENEMY_OBJECTS)
		self.mPickNode3.setFromCollideMask(PLAYER_ENEMY_OBJECTS)
		self.mPickNode4.setFromCollideMask(PLAYER_ENEMY_OBJECTS)
		self.mPickNode5.setFromCollideMask(PLAYER_ENEMY_OBJECTS)

		#Register the ray as something that can cause collisions
		self.mPickerTraverser.addCollider(self.mPickNP, self.mCollisionQue)
		self.mPickerTraverser.addCollider(self.mPickNP2, self.mCollisionQue)
		self.mPickerTraverser.addCollider(self.mPickNP3, self.mCollisionQue)
		self.mPickerTraverser.addCollider(self.mPickNP4, self.mCollisionQue)
		self.mPickerTraverser.addCollider(self.mPickNP5, self.mCollisionQue)
	
	def handleUnitIntoCollision(self, entry):
		try:
			fromName = entry.getFromNodePath().getParent().getName()
			intoName = entry.getIntoNodePath().getParent().getName()
			Unit.collideWithUnit(self.actors[intoName], self.actors[fromName])
			if (fromName == "player" or intoName == "player") and self.collisionSound.status() is not self.collisionSound.PLAYING:
				self.collisionSound.play()
		except:
			pass
	
	def handleUnitOutCollision(self, entry):
		pass
	
	def handleWingIntoCollision(self, entry):
		fromName = entry.getFromNodePath().getParent().getName()
		Unit.collideWithObstacle(self.actors[fromName])
		if fromName == "player" and self.collisionSound.status() is not self.collisionSound.PLAYING:
			self.collisionSound.play()
	
	def handleCubeIntoCollision(self, entry):
		try:
			fromName = entry.getFromNodePath().getParent().getName()
			Unit.collideWithObstacle(self.actors[fromName])
			if fromName == "player" and self.collisionSound.status() is not self.collisionSound.PLAYING:
				self.collisionSound.play()
		except:
			pass
	
	def handleBarIntoCollision(self, entry):
		fromName = entry.getFromNodePath().getParent().getName()
		Unit.collideWithObstacle(self.actors[fromName])
		if fromName == "player" and self.collisionSound.status() is not self.collisionSound.PLAYING:
			self.collisionSound.play()
	
	def gameOver(self):
		pass
Beispiel #17
0
def mousePick(status):
  if pickingEnabled:
    if status == 'down':
      smileyModel.setScale(.9)

  if status == 'up':
    smileyModel.setScale(1.0)

# Here as well we see something already seen in the previous steps related to collision events so I won't go into details.
collisionHandler.addInPattern('%fn-into-%in')
collisionHandler.addOutPattern('%fn-out-%in')

#** Let's manage now the collision events:
DO=DirectObject()
# if you went from step3 and step4, here should not be mysteries for you
DO.accept('mouseraycnode-into-smileycnode', collideEventIn)
DO.accept('mouseraycnode-out-smileycnode', collideEventOut)

#** This little but important variable will be used to know the picking state at any time - note that the picking is enabled ASA the mouse pointer goes above the ball and disabled when it leave.
pickingEnabled=False

#** This is how we interact with mouse clicks - see the mousePick function above for details
DO.accept('mouse1', mousePick, ['down'])
DO.accept('mouse1-up', mousePick, ['up'])

#** And at last, we start the task that continuously update the ray collider position and orientation while we move the mouse pointer
taskMgr.add(rayupdate, "updatePicker")

splash.destroy()
run()
Beispiel #18
0
class SCTerminal(SCElement):
    """ SCTerminal is the base class for all 'terminal' speedchat
    entities """
    def __init__(self, linkedEmote=None):
        SCElement.__init__(self)
        self.setLinkedEmote(linkedEmote)

        scGui = loader.loadModel(SCMenu.GuiModelName)
        self.emotionIcon = scGui.find('**/emotionIcon')
        self.setDisabled(False)
        self.__numCharges = -1

        # should we listen for whisper mode changes?
        self._handleWhisperModeSV = StateVar(False)
        # can't set this up until we're ready to have the handler func called
        self._handleWhisperModeFC = None

    def destroy(self):
        self._handleWhisperModeSV.set(False)
        if self._handleWhisperModeFC:
            self._handleWhisperModeFC.destroy()
        self._handleWhisperModeSV.destroy()
        SCElement.destroy(self)

    def privSetSettingsRef(self, settingsRef):
        SCElement.privSetSettingsRef(self, settingsRef)
        if self._handleWhisperModeFC is None:
            self._handleWhisperModeFC = FunctionCall(
                self._handleWhisperModeSVChanged, self._handleWhisperModeSV)
            self._handleWhisperModeFC.pushCurrentState()
        # if this terminal is not whisperable, we need to listen for whisper mode changes
        self._handleWhisperModeSV.set((self.settingsRef is not None)
                                      and (not self.isWhisperable()))

    def _handleWhisperModeSVChanged(self, handleWhisperMode):
        if handleWhisperMode:
            # this terminal can't be whispered. we need to reconstruct
            # our GUI element when the whisper mode changes
            # listen for that mode change
            # create a DirectObject to avoid conflicts with other parts of this
            # object that are listening for this event
            self._wmcListener = DirectObject()
            self._wmcListener.accept(
                self.getEventName(SCWhisperModeChangeEvent),
                self._handleWhisperModeChange)
        else:
            if hasattr(self, '_wmcListener'):
                # we no longer need to listen for whisper mode changes
                self._wmcListener.ignoreAll()
                del self._wmcListener
                # make sure our GUI element is appropriate
                self.invalidate()

    def _handleWhisperModeChange(self, whisperMode):
        # whisper mode changed, we need to change our GUI element
        self.invalidate()

    # the meat of SCTerminal; inheritors should override this
    # and perform the appropriate action
    def handleSelect(self):
        """ called when the user selects this node """
        # send the generic 'something was selected' event
        messenger.send(self.getEventName(SCTerminalSelectedEvent))

        # if we have a linked emote, and it isn't disabled, generate a msg
        if self.hasLinkedEmote() and self.linkedEmoteEnabled():
            messenger.send(self.getEventName(SCTerminalLinkedEmoteEvent),
                           [self.linkedEmote])

    def isWhisperable(self):
        # can this terminal be sent as a whisper message?
        return True

    # Some terminal nodes have an emote associated with them, which
    # should be invoked when the node is selected.
    def getLinkedEmote(self):
        return self.linkedEmote

    def setLinkedEmote(self, linkedEmote):
        self.linkedEmote = linkedEmote
        # TODO: we should make sure we're listening for emote
        # enable state changes if this is set while we're visible
        self.invalidate()

    def hasLinkedEmote(self):
        return (self.linkedEmote is not None)

    def linkedEmoteEnabled(self):
        if Emote.globalEmote:
            return Emote.globalEmote.isEnabled(self.linkedEmote)

    def getCharges(self):
        return self.__numCharges

    def setCharges(self, nCharges):
        self.__numCharges = nCharges
        if (nCharges == 0):
            self.setDisabled(True)

    # support for disabled terminals
    def isDisabled(self):
        return self.__disabled or (self.isWhispering()
                                   and not self.isWhisperable())

    def setDisabled(self, bDisabled):
        # make the button 'unclickable'
        self.__disabled = bDisabled

    # from SCElement
    def onMouseClick(self, event):
        if not self.isDisabled():
            SCElement.onMouseClick(self, event)
            self.handleSelect()

    def getMinDimensions(self):
        width, height = SCElement.getMinDimensions(self)
        if self.hasLinkedEmote():
            # add space for the emotion icon
            width += 1.3
        return width, height

    def finalize(self, dbArgs={}):
        """ catch this call and influence the appearance of our button """
        if not self.isDirty():
            return

        args = {}

        if self.hasLinkedEmote():
            self.lastEmoteIconColor = self.getEmoteIconColor()
            self.emotionIcon.setColorScale(*self.lastEmoteIconColor)
            args.update({
                'image': self.emotionIcon,
                'image_pos': (self.width - .6, 0, -self.height * .5),
            })

        if self.isDisabled():
            args.update({
                'rolloverColor': (0, 0, 0, 0),
                'pressedColor': (0, 0, 0, 0),
                'rolloverSound':
                None,
                'clickSound':
                None,
                'text_fg':
                self.getColorScheme().getTextDisabledColor() + (1, ),
            })

        args.update(dbArgs)
        SCElement.finalize(self, dbArgs=args)

    def getEmoteIconColor(self):
        if self.linkedEmoteEnabled() and (not self.isWhispering()):
            r, g, b = self.getColorScheme().getEmoteIconColor()
        else:
            r, g, b = self.getColorScheme().getEmoteIconDisabledColor()
        return (r, g, b, 1)

    def updateEmoteIcon(self):
        if hasattr(self, 'button'):
            self.lastEmoteIconColor = self.getEmoteIconColor()
            for i in range(self.button['numStates']):
                self.button['image%s_image' %
                            i].setColorScale(*self.lastEmoteIconColor)
        else:
            self.invalidate()

    # from SCObject
    def enterVisible(self):
        SCElement.enterVisible(self)

        # Check if the emote state has changed since the last time
        # we were finalized, and invalidate if it's different.
        if hasattr(self, 'lastEmoteIconColor'):
            if self.getEmoteIconColor() != self.lastEmoteIconColor:
                self.invalidate()

        # listen for whisper-mode changes
        def handleWhisperModeChange(whisperMode, self=self):
            if self.hasLinkedEmote():
                # we are leaving or entering whisper mode;
                # the appearance of our emote icon needs to change
                # (no linked emotes on whispers)
                if self.isVisible() and not self.isWhispering():
                    self.updateEmoteIcon()

        self.accept(self.getEventName(SCWhisperModeChangeEvent),
                    handleWhisperModeChange)

        # listen for emote-enable state changes
        def handleEmoteEnableStateChange(self=self):
            if self.hasLinkedEmote():
                # emotions have just become enabled/disabled
                # update our emote icon
                # (no emotes when whispering)
                if self.isVisible() and not self.isWhispering():
                    self.updateEmoteIcon()

        if self.hasLinkedEmote():
            if Emote.globalEmote:
                self.accept(Emote.globalEmote.EmoteEnableStateChanged,
                            handleEmoteEnableStateChange)

    def exitVisible(self):
        SCElement.exitVisible(self)
        self.ignore(self.getEventName(SCWhisperModeChangeEvent))
        if Emote.globalEmote:
            self.ignore(Emote.globalEmote.EmoteEnableStateChanged)

    def getDisplayText(self):
        if self.getCharges() != -1:
            return self.text + " (%s)" % self.getCharges()
        return self.text
Beispiel #19
0
                                      #     inside the scrollable window.
                                      # 0 : does not block mouse wheel events from being sent to all other objects.
                                      #     You can scroll the window by holding down the modifier key
                                      #     (defined below) while scrolling your wheel.
               modifier='control'  # shift/control/alt
               )
   # populate the list with alphabets and numbers
   for a in string.ascii_letters+string.digits:
       # extraArgs would be passed to command and contextMenu
       btnList.addItem(text='item  '+(a+' ')*10, extraArgs=a, atIndex=None)
   btnList.setAutoFocus(1)  # after adding those items,
                            # enable auto view-focus on newly added item

   DO=DirectObject()
   # events for btnList
   DO.accept('h',btnList.hide)
   DO.accept('s',btnList.show)
   DO.accept('space',btnList.toggleVisibility)
   DO.accept('delete',btnList.destroy)
   DO.accept('enter',addNewItem)
   DO.accept('enter-repeat',addNewItem)
   DO.accept('insert',insertNewItemAtSelected)
   DO.accept('insert-repeat',insertNewItemAtSelected)
   DO.accept('control-insert',insertNewItemBelowSelected)
   DO.accept('control-insert-repeat',insertNewItemBelowSelected)
   DO.accept('caps_lock-repeat',disableRandomItem)
   DO.accept('tab-repeat',enableRandomItem)
   DO.accept('x-repeat',removeRandomItem)
   # events for the world
   DO.accept('wheel_up',teapot.setScale,[teapot,1.2])
   DO.accept('wheel_down',teapot.setScale,[teapot,.8])
Beispiel #20
0
but then we should have used 2 accepts like this:

DO.accept('ray1-again-smileys', collideAgainBalls)
DO.accept('ray1-again-frowney', collideAgainBalls)

instead of just one as we did below, and this don't hurt very much in this snippet cos' we got just 2 groups, but could be complicated if we need to use a lot more groups.

Another big thing to note is that we could have been done all of this using the masking technique (see step4.py).
"""

#** to manage the collision events need Directobject, because the chaining between the CollisionHandlerEvent handler and our two functions seen above, happens with the accept() function of a DirectObject instance
DO = DirectObject()

#** Let's manage the collision events: as you can see in this rack of 4 accepts, these are the resulting events generated by the patterns defined above. Now it's up to you to understand the why an the how comparing these with those above.
DO.accept('ray1-into-smiley', collideInSmiley)
DO.accept('ray1-out-smiley', collideOutSmiley)
DO.accept('ray1-into-frowney', collideInFrowney)
DO.accept('ray1-out-frowney', collideOutFrowney)
# the event here instead, will call the collideAgainBalls function handler while the mouse pointer keep over any ball, either of the smiley or the frowney groups - still, check above how we defined the pattern string to understand how we came to this.
DO.accept('ray_again_all', collideAgainBalls)

#** Storage for the object actually hovered by the mouse pointer
pickingEnabledOject = None

#** Here's how we interact with mouse clicks - see the mouseClick function above
DO.accept('mouse1', mouseClick, ['down'])
DO.accept('mouse1-up', mouseClick, ['up'])

#** And at the end of all, we start the task that continuously update the ray collider position and orientation while we move the mouse pointer
taskMgr.add(rayupdate, "updatePicker")
Beispiel #21
0
class SCTerminal(SCElement):

    def __init__(self, linkedEmote = None):
        SCElement.__init__(self)
        self.setLinkedEmote(linkedEmote)
        scGui = loader.loadModel(SCMenu.GuiModelName)
        self.emotionIcon = scGui.find('**/emotionIcon')
        self.setDisabled(False)
        self.__numCharges = -1
        self._handleWhisperModeSV = StateVar(False)
        self._handleWhisperModeFC = None
        return

    def destroy(self):
        self._handleWhisperModeSV.set(False)
        if self._handleWhisperModeFC:
            self._handleWhisperModeFC.destroy()
        self._handleWhisperModeSV.destroy()
        SCElement.destroy(self)

    def privSetSettingsRef(self, settingsRef):
        SCElement.privSetSettingsRef(self, settingsRef)
        if self._handleWhisperModeFC is None:
            self._handleWhisperModeFC = FunctionCall(self._handleWhisperModeSVChanged, self._handleWhisperModeSV)
            self._handleWhisperModeFC.pushCurrentState()
        self._handleWhisperModeSV.set(self.settingsRef is not None and not self.isWhisperable())
        return

    def _handleWhisperModeSVChanged(self, handleWhisperMode):
        if handleWhisperMode:
            self._wmcListener = DirectObject()
            self._wmcListener.accept(self.getEventName(SCWhisperModeChangeEvent), self._handleWhisperModeChange)
        elif hasattr(self, '_wmcListener'):
            self._wmcListener.ignoreAll()
            del self._wmcListener
            self.invalidate()

    def _handleWhisperModeChange(self, whisperMode):
        self.invalidate()

    def handleSelect(self):
        messenger.send(self.getEventName(SCTerminalSelectedEvent))
        if self.hasLinkedEmote() and self.linkedEmoteEnabled():
            messenger.send(self.getEventName(SCTerminalLinkedEmoteEvent), [self.linkedEmote])

    def isWhisperable(self):
        return True

    def getLinkedEmote(self):
        return self.linkedEmote

    def setLinkedEmote(self, linkedEmote):
        self.linkedEmote = linkedEmote
        self.invalidate()

    def hasLinkedEmote(self):
        return self.linkedEmote is not None

    def linkedEmoteEnabled(self):
        if Emote.globalEmote:
            return Emote.globalEmote.isEnabled(self.linkedEmote)

    def getCharges(self):
        return self.__numCharges

    def setCharges(self, nCharges):
        self.__numCharges = nCharges
        if nCharges is 0:
            self.setDisabled(True)

    def isDisabled(self):
        return self.__disabled or self.isWhispering() and not self.isWhisperable()

    def setDisabled(self, bDisabled):
        self.__disabled = bDisabled

    def onMouseClick(self, event):
        if not self.isDisabled():
            SCElement.onMouseClick(self, event)
            self.handleSelect()

    def getMinDimensions(self):
        width, height = SCElement.getMinDimensions(self)
        if self.hasLinkedEmote():
            width += 1.3
        return (width, height)

    def finalize(self, dbArgs = {}):
        if not self.isDirty():
            return
        args = {}
        if self.hasLinkedEmote():
            self.lastEmoteIconColor = self.getEmoteIconColor()
            self.emotionIcon.setColorScale(*self.lastEmoteIconColor)
            args.update({'image': self.emotionIcon,
             'image_pos': (self.width - 0.6, 0, -self.height * 0.5)})
        if self.isDisabled():
            args.update({'rolloverColor': (0, 0, 0, 0),
             'pressedColor': (0, 0, 0, 0),
             'rolloverSound': None,
             'clickSound': None,
             'text_fg': self.getColorScheme().getTextDisabledColor() + (1,)})
        args.update(dbArgs)
        SCElement.finalize(self, dbArgs=args)
        return

    def getEmoteIconColor(self):
        if self.linkedEmoteEnabled() and not self.isWhispering():
            r, g, b = self.getColorScheme().getEmoteIconColor()
        else:
            r, g, b = self.getColorScheme().getEmoteIconDisabledColor()
        return (r,
         g,
         b,
         1)

    def updateEmoteIcon(self):
        if hasattr(self, 'button'):
            self.lastEmoteIconColor = self.getEmoteIconColor()
            for i in xrange(self.button['numStates']):
                self.button['image%s_image' % i].setColorScale(*self.lastEmoteIconColor)

        else:
            self.invalidate()

    def enterVisible(self):
        SCElement.enterVisible(self)
        if hasattr(self, 'lastEmoteIconColor'):
            if self.getEmoteIconColor() != self.lastEmoteIconColor:
                self.invalidate()

        def handleWhisperModeChange(whisperMode, self = self):
            if self.hasLinkedEmote():
                if self.isVisible() and not self.isWhispering():
                    self.updateEmoteIcon()

        self.accept(self.getEventName(SCWhisperModeChangeEvent), handleWhisperModeChange)

        def handleEmoteEnableStateChange(self = self):
            if self.hasLinkedEmote():
                if self.isVisible() and not self.isWhispering():
                    self.updateEmoteIcon()

        if self.hasLinkedEmote():
            if Emote.globalEmote:
                self.accept(Emote.globalEmote.EmoteEnableStateChanged, handleEmoteEnableStateChange)

    def exitVisible(self):
        SCElement.exitVisible(self)
        self.ignore(self.getEventName(SCWhisperModeChangeEvent))
        if Emote.globalEmote:
            self.ignore(Emote.globalEmote.EmoteEnableStateChanged)

    def getDisplayText(self):
        if self.getCharges() is not -1:
            return self.text + ' (%s)' % self.getCharges()
        else:
            return self.text
Beispiel #22
0
    colliderINTO = entry.getIntoNodePath().getParent()
    # we now may change the aspect of the two colliding objects
    colliderINTO.setColor(1, 1, 1, 1)
    colliderFROM.setScale(1.5)


#... and this when they leave each other alone.
def collideEventOut(entry):
    colliderFROM = entry.getFromNodePath().getParent()
    colliderINTO = entry.getIntoNodePath().getParent()
    colliderINTO.setColor(.4, .4, .4, 1)
    colliderFROM.setScale(1.0)


#** Here's the definition of the patterns that should catch our collisions - note that just these two are enough to catch the 2 couple of combinations.
collisionHandler.addInPattern('%fn-into-%in')
collisionHandler.addOutPattern('%fn-out-%in')

#** Let's manage the collision events:
DO = DirectObject()
# we should provide a couple of event strings for each couple of interacting objects (remember we made the smiley react against the whole heart and the frowney with the broken one). Compare these strings with the patterns above and if it is not enough to understand why it works, go back and dig again step2 and step3 until they're clear for you.
# Note that we route the in and out events to the same functions for both couples but that is just to slim the code.
DO.accept('collider_heart-into-smileycnode', collideEventIn)
DO.accept('collider_heart-out-smileycnode', collideEventOut)
#
DO.accept('collider_brkheart-into-frowneycnode', collideEventIn)
DO.accept('collider_brkheart-out-frowneycnode', collideEventOut)

splash.destroy()
run()
Beispiel #23
0
class ScreenManager(object):
    '''
    Maintain all instances of screens within this class.
    Screen order is as follows:
    
    ScreenManager
     - render (root node)
       - modal node
         - individual screen nodes
         
    Each screen has its own node in the tree which is the parent of all objects drawn on that screen
    Changing screens is merely done by hiding the individual screen's parent node and show()ing the
    next screen's parent object node
    '''
    def __init__(self, game):
        '''
        Set up a 2d node and a 3d node for drawing 2d and 3d objects.
        
        All objects must be parented to their respective nodes in order to be rendered
        '''
        self.game = game
        self._flipNode = render.attachNewNode("flip_node")
        self._flipNode2d = aspect2d.attachNewNode("flip_node2d")

        if base.displayFlipped:
            self._flipNode.setScale(-1, 1, 1)
            self._flipNode2d.setScale(-1, 1, 1)

        self._node = self._flipNode.attachNewNode(PandaNode("screen_manager"))
        self._2dnode = self._flipNode2d.attachNewNode(
            PandaNode("2dscreen_manager"))
        self.logger = logging.getLogger("ScreenManager")
        self.logger.info("Initializing Screen Manager")

        # Create a dictionary to hold our screens
        self.screens = {}
        self.modal_screens = {}

        # This shows the frame rate meter at the top right of the screen for diagnostic purposes
        base.setFrameRateMeter(False)

        self.modaltext = None
        self.modal_text_color = ""
        self.modal_text_blink_status = False

        self.obj = DirectObject()

        self.debug_text = OnscreenText("",
                                       1,
                                       font=base.fontLoader.load('arial.ttf'),
                                       fg=(1, 1, 1, 1),
                                       pos=(1.2, -0.9),
                                       align=TextNode.ARight,
                                       scale=.05,
                                       mayChange=True,
                                       parent=self._2dnode)
        self.debug_text.hide()

    def loadScreens(self):
        '''
        Load all screens into the 'screens' dictionary for quick access.
        '''
        self.screens['boot'] = BootScreen(self)
        self.screens['svc_main_old'] = MainMenu(self)
        self.screens['svc_diagnostics'] = DiagnosticsMenu(self)
        self.screens['svc_update'] = UpdateCode(self)
        self.screens['svc_3d'] = ThreeDPlacement(self)
        self.screens['svc_main'] = MainMenu(self)
        self.screens['svc_flashers'] = Flashers(self)
        self.screens['svc_switches'] = Switches(self)
        self.screens['svc_log'] = Log(self)
        self.screens['stack'] = StackScreen(self)
        self.screens['attract1'] = PCCScreen(self)
        self.screens['attract2'] = DMIntroScreen(self)
        self.screens['attract3'] = HighScoreDisplay(self)
        self.screens['attract4'] = GameScoreDisplay(self)
        self.screens['attract5'] = ThanksDisplay(self)
        self.screens['blocks'] = BlocksScreen(self)
        self.screens['skillshot'] = SkillShotScreen(self)
        self.screens['score'] = ScoreScreen(self)
        self.screens['bonus'] = BonusScreen(self)
        self.screens['computer'] = ComputerScreen(self)
        self.screens['acmag'] = AcmagScreen(self)
        self.screens['match'] = MatchScreen(self)
        self.screens['wtsa'] = SanAngelesScreen(self)
        self.screens['carchase'] = CarChaseScreen(self)
        self.screens['extraball'] = ExtraBallScreen(self)
        self.screens['claw'] = ClawScreen(self)
        self.screens['simon_says'] = SimonSaysScreen(self)

    def getScreen(self, name):
        return self.screens[name]

    def registerEvents(self):
        self.logger.info("Registering event handlers")
        base.accept("update_score", self._onScoreUpdate)
        self.obj.accept("show_screen", self._thread_safe_showScreen)
        self.obj.accept("update_ball", self._onBallUpdate)

    def _onScoreUpdate(self, player, score):
        self.logger.info("onScoreUpdate triggered")
        self.screens['score'].update_score(player, score)

    def _onBallUpdate(self, ball):
        self.logger.info("onBallUpdate triggered")
        self.screens['score'].update_ball(ball)

    def showScreen(self, screen_name, hideOthers=True, hideScore=False):
        self.logger.info(
            "screenmanager::showScreen Thread: %s Screen: %s" %
            (str(threading.current_thread().getName()), screen_name))
        #base.messenger.send("show_screen", [screen_name, hideOthers, hideScore])
        #print base.display_queue
        base.display_queue.put_nowait(
            partial(self._thread_safe_showScreen,
                    screen_name=screen_name,
                    hideOthers=hideOthers,
                    hideScore=hideScore))

    def getShownScreens(self):
        shown_screens = []
        for screen in self.screens:
            if not self.screens[screen].is_hidden():
                shown_screens.append(screen)

        return shown_screens

    def _thread_safe_showScreen(self,
                                screen_name,
                                hideOthers=True,
                                hideScore=False):
        '''
        Show the given screen. If hideOthers is true, all other screens are hidden
        before showing the desired screen.
        '''

        if not screen_name in self.screens:
            self.logger.warning("Tried to show screen %s, not in screen list",
                                screen_name)
        if hideOthers:
            for screen in self.screens:
                if screen != 'score':
                    self.screens[screen].hide()

            if hideScore:
                self.screens['score'].hide()

        # Show the given screen
        self.screens[screen_name].show()
        self.logger.info(
            "Showing screen %s Thread %s" %
            (screen_name, str(threading.current_thread().getName())))

    def hideScreen(self, screen_name):
        self.logger.info("screenmanager::hideScreen %s" % (screen_name))
        base.display_queue.put_nowait(
            partial(self._thread_safe_hideScreen, screen_name=screen_name))

    def hideAllScreens(self):
        base.display_queue.put_nowait(partial(
            self._thread_safe_hideAllScreens))

    def _thread_safe_hideAllScreens(self):
        for screen in self.screens:
            self.screens[screen].hide()

    def _thread_safe_hideScreen(self, screen_name):
        self.screens[screen_name].hide()

    def getNode(self):
        '''
        Return the 3d node for this screen manager. This is useful for screens
        to obtain a node to parent objects to for drawing (done in the GameScreen constructor)
        '''
        return self._node

    def get2dNode(self):
        '''
        Return the 2d node for this screen manager.
        '''
        return self._2dnode

    def showDebugMessage(self, message):
        base.taskMgr.remove('hide_debugmsg')
        self.debug_text.setText(message)
        self.debug_text.show()
        base.taskMgr.doMethodLater(10,
                                   self.hideDebugMessage,
                                   'hide_debugmsg',
                                   extraArgs=[])

    def hideDebugMessage(self):
        self.debug_text.hide()

    def showModalMessage(self,
                         message,
                         modal_name="",
                         time=0,
                         scale=0.2,
                         font="arial.ttf",
                         fg=(1, 1, 0, 1),
                         bg=(0, 0, 0, 1),
                         frame_color=(1, 1, 0, 1),
                         animation="none",
                         start_location=None,
                         end_location=None,
                         animation_duration=2,
                         blink_speed=0,
                         blink_color=(0, 0, 0, 1),
                         frame_blink_color=None,
                         frame_width=4,
                         frame_margin=(0.1, 0.1, 0.1, 0.1)):
        #cardMaker.setFrame(-sizeX/2.0, sizeX/2.0, -sizeY/2.0, sizeY/2.0)
        if modal_name in self.modal_screens:
            self._hideModalMessage(modal_name)
            base.taskMgr.remove('hide_' + modal_name)

        if modal_name == "":
            modal_name = "modal_" + str(random.randint(1, 63463))

        modal_object = {}

        modal_object['modaltext'] = TextNode('modal')
        modal_object['modaltext'].setText(message)
        modal_object['modal_text_color'] = fg
        modal_object['blink_color'] = blink_color
        modal_object['modaltext'].setFont(base.fontLoader.load(font))
        modal_object['modaltext'].setTextColor(fg[0], fg[1], fg[2], fg[3])

        modal_object['modaltext'].setAlign(TextNode.ACenter)

        modal_object['blink_status'] = False

        if frame_blink_color == None:
            frame_blink_color = frame_color

        # Set our text shadows
        #self.modaltext.setShadow(0.05, 0.05)
        #self.modaltext.setShadowColor(0, 0, 0, 1)

        # Set the border
        modal_object['modaltext'].setFrameColor(frame_color[0], frame_color[1],
                                                frame_color[2], frame_color[3])
        modal_object['modaltext'].setFrameAsMargin(frame_margin[0],
                                                   frame_margin[1],
                                                   frame_margin[2],
                                                   frame_margin[3])
        modal_object['modaltext'].setFrameLineWidth(frame_width)

        # Set the background styling up
        modal_object['modaltext'].setCardColor(bg[0], bg[1], bg[2], bg[3])
        modal_object['modaltext'].setCardAsMargin(0, 0, 0, 0)
        modal_object['modaltext'].setCardDecal(True)
        modal_object['frame_color'] = frame_color
        modal_object['frame_blink_color'] = frame_blink_color

        modal_object['modaltextNodePath'] = self._2dnode.attachNewNode(
            modal_object['modaltext'], 20)
        modal_object['modaltextNodePath'].setScale(scale)
        if start_location != None:
            modal_object['modaltextNodePath'].setPos(start_location)

        if animation == "easeIn" or animation == "up":
            interval = LerpPosInterval(modal_object['modaltextNodePath'],
                                       pos=end_location,
                                       startPos=start_location,
                                       blendType='easeIn',
                                       duration=animation_duration).start()

        if animation == "slide":
            seq = Sequence(
                LerpPosInterval(modal_object['modaltextNodePath'],
                                pos=end_location,
                                startPos=start_location,
                                blendType='easeOut',
                                duration=0.8), Wait(time - 1.6),
                LerpPosInterval(modal_object['modaltextNodePath'],
                                pos=start_location,
                                startPos=end_location,
                                blendType='easeIn',
                                duration=0.8)).start()

        self.modal_screens[modal_name] = modal_object

        # Set our timer so this message can expire if time is > 0
        if time > 0:
            base.taskMgr.doMethodLater(time,
                                       self._hideModalMessage,
                                       'hide_' + modal_name,
                                       extraArgs=[modal_name])

        if blink_speed > 0:
            base.taskMgr.doMethodLater(blink_speed,
                                       self._blinkModalMessage,
                                       'blink_' + modal_name,
                                       extraArgs=[modal_name])

    def _blinkModalMessage(self, modal_name):
        self.modal_screens[modal_name][
            'blink_status'] = not self.modal_screens[modal_name]['blink_status']

        if self.modal_screens[modal_name]['blink_status']:
            self.modal_screens[modal_name]['modaltext'].setTextColor(
                self.modal_screens[modal_name]['modal_text_color'][0],
                self.modal_screens[modal_name]['modal_text_color'][1],
                self.modal_screens[modal_name]['modal_text_color'][2],
                self.modal_screens[modal_name]['modal_text_color'][3])
            self.modal_screens[modal_name]['modaltext'].setFrameColor(
                self.modal_screens[modal_name]['frame_color'][0],
                self.modal_screens[modal_name]['frame_color'][1],
                self.modal_screens[modal_name]['frame_color'][2],
                self.modal_screens[modal_name]['frame_color'][3])
        else:
            self.modal_screens[modal_name]['modaltext'].setTextColor(
                self.modal_screens[modal_name]['blink_color'][0],
                self.modal_screens[modal_name]['blink_color'][1],
                self.modal_screens[modal_name]['blink_color'][2],
                self.modal_screens[modal_name]['blink_color'][3])
            self.modal_screens[modal_name]['modaltext'].setFrameColor(
                self.modal_screens[modal_name]['frame_blink_color'][0],
                self.modal_screens[modal_name]['frame_blink_color'][1],
                self.modal_screens[modal_name]['frame_blink_color'][2],
                self.modal_screens[modal_name]['frame_blink_color'][3])
        return Task.again

    def hideModalMessage(self, modal_name):
        if not modal_name in self.modal_screens: return
        self.modal_screens[modal_name]['modaltextNodePath'].removeNode()
        del self.modal_screens[modal_name]
        base.taskMgr.remove('blink_' + modal_name)

    def clearModalMessages(self):
        for modal_name in self.modal_screens.copy():
            self.hideModalMessage(modal_name)

    def isModalBeingShown(self):
        return len(self.modal_screens) > 0

    def _hideModalMessage(self, modal_name):
        self.hideModalMessage(modal_name)
Beispiel #24
0
class EnemyBike(Bike):
    def __init__(self, cTrav, cevent):
        #messenger.toggleVerbose()
        Bike.__init__(self, cTrav)
        self.bike.setPos(10, 0, 0)
        self.initAI()
        self.hp = 10
        
        self.singleShot = base.loader.loadSfx('50Cal.mp3')
        
        self.shooting = 0
        self.decshooting = True
        self.targeting = 0
        self.dectargeting = True
        
        frombikemask = BitMask32(0x10)
        intobikemask = BitMask32.allOff()
        floormask = BitMask32(0x2)
        
        self.cevent = CollisionHandlerEvent()
        self.cevent.addInPattern('%fn-into-%in')
        self.cevent.addOutPattern('%fn-out-%in')
        
        self.bullettrace = self.bike.attachNewNode(CollisionNode('aimtrace'))
        self.bullettrace.node().addSolid(CollisionRay(0, 0, 0, 0, -1, .1))
        self.bullettrace.node().setFromCollideMask(frombikemask)
        self.bullettrace.node().setIntoCollideMask(intobikemask)
        #self.bullettrace.show()
        #base.cTrav.addCollider(self.bullettrace, self.bike)
        base.cTrav.addCollider(self.bullettrace, self.cevent)
        
        self.gravtrace = self.bike.attachNewNode(CollisionNode('colNode'))
        self.gravtrace.node().addSolid(CollisionRay(0, 0, 0, 0, 0, -1))
        self.gravtrace.node().setFromCollideMask(floormask)
        self.gravtrace.node().setIntoCollideMask(BitMask32.allOff())
        #self.gravtrace.show()
        
        self.vistrace = self.bike.attachNewNode(CollisionNode('vistrace'))
        self.vistrace.node().addSolid(CollisionRay(0, 0, 0, 0, -1, .15))
        #self.vistrace.node().addSolid(CollisionRay(0, 0, 0, 1, 1, 0))
        #self.vistrace.node().addSolid(CollisionRay(0, 0, 0, -1, 1, 0))
        self.vistrace.node().addSolid(CollisionRay(0, 0, 0, 1, -1, .15))
        self.vistrace.node().addSolid(CollisionRay(0, 0, 0, -1, -1, .15))
        self.vistrace.node().setFromCollideMask(frombikemask)
        self.vistrace.node().setIntoCollideMask(intobikemask)
        #self.vistrace.show()
        #base.cTrav.addCollider(self.vistrace, self.bike)
        base.cTrav.addCollider(self.vistrace, self.cevent)
         
        self.lifter = CollisionHandlerFloor()
        self.lifter.setMaxVelocity(9.8)
        base.cTrav.addCollider(self.gravtrace,self.lifter)
        self.lifter.addCollider(self.gravtrace, self.bike)
        
        
        
        
        self.do = DirectObject()
        self.do.accept('vistrace-into-p_bike_push', self.visIn)
        self.do.accept('vistrace-out-p_bike_push', self.visOut)
        self.do.accept('aimtrace-into-p_bike_push', self.aimIn)
        self.do.accept('aimtrace-out-p_bike_push', self.aimOut)
        
        self.prev = self.bike.getPos()
		
    def initAI(self):
        self.AIchar = AICharacter("Enemy Bike", self.bike, 100, 0.05, 100)
        self.AIbehaviors = self.AIchar.getAiBehaviors()
        
        self.AImode = 'scan'
        self.target = None
        
        """
        l = loader.loadModel("shield.egg")
        l.reparentTo(render)
        l.setPos(70.0, 70.0, 0.0)
        l = loader.loadModel("shield.egg")
        l.reparentTo(render)
        l.setPos(70.0, -70.0, 0.0)
        l = loader.loadModel("shield.egg")
        l.reparentTo(render)
        l.setPos(-70.0, 70.0, 0.0)
        l = loader.loadModel("shield.egg")
        l.reparentTo(render)
        l.setPos(-70.0, -70.0, 0.0)
        """
		
    def update(self):
        #self.shoot()
        if self.AImode == 'flee':
            if random.randint(1, 60) == 1:
                self.lightsToggle()
        
        if (self.bike.getPos() - self.prev).length() > 0.01:
            self.bike.loop("move")
        else:
            #self.bike.stop()
            pass
        self.prev = self.bike.getPos()
        
        if self.shooting > 0:
            self.shoot()
            if self.decshooting:
                self.shooting -= 1
        if self.targeting > 0:
            if self.dectargeting:
                self.targeting -= 1
                if self.targeting == 0:
                    self.setMode('scan')
        if self.hp <= 1:
            self.setMode('flee')
        
        #print "shooting: " + str(self.shooting) + " (" + str(self.decshooting) + ")"
        #print "targeting: " + str(self.targeting) + " (" + str(self.dectargeting) + ")"
            
    def shoot(self):
        
        if self.shotClock >= 25:
            #create a bullet
            self.singleShot.play()
            #this may be the worst thing ever
            self.bike.setH((self.bike.getH() - 180.0) % 360.0)
            self.bullet.createBullet(self.bike)
            self.bike.setH((self.bike.getH() + 180.0) % 360.0)
            self.shotClock = 0
        else:
            self.shotClock += 1
            
            
    def setMode(self, mode):
        self.AImode = mode
        #self.AIbehaviors.removeAi("all")
        
        mag = 70.0
        r1 = 10.0
        r2 = 2.0
        #self.AIbehaviors.flee(Vec3(mag, mag, 0.0), r1, r2, 1.0)
        #self.AIbehaviors.flee(Vec3(mag, -mag, 0.0), r1, r2, 1.0)
        #self.AIbehaviors.flee(Vec3(-mag, mag, 0.0), r1, r2, 1.0)
        #self.AIbehaviors.flee(Vec3(-mag, -mag, 0.0), r1, r2, 1.0)
        #print self.AImode
        if self.AImode == 'target':
            #self.AIchar.setMaxForce(100);
            self.AIbehaviors.wander(0.5, 0, 17, 0.25)
            self.AIbehaviors.pursue(self.target.dummy, 0.5)
            self.AIbehaviors.evade(self.target.dummy, 4.0, 2.5, 0.95)
            
        elif self.AImode == 'flee':
            #self.AIchar.setMaxForce(100);
            self.AIbehaviors.wander(1.0, 0, 17, 0.5)
            self.AIbehaviors.pursue(self.target.dummy, 0.0)
            self.AIbehaviors.evade(self.target.dummy, 3.0, 6.0, 1.0)
        elif self.AImode == 'scan':
            #self.AIchar.setMaxForce(100);
            self.AIbehaviors.wander(0.5, 0, 17, 0.35)
            self.AIbehaviors.pursue(self.target.dummy, 0.5)
            self.AIbehaviors.evade(self.target.dummy, 3.0, 2.5, 0.85)
        
        
            
            
    def aimIn(self, event):
        #print length(self.bike.getPos(), event.getFromNodePath().getPos())
        #self.AImode = 'target'
        #print event.getFromNodePath().getParent().AImode
        #print event
        self.shooting = 60
        self.decshoot = False
        
    def aimOut(self, event):
        #print event
        self.decshoot = True

    def visIn(self, event):
        #print self.physNode.getPos()
        #print (self.bike.getPos() - event.getIntoNodePath().getPos()).length()
        self.setMode('target')
        self.targeting = 5
        self.dectargeting = False

        
    def visOut(self, event):
        self.dectargeting = True
Beispiel #25
0
# ** This is a task function called each frame, where the collision ray position is syncronized with the mouse pointer position and, more important, we traverse our collision traverser to make its routines check the collisions.
def rayupdate(task):
    if base.mouseWatcherNode.hasMouse():
        mpos = base.mouseWatcherNode.getMouse()
        # here the meat: differently from step 6, we do not call setFromLens to shoot our ray in 3d space from the camera lens, but rather we move the ray along the cursor position and shoot a straight ray from there along Y axis. This is because in orthographic view there is no perspective and therefore a ray is shoot parallel to its starting point
        pickerNP.setPos(render2d, mpos[0], 0, mpos[1])
        # and here we run the traverse step, to check the collisions in our scene
        customCtrav.traverse(render2d)
    return task.cont


# ** to manage the collision and mouse button events
DO = DirectObject()

# ** Let's manage the collision events: as you can see these are the events generated by the patterns defined above, a fixed string this time so no surprises here.
DO.accept("ray-into-cards", collideInCard)
DO.accept("ray-out-cards", collideOutCard)

# ** Storage for the object eventually below the mouse pointer
pickingEnabledOject = None

# ** Here's how we interact with mouse clicks - see the mouseClick function above
DO.accept("mouse1", mouseClick, ["down"])
DO.accept("mouse1-up", mouseClick, ["up"])

# ** And here we start the task that continuously update the ray collider position and make traverse the collision traverser in 2d space
taskMgr.add(rayupdate, "updatePicker")

splash.destroy()
run()
Beispiel #26
0
class Graphics_Data():
    def __init__(self, golog, simplex, **kwargs):
        self.simplex = simplex
        self.golog = golog
        self.messenger = self.golog.base.messenger
        self.listener = DirectObject(
        )  # might let Graphics_Data Inherit from Direct_Object
        self.graphics_kwargs = dict(
        )  # keeping track of information needed to re-create graphics_data

        #things to clean self for deletion:
        self.node_list = []
        self.listeners = [self.listener]

        if simplex.level == 0:
            self.NP = golog.render.attachNewNode(simplex.label)
            self.node_list.append(self.NP)
            self.NP.setTag(
                'level',
                '0')  # to tell mode_heads what type of simplex this is
            golog.sphere.instanceTo(self.NP)
            self.collision = self.NP.attachNewNode(
                CollisionNode('sphereColNode'))
            self.collision.node().addSolid(CollisionSphere(0, 0, 0, 1))
            self.messenger_names = {'node': str(id(self.NP))}

            #detail parents
            self.parents = (
            )  #need to give no parents for a unified update function

            self.parent_pos_convolution = lambda *x: golog.render.getPos(
            )  # function of parent's [node] positions to detail offset (0-simlex it's just render location)
            #listener for parental updates, pass arguemnts through extraKwargs to detail what kind of update to perform
            for parent in self.parents:
                self.listener.accept(self.parents.messenger_names['node'],
                                     self.update)

            #set position
            if 'pos' in kwargs.keys(): self.update({'pos': kwargs['pos']})
            else: self.update({'pos': LPoint3f(0, 0, 0)})

        elif simplex.level == 1:
            self.NP = golog.render.attachNewNode(simplex.label)
            self.node_list.append(self.NP)
            self.NP.setTag('level', '1')
            self.golog.cone.instanceTo(self.NP)
            self.collision = self.NP.attachNewNode(
                CollisionNode('coneColNode'))
            self.collision.node().addSolid(CollisionSphere(0, 0, 0, 1))
            self.messenger_names = {'node': str(id(simplex))}
            self.graphics = (Rope(), Rope())  #two ropes :)
            for rope in self.graphics:
                self.node_list.append(rope)

            #set up parents
            self.parents = tuple(golog.Simplex_to_Graphics[face]
                                 for face in self.simplex.faces)

            def tuple_avg(tuples):
                b = LPoint3f(0, 0, 0)
                for a in tuples:
                    b = b + a
                return b / len(tuples)

            self.parent_pos_convolution = lambda *x: tuple_avg(
                tuple(parent.NP.getPos() for parent in self.parents))
            for parent in self.parents:
                self.listener.accept(parent.messenger_names['node'],
                                     self.update)

            if 'pos' in kwargs.keys():
                if isinstance(kwargs['pos'], tuple):
                    pos = LPoint3f(*kwargs['pos'])
                else:
                    pos = kwargs['pos']
            else:
                pos = LPoint3f(0, 0, 0)
            self.graphics_kwargs['pos'] = pos

            #create shitty control nodes for rope module (I know, this is not pretty)
            self.control_nodes = (
                self.golog.render.attachNewNode(simplex.label +
                                                '_control_node0'),
                self.golog.render.attachNewNode(simplex.label +
                                                '_control_node1'))
            for node in self.control_nodes:
                self.node_list.append(node)
            control_listener = DirectObject()
            self.listeners.append(control_listener)

            def control_updator(*x):
                for i in [0, 1]:
                    self.control_nodes[i].setPos(self.graphics_kwargs['pos'] +
                                                 self.parents[i].NP.getPos())

            control_updator()
            control_listener.accept(self.messenger_names['node'],
                                    control_updator)

            self.update({'pos': None})

            #set up rope graphics
            self.graphics[0].setup(3, [(self.NP, (0, 0, 0)),
                                       (self.control_nodes[0], (0, 0, 0)),
                                       (self.parents[0].NP, (0, 0, 0))])
            self.graphics[1].setup(3, [(self.parents[1].NP, (0, 0, 0)),
                                       (self.control_nodes[1], (0, 0, 0)),
                                       (self.NP, (0, 0, 0))])
            for rope in self.graphics:
                rope.reparentTo(golog.render)

        #set up dictionary references
        self.golog.Simplex_to_Graphics[simplex] = self
        self.golog.Graphics_to_Simplex[self] = simplex
        self.golog.NP_to_Graphics[self.NP] = self
        #create an invisible textNode that can be shown if called
        text = TextNode(self.simplex.label + '_text_node')
        #? make this wrap if too long
        text.setText(self.simplex.label)
        text.setCardDecal(True)
        text.setCardColor(.5, 1, .5, 1)
        text.setCardAsMargin(0, 0, 0, 0)
        text.setTextColor(0, 0, 0, 1)
        self.textNP = self.NP.attachNewNode(text)
        #? make this update to always be in front of camera
        # - Either get it into 2d plane, or make a z axis that always faces the camera and attach to that
        self.textNP.setPos(0, -1, 0)
        self.textNP.show()
        self.node_list.append(self.textNP)

    #function that cleans up references and listeners for deletion
    #!!! THIS SHOULD NOT BE CALLED UNLESS DELETING UNDERLYING SIMPLEX AS WELL !!!#
    def _remove(self):
        #first should clean the nodes it supports (done through hcat)
        simplex = self.simplex
        supports = [*simplex.supports]
        for simp in supports:
            self.golog.Simplex_to_Graphics[simp]._remove()

        #delete listeners
        for listener in self.listeners:
            listener.ignoreAll()
            del listener

        #delete relevant nodes
        for node in self.node_list:
            node.removeNode()

        #delete dictionary references
        del self.golog.Simplex_to_Graphics[simplex]
        del self.golog.Graphics_to_Simplex[self]
        del self.golog.NP_to_Graphics[self.NP]

        #remove simplex from sSet
        self.golog.sSet.remove(simplex)

    #listener calls update with some data
    def update(self, kwargs):
        if 'pos' in kwargs:
            #if an offset is provided, change the graphics_kwargs, if not, leave them
            if kwargs['pos']: self.graphics_kwargs['pos'] = kwargs['pos']
            newpos = self.parent_pos_convolution() + self.graphics_kwargs[
                'pos']  #set a new offset base on parent positions
            self.NP.setPos(newpos)
            self.messenger.send(self.messenger_names['node'], [{'pos': None}])

    #supress attribute errors
    def __getattr__(self, attr):
        return None
Beispiel #27
0
class CollisionManager:
    def __init__(self):
        self.line_dir = NodePath()

        base.cTrav = CollisionTraverser()
        self.col_handler = CollisionHandlerEvent()

        picker_node = CollisionNode("mouseRayNode")
        pickerNPos = base.camera.attachNewNode(picker_node)
        self.pickerRay = CollisionRay()
        picker_node.addSolid(self.pickerRay)

        plane_node = CollisionNode("base_plane")
        plane = base.render.attachNewNode(plane_node)
        self.plane_col = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
        picker_node.addSolid(self.pickerRay)


        picker_node.setTag("rays","mray")
        base.cTrav.addCollider(pickerNPos, self.col_handler)

        self.col_handler.addInPattern("%(rays)ft-into-%(type)it")
        self.col_handler.addOutPattern("%(rays)ft-out-%(type)it")
        self.col_handler.addAgainPattern("ray_again_all%(""rays"")fh%(""type"")ih")

        self.model = loader.loadModel("../models/chest.egg")
        self.model_node = NodePath("sdfafd")
        self.model.reparentTo(self.model_node)
        self.model_node.reparentTo(render)
#
#        self.text_node = TextNode("battle_text")
#        self.text_node.setText("TEXTYTEXTYTEXTTEXT")
#        self.text_node_path = render.attachNewNode(self.text_node)
#        self.text_node_path.reparentTo(render)
#        self.text_node_path.setPos(0,0,4)
#        self.text_node_path.setHpr(0,0,0)
#        self.text_node_path.setScale(1)
#        #self.text_node_path.setTransparency(TransparencyAttrib.MAlpha)
#        self.text_node.setTextColor((1,1,1,1))
#        self.text_node.setAlign(TextNode.ALeft)

        self.placement_ghost = EditorObjects.PlacementGhost(0,"tower",base.object_scale)

        z=0
        self.plane = Plane(Vec3(0, 0, 1), Point3(0, 0, z))

        taskMgr.add(self.ray_update, "updatePicker")
        taskMgr.add(self.get_mouse_plane_pos, "MousePositionOnPlane")
        taskMgr.add(self.task_mouse_press_check, "checkMousePress")

        self.input_init()

        self.pickable=None

    def input_init(self):
        self.DO=DirectObject()

        self.DO.accept('mouse1', self.mouse_click, ["1-down"])
        self.DO.accept('mouse1-up', self.mouse_click, ["1-up"])
        self.DO.accept('mouse3', self.mouse_click, ["3-down"])

        self.DO.accept('0', self.placement_ghost.change_player, [0])
        self.DO.accept('1', self.placement_ghost.change_player, [1])
        self.DO.accept('2', self.placement_ghost.change_player, [2])

        self.DO.accept('a', self.placement_ghost.change_type, ["army"])
        self.DO.accept('t', self.placement_ghost.change_type, ["tower"])

        self.DO.accept('control-s', base.xml_manager.save)

        self.DO.accept('mray-into-army', self.col_in_object)
        self.DO.accept('mray-out-army', self.col_out_object)
        self.DO.accept('mray-into-tower', self.col_in_object)
        self.DO.accept('mray-out-tower', self.col_out_object)

        self.DO.accept('ray_again_all', self.col_against_object)

    def col_against_object(self,entry):
        if entry.getIntoNodePath().getParent() != self.pickable:

            np_from=entry.getFromNodePath()
            np_into=entry.getIntoNodePath()
            self.selected_type = np_into.getTag("type")

            self.pickable = np_into.getParent()

    def col_in_object(self,entry):
        if base.state == "selecting":
            np_into=entry.getIntoNodePath()
            np_into.getParent().setColor(0.5,0.5,0.5,1)

    def col_out_object(self,entry):
        np_into=entry.getIntoNodePath()
        try:
            np_into.getParent().clearColor()
        except:
            print "ERROR CLEARING COLOUR"

    def get_mouse_plane_pos(self, task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()
            self.pos3d = Point3()
            nearPoint = Point3()
            farPoint = Point3()
            base.camLens.extrude(mpos, nearPoint, farPoint)
            if self.plane.intersectsLine(self.pos3d,
                render.getRelativePoint(camera, nearPoint),
                render.getRelativePoint(camera, farPoint)):
                #print "Mouse ray intersects ground plane at ", self.pos3d
                self.model_node.setPos(render, self.pos3d)
                self.placement_ghost.set_position(self.pos3d[0],self.pos3d[1])
        return task.again

    def ray_update(self,task):
        if base.mouseWatcherNode.hasMouse():
            mpos = base.mouseWatcherNode.getMouse()

            self.pickerRay.setFromLens(base.camNode, mpos.getX(),mpos.getY())
        return task.cont

    def task_mouse_place(self,task):
        if base.mouseWatcherNode.isButtonDown(MouseButton.one()):
            self.placing_object = True
            self.place_pos = (self.anchor_x,self.anchor_y)
            self.line_dir.remove()
            ls = LineSegs()
            ls.move_to(self.anchor_x,self.anchor_y,1)
            ls.draw_to(self.model.getX(),self.model.getY(),1)
            node = ls.create()
            angle1 = math.atan2(self.anchor_y - self.anchor_y,self.anchor_x - self.anchor_x+50)
            angle2 = math.atan2(self.anchor_y - self.model.getY(),self.anchor_x - self.model.getY());
            final_angle = angle1-angle2;
            self.model.setHpr(final_angle,0,0)
            self.line_dir = NodePath(node)
            self.line_dir.reparentTo(render)
            return task.again
        else:
            self.line_dir.hide()
            taskMgr.add(self.task_mouse_press_check, "checkMousePress")
            return task.done

    def task_mouse_press_check(self,task):
        if base.mouseWatcherNode.isButtonDown(MouseButton.one()):
            #if self.multi_select == True:
                self.anchor_x,self.anchor_y = self.model.getX(),self.model.getY()
                taskMgr.add(self.task_mouse_place, "multibox")
                return task.done
        return task.again

    def mouse_click(self,status):
        print base.state
        if status == "1-down":
            if base.state == "placement":
                if self.placement_ghost.get_type() == "tower":
                    obj = self.placement_ghost.place("tower",self.model.getX(),self.model.getY())
                elif self.placement_ghost.get_type() == "army":
                    obj = self.placement_ghost.place("army",self.model.getX(),self.model.getY())
                base.details_box.set_object(obj)
                base.change_state("modifying")
            elif base.state == "moving":
                obj = base.details_box.get_object()
                obj.set_position(self.pos3d[0],self.pos3d[1])
                base.change_state("modifying")
            elif base.state == "selecting" and self.pickable != None:
                obj = base.get_obj_from_node(self.pickable)
                base.details_box.set_object(obj,"selecting")
                base.change_state("modifying")
        elif status == "1-up":
            print "Mouse",status
        elif status == "3-down":
            if base.state == "placement":
                base.change_state("selecting")
            elif base.state == "selecting":
                base.change_state("placement")
Beispiel #28
0
    def __init__(self, golog, simplex, **kwargs):
        self.simplex = simplex
        self.golog = golog
        self.messenger = self.golog.base.messenger
        self.listener = DirectObject(
        )  # might let Graphics_Data Inherit from Direct_Object
        self.graphics_kwargs = dict(
        )  # keeping track of information needed to re-create graphics_data

        #things to clean self for deletion:
        self.node_list = []
        self.listeners = [self.listener]

        if simplex.level == 0:
            self.NP = golog.render.attachNewNode(simplex.label)
            self.node_list.append(self.NP)
            self.NP.setTag(
                'level',
                '0')  # to tell mode_heads what type of simplex this is
            golog.sphere.instanceTo(self.NP)
            self.collision = self.NP.attachNewNode(
                CollisionNode('sphereColNode'))
            self.collision.node().addSolid(CollisionSphere(0, 0, 0, 1))
            self.messenger_names = {'node': str(id(self.NP))}

            #detail parents
            self.parents = (
            )  #need to give no parents for a unified update function

            self.parent_pos_convolution = lambda *x: golog.render.getPos(
            )  # function of parent's [node] positions to detail offset (0-simlex it's just render location)
            #listener for parental updates, pass arguemnts through extraKwargs to detail what kind of update to perform
            for parent in self.parents:
                self.listener.accept(self.parents.messenger_names['node'],
                                     self.update)

            #set position
            if 'pos' in kwargs.keys(): self.update({'pos': kwargs['pos']})
            else: self.update({'pos': LPoint3f(0, 0, 0)})

        elif simplex.level == 1:
            self.NP = golog.render.attachNewNode(simplex.label)
            self.node_list.append(self.NP)
            self.NP.setTag('level', '1')
            self.golog.cone.instanceTo(self.NP)
            self.collision = self.NP.attachNewNode(
                CollisionNode('coneColNode'))
            self.collision.node().addSolid(CollisionSphere(0, 0, 0, 1))
            self.messenger_names = {'node': str(id(simplex))}
            self.graphics = (Rope(), Rope())  #two ropes :)
            for rope in self.graphics:
                self.node_list.append(rope)

            #set up parents
            self.parents = tuple(golog.Simplex_to_Graphics[face]
                                 for face in self.simplex.faces)

            def tuple_avg(tuples):
                b = LPoint3f(0, 0, 0)
                for a in tuples:
                    b = b + a
                return b / len(tuples)

            self.parent_pos_convolution = lambda *x: tuple_avg(
                tuple(parent.NP.getPos() for parent in self.parents))
            for parent in self.parents:
                self.listener.accept(parent.messenger_names['node'],
                                     self.update)

            if 'pos' in kwargs.keys():
                if isinstance(kwargs['pos'], tuple):
                    pos = LPoint3f(*kwargs['pos'])
                else:
                    pos = kwargs['pos']
            else:
                pos = LPoint3f(0, 0, 0)
            self.graphics_kwargs['pos'] = pos

            #create shitty control nodes for rope module (I know, this is not pretty)
            self.control_nodes = (
                self.golog.render.attachNewNode(simplex.label +
                                                '_control_node0'),
                self.golog.render.attachNewNode(simplex.label +
                                                '_control_node1'))
            for node in self.control_nodes:
                self.node_list.append(node)
            control_listener = DirectObject()
            self.listeners.append(control_listener)

            def control_updator(*x):
                for i in [0, 1]:
                    self.control_nodes[i].setPos(self.graphics_kwargs['pos'] +
                                                 self.parents[i].NP.getPos())

            control_updator()
            control_listener.accept(self.messenger_names['node'],
                                    control_updator)

            self.update({'pos': None})

            #set up rope graphics
            self.graphics[0].setup(3, [(self.NP, (0, 0, 0)),
                                       (self.control_nodes[0], (0, 0, 0)),
                                       (self.parents[0].NP, (0, 0, 0))])
            self.graphics[1].setup(3, [(self.parents[1].NP, (0, 0, 0)),
                                       (self.control_nodes[1], (0, 0, 0)),
                                       (self.NP, (0, 0, 0))])
            for rope in self.graphics:
                rope.reparentTo(golog.render)

        #set up dictionary references
        self.golog.Simplex_to_Graphics[simplex] = self
        self.golog.Graphics_to_Simplex[self] = simplex
        self.golog.NP_to_Graphics[self.NP] = self
        #create an invisible textNode that can be shown if called
        text = TextNode(self.simplex.label + '_text_node')
        #? make this wrap if too long
        text.setText(self.simplex.label)
        text.setCardDecal(True)
        text.setCardColor(.5, 1, .5, 1)
        text.setCardAsMargin(0, 0, 0, 0)
        text.setTextColor(0, 0, 0, 1)
        self.textNP = self.NP.attachNewNode(text)
        #? make this update to always be in front of camera
        # - Either get it into 2d plane, or make a z axis that always faces the camera and attach to that
        self.textNP.setPos(0, -1, 0)
        self.textNP.show()
        self.node_list.append(self.textNP)
Beispiel #29
0
	def setMode(self, n=0):
		if n != self.mode:
			self.mode = n
			if n == 0:
				base.mouseWatcherNode.setGeometry(self.dummyNP.node())
				#self.crosshair2.detachNode()
				self.crosshair2.hide()
				self.crosshair.show()
				#self.crosshair.reparentTo(self.dummyNP)
			else:
				base.mouseWatcherNode.setGeometry(self.dummyNP2.node())
				#self.crosshair.detachNode()
				self.crosshair2.show()
				self.crosshair.hide()
				#self.crosshair2.reparentTo(self.dummyNP2)
				
		
	def toggle(self):
		if self.mode == 0:
			self.setMode(1)
		else:
			self.setMode(0)
		
			
if __name__ == "__main__":
	m = MouseCursor()
	DO = DirectObject()
	DO.accept("mouse3", m.toggle)
	DO.accept("escape", sys.exit)
	run()
Beispiel #30
0
class PandaPhysicsSystem(DelegateByNetmode, SignalListener):
    subclasses = {}

    def __init__(self):
        self.register_signals()

        self.world = BulletWorld()
        self.world.setGravity((0, 0, -9.81))

        # # Seems that this does not function
        # on_contact_added = PythonCallbackObject(self._on_contact_added)
        # self.world.set_contact_added_callback(on_contact_added)

        # on_filter = PythonCallbackObject(self._filter_collision)
        # self.world.set_filter_callback(on_filter)

        self.listener = DirectObject()
        self.listener.accept('bullet-contact-added', self._on_contact_added)
        self.listener.accept('bullet-contact-destroyed', self._on_contact_removed)

        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(True)
        debug_node.showBoundingBoxes(False)
        debug_node.showNormals(False)

        self.debug_nodepath = render.attachNewNode(debug_node)
        self.world.set_debug_node(debug_node)

        self.tracked_contacts = defaultdict(int)
        self.existing_collisions = set()

    def _create_contacts_from_result(self, requesting_node, contact_result):
        """Return collision contacts between two nodes"""
        contacts = []

        for contact in contact_result.get_contacts():
            if contact.get_node0() == requesting_node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_a()
                normal = -manifold.get_normal_world_on_b()

            elif contact.get_node1() == requesting_node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_b()
                normal = manifold.get_normal_world_on_b()

            impulse = manifold.get_applied_impulse()
            contact_ = CollisionContact(position, normal, impulse)
            contacts.append(contact_)

        return contacts

    def _on_contact_removed(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] -= 1

    def _on_contact_added(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] += 1

    def _filter_collision(self, filter_data):
        filter_data.set_collide(True)

    @RegisterPhysicsNode.on_global
    def register_node(self, node):
        self.world.attachRigidBody(node)
        node.set_python_tag("world", self.world)

    @DeregisterPhysicsNode.on_global
    def deregister_node(self, node):
        self.world.removeRigidBody(node)
        node.clear_python_tag("world")

    def dispatch_collisions(self):
        # Dispatch collisions
        existing_collisions = self.existing_collisions
        for pair, contact_count in self.tracked_contacts.items():
            if contact_count > 0 and pair not in existing_collisions:
                existing_collisions.add(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = entity_from_nodepath(node_a)
                entity_b = entity_from_nodepath(node_b)

                contact_result = None

                if entity_a is not None:
                    def contact_getter():
                        nonlocal contact_result
                        if contact_result is None:
                            contact_result = self.world.contact_test_pair(node_a, node_b)

                        return self._create_contacts_from_result(node_a, contact_result)

                    collision_result = LazyCollisionResult(entity_b, CollisionState.started, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_a)

                if entity_b is not None:
                    def contact_getter():
                        nonlocal contact_result
                        if contact_result is None:
                            contact_result = self.world.contact_test_pair(node_a, node_b)

                        return self._create_contacts_from_result(node_b, contact_result)

                    collision_result = LazyCollisionResult(entity_a, CollisionState.started, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_b)

            elif contact_count == 0 and pair in existing_collisions:
                existing_collisions.remove(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = entity_from_nodepath(node_a)
                entity_b = entity_from_nodepath(node_b)

                # Don't send contacts for ended collisions
                contact_getter = lambda: None

                if entity_a is not None:
                    collision_result = LazyCollisionResult(entity_b, CollisionState.ended, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_a)

                if entity_b is not None:
                    collision_result = LazyCollisionResult(entity_a, CollisionState.ended, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_b)

    def update(self, delta_time):
        self.world.doPhysics(delta_time)
        self.dispatch_collisions()
Beispiel #31
0
# **...but from now on things are about to change: these two functions are the handlers the collision handler will call as soon as two events will happens: the two objects touch each other, the two objects leave each other alone. Afterwards we'll see how to make this happen.
# this is the function will be called while the two objects collide...
def collideEventIn(entry):
    # lights on
    snipstuff.dlight.setColor((0.5, 0.5, 0.5, 1))


# ... and this when they leave each other alone.
def collideEventOut(entry):
    # lights shut down
    snipstuff.dlight.setColor((0.0, 0.1, 0.0, 1))


# ** And here it is how we tell to our handler which are the two functions to call whenever a collision or the opposite event happens:
# this method is for the INTO event, as is when the FROM object (heart) collide with the INTO one (smiley). You see that we set a pattern string with strange symbols inside - I'm not going to dig these details cos you'll find a wide explanation inside the panda3D manual at the chapter "Collision Handlers" - just know that that pattern will match a system event we'll define later, which the collision handler will call ASA the event occurs.
collisionHandler.addInPattern("%fn-into-%in")

# this is on the other hand the relative call for the OUT event, as is when the FROM object (heart) goes OUT the INTO oject (heart).
collisionHandler.addOutPattern("%fn-out-%in")

# ** To manage the collision events need Directobject, because the chaining between the CollisionHandlerEvent handler and our two functions seen above, happens with the accept() function of a DirectObject instance that define the event strings the task manager will call via the CollisionHandlerEvent stimulus.
DO = DirectObject()

# ** And at last here it is the event catching setup: we tell the panda3D event manager to call our function handlers whenever 'somebody' fires the strings 'collider_heart-into-smileycnode' or 'collider_heart-out-smileycnode' - this is to say that whenever the CollisionHandlerEvent object detect a collision, will send an event string to the engine formatted, as you can see, with first the name of the FROM collider (collider_heart precisely) the "-into-" or "-out-" string chunk and at the end the name of the INTO collider (smileycnode precisely). Note that '-into-' and '-out-' are just for our convenience, nobody oblige us to write them like that: we may call'em 'dummy' and 'foo' respectively but provided that they're specified also in the pattern declaration above in place of '-into-' and '-out-'. Now go back above and compare what said here with the pattern strings specified above with the addInPattern and addOutPattern declarations and with a little help of the panda3D manual you should understand all this knotted stuff.
DO.accept("collider_heart-into-smileycnode", collideEventIn)
DO.accept("collider_heart-out-smileycnode", collideEventOut)

splash.destroy()
run()
Beispiel #32
0
  # we retrieve the two object nodepaths - note that we need to go back the nodes hierarchy because the getXXXNodePath methods returns just the collision geometry, that we know is parented to the very object nodepath we need to manage here
  colliderFROM = entry.getFromNodePath().getParent()
  colliderINTO = entry.getIntoNodePath().getParent()
  # we now may change the aspect of the two colliding objects
  colliderINTO.setColor(1,1,1,1)
  colliderFROM.setScale(1.5)

#... and this when they leave each other alone.
def collideEventOut(entry):
  colliderFROM = entry.getFromNodePath().getParent()
  colliderINTO = entry.getIntoNodePath().getParent()
  colliderINTO.setColor(.4, .4, .4, 1)
  colliderFROM.setScale(1.0)

#** Here's the definition of the patterns that should catch our collisions - note that just these two are enough to catch the 2 couple of combinations.
collisionHandler.addInPattern('%fn-into-%in')
collisionHandler.addOutPattern('%fn-out-%in')

#** Let's manage the collision events:
DO=DirectObject()
# we should provide a couple of event strings for each couple of interacting objects (remember we made the smiley react against the whole heart and the frowney with the broken one). Compare these strings with the patterns above and if it is not enough to understand why it works, go back and dig again step2 and step3 until they're clear for you.
# Note that we route the in and out events to the same functions for both couples but that is just to slim the code.
DO.accept('collider_heart-into-smileycnode', collideEventIn)
DO.accept('collider_heart-out-smileycnode', collideEventOut)
#
DO.accept('collider_brkheart-into-frowneycnode', collideEventIn)
DO.accept('collider_brkheart-out-frowneycnode', collideEventOut)

splash.destroy()
run()
Beispiel #33
0
	def __init__(self):
		ShowBase.__init__(self)
		
		#Setup
		scene = BulletWorld()
		scene.setGravity(Vec3(0, 0, -9.81))
		base.setBackgroundColor(0.6,0.9,0.9)
		fog = Fog("The Fog")
		fog.setColor(0.9,0.9,1.0)
		fog.setExpDensity(0.003)
		render.setFog(fog)
		#Lighting
		
		#Sun light
		sun = DirectionalLight("The Sun")
		sun_np = render.attachNewNode(sun)
		sun_np.setHpr(0,-60,0)
		render.setLight(sun_np)
		
		#Ambient light
		amb = AmbientLight("The Ambient Light")
		amb.setColor(VBase4(0.39,0.39,0.39, 1))
		amb_np = render.attachNewNode(amb)
		render.setLight(amb_np)
		
		#Variables
		self.gear = 0
		
		self.start = 0
		
		self.Pbrake = 0
		
		self.terrain_var = 1
		
		self.time = 0
		
		self.headlight_var = 0
		
		self.RPM = 0
		
		self.clutch = 0
		
		self.carmaxspeed = 100 #KPH
		
		self.carmaxreversespeed = -40 #KPH
		
		self.steering = 0
		
		
		#Functions
		def V1():
			camera.setPos(0.25,-1.2,0.5)
			camera.setHpr(0,-13,0)
			
		def V2():
			camera.setPos(0,-15,3)
			camera.setHpr(0,-10,0)
			
		def V3():
			camera.setPos(0,0,9)
			camera.setHpr(0,-90,0)
			
		def up():
			self.gear = self.gear -1
			if self.gear < -1:
				self.gear = -1
				
		def down():
			self.gear = self.gear +1
			if self.gear > 1:
				self.gear = 1
				
		def start_function():
			self.start = 1
			self.start_sound.play()
			self.engine_idle_sound.play()
			self.RPM = 1000
			
		def stop_function():
			self.start = 0
			self.engine_idle_sound.stop()
				
		def parkingbrake():
			self.Pbrake = (self.Pbrake + 1) % 2
			
		def rotate():
			Car_np.setHpr(0, 0, 0)
			
		def horn():
			self.horn_sound.play()
			
		def set_time():
			if self.time == -1:
				sun.setColor(VBase4(0.4, 0.3, 0.3, 1))
				base.setBackgroundColor(0.8,0.7,0.7)
			if self.time == 0:
				sun.setColor(VBase4(0.7, 0.7, 0.7, 1))
				base.setBackgroundColor(0.6,0.9,0.9)
			if self.time == 1:
				sun.setColor(VBase4(0.2, 0.2, 0.2, 1))
				base.setBackgroundColor(0.55,0.5,0.5)
			if self.time == 2:
				sun.setColor(VBase4(0.02, 0.02, 0.05, 1))
				base.setBackgroundColor(0.3,0.3,0.3)
				
			if self.time == -2:
				self.time = -1
			if self.time == 3:
				self.time = 2
			
		def time_forward():
			self.time = self.time + 1
			
		def time_backward():
			self.time = self.time -1
			
		def set_terrain():
			if self.terrain_var == 1:
				self.ground_model.setTexture(self.ground_tex, 1)
				self.ground_model.setScale(3)
			if self.terrain_var == 2:
				self.ground_model.setTexture(self.ground_tex2, 1)
				self.ground_model.setScale(3)
			if self.terrain_var == 3:
				self.ground_model.setTexture(self.ground_tex3, 1)
				self.ground_model.setScale(4)
				
			if self.terrain_var == 4:
				self.terrain_var = 1
			if self.terrain_var == 0:
				self.terrain_var = 3
			
		def next_terrain():
			self.terrain_var = self.terrain_var + 1
			
		def previous_terrain():
			self.terrain_var = self.terrain_var - 1
			
		def show_menu():
			self.menu_win.show()
			self.a1.show()
			self.a2.show()
			self.a3.show()
			self.a4.show()
			self.t1.show()
			self.t2.show()
			self.ok.show()
			self.exit_button.show()
			
		def hide_menu():
			self.menu_win.hide()
			self.a1.hide()
			self.a2.hide()
			self.a3.hide()
			self.a4.hide()
			self.ok.hide()
			self.t1.hide()
			self.t2.hide()
			self.exit_button.hide()
		
		def Menu():
			self.menu_win = OnscreenImage(image = "Textures/menu.png", pos = (0.9,0,0), scale = (0.5))
			self.menu_win.setTransparency(TransparencyAttrib.MAlpha)
			
			#The Arrow Buttons
			self.a1 = DirectButton(text = "<", scale = 0.2, pos = (0.55,0,0.25), command = previous_terrain)
			self.a2 = DirectButton(text = ">", scale = 0.2, pos = (1.15,0,0.25), command = next_terrain)
			self.a3 = DirectButton(text = "<", scale = 0.2, pos = (0.55,0,0.0), command = time_backward)
			self.a4 = DirectButton(text = ">", scale = 0.2, pos = (1.15,0,0.0), command = time_forward)
			
			#The Text
			self.t1 = OnscreenText(text = "Terrain", pos = (0.85,0.25,0), scale = 0.1, fg = (0.4,0.4,0.5,1))
			self.t2 = OnscreenText(text = "Time", pos = (0.85,0,0), scale = 0.1, fg = (0.4,0.4,0.5,1))
			
			#The Buttons
			self.ok = DirectButton(text = "Okay", scale = 0.11, pos = (0.87,0,-0.25), command = hide_menu)
			self.exit_button = DirectButton(text = "Quit", scale = 0.11, pos = (0.87,0,-0.42), command = sys.exit)
			
		Menu()
		
		
		def take_screenshot():
			base.screenshot("Screenshot")
			
		def set_headlights():
			if self.headlight_var == 1:
				Headlight1.setColor(VBase4(9.0,8.9,8.9,1))
				Headlight2.setColor(VBase4(9.0,8.9,8.9,1))
			if self.headlight_var == 0:
				Headlight1.setColor(VBase4(0,0,0,1))
				Headlight2.setColor(VBase4(0,0,0,1))
			
		def headlights():
			self.headlight_var = (self.headlight_var + 1) % 2
			
		def update_rpm():
			
			#Simulate RPM
			if self.start == 1:
				if self.gear == 0:
					self.RPM = self.RPM - self.RPM / 400
				else:
					self.RPM = self.RPM + self.carspeed / 9
					self.RPM = self.RPM - self.RPM / 200
			
			#Reset RPM to 0 when engine is off
			if self.start == 0:
				if self.RPM > 0.0:
					self.RPM = self.RPM - 40
				if self.RPM < 10:
					self.RPM = 0.0
								
			#Idle RPM power
			if self.start == 1:
				if self.RPM < 650:
					self.RPM = self.RPM + 4
				if self.RPM < 600:
					self.clutch = 1
				else:
					self.clutch = 0
					
			#RPM limit		
			if self.RPM > 6000:
				self.RPM = 6000
				

		#Controls 
		inputState.watchWithModifiers("F", "arrow_up")
		inputState.watchWithModifiers("B", "arrow_down")
		inputState.watchWithModifiers("L", "arrow_left")
		inputState.watchWithModifiers("R", "arrow_right")
		
		do = DirectObject()
		
		do.accept("escape", show_menu)
		do.accept("1", V1)
		do.accept("2", V2)
		do.accept("3", V3)
		do.accept("page_up", up)
		do.accept("page_down", down)
		do.accept("x-repeat", start_function)
		do.accept("x", stop_function)
		do.accept("p", parkingbrake)
		do.accept("backspace", rotate)
		do.accept("enter", horn)
		do.accept("f12", take_screenshot)
		do.accept("h", headlights)
		
		#The ground
		self.ground = BulletPlaneShape(Vec3(0, 0, 1,), 1)
		self.ground_node = BulletRigidBodyNode("The ground")
		self.ground_node.addShape(self.ground)
		self.ground_np = render.attachNewNode(self.ground_node)
		self.ground_np.setPos(0, 0, -2)
		scene.attachRigidBody(self.ground_node)
		
		self.ground_model = loader.loadModel("Models/plane.egg")
		self.ground_model.reparentTo(render)
		self.ground_model.setPos(0,0,-1)
		self.ground_model.setScale(3)
		self.ground_tex = loader.loadTexture("Textures/ground.png")
		self.ground_tex2 = loader.loadTexture("Textures/ground2.png")
		self.ground_tex3 = loader.loadTexture("Textures/ground3.png")
		self.ground_model.setTexture(self.ground_tex, 1)
		
		#The car
		Car_shape = BulletBoxShape(Vec3(1, 2.0, 1.0))
		Car_node = BulletRigidBodyNode("The Car")
		Car_node.setMass(1200.0)
		Car_node.addShape(Car_shape)
		Car_np = render.attachNewNode(Car_node)
		Car_np.setPos(0,0,3)
		Car_np.setHpr(0,0,0)
		Car_np.node().setDeactivationEnabled(False)
		scene.attachRigidBody(Car_node)
		
		Car_model = loader.loadModel("Models/Car.egg")
		Car_model.reparentTo(Car_np)
		Car_tex = loader.loadTexture("Textures/Car1.png")
		Car_model.setTexture(Car_tex, 1)
		
		self.Car_sim = BulletVehicle(scene, Car_np.node())
		self.Car_sim.setCoordinateSystem(ZUp)
		scene.attachVehicle(self.Car_sim)
		
		#The inside of the car
		Car_int = loader.loadModel("Models/inside.egg")
		Car_int.reparentTo(Car_np)
		Car_int_tex = loader.loadTexture("Textures/inside.png")
		Car_int.setTexture(Car_int_tex, 1)
		Car_int.setTransparency(TransparencyAttrib.MAlpha)
		
		#The steering wheel
		Sw = loader.loadModel("Models/Steering wheel.egg")
		Sw.reparentTo(Car_np)
		Sw.setPos(0.25,0,-0.025)
		
		#The first headlight
		Headlight1 = Spotlight("Headlight1")
		lens = PerspectiveLens()
		lens.setFov(180)
		Headlight1.setLens(lens)
		Headlight1np = render.attachNewNode(Headlight1)
		Headlight1np.reparentTo(Car_np)
		Headlight1np.setPos(-0.8,2.5,-0.5)
		Headlight1np.setP(-15)
		render.setLight(Headlight1np)
		
		#The second headlight
		Headlight2 = Spotlight("Headlight2")
		Headlight2.setLens(lens)
		Headlight2np = render.attachNewNode(Headlight2)
		Headlight2np.reparentTo(Car_np)
		Headlight2np.setPos(0.8,2.5,-0.5)
		Headlight2np.setP(-15)
		render.setLight(Headlight2np)
		
		#Sounds
		self.horn_sound = loader.loadSfx("Sounds/horn.ogg")
		self.start_sound = loader.loadSfx("Sounds/enginestart.ogg")
		self.engine_idle_sound = loader.loadSfx("Sounds/engineidle.ogg")
		self.engine_idle_sound.setLoop(True)
		self.accelerate_sound = loader.loadSfx("Sounds/enginethrottle.ogg")
				
		#Camera
		base.disableMouse()
		camera.reparentTo(Car_np)
		camera.setPos(0,-15,3)
		camera.setHpr(0,-10,0)
		
		#Wheel function
		def Wheel(pos, np, r, f):
			w = self.Car_sim.createWheel()
			w.setNode(np.node())
			w.setChassisConnectionPointCs(pos)
			w.setFrontWheel(f)
			w.setWheelDirectionCs(Vec3(0, 0, -1))
			w.setWheelAxleCs(Vec3(1, 0, 0))
			w.setWheelRadius(r)
			w.setMaxSuspensionTravelCm(40)
			w.setSuspensionStiffness(120)
			w.setWheelsDampingRelaxation(2.3)
			w.setWheelsDampingCompression(4.4)
			w.setFrictionSlip(50)
			w.setRollInfluence(0.1)
		
		#Wheels	
		w1_np = loader.loadModel("Models/Lwheel")
		w1_np.reparentTo(render)
		w1_np.setColorScale(0,6)
		Wheel(Point3(-1,1,-0.6), w1_np, 0.4, False)
		
		w2_np = loader.loadModel("Models/Rwheel")
		w2_np.reparentTo(render)
		w2_np.setColorScale(0,6)
		Wheel(Point3(-1.1,-1.2,-0.6), w2_np, 0.4, True)
		
		w3_np = loader.loadModel("Models/Lwheel")
		w3_np.reparentTo(render)
		w3_np.setColorScale(0,6)
		Wheel(Point3(1.1,-1,-0.6), w3_np, 0.4, True)
		
		w4_np = loader.loadModel("Models/Rwheel")
		w4_np.reparentTo(render)
		w4_np.setColorScale(0,6)
		Wheel(Point3(1,1,-0.6), w4_np, 0.4, False)
		

		
		#The engine and steering
		def processInput(dt):
			
			#Vehicle properties
			self.steeringClamp = 35.0
			self.steeringIncrement = 70
			engineForce = 0.0
			brakeForce = 0.0
			
			
			#Get the vehicle's current speed
			self.carspeed = self.Car_sim.getCurrentSpeedKmHour()
			
			
			#Engage clutch when in gear 0
			if self.gear == 0:
				self.clutch = 1
			
			
			#Slow the steering when at higher speeds
			self.steeringIncrement = self.steeringIncrement - self.carspeed / 1.5
			
			
			#Reset the steering
			if not inputState.isSet("L") and not inputState.isSet("R"):
				
				if self.steering < 0.00:
					self.steering = self.steering + 0.6
				if self.steering > 0.00:
					self.steering = self.steering - 0.6
					
				if self.steering < 1.0 and self.steering > -1.0:
					self.steering = 0
			
			
			#Slow the car down while it's moving
			if self.clutch == 0:
				brakeForce = brakeForce + self.carspeed / 5
			else:
				brakeForce = brakeForce + self.carspeed / 15
		
			
			#Forward
			if self.start == 1:
				if inputState.isSet("F"):
					self.RPM = self.RPM + 35
					self.accelerate_sound.play()
				if self.clutch == 0:
					
					if self.gear == -1:
						if self.carspeed > self.carmaxreversespeed:	
							engineForce = -self.RPM / 3
							
					if self.gear == 1:
						if self.carspeed < self.carmaxspeed:
							engineForce = self.RPM / 1

			
			#Brake	
			if inputState.isSet("B"):
				engineForce = 0.0
				brakeForce = 12.0
				if self.gear != 0 and self.clutch == 0:
					self.RPM = self.RPM - 20
				
			#Left	
			if inputState.isSet("L"):
				if self.steering < 0.0:
					#This makes the steering reset at the correct speed when turning from right to left
					self.steering += dt * self.steeringIncrement + 0.6
					self.steering = min(self.steering, self.steeringClamp)
				else:
					#Normal steering
					self.steering += dt * self.steeringIncrement
					self.steering = min(self.steering, self.steeringClamp)
			
			#Right	
			if inputState.isSet("R"):
				if self.steering > 0.0:
					#This makes the steering reset at the correct speed when turning from left to right
					self.steering -= dt * self.steeringIncrement + 0.6
					self.steering = max(self.steering, -self.steeringClamp)
				else:
					#Normal steering
					self.steering -= dt * self.steeringIncrement
					self.steering = max(self.steering, -self.steeringClamp)
			
			#Park
			if self.Pbrake == 1:
				brakeForce = 10.0
				if self.gear != 0 and self. clutch == 0:
					self.RPM = self.RPM - 20
				
				
			#Apply forces to wheels	
			self.Car_sim.applyEngineForce(engineForce, 0);
			self.Car_sim.applyEngineForce(engineForce, 3);
			self.Car_sim.setBrake(brakeForce, 1);
			self.Car_sim.setBrake(brakeForce, 2);
			self.Car_sim.setSteeringValue(self.steering, 0);
			self.Car_sim.setSteeringValue(self.steering, 3);
			
			#Steering wheel
			Sw.setHpr(0,0,-self.steering*10)
		
		
		#The HUD
		self.gear_hud = OnscreenImage(image = "Textures/gear_hud.png", pos = (-1,0,-0.85), scale = (0.2))
		self.gear_hud.setTransparency(TransparencyAttrib.MAlpha)
		
		self.gear2_hud = OnscreenImage(image = "Textures/gear2_hud.png", pos = (-1,0,-0.85), scale = (0.2))
		self.gear2_hud.setTransparency(TransparencyAttrib.MAlpha)
		
		self.starter = OnscreenImage(image = "Textures/starter.png", pos = (-1.2,0,-0.85), scale = (0.15))
		self.starter.setTransparency(TransparencyAttrib.MAlpha)
		
		self.park = OnscreenImage(image = "Textures/pbrake.png", pos = (-0.8,0,-0.85), scale = (0.1))
		self.park.setTransparency(TransparencyAttrib.MAlpha)
		
		self.rev_counter = OnscreenImage(image = "Textures/dial.png", pos = (-1.6, 0.0, -0.70), scale = (0.6,0.6,0.4))
		self.rev_counter.setTransparency(TransparencyAttrib.MAlpha)
		
		self.rev_needle = OnscreenImage(image = "Textures/needle.png", pos = (-1.6, 0.0, -0.70), scale = (0.5))
		self.rev_needle.setTransparency(TransparencyAttrib.MAlpha)
		
		self.rev_text = OnscreenText(text = " ", pos = (-1.6, -0.90, 0), scale = 0.05)
		
		self.speedometer = OnscreenImage(image = "Textures/dial.png", pos = (-1.68, 0.0, -0.10), scale = (0.7,0.7,0.5))
		self.speedometer.setTransparency(TransparencyAttrib.MAlpha)
		
		self.speedometer_needle = OnscreenImage(image = "Textures/needle.png", pos = (-1.68, 0.0, -0.10), scale = (0.5))
		self.speedometer_needle.setTransparency(TransparencyAttrib.MAlpha)
		
		self.speedometer_text = OnscreenText(text = " ", pos = (-1.68, -0.35, 0), scale = 0.05)
		
		
		#Update the HUD
		def Update_HUD():
			
			#Move gear selector
			if self.gear == -1:
				self.gear2_hud.setPos(-1,0,-0.785)
			if self.gear == 0:
				self.gear2_hud.setPos(-1,0,-0.85)
			if self.gear == 1:
				self.gear2_hud.setPos(-1,0,-0.91)
				
			#Rotate starter
			if self.start == 0:
				self.starter.setHpr(0,0,0)
			else:
				self.starter.setHpr(0,0,45)	
				
			#Update the parking brake light
			if self.Pbrake == 1:
				self.park.setImage("Textures/pbrake2.png")
				self.park.setTransparency(TransparencyAttrib.MAlpha)
			else:
				self.park.setImage("Textures/pbrake.png")
				self.park.setTransparency(TransparencyAttrib.MAlpha)	
				
			#Update the rev counter
			self.rev_needle.setR(self.RPM/22)	
			rev_string = str(self.RPM)[:4]
			self.rev_text.setText(rev_string+" RPM")
			
			#Update the speedometer
			if self.carspeed > 0.0:
				self.speedometer_needle.setR(self.carspeed*2.5)
			if self.carspeed < 0.0:
				self.speedometer_needle.setR(-self.carspeed*2.5)
			speed_string = str(self.carspeed)[:3]
			self.speedometer_text.setText(speed_string+" KPH")
					
					
						
		#Update the program
		def update(task):
			dt = globalClock.getDt() 
			processInput(dt)
			Update_HUD()
			set_time()
			set_terrain()
			set_headlights()
			update_rpm()
			scene.doPhysics(dt, 5, 1.0/180.0)
			return task.cont
			
		taskMgr.add(update, "Update")
class DirectEntry(DirectFrame):
    """
    DirectEntry(parent) - Create a DirectGuiWidget which responds
    to keyboard buttons
    """

    directWtext = ConfigVariableBool('direct-wtext', 1)

    AllowCapNamePrefixes = (
        "Al",
        "Ap",
        "Ben",
        "De",
        "Del",
        "Della",
        "Delle",
        "Der",
        "Di",
        "Du",
        "El",
        "Fitz",
        "La",
        "Las",
        "Le",
        "Les",
        "Lo",
        "Los",
        "Mac",
        "St",
        "Te",
        "Ten",
        "Van",
        "Von",
    )
    ForceCapNamePrefixes = (
        "D'",
        "DeLa",
        "Dell'",
        "L'",
        "M'",
        "Mc",
        "O'",
    )

    def __init__(self, parent=None, **kw):
        # Inherits from DirectFrame
        # A Direct Frame can have:
        # - A background texture (pass in path to image, or Texture Card)
        # - A midground geometry item (pass in geometry)
        # - A foreground text Node (pass in text string or Onscreen Text)
        # For a direct entry:
        # Each button has 3 states (focus, noFocus, disabled)
        # The same image/geom/text can be used for all three states or each
        # state can have a different text/geom/image
        # State transitions happen automatically based upon mouse interaction
        optiondefs = (
            # Define type of DirectGuiWidget
            ('pgFunc', PGEntry, None),
            ('numStates', 3, None),
            ('state', DGG.NORMAL, None),
            ('entryFont', None, DGG.INITOPT),
            ('width', 10, self.updateWidth),
            ('numLines', 1, self.updateNumLines),
            ('focus', 0, self.setFocus),
            ('cursorKeys', 1, self.setCursorKeysActive),
            ('obscured', 0, self.setObscureMode),
            # Setting backgroundFocus allows the entry box to get keyboard
            # events that are not handled by other things (i.e. events that
            # fall through to the background):
            ('backgroundFocus', 0, self.setBackgroundFocus),
            # Text used for the PGEntry text node
            # NOTE: This overrides the DirectFrame text option
            ('initialText', '', DGG.INITOPT),
            # Enable or disable text overflow scrolling
            ('overflow', 0, self.setOverflowMode),
            # Command to be called on hitting Enter
            ('command', None, None),
            ('extraArgs', [], None),
            # Command to be called when enter is hit but we fail to submit
            ('failedCommand', None, None),
            ('failedExtraArgs', [], None),
            # commands to be called when focus is gained or lost
            ('focusInCommand', None, None),
            ('focusInExtraArgs', [], None),
            ('focusOutCommand', None, None),
            ('focusOutExtraArgs', [], None),
            # Sounds to be used for button events
            ('rolloverSound', DGG.getDefaultRolloverSound(),
             self.setRolloverSound),
            ('clickSound', DGG.getDefaultClickSound(), self.setClickSound),
            ('autoCapitalize', 0, self.autoCapitalizeFunc),
            ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes,
             None),
            ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes,
             None),
        )
        # Merge keyword options with default options
        self.defineoptions(kw, optiondefs)

        # Initialize superclasses
        DirectFrame.__init__(self, parent)

        if self['entryFont'] == None:
            font = DGG.getDefaultFont()
        else:
            font = self['entryFont']

        # Create Text Node Component
        self.onscreenText = self.createcomponent(
            'text',
            (),
            None,
            OnscreenText,
            (),
            parent=ShowBaseGlobal.hidden,
            # Pass in empty text to avoid extra work, since its really
            # The PGEntry which will use the TextNode to generate geometry
            text='',
            align=TextNode.ALeft,
            font=font,
            scale=1,
            # Don't get rid of the text node
            mayChange=1)

        # We can get rid of the node path since we're just using the
        # onscreenText as an easy way to access a text node as a
        # component
        self.onscreenText.removeNode()

        # Bind command function
        self.bind(DGG.ACCEPT, self.commandFunc)
        self.bind(DGG.ACCEPTFAILED, self.failedCommandFunc)

        self.accept(self.guiItem.getFocusInEvent(), self.focusInCommandFunc)
        self.accept(self.guiItem.getFocusOutEvent(), self.focusOutCommandFunc)

        # listen for auto-capitalize events on a separate object to prevent
        # clashing with other parts of the system
        self._autoCapListener = DirectObject()

        # Call option initialization functions
        self.initialiseoptions(DirectEntry)

        if not hasattr(self, 'autoCapitalizeAllowPrefixes'):
            self.autoCapitalizeAllowPrefixes = DirectEntry.AllowCapNamePrefixes
        if not hasattr(self, 'autoCapitalizeForcePrefixes'):
            self.autoCapitalizeForcePrefixes = DirectEntry.ForceCapNamePrefixes

        # Update TextNodes for each state
        for i in range(self['numStates']):
            self.guiItem.setTextDef(i, self.onscreenText.textNode)

        # Now we should call setup() again to make sure it has the
        # right font def.
        self.setup()

        # Update initial text
        self.unicodeText = 0
        if self['initialText']:
            self.enterText(self['initialText'])

    def destroy(self):
        self.ignoreAll()
        self._autoCapListener.ignoreAll()
        DirectFrame.destroy(self)

    def setup(self):
        self.guiItem.setupMinimal(self['width'], self['numLines'])

    def updateWidth(self):
        self.guiItem.setMaxWidth(self['width'])

    def updateNumLines(self):
        self.guiItem.setNumLines(self['numLines'])

    def setFocus(self):
        PGEntry.setFocus(self.guiItem, self['focus'])

    def setCursorKeysActive(self):
        PGEntry.setCursorKeysActive(self.guiItem, self['cursorKeys'])

    def setOverflowMode(self):
        PGEntry.set_overflow_mode(self.guiItem, self['overflow'])

    def setObscureMode(self):
        PGEntry.setObscureMode(self.guiItem, self['obscured'])

    def setBackgroundFocus(self):
        PGEntry.setBackgroundFocus(self.guiItem, self['backgroundFocus'])

    def setRolloverSound(self):
        rolloverSound = self['rolloverSound']
        if rolloverSound:
            self.guiItem.setSound(DGG.ENTER + self.guiId, rolloverSound)
        else:
            self.guiItem.clearSound(DGG.ENTER + self.guiId)

    def setClickSound(self):
        clickSound = self['clickSound']
        if clickSound:
            self.guiItem.setSound(DGG.ACCEPT + self.guiId, clickSound)
        else:
            self.guiItem.clearSound(DGG.ACCEPT + self.guiId)

    def commandFunc(self, event):
        if self['command']:
            # Pass any extra args to command
            self['command'](*[self.get()] + self['extraArgs'])

    def failedCommandFunc(self, event):
        if self['failedCommand']:
            # Pass any extra args
            self['failedCommand'](*[self.get()] + self['failedExtraArgs'])

    def autoCapitalizeFunc(self):
        if self['autoCapitalize']:
            self._autoCapListener.accept(self.guiItem.getTypeEvent(),
                                         self._handleTyping)
            self._autoCapListener.accept(self.guiItem.getEraseEvent(),
                                         self._handleErasing)
        else:
            self._autoCapListener.ignore(self.guiItem.getTypeEvent())
            self._autoCapListener.ignore(self.guiItem.getEraseEvent())

    def focusInCommandFunc(self):
        if self['focusInCommand']:
            self['focusInCommand'](*self['focusInExtraArgs'])
        if self['autoCapitalize']:
            self.accept(self.guiItem.getTypeEvent(), self._handleTyping)
            self.accept(self.guiItem.getEraseEvent(), self._handleErasing)

    def _handleTyping(self, guiEvent):
        self._autoCapitalize()

    def _handleErasing(self, guiEvent):
        self._autoCapitalize()

    def _autoCapitalize(self):
        name = self.guiItem.getWtext()
        # capitalize each word, allowing for things like McMutton
        capName = u''
        # track each individual word to detect prefixes like Mc
        wordSoFar = u''
        # track whether the previous character was part of a word or not
        wasNonWordChar = True
        for i, character in enumerate(name):
            # test to see if we are between words
            # - Count characters that can't be capitalized as a break between words
            #   This assumes that string.lower and string.upper will return different
            #   values for all unicode letters.
            # - Don't count apostrophes as a break between words
            if character.lower() == character.upper() and character != u"'":
                # we are between words
                wordSoFar = u''
                wasNonWordChar = True
            else:
                capitalize = False
                if wasNonWordChar:
                    # first letter of a word, capitalize it unconditionally;
                    capitalize = True
                elif (character == character.upper()
                      and len(self.autoCapitalizeAllowPrefixes)
                      and wordSoFar in self.autoCapitalizeAllowPrefixes):
                    # first letter after one of the prefixes, allow it to be capitalized
                    capitalize = True
                elif (len(self.autoCapitalizeForcePrefixes)
                      and wordSoFar in self.autoCapitalizeForcePrefixes):
                    # first letter after one of the force prefixes, force it to be capitalized
                    capitalize = True
                if capitalize:
                    # allow this letter to remain capitalized
                    character = character.upper()
                else:
                    character = character.lower()
                wordSoFar += character
                wasNonWordChar = False
            capName += character
        self.guiItem.setWtext(capName)
        self.guiItem.setCursorPosition(self.guiItem.getNumCharacters())

    def focusOutCommandFunc(self):
        if self['focusOutCommand']:
            self['focusOutCommand'](*self['focusOutExtraArgs'])
        if self['autoCapitalize']:
            self.ignore(self.guiItem.getTypeEvent())
            self.ignore(self.guiItem.getEraseEvent())

    def set(self, text):
        """ Changes the text currently showing in the typable region;
        does not change the current cursor position.  Also see
        enterText(). """

        assert not isinstance(text, bytes)
        self.unicodeText = True
        self.guiItem.setWtext(text)

    def get(self, plain=False):
        """ Returns the text currently showing in the typable region.
        If plain is True, the returned text will not include any
        formatting characters like nested color-change codes. """

        wantWide = self.unicodeText or self.guiItem.isWtext()
        if not self.directWtext.getValue():
            # If the user has configured wide-text off, then always
            # return an 8-bit string.  This will be encoded if
            # necessary, according to Panda's default encoding.
            wantWide = False

        if plain:
            if wantWide:
                return self.guiItem.getPlainWtext()
            else:
                return self.guiItem.getPlainText()
        else:
            if wantWide:
                return self.guiItem.getWtext()
            else:
                return self.guiItem.getText()

    def getCursorPosition(self):
        return self.guiItem.getCursorPosition()

    def setCursorPosition(self, pos):
        if (pos < 0):
            self.guiItem.setCursorPosition(self.guiItem.getNumCharacters() +
                                           pos)
        else:
            self.guiItem.setCursorPosition(pos)

    def getNumCharacters(self):
        return self.guiItem.getNumCharacters()

    def enterText(self, text):
        """ sets the entry's text, and moves the cursor to the end """
        self.set(text)
        self.setCursorPosition(self.guiItem.getNumCharacters())

    def getFont(self):
        return self.onscreenText.getFont()

    def getBounds(self, state=0):
        # Compute the width and height for the entry itself, ignoring
        # geometry etc.
        tn = self.onscreenText.textNode
        mat = tn.getTransform()
        align = tn.getAlign()
        lineHeight = tn.getLineHeight()
        numLines = self['numLines']
        width = self['width']

        if align == TextNode.ALeft:
            left = 0.0
            right = width
        elif align == TextNode.ACenter:
            left = -width / 2.0
            right = width / 2.0
        elif align == TextNode.ARight:
            left = -width
            right = 0.0

        bottom = -0.3 * lineHeight - (lineHeight * (numLines - 1))
        top = lineHeight

        self.ll.set(left, 0.0, bottom)
        self.ur.set(right, 0.0, top)
        self.ll = mat.xformPoint(Point3.rfu(left, 0.0, bottom))
        self.ur = mat.xformPoint(Point3.rfu(right, 0.0, top))

        vec_right = Vec3.right()
        vec_up = Vec3.up()
        left = (vec_right[0] * self.ll[0] + vec_right[1] * self.ll[1] +
                vec_right[2] * self.ll[2])
        right = (vec_right[0] * self.ur[0] + vec_right[1] * self.ur[1] +
                 vec_right[2] * self.ur[2])
        bottom = (vec_up[0] * self.ll[0] + vec_up[1] * self.ll[1] +
                  vec_up[2] * self.ll[2])
        top = (vec_up[0] * self.ur[0] + vec_up[1] * self.ur[1] +
               vec_up[2] * self.ur[2])
        self.ll = Point3(left, 0.0, bottom)
        self.ur = Point3(right, 0.0, top)

        # Scale bounds to give a pad around graphics.  We also want to
        # scale around the border width.
        pad = self['pad']
        borderWidth = self['borderWidth']
        self.bounds = [
            self.ll[0] - pad[0] - borderWidth[0],
            self.ur[0] + pad[0] + borderWidth[0],
            self.ll[2] - pad[1] - borderWidth[1],
            self.ur[2] + pad[1] + borderWidth[1]
        ]
        return self.bounds
Beispiel #35
0
class PandaPhysicsSystem(DelegateByNetmode, SignalListener):
    subclasses = {}

    def __init__(self):
        self.register_signals()

        self.world = BulletWorld()
        self.world.setGravity((0, 0, -9.81))

        # # Seems that this does not function
        # on_contact_added = PythonCallbackObject(self._on_contact_added)
        # self.world.set_contact_added_callback(on_contact_added)

        # on_filter = PythonCallbackObject(self._filter_collision)
        # self.world.set_filter_callback(on_filter)

        self.listener = DirectObject()
        self.listener.accept('bullet-contact-added', self._on_contact_added)
        self.listener.accept('bullet-contact-destroyed',
                             self._on_contact_removed)

        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(True)
        debug_node.showBoundingBoxes(False)
        debug_node.showNormals(False)

        self.debug_nodepath = render.attachNewNode(debug_node)
        self.world.set_debug_node(debug_node)

        self.tracked_contacts = defaultdict(int)
        self.existing_collisions = set()

    def _create_contacts_from_result(self, requesting_node, contact_result):
        """Return collision contacts between two nodes"""
        contacts = []

        for contact in contact_result.get_contacts():
            if contact.get_node0() == requesting_node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_a()
                normal = -manifold.get_normal_world_on_b()

            elif contact.get_node1() == requesting_node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_b()
                normal = manifold.get_normal_world_on_b()

            impulse = manifold.get_applied_impulse()
            contact_ = CollisionContact(position, normal, impulse)
            contacts.append(contact_)

        return contacts

    def _on_contact_removed(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] -= 1

    def _on_contact_added(self, node_a, node_b):
        self.tracked_contacts[(node_a, node_b)] += 1

    def _filter_collision(self, filter_data):
        filter_data.set_collide(True)

    @RegisterPhysicsNode.on_global
    def register_node(self, node):
        self.world.attachRigidBody(node)
        node.set_python_tag("world", self.world)

    @DeregisterPhysicsNode.on_global
    def deregister_node(self, node):
        self.world.removeRigidBody(node)
        node.clear_python_tag("world")

    def dispatch_collisions(self):
        # Dispatch collisions
        existing_collisions = self.existing_collisions
        for pair, contact_count in self.tracked_contacts.items():
            if contact_count > 0 and pair not in existing_collisions:
                existing_collisions.add(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = entity_from_nodepath(node_a)
                entity_b = entity_from_nodepath(node_b)

                contact_result = None

                if entity_a is not None:

                    def contact_getter():
                        nonlocal contact_result
                        if contact_result is None:
                            contact_result = self.world.contact_test_pair(
                                node_a, node_b)

                        return self._create_contacts_from_result(
                            node_a, contact_result)

                    collision_result = LazyCollisionResult(
                        entity_b, CollisionState.started, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_a)

                if entity_b is not None:

                    def contact_getter():
                        nonlocal contact_result
                        if contact_result is None:
                            contact_result = self.world.contact_test_pair(
                                node_a, node_b)

                        return self._create_contacts_from_result(
                            node_b, contact_result)

                    collision_result = LazyCollisionResult(
                        entity_a, CollisionState.started, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_b)

            elif contact_count == 0 and pair in existing_collisions:
                existing_collisions.remove(pair)

                # Dispatch collision
                node_a, node_b = pair

                entity_a = entity_from_nodepath(node_a)
                entity_b = entity_from_nodepath(node_b)

                # Don't send contacts for ended collisions
                contact_getter = lambda: None

                if entity_a is not None:
                    collision_result = LazyCollisionResult(
                        entity_b, CollisionState.ended, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_a)

                if entity_b is not None:
                    collision_result = LazyCollisionResult(
                        entity_a, CollisionState.ended, contact_getter)
                    CollisionSignal.invoke(collision_result, target=entity_b)

    def update(self, delta_time):
        self.world.doPhysics(delta_time)
        self.dispatch_collisions()
Beispiel #36
0
        if self.steer2d:
            base.cam.setX(self.avatar.getX())
            base.cam.setZ(self.avatar.getZ() + self.camdistZ)
        base.cam.lookAt(self.avatar)

        return Task.cont


#=========================================================================
# Main
#=========================================================================

alight = AmbientLight('alight')
alight.setColor((.3, .3, .3, 1))
alnp = render.attachNewNode(alight)
render.setLight(alnp)

dlight = DirectionalLight('dlight')
lv = .6
dlight.setColor((lv, lv, lv, 1))
dlnp = render.attachNewNode(dlight)
render.setLight(dlnp)
dlnp.setPos(0, -20, 35)
dlnp.lookAt(0, 0, 0)

DO = DirectObject()
DO.accept('c', toggle_collisions)
DO.accept('h', toggle_info)
DO.accept('x', toggle_wire)
DO.accept('escape', sys.exit)
Beispiel #37
0
but then we should have used 2 accepts like this:

DO.accept('ray1-again-smileys', collideAgainBalls)
DO.accept('ray1-again-frowney', collideAgainBalls)

instead of just one as we did below, and this don't hurt very much in this snippet cos' we got just 2 groups, but could be complicated if we need to use a lot more groups.

Another big thing to note is that we could have been done all of this using the masking technique (see step4.py).
"""

#** to manage the collision events need Directobject, because the chaining between the CollisionHandlerEvent handler and our two functions seen above, happens with the accept() function of a DirectObject instance
DO=DirectObject()

#** Let's manage the collision events: as you can see in this rack of 4 accepts, these are the resulting events generated by the patterns defined above. Now it's up to you to understand the why an the how comparing these with those above.
DO.accept('ray1-into-smiley', collideInSmiley)
DO.accept('ray1-out-smiley', collideOutSmiley)
DO.accept('ray1-into-frowney', collideInFrowney)
DO.accept('ray1-out-frowney', collideOutFrowney)
# the event here instead, will call the collideAgainBalls function handler while the mouse pointer keep over any ball, either of the smiley or the frowney groups - still, check above how we defined the pattern string to understand how we came to this.
DO.accept('ray_again_all', collideAgainBalls)

#** Storage for the object actually hovered by the mouse pointer
pickingEnabledOject=None

#** Here's how we interact with mouse clicks - see the mouseClick function above
DO.accept('mouse1', mouseClick, ['down'])
DO.accept('mouse1-up', mouseClick, ['up'])

#** And at the end of all, we start the task that continuously update the ray collider position and orientation while we move the mouse pointer
taskMgr.add(rayupdate, "updatePicker")
Beispiel #38
0
class ControlSettingsScreenHelper(object):

    COLOUR_VALID = (1, 1, 1, 1)
    COLOUR_SELECTED = (0.75, 0.75, 1, 1)
    COLOUR_INVALID = (1, 0.75, 0.75, 1)

    def __init__(self, app, scene, parent):
        self.app = app
        self.scene = scene
        self.parent = parent
        self.keymap = self.app.keymap
        self.do = DirectObject()

        self.saveButton = None
        self.finishButton = None
        self.pendingChanges = False

        # The KeyboadMapping provides a dict of keys to actions: this member
        # does the opposite (provides a dict to actions to keys)
        self.keys = {}

        self.selectedAction = None
        self.inputLookup = {}
        self.layout = []

    def show(self):
        self.keys = dict((v, k) for k, v in self.keymap.actions.items())

        for column in self.layout:
            for category in column:
                for action in category:
                    if action in self.keys:
                        self.inputLookup[action]['text'] = self.keys[action]
                        self.inputLookup[action]['frameColor'] = self.COLOUR_VALID
                    else:
                        self.inputLookup[action]['frameColor'] = self.COLOUR_INVALID
                        self.keys[action] = None

    def setup(self, node):
        colours = self.app.theme.colours

        TEXT_PROPERTIES = {
            'parent': node,
            'text_scale': 0.038,
            'text_fg': colours.listboxButtons,
            'text_align': TextNode.A_right,
            'relief': None,
        }

        KEY_PROPERTIES = {
            'parent': node,
            'scale': 0.038,
            'frameColor': self.COLOUR_VALID,
            'frameSize': (-3.0, 3.0, -0.7, 0.7),
            'text_align': TextNode.A_center,
            'text_scale': 0.9,
            'text_pos': (0, -0.18),
            'relief': DGG.FLAT,
            'textMayChange': True,
            'command': self.actionSelected,
        }

        movement = [ACTION_JUMP, ACTION_DOWN, ACTION_LEFT, ACTION_RIGHT]
        menus = [ACTION_MAIN_MENU, ACTION_MORE_MENU]
        actions = [
            ACTION_UPGRADE_MENU, ACTION_USE_UPGRADE,
            ACTION_ABANDON_UPGRADE, ACTION_EDIT_PLAYER_INFO, ACTION_READY,
            ACTION_PAUSE_GAME, ACTION_EMOTE,
        ]
        misc = [ACTION_CHAT, ACTION_FOLLOW]
        upgrades = [
            upgradeClass.action for upgradeClass in sorted(
                allUpgrades, key=lambda upgradeClass: upgradeClass.order)]
        upgrades.append(ACTION_CLEAR_UPGRADE)

        display = [
            ACTION_LEADERBOARD_TOGGLE, ACTION_HUD_TOGGLE,
            ACTION_TERMINAL_TOGGLE]

        actionNames = {
            ACTION_ABANDON_UPGRADE: 'Abandon upgrade',
            ACTION_UPGRADE_MENU: 'Select upgrade',
            ACTION_USE_UPGRADE: 'Activate upgrade',
            ACTION_EDIT_PLAYER_INFO: 'Change nick / hat',
            ACTION_CHAT: 'Chat',
            ACTION_DOWN: 'Drop down',
            ACTION_EMOTE: 'Emote',
            ACTION_FOLLOW: 'Auto pan (replay)',
            ACTION_JUMP: 'Jump',
            ACTION_LEADERBOARD_TOGGLE: 'Show leaderboard',
            ACTION_LEFT: 'Move left',
            ACTION_MAIN_MENU: 'Main menu',
            ACTION_MORE_MENU: 'Advanced',
            ACTION_CLEAR_UPGRADE: 'Deselect upgrade',
            ACTION_READY: 'Toggle ready',
            ACTION_PAUSE_GAME: 'Pause/resume',
            ACTION_RIGHT: 'Move right',
            ACTION_HUD_TOGGLE: 'Toggle HUD',
            ACTION_TERMINAL_TOGGLE: 'Toggle terminal',
        }
        actionNames.update((upgradeClass.action, upgradeClass.name) for
                           upgradeClass in allUpgrades)

        # Organise the categories by column
        self.layout = [
            [movement, menus],
            [actions, display],
            [upgrades, misc],
        ]

        xPos = -0.68

        for column in self.layout:          # Each column
            yPos = 0.30
            for category in column:         # Each category
                for action in category:     # Each action
                    # Draw action name (eg. Respawn)
                    label = DirectLabel(
                        text=actionNames[action],
                        **TEXT_PROPERTIES
                    )
                    align(label, right=xPos, midZ=yPos)

                    # Create input box
                    box = DirectButton(
                        text='',
                        extraArgs=[action],
                        **KEY_PROPERTIES
                    )
                    align(box, left=xPos + 0.03, midZ=yPos)
                    self.inputLookup[action] = box

                    yPos -= 0.07  # Between items
                yPos -= 0.08      # Between categories
            xPos += 0.65          # Between columns

        BUTTON_PROPERTIES = {
            'scale': 0.04,
            'frameSize': (-5.0, 5.0, -1.0, 1.5),
            'parent': node,
        }

        self.restoreDefaultButton = DirectButton(
            text='Restore defaults',
            # scale=0.04,
            # parent=node,
            command=self.restoreDefaults,
            # text_align=TextNode.A_left,
            # pad=(0.5, 0.2)
            **BUTTON_PROPERTIES
        )
        align(self.restoreDefaultButton, midX=0, z=-0.63)

        self.saveButton = DirectButton(
            text='Save',
            command=self.save,
            **BUTTON_PROPERTIES
        )
        align(self.saveButton, left=-0.87, z=-0.63)
        self.saveButton.hide()

        self.finishButton = DirectButton(
            text='Back',
            command=self.cancelPressed,
            **BUTTON_PROPERTIES
        )
        align(self.finishButton, right=0.87, z=-0.63)

    def cancelPressed(self):
        self.deselectAction()
        if self.pendingChanges:
            self.keymap.reset()
            self.show()
            self.hideSaveButton()
        else:
            self.parent.showMainButtons()

    def save(self):
        self.keymap.apply()
        self.keymap.save()
        self.hideSaveButton()

    def showSaveButton(self):
        self.pendingChanges = True
        self.saveButton.show()
        self.finishButton['text'] = 'Cancel'

    def hideSaveButton(self):
        self.pendingChanges = False
        self.saveButton.hide()
        self.finishButton['text'] = 'Back'

    def restoreDefaults(self):
        self.deselectAction()
        self.keymap.revertToDefault()
        self.show()
        self.showSaveButton()

    def deselectAction(self):
        if self.selectedAction:
            self.inputLookup[self.selectedAction]['frameColor'] = self.COLOUR_VALID
        self.selectedAction = None
        self.do.ignoreAll()

    def actionSelected(self, action):
        self.deselectAction()
        self.selectedAction = action
        button = self.inputLookup[action]
        button['frameColor'] = self.COLOUR_SELECTED
        log.debug('Changing key for %s' % action)

        self.app.panda.buttonThrowers[0].node().setButtonDownEvent('button')
        self.do.accept('button', self.keyPressed, [action])

    def keyPressed(self, action, key):
        self.deselectAction()

        oldKey = self.keys[action]

        if oldKey == key:
            return

        # Remove the old key from the keymap
        if oldKey is not None:
            del self.keymap.actions[oldKey]

        self.inputLookup[action]['text'] = key

        # If there's a conflict, remove the conflicting action from the keymap
        if key in self.keymap.actions:
            secondAction = self.keymap.actions[key]
            log.debug('Overwriting conflicting key for %s' % secondAction)

            self.inputLookup[secondAction]['text'] = ''
            self.inputLookup[secondAction]['frameColor'] = self.COLOUR_INVALID
            self.keys[secondAction] = None

        # Update the keymap with the new key
        self.keys[action] = key
        self.keymap.actions[key] = action
        log.debug('New key for %s is %s' % (action, key))

        self.showSaveButton()
Beispiel #39
0
class DirectEntry(DirectFrame):
    __module__ = __name__
    directWtext = ConfigVariableBool('direct-wtext', 1)
    AllowCapNamePrefixes = ('Al', 'Ap', 'Ben', 'De', 'Del', 'Della', 'Delle', 'Der', 'Di', 'Du', 'El', 'Fitz', 'La', 'Las', 'Le', 'Les', 'Lo', 'Los', 'Mac', 'St', 'Te', 'Ten', 'Van', 'Von')
    ForceCapNamePrefixes = ("D'", 'DeLa', "Dell'", "L'", "M'", 'Mc', "O'")

    def __init__(self, parent = None, **kw):
        optiondefs = (('pgFunc', PGEntry, None),
         ('numStates', 3, None),
         ('state', DGG.NORMAL, None),
         ('entryFont', None, DGG.INITOPT),
         ('width', 10, self.setup),
         ('numLines', 1, self.setup),
         ('focus', 0, self.setFocus),
         ('cursorKeys', 1, self.setCursorKeysActive),
         ('obscured', 0, self.setObscureMode),
         ('backgroundFocus', 0, self.setBackgroundFocus),
         ('initialText', '', DGG.INITOPT),
         ('command', None, None),
         ('extraArgs', [], None),
         ('failedCommand', None, None),
         ('failedExtraArgs', [], None),
         ('focusInCommand', None, None),
         ('focusInExtraArgs', [], None),
         ('focusOutCommand', None, None),
         ('focusOutExtraArgs', [], None),
         ('rolloverSound', DGG.getDefaultRolloverSound(), self.setRolloverSound),
         ('clickSound', DGG.getDefaultClickSound(), self.setClickSound),
         ('autoCapitalize', 0, self.autoCapitalizeFunc),
         ('autoCapitalizeAllowPrefixes', DirectEntry.AllowCapNamePrefixes, None),
         ('autoCapitalizeForcePrefixes', DirectEntry.ForceCapNamePrefixes, None))
        self.defineoptions(kw, optiondefs)
        DirectFrame.__init__(self, parent)
        if self['entryFont'] == None:
            font = DGG.getDefaultFont()
        else:
            font = self['entryFont']
        self.onscreenText = self.createcomponent('text', (), None, OnscreenText, (), parent=hidden, text='', align=TextNode.ALeft, font=font, scale=1, mayChange=1)
        self.onscreenText.removeNode()
        self.bind(DGG.ACCEPT, self.commandFunc)
        self.bind(DGG.ACCEPTFAILED, self.failedCommandFunc)
        self.accept(self.guiItem.getFocusInEvent(), self.focusInCommandFunc)
        self.accept(self.guiItem.getFocusOutEvent(), self.focusOutCommandFunc)
        self._autoCapListener = DirectObject()
        self.initialiseoptions(DirectEntry)
        if not hasattr(self, 'autoCapitalizeAllowPrefixes'):
            self.autoCapitalizeAllowPrefixes = DirectEntry.AllowCapNamePrefixes
        if not hasattr(self, 'autoCapitalizeForcePrefixes'):
            self.autoCapitalizeForcePrefixes = DirectEntry.ForceCapNamePrefixes
        for i in range(self['numStates']):
            self.guiItem.setTextDef(i, self.onscreenText.textNode)

        self.setup()
        self.unicodeText = 0
        if self['initialText']:
            self.enterText(self['initialText'])
        return None

    def destroy(self):
        self.ignoreAll()
        self._autoCapListener.ignoreAll()
        DirectFrame.destroy(self)

    def setup(self):
        self.guiItem.setupMinimal(self['width'], self['numLines'])

    def setFocus(self):
        PGEntry.setFocus(self.guiItem, self['focus'])

    def setCursorKeysActive(self):
        PGEntry.setCursorKeysActive(self.guiItem, self['cursorKeys'])

    def setObscureMode(self):
        PGEntry.setObscureMode(self.guiItem, self['obscured'])

    def setBackgroundFocus(self):
        PGEntry.setBackgroundFocus(self.guiItem, self['backgroundFocus'])

    def setRolloverSound(self):
        rolloverSound = self['rolloverSound']
        if rolloverSound:
            self.guiItem.setSound(DGG.ENTER + self.guiId, rolloverSound)
        else:
            self.guiItem.clearSound(DGG.ENTER + self.guiId)

    def setClickSound(self):
        clickSound = self['clickSound']
        if clickSound:
            self.guiItem.setSound(DGG.ACCEPT + self.guiId, clickSound)
        else:
            self.guiItem.clearSound(DGG.ACCEPT + self.guiId)

    def commandFunc(self, event):
        if self['command']:
            apply(self['command'], [self.get()] + self['extraArgs'])

    def failedCommandFunc(self, event):
        if self['failedCommand']:
            apply(self['failedCommand'], [self.get()] + self['failedExtraArgs'])

    def autoCapitalizeFunc(self):
        if self['autoCapitalize']:
            self._autoCapListener.accept(self.guiItem.getTypeEvent(), self._handleTyping)
            self._autoCapListener.accept(self.guiItem.getEraseEvent(), self._handleErasing)
        else:
            self._autoCapListener.ignore(self.guiItem.getTypeEvent())
            self._autoCapListener.ignore(self.guiItem.getEraseEvent())

    def focusInCommandFunc(self):
        if self['focusInCommand']:
            apply(self['focusInCommand'], self['focusInExtraArgs'])
        if self['autoCapitalize']:
            self.accept(self.guiItem.getTypeEvent(), self._handleTyping)
            self.accept(self.guiItem.getEraseEvent(), self._handleErasing)

    def _handleTyping(self, guiEvent):
        self._autoCapitalize()

    def _handleErasing(self, guiEvent):
        self._autoCapitalize()

    def _autoCapitalize(self):
        name = self.get().decode('utf-8')
        capName = ''
        wordSoFar = ''
        wasNonWordChar = True
        for i in xrange(len(name)):
            character = name[i]
            if string.lower(character) == string.upper(character) and character != "'":
                wordSoFar = ''
                wasNonWordChar = True
            else:
                capitalize = False
                if wasNonWordChar:
                    capitalize = True
                elif character == string.upper(character) and len(self.autoCapitalizeAllowPrefixes) and wordSoFar in self.autoCapitalizeAllowPrefixes:
                    capitalize = True
                elif len(self.autoCapitalizeForcePrefixes) and wordSoFar in self.autoCapitalizeForcePrefixes:
                    capitalize = True
                if capitalize:
                    character = string.upper(character)
                else:
                    character = string.lower(character)
                wordSoFar += character
                wasNonWordChar = False
            capName += character

        self.enterText(capName.encode('utf-8'))

    def focusOutCommandFunc(self):
        if self['focusOutCommand']:
            apply(self['focusOutCommand'], self['focusOutExtraArgs'])
        if self['autoCapitalize']:
            self.ignore(self.guiItem.getTypeEvent())
            self.ignore(self.guiItem.getEraseEvent())

    def set(self, text):
        self.unicodeText = isinstance(text, types.UnicodeType)
        if self.unicodeText:
            self.guiItem.setWtext(text)
        else:
            self.guiItem.setText(text)

    def get(self, plain = False):
        if not self.unicodeText:
            wantWide = self.guiItem.isWtext()
            if not self.directWtext.getValue():
                wantWide = False
            if plain:
                return wantWide and self.guiItem.getPlainWtext()
            else:
                return self.guiItem.getPlainText()
        elif wantWide:
            return self.guiItem.getWtext()
        else:
            return self.guiItem.getText()

    def setCursorPosition(self, pos):
        if pos < 0:
            self.guiItem.setCursorPosition(self.guiItem.getNumCharacters() + pos)
        else:
            self.guiItem.setCursorPosition(pos)

    def enterText(self, text):
        self.set(text)
        self.setCursorPosition(self.guiItem.getNumCharacters())

    def getFont(self):
        return self.onscreenText.getFont()

    def getBounds(self, state = 0):
        tn = self.onscreenText.textNode
        mat = tn.getTransform()
        align = tn.getAlign()
        lineHeight = tn.getLineHeight()
        numLines = self['numLines']
        width = self['width']
        if align == TextNode.ALeft:
            left = 0.0
            right = width
        elif align == TextNode.ACenter:
            left = -width / 2.0
            right = width / 2.0
        elif align == TextNode.ARight:
            left = -width
            right = 0.0
        bottom = -0.3 * lineHeight - lineHeight * (numLines - 1)
        top = lineHeight
        self.ll.set(left, 0.0, bottom)
        self.ur.set(right, 0.0, top)
        self.ll = mat.xformPoint(self.ll)
        self.ur = mat.xformPoint(self.ur)
        pad = self['pad']
        borderWidth = self['borderWidth']
        self.bounds = [self.ll[0] - pad[0] - borderWidth[0],
         self.ur[0] + pad[0] + borderWidth[0],
         self.ll[2] - pad[1] - borderWidth[1],
         self.ur[2] + pad[1] + borderWidth[1]]
        return self.bounds
Beispiel #40
0
class PandaPhysicsSystem(DelegateByNetmode, SignalListener):
    subclasses = {}

    def __init__(self):
        self.register_signals()

        self.world = BulletWorld()
        self.world.setGravity((0, 0, -9.81))

        # # Seems that this does not function
        # on_contact_added = PythonCallbackObject(self._on_contact_added)
        # self.world.set_contact_added_callback(on_contact_added)

        # on_filter = PythonCallbackObject(self._filter_collision)
        # self.world.set_filter_callback(on_filter)

        self.listener = DirectObject()
        self.listener.accept('bullet-contact-added', self._on_contact_added)
        self.listener.accept('bullet-contact-destroyed', self._on_contact_removed)

        debug_node = BulletDebugNode('Debug')
        debug_node.showWireframe(True)
        debug_node.showConstraints(True)
        debug_node.showBoundingBoxes(False)
        debug_node.showNormals(False)

        self.debug_nodepath = render.attachNewNode(debug_node)
        self.world.set_debug_node(debug_node)

        self.debug_nodepath.show()

    def _get_contacts(self, node):
        test = self.world.contact_test(node)
        contacts = []

        for contact in test.get_contacts():
            if contact.get_node0() == node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_a()
                normal = None

            elif contact.get_node1() == node:
                manifold = contact.get_manifold_point()

                position = manifold.get_position_world_on_b()
                normal = None

            else:
                continue

            impulse = manifold.get_applied_impulse()
            contact_ = CollisionContact(position, normal, impulse)
            contacts.append(contact_)

        return contacts

    def _on_contact_added(self, node_a, node_b):
        if node_a.has_python_tag("on_contact_added"):
            callback = node_a.get_python_tag("on_contact_added")

            contacts = self._get_contacts(node_a)
            callback(node_b, contacts)

        if node_b.has_python_tag("on_contact_added"):
            callback = node_b.get_python_tag("on_contact_added")

            contacts = self._get_contacts(node_b)
            callback(node_a, contacts)

    def _on_contact_removed(self, node_a, node_b):
        if node_a.has_python_tag("on_contact_removed"):
            callback = node_a.get_python_tag("on_contact_removed")
            callback(node_b)

        if node_b.has_python_tag("on_contact_removed"):
            callback = node_b.get_python_tag("on_contact_removed")
            callback(node_a)

    def _filter_collision(self, filter_data):
        filter_data.set_collide(True)

    @RegisterPhysicsNode.on_global
    def register_node(self, node):
        self.world.attachRigidBody(node)
        node.set_python_tag("world", self.world)

    @DeregisterPhysicsNode.on_global
    def deregister_node(self, node):
        self.world.removeRigidBody(node)
        node.clear_python_tag("world")

    def update(self, delta_time):
        self.world.doPhysics(delta_time)