-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtemplate.py
156 lines (139 loc) · 6.47 KB
/
template.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import direct.directbase.DirectStart #starts Panda
from pandac.PandaModules import * #basic Panda modules
from direct.showbase.DirectObject import DirectObject #for event handling
from direct.actor.Actor import Actor #for animated models
from direct.interval.IntervalGlobal import * #for compound intervals
from direct.task import Task #for update fuctions
import sys, math, random
class World(DirectObject): #subclassing here is necessary to accept events
def __init__(self):
#turn off default mouse control, otherwise can't reposition camera
base.disableMouse()
camera.setPosHpr(0, -15, 7, 0, -15, 0)
self.loadModels()
self.setupLights()
self.setupCollisions()
render.setShaderAuto() #turns on per-pixel lighting, normal mapping, etc (you probably want to use this)
self.keyMap = {"left":0, "right":0, "forward":0}
taskMgr.add(self.move, "moveTask")
self.prevtime = 0
self.ismoving = False
self.accept("escape", sys.exit)
self.accept("arrow_up", self.setKey, ["forward", 1])
self.accept("arrow_right", self.setKey, ["right", 1])
self.accept("arrow_left", self.setKey, ["left", 1])
self.accept("arrow_up-up", self.setKey, ["forward", 0])
self.accept("arrow_right-up", self.setKey, ["right", 0])
self.accept("arrow_left-up", self.setKey, ["left", 0])
#"mouse1" is left mouse button is clicked
#append "-up" for equivalent of for equivalent of KEYUP event
self.accept("ate-smiley", self.eat)
def setKey(self, key, value):
self.keyMap[key] = value
def loadModels(self):
"""loads initial models into the world."""
self.panda = Actor("models/panda-model", {"walk":"panda-walk4", "eat":"panda-eat"})
self.panda.reparentTo(render)
self.panda.setScale(0.005)
self.panda.setH(180)
self.env = loader.loadModel("models/environment")
self.env.reparentTo(render)
self.env.setScale(.25)
self.env.setPos(-8, 42, 0)
#load targets
self.targets = []
for i in range(10):
target = loader.loadModel("smiley")
target.setScale(.5)
target.setPos(random.uniform(-20, 20), random.uniform(-15, 15), 2)
target.reparentTo(render)
self.targets.append(target)
def setupLights(self):
#ambient light
self.ambientLight = AmbientLight("ambientLight") #parameter is a name
#four values, RGBA, Alpha is largely irrelevant, value [0,1]
self.ambientLight.setColor((.25, .25, .25, 1))
self.ambientLightNP = render.attachNewNode(self.ambientLight)
#the nodepath that calls setLight is what gets illuminated by the light
render.setLight(self.ambientLightNP)
#call clearLight() to turn it off
self.keyLight = DirectionalLight("keyLight")
self.keyLight.setColor((.6, .6, .6, 1))
self.keyLightNP = render.attachNewNode(self.keyLight)
self.keyLightNP.setHpr(0, -26, 0)
render.setLight(self.keyLightNP)
self.fillLight = DirectionalLight("fillLight")
self.fillLight.setColor((.3, .3, .3, 1))
self.fillLightNP = render.attachNewNode(self.fillLight)
self.fillLightNP.setHpr(30, 0, 0)
render.setLight(self.fillLightNP)
def walk(self):
"""compound interval for walking"""
#self.pandaWalk = self.panda.posInterval(1, (0, -5, 0))
#some interval methods:
#start(), loop(), pause(), resume(), finish()
#start() can take arguments: start(starttime, endtime, playrate)
dist = 5
angle = deg2Rad(self.panda.getH())
dx = dist * math.sin(angle)
dy = dist * -math.cos(angle)
pandaWalk = Parallel(self.panda.posInterval(1, (self.panda.getX()+dx, self.panda.getY()+dy, 0)), \
self.panda.actorInterval("walk", loop=1, duration=1))
pandaWalk.start()
def turn(self, direction):
pandaTurn = self.panda.hprInterval(.2, (self.panda.getH() - (10*direction), 0, 0))
pandaTurn.start()
def move(self, task):
elapsed = task.time - self.prevtime
camera.lookAt(self.panda)
if self.keyMap["left"]:
self.panda.setH(self.panda.getH() + elapsed*100)
if self.keyMap["right"]:
self.panda.setH(self.panda.getH() - elapsed*100)
if self.keyMap["forward"]:
dist = 15 * elapsed
angle = deg2Rad(self.panda.getH())
dx = dist * math.sin(angle)
dy = dist * -math.cos(angle)
self.panda.setPos(self.panda.getX()+dx, self.panda.getY()+dy, 0)
if self.keyMap["left"] or self.keyMap["right"] or self.keyMap["forward"]:
if self.ismoving == False:
self.ismoving = True
self.panda.loop("walk")
else:
if self.ismoving:
self.ismoving = False
self.panda.stop()
self.panda.pose("walk",4)
self.prevtime = task.time
return Task.cont
def setupCollisions(self):
#instantiates a collision traverser and sets it to the default
base.cTrav = CollisionTraverser()
self.cHandler = CollisionHandlerEvent()
#set pattern for event sent on collision
#"%in" is substituted with the name of the into object
self.cHandler.setInPattern("ate-%in")
cSphere = CollisionSphere((0,0,0), 500)#because the panda is scaled way down, radius has to be huge
cNode = CollisionNode("panda")
cNode.addSolid(cSphere)
cNode.setIntoCollideMask(BitMask32.allOff())#panda is *only* a from object
cNodePath = self.panda.attachNewNode(cNode)
#cNodePath.show()
#registers a from object with the traverser with a corresponding handler
base.cTrav.addCollider(cNodePath, self.cHandler)
for target in self.targets:
cSphere = CollisionSphere((0,0,0), 2)
cNode = CollisionNode("smiley")
cNode.addSolid(cSphere)
cNodePath = target.attachNewNode(cNode)
#cNodePath.show()
def eat(self, cEntry):
"""handles panda eating a smiley"""
#remove target from list of targets
self.targets.remove(cEntry.getIntoNodePath().getParent())
#remove from scene graph
cEntry.getIntoNodePath().getParent().remove()
self.panda.play("eat")
w = World()
run()