]> git.lizzy.rs Git - shadowclad.git/blob - src/game/player.c
636b130603dfc820218d5898150bad36af2049f2
[shadowclad.git] / src / game / player.c
1 #include "player.h"
2
3 #include "engine/asset.h"
4 #include "engine/render.h"
5
6 #include "level.h"
7
8 static const float movementSpeed = 0.5f;
9 static const float collisionRadius = 0.5f;
10
11 Scene* playerCharacter;
12 Scene* playerProjectedMovement;
13 static Transform screenToWorldMovementTransform;
14 static Vector worldMovementUp;
15 static Vector worldMovementDown;
16 static Vector worldMovementLeft;
17 static Vector worldMovementRight;
18 static Direction movementDirection;
19
20 static void movePlayer(Vector direction, float delta);
21 static Vector worldMovementDirection(float x, float y);
22
23
24
25 void initPlayer() {
26         screenToWorldMovementTransform = identity();
27         rotate(&screenToWorldMovementTransform, (Vector) { 0.0f, 1.0f, 0.0f }, - TAU / 8.0f);
28
29         worldMovementUp = worldMovementDirection(0.0f, 1.0f);
30         worldMovementDown = worldMovementDirection(0.0f, -1.0f);
31         worldMovementLeft = worldMovementDirection(-1.0f, 0.0f);
32         worldMovementRight = worldMovementDirection(1.0f, 0.0f);
33
34         playerCharacter = newScene();
35         cameraAnchor = playerCharacter;
36         playerCharacter->solid = importSolid("assets/playercharacter.3ds");
37
38         playerProjectedMovement = newScene();
39 }
40
41 void spawnPlayer(Transform transform) {
42         playerCharacter->transform = transform;
43         reparentScene(playerCharacter, currentScene);
44         reparentScene(playerProjectedMovement, currentScene);
45 }
46
47 void updatePlayer(float delta) {
48         Vector direction = { 0.0f, 0.0f, 0.0f };
49         if (movementDirection & DIRECTION_UP) {
50                 direction = addVectors(direction, worldMovementUp);
51         }
52         if (movementDirection & DIRECTION_DOWN) {
53                 direction = addVectors(direction, worldMovementDown);
54         }
55         if (movementDirection & DIRECTION_LEFT) {
56                 direction = addVectors(direction, worldMovementLeft);
57         }
58         if (movementDirection & DIRECTION_RIGHT) {
59                 direction = addVectors(direction, worldMovementRight);
60         }
61         movePlayer(direction, delta);
62 }
63
64 void startMovement(Direction direction) {
65         movementDirection |= direction;
66 }
67
68 void stopMovement(Direction direction) {
69         movementDirection &= ~direction;
70 }
71
72 static void movePlayer(Vector direction, float delta) {
73         direction = clampMagnitude(direction, 1.0f);
74         Vector displacement = scaleVector(direction, delta * movementSpeed);
75
76 {
77 Vector displacement = scaleVector(direction, 0.006944f * movementSpeed * 1000.0f);
78
79         playerProjectedMovement->transform = playerCharacter->transform;
80
81         Vector initialPosition = translationOf(playerCharacter->transform);
82         Vector position = initialPosition;
83
84         GridLocation location = gridLocationFromPosition(position);
85         Obstacle obstacle = getObstacles(location);
86
87         // Eliminate redundant corner checks
88         if (obstacle & OBSTACLE_XP) {
89                 obstacle &= ~(OBSTACLE_XP_ZP | OBSTACLE_XP_ZN);
90         }
91         if (obstacle & OBSTACLE_XN) {
92                 obstacle &= ~(OBSTACLE_XN_ZP | OBSTACLE_XN_ZN);
93         }
94         if (obstacle & OBSTACLE_ZP) {
95                 obstacle &= ~(OBSTACLE_XP_ZP | OBSTACLE_XN_ZP);
96         }
97         if (obstacle & OBSTACLE_ZN) {
98                 obstacle &= ~(OBSTACLE_XP_ZN | OBSTACLE_XN_ZN);
99         }
100
101         float edgeXp = cellBoundaryCoord(location.x + 1);
102         float edgeXn = cellBoundaryCoord(location.x);
103         float edgeZp = cellBoundaryCoord(location.z + 1);
104         float edgeZn = cellBoundaryCoord(location.z);
105         float distanceXp = edgeXp - position.x;
106         if (obstacle & OBSTACLE_XP) distanceXp -= collisionRadius;
107         float distanceXn = edgeXn - position.x;
108         if (obstacle & OBSTACLE_XN) distanceXn += collisionRadius;
109         float distanceZp = edgeZp - position.z;
110         if (obstacle & OBSTACLE_ZP) distanceZp -= collisionRadius;
111         float distanceZn = edgeZn - position.z;
112         if (obstacle & OBSTACLE_ZN) distanceZn += collisionRadius;
113
114         // Check all edges for intersecting already
115         if (distanceXp < 0.0f) {
116                 position.x += distanceXp;
117                 displacement = growVectorNoFlip(displacement, distanceXp);
118                 distanceXp = 0.0f;
119         }
120         if (distanceXn > 0.0f) {
121                 position.x += distanceXn;
122                 displacement = growVectorNoFlip(displacement, - distanceXn);
123                 distanceXn = 0.0f;
124         }
125         if (distanceZp < 0.0f) {
126                 position.z += distanceZp;
127                 displacement = growVectorNoFlip(displacement, distanceZp);
128                 distanceZp = 0.0f;
129         }
130         if (distanceZn > 0.0f) {
131                 position.z += distanceZn;
132                 displacement = growVectorNoFlip(displacement, - distanceZn);
133                 distanceZn = 0.0f;
134         }
135
136         // Calculate direct movement limits
137         float dx = displacement.x;
138         float dz = displacement.z;
139         if (dx > distanceXp) {
140                 dz *= distanceXp / dx;
141                 dx = distanceXp;
142                 // Might need a flag that we've reached a limit in X+?
143         }
144         if (dx < distanceXn) {
145                 dz *= distanceXn / dx;
146                 dx = distanceXn;
147                 // ?
148         }
149         if (dz > distanceZp) {
150                 dx *= distanceZp / dz;
151                 dz = distanceZp;
152                 // ?
153         }
154         if (dz < distanceZn) {
155                 dx *= distanceZn / dz;
156                 dz = distanceZn;
157                 // ?
158         }
159         // This is how far we can move until we collide or leave the grid cell
160         position = addVectors(position, (Vector) { dx, 0.0f, dz });
161         translate(&playerProjectedMovement->transform, subtractVectors(position, initialPosition));
162 }
163
164
165         translate(&playerCharacter->transform, displacement);
166 }
167
168 static Vector worldMovementDirection(float x, float y) {
169         Vector direction = (Vector) { x, 0.0f, -y };
170         direction = normalized(
171                 applyTransform(screenToWorldMovementTransform, direction));
172         return direction;
173 }