1 module player;
2 
3 import liberty.engine;
4 
5 /**
6  * Example class for player.
7 **/
8 final class Player : SceneNode {
9   mixin NodeConstructor;
10 
11   private {
12     SceneNode tree;
13     Camera camera;
14     BSPCube[3] playerBody;
15     CubeMap skybox;
16 
17     float gravity = -80.0f;
18     float jumpPower = 20.0f;
19     float upSpeed = 0;
20     float moveSpeed = 5.0f;
21     bool onGround;
22     int killZ = -10;
23   }
24 
25   /**
26    * Optional.
27    * If declared, it is called after all objects instantiation.
28   **/
29   override void start() {
30     tree = getScene().getTree();
31 
32     (camera = spawn!Camera("MyCam"))
33       .setPreset(CameraPreset.getEmpty())
34       .setMouseMoveLocked()
35       .registerToScene();
36 
37     foreach (i; 0..3)
38       (playerBody[i] = spawn!BSPCube("Body" ~ i.to!string))
39         .build()
40         .getTransform()
41         .setRelativeLocationY(i)
42         .setPivotY(-0.5f);
43     
44     playerBody[1]
45       .getTransform()
46       .rotateYaw(45.0f);
47 
48     foreach (i; 0..10)
49       tree.spawn!BSPCube("Block" ~ i.to!string)
50         .build()
51         .getTransform()
52         .setAbsoluteLocationX(uniform!"[]"(-19, 19))
53         .setAbsoluteLocationZ(uniform!"[]"(-19, 19))
54         .setPivotY(-0.5f);
55 
56     (skybox = spawn!CubeMap("Sky"))
57       .build(new Material([
58         "res/textures/skybox/right.bmp",
59         "res/textures/skybox/left.bmp",
60         "res/textures/skybox/bottom.bmp",
61         "res/textures/skybox/top.bmp",
62         "res/textures/skybox/back.bmp",
63         "res/textures/skybox/front.bmp"
64       ]));
65   }
66 
67   /**
68    * Optional.
69    * If declared, it is called every frame.
70   **/
71   override void update() {
72     //Logger.exception(getScene().getId());
73 
74     if (Input.getKeyboard().isButtonDown(KeyboardButton.T))
75       GfxEngine.toggleWireframe();
76 
77     updateMouseMode();
78     updateBody();
79     updatePhysics();
80 
81     if (getTransform().getAbsoluteLocation().y < killZ)
82       CoreEngine.pause();
83 
84     if (Input.getKeyboard().isButtonDown(KeyboardButton.F))
85       Platform.getWindow().toggleFullscreen();
86 
87     if (Input.getKeyboard().isButtonDown(KeyboardButton.L))
88       getScene().getSerializer().serialize();
89   }
90 
91   private void updateMouseMode() {
92     if (Input.getMouse().isButtonHold(MouseButton.RIGHT)) {
93       camera.setMouseMoveLocked(false);
94       Input.getMouse().setCursorType(CursorType.DISABLED);
95     }
96     
97     if (Input.getMouse().isButtonUp(MouseButton.RIGHT)) {
98       camera.setMouseMoveLocked();
99       Input.getMouse().setCursorType(CursorType.NORMAL);
100     }
101   }
102 
103   private void updateBody() {
104     const float deltaTime = Time.getDelta();
105 
106     if (Input.getKeyboard().isButtonHold(KeyboardButton.A)) {
107       getTransform().setAbsoluteLocationX!"+="(-moveSpeed * deltaTime);
108       playerBody[1]
109         .getTransform()
110         .rotateYaw!"-="(300.0f * deltaTime);
111     }
112 
113     if (Input.getKeyboard().isButtonHold(KeyboardButton.D)) {
114       getTransform().setAbsoluteLocationX!"+="(moveSpeed * deltaTime);
115       playerBody[1]
116         .getTransform()
117         .rotateYaw!"+="(300.0f * deltaTime);
118     }
119     
120     if (Input.getKeyboard().isButtonHold(KeyboardButton.W))
121       getTransform().setAbsoluteLocationZ!"+="(-moveSpeed * deltaTime);
122 
123     if (Input.getKeyboard().isButtonHold(KeyboardButton.S))
124       getTransform().setAbsoluteLocationZ!"+="(moveSpeed * deltaTime);
125 
126     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_1))
127       getTransform().rotateYaw!"+="(1.0f);
128     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_2))
129       getTransform().rotatePitch!"+="(1.0f);
130     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_3))
131       getTransform().rotateRoll!"+="(1.0f);
132 
133     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_4))
134       getTransform().setAbsoluteScale!"+="(1.0f * deltaTime);
135     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_5))
136       getTransform().setAbsoluteScale!"-="(1.0f * deltaTime);
137 
138     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_6))
139       camera.setZNear!"+="(3.0f * deltaTime);
140     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_7))
141       camera.setZNear!"-="(3.0f * deltaTime);
142 
143     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_8))
144       camera.setZFar(20.0f);
145 
146     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_9))
147       camera.setFieldOfView!"+="(20.0f * deltaTime);
148 
149     if (Input.getKeyboard().isButtonHold(KeyboardButton.NUM_0))
150       camera.setFieldOfView!"-="(20.0f * deltaTime);
151 
152     if (Input.getKeyboard().isButtonHold(KeyboardButton.SPACE) && onGround)
153       upSpeed = jumpPower;
154 
155     if (Input.getKeyboard().isButtonDown(KeyboardButton.LEFT_CONTROL))
156       playerBody[1]
157         .setVisibility(Visibility.Hidden);
158 
159     if (Input.getKeyboard().isButtonDown(KeyboardButton.RIGHT_CONTROL))
160       playerBody[1]
161         .setVisibility(Visibility.Visible);
162   }
163 
164   private void updatePhysics() {
165     const float deltaTime = Time.getDelta();
166     upSpeed += gravity * deltaTime;
167     getTransform().setAbsoluteLocationY!"+="(upSpeed * deltaTime);
168     const Vector3F worldPos = getTransform().getAbsoluteLocation();
169 
170     const float terrainHeight = tree.getChild!Terrain("Demo001Terrain")
171       .getHeight(worldPos.x, worldPos.z);
172 
173     onGround = false;
174     
175     if (worldPos.y < terrainHeight) {
176       onGround = true;
177       upSpeed = 0;
178       getTransform().setAbsoluteLocationY(terrainHeight);
179     }
180   }
181 }