return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
}
+Vector3D scaleVector(Vector3D vec, float scale) {
+ return (Vector3D) { vec.x * scale,
+ vec.y * scale,
+ vec.z * scale };
+}
+
+Vector3D clampMagnitude(Vector3D vec, float maxMagnitude) {
+ float m = magnitude(vec);
+ if (m > maxMagnitude) {
+ vec = scaleVector(vec, maxMagnitude / m);
+ }
+ return vec;
+}
+
+float magnitude(Vector3D vec) {
+ return sqrtf(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
+}
+
Vector3D applyTransform(Transform transform, Vector3D vec) {
GLfloat* a = (GLfloat*) &transform;
GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f };
}
Vector3D normalized(Vector3D vec) {
- float magnitude = sqrtf(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
- return (Vector3D) {vec.x / magnitude, vec.y / magnitude, vec.z / magnitude};
+ float m = magnitude(vec);
+ return (Vector3D) { vec.x / m, vec.y / m, vec.z / m };
}
Vector3D subtractVectors(Vector3D v1, Vector3D v2);
Vector3D crossProduct(Vector3D v1, Vector3D v2);
float dotProduct(Vector3D v1, Vector3D v2);
+Vector3D scaleVector(Vector3D vec, float scale);
+Vector3D clampMagnitude(Vector3D vec, float maxMagnitude);
+float magnitude(Vector3D vec);
Vector3D applyTransform(Transform transform, Vector3D vec);
Vector3D translationOf(Transform transform);
Vector3D normalized(Vector3D vec);
#include "player.h"
-void onKeyPressed(unsigned char key, int x, int y) {
+void onKeyboardEvent(GLFWwindow* window, int key, int scancode, int action, int mods) {
switch (key) {
- case 'w':
- playerMovementInput(0.0f, 1.0f);
+ case GLFW_KEY_W:
+ if (action == GLFW_PRESS) {
+ startMovement(DIRECTION_UP);
+ }
+ else if (action == GLFW_RELEASE) {
+ stopMovement(DIRECTION_UP);
+ }
break;
- case 's':
- playerMovementInput(0.0f, -1.0f);
+ case GLFW_KEY_S:
+ if (action == GLFW_PRESS) {
+ startMovement(DIRECTION_DOWN);
+ }
+ else if (action == GLFW_RELEASE) {
+ stopMovement(DIRECTION_DOWN);
+ }
break;
- case 'a':
- playerMovementInput(-1.0f, 0.0f);
+ case GLFW_KEY_A:
+ if (action == GLFW_PRESS) {
+ startMovement(DIRECTION_LEFT);
+ }
+ else if (action == GLFW_RELEASE) {
+ stopMovement(DIRECTION_LEFT);
+ }
break;
- case 'd':
- playerMovementInput(1.0f, 0.0f);
+ case GLFW_KEY_D:
+ if (action == GLFW_PRESS) {
+ startMovement(DIRECTION_RIGHT);
+ }
+ else if (action == GLFW_RELEASE) {
+ stopMovement(DIRECTION_RIGHT);
+ }
break;
default:
break;
}
}
-
-void onKeyboardEvent(GLFWwindow* window, int key, int scancode, int action, int mods) {
- if (action == GLFW_PRESS) {
- switch (key) {
- case GLFW_KEY_W:
- playerMovementInput(0.0f, 1.0f);
- break;
- case GLFW_KEY_S:
- playerMovementInput(0.0f, -1.0f);
- break;
- case GLFW_KEY_A:
- playerMovementInput(-1.0f, 0.0f);
- break;
- case GLFW_KEY_D:
- playerMovementInput(1.0f, 0.0f);
- break;
- default:
- break;
- }
- }
-}
#include <GLFW/glfw3.h>
-void onKeyPressed(unsigned char key, int x, int y);
void onKeyboardEvent(GLFWwindow* window, int key, int scancode, int action, int mods);
#endif // INPUT_H_
#include "engine/asset.h"
#include "engine/render.h"
+static const float movementSpeed = 2.5f;
+
Scene* playerCharacter;
-static Transform movementDirectionTransform;
+static Transform screenToWorldMovementTransform;
+static Vector3D worldMovementUp;
+static Vector3D worldMovementDown;
+static Vector3D worldMovementLeft;
+static Vector3D worldMovementRight;
+static Direction movementDirection;
+
+static void movePlayer(Vector3D direction, float delta);
+static Vector3D worldMovementDirection(float x, float y);
void initPlayer() {
- movementDirectionTransform = identity();
- rotate(&movementDirectionTransform, (Vector3D) { 0.0f, 1.0f, 0.0f }, - TAU / 8.0f);
+ screenToWorldMovementTransform = identity();
+ rotate(&screenToWorldMovementTransform, (Vector3D) { 0.0f, 1.0f, 0.0f }, - TAU / 8.0f);
+
+ worldMovementUp = worldMovementDirection(0.0f, 1.0f);
+ worldMovementDown = worldMovementDirection(0.0f, -1.0f);
+ worldMovementLeft = worldMovementDirection(-1.0f, 0.0f);
+ worldMovementRight = worldMovementDirection(1.0f, 0.0f);
playerCharacter = newScene();
cameraAnchor = playerCharacter;
reparentScene(playerCharacter, currentScene);
}
-void playerMovementInput(float x, float y) {
- if (!playerCharacter) {
- return;
+void updatePlayer(float delta) {
+ Vector3D direction = { 0.0f, 0.0f, 0.0f };
+ if (movementDirection & DIRECTION_UP) {
+ direction = addVectors(direction, worldMovementUp);
+ }
+ if (movementDirection & DIRECTION_DOWN) {
+ direction = addVectors(direction, worldMovementDown);
}
+ if (movementDirection & DIRECTION_LEFT) {
+ direction = addVectors(direction, worldMovementLeft);
+ }
+ if (movementDirection & DIRECTION_RIGHT) {
+ direction = addVectors(direction, worldMovementRight);
+ }
+ movePlayer(direction, delta);
+}
+void startMovement(Direction direction) {
+ movementDirection |= direction;
+}
+
+void stopMovement(Direction direction) {
+ movementDirection &= ~direction;
+}
+
+static void movePlayer(Vector3D direction, float delta) {
+ direction = clampMagnitude(direction, 1.0f);
+ Vector3D displacement = scaleVector(direction, delta * movementSpeed);
+ translate(&playerCharacter->transform, displacement);
+}
+
+static Vector3D worldMovementDirection(float x, float y) {
Vector3D direction = (Vector3D) { x, 0.0f, -y };
direction = normalized(
- applyTransform(movementDirectionTransform, direction));
- float velocity = 1.0f;
- Vector3D movement = { direction.x * velocity,
- direction.y * velocity,
- direction.z * velocity };
-
- translate(&(playerCharacter->transform), movement);
+ applyTransform(screenToWorldMovementTransform, direction));
+ return direction;
}
#include "engine/scene.h"
+enum Direction {
+ DIRECTION_UP = 1 << 0,
+ DIRECTION_DOWN = 1 << 1,
+ DIRECTION_LEFT = 1 << 2,
+ DIRECTION_RIGHT = 1 << 3,
+};
+
+typedef enum Direction Direction;
+
extern Scene* playerCharacter;
void initPlayer();
void spawnPlayer(Transform transform);
-void playerMovementInput(float x, float y);
+void updatePlayer(float delta);
+void startMovement(Direction direction);
+void stopMovement(Direction direction);
#endif // PLAYER_H_
}
glfwMakeContextCurrent(window);
- //glutInitDisplayMode(//glut_DOUBLE | //glut_RGBA | //glut_DEPTH);
logInfo("OpenGL %s", (const char*) glGetString(GL_VERSION));
logInfo("GLSL %s", (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
logError("GLEW init failed: %s", (const char*) glewGetErrorString(glewInitStatus));
return 1;
}
-/*
- if (GLXEW_EXT_swap_control) {
- Display* display = glXGetCurrentDisplay();
- GLXDrawable drawable = glXGetCurrentDrawable();
- if (drawable) {
- glXSwapIntervalEXT(display, drawable, 1);
- }
- else {
- logWarning("Drawable is not here ¯\\_(ツ)_/¯");
- logWarning("Could not enable vsync (GLX_EXT_swap_control)");
- }
- }
- else if (GLXEW_MESA_swap_control) {
- glXSwapIntervalMESA(1);
- logDebug("Vsync enabled with GLX_MESA_swap_control, swap interval %d", glXGetSwapIntervalMESA());
- }
- else {
- logWarning("Could not enable vsync (extensions not supported)");
- }
-*/
+
logInfo("Setting swap interval to 1");
glfwSwapInterval(1);
initPlayer();
startLevel();
+ float lastTime = glfwGetTime();
+ float delta = 0.0f;
+
while (!glfwWindowShouldClose(window)) {
+ float time = glfwGetTime();
+ delta = time - lastTime;
+ lastTime = time;
+
+ updatePlayer(delta);
renderFrame(window);
glfwPollEvents();
}