Implement continuous player movement

master
outfrost 2020-06-23 04:44:23 +02:00
parent 3b45ae5a19
commit b62918e84e
7 changed files with 123 additions and 68 deletions

View File

@ -72,6 +72,24 @@ float dotProduct(Vector3D v1, Vector3D v2) {
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 };
@ -92,6 +110,6 @@ Vector3D translationOf(Transform transform) {
}
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 };
}

View File

@ -29,6 +29,9 @@ Vector3D addVectors(Vector3D v1, Vector3D v2);
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);

View File

@ -2,42 +2,41 @@
#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;
}
}
}

View File

@ -3,7 +3,6 @@
#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_

View File

@ -3,14 +3,29 @@
#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;
@ -22,18 +37,40 @@ void spawnPlayer(Transform transform) {
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;
}

View File

@ -5,10 +5,21 @@
#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_

View File

@ -36,7 +36,6 @@ int main(/*int argc, char** argv*/) {
}
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));
@ -47,26 +46,7 @@ int main(/*int argc, char** argv*/) {
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);
@ -83,7 +63,15 @@ int main(/*int argc, char** argv*/) {
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();
}