nodes/door.pyΒΆ
Part of Q1K3.
1"""Sliding door for Q1K3 port.
2
3Mirrors upstream `entity_door.js`. Door slides along its yaw axis when the
4player is nearby. Optionally locked behind a key pickup.
5"""
6
7from __future__ import annotations
8
9import math
10from typing import TYPE_CHECKING
11
12from simvx.core import Material, MeshInstance3D, Node3D, Vec3
13
14from . import meshes, textures
15from .mathutil import rotate_y
16
17if TYPE_CHECKING: # pragma: no cover
18 from .root import Q1K3Root
19
20
21class Door(Node3D):
22 SCALE = (96, 96, 16)
23 OPEN_DISTANCE = 96.0
24 PROXIMITY = 128.0
25 OPEN_HOLD_TIME = 3.0
26
27 def __init__(
28 self,
29 game: Q1K3Root,
30 pos: Vec3,
31 yaw_dir: int = 0,
32 needs_key: bool = False,
33 tex_id: int = textures.TEX_DOOR,
34 ) -> None:
35 super().__init__()
36 self.game = game
37 self.position = pos
38 # Doors live in both enemy and friendly collision lists, so they need
39 # `.p` and `.s` like any PhysicsBody (sphere collision check).
40 self.p = Vec3(pos.x, pos.y, pos.z)
41 self.s = Vec3(64, 64, 64)
42 self._yaw = yaw_dir * math.pi / 2
43 self._start_pos = Vec3(pos.x, pos.y, pos.z)
44 self._reset_state_at = 0.0
45 self._open = 0.0
46 self.needs_key = needs_key
47 self._dead = False
48
49 self._inst = MeshInstance3D(
50 mesh=meshes.cube(),
51 material=Material(
52 albedo_map=textures.get(tex_id),
53 roughness=0.6,
54 metallic=0.0,
55 ),
56 scale=type(self).SCALE,
57 )
58 self.add_child(self._inst)
59
60 def on_update(self, dt: float) -> None:
61 player = self.game.player
62 if player is None:
63 return
64
65 d = (self.position - player.p).length()
66 if d < type(self).PROXIMITY:
67 if self.needs_key and not self.game.has_key:
68 self.game.show_message("YOU NEED THE KEY...")
69 return
70 if self.needs_key and self.game.has_key:
71 self.needs_key = False
72 self._reset_state_at = self.game.game_time + type(self).OPEN_HOLD_TIME
73
74 if self._reset_state_at < self.game.game_time:
75 self._open = max(0.0, self._open - dt)
76 else:
77 self._open = min(1.0, self._open + dt)
78
79 offset_x = type(self).OPEN_DISTANCE * self._open
80 # Slide perpendicular to the door's yaw axis
81 slide = rotate_y(Vec3(offset_x, 0, 0), self._yaw)
82 self.position = self._start_pos + slide
83 self.p = Vec3(self.position.x, self.position.y, self.position.z)