class Power(NodePath, HUDElement): """Modified from drwr: https://discourse.panda3d.org/t/health-bars-using-directgui/2098/3""" def __init__(self, min_strike=0.05, max_strike=7): self.min_strike = min_strike self.max_strike = max_strike HUDElement.__init__(self) self.text_scale = 0.11 self.text_color = (1, 1, 1, 1) NodePath.__init__(self, 'powerbar') self.reparentTo(self.dummy_right) cmfg = CardMaker('fg') cmfg.setFrame(0, 1, -0.04, 0.04) self.fg = self.attachNewNode(cmfg.generate()) cmbg = CardMaker('bg') cmbg.setFrame(-1, 0, -0.04, 0.04) self.bg = self.attachNewNode(cmbg.generate()) self.bg.setPos(1, 0, 0) self.fg.setColor(1, 0, 0, 1) self.bg.setColor(0.5, 0.5, 0.5, 1) self.setScale(0.3) start_value = 2 self.text = OnscreenText( text=f"{start_value:.2f} m/s", pos=(0, 0), scale=self.text_scale, fg=self.text_color, align=TextNode.ACenter, mayChange=True, parent=self, ) self.text.setPos(0.5, -0.15) self.setPos(0, 0, -0.9) self.set(start_value) def init(self): self.show() def destroy(self): self.hide() del self.text del self def set(self, V0): self.text.setText(f"{V0:.2f} m/s") value = (V0 - self.min_strike) / (self.max_strike - self.min_strike) if value < 0: value = 0 if value > 1: value = 1 self.fg.setScale(value, 1, 1) self.bg.setScale(1.0 - value, 1, 1)
class Personagem(): def __init__(self, render): self.fram = DirectFrame(frameSize=(100,100,100,100), frameColor=(255,0,0,0), pos=(0.0,0,0)) #self.fram.setPos(-1,0) #render.attachNewNode (self.frame) def hp(self,base): self.hp = OnscreenText(text = "100", pos=(0,0,0), parent = base.aspect2d) #self.NewButton = DirectButton(frameColor = (0, 0, 0, 0), parent = base.aspect2d, text = ("Testing"), scale = 0.08, command = sys.exit) self.hp.setPos(-1.25, 0) #self.hp.setFrame(self.fram) def experiencia(self): pass
class ConsoleLog: def __init__(self, text, valid, archivable=True, auto_create=True): """ @param text: What did they type in the console? @type text: str @param valid: Did the command work? @type valid: bool @param archivable: Should the log be retrievable via arrow keys? @type archivable: bool @param auto_create: Should the text of the log be auto created? @type auto_create: bool """ self.text = text self.valid = valid self.log = None self.archivable = archivable if auto_create: self.create() if not valid and self.log is not None: self.log["fg"] = (1, 0, 0, 1) def create(self): self.log = OnscreenText(text=self.text, fg=(1, 1, 1, 1), pos=(-1.25, -.8), align=TextNode.ALeft) if not self.archivable: self.log["pos"] = (self.log["pos"][0] + 0.05, self.log["pos"][1]) self.log["fg"] = (.8, .8, .8, 1) if not self.valid: self.log["fg"] = (1, 0, 0, 1) if not self.archivable: self.log["fg"] = (.8, 0, 0, 1) def move_up(self): """ Move the OnscreenText up """ self.log.setPos(self.log.getPos()[0], self.log.getPos()[1] + 0.07) def destroy(self): self.log.destroy()
def load(args): """Sets up the GUI for the main menu. Arguments: This takes no arguments. """ global backFrame global menuFrame global pauseText global backButton font_digital = loader.loadFont('digital.egg') backFrame = DirectFrame() backFrame['frameColor'] = (0, 0, 0, .5) backFrame['frameSize'] = (2, -2, 2, -2) backFrame.setPos(0, 0, 0) menuFrame = DirectFrame() menuFrame.reparentTo(backFrame) menuFrame['frameColor'] = (1, 1, 1, .5) menuFrame['frameSize'] = (.5, -.5, .5, -.5) menuFrame.setPos(0, 0, 0) pauseText = OnscreenText() pauseText['text'] = ('PAUSED') pauseText['scale'] = (.1) pauseText['font'] = (font_digital) pauseText['fg'] = (1, 1, 1, 1) pauseText.setPos(0, .9) backButton = DirectButton() backButton.reparentTo(menuFrame) backButton['text'] = ('Back') backButton['text_scale'] = (.1) backButton['text_pos'] = (0, -0.03) backButton['frameVisibleScale'] = (2, 0.5, 0) backButton['frameColor'] = (1, 1, 1, 0) backButton['command'] = (messenger.send) backButton['extraArgs'] = ("switch_gui", [gui.menu.pause_options, gui.menu.pause]) backButton.setPos(0, 0, 0)
def test_onscreentext_text_pos(): text = OnscreenText(pos=(1, 2)) assert text['pos'] == (1, 2) assert text.pos == (1, 2) assert text.getPos() == (1, 2) assert text.text_pos == (1, 2) assert text.getTextPos() == (1, 2) assert text.get_pos() == (0, 0, 0) text.setTextPos(3, 4) assert text['pos'] == (3, 4) assert text.pos == (3, 4) assert text.getPos() == (3, 4) assert text.text_pos == (3, 4) assert text.getTextPos() == (3, 4) assert text.get_pos() == (0, 0, 0) text.text_pos = (7, 8) assert text['pos'] == (7, 8) assert text.pos == (7, 8) assert text.getPos() == (7, 8) assert text.text_pos == (7, 8) assert text.getTextPos() == (7, 8) assert text.get_pos() == (0, 0, 0) text.setPos(9, 10) assert text['pos'] == (9, 10) assert text.pos == (9, 10) assert text.getPos() == (9, 10) assert text.text_pos == (9, 10) assert text.getTextPos() == (9, 10) assert text.get_pos() == (0, 0, 0) text['pos'] = (11, 12) assert text['pos'] == (11, 12) assert text.pos == (11, 12) assert text.getPos() == (11, 12) assert text.text_pos == (11, 12) assert text.getTextPos() == (11, 12) assert text.get_pos() == (0, 0, 0)
class ScrollText(): def __init__(self, text='', align=TextNode.ALeft, scale=(1, 1), font=None, font_size=12, parent=None, frameColor=(0.33, 0.33, 0.33, .66), frameSize=(0, 0.5, -1.0, 0)): if parent is None: parent = aspect2d self.parent = parent self.frame = DirectScrolledFrame( parent=parent, frameColor=frameColor, state=DGG.DISABLED, frameSize=frameSize, relief=DGG.FLAT, scrollBarWidth=scale[0] * font_size, horizontalScroll_relief=DGG.FLAT, verticalScroll_relief=DGG.FLAT, ) self.text = OnscreenText(parent=self.frame.getCanvas(), text=text, align=align, scale=tuple(scale * font_size), font=font) bounds = self.text.getTightBounds() self.frame['canvasSize'] = [ 0, bounds[1][0] - bounds[0][0], -bounds[1][2] + bounds[0][2], 0 ] self.text.setPos(-bounds[0][0], -bounds[1][2]) self.frame.setPos(0, 0, 0) def destroy(self): self.frame.destroy() def reparent_to(self, parent): self.frame.reparent_to(parent)
class StageScreen(DirectObject.DirectObject): def __init__(self, callback = None): self.stageRoot = NodePath("stageSelectRoot") self.ps = PreviewStrip("../assets/stages" ,-0.7) self.ps.getStripNP().reparentTo(self.stageRoot) self.callback = callback # name of the stage will be displayed here self.text = OnscreenText("") self.text.reparentTo(self.stageRoot) self.text.setPos(0,self.ps.height - 0.4) self.preview_size = [-0.5, 0.5, -0.5, 0.5] self.generator = CardMaker("PreviewMaker") self.generator.setFrame(*self.preview_size) self.preview = self.stageRoot.attachNewNode(self.generator.generate()) self.preview.setPos(0,0, 0.4) # keys are read so that the first in the pair is from player 1 # and second from the player 2, so that they both can decide self.keys = readKeys() self.left = [self.keys[0][1], self.keys[1][2]] self.right = [self.keys[0][3], self.keys[1][3]] self.select = [self.keys[0][4], self.keys[1][4]] self.ready = OnscreenText("ready") self.ready.reparentTo(self.stageRoot) self.ready.setPos(0,self.ps.height) # will be shown when players selected the stage self.ready.hide() # we notify ourselves to enable the key input and update text # and preview self.updateText() self.updateImg() self.disableInput() def enableInput(self): self.accept( self.left[0], self.rotateLeft ) self.accept( self.left[1], self.rotateLeft ) self.accept( self.right[0], self.rotateRight ) self.accept( self.right[1], self.rotateRight ) self.accept( self.select[0], self.callback) self.accept( self.select[1], self.callback) def disableInput(self): for key in self.left + self.right + self.select: self.ignore(key) def getNp(self): return self.stageRoot def updateText(self): t = str(self.ps.current().getTexture().getFilename()) self.text["text"] = t.split(sep)[-2] def updateImg(self): self.preview.setTexture(self.ps.current().getTexture()) def rotateRight(self): self.ps.rotateRight() self.updateText() self.updateImg() def rotateLeft(self): self.ps.rotateLeft() self.updateText() self.updateImg() def hide(self): self.stageRoot.hide() def show(self): self.stageRoot.show() def getStage(self): # return path to stage acceptable by Match class t = str(self.ps.current().getTexture().getFilename()).rstrip("icon.jpg") return t + "stage"
class Game(ShowBase, Player, Walls): def __init__(self): ShowBase.__init__(self) Player.__init__(self) Walls.__init__(self) Road.__init__(self) self.all_car = [] self.carN = 1 self.car_y = [-6, -4, -2, 0, 2, 4, 6, 8, 10] self.car_x = [-25, 25] self.speed = [.1, .2, .3, .4] self.score = 0 self.highscore = 0 self.output = "Score: " + str(self.score) self.difficulty = .3 self.font = loader.loadFont('Fonts/SigmarOne-Regular.ttf') self.collision = False self.env = loader.loadModel("Models/env.egg.pz") self.env.reparentTo(self.render) self.env.setScale(30) self.traverser = CollisionTraverser('traverser') base.cTrav = self.traverser self.colEvent = CollisionHandlerEvent() self.traverser.addCollider(self.player_collision, self.colEvent) self.colEvent.addInPattern("into-%in") self.colEvent.addOutPattern("out-%in") for name in ["Twall", "Bwall", "Rwall", "Lwall"]: self.accept(f"into-{name}", self.Check) self.accept(f"out-{name}", self.Out) base.setBackgroundColor(.1, .1, .1) base.disableMouse() camera.setPosHpr(0, -35, 20, 0, -30, 0) taskMgr.add(self.Move, "move_player") taskMgr.add(self.car_check, "car_check") self.carSeq = Sequence(Func(self.MakeCar), Wait(self.difficulty)) self.carSeq.loop() self.text = OnscreenText(text=self.output, pos=(1, .9), scale=.1, mayChange=1, font=self.font, fg=(1, .5, 0, 1)) self.idle.play() self.pause(False) def Check(self, coll): if coll.getIntoNodePath().getName() == "Twall": self.wOn = False if coll.getIntoNodePath().getName() == "Rwall": self.dOn = False if coll.getIntoNodePath().getName() == "Bwall": self.sOn = False if coll.getIntoNodePath().getName() == "Lwall": self.aOn = False def Out(self, coll): if coll.getIntoNodePath().getName() == "Twall": self.wOn = True if coll.getIntoNodePath().getName() == "Rwall": self.dOn = True if coll.getIntoNodePath().getName() == "Bwall": self.sOn = True if coll.getIntoNodePath().getName() == "Lwall": self.aOn = True def MakeCar(self): shuffle(self.car_y) shuffle(self.car_x) shuffle(self.speed) self.all_car.append( Car(self.speed[0], self.car_x[0], self.car_y[0], str(self.carN))) self.carN += 1 def car_check(self, task): for car in self.all_car: if car.x < -25 or car.x > 25: self.all_car.remove(car) car.car.removeNode() taskMgr.remove('move_car' + car.car_num) self.score += 1 self.output = "Score: " + str(self.score) self.text.setText(self.output) if not (self.collision): self.accept(f"into-{car.name}", self.collide_car) return Task.cont def collide_car(self, coll): for car in self.all_car: if car.carNode != coll.getIntoNodePath(): car.car.removeNode() taskMgr.remove('move_car' + car.car_num) self.collision = True self.pause() def pause(self, coll=True): self.carSeq.pause() self.walk.stop() taskMgr.remove("move_player") if self.score > self.highscore: self.highscore = self.score self.text.setPos(10, 10) if coll: self.dead_text = OnscreenText( text= f"You Have Been Hit \n Score: {self.score} \n Highscore: {self.highscore} \n \n \n Press R to play again \n Press F to exit", pos=(0, .4), scale=.1, mayChange=1, fg=(.1, .7, .1, 1), font=self.font) else: self.dead_text = OnscreenText( text=f"Dodge the Cars! \n \n Press R to start", pos=(0, .4), scale=.1, mayChange=1, fg=(0, .6, 1, 1), font=self.font) self.accept("r", self.un_pause) self.accept("f", self.exit) def un_pause(self): for car in self.all_car: car.car.removeNode() for car in self.all_car: self.all_car.remove(car) taskMgr.remove("pause") taskMgr.add(self.Move, "move_player") self.carSeq.resume() self.ignore("r") self.ignore("f") self.score = 0 self.dead_text.remove_node() self.output = "Score: " + str(self.score) self.text.setText(self.output) self.text.setPos(1.1, .9) self.collision = False def exit(self): finalizeExit()
def addLine(self, text, color): # Whilst in a battle, we don't want to display update text. if base.localAvatarReachable(): place = base.cr.playGame.getPlace() if base.localAvatar.getBattleZone() or ( place and place.fsm.getCurrentState().getName() != 'walk'): self.queuedLines[text] = color return if len(self.lines) == self.MAX_LINES: oldestLine = self.lines[len(self.lines) - 1] ival = self.ivalDict.get(oldestLine, None) ival.finish() newLine = OnscreenText(parent=self, text=text, fg=color, shadow=(color[0] * self.SHADOW_MODIFIER, color[1] * self.SHADOW_MODIFIER, color[2] * self.SHADOW_MODIFIER, 1.0), mayChange=1, font=CIGlobals.getMinnieFont()) newLine.setPos(*self.LINE_MINIMUM_POS) initScale = (1.0, 1.0, 1.0) growScale = (1.15, 1.15, 1.15) """ LerpScaleInterval(newLine, 0.5, scale = initScale, blendType = 'easeIn', bakeInStart = 0), """ lineIval = Sequence( Func(self.alertSfx.play), LerpScaleInterval(newLine, 0.5, scale=initScale, startScale=(0.01, 0.01, 0.01), blendType='easeOut', bakeInStart=0), Wait(0.5), Wait(self.SHOW_DURATION), Parallel( LerpPosInterval(newLine, self.FADE_DURATION, pos=(0.0, 0.0, (self.LINE_Y_OFFSET * (self.MAX_LINES + 1.8))), blendType='easeIn', bakeInStart=0, other=self), LerpColorScaleInterval(newLine, self.FADE_DURATION - 0.5, (1.0, 1.0, 1.0, 0.01), blendType='easeIn')), Func(self.deleteLine, newLine)) self.lines.insert(0, newLine) self.ivalDict.update({newLine: lineIval}) for i in range(1, len(self.lines)): line = self.lines[i] if not line.isEmpty(): # Let's reposition this element. line.setPos( line.getX(), self.LINE_MINIMUM_POS[1] + (self.LINE_Y_OFFSET * i)) lineIval.start()
class GameTextBox(DirectObject, NodePath): '''游戏文本显示器类 Main displayer of current game text. 继承自Panda3D的DirectFram Attributes: currentText: A list that includes current game text (see sogal_text's recordedText) currentSpeaker: A string that represents the speaker textFont: The font of the text properties: Properties of the text box. ''' def __init__(self): ''' Constructor ''' self.currentText = [] self.currentSpeaker = "" self.newText = None self.textfont = None self.properties = copy.deepcopy(base.getStyle('textbox')) self._normal_speakerLabel = None self._normal_textLabel = None self._large_label = None self._frame = None self._textArrow = None self.__namescale = None NodePath.__init__(self, 'GameTextBox') self.reparentTo(aspect2d) self.reload() def presave(self): runtime_data.RuntimeData.current_text = [ self.currentText, self.currentSpeaker ] def reload(self): if runtime_data.RuntimeData.gameTextBox_properties: #this creates an reference self.properties = runtime_data.RuntimeData.gameTextBox_properties else: runtime_data.RuntimeData.gameTextBox_properties = self.properties self.applyStyle() if runtime_data.RuntimeData.current_text: if runtime_data.RuntimeData.current_text[0]: self.currentText = copy.copy( runtime_data.RuntimeData.current_text[0]) if self.currentTextLabel: self.currentTextLabel.loadRecordedText( runtime_data.RuntimeData.current_text[0]) if runtime_data.RuntimeData.current_text[1]: self.currentSpeaker = runtime_data.RuntimeData.current_text[1] if self._normal_speakerLabel: self._normal_speakerLabel.setText( runtime_data.RuntimeData.current_text[1]) def reloadTheme(self): self.properties = copy.deepcopy(base.getStyle('textbox')) runtime_data.RuntimeData.gameTextBox_properties = self.properties self.applyStyle() def showArrow(self): if self._textArrow: if self.currentTextLabel: ''' self._textArrow.setPos(self._frame.getWidth()/2-self.properties['arrow_rightspace'], 0, self.currentTextLabel.textNode.getLowerRight3d()[2]-0.03) ''' apos = self._frame.getRelativePoint( self.currentTextLabel, self.currentTextLabel.getEndPos()) apos = (self._frame.getWidth() / 2 - self.properties['arrow_rightspace'], 0, apos[2]) self._textArrow.setPos(apos) else: self._textArrow.setPos(0, 0, 0) self._textArrow.show() def hideArrow(self): if self._textArrow: self._textArrow.hide() def quickFinish(self): '''Finish the current text typer quickly ''' if self.currentTextLabel: self.currentTextLabel.quickFinish() def destroyElements(self): self.currentText = [] self.currentSpeaker = None self.newText = '' if self._textArrow: self._textArrow.removeNode() self._textArrow = None if self._normal_textLabel: self._normal_textLabel.destroy() self._normal_textLabel = None if self._normal_speakerLabel: self._normal_speakerLabel.destroy() self._normal_speakerLabel = None if self._frame: self._frame.destroy() self._frame = None if self._large_label: self._large_label.destroy() self._large_label = None def destroy(self, *args, **kwargs): if self.currentTextLabel: self.currentTextLabel.destroy if self._frame: self._frame.destroy() self._frame = None def clearText(self): '''make current text empty''' self.currentText = [] self.currentSpeaker = None self.newText = '' if self.currentTextLabel: self.currentTextLabel.clear() if self._currentStyle == GameTextBoxStyle.Normal and self._normal_speakerLabel: self._normal_speakerLabel.setText('') def pushText(self, text, speaker=None, continuous=False, text_speed=None, fadein=None, rate=1.0, read=False): '''添加文字 进行判断并改变文字 parameters: speaker: A string contains the speaker's name. (None means no speaker) read: see if the text is already read ''' if self.currentTextLabel and self.currentTextLabel.isWaiting(): self.currentTextLabel.quickFinish() #The text is necessary if not text: return text = text.rstrip('\n') text_speed = (text_speed or base.getStyle('textbox')['text_speed'] or runtime_data.game_settings['text_speed']) * rate if fadein is None: fadein = base.getStyle('textbox')['text_fadein_duration'] fadein_style = base.getStyle('textbox')['text_fadein_style'] if self._currentStyle == GameTextBoxStyle.Normal: if not continuous: self.currentTextLabel.clear() elif self._currentStyle == GameTextBoxStyle.Large: if not continuous and self.currentTextLabel.hasContent(): self.currentTextLabel.appendText( '\n') #Inserting an empty line if continuous: #When continuous, ignore the speaker speaker = None #self.currentSpeaker = '' else: self.currentSpeaker = speaker if self._currentStyle == GameTextBoxStyle.Normal: if not continuous: if speaker: self._normal_speakerLabel.setText( self.currentSpeaker) #TODO: use SogalText else: self._normal_speakerLabel.setText(' ') elif self._currentStyle == GameTextBoxStyle.Large: if speaker: self.currentTextLabel.appendText(self.currentSpeaker, custom=True, newLine=True, textScale=self.__namescale) self.newText = text #This is *very* useful safeprint(self.newText) if not read: self.currentTextLabel.appendText(self.newText, speed=text_speed, newLine=(not continuous), fadein=fadein, fadeinType=fadein_style) else: self.currentTextLabel.appendText(self.newText, speed=text_speed, newLine=(not continuous), fadein=fadein, fadeinType=fadein_style, custom=True, fg=self.properties['read_fg']) self.currentText = self.currentTextLabel.getCopiedText() #TODO: FADING TEXT AND TYPER AGAIN _currentStyle = None @property def currentStyle(self): '''Style of this box ''' return self._currentStyle @property def currentTextLabel(self): '''current text label ''' if self._currentStyle == GameTextBoxStyle.Normal: return self._normal_textLabel elif self._currentStyle == GameTextBoxStyle.Large: return self._large_label def applyStyle(self): '''套用风格 Apply style setting. override this to apply your own style ''' # 窝才想起来这是引用不是浅拷贝……所以构造函数中运行这个就能同步runtime_data了lol # if runtime_data.RuntimeData.gameTextBox_properties: # self.properties = runtime_data.RuntimeData.gameTextBox_properties # else: runtime_data.RuntimeData.gameTextBox_properties = self.properties self.destroyElements() if self.properties.has_key('style'): self.setTextBoxStyle(self.properties['style']) else: self.setTextBoxStyle('normal') st = self._currentStyle if st == GameTextBoxStyle.Normal: height = self.properties['normal_height'] width = self.properties['normal_width'] self._frame = DirectFrame( parent=self, frameSize=(-width / 2.0, width / 2.0, -height / 2.0, height / 2.0), frameColor=self.properties['background_color'], ) if self.currentSpeaker: speaker = self.currentSpeaker else: speaker = '' self._normal_speakerLabel = OnscreenText( parent=self._frame, text=speaker, font=base.textFont, fg=self.properties['foreground_color'], mayChange=True # @UndefinedVariable , align=TextNode.ALeft #@UndefinedVariable , scale=self.properties['normal_name_scale']) self._normal_textLabel = SogalText( parent=self._frame, font=base.textFont, fg=self.properties['foreground_color'], scale=self.properties['normal_text_scale'], shadow=(0.1, 0.1, 0.1, 0.5), pos=(-width / 2.0 + self.properties['normal_text_pos'][0], 0, height / 2.0 + self.properties['normal_text_pos'][1]), wordwrap=self.properties['normal_text_wrap']) self.setPos(self.properties['normal_pos'][0], 0, self.properties['normal_pos'][1]) self._normal_speakerLabel.setPos( -width / 2.0 + self.properties['normal_name_pos'][0], height / 2.0 + self.properties['normal_name_pos'][1]) self._normal_speakerLabel.setShadow((0.1, 0.1, 0.1, 0.5)) self._normal_textLabel.textMaker.setTabWidth(1.0) elif st == GameTextBoxStyle.Large: self.__namescale = self.properties[ 'large_name_scale'] / self.properties['large_text_scale'] height = self.properties['large_height'] width = self.properties['large_width'] self._frame = DirectFrame( parent=self, frameSize=(-width / 2.0, width / 2.0, -height / 2.0, height / 2.0), frameColor=self.properties['background_color'], ) self._large_label = SogalText( parent=self._frame, font=base.textFont, fg=self.properties['foreground_color'], scale=self.properties['large_text_scale'], shadow=(0.1, 0.1, 0.1, 0.5), pos=(-width / 2.0 + self.properties['large_text_pos'][0], 0, height / 2.0 + self.properties['large_text_pos'][1]), wordwrap=self.properties['large_text_wrap']) self.setPos(self.properties['large_pos'][0], 0, self.properties['large_pos'][1]) self._large_label.textMaker.setTabWidth(1.0) #generate an arrow after text arrow = loader.loadModel( 'models/text_arrow/text_arrow') # @UndefinedVariable arrow.reparentTo(self._frame) arrow.setColor(self.properties['arrow_color']) arrow.setScale(self.properties['arrow_scale']) width = 2.0 if self._currentStyle == GameTextBoxStyle.Normal: width = self.properties['normal_width'] elif self._currentStyle == GameTextBoxStyle.Large: width = self.properties['large_width'] self._textArrow = arrow self._textArrow.hide() def setTextBoxStyle(self, style): if style.strip() == 'normal': self._currentStyle = GameTextBoxStyle.Normal elif style.strip() == 'large': self._currentStyle = GameTextBoxStyle.Large else: safeprint('Unknown style: ' + str(style)) self.properties['style'] = style def paragraphSparator(self): #if self._currentStyle == GameTextBoxStyle.Large: self.clearText() def setTextBoxProperty(self, propname, value): runtime_data.RuntimeData.gameTextBox_properties[propname] = value def applyTextBoxProperties(self): self.applyStyle() def getIsWaitingForText(self): is_waiting = False if self.currentTextLabel: is_waiting = self.currentTextLabel.isWaiting() return is_waiting def getIsWaiting(self): '''Inherited from GameTextBoxBase Get whether the text typer is unfinished ''' return self.getIsWaitingForText()
class MyApp(ShowBase): """Test class for the all the uses cases for the EasingMgr class.""" def __init__(self): ShowBase.__init__(self) base.disableMouse() base.setBackgroundColor(.2, .2, .2) camera.setPos(0, 0, 45) camera.setHpr(0, -90, 0) self.curr_ease = [(easeClass[8], easeType[1]), (easeClass[8], easeType[1]), (easeClass[8], easeType[1])] self.curr_param = easeParam[2] self._labs = [] self.param_lab = OnscreenText(text=self.curr_param, pos=(-1.3, .9), scale=0.07, fg=(0.8, 0.8, 0.8, 1), align=TextNode.ALeft, mayChange=1) self.controls = OnscreenText(text='Controls: \n' + ' [p] Change paramter. \n' + ' [q, a, z] Change ease mode (x, y, z).\n' + ' [w, s, x] Change ease type (x,y, z).\n' + ' [spacebar] Start the transition.\n' + ' [esc] Quit.', pos=(-1.3, -.7), scale=0.055, fg=(0.8, 0.8, 0.8, 1), align=TextNode.ALeft) for i in range(3): row = [] row.append(OnscreenText(text=axis[i], pos=(-.9, .9 - (i*.1)), scale=0.07, fg=(0.8, 0.8, 0.8, 1), align=TextNode.ALeft, mayChange=1)) row.append(OnscreenText(text=self.curr_ease[i][0], pos=(-.8, .9 - (i*.1)), scale=0.07, fg=(0.8, 0.8, 0.8, 1), align=TextNode.ALeft, mayChange=1)) row.append(OnscreenText(text=self.curr_ease[i][1], pos=(-.6, .9 - (i*.1)), scale=0.07, fg=(0.8, 0.8, 0.8, 1), align=TextNode.ALeft, mayChange=1)) self._labs.append(row) self._node = None self._ease_values = {'position3D': [(-8.0, -3.0, 10.0), (15.0, 3.0, -20.0)], 'position2D': [(-.7, -.3), (.7, .3)], 'scale1D': [[.08], [.20]], 'scale3D': [(1.0, 1.0, 1.0), (4.0, 4.0, 4.0)]} self.end_time = 1.0 self.accept('escape', sys.exit, [0]) self.input_setup(True) self.__easingMgr = EasingMgr() self.__curr_tr = None self.__change_param(0) def input_setup(self, activate): if activate: self.accept('q-up', self.__change_class, extraArgs=[0, 1]) self.accept('a-up', self.__change_class, extraArgs=[1, 1]) self.accept('z-up', self.__change_class, extraArgs=[2, 1]) self.accept('w-up', self.__change_type, extraArgs=[0, 1]) self.accept('s-up', self.__change_type, extraArgs=[1, 1]) self.accept('x-up', self.__change_type, extraArgs=[2, 1]) self.accept('p-up', self.__change_param, extraArgs=[1]) self.accept('space-up', self.start_ease) self.accept('escape', sys.exit, [0]) else: self.ignoreAll() def start_ease(self): self.input_setup(False) self.__easingMgr.start_transition(self.__curr_tr) def check_finished(self): if not self.__curr_tr.is_updating: self.input_setup(True) def __change_class(self, row, incr): self.curr_ease[row] = (easeClass[ (easeClass.index(self.curr_ease[row][0]) + incr) % len(easeClass)], self.curr_ease[row][1]) self._labs[row][1].setText(self.curr_ease[row][0]) self.change_transition() def __change_type(self, row, incr): self.curr_ease[row] = (self.curr_ease[row][0], easeType[ (easeType.index(self.curr_ease[row][1]) + incr) % len(easeType)]) self._labs[row][2].setText(self.curr_ease[row][1]) self.change_transition() def __change_param(self, incr): self.curr_param = easeParam[ (easeParam.index(self.curr_param) + incr) % len(easeParam)] self.param_lab.setText(self.curr_param) self.release_nodes() if self.curr_param in ['position2D', 'scale1D']: self.load_text() if self.curr_param in ['position3D', 'scale3D']: self.load_sphere() if '1D' in self.curr_param: for i, row in enumerate(self._labs): if i < 1: for lab in row: lab.show() else: for lab in row: lab.hide() if '2D' in self.curr_param: for i, row in enumerate(self._labs): if i < 2: for lab in row: lab.show() else: for lab in row: lab.hide() if '3D' in self.curr_param: for i, row in enumerate(self._labs): for lab in row: lab.show() self.change_transition() def change_transition(self): if self.__curr_tr: self.__easingMgr.remove_transition(self.__curr_tr) values = self._ease_values[self.curr_param] self.__curr_tr = self.__easingMgr.add_transition(self._node, self.curr_param, self.curr_ease, self.end_time, values, self.check_finished) def load_text(self): self._node = OnscreenText(text='Fantastic text', pos=(self._ease_values['position2D'][0]), scale=self._ease_values['scale1D'][0][0]) def load_sphere(self): self._node = loader.loadModel("assets/planet_sphere") self._node.reparentTo(render) self._node.setScale(self._ease_values['scale3D'][0][0], self._ease_values['scale3D'][0][1], self._ease_values['scale3D'][0][2]) self._node.setPos(self._ease_values['position3D'][0][0], self._ease_values['position3D'][0][1], self._ease_values['position3D'][0][2]) self._node_tex = loader.loadTexture("assets/earth.jpg") self._node.setTexture(self._node_tex, 1) def release_nodes(self): if self._node: self._node.removeNode() self._node = None
class VirtualWorld(ShowBase): def __init__(self, scene_file, pedestrian_file, dir, mode): ShowBase.__init__(self) self.globalClock = ClockObject.getGlobalClock() self.globalClock.setMode(ClockObject.MSlave) self.directory = dir self.model = Model(dir) self.loadScene(scene_file) self.loadPedestrians(pedestrian_file) self.cam_label = OST("Top Down", pos=(0, 0.95), fg=(1, 1, 1, 1), scale=0.05, mayChange=True) self.time_label = OST("Time: 0.0", pos=(-1.3, 0.95), fg=(1, 1, 1, 1), scale=0.06, mayChange=True, align=TextNode.ALeft) self.accept("arrow_right", self.changeCamera, [1]) self.accept("arrow_left", self.changeCamera, [-1]) self.accept("escape", self.exit) self.accept("aspectRatioChanged", self.setAspectRatio) self.accept("window-event", self.windowChanged) #base.disableMouse() lens = OrthographicLens() lens.setFilmSize(1550, 1000) self.display_region = base.win.makeDisplayRegion() self.default_camera = render.attachNewNode(Camera("top down")) self.default_camera.node().setLens(lens) self.default_camera.setPosHpr(Vec3(-75, 0, 2200), Vec3(0, -90, 0)) self.setCamera(0) self.controller = Controller(self, mode) self.taskMgr.add(self.updateCameraModules, "Update Camera Modules", 80) self.globalClock.setFrameTime(0.0) self.width = WIDTH self.height = HEIGHT props = WindowProperties() props.setTitle('Virtual Vision Simulator') base.win.requestProperties(props) def getModel(self): """ Returns the model that stores all of the cameras, pedestrians and static objects in the scene. """ return self.model def getController(self): """ Returns a controller that is used to control the world time. """ return self.controller def getTime(self): """ Returns the current time in the world. """ return self.globalClock.getFrameTime() def loadScene(self, scene_file): """ Loads the static objects that make up the scene. Also loads the lights that illuminate the scene and for performance implications, sets what lights affect what objects. """ if not os.path.exists(scene_file): logging.error("The path '%s' does not exist" % scene_file) sys.exit() light_builder = LightBuilder(self) object_builder = ObjectBuilder(self, self.directory) parser = SceneFileParser(self.model, object_builder, light_builder) parser.parse(scene_file) self.setUpLights() def setUpLights(self): # Set what lights illuminate what objects light_list = self.model.getLightList() static_objects = self.model.getObjectList() for object in static_objects: if object.hasLighting(): model_root = object.getModel().getChildren()[0] children = model_root.getChildren() for child in children: light_map = {} for index, light in enumerate(light_list): distance = Length(child.getPos(render), light.getPos()) half_fov = light.node().getLens().getFov()[0] / 2.0 height = light.getPos()[2] radius = height * tan(radians(half_fov)) if distance > radius**2 + 2500 + 10: continue if distance not in light_map: light_map[distance] = [index] else: light_map[distance].append(index) sorted_lights = sorted(light_map.keys()) light_count = 0 for key in sorted_lights: for i in light_map[key]: child.setLight(light_list[i]) light_count += 1 if light_count > LIGHTS_PER_OBJECT: break if light_count > LIGHTS_PER_OBJECT: break child.flattenStrong() # Apply a directional light to the static models light_list = self.model.getLightList(DIRECTIONALLIGHT) if light_list: for object in static_objects: if object.hasLighting(): model_root = object.getModel().getChildren()[0] model_root.setLight(light_list[0]) render.setShaderAuto() render.setAntialias(AntialiasAttrib.MLine) def loadPedestrians(self, pedestrian_file): """Loads the pedestrians into the scene.""" if not os.path.exists(pedestrian_file): logging.error("The path '%s' does not exist" % pedestrian_file) sys.exit() pedestrian_builder = PedestrianBuilder(self, "../media/characters/") parser = PedestrianFileParser(self.model, pedestrian_builder) parser.parse("../media/characters/pedestrians.xml") parser.parse(pedestrian_file) def addCamera(self, config): """ This method is used to add a new panda camera to the world. The panda camera is returned so that it can be linked with a camera module. """ type = config.type cam_builder = PandaCameraBuilder(self) if type == WIDE_FOV_CAMERA: pass else: camera = cam_builder.buildPandaPTZCamera(config) self.model.addCamera(camera) return camera def setAspectRatio(self): """ This method is called when the aspect ratio of the window changes. It updates the aspect ratios of all the cameras. """ width = base.win.getXSize() height = base.win.getYSize() ratio = self.camLens.getAspectRatio() camera_list = self.model.getCameraList() for camera in camera_list: camera.setAspectRatio(ratio) camera.setImageSize(width, height) self.default_camera.node().getLens().setAspectRatio(ratio) r = width / float(height) self.time_label.setPos(-r, 0.95) def changeCamera(self, num): """ This method is used to toggle the camera that is viewed in the main window. Typically num is either 1 or -1 denoting whether to toggle up or down the camera list. """ number = self.cur_camera + 1 + num num_cameras = len(self.model.getCameraList()) if number > num_cameras: number = 0 elif number < 0: number = num_cameras self.setCamera(number) def setCamera(self, num): """ This method sets which cameras view is shown in the panda3d window. """ if MANUAL_CAMERA: self.cur_camera = num - 1 return self.display_region.setClearColor(VBase4(0, 0, 0, 1)) self.display_region.setClearColorActive(True) self.display_region.setClearDepthActive(True) if num == 0: self.cur_camera = -1 self.display_region.setCamera(self.default_camera) self.cam_label.setText("Top Down") else: camera_list = self.model.getCameraList() index = num - 1 if index < len(camera_list): self.cur_camera = index camera = camera_list[index] camera_np = camera.getCameraNode() self.display_region.setCamera(camera_np) name = camera.getName() status_label = camera.getStatusLabel() label = "%s: %s" % (name, status_label) self.cam_label.setText(label) def step(self, increment): """ This method updates the world by one time step. """ if increment: new_time = self.globalClock.getFrameTime() + increment else: new_time = self.globalClock.getRealTime() self.globalClock.setFrameTime(new_time) self.time_label.setText("Time: %.2f" % new_time) self.updateActors() self.updateCameras() def updateActors(self): """ This method updates the pedestrians in the scene by calling their update functions. """ pedestrians = self.model.getPedestrianList() time = self.getTime() for pedestrian in pedestrians: if pedestrian.isActive(time): pedestrian.update(time) def updateCameras(self): """ This method updates the panda cameras which are used to provide the higher level camera modules with rendered images of the scene. There is one panda camera for each camera module. """ time = self.getTime() camera_list = self.model.getCameraList() for camera in camera_list: camera.update(time) if self.cur_camera != -1: cur_camera = camera_list[self.cur_camera] if cur_camera.statusChanged(): name = cur_camera.getName() status_label = cur_camera.getStatusLabel() label = "%s: %s" % (name, status_label) self.cam_label.setText(label) def updateCameraModules(self, task): """ This method updates the camera modules by calling their update function. This allows the camera modules to process messages and complete any tasks that were assigned to them. """ time = self.getTime() for camera in self.model.getCameraModules(): camera.update(time) return Task.cont def windowChanged(self, window): """ This function is called when the window is modified. It updates the image size used by the cameras when getting the rendered image from the texture. """ wp = window.getProperties() width = wp.getXSize() height = wp.getYSize() if width != self.width or height != self.height: self.width = width self.height = height camera_list = self.model.getCameraList() for camera in camera_list: camera.setImageSize(width, height) self.windowEvent(window) def exit(self): sys.exit()
class GameApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.viewDistanceChunks = 4 self.viewDistance = (self.viewDistanceChunks + 0.5) * CHUNK_SIDE self.visibleChunksXY = set() self.visibleChunks = {} self.chunksForLoader = {} # Disable the camera trackball controls. self.disableMouse() self.camAngleA = 0 self.camAngleB = 0 self.currChunkXY = (None, None) self.currChunk = None self.accept('arrow_left', self.evtArrowLeft) self.accept('arrow_left-repeat', self.evtArrowLeft) self.accept('arrow_right', self.evtArrowRight) self.accept('arrow_right-repeat', self.evtArrowRight) self.accept('arrow_up', self.evtArrowUp) self.accept('arrow_up-repeat', self.evtArrowUp) self.accept('arrow_down', self.evtArrowDown) self.accept('arrow_down-repeat', self.evtArrowDown) self.accept('w', self.evtForward) self.accept('w-repeat', self.evtForward) self.accept('s', self.evtBack) self.accept('s-repeat', self.evtBack) self.accept('i', self.render.analyze) self.dirtTexture = self.loader.loadTexture("textures/blocks/dirt.png") self.dirtTexture.setMagfilter(Texture.FTNearest) self.dirtTexture.setMinfilter(Texture.FTLinearMipmapLinear) self.waterTexture = self.loader.loadTexture( "textures/blocks/water.jpg") self.waterTexture.setMagfilter(Texture.FTNearest) self.waterTexture.setMinfilter(Texture.FTLinearMipmapLinear) self.xyzInfo = OnscreenText(text="text", align=TextNode.ALeft, parent=pixel2d, fg=(1, 1, 1, 1), bg=(0, 0, 0, 0.7)) self.xyzInfo.setScale(18, 20) self.xyzInfo.setPos(5, -20) #self.messenger.toggleVerbose() self.setFrameRateMeter(True) #self.chunkLoaderThread = threading.Thread(target=chunkLoader) #self.chunkLoaderThread.start() taskMgr.doMethodLater(0.01, self.refreshChunksTask, 'refreshChunksTask') taskMgr.setupTaskChain('chunkLoaderTaskChain', numThreads=1) bgColor = (0.3, 0.5, 1) self.setBackgroundColor(*bgColor) self.initFog(bgColor) self.camLens.setFar(self.viewDistance) self.setCamPos(CHUNK_SIDE / 2, CHUNK_SIDE / 2, 32) dlight = DirectionalLight('dlight') dlight.setColor(VBase4(0.8, 0.8, 0.5, 1)) dlnp = render.attachNewNode(dlight) dlnp.setHpr(-30, -60, 0) render.setLight(dlnp) alight = AmbientLight('alight') alight.setColor(VBase4(0.4, 0.4, 0.4, 1)) alnp = render.attachNewNode(alight) render.setLight(alnp) def initFog(self, color): self.fog = Fog("fog") self.fog.setColor(*color) self.fog.setLinearRange(self.viewDistance * 0.8, self.viewDistance) self.render.setFog(self.fog) @staticmethod def coordConvert(angA, angB, l): angA = radians(90 + angA) angB = radians(90 - angB) x = sin(angB) * cos(angA) * l y = sin(angB) * sin(angA) * l z = cos(angB) * l return x, y, z #----------Events-------------- def evtArrowLeft(self): self.camAngleA += 1 if self.camAngleA > 180: self.camAngleA = -179 self.camera.setH(self.camAngleA) def evtArrowRight(self): self.camAngleA -= 1 if self.camAngleA < -179: self.camAngleA = 180 self.camera.setH(self.camAngleA) def evtArrowUp(self): self.camAngleB += 1 if self.camAngleB > 90: self.camAngleB = 90 self.camera.setP(self.camAngleB) def evtArrowDown(self): self.camAngleB -= 1 if self.camAngleB < -90: self.camAngleB = -90 self.camera.setP(self.camAngleB) def evtForward(self): dx, dy, dz = self.coordConvert(self.camAngleA, self.camAngleB, 0.2) x, y, z = self.camera.getPos() self.setCamPos(x + dx, y + dy, z + dz) def evtBack(self): dx, dy, dz = self.coordConvert(self.camAngleA, self.camAngleB, -0.2) x, y, z = self.camera.getPos() self.setCamPos(x + dx, y + dy, z + dz) #------------------------------ def setCamPos(self, x, y, z): self.camera.setPos(x, y, z) chunkXY = (int(floor(x / CHUNK_SIDE)), int(floor(y / CHUNK_SIDE))) if chunkXY != self.currChunkXY: self.setCurrChunk(chunkXY) self.xyzInfo.setText("x=%2.2f\ny=%2.2f\nz=%2.2f" % (x, y, z)) def setCurrChunk(self, chunkXY): print chunkXY self.currChunkXY = chunkXY self.updateVisibleChunkSet() @staticmethod def loadChunk(chunkXY): return Chunk(chunkXY) def createVisibleChunkList(self): currChunkX, currChunkY = self.currChunkXY viewDistSquare = (self.viewDistanceChunks + 1)**2 #chunkList = filter( lambda xy : xy[0]**2 + xy[1]**2 <= viewDistSquare, # product(xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1), # xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1))) chunkList = product( xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1), xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1)) def maxXY(xy1, xy2): x1, y1 = xy1 x2, y2 = xy2 max1 = max(abs(x1), abs(y1)) max2 = max(abs(x2), abs(y2)) return cmp(max1, max2) chunkList = [(x + currChunkX, y + currChunkY) for x, y in sorted(chunkList, maxXY)] return chunkList def updateVisibleChunkSet(self): self.visibleChunksXY = self.createVisibleChunkList() self.chunkRefreshNeeded = True def refreshChunksTask(self, task): if not self.chunkRefreshNeeded: return task.again if taskMgr.hasTaskNamed('chunkLoaderTask'): return task.again self.chunkRefreshNeeded = False print "thinking..." chunksToUnload = {} oldVisibleChunks = self.visibleChunks self.visibleChunks = {} for xy, chunk in oldVisibleChunks.iteritems(): if isinstance(chunk, Chunk): if xy in self.visibleChunksXY: self.visibleChunks[xy] = chunk else: chunksToUnload[xy] = chunk chunk.hide() chunk.setFree(True) chunksToLoadXY = set() for xy in self.visibleChunksXY: if not self.visibleChunks.has_key(xy): chunk = self.chunksForLoader.get(xy, None) if isinstance(chunk, Chunk): chunk.show(self) self.visibleChunks[xy] = chunk del self.chunksForLoader[xy] else: if len(chunksToLoadXY) <= 2: chunksToLoadXY.add(xy) for xy, chunk in self.chunksForLoader.iteritems(): chunk.setFree(True) for xy, chunk in chunksToUnload.iteritems(): self.chunksForLoader[xy] = chunk for xy in chunksToLoadXY: self.chunksForLoader[xy] = True taskMgr.add(self.chunkLoaderTask, 'chunkLoaderTask', taskChain='chunkLoaderTaskChain') print "end of thinking" return task.again def chunkLoaderTask(self, task): print "loader Task" for xy, chunk in self.chunksForLoader.items(): if chunk == True: newChunk = Chunk(xy) self.chunksForLoader[xy] = newChunk self.chunkRefreshNeeded = True elif isinstance(chunk, Chunk) and chunk.getFree(): chunk.unload() del self.chunksForLoader[xy] else: print "chunkLoaderTask:unexpected chunk" print "loader Task end" return Task.done
class KubikiApp(ShowBase): def __init__(self): ShowBase.__init__(self) self.viewDistanceChunks = 4 self.viewDistance = (self.viewDistanceChunks + 0.5) * CHUNK_SIDE self.visibleChunksXY = set() self.visibleChunks = {} self.chunksForLoader = {} # Disable the camera trackball controls. self.disableMouse() self.camAngleA = 0 self.camAngleB = 0 self.currChunkXY = (None, None) self.currChunk = None self.accept('arrow_left', self.evtArrowLeft) self.accept('arrow_left-repeat', self.evtArrowLeft) self.accept('arrow_right', self.evtArrowRight) self.accept('arrow_right-repeat', self.evtArrowRight) self.accept('arrow_up', self.evtArrowUp) self.accept('arrow_up-repeat', self.evtArrowUp) self.accept('arrow_down', self.evtArrowDown) self.accept('arrow_down-repeat', self.evtArrowDown) self.accept('w', self.evtForward) self.accept('w-repeat', self.evtForward) self.accept('s', self.evtBack) self.accept('s-repeat', self.evtBack) self.accept('i', self.render.analyze) self.texture = self.loader.loadTexture("dirt.png") self.texture.setMagfilter(Texture.FTNearest) self.texture.setMinfilter(Texture.FTLinearMipmapLinear) self.xyzInfo = OnscreenText(text="text", align=TextNode.ALeft, parent=pixel2d, fg=(1, 1, 1, 1), bg=(0, 0, 0, 0.7)) self.xyzInfo.setScale(18, 20) self.xyzInfo.setPos(5, -20) #self.messenger.toggleVerbose() self.setFrameRateMeter(True) #self.chunkLoaderThread = threading.Thread(target=chunkLoader) #self.chunkLoaderThread.start() taskMgr.doMethodLater(0.01, self.refreshChunksTask, 'refreshChunksTask') taskMgr.setupTaskChain('chunkLoaderTaskChain', numThreads=1) bgColor = (0.3, 0.5, 1) self.setBackgroundColor(*bgColor) self.initFog(bgColor) self.camLens.setFar(self.viewDistance) self.setCamPos(CHUNK_SIDE / 2, CHUNK_SIDE / 2, 32) dlight = DirectionalLight('dlight') dlight.setColor(VBase4(0.8, 0.8, 0.5, 1)) dlnp = render.attachNewNode(dlight) dlnp.setHpr(-30, -60, 0) render.setLight(dlnp) alight = AmbientLight('alight') alight.setColor(VBase4(0.4, 0.4, 0.4, 1)) alnp = render.attachNewNode(alight) render.setLight(alnp) def initFog(self, color): self.fog = Fog("fog") self.fog.setColor(*color) self.fog.setLinearRange(self.viewDistance * 0.8, self.viewDistance) self.render.setFog(self.fog) @staticmethod def coordConvert(angA, angB, l): #Преобразование из системы коородинат Panda3d в координаты для формулы angA = radians(90 + angA) angB = radians(90 - angB) x = sin(angB) * cos(angA) * l y = sin(angB) * sin(angA) * l z = cos(angB) * l return x, y, z #----------Events-------------- def evtArrowLeft(self): self.camAngleA += 1 if self.camAngleA > 180: self.camAngleA = -179 self.camera.setH(self.camAngleA) def evtArrowRight(self): self.camAngleA -= 1 if self.camAngleA < -179: self.camAngleA = 180 self.camera.setH(self.camAngleA) def evtArrowUp(self): self.camAngleB += 1 if self.camAngleB > 90: self.camAngleB = 90 self.camera.setP(self.camAngleB) def evtArrowDown(self): self.camAngleB -= 1 if self.camAngleB < -90: self.camAngleB = -90 self.camera.setP(self.camAngleB) def evtForward(self): dx, dy, dz = self.coordConvert(self.camAngleA, self.camAngleB, 0.2) x, y, z = self.camera.getPos() self.setCamPos(x + dx, y + dy, z + dz) def evtBack(self): dx, dy, dz = self.coordConvert(self.camAngleA, self.camAngleB, -0.2) x, y, z = self.camera.getPos() self.setCamPos(x + dx, y + dy, z + dz) #------------------------------ def setCamPos(self, x, y, z): self.camera.setPos(x, y, z) chunkXY = (int(floor(x / CHUNK_SIDE)), int(floor(y / CHUNK_SIDE))) if chunkXY != self.currChunkXY: self.setCurrChunk(chunkXY) self.xyzInfo.setText("x=%2.2f\ny=%2.2f\nz=%2.2f" % (x, y, z)) def setCurrChunk(self, chunkXY): print chunkXY self.currChunkXY = chunkXY self.updateVisibleChunkSet() @staticmethod def loadChunk(chunkXY): return Chunk(chunkXY) def createVisibleChunkList(self): currChunkX, currChunkY = self.currChunkXY #Создаём список смещений чанков от текущего, и фильтруем его через функцию чтобы скруглить #слишком удалённые углы viewDistSquare = (self.viewDistanceChunks + 1)**2 #chunkList = filter( lambda xy : xy[0]**2 + xy[1]**2 <= viewDistSquare, # product(xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1), # xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1))) chunkList = product( xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1), xrange(-self.viewDistanceChunks, self.viewDistanceChunks + 1)) def maxXY(xy1, xy2): x1, y1 = xy1 x2, y2 = xy2 max1 = max(abs(x1), abs(y1)) max2 = max(abs(x2), abs(y2)) return cmp(max1, max2) chunkList = [(x + currChunkX, y + currChunkY) for x, y in sorted(chunkList, maxXY)] return chunkList def updateVisibleChunkSet(self): #Новый массив с видимыми чанками self.visibleChunksXY = self.createVisibleChunkList() self.chunkRefreshNeeded = True def refreshChunksTask(self, task): if not self.chunkRefreshNeeded: return task.again if taskMgr.hasTaskNamed('chunkLoaderTask'): return task.again self.chunkRefreshNeeded = False print "thinking..." chunksToUnload = {} oldVisibleChunks = self.visibleChunks self.visibleChunks = {} #Старые видимые чанки переносим в новые или готовим к выгрузке for xy, chunk in oldVisibleChunks.iteritems(): if isinstance(chunk, Chunk): if xy in self.visibleChunksXY: self.visibleChunks[xy] = chunk else: chunksToUnload[xy] = chunk chunk.hide() chunk.setFree(True) chunksToLoadXY = set() #Недостающие чанки получаем из загруженных или готовим задание на загрузку for xy in self.visibleChunksXY: if not self.visibleChunks.has_key(xy): chunk = self.chunksForLoader.get(xy, None) if isinstance(chunk, Chunk): chunk.show(self) self.visibleChunks[xy] = chunk del self.chunksForLoader[xy] else: if len(chunksToLoadXY) <= 2: chunksToLoadXY.add(xy) #Загруженные, но ненужные чанки - на выгрузку for xy, chunk in self.chunksForLoader.iteritems(): chunk.setFree(True) #Задание на выгрузку for xy, chunk in chunksToUnload.iteritems(): self.chunksForLoader[xy] = chunk #Задание на загрузку for xy in chunksToLoadXY: self.chunksForLoader[xy] = True #Запускаем задачу загрузки-выгрузки taskMgr.add(self.chunkLoaderTask, 'chunkLoaderTask', taskChain='chunkLoaderTaskChain') print "end of thinking" return task.again def chunkLoaderTask(self, task): """ Запускается при необходимости загрузить-выгрузить чанки. Выполняется в отдельном потоке """ print "loader Task" for xy, chunk in self.chunksForLoader.items(): if chunk == True: #Грузим новый чанк newChunk = Chunk(xy) self.chunksForLoader[xy] = newChunk self.chunkRefreshNeeded = True elif isinstance(chunk, Chunk) and chunk.getFree(): #Выгружаем ненужный чанк chunk.unload() del self.chunksForLoader[xy] else: print "chunkLoaderTask:unexpected chunk" print "loader Task end" return Task.done
class SkillShotScreen(GameScreen): awards = [ "QUICK FREEZE", "ADVANCE BONUS X", "5000 POINTS", "SPOT MTL", "QUICK FREEZE", "500,000 POINTS", "LIGHT CLAW" ] current_side = 1 current_award = 0 cube = None _awardText = None cubeMovement = None cubeRotation = None awardMovement = None SKILLSHOT_THRESHOLD = 2.34726002216 def __init__(self, screen_manager): super(SkillShotScreen, self).__init__(screen_manager, "skillshot_screen") # Load our trunk model self.cube = base.loader.loadModel("assets/models/powerup.egg") # Set its position to: # X: -0.4 (just to the left of h-center) # Y: 40 (way far back away from the viewer) # Z: 0 (vertically center) self.cube.setPos(11, 40, 0) # Set the scaling size of the trunk self.cube.setScale(0.05, 0.05, 0.05) if base.displayFlipped: self.cube.setAttrib( CullFaceAttrib.make(CullFaceAttrib.MCullCounterClockwise)) # Insert the trunk into this screen's rendering tree self.cube.reparentTo(self.node) """ # Set up a splotlight to project onto the trunk self.dlight = Spotlight('my dlight') # Associate the spotlight to the rendering system self.dlnp = render.attachNewNode(self.dlight) # Set this trunk's light explicitly so it only takes light from this light self.cube.setLight(self.dlnp) self.dlnp.lookAt(self.cube) plight = PointLight('plight') plight.setColor(VBase4(1, 1, 1, 1)) self.plnp = render.attachNewNode(plight) self.plnp.setPos(11, 35, 12) """ self.dlight = DirectionalLight('dlight') self.dlight.setColor(VBase4(1, 1, 1, 1)) self.dlnp = render.attachNewNode(self.dlight) self.dlnp.setHpr(0, -60, 0) self.dlnp.lookAt(self.cube) self.obj = DirectObject() self.movement_speed = 0.7 """ self.explosion = Sprite( parent=self.node, file_name="assets/sprites/explosion/explosion_", file_type="png", num_frames=29, int_padding=2, scale=(5,5,5)) """ self.explosion = Sprite( parent=self.node, file_name="assets/sprites/blue_explosion/blue_explosion_", file_type="png", num_frames=13, int_padding=2, scale=(5, 5, 5)) #0.6 - high #-0.4 - low self._awardText = OnscreenText( "RANDOM AWARD", 1, font=base.fontLoader.load('digital.ttf'), fg=((0.0 / 255.0), (255.0 / 255.0), (255.0 / 255.0), 1), pos=(1, -0.4), align=TextNode.ACenter, scale=.1, mayChange=True, parent=self.node2d) self.cubeRotation = self.cube.hprInterval(1.2, Vec3(360, 0, 0)) # Set up a sequence to perform the animation in, pause and out... "sequentially" self.cubeMovement = Sequence( # Lerp stands for "linearly interpolate", so we move from one position to the other with # an 'easeOut' blend so it comes to a nice slow stop at the end instead of an abrupt finish LerpPosInterval(self.cube, self.movement_speed, pos=(13, 40, 11), startPos=(13, 40, 0), blendType='easeOut'), # Animate back to our home position (off screen) with an ease in so it starts moving gradually LerpPosInterval(self.cube, self.movement_speed, pos=(13, 40, 0), blendType='easeIn')) self.awardMovement = Sequence( LerpFunc(self._updateAwardTextPosition, fromData=-0.4, toData=0.6, duration=self.movement_speed, blendType='easeOut', extraArgs=[], name=None), LerpFunc(self._updateAwardTextPosition, fromData=0.6, toData=-0.4, duration=self.movement_speed, blendType='easeIn', extraArgs=[], name=None)) def _updateAwardTextPosition(self, t): self._awardText.setPos(1, t) def show(self): """ Overridden method that is invoked when the screen is shown. We use this to orient our camera and spotlights to the appropriate place. We do this because not every screen has its own camera. I suppose we could do that in the future the same way that each screen has its own 2d and 3d nodes. """ # Set the camera a bit up in the air (vertically, not moving forward. Just straight up) base.camera.setZ(9.6) # Set the pitch negatively a bit so we can look down upon the trunk base.camera.setP(-5) # Call our base class show method now so it can render anything it wants super(SkillShotScreen, self).show() # Fire off the sequence self.cubeMovement.loop() self.cubeRotation.loop() self.awardMovement.loop() base.taskMgr.doMethodLater(0.1, self._advanceAward, 'award_advance') self.cube.setLight(self.dlnp) random.shuffle(self.awards) self.obj.ignoreAll() self.obj.acceptOnce("skillshot_hit", self.stop_skillshot_motion) self.cube.show() self._awardText.show() def stop_skillshot_motion(self): self.explosion = Sprite( parent=self.node, file_name="assets/sprites/blue_explosion/blue_explosion_", file_type="png", num_frames=13, int_padding=2, scale=(5, 5, 5)) self.cubeRotation.pause() self.cubeMovement.pause() self.awardMovement.pause() base.taskMgr.remove('award_advance') self.cube.hide() self._awardText.hide() self.explosion.setPos(self.cube.getX() - 0.50, 40, self.cube.getZ()) self.explosion.fps = 24 self.explosion.play(loops=1) # -0.3550 is the threshold if self.cube.getZ() <= self.SKILLSHOT_THRESHOLD: base.screenManager.showModalMessage( message=self.awards[self.current_award], time=5.0, font="eurostile.ttf", scale=0.08, bg=(0, 0, 0, 1), fg=(0, 1, 1, 1), frame_color=(0, 1, 1, 1), blink_speed=0.015, blink_color=(0, 0, 0, 1), #l r t b frame_margin=(0.1, 0.25, 0, 0), animation='slide', start_location=(1.7, 0, 0.8), end_location=(1, 0, 0.8)) def is_skillshot_hit(self): if self.cube.getZ() <= self.SKILLSHOT_THRESHOLD: return self.awards[self.current_award] else: return False def _advanceAward(self, task): self.current_award = (self.current_award + 1) % len(self.awards) self._awardText.setText(self.awards[self.current_award]) return task.again def hide(self): """ Called when the screen manager wants to remove this screen from the display. We have no choice but to obey when this method is called. So hide our background. Our models will be hidden automatically as the 3d nodes are removed from the render tree """ super(SkillShotScreen, self).hide() if self.cube != None: self.cube.clearLight(self.dlnp) if self.cubeMovement: self.cubeMovement.finish() if self.cubeRotation: self.cubeRotation.finish() if self.awardMovement: self.awardMovement.finish() base.taskMgr.remove('award_advance') if self._awardText != None: self._awardText.hide()
class GameTextBox(DirectObject, NodePath): '''游戏文本显示器类 Main displayer of current game text. 继承自Panda3D的DirectFram Attributes: currentText: A list that includes current game text (see sogal_text's recordedText) currentSpeaker: A string that represents the speaker textFont: The font of the text properties: Properties of the text box. ''' def __init__(self): ''' Constructor ''' self.currentText = [] self.currentSpeaker = "" self.newText = None self.textfont = None self.properties = copy.deepcopy(base.getStyle('textbox')) self._normal_speakerLabel = None self._normal_textLabel = None self._large_label = None self._frame = None self._textArrow = None self.__namescale = None NodePath.__init__(self, 'GameTextBox') self.reparentTo(aspect2d) self.reload() def presave(self): runtime_data.RuntimeData.current_text = [self.currentText, self.currentSpeaker] def reload(self): if runtime_data.RuntimeData.gameTextBox_properties: #this creates an reference self.properties = runtime_data.RuntimeData.gameTextBox_properties else: runtime_data.RuntimeData.gameTextBox_properties = self.properties self.applyStyle() if runtime_data.RuntimeData.current_text: if runtime_data.RuntimeData.current_text[0]: self.currentText = copy.copy(runtime_data.RuntimeData.current_text[0]) if self.currentTextLabel: self.currentTextLabel.loadRecordedText(runtime_data.RuntimeData.current_text[0]) if runtime_data.RuntimeData.current_text[1]: self.currentSpeaker = runtime_data.RuntimeData.current_text[1] if self._normal_speakerLabel: self._normal_speakerLabel.setText(runtime_data.RuntimeData.current_text[1]) def reloadTheme(self): self.properties = copy.deepcopy(base.getStyle('textbox')) runtime_data.RuntimeData.gameTextBox_properties = self.properties self.applyStyle() def showArrow(self): if self._textArrow: if self.currentTextLabel: ''' self._textArrow.setPos(self._frame.getWidth()/2-self.properties['arrow_rightspace'], 0, self.currentTextLabel.textNode.getLowerRight3d()[2]-0.03) ''' apos = self._frame.getRelativePoint(self.currentTextLabel, self.currentTextLabel.getEndPos()) apos = (self._frame.getWidth()/2-self.properties['arrow_rightspace'], 0, apos[2]) self._textArrow.setPos(apos) else: self._textArrow.setPos(0,0,0) self._textArrow.show() def hideArrow(self): if self._textArrow: self._textArrow.hide() def quickFinish(self): '''Finish the current text typer quickly ''' if self.currentTextLabel: self.currentTextLabel.quickFinish() def destroyElements(self): self.currentText = [] self.currentSpeaker = None self.newText = '' if self._textArrow: self._textArrow.removeNode() self._textArrow = None if self._normal_textLabel: self._normal_textLabel.destroy() self._normal_textLabel = None if self._normal_speakerLabel: self._normal_speakerLabel.destroy() self._normal_speakerLabel = None if self._frame: self._frame.destroy() self._frame = None if self._large_label: self._large_label.destroy() self._large_label = None def destroy(self, *args, **kwargs): if self.currentTextLabel: self.currentTextLabel.destroy if self._frame: self._frame.destroy() self._frame = None def clearText(self): '''make current text empty''' self.currentText = [] self.currentSpeaker = None self.newText = '' if self.currentTextLabel: self.currentTextLabel.clear() if self._currentStyle == GameTextBoxStyle.Normal and self._normal_speakerLabel: self._normal_speakerLabel.setText('') def pushText(self, text, speaker = None, continuous = False, text_speed = None, fadein = None, rate = 1.0,read = False): '''添加文字 进行判断并改变文字 parameters: speaker: A string contains the speaker's name. (None means no speaker) read: see if the text is already read ''' if self.currentTextLabel and self.currentTextLabel.isWaiting(): self.currentTextLabel.quickFinish() #The text is necessary if not text: return text = text.rstrip('\n') text_speed = (text_speed or base.getStyle('textbox')['text_speed'] or runtime_data.game_settings['text_speed']) * rate if fadein is None: fadein = base.getStyle('textbox')['text_fadein_duration'] fadein_style = base.getStyle('textbox')['text_fadein_style'] if self._currentStyle == GameTextBoxStyle.Normal: if not continuous: self.currentTextLabel.clear() elif self._currentStyle == GameTextBoxStyle.Large: if not continuous and self.currentTextLabel.hasContent(): self.currentTextLabel.appendText('\n') #Inserting an empty line if continuous: #When continuous, ignore the speaker speaker = None #self.currentSpeaker = '' else: self.currentSpeaker = speaker if self._currentStyle == GameTextBoxStyle.Normal: if not continuous: if speaker: self._normal_speakerLabel.setText(self.currentSpeaker) #TODO: use SogalText else: self._normal_speakerLabel.setText(' ') elif self._currentStyle == GameTextBoxStyle.Large: if speaker: self.currentTextLabel.appendText(self.currentSpeaker,custom = True, newLine = True, textScale = self.__namescale) self.newText = text #This is *very* useful safeprint(self.newText) if not read: self.currentTextLabel.appendText(self.newText, speed = text_speed , newLine = (not continuous) , fadein = fadein, fadeinType = fadein_style) else: self.currentTextLabel.appendText(self.newText, speed = text_speed , newLine = (not continuous) , fadein = fadein, fadeinType = fadein_style, custom = True, fg = self.properties['read_fg']) self.currentText = self.currentTextLabel.getCopiedText() #TODO: FADING TEXT AND TYPER AGAIN _currentStyle = None @property def currentStyle(self): '''Style of this box ''' return self._currentStyle @property def currentTextLabel(self): '''current text label ''' if self._currentStyle == GameTextBoxStyle.Normal: return self._normal_textLabel elif self._currentStyle == GameTextBoxStyle.Large: return self._large_label def applyStyle(self): '''套用风格 Apply style setting. override this to apply your own style ''' # 窝才想起来这是引用不是浅拷贝……所以构造函数中运行这个就能同步runtime_data了lol # if runtime_data.RuntimeData.gameTextBox_properties: # self.properties = runtime_data.RuntimeData.gameTextBox_properties # else: runtime_data.RuntimeData.gameTextBox_properties = self.properties self.destroyElements() if self.properties.has_key('style'): self.setTextBoxStyle(self.properties['style']) else: self.setTextBoxStyle('normal') st = self._currentStyle if st == GameTextBoxStyle.Normal: height = self.properties['normal_height'] width = self.properties['normal_width'] self._frame = DirectFrame( parent = self, frameSize = (-width/2.0,width/2.0,-height/2.0,height/2.0), frameColor = self.properties['background_color'], ) if self.currentSpeaker: speaker = self.currentSpeaker else: speaker = '' self._normal_speakerLabel = OnscreenText(parent = self._frame , text = speaker , font = base.textFont , fg = self.properties['foreground_color'] , mayChange = True # @UndefinedVariable , align = TextNode.ALeft#@UndefinedVariable , scale = self.properties['normal_name_scale'] ) self._normal_textLabel = SogalText(parent = self._frame, font = base.textFont, fg = self.properties['foreground_color'], scale = self.properties['normal_text_scale'], shadow = (0.1,0.1,0.1,0.5), pos = (-width/2.0 + self.properties['normal_text_pos'][0], 0, height/2.0 + self.properties['normal_text_pos'][1]), wordwrap = self.properties['normal_text_wrap'] ) self.setPos(self.properties['normal_pos'][0],0,self.properties['normal_pos'][1]) self._normal_speakerLabel.setPos(-width/2.0 + self.properties['normal_name_pos'][0], height/2.0 + self.properties['normal_name_pos'][1]) self._normal_speakerLabel.setShadow((0.1,0.1,0.1,0.5)) self._normal_textLabel.textMaker.setTabWidth(1.0) elif st == GameTextBoxStyle.Large: self.__namescale = self.properties['large_name_scale']/self.properties['large_text_scale'] height = self.properties['large_height'] width = self.properties['large_width'] self._frame = DirectFrame( parent = self, frameSize = (-width/2.0,width/2.0,-height/2.0,height/2.0), frameColor = self.properties['background_color'], ) self._large_label = SogalText(parent = self._frame, font = base.textFont, fg = self.properties['foreground_color'], scale = self.properties['large_text_scale'], shadow = (0.1,0.1,0.1,0.5), pos = (-width/2.0 + self.properties['large_text_pos'][0], 0, height/2.0 + self.properties['large_text_pos'][1]), wordwrap = self.properties['large_text_wrap'] ) self.setPos(self.properties['large_pos'][0],0,self.properties['large_pos'][1]) self._large_label.textMaker.setTabWidth(1.0) #generate an arrow after text arrow = loader.loadModel('models/text_arrow/text_arrow') # @UndefinedVariable arrow.reparentTo(self._frame) arrow.setColor(self.properties['arrow_color']) arrow.setScale(self.properties['arrow_scale']) width = 2.0 if self._currentStyle == GameTextBoxStyle.Normal: width = self.properties['normal_width'] elif self._currentStyle == GameTextBoxStyle.Large: width = self.properties['large_width'] self._textArrow = arrow self._textArrow.hide() def setTextBoxStyle(self, style): if style.strip() == 'normal': self._currentStyle = GameTextBoxStyle.Normal elif style.strip() == 'large': self._currentStyle = GameTextBoxStyle.Large else: safeprint('Unknown style: ' + str(style)) self.properties['style'] = style def paragraphSparator(self): #if self._currentStyle == GameTextBoxStyle.Large: self.clearText() def setTextBoxProperty(self, propname, value): runtime_data.RuntimeData.gameTextBox_properties[propname] = value def applyTextBoxProperties(self): self.applyStyle() def getIsWaitingForText(self): is_waiting = False if self.currentTextLabel: is_waiting = self.currentTextLabel.isWaiting() return is_waiting def getIsWaiting(self): '''Inherited from GameTextBoxBase Get whether the text typer is unfinished ''' return self.getIsWaitingForText()
def load(args): """Sets up the GUI for the in game pause menu. Arguments: args[0] -- The function for the 'resume' button. args[1] -- The function for the 'settings' button. args[2] -- The function for the 'exit' button. """ # GUI should do what they are told, they should get data sent to them, not request it. global pauseText global backFrame global menuFrame global resumeButton font_digital = loader.loadFont("digital.egg") backFrame = DirectFrame() backFrame["frameSize"] = (2, -2, 2, -2) backFrame.setPos(0, 0, 0) backFrame["frameColor"] = (0, 0, 0, 0.5) menuFrame = DirectFrame() menuFrame.reparentTo(backFrame) menuFrame["frameColor"] = (1, 1, 1, 0.5) menuFrame["frameSize"] = (0.5, -0.5, 0.5, -0.5) menuFrame.setPos(0, 0, 0) buttonClickSound = loader.loadSfx("sound/buttonClick.wav") buttonRollSound = loader.loadSfx("sound/buttonRoll.wav") resumeButton = DirectButton() resumeButton.reparentTo(menuFrame) resumeButton["text"] = "Resume" resumeButton["text_scale"] = 0.1 resumeButton["text_pos"] = (0, -0.03) resumeButton["frameVisibleScale"] = (2, 0.5, 0) resumeButton["frameColor"] = (1, 1, 1, 0) resumeButton["command"] = resume resumeButton["rolloverSound"] = buttonRollSound resumeButton["clickSound"] = buttonClickSound resumeButton.setPos(0, 0, 0.4) settingsButton = DirectButton() settingsButton.reparentTo(menuFrame) settingsButton["text"] = "Settings" settingsButton["text_scale"] = 0.1 settingsButton["text_pos"] = (0, -0.03) settingsButton["frameVisibleScale"] = (2, 0.5, 0) settingsButton["frameColor"] = (1, 1, 1, 0) settingsButton["rolloverSound"] = buttonRollSound settingsButton["clickSound"] = buttonClickSound settingsButton["command"] = messenger.send # Command to run settingsButton["extraArgs"] = ("switch_gui", [gui.menu.pause, gui.menu.pause_options]) # Args to send settingsButton.setPos(0, 0, 0.2) exitButton = DirectButton() exitButton.reparentTo(menuFrame) exitButton["text"] = "Exit" exitButton["text_scale"] = 0.1 exitButton["text_pos"] = (0, -0.03) exitButton["frameVisibleScale"] = (2, 0.5, 0) exitButton["frameColor"] = (1, 1, 1, 0) exitButton["rolloverSound"] = buttonRollSound exitButton["clickSound"] = buttonClickSound exitButton["command"] = exit exitButton.setPos(0, 0, 0) pauseText = OnscreenText() pauseText["text"] = "PAUSED" pauseText["scale"] = 0.1 pauseText["font"] = font_digital pauseText["fg"] = (1, 1, 1, 1) pauseText.setPos(0, 0.9)
class Window(): texture = None def __init__(self, title, scale, parent=None, child=None, transparent=False, owner=None): self.scale = scale self.owner = owner self.last_pos = None self.title_text = title self.title_color = (1, 1, 1, 1) self.title_pad = tuple(self.scale * 2) if parent is None: parent = aspect2d self.parent = parent if transparent: frameColor = (0, 0, 0, 0) else: frameColor = (0, 0, 0, 1) self.pad = 0 # if Window.texture is None: # Window.texture = loader.loadTexture('textures/futureui1.png') # image_scale = (scale[0] * Window.texture.get_x_size(), 1, scale[1] * Window.texture.get_y_size()) self.frame = DirectFrame( parent=parent, state=DGG.NORMAL, frameColor=frameColor ) #, image=self.texture, image_scale=image_scale) self.title_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.title = OnscreenText(text=self.title_text, style=Plain, fg=self.title_color, scale=tuple(self.scale * 14), parent=self.title_frame, pos=(0, 0), align=TextNode.ALeft, font=None, mayChange=True) bounds = self.title.getTightBounds() self.title_frame['frameSize'] = [ 0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, 0, bounds[1][2] - bounds[0][2] + self.title_pad[1] * 2 ] self.title.setPos(-bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.close_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.close = OnscreenText(text='X', style=Plain, fg=self.title_color, scale=tuple(self.scale * 14), parent=self.close_frame, pos=(0, 0), align=TextNode.ACenter, font=None, mayChange=True) bounds = self.close.getTightBounds() self.close_frame['frameSize'] = [ 0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, self.title_frame['frameSize'][2], self.title_frame['frameSize'][3] ] self.close.setPos(-bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.frame.setPos(0, 0, 0) self.title_frame.bind(DGG.B1PRESS, self.start_drag) self.title_frame.bind(DGG.B1RELEASE, self.stop_drag) self.close_frame.bind(DGG.B1PRESS, self.close_window) self.set_child(child) def set_child(self, child): if child is not None: self.child = child child.reparent_to(self.frame) self.update() def update(self): if self.child is not None: frame_size = self.child.frame['frameSize'] if frame_size is not None: frame_size[0] -= self.pad frame_size[1] += self.pad frame_size[2] += self.pad frame_size[3] -= self.pad self.frame['frameSize'] = frame_size if self.frame['frameSize'] is not None: width = self.frame['frameSize'][1] - self.frame['frameSize'][0] title_size = self.title_frame['frameSize'] title_size[0] = 0 title_size[1] = width self.title_frame['frameSize'] = title_size self.close_frame.setPos(width - self.close_frame['frameSize'][1], 0, 0) def start_drag(self, event): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() self.drag_start = self.frame.parent.get_relative_point( render2d, Point3(mpos.get_x(), 0, mpos.get_y())) - self.frame.getPos() taskMgr.add(self.drag, "drag", -1) def drag(self, task): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() current_pos = self.frame.parent.get_relative_point( render2d, Point3(mpos.get_x(), 0, mpos.get_y())) self.frame.set_pos(current_pos - self.drag_start) return task.again def close_window(self, event=None): if self.owner is not None: self.owner.window_closed(self) self.destroy() def stop_drag(self, event): taskMgr.remove("drag") self.last_pos = self.frame.getPos() def destroy(self): if self.frame is not None: self.frame.destroy() self.frame = None def getPos(self): return self.frame.getPos() def setPos(self, pos): self.frame.setPos(pos)
class VisualizerApp(ShowBase): FOV = 90 VIEW_DISTANCE_CHUNKS = 5 def __init__(self, level, chunks): ShowBase.__init__(self) self.level = level self.disableMouse() wp = WindowProperties() #wp.setFullscreen(True) wp.setCursorHidden(True) wp.setMouseMode(WindowProperties.M_relative) #wp.setSize(800, 500) self.win.requestProperties(wp) self.camLens.setFov(VisualizerApp.FOV) self.keyMap = { 'forward': 0, 'backward': 0, 'left': 0, 'right': 0, 'shift': 0 } self.setBackgroundColor(0.53, 0.80, 0.92, 1) self.accept('escape', sys.exit) self.accept("a", self.set_key, ["left", True]) self.accept("d", self.set_key, ["right", True]) self.accept("w", self.set_key, ["forward", True]) self.accept("s", self.set_key, ["backward", True]) self.accept('lshift', self.set_key, ['shift', True]) self.accept("a-up", self.set_key, ["left", False]) self.accept("d-up", self.set_key, ["right", False]) self.accept("w-up", self.set_key, ["forward", False]) self.accept("s-up", self.set_key, ["backward", False]) self.accept('lshift-up', self.set_key, ['shift', False]) self.cameraMovementTask = taskMgr.add(self.camera_movement, "CameraMovement") self.cameraRotationTask = taskMgr.add(self.camera_rotation, 'CameraRotation') self.position_text = OnscreenText(text="Position: \nChunk: ", align=TextNode.ALeft, parent=self.pixel2d, fg=(1, 1, 1, 1), bg=(0, 0, 0, 0.7)) self.position_text.setScale(18) self.position_text.setPos(5, -20) self.taskMgr.setupTaskChain('chunk_loader_chain', numThreads=6) self.create_lights() self.taskMgr.doMethodLater(0, self.load_chunks, 'Load Chunks', extraArgs=[chunks], appendTask=True) self.camera.setPos(-64 * 5, 54 * 5, 100) def create_lights(self): plight = PointLight('plight') plight.setColor((0.2, 0.2, 0.2, 1)) plight_node = self.render.attachNewNode(plight) plight_node.setPos(-64 * 25, 54 * 25, 126) self.render.setLight(plight_node) alight = AmbientLight('alight') alight.setColor((0.2, 0.2, 0.2, 1)) self.render.setLight(self.render.attachNewNode(alight)) def set_key(self, key, value): self.keyMap[key] = value def recenter_mouse(self): self.win.movePointer(0, int(self.win.getProperties().getXSize() / 2), int(self.win.getProperties().getYSize() / 2)) SENSITIVITY_MULTIPLIER = 20 def camera_rotation(self, task): mw = self.mouseWatcherNode has_mouse = mw.hasMouse() if has_mouse: dx, dy = mw.getMouseX(), mw.getMouseY() else: dx, dy = 0, 0 camera_h = self.camera.getH() + -dx * VisualizerApp.SENSITIVITY_MULTIPLIER camera_p = self.camera.getP() + dy * VisualizerApp.SENSITIVITY_MULTIPLIER self.camera.setH(camera_h) self.camera.setP(camera_p) self.recenter_mouse() return task.cont MOVE_SPEED = 3 MOVE_SPEED_MULTIPLIER = 10 def camera_movement(self, task): dt = globalClock.getDt() direction = self.render.getRelativeVector(self.camera, (0, 1, 0)) direction.normalize() position = self.camera.getPos() move_speed = VisualizerApp.MOVE_SPEED if self.keyMap['shift']: move_speed *= VisualizerApp.MOVE_SPEED_MULTIPLIER if self.keyMap['forward']: position += direction * dt * move_speed if self.keyMap['backward']: position += direction * dt * -move_speed self.camera.setPos(position) chunk_x = position.x // self.level.chunk_width chunk_z = position.y // self.level.chunk_depth self.position_text.text = 'Position: (x: %04d, y: %04d, z: %04d)\nChunk (x: %02d, z: %02d)' % (position.x, position.z, position.y, chunk_x, chunk_z) return task.cont def load_chunks(self, chunks, task): for chunk in chunks: self.taskMgr.doMethodLater(0, self.load_chunk, 'Load Chunk', extraArgs=[chunk], appendTask=True, taskChain='chunk_loader_chain') return task.done def load_chunk(self, chunk, task): voxel_real_size = Vec3(self.level.chunk_unit_width / self.level.chunk_width, self.level.chunk_unit_height / self.level.chunk_voxel_height, self.level.chunk_unit_depth / self.level.chunk_depth) chunk_size = Vec3(self.level.chunk_width, self.level.chunk_voxel_height, self.level.chunk_depth) chunk = VChunk(chunk_size, voxel_real_size, chunk) chunk.show(self) return task.done
class Window(): texture = None def __init__(self, title_text, scale, parent=None, child=None, transparent=False, owner=None): self.title_text = title_text self.scale = scale self.title_size = settings.ui_font_size self.owner = owner self.child = None self.last_pos = None self.title_color = (1, 1, 1, 1) self.title_pad = tuple(self.scale * 2) if parent is None: parent = aspect2d self.parent = parent if transparent: frameColor = (0, 0, 0, 0) else: frameColor = (0.5, 0.5, 0.5, 1) self.pad = 0 self.event_handler = DirectObject() self.button_thrower = base.buttonThrowers[0].node() self.event_handler.accept("wheel_up-up", self.mouse_wheel_event, extraArgs = [-1]) self.event_handler.accept("wheel_down-up", self.mouse_wheel_event, extraArgs = [1]) self.scrollers = [] # if Window.texture is None: # Window.texture = loader.loadTexture('textures/futureui1.png') # image_scale = (scale[0] * Window.texture.get_x_size(), 1, scale[1] * Window.texture.get_y_size()) self.frame = DirectFrame(parent=parent, state=DGG.NORMAL, frameColor=frameColor)#, image=self.texture, image_scale=image_scale) self.title_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.title = OnscreenText(text=self.title_text, style=Plain, fg=self.title_color, scale=tuple(self.scale * self.title_size), parent=self.title_frame, pos=(0, 0), align=TextNode.ALeft, font=None, mayChange=True) bounds = self.title.getTightBounds() self.title_frame['frameSize'] = [0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, 0, bounds[1][2] - bounds[0][2] + self.title_pad[1] * 2] self.title.setPos( -bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.close_frame = DirectFrame(parent=self.frame, state=DGG.NORMAL, frameColor=(.5, .5, .5, 1)) self.close = OnscreenText(text='X', style=Plain, fg=self.title_color, scale=tuple(self.scale * self.title_size), parent=self.close_frame, pos=(0, 0), align=TextNode.ACenter, font=None, mayChange=True) bounds = self.close.getTightBounds() self.close_frame['frameSize'] = [0, bounds[1][0] - bounds[0][0] + self.title_pad[0] * 2, self.title_frame['frameSize'][2], self.title_frame['frameSize'][3]] self.close.setPos( -bounds[0][0] + self.title_pad[0], -bounds[0][2] + self.title_pad[1]) self.frame.setPos(0, 0, 0) self.title_frame.bind(DGG.B1PRESS, self.start_drag) self.title_frame.bind(DGG.B1RELEASE, self.stop_drag) self.close_frame.bind(DGG.B1PRESS, self.close_window) self.set_child(child) def set_child(self, child): if child is not None: self.child = child child.reparent_to(self.frame) self.update() def update(self): if self.child is not None: frame_size = list(self.child.frame['frameSize']) if frame_size is not None: frame_size[0] -= self.pad frame_size[1] += self.pad frame_size[2] += self.pad frame_size[3] -= self.pad self.frame['frameSize'] = frame_size if self.frame['frameSize'] is not None: width = self.frame['frameSize'][1] - self.frame['frameSize'][0] title_size = self.title_frame['frameSize'] title_size[0] = 0 title_size[1] = width self.title_frame['frameSize'] = title_size self.close_frame.setPos(width - self.close_frame['frameSize'][1], 0, 0) def register_scroller(self, scroller): self.scrollers.append(scroller) def mouse_wheel_event(self, dir): # If the user is scrolling a scroll-bar, don't try to scroll the scrolled-frame too. region = base.mouseWatcherNode.getOverRegion() if region is not None: widget = base.render2d.find("**/*{0}".format(region.name)) if widget.is_empty() or isinstance(widget.node(), PGSliderBar) or isinstance(widget.getParent().node(), PGSliderBar): return # Get the mouse-position if not base.mouseWatcherNode.hasMouse(): return mouse_pos = base.mouseWatcherNode.getMouse() found_scroller = None # Determine whether any of the scrolled-frames are under the mouse-pointer for scroller in self.scrollers: bounds = scroller['frameSize'] pos = scroller.get_relative_point(base.render2d, Point3(mouse_pos.get_x() ,0, mouse_pos.get_y())) if pos.x > bounds[0] and pos.x < bounds[1] and \ pos.z > bounds[2] and pos.z < bounds[3]: found_scroller = scroller break if found_scroller is not None: if not found_scroller.verticalScroll.isHidden(): self.do_mouse_scroll(found_scroller.verticalScroll, dir, None) else: self.do_mouse_scroll(found_scroller.horizontalScroll, dir, None) def do_mouse_scroll(self, obj, dir, data): if isinstance(obj, DirectSlider) or isinstance(obj, DirectScrollBar): obj.setValue(obj.getValue() + dir * obj["pageSize"] * 0.1) def start_drag(self, event): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() self.drag_start = self.frame.parent.get_relative_point(render2d, Point3(mpos.get_x() ,0, mpos.get_y())) - self.frame.getPos() taskMgr.add(self.drag, "drag", -1) def drag(self, task): if base.mouseWatcherNode.has_mouse(): mpos = base.mouseWatcherNode.get_mouse() current_pos = self.frame.parent.get_relative_point(render2d, Point3(mpos.get_x() ,0, mpos.get_y())) self.frame.set_pos(current_pos - self.drag_start) return task.again def close_window(self, event=None): if self.owner is not None: self.owner.window_closed(self) self.destroy() def stop_drag(self, event): taskMgr.remove("drag") self.last_pos = self.frame.getPos() def destroy(self): if self.frame is not None: self.frame.destroy() self.frame = None self.scrollers = [] self.event_handler.ignore_all() def getPos(self): return self.frame.getPos() def setPos(self, pos): self.frame.setPos(pos)
class LabTask03(DirectObject): #define the state of the game and level gameState = 'INIT' gameLevel = 1 cameraState = 'STARTUP' count = 0 attempts = 3 posX = -200 posY = 20 posZ = 30 score = 0 contacts = 0 pause = False fire = True desiredCamPos = Vec3(-200,30,20) def __init__(self): self.imageObject = OnscreenImage(image = 'models/splashscreen.png', pos=(0,0,0), scale=(1.4,1,1)) preloader = Preloader() self.musicLoop = loader.loadSfx("music/loop/EndlessBliss.mp3") self.snowmansHit = loader.loadSfx("music/effects/snowball_hit.wav") self.candleThrow = loader.loadSfx("music/effects/snowball_throw.wav") self.presentHit = loader.loadSfx("music/effects/present_hit.wav") self.loseSound = loader.loadSfx("music/effects/Failure-WahWah.mp3") self.winSound = loader.loadSfx("music/effects/Ta Da-SoundBible.com-1884170640.mp3") self.nextLevelSound = loader.loadSfx("music/effects/button-17.wav") self.loseScreen = OnscreenImage(image = 'models/losescreen.png', pos=(0,0,0), scale=(1.4,1,1)) self.loseScreen.hide() self.winScreen = OnscreenImage(image = 'models/winscreen.png', pos=(0,0,0), scale=(1.4,1,1)) self.winScreen.hide() self.helpScreen = OnscreenImage(image = 'models/helpscreen.jpg', pos=(0,0,0.1), scale=(1,1,0.8)) self.helpScreen.hide() self.backBtn = DirectButton(text=("Back"), scale = 0.1, pos = (0,0,-0.8), command = self.doBack) self.retryBtn = DirectButton(text="Retry", scale = 0.1, pos = (0,0,0), command = self.doRetry) self.retryBtn.hide() self.menuBtn = DirectButton(text="Main Menu", scale = 0.1, pos = (0,0,0), command = self.doBack) self.menuBtn.hide() self.backBtn.hide() base.setBackgroundColor(0.1, 0.1, 0.8, 1) #base.setFrameRateMeter(True) # Position the camera base.cam.setPos(0, 30, 20) base.cam.lookAt(0, 30, 0) # Light alight = AmbientLight('ambientLight') alight.setColor(Vec4(0.5, 0.5, 0.5, 1)) alightNP = render.attachNewNode(alight) dlight = DirectionalLight('directionalLight') dlight.setDirection(Vec3(1, 1, -1)) dlight.setColor(Vec4(0.7, 0.7, 0.7, 1)) dlightNP = render.attachNewNode(dlight) render.clearLight() render.setLight(alightNP) render.setLight(dlightNP) # Input self.accept('escape', self.doExit) self.accept('r', self.doReset) self.accept('f1', self.toggleWireframe) self.accept('f2', self.toggleTexture) self.accept('f3', self.toggleDebug) self.accept('f5', self.doScreenshot) self.accept('f', self.doShoot, [True]) self.accept('p', self.doPause) inputState.watchWithModifiers('forward', 'w') inputState.watchWithModifiers('left', 'a') inputState.watchWithModifiers('reverse', 's') inputState.watchWithModifiers('right', 'd') inputState.watchWithModifiers('turnLeft', 'q') inputState.watchWithModifiers('turnRight', 'e') inputState.watchWithModifiers('moveLineUp', 'i') inputState.watchWithModifiers('moveLineDown','k') inputState.watchWithModifiers('moveLineRight','l') inputState.watchWithModifiers('moveLineLeft','j') self.font = loader.loadFont('models/SHOWG.TTF') self.font.setPixelsPerUnit(60) self.attemptText = OnscreenText(text='', pos = (0.9,0.8), scale = 0.07, font = self.font) self.levelText = OnscreenText(text='', pos=(-0.9,0.9), scale = 0.07, font = self.font ) self.scoreText = OnscreenText(text='', pos = (0.9,0.9), scale = 0.07, font = self.font) self.text = OnscreenText(text = '', pos = (0, 0), scale = 0.07, font = self.font) self.pauseText = OnscreenText(text='P: Pause', pos= (0.9,0.7), scale = 0.05, font = self.font) self.pauseText.hide() # Task taskMgr.add(self.update, 'updateWorld') # Physics self.setup() # _____HANDLER_____ def doRetry(self): self.loseScreen.hide() self.levelText.clearText() self.scoreText.clearText() self.attemptText.clearText() self.playGame() self.retryBtn.hide() self.cleanup() self.setup() def doExit(self): self.cleanup() sys.exit(1) def doReset(self): self.attempts = 3 self.cameraState = 'STARTUP' base.cam.setPos(0,30,20) self.arrow.removeNode() self.scoreText.clearText() self.levelText.clearText() self.attemptText.clearText() self.cleanup() self.setup() def toggleWireframe(self): base.toggleWireframe() def toggleTexture(self): base.toggleTexture() def toggleDebug(self): if self.debugNP.isHidden(): self.debugNP.show() else: self.debugNP.hide() def doScreenshot(self): base.screenshot('Bullet') def doShoot(self, ccd): if(self.fire and self.attempts > 0 and self.gameState == 'PLAY'): self.cameraState = 'LOOK' self.fire = False self.candleThrow.play() self.attempts -= 1 #get from/to points from mouse click ## pMouse = base.mouseWatcherNode.getMouse() ## pFrom = Point3() ## pTo = Point3() ## base.camLens.extrude(pMouse, pFrom, pTo) ## pFrom = render.getRelativePoint(base.cam, pFrom) ## pTo = render.getRelativePoint(base.cam, pTo) # calculate initial velocity v = self.pTo - self.pFrom ratio = v.length() / 40 v.normalize() v *= 70.0 * ratio torqueOffset = random.random() * 10 #create bullet shape = BulletSphereShape(0.5) shape01 = BulletSphereShape(0.5) shape02 = BulletSphereShape(0.5) shape03 = BulletSphereShape(0.5) body = BulletRigidBodyNode('Candle') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape, TransformState.makePos(Point3(0,0,0))) bodyNP.node().addShape(shape01, TransformState.makePos(Point3(0,0.5,-0.5))) bodyNP.node().addShape(shape02,TransformState.makePos(Point3(0,1,-1))) bodyNP.node().addShape(shape03,TransformState.makePos(Point3(0,1.5,-1.5))) bodyNP.node().setMass(100) bodyNP.node().setFriction(1.0) bodyNP.node().setLinearVelocity(v) bodyNP.node().applyTorque(v*torqueOffset) bodyNP.setPos(self.pFrom) bodyNP.setCollideMask(BitMask32.allOn()) visNP = loader.loadModel('models/projectile.X') visNP.setScale(0.7) visNP.clearModelNodes() visNP.reparentTo(bodyNP) #self.bird = bodyNP.node() if ccd: bodyNP.node().setCcdMotionThreshold(1e-7) bodyNP.node().setCcdSweptSphereRadius(0.5) self.world.attachRigidBody(bodyNP.node()) #remove the bullet again after 1 sec self.bullets = bodyNP taskMgr.doMethodLater(5, self.removeBullet, 'removeBullet', extraArgs=[bodyNP], appendTask = True) def removeBullet(self, bulletNP, task): self.cameraState = 'STAY' self.fire = True self.world.removeRigidBody(bulletNP.node()) bulletNP.removeNode() if(self.attempts <= 0 and len(self.snowmans)>0): self.gameState = 'LOSE' self.doContinue() return task.done # ____TASK___ def processInput(self, dt): force = Vec3(0, 0, 0) torque = Vec3(0, 0, 0) #print self.pTo.getY() if inputState.isSet('forward'): if(self.pTo.getZ() < 40): self.pTo.addZ(0.5) if inputState.isSet('reverse'): if(self.pTo.getZ() > 0 ): self.pTo.addZ(-0.5) if inputState.isSet('left'): if(self.pTo.getY() < 100): self.pTo.addY(0.5) self.arrow.setScale(self.arrow.getSx(),self.arrow.getSy()-0.006,self.arrow.getSz()) if inputState.isSet('right'): if(self.pTo.getY() > 60): self.pTo.addY(-0.5) self.arrow.setScale(self.arrow.getSx(),self.arrow.getSy()+0.006,self.arrow.getSz()) self.arrow.lookAt(self.pTo) def processContacts(self, dt): for box in self.boxes: for snowman in self.snowmans: result = self.world.contactTestPair(box, snowman.node()) if (result.getNumContacts() > 0): self.snowmansHit.play() self.score += 100 self.text.setPos(0,0.7) self.text.setText("HIT") self.snowmans.remove(snowman) self.world.removeRigidBody(snowman.node()) snowman.removeNode() if(len(self.snowmans) <= 0): self.gameState = "NEXT" self.text.setText('Nice! Press space to continue') for box in self.boxes: for present in self.presents: result01 = self.world.contactTestPair(box,present.node()) if(result01.getNumContacts() > 0): self.presents.remove(present) self.world.removeRigidBody(present.node()) present.removeNode() self.presentHit.play() self.score += 500 def doContinue(self): if(self.gameState == 'INIT'): self.gameState = 'MENU' self.text.clearText() self.musicLoop.setLoop(True) self.musicLoop.setVolume(0.5) self.musicLoop.play() self.startBtn = DirectButton(text=("Play"), scale = 0.1, pos = (0,0,0),command=self.playGame) self.helpBtn = DirectButton(text=("Help"), scale = 0.1, pos = (0,0,-0.2),command=self.help) self.exitBtn = DirectButton(text=("Exit"), scale = 0.1, pos = (0,0,-0.4), command = self.doExit) return if self.gameState == 'NEXT': self.nextLevelSound.play() self.fire = True self.gameLevel += 1 self.score += (self.attempts * 100) self.doReset() self.gameState = 'PLAY' return if self.gameState == 'LOSE': self.loseSound.play() self.arrow.removeNode() self.loseScreen.show() self.levelText.hide() self.attemptText.hide() self.scoreText.hide() self.text.hide() self.pauseText.hide() self.retryBtn.show() return if self.gameState == 'WIN': self.levelText.hide() self.attemptText.hide() self.scoreText.clearText() self.scoreText.setPos(0,0.6) self.scoreText.setText("%s"%self.score) self.winScreen.show() self.winSound.play() self.menuBtn.show() self.pauseText.hide() return def playGame(self): print "Play Game" self.attempts = 3 self.score = 0 self.gameLevel = 1 self.gameState = 'PLAY' self.musicLoop.setVolume(0.3) self.imageObject.hide() self.startBtn.hide() self.exitBtn.hide() self.helpBtn.hide() self.cleanup() self.setup() def doBack(self): self.gameState = 'MENU' self.scoreText.setPos(0.9,0.9) self.scoreText.hide() self.imageObject.show() self.startBtn.show() self.exitBtn.show() self.helpBtn.show() self.helpScreen.hide() self.backBtn.hide() self.menuBtn.hide() self.winScreen.hide() def help(self): self.gameState = 'HELP' self.startBtn.hide() self.exitBtn.hide() self.helpBtn.hide() self.backBtn.show() self.helpScreen.show() return def doPause(self): self.pause = not self.pause if(self.pause): self.text.setText("Pause") else: self.text.clearText() def update(self, task): dt = globalClock.getDt() if(not self.pause): if self.gameState == 'INIT': self.text.setPos(0,0) self.text.setText('Press space to continue') self.accept('space',self.doContinue) if self.gameState == 'PLAY': #print self.posZ #if(self.posX < -120): # self.posX += 0.03 # self.posZ -= 0.02 #elif(self.posZ < 70): # self.posZ += 0.02; #elif(self.posZ > 70 and self.posX > -120): # self.posZ -= 0.02 # self.posX -= 0.03 #base.cam.setPos(self.posX, self.posZ, self.posY) self.levelText.setText('Level: %s'%self.gameLevel) self.attemptText.setText('Tries Left: %s'%self.attempts) self.scoreText.setText('Score: %s'%self.score) self.pauseText.show() self.processContacts(dt) self.world.doPhysics(dt, 20, 1.0/180.0) #self.drawLines() self.processInput(dt) if self.cameraState == 'STARTUP': oldPos = base.cam.getPos() pos = (oldPos*0.9) + (self.desiredCamPos*0.1) base.cam.setPos(pos) base.cam.lookAt(0,30,0) elif self.cameraState == 'STAY': #oldPos = base.cam.getPos() #currPos = (oldPos*0.9) + (self.desiredCamPos*0.1) #base.cam.setPos(currPos) base.cam.lookAt(0,30,0) elif self.cameraState == 'LOOK': base.cam.lookAt(self.bullets) #base.cam.setPos(-200,self.bullets.getZ(),20) if self.gameState == 'NEXT': self.world.doPhysics(dt, 20, 1.0/180.0) ## self.raycast() return task.cont def raycast(self): # Raycast for closest hit tsFrom = TransformState.makePos(Point3(0,0,0)) tsTo = TransformState.makePos(Point3(10,0,0)) shape = BulletSphereShape(0.5) penetration = 1.0 result = self.world.sweepTestClosest(shape, tsFrom, tsTo, penetration) if result.hasHit(): torque = Vec3(10,0,0) force = Vec3(0,0,100) ## for hit in result.getHits(): ## hit.getNode().applyTorque(torque) ## hit.getNode().applyCentralForce(force) result.getNode().applyTorque(torque) result.getNode().applyCentralForce(force) ## print result.getClosestHitFraction() ## print result.getHitFraction(), \ ## result.getNode(), \ ## result.getHitPos(), \ ## result.getHitNormal() def cleanup(self): self.world = None self.worldNP.removeNode() self.arrow.removeNode() self.lines.reset() self.text.clearText() def setup(self): self.attemptText.show() self.levelText.show() self.scoreText.show() self.text.show() self.worldNP = render.attachNewNode('World') # World self.debugNP = self.worldNP.attachNewNode(BulletDebugNode('Debug')) self.debugNP.show() self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -9.81)) self.world.setDebugNode(self.debugNP.node()) #arrow self.scaleY = 10 self.arrow = loader.loadModel('models/arrow.X') self.arrow.setScale(0.5,0.5,0.5) self.arrow.setAlphaScale(0.5) #self.arrow.setTransparency(TransparencyAttrib.MAlpha) self.arrow.reparentTo(render) #SkyBox skybox = loader.loadModel('models/skybox.X') skybox.reparentTo(render) # Ground shape = BulletPlaneShape(Vec3(0, 0, 1), 0) np = self.worldNP.attachNewNode(BulletRigidBodyNode('Ground')) np.node().addShape(shape) np.setPos(0, 0, -1) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) visualNP = loader.loadModel('models/ground.X') visualNP.clearModelNodes() visualNP.reparentTo(np) #some boxes self.boxes = [] self.snowmans = [] self.platforms = [] self.presents = [] #TODO: Make a table #Table Top #self.createBox(Vec3(),Vec3()) if(self.gameLevel == 1): self.createBox(Vec3(5,7,1),Vec3(0,5,10),1.0) #2 legs self.createBox(Vec3(4,1,4),Vec3(0,11,5),1.0) self.createBox(Vec3(4,1,4),Vec3(0,-1,5),1.0) # Pigs self.createSnowman(2.0,Vec3(0, 5, 2.0),10.0) self.createSnowman(1.5, Vec3(0,-10,4.0),10.0) if(self.gameLevel == 2): #table01 self.createBox(Vec3(5,14,1),Vec3(0,-2,12),2.0) self.createBox(Vec3(5,7,1),Vec3(0,5,10),2.0) self.createBox(Vec3(4,1,4),Vec3(0,11,5),1.0) self.createBox(Vec3(4,1,4),Vec3(0,-1,5),1.0) #table02 self.createBox(Vec3(5,7,1),Vec3(0,-9,10),2.0) self.createBox(Vec3(4,1,4),Vec3(0,-3,5),1.0) self.createBox(Vec3(4,1,4),Vec3(0,-15,5),1.0) #table03 self.createBox(Vec3(1,1,1), Vec3(0,-1,14), 2.0) self.createBox(Vec3(1,1,1), Vec3(0,-3,14), 2.0) self.createBox(Vec3(1,1,1), Vec3(0,3,14), 2.0) self.createBox(Vec3(1,1,1), Vec3(0,-5,14), 2.0) self.createBox(Vec3(1,1,1), Vec3(0,5,14), 2.0) #pigs self.createSnowman(2.0,Vec3(0, 5, 2.0),10.0) self.createSnowman(2.0, Vec3(0,-9,2.0), 10.0) self.createSnowman(2.0,Vec3(0,-23,2.0),10.0) if(self.gameLevel == 3): #table01 self.createBox(Vec3(4,2,2),Vec3(0,12,12),1.0) self.createBox(Vec3(4,1,4),Vec3(0,11,5),1.0) self.createBox(Vec3(4,1,4),Vec3(0,13,5),1.0) #table02 self.createBox(Vec3(4,2,2),Vec3(0,-15,12),1.0) self.createBox(Vec3(4,1,4),Vec3(0,-14,5),1.0) self.createBox(Vec3(4,1,4),Vec3(0,-16,5),1.0) #table03 self.createBox(Vec3(4,10,1),Vec3(0,-1,12),1.0) self.createBox(Vec3(4,10,1),Vec3(0,-1,14),1.0) self.createBox(Vec3(4,2,4),Vec3(0,-2,5),0.1) #table04 self.createPlatform(Vec3(4,8,1),Vec3(0,7,16),1.0) self.createPlatform(Vec3(4,8,1),Vec3(0,-9,16),1.0) self.createBox(Vec3(4,1,3),Vec3(0,13,20),1.0) self.createBox(Vec3(4,1,3),Vec3(0,-16,20),1.0) #table05 self.createBox(Vec3(4,15,1),Vec3(0,-1,24),1.0) self.createStoneBox(Vec3(1,1,1),Vec3(0,2,20),5.0) self.createStoneBox(Vec3(1,1,1),Vec3(0,-2,20),5.0) self.createStoneBox(Vec3(1,1,1),Vec3(0,4,20),5.0) self.createStoneBox(Vec3(1,1,1),Vec3(0,8,20),5.0) self.createStoneBox(Vec3(1,1,1),Vec3(0,6,20),5.0) #pigs self.createSnowman(2.0,Vec3(0, 5, 2.0),10.0) self.createSnowman(2.0,Vec3(0,-8.5,2.0),10.0) self.createSnowman(1.5, Vec3(0,-9,19.5), 7.0) #presents self.createPresent(Vec3(2,2,2),Vec3(0,-20,5)) if(self.gameLevel == 4): #wall self.createStoneBox(Vec3(4,1.5,10), Vec3(0,20,10),20) #table01 self.createBox(Vec3(4,1,5), Vec3(0,7,7),1) self.createBox(Vec3(4,1,5), Vec3(0,0,7),1) self.createBox(Vec3(4,1,4), Vec3(0,3,7),1) self.createPlatform(Vec3(5,8,1), Vec3(0,4,13),1) self.createBox(Vec3(4,1,3), Vec3(0,11,18),1) self.createBox(Vec3(4,1,3), Vec3(0,-3,18),1) self.createBox(Vec3(4,8,1), Vec3(0,4,25),1) self.createStoneBox(Vec3(1,1,1), Vec3(0,4,27),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,7,27),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,2,27),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,2,29),2) #stairs self.createPlatform(Vec3(4,50,4), Vec3(0,-55,5),100) #table02 self.createBox(Vec3(4,1,5), Vec3(0,-13,15),1) self.createBox(Vec3(4,1,5), Vec3(0,-20,15),1) self.createBox(Vec3(4,1,4), Vec3(0,-17,15),1) self.createPlatform(Vec3(4,8,1), Vec3(0,-16,22),1) self.createBox(Vec3(4,1,3), Vec3(0,-9,28),1) self.createBox(Vec3(4,1,3), Vec3(0,-23,28),1) self.createBox(Vec3(4,8,1), Vec3(0,-16,33),1) self.createStoneBox(Vec3(1,1,1), Vec3(0,-16,35),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,-13,35),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,-18,35),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,-18,37),2) self.createStoneBox(Vec3(1,1,1), Vec3(0,-14,37),2) #snowman self.createSnowman(2.0,Vec3(0,30,5),1.0) self.createSnowman(1.5,Vec3(0,4,18),1.0) self.createSnowman(1.5,Vec3(0,-13,26),1.0) self.createSnowman(1.5,Vec3(0,-19,26),1.0) self.createSnowman(2.0,Vec3(0,12,5),1.0) self.createPresent(Vec3(2,2,2),Vec3(0,-25,13)) self.createPresent(Vec3(3,3,3),Vec3(0,-30,13)) self.createPresent(Vec3(4,4,4),Vec3(0,-36,13)) #self.createSnowman(1.5,Vec3(0,4,20),1.0) if(self.gameLevel == 5): #table01 self.createStoneBox(Vec3(4,7,3), Vec3(0,30,5),10.0) self.createStoneBox(Vec3(4,7,3), Vec3(0,-30,5),10.0) self.createBox(Vec3(4,1,3), Vec3(0,0,5), 1.0) self.createSnowman(1.5,Vec3(0,-6,5),1.0) self.createSnowman(1.5,Vec3(0,6,5),1.0) self.createBox(Vec3(4,1,3), Vec3(0,-12,5), 1.0) self.createBox(Vec3(4,1,3), Vec3(0,12,5), 1.0) self.createSnowman(1.5,Vec3(0,-18,5),1.0) self.createSnowman(1.5,Vec3(0,18,5),1.0) self.createStoneBox(Vec3(4,6,1),Vec3(0,-18,10), 0.1) self.createStoneBox(Vec3(4,6,1),Vec3(0,-6,10), 0.1) self.createStoneBox(Vec3(4,6,1),Vec3(0,6,10), 0.1) self.createStoneBox(Vec3(4,6,1),Vec3(0,18,10), 0.1) self.createStoneBox(Vec3(4,1,3),Vec3(0,23,14), 1.0) self.createStoneBox(Vec3(4,1,3),Vec3(0,-23,14), 1.0) self.createBox(Vec3(4,1,3),Vec3(0,18,14),1.0) self.createBox(Vec3(4,1,3),Vec3(0,-18,14),1.0) self.createStoneBox(Vec3(4,1,7),Vec3(0,13,20), 2.0) self.createStoneBox(Vec3(4,1,7),Vec3(0,-13,20), 2.0) self.createBox(Vec3(4,1,3),Vec3(0,8,14),1.0) self.createBox(Vec3(4,1,3),Vec3(0,-8,14),1.0) self.createStoneBox(Vec3(4,1,3),Vec3(0,3,14), 1.0) self.createStoneBox(Vec3(4,1,3),Vec3(0,-3,14), 1.0) self.createPlatform(Vec3(4,3.5,1),Vec3(0,-20 ,20), 1.0) self.createPlatform(Vec3(4,3.5,1),Vec3(0,20 ,20), 1.0) self.createPlatform(Vec3(4,3.5,1),Vec3(0,-5 ,20), 1.0) self.createPlatform(Vec3(4,3.5,1),Vec3(0,5 ,20), 1.0) self.createStoneBox(Vec3(4,1,3.5),Vec3(0,-18,25), 2.0) self.createStoneBox(Vec3(4,1,3.5),Vec3(0,18,25), 2.0) self.createStoneBox(Vec3(4,1,3.5),Vec3(0,-7.5,25), 2.0) self.createStoneBox(Vec3(4,1,3.5),Vec3(0,7.5,25), 2.0) self.createStoneBox(Vec3(4,6,1),Vec3(0,-12,30), 2.0) self.createStoneBox(Vec3(4,6,1),Vec3(0,12,30), 2.0) self.createBox(Vec3(4,1,5),Vec3(0,-5,30), 2.0) self.createBox(Vec3(4,1,5),Vec3(0,5,30), 2.0) self.createBox(Vec3(4,5,1),Vec3(0,0,40), 2.0) self.createPlatform(Vec3(4,2,0.5),Vec3(0,0,42), 2.0) self.createStoneBox(Vec3(4,0.5,2),Vec3(0,-3.5,45), 2.0) self.createStoneBox(Vec3(4,0.5,2),Vec3(0,3.5,45), 2.0) self.createStoneBox(Vec3(4,4,0.5),Vec3(0,0,48), 2.0) self.createPresent(Vec3(1.5,1.5,1.5),Vec3(0,22,30)) self.createPresent(Vec3(1.5,1.5,1.5),Vec3(0,-22,30)) self.createPresent(Vec3(2,2,1),Vec3(0,0,44)) self.createPresent(Vec3(3,3,4),Vec3(0,0,33)) if(self.gameLevel > 5): self.gameState = 'WIN' self.doContinue() return # drawing lines between the points ## self.lines = LineNodePath(parent = render, thickness = 3.0, colorVec = Vec4(1, 0, 0, 1)) ## self.pFrom = Point3(-4, 0, 0.5) ## self.pTo = Point3(4, 0, 0.5) # Aiming line self.lines = LineNodePath(parent = render, thickness = 3.0, colorVec = Vec4(1, 0, 0, 1)) self.pFrom = Point3(0, 100, 0.5) self.pTo = Point3(0, 60, 10) self.arrow.setPos(self.pFrom) def drawLines(self): # Draws lines for the ray. self.lines.reset() self.lines.drawLines([(self.pFrom,self.pTo)]) self.lines.create() def createBox(self,size,pos,mass): shape = BulletBoxShape(size) body = BulletRigidBodyNode('Obstacle') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape) bodyNP.node().setMass(mass) bodyNP.node().setFriction(1.0) bodyNP.node().setDeactivationEnabled(False) bodyNP.setPos(pos) bodyNP.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(bodyNP.node()) visNP = loader.loadModel('models/crate.X') visNP.setScale(size*2) visNP.clearModelNodes() visNP.reparentTo(bodyNP) self.boxes.append(body) def createStoneBox(self,size,pos,mass): shape = BulletBoxShape(size) body = BulletRigidBodyNode('Obstacle') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape) bodyNP.node().setMass(mass) bodyNP.node().setFriction(1.0) bodyNP.node().setDeactivationEnabled(False) bodyNP.setPos(pos) bodyNP.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(bodyNP.node()) visNP = loader.loadModel('models/stone.X') visNP.setScale(size*2) visNP.clearModelNodes() visNP.reparentTo(bodyNP) self.boxes.append(body) def createSnowman(self, size, pos, mass): shape = BulletBoxShape(Vec3(size,size,size)) shape01 = BulletSphereShape(size/2) body = BulletRigidBodyNode('Snowman') np = self.worldNP.attachNewNode(body) np.node().setMass(mass) np.node().addShape(shape, TransformState.makePos(Point3(0,0,-1))) np.node().addShape(shape01, TransformState.makePos(Point3(0,0,1))) np.node().setFriction(10.0) np.node().setDeactivationEnabled(False) np.setPos(pos) np.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(np.node()) visualNP = loader.loadModel('models/snowman.X') visualNP.setScale(size) visualNP.clearModelNodes() visualNP.reparentTo(np) self.snowmans.append(np) def createPlatform(self,size,pos,mass): shape = BulletBoxShape(size) body = BulletRigidBodyNode('Platform') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape) bodyNP.node().setMass(mass) bodyNP.node().setFriction(1.0) bodyNP.node().setDeactivationEnabled(False) bodyNP.setPos(pos) bodyNP.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(bodyNP.node()) visNP = loader.loadModel('models/crate.X') visNP.setScale(size*2) visNP.clearModelNodes() visNP.reparentTo(bodyNP) self.platforms.append(body) def createPresent(self,size,pos): shape = BulletBoxShape(size*0.7) body = BulletRigidBodyNode('Present') bodyNP = self.worldNP.attachNewNode(body) bodyNP.node().addShape(shape) bodyNP.node().setMass(1.0) bodyNP.node().setFriction(1.0) bodyNP.node().setDeactivationEnabled(False) bodyNP.setPos(pos) bodyNP.setCollideMask(BitMask32.allOn()) self.world.attachRigidBody(bodyNP.node()) visNP = loader.loadModel('models/present.X') visNP.setScale(size*2) visNP.clearModelNodes() visNP.reparentTo(bodyNP) self.presents.append(bodyNP)
class AsteroidsDemo(ShowBase): def __init__(self, p3d_proto=None, obs_pixel=0, act_disc=0): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) self.p3d_proto = p3d_proto self.obs_pixel = obs_pixel self.act_disc = act_disc globalClock.setFrameRate(30) # MNormal:0 MNoneRealTime:1 MForced:2 MLimited:5 #~ globalClock.setMode(0) globalClock.setMode(1) self.exitFunc = on_exit if SHOW_ARROW: self.ship_arrow = P3DCreateAxes(length=GUN_RANGE / SCREEN_X) self.ship_arrow1 = P3DCreateAxes(length=GUN_RANGE / SCREEN_X) #~ self.ship_arrow1 = P3DCreateAxes(length=AVOID_DIST/SCREEN_X) #~ self.ast_arrow = P3DCreateAxes(length=GUN_RANGE/SCREEN_X) #~ self.ast_arrow1 = P3DCreateAxes(length=AVOID_DIST/SCREEN_X) self.bullets_text = OnscreenText(text="bullets 100:100", parent=base.a2dBottomRight, scale=.1, align=TextNode.ALeft, pos=(-1.99, 1.8), fg=(0, 1, 0, 1), shadow=(0, 0, 0, 0.5)) self.life_text = OnscreenText(text="life 10:10", parent=base.a2dBottomRight, scale=.1, align=TextNode.ALeft, pos=(-1.99, 1.7), fg=(1, 0, 0, 1), shadow=(0, 0, 0, 0.5)) self.debug_text = OnscreenText(text="DBG --", parent=base.a2dBottomRight, scale=.1, align=TextNode.ALeft, pos=(-1.99, 1.9), fg=(1, 1, 0, 1), shadow=(0, 0, 0, 0.5)) self.text_agent1 = OnscreenText(text="A1", parent=base.a2dBottomRight, scale=.1, align=TextNode.ALeft, pos=(-1, 1), fg=(0, 1, 0, 1), shadow=(0, 0, 0, 0.5)) # Disable default mouse-based camera control. This is a method on the # ShowBase class from which we inherit. self.disableMouse() # Load the background starfield. self.setBackgroundColor((0, 0, 0, 1)) self.bg = loadObject("stars.jpg", scale=146, depth=200, transparency=False) # Load the ship and set its initial velocity. #~ self.ship = loadObject("ship.png", scale=2) #~ self.setVelocity(self.ship, LVector3.zero()) self.ship1 = Ship(self) self.ship2 = Ship(self) # A dictionary of what keys are currently being pressed # The key events update this list, and our task will query it as input self.keys = {"turnLeft": 0, "turnRight": 0, "accel": 0, "fire": 0} #~ self.accept("escape", sys.exit) # Escape quits self.accept("escape", on_exit) # Escape quits # Other keys events set the appropriate value in our key dictionary self.accept("a", self.setKey, ["turnLeft", 1]) self.accept("a-up", self.setKey, ["turnLeft", 0]) self.accept("d", self.setKey, ["turnRight", 1]) self.accept("d-up", self.setKey, ["turnRight", 0]) self.accept("w", self.setKey, ["accel", 1]) self.accept("w-up", self.setKey, ["accel", 0]) self.accept("arrow_left", self.setKey, ["turnLeft", 1]) self.accept("arrow_left-up", self.setKey, ["turnLeft", 0]) self.accept("arrow_right", self.setKey, ["turnRight", 1]) self.accept("arrow_right-up", self.setKey, ["turnRight", 0]) self.accept("arrow_up", self.setKey, ["accel", 1]) self.accept("arrow_up-up", self.setKey, ["accel", 0]) self.accept("space", self.setKey, ["fire", 1]) self.accept("space-up", self.setKey, ["fire", 0]) self.gameTask = taskMgr.add(self.gameLoop, "gameLoop") # Stores the time at which the next bullet may be fired. self.nextBullet = 0.0 # This list will stored fired bullets. self.bullets = [] self.reset_hud() # Complete initialization by spawning the asteroids. self.spawnAsteroids() def reset_hud(self): self.rounds = 0 self.count_win = 50 self.draws = [0] * self.count_win self.wins1 = [0] * self.count_win self.wins2 = [0] * self.count_win self.wins1s = 0 self.wins2s = 0 # As described earlier, this simply sets a key in the self.keys dictionary # to the given value. def setKey(self, key, val): self.keys[key] = val def setVelocity(self, obj, val): obj.setPythonTag("velocity", val) def getVelocity(self, obj): return obj.getPythonTag("velocity") def setExpires(self, obj, val): obj.setPythonTag("expires", val) def getExpires(self, obj): return obj.getPythonTag("expires") def setAttacker(self, obj, val): obj.setPythonTag("attacker", val) def getAttacker(self, obj): return obj.getPythonTag("attacker") def spawnAsteroids(self): # Control variable for if the ship is alive self.alive = True self.asteroids = [] # List that will contain our asteroids for i in range(AST_NUM): # This loads an asteroid. The texture chosen is random # from "asteroid1.png" to "asteroid3.png". asteroid = loadObject("asteroid%d.png" % (randint(1, 3)), scale=AST_INIT_SCALE) self.asteroids.append(asteroid) # This is kind of a hack, but it keeps the asteroids from spawning # near the player. It creates the list (-20, -19 ... -5, 5, 6, 7, # ... 20) and chooses a value from it. Since the player starts at 0 # and this list doesn't contain anything from -4 to 4, it won't be # close to the player. asteroid.setX( choice( tuple(range(-SCREEN_X, -5)) + tuple(range(5, SCREEN_X)))) # Same thing for Y asteroid.setZ( choice( tuple(range(-SCREEN_Y, -5)) + tuple(range(5, SCREEN_Y)))) # Heading is a random angle in radians heading = random() * 2 * pi # Converts the heading to a vector and multiplies it by speed to # get a velocity vector v = LVector3(sin(heading), 0, cos(heading)) * AST_INIT_VEL self.setVelocity(self.asteroids[i], v) # This is our main task function, which does all of the per-frame # processing. It takes in self like all functions in a class, and task, # the task object returned by taskMgr. def gameLoop(self, task): # Get the time elapsed since the next frame. We need this for our # distance and velocity calculations. dt = globalClock.getDt() if not self.alive: return Task.cont # Net Update Action action = self.net_update_action() a_turn = action.get('turn', 0) a_accel = action.get('accel', -1) a_fire = action.get('fire', -1) a_turn2 = action.get('turn2', 0) a_accel2 = action.get('accel2', -1) a_fire2 = action.get('fire2', -1) # Net Update End # Reset By Agent Begin if action.get('restart', False): self.resetGame(restart=1) return Task.cont # Reset End # update ship position self.ship1.updateShip(dt, a_turn, a_accel) if ONE_SHIP_ONLY: self.ship1.hide() self.ship_arrow.hide() self.text_agent1.hide() else: self.ship1.updateFire(task, a_fire) # AI vs Player Begin if DOG_FIGHT == 2: a_turn2 = self.keys["turnRight"] - self.keys["turnLeft"] a_accel2 = self.keys["accel"] a_fire2 = self.keys["fire"] # slower turn_rate for human turn_ra = TURN_RATE * 0.66 # AVP End else: turn_ra = TURN_RATE self.ship2.updateShip(dt, a_turn2, a_accel2, turn_ra=turn_ra) self.ship2.updateFire(task, a_fire2) # check crash to each other if DOG_FIGHT: self.ship1.checkCrash(self.ship2.ship) self.ship2.checkCrash(self.ship1.ship) # end # update asteroids for obj in self.asteroids: self.updatePos(obj, dt) # update bullets newBulletArray = [] for obj in self.bullets: self.updatePos(obj, dt) # Update the bullet # Bullets have an experation time (see definition of fire) if self.getExpires(obj) > task.time: newBulletArray.append(obj) else: obj.removeNode() # Otherwise, remove it from the scene. # Set the bullet array to be the newly updated array self.bullets = newBulletArray for bullet in self.bullets: # check ship1 vs ship2 if DOG_FIGHT: if self.ship1.checkHit(bullet): if self.ship1.alive: self.ship2.game_score += 10 else: self.ship2.game_score += 100 self.wins2s += self.ship2.alive elif self.ship2.checkHit(bullet): if self.ship2.alive: self.ship1.game_score += 10 else: self.ship1.game_score += 100 self.wins1s += self.ship1.alive # end for i in range(len(self.asteroids) - 1, -1, -1): asteroid = self.asteroids[i] if ((bullet.getPos() - asteroid.getPos()).lengthSquared() < (((bullet.getScale().getX() + asteroid.getScale().getX()) * .5)**2)): # Schedule the bullet for removal self.setExpires(bullet, 0) self.asteroidHit(i) # Handle the hit # Scoring Begin if self.getAttacker(bullet) == id(self.ship1): self.ship1.game_score += 10 else: self.ship2.game_score += 10 # Scoring End # DEBUG BEGIN wrn = self.count_win / 100. wr1 = sum(self.wins1) / wrn wr2 = sum(self.wins2) / wrn drr = sum(self.draws) / wrn self.debug_text.setText( "r%d: A1 %d:%d, wr%% %d:%d, dr %d%%, crash %d:%d" % (self.rounds, self.wins1s, self.wins2s, wr1, wr2, drr, self.ship1.crash, self.ship2.crash)) # DEBUG END # If the player has successfully destroyed all asteroids, respawn them if len(self.asteroids) == 0: self.spawnAsteroids() # Net Update State game_over = self.net_update_state(done=0) # Net Update End if game_over: # win rate begin self.wins1.append(self.ship1.alive) self.wins1.pop(0) self.wins2.append(self.ship2.alive) self.wins2.pop(0) self.draws.append(0 if self.ship1.alive + self.ship2.alive else 1) self.draws.pop(0) # win rate end self.resetGame() return Task.cont # Since every return is Task.cont, the task will # continue indefinitely # Net Update Begin def resetGame(self, wait=0, restart=0): self.alive = False for i in self.asteroids + self.bullets: i.removeNode() self.bullets = [] # Clear the bullet list self.rounds += 1 if restart: self.reset_hud() Sequence( Wait(wait), # Wait 2 seconds Func(self.ship1.reset, restart), # Show the ship Func(self.ship2.reset, restart), # Show the ship Func(self.spawnAsteroids)).start() # Remake asteroids def getFrame(self, render=0): """ 84x84 1 channel """ if render: self.graphicsEngine.renderFrame() dr = self.camNode.getDisplayRegion(0) img = dr.getScreenshot().getRamImageAs('G') img = np.array(img, dtype=np.uint8).reshape((WIN_H, WIN_W)) img = cv2.resize(img, (84, 84), interpolation=cv2.INTER_AREA) return img def net_update_state(self, done=0): """ 游戏状态, 输出到udp """ ship1_state, ship1_obs, ship1_score, ast_critical1 = self.ship1.getState( self.ship2.ship, self.asteroids, invincible=ONE_SHIP_ONLY) ship2_state, ship2_obs, ship2_score, ast_critical2 = self.ship2.getState( self.ship1.ship, self.asteroids, shuffle=SHUFFLE_AST) if done: game_done = 1 else: game_done = 0 if self.ship1.alive and self.ship2.alive else 1 # HUD Begin self.bullets_text.setText("bullets %d:%d [%d]" % (self.ship1.bullets_num, self.ship2.bullets_num, len(self.bullets))) self.life_text.setText("life %d:%d" % (self.ship1.life, self.ship2.life)) self.text_agent1.setPos(self.ship1.ship.getPos().getX() / 15 - 1, self.ship1.ship.getPos().getZ() / 15 + 1) if SHOW_ARROW: self.ship_arrow.setPos(self.ship1.ship.getPos() / 15) self.ship_arrow.setR(self.ship1.ship.getR() + np.rad2deg(ast_critical1.azimuth)) self.ship_arrow1.setPos(self.ship2.ship.getPos() / 15) self.ship_arrow1.setR(self.ship2.ship.getR() + np.rad2deg(ast_critical2.azimuth)) # HUD End obs_state = ( ship1_score, ship2_score, game_done, len(ship1_state), *ship1_state, len(ship1_obs), *ship1_obs, len(ship2_state), *ship2_state, len(ship2_obs), *ship2_obs, ) if self.p3d_proto: self.p3d_proto.set_game_state('{}f'.format(len(obs_state)), obs_state, game_done) return game_done def net_update_action(self): """ upd 获取的动作输入 """ action = {} if self.p3d_proto: action.update(self.p3d_proto.get_game_action()) return action # Net Update End # Updates the positions of objects def updatePos(self, obj, dt): vel = self.getVelocity(obj) newPos = obj.getPos() + (vel * dt) # Check if the object is out of bounds. If so, wrap it radius = .5 * obj.getScale().getX() if newPos.getX() - radius > SCREEN_X: newPos.setX(-SCREEN_X) elif newPos.getX() + radius < -SCREEN_X: newPos.setX(SCREEN_X) if newPos.getZ() - radius > SCREEN_Y: newPos.setZ(-SCREEN_Y) elif newPos.getZ() + radius < -SCREEN_Y: newPos.setZ(SCREEN_Y) obj.setPos(newPos) # The handler when an asteroid is hit by a bullet def asteroidHit(self, index): # If the asteroid is small it is simply removed if self.asteroids[index].getScale().getX() <= AST_MIN_SCALE: self.asteroids[index].removeNode() # Remove the asteroid from the list of asteroids. del self.asteroids[index] else: # If it is big enough, divide it up into little asteroids. # First we update the current asteroid. asteroid = self.asteroids[index] newScale = asteroid.getScale().getX() * AST_SIZE_SCALE asteroid.setScale(newScale) # Rescale it # The new direction is chosen as perpendicular to the old direction # This is determined using the cross product, which returns a # vector perpendicular to the two input vectors. By crossing # velocity with a vector that goes into the screen, we get a vector # that is orthagonal to the original velocity in the screen plane. vel = self.getVelocity(asteroid) speed = vel.length() * AST_VEL_SCALE vel.normalize() vel = LVector3(0, 1, 0).cross(vel) vel *= speed self.setVelocity(asteroid, vel) # Now we create a new asteroid identical to the current one newAst = loadObject(scale=newScale) self.setVelocity(newAst, vel * -1) newAst.setPos(asteroid.getPos()) newAst.setTexture(asteroid.getTexture(), 1) self.asteroids.append(newAst)
class CharGen(): def __init__(self): self.text = "CharGen" self.textObject = OnscreenText(text=self.text, pos=(0.95, -0.95), scale=0.07, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1) self.f = DirectFrame(frameColor=(1, 1, 1, 0.5), frameSize=(-1, 1, -0.4, 0.4)) self.f.setPos(-0.5, 0, -0.5) self.flavorText = OnscreenText("Primary Colour", pos=(0, 0, 0.4), scale=0.07, align=TextNode.ACenter, mayChange=1, fg=(1, 1, 1, 1)) self.flavorText.reparent_to(self.f) self.flavorText.setPos(0, 0.2) #slider R self.sR = DirectSlider(self.f, range=(0, 1), value=0, pageSize=3, command=self.setCol) self.sR.setScale(0.5, 0.5, 0.5) self.sR.setPos(0, 0, 0) self.sR.setColor(1, 0, 0) #slider G self.sG = DirectSlider(self.f, range=(0, 1), value=0, pageSize=3, command=self.setCol) self.sG.setScale(0.5, 0.5, 0.5) self.sG.setPos(0, 0, -0.1) self.sG.setColor(0, 1, 0) #slider B self.sB = DirectSlider(self.f, range=(0, 1), value=0, pageSize=3, command=self.setCol) self.sB.setScale(0.5, 0.5, 0.5) self.sB.setPos(0, 0, -0.2) self.sB.setColor(0, 0, 1) self.pandaActor = Actor("models/panda-model", {"walk": "models/panda-walk4"}) self.pandaActor.setScale(0.005, 0.005, 0.005) self.pandaActor.setPos(0.8, 12, -0.5) self.pandaActor.reparentTo(base.render) def setCol(self): #print(self.s['value']) self.pandaActor.setColor(self.sR['value'], self.sG['value'], self.sB['value'])
class VirtualWorld(ShowBase): def __init__(self, scene_file, pedestrian_file, dir, mode): ShowBase.__init__(self) self.globalClock = ClockObject.getGlobalClock() self.globalClock.setMode(ClockObject.MSlave) self.directory = dir self.model = Model(dir) self.loadScene(scene_file) self.loadPedestrians(pedestrian_file) self.cam_label = OST("Top Down", pos=(0, 0.95), fg=(1,1,1,1), scale=0.05, mayChange=True) self.time_label = OST("Time: 0.0", pos=(-1.3, 0.95), fg=(1,1,1,1), scale=0.06, mayChange=True, align=TextNode.ALeft) self.accept("arrow_right", self.changeCamera, [1]) self.accept("arrow_left", self.changeCamera, [-1]) self.accept("escape", self.exit) self.accept("aspectRatioChanged", self.setAspectRatio) self.accept("window-event", self.windowChanged) #base.disableMouse() lens = OrthographicLens() lens.setFilmSize(1550, 1000) self.display_region = base.win.makeDisplayRegion() self.default_camera = render.attachNewNode(Camera("top down")) self.default_camera.node().setLens(lens) self.default_camera.setPosHpr(Vec3( -75, 0, 2200), Vec3(0, -90, 0)) self.setCamera(0) self.controller = Controller(self, mode) self.taskMgr.add(self.updateCameraModules, "Update Camera Modules", 80) self.globalClock.setFrameTime(0.0) self.width = WIDTH self.height = HEIGHT props = WindowProperties( ) props.setTitle( 'Virtual Vision Simulator' ) base.win.requestProperties( props ) def getModel(self): """ Returns the model that stores all of the cameras, pedestrians and static objects in the scene. """ return self.model def getController(self): """ Returns a controller that is used to control the world time. """ return self.controller def getTime(self): """ Returns the current time in the world. """ return self.globalClock.getFrameTime() def loadScene(self, scene_file): """ Loads the static objects that make up the scene. Also loads the lights that illuminate the scene and for performance implications, sets what lights affect what objects. """ if not os.path.exists(scene_file): logging.error("The path '%s' does not exist" % scene_file) sys.exit() light_builder = LightBuilder(self) object_builder = ObjectBuilder(self, self.directory) parser = SceneFileParser(self.model, object_builder, light_builder) parser.parse(scene_file) self.setUpLights() def setUpLights(self): # Set what lights illuminate what objects light_list = self.model.getLightList() static_objects = self.model.getObjectList() for object in static_objects: if object.hasLighting(): model_root = object.getModel().getChildren()[0] children = model_root.getChildren() for child in children: light_map = {} for index, light in enumerate(light_list): distance = Length(child.getPos(render), light.getPos()) half_fov = light.node().getLens().getFov()[0] / 2.0 height = light.getPos()[2] radius = height * tan(radians(half_fov)) if distance > radius ** 2 + 2500 + 10: continue if distance not in light_map: light_map[distance] = [index] else: light_map[distance].append(index) sorted_lights = sorted(light_map.keys()) light_count = 0 for key in sorted_lights: for i in light_map[key]: child.setLight(light_list[i]) light_count += 1 if light_count > LIGHTS_PER_OBJECT: break if light_count > LIGHTS_PER_OBJECT: break child.flattenStrong() # Apply a directional light to the static models light_list = self.model.getLightList(DIRECTIONALLIGHT) if light_list: for object in static_objects: if object.hasLighting(): model_root = object.getModel().getChildren()[0] model_root.setLight(light_list[0]) render.setShaderAuto() render.setAntialias(AntialiasAttrib.MLine) def loadPedestrians(self, pedestrian_file): """Loads the pedestrians into the scene.""" if not os.path.exists(pedestrian_file): logging.error("The path '%s' does not exist" % pedestrian_file) sys.exit() pedestrian_builder = PedestrianBuilder(self, "../media/characters/") parser = PedestrianFileParser(self.model, pedestrian_builder) parser.parse("../media/characters/pedestrians.xml") parser.parse(pedestrian_file) def addCamera(self, config): """ This method is used to add a new panda camera to the world. The panda camera is returned so that it can be linked with a camera module. """ type = config.type cam_builder = PandaCameraBuilder(self) if type == WIDE_FOV_CAMERA: pass else: camera = cam_builder.buildPandaPTZCamera(config) self.model.addCamera(camera) return camera def setAspectRatio(self): """ This method is called when the aspect ratio of the window changes. It updates the aspect ratios of all the cameras. """ width = base.win.getXSize() height = base.win.getYSize() ratio = self.camLens.getAspectRatio() camera_list = self.model.getCameraList() for camera in camera_list: camera.setAspectRatio(ratio) camera.setImageSize(width, height) self.default_camera.node().getLens().setAspectRatio(ratio) r = width / float(height) self.time_label.setPos(-r, 0.95) def changeCamera(self, num): """ This method is used to toggle the camera that is viewed in the main window. Typically num is either 1 or -1 denoting whether to toggle up or down the camera list. """ number = self.cur_camera + 1 + num num_cameras = len(self.model.getCameraList()) if number > num_cameras: number = 0 elif number < 0: number = num_cameras self.setCamera(number) def setCamera(self, num): """ This method sets which cameras view is shown in the panda3d window. """ if MANUAL_CAMERA: self.cur_camera = num -1 return self.display_region.setClearColor(VBase4(0, 0, 0, 1)) self.display_region.setClearColorActive(True) self.display_region.setClearDepthActive(True) if num == 0: self.cur_camera = -1 self.display_region.setCamera(self.default_camera) self.cam_label.setText("Top Down") else: camera_list = self.model.getCameraList() index = num - 1 if index < len(camera_list): self.cur_camera = index camera = camera_list[index] camera_np = camera.getCameraNode() self.display_region.setCamera(camera_np) name = camera.getName() status_label = camera.getStatusLabel() label = "%s: %s" %(name, status_label) self.cam_label.setText(label) def step(self, increment): """ This method updates the world by one time step. """ if increment: new_time = self.globalClock.getFrameTime() + increment else: new_time = self.globalClock.getRealTime() self.globalClock.setFrameTime(new_time) self.time_label.setText("Time: %.2f" % new_time) self.updateActors() self.updateCameras() def updateActors(self): """ This method updates the pedestrians in the scene by calling their update functions. """ pedestrians = self.model.getPedestrianList() time = self.getTime() for pedestrian in pedestrians: if pedestrian.isActive(time): pedestrian.update(time) def updateCameras(self): """ This method updates the panda cameras which are used to provide the higher level camera modules with rendered images of the scene. There is one panda camera for each camera module. """ time = self.getTime() camera_list = self.model.getCameraList() for camera in camera_list: camera.update(time) if self.cur_camera != -1: cur_camera = camera_list[self.cur_camera] if cur_camera.statusChanged(): name = cur_camera.getName() status_label = cur_camera.getStatusLabel() label = "%s: %s" %(name, status_label) self.cam_label.setText(label) def updateCameraModules(self, task): """ This method updates the camera modules by calling their update function. This allows the camera modules to process messages and complete any tasks that were assigned to them. """ time = self.getTime() for camera in self.model.getCameraModules(): camera.update(time) return Task.cont def windowChanged(self, window): """ This function is called when the window is modified. It updates the image size used by the cameras when getting the rendered image from the texture. """ wp = window.getProperties() width = wp.getXSize() height = wp.getYSize() if width != self.width or height != self.height: self.width = width self.height = height camera_list = self.model.getCameraList() for camera in camera_list: camera.setImageSize(width, height) self.windowEvent(window) def exit(self): sys.exit()