Implement continuous player movement
parent
3b45ae5a19
commit
b62918e84e
|
@ -72,6 +72,24 @@ float dotProduct(Vector3D v1, Vector3D v2) {
|
||||||
return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
|
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) {
|
Vector3D applyTransform(Transform transform, Vector3D vec) {
|
||||||
GLfloat* a = (GLfloat*) &transform;
|
GLfloat* a = (GLfloat*) &transform;
|
||||||
GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f };
|
GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f };
|
||||||
|
@ -92,6 +110,6 @@ Vector3D translationOf(Transform transform) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3D normalized(Vector3D vec) {
|
Vector3D normalized(Vector3D vec) {
|
||||||
float magnitude = sqrtf(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
|
float m = magnitude(vec);
|
||||||
return (Vector3D) {vec.x / magnitude, vec.y / magnitude, vec.z / magnitude};
|
return (Vector3D) { vec.x / m, vec.y / m, vec.z / m };
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ Vector3D addVectors(Vector3D v1, Vector3D v2);
|
||||||
Vector3D subtractVectors(Vector3D v1, Vector3D v2);
|
Vector3D subtractVectors(Vector3D v1, Vector3D v2);
|
||||||
Vector3D crossProduct(Vector3D v1, Vector3D v2);
|
Vector3D crossProduct(Vector3D v1, Vector3D v2);
|
||||||
float dotProduct(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 applyTransform(Transform transform, Vector3D vec);
|
||||||
Vector3D translationOf(Transform transform);
|
Vector3D translationOf(Transform transform);
|
||||||
Vector3D normalized(Vector3D vec);
|
Vector3D normalized(Vector3D vec);
|
||||||
|
|
|
@ -2,42 +2,41 @@
|
||||||
|
|
||||||
#include "player.h"
|
#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) {
|
switch (key) {
|
||||||
case 'w':
|
case GLFW_KEY_W:
|
||||||
playerMovementInput(0.0f, 1.0f);
|
if (action == GLFW_PRESS) {
|
||||||
|
startMovement(DIRECTION_UP);
|
||||||
|
}
|
||||||
|
else if (action == GLFW_RELEASE) {
|
||||||
|
stopMovement(DIRECTION_UP);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 's':
|
case GLFW_KEY_S:
|
||||||
playerMovementInput(0.0f, -1.0f);
|
if (action == GLFW_PRESS) {
|
||||||
|
startMovement(DIRECTION_DOWN);
|
||||||
|
}
|
||||||
|
else if (action == GLFW_RELEASE) {
|
||||||
|
stopMovement(DIRECTION_DOWN);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case GLFW_KEY_A:
|
||||||
playerMovementInput(-1.0f, 0.0f);
|
if (action == GLFW_PRESS) {
|
||||||
|
startMovement(DIRECTION_LEFT);
|
||||||
|
}
|
||||||
|
else if (action == GLFW_RELEASE) {
|
||||||
|
stopMovement(DIRECTION_LEFT);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case GLFW_KEY_D:
|
||||||
playerMovementInput(1.0f, 0.0f);
|
if (action == GLFW_PRESS) {
|
||||||
|
startMovement(DIRECTION_RIGHT);
|
||||||
|
}
|
||||||
|
else if (action == GLFW_RELEASE) {
|
||||||
|
stopMovement(DIRECTION_RIGHT);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#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);
|
void onKeyboardEvent(GLFWwindow* window, int key, int scancode, int action, int mods);
|
||||||
|
|
||||||
#endif // INPUT_H_
|
#endif // INPUT_H_
|
||||||
|
|
|
@ -3,14 +3,29 @@
|
||||||
#include "engine/asset.h"
|
#include "engine/asset.h"
|
||||||
#include "engine/render.h"
|
#include "engine/render.h"
|
||||||
|
|
||||||
|
static const float movementSpeed = 2.5f;
|
||||||
|
|
||||||
Scene* playerCharacter;
|
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() {
|
void initPlayer() {
|
||||||
movementDirectionTransform = identity();
|
screenToWorldMovementTransform = identity();
|
||||||
rotate(&movementDirectionTransform, (Vector3D) { 0.0f, 1.0f, 0.0f }, - TAU / 8.0f);
|
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();
|
playerCharacter = newScene();
|
||||||
cameraAnchor = playerCharacter;
|
cameraAnchor = playerCharacter;
|
||||||
|
@ -22,18 +37,40 @@ void spawnPlayer(Transform transform) {
|
||||||
reparentScene(playerCharacter, currentScene);
|
reparentScene(playerCharacter, currentScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
void playerMovementInput(float x, float y) {
|
void updatePlayer(float delta) {
|
||||||
if (!playerCharacter) {
|
Vector3D direction = { 0.0f, 0.0f, 0.0f };
|
||||||
return;
|
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 };
|
Vector3D direction = (Vector3D) { x, 0.0f, -y };
|
||||||
direction = normalized(
|
direction = normalized(
|
||||||
applyTransform(movementDirectionTransform, direction));
|
applyTransform(screenToWorldMovementTransform, direction));
|
||||||
float velocity = 1.0f;
|
return direction;
|
||||||
Vector3D movement = { direction.x * velocity,
|
|
||||||
direction.y * velocity,
|
|
||||||
direction.z * velocity };
|
|
||||||
|
|
||||||
translate(&(playerCharacter->transform), movement);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,21 @@
|
||||||
|
|
||||||
#include "engine/scene.h"
|
#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;
|
extern Scene* playerCharacter;
|
||||||
|
|
||||||
void initPlayer();
|
void initPlayer();
|
||||||
void spawnPlayer(Transform transform);
|
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_
|
#endif // PLAYER_H_
|
||||||
|
|
30
src/main.c
30
src/main.c
|
@ -36,7 +36,6 @@ int main(/*int argc, char** argv*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
//glutInitDisplayMode(//glut_DOUBLE | //glut_RGBA | //glut_DEPTH);
|
|
||||||
|
|
||||||
logInfo("OpenGL %s", (const char*) glGetString(GL_VERSION));
|
logInfo("OpenGL %s", (const char*) glGetString(GL_VERSION));
|
||||||
logInfo("GLSL %s", (const char*) glGetString(GL_SHADING_LANGUAGE_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));
|
logError("GLEW init failed: %s", (const char*) glewGetErrorString(glewInitStatus));
|
||||||
return 1;
|
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");
|
logInfo("Setting swap interval to 1");
|
||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
|
@ -83,7 +63,15 @@ int main(/*int argc, char** argv*/) {
|
||||||
initPlayer();
|
initPlayer();
|
||||||
startLevel();
|
startLevel();
|
||||||
|
|
||||||
|
float lastTime = glfwGetTime();
|
||||||
|
float delta = 0.0f;
|
||||||
|
|
||||||
while (!glfwWindowShouldClose(window)) {
|
while (!glfwWindowShouldClose(window)) {
|
||||||
|
float time = glfwGetTime();
|
||||||
|
delta = time - lastTime;
|
||||||
|
lastTime = time;
|
||||||
|
|
||||||
|
updatePlayer(delta);
|
||||||
renderFrame(window);
|
renderFrame(window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue