Here’s a 65 line interactive door program which I wrote to be fairly modular. Features include a dynamic collision box which moves with the door as it opens and closes on a button press, and an animated handle. Included with the code snippet is a detailed video tutorial explaining each line of the code, and also what the program looks like when run in a game window. I also show and explain the 3D modeling which went into making the door model itself.
Snippet below. Comments, improvements, and suggestions are welcome.
Tutorial:
https://youtu.be/5kMGXgbfzHk
# begin door setup
door_1 = self.loader.loadModel("models/new_door_1.gltf")
door_1_door = door_1.find("**/door")
door_1_jamb = door_1.find("**/jamb")
door_1_jamb.hide()
door_1_handle = door_1.find("**/handle")
h_hpr = door_1_handle.getHpr()
door_1.reparentTo(self.render)
door_1.setScale(1)
pine_tex = self.loader.loadTexture("tex/pine.png")
door_1_door.setTexture(pine_tex)
door_1.setPos(-20, 0, 0)
# get door jamb mesh
door_for_jamb = self.loader.loadModel("models/new_door_jamb.gltf")
door_for_jamb.setScale(door_1.getScale())
door_for_jamb.setPos(door_1.getPos())
door_for_jamb.reparentTo(self.render)
# collision geometry for the door
from panda3d.bullet import BulletBoxShape
from panda3d.bullet import BulletRigidBodyNode
door_box_1 = BulletBoxShape((0.26, 0.02, 0.5))
node = BulletRigidBodyNode('door_box_1')
node.addShape(door_box_1)
node.setFriction(0.8)
door_box_np = self.render.attachNewNode(node)
d_pos = door_1.getPos()
adjusted_d_pos = (d_pos[0] + 0.24, d_pos[1], d_pos[2] + 0.5)
door_box_np.setPos(adjusted_d_pos)
world.attachRigidBody(node)
door_box_hpr = door_box_np.getHpr()
def toggle_door():
if door_1.getHpr()[0] == 0:
# rotate the door outward
rotate = LerpHprInterval(door_1, 1, (-80, 0, 0))
coll_rotate = LerpPosHprInterval(door_box_np, 1, (-19.9, -0.2, 0.5), (-80, 0, 0))
handle_twitch = LerpHprInterval(door_1_handle, 0.1, (h_hpr[0], h_hpr[1] - 15, h_hpr[2]))
handle_untwitch = LerpHprInterval(door_1_handle, 0.2, h_hpr)
para = Parallel()
para.append(rotate)
para.append(coll_rotate)
para.append(handle_twitch)
seq = Sequence()
seq.append(para)
seq.append(handle_untwitch)
seq.start()
elif door_1.getHpr()[0] == -80:
# rotate the door inward
rotate = LerpHprInterval(door_1, 1, (0, 0, 0))
coll_rotate = LerpPosHprInterval(door_box_np, 1, adjusted_d_pos, door_box_hpr)
handle_twitch = LerpHprInterval(door_1_handle, 0.1, (h_hpr[0], h_hpr[1] - 15, h_hpr[2]))
handle_untwitch = LerpHprInterval(door_1_handle, 0.2, h_hpr)
para = Parallel()
para.append(coll_rotate)
para.append(rotate)
para.append(handle_twitch)
seq = Sequence()
seq.append(para)
seq.append(handle_untwitch)
seq.start()
op_d = DirectObject()
op_d.accept('e', toggle_door)