第二个学习的例程,选了机器人的程序,因为感觉可能和实习比较相关一些。。
1.序列和并行
Sequences play intervals one after the other, effectively a “do in order” command.
序列在小行星例程中也碰到过
Parallels are a “do together,” playing all intervals at the same time.
mySequence = Sequence(myInterval1,…,myIntervaln, name="Sequence Name")
myParallel = Parallel(myInterval1,…,myIntervaln, name="Parallel Name")
2.姿态角
例程 :camera.setPosHpr(14.5, -15.4, 14, 45, -14, 0)
Pos指的是x,y,z三轴,Hpr指的是姿态角(绕x,y,z轴旋转的角度) (heading,pitch,roll)
3.self.setupLights()
顾名思义,开启灯光,实测了一下差距是挺大的
def setupLights(self):
ambientLight = AmbientLight("ambientLight")
ambientLight.setColor((.8, .8, .75, 1))
directionalLight = DirectionalLight("directionalLight")
directionalLight.setDirection(LVector3(0, 0, -2.5))
directionalLight.setColor((0.9, 0.8, 0.9, 1))
render.setLight(render.attachNewNode(ambientLight))
render.setLight(render.attachNewNode(directionalLight))
4.(疑问) camera 和 render
在小行星例程中,obj.reparentTo(camera), 当我将其改为obj.reparentTo(render)的时候似乎没有任何问题。
本例程中,将render改为camera就不行了。
我的理解下是render是静止的场景图和camera是相机,决定了所要看到的场景图的视角 (和main page上的hellowworld程序类似),但这样如何解释小行星例程中用camera也可以呢?
# Every object uses the plane model and is parented to the camera
# so that it faces the screen.
不是很懂
5. Actor演员类
这里我还没看到手册上关于Actor的详细介绍,但我觉得这个例程的备注已经非常清晰:
# Models that use skeletal animation are known as Actors instead of models
# Instead of just one file, the have one file for the main model, and an
# additional file for each playable animation.
# They are loaded using Actor.Actor instead of loader.LoadModel.
# The constructor takes the location of the main object as with a normal model
# and a dictionary (A fancy python structure that is like a lookup table)
# that contains names for animations, and paths to the appropriate
# files
self.robot1 = Actor.Actor('models/robot',
{'leftPunch': 'models/robot_left_punch',
'rightPunch': 'models/robot_right_punch',
'headUp': 'models/robot_head_up',
'headDown': 'models/robot_head_down'})
# Actors need to be positioned and parented like normal objects
self.robot1.setPosHprScale(-1, -2.5, 4, 45, 0, 0, 1.25, 1.25, 1.25)
self.robot1.reparentTo(render)
主页的介绍如下:
Loading each animation requires a tuple: the name one is giving the animation and the path to the animation. This entire process can be shortened to a single command:
nodePath = Actor('Model Path', {
'Animation Name 1':'Animation Path 1',
'Animation Name 2':'Animation Path 2',
})
6. Actor添加动作
# Now we define how the animated models will move. Animations are played
# through special intervals. In this case we use actor intervals in a
# sequence to play the part of the punch animation where the arm extends,
# call a function to check if the punch landed, and then play the part of the
# animation where the arm retracts
# Punch sequence for robot 1's left arm
self.robot1.punchLeft = Sequence(
# Interval for the outstreched animation
self.robot1.actorInterval('leftPunch', startFrame=1, endFrame=10),
# Function to check if the punch was successful
Func(self.checkPunch, 2),
# Interval for the retract animation
self.robot1.actorInterval('leftPunch', startFrame=11, endFrame=32))
# Now that we have defined the motion, we can define our key input.
# Each fist is bound to a key. When a key is pressed, self.tryPunch checks to
# make sure that the both robots have their heads down, and if they do it
# plays the given interval
self.accept('escape', sys.exit)
self.accept('a', self.tryPunch, [self.robot1.punchLeft])
self.accept('s', self.tryPunch, [self.robot1.punchRight])
self.accept('k', self.tryPunch, [self.robot2.punchLeft])
self.accept('l', self.tryPunch, [self.robot2.punchRight])
这两段分别定义了Actoer的动作和触发条件,也是本例程的核心内容。具体语法需要先去看一下主页手册的内容。
7. 动画控制
查询了手册之后,发现了这样几种控制方式:
首先对Actor的加载如5中不变:
第一种,不是例程中用到的,但更简单一些
actor.play('Animation Name')
actor.loop('Animation Name')
actor.stop()
参数即动作名称,三个函数的名称也很显然对应了其功能
actor.pose('Animation Name', FrameNumber)
这个函数pose的介绍是保持特定的一帧即第二个参数,有点像暂停的感觉?
actor.pose('Animation Name', 30)
actor.loop('Animation Name', restart = 0, fromFrame = 24, toFrame = 36)
也可以控制动画的具体播放帧
还有一个叫做AnimControl是一个可以控制某个动画的类。用法如下:很像例程中的方法了
myAnimControl=actor.getAnimControl('Animation Name') #get the AnimControl
myAnimControl.isPlaying() #returns a boolean whether the animation is playing or not
myAnimControl.getFrame() #returns the current frame number
myAnimControl #returns the speed of the animation, in frames per second
myAnimControl.getFullFframe() #returns a floating-point frame number exceeding the framecount. Not recommended.
myAnimControl.getFullFrame() #returns an integer frame number exceeding the framecount. Not recommended.
myAnimControl.getNextFrame() #returns the number of the next frame on the queue.
myAnimControl.getNumFrames() #returns the total number of frames
myAnimControl.getPlayRate() #returns the playrate. explained further below
myAnimControl.loop() #starts playing the animation in a loop
myAnimControl.play() #starts playing the animation
myAnimControl.pose(frame) #poses at frame frame
myAnimControl.setPlayRate(rate) #sets the playrate. explained further below
myAnimControl.stop() #stops the animation
第二种就是例程中用的,属于Intervals这一大块
我感觉是建立动画interval,然后作为Actor的属性可以被调用,使用下面的语句进行播放:
interval.start()
interval.start(startT, endT, playRate)
interval.loop()
interval.loop(startT, endT, playRate)
interval.finish()
interval.pause()
interval.resume()
还有一些常用的语法,都比较简单,详见手册就可以了
有一点似乎 例程中将Sequence圈起来的多个interval可以当作一个interval来start,似乎表明可以通过这种方式来组合动画