Interactive Door on Keypress with Dynamic Physics and Animation

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)
3 Likes