3 #include "engine/asset.h"
4 #include "engine/render.h"
8 static const float movementSpeed = 0.5f;
9 static const float collisionRadius = 0.5f;
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;
20 static void movePlayer(Vector direction, float delta);
21 static Vector worldMovementDirection(float x, float y);
26 screenToWorldMovementTransform = identity();
27 rotate(&screenToWorldMovementTransform, (Vector) { 0.0f, 1.0f, 0.0f }, - TAU / 8.0f);
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);
34 playerCharacter = newScene();
35 cameraAnchor = playerCharacter;
36 playerCharacter->solid = importSolid("assets/playercharacter.3ds");
38 playerProjectedMovement = newScene();
41 void spawnPlayer(Transform transform) {
42 playerCharacter->transform = transform;
43 reparentScene(playerCharacter, currentScene);
44 reparentScene(playerProjectedMovement, currentScene);
47 void updatePlayer(float delta) {
48 Vector direction = { 0.0f, 0.0f, 0.0f };
49 if (movementDirection & DIRECTION_UP) {
50 direction = addVectors(direction, worldMovementUp);
52 if (movementDirection & DIRECTION_DOWN) {
53 direction = addVectors(direction, worldMovementDown);
55 if (movementDirection & DIRECTION_LEFT) {
56 direction = addVectors(direction, worldMovementLeft);
58 if (movementDirection & DIRECTION_RIGHT) {
59 direction = addVectors(direction, worldMovementRight);
61 movePlayer(direction, delta);
64 void startMovement(Direction direction) {
65 movementDirection |= direction;
68 void stopMovement(Direction direction) {
69 movementDirection &= ~direction;
72 static void movePlayer(Vector direction, float delta) {
73 direction = clampMagnitude(direction, 1.0f);
74 Vector displacement = scaleVector(direction, delta * movementSpeed);
77 Vector displacement = scaleVector(direction, 0.006944f * movementSpeed * 1000.0f);
79 playerProjectedMovement->transform = playerCharacter->transform;
81 Vector initialPosition = translationOf(playerCharacter->transform);
82 Vector position = initialPosition;
84 GridLocation location = gridLocationFromPosition(position);
85 Obstacle obstacle = getObstacles(location);
87 // Eliminate redundant corner checks
88 if (obstacle & OBSTACLE_XP) {
89 obstacle &= ~(OBSTACLE_XP_ZP | OBSTACLE_XP_ZN);
91 if (obstacle & OBSTACLE_XN) {
92 obstacle &= ~(OBSTACLE_XN_ZP | OBSTACLE_XN_ZN);
94 if (obstacle & OBSTACLE_ZP) {
95 obstacle &= ~(OBSTACLE_XP_ZP | OBSTACLE_XN_ZP);
97 if (obstacle & OBSTACLE_ZN) {
98 obstacle &= ~(OBSTACLE_XP_ZN | OBSTACLE_XN_ZN);
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;
114 // Check all edges for intersecting already
115 if (distanceXp < 0.0f) {
116 position.x += distanceXp;
117 displacement = growVectorNoFlip(displacement, distanceXp);
120 if (distanceXn > 0.0f) {
121 position.x += distanceXn;
122 displacement = growVectorNoFlip(displacement, - distanceXn);
125 if (distanceZp < 0.0f) {
126 position.z += distanceZp;
127 displacement = growVectorNoFlip(displacement, distanceZp);
130 if (distanceZn > 0.0f) {
131 position.z += distanceZn;
132 displacement = growVectorNoFlip(displacement, - distanceZn);
136 // Calculate direct movement limits
137 float dx = displacement.x;
138 float dz = displacement.z;
139 if (dx > distanceXp) {
140 dz *= distanceXp / dx;
142 // Might need a flag that we've reached a limit in X+?
144 if (dx < distanceXn) {
145 dz *= distanceXn / dx;
149 if (dz > distanceZp) {
150 dx *= distanceZp / dz;
154 if (dz < distanceZn) {
155 dx *= distanceZn / dz;
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));
165 translate(&playerCharacter->transform, displacement);
168 static Vector worldMovementDirection(float x, float y) {
169 Vector direction = (Vector) { x, 0.0f, -y };
170 direction = normalized(
171 applyTransform(screenToWorldMovementTransform, direction));