player blocks interaction callbacks

This commit is contained in:
MihailRis
2024-03-09 01:56:45 +03:00
parent ec10c77707
commit 87dd1dd6b2
2 changed files with 194 additions and 56 deletions
+148 -51
View File
@@ -20,10 +20,14 @@
#include "../core_defs.h" #include "../core_defs.h"
#define _USE_MATH_DEFINES
#include <cmath>
const float CAM_SHAKE_OFFSET = 0.025f; const float CAM_SHAKE_OFFSET = 0.025f;
const float CAM_SHAKE_OFFSET_Y = 0.031f; const float CAM_SHAKE_OFFSET_Y = 0.031f;
const float CAM_SHAKE_SPEED = 1.75f; const float CAM_SHAKE_SPEED = 1.75f;
const float CAM_SHAKE_DELTA_K = 10.0f; const float CAM_SHAKE_DELTA_K = 10.0f;
const float STEPS_SPEED = 1.75f;
const float ZOOM_SPEED = 16.0f; const float ZOOM_SPEED = 16.0f;
const float CROUCH_ZOOM = 0.9f; const float CROUCH_ZOOM = 0.9f;
const float RUN_ZOOM = 1.1f; const float RUN_ZOOM = 1.1f;
@@ -34,7 +38,6 @@ const float CROUCH_SHIFT_Y = -0.2f;
CameraControl::CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings) CameraControl::CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings)
: player(player), : player(player),
camera(player->camera), camera(player->camera),
currentViewCamera(player->currentCamera),
settings(settings), settings(settings),
offset(0.0f, 0.7f, 0.0f) { offset(0.0f, 0.7f, 0.0f) {
} }
@@ -46,7 +49,10 @@ void CameraControl::refresh() {
void CameraControl::updateMouse(PlayerInput& input) { void CameraControl::updateMouse(PlayerInput& input) {
glm::vec2& cam = player->cam; glm::vec2& cam = player->cam;
float sensitivity = (input.zoom ? settings.sensitivity / 4.f : settings.sensitivity); float sensitivity = (input.zoom
? settings.sensitivity / 4.f
: settings.sensitivity);
cam -= glm::degrees(Events::delta / (float)Window::height * sensitivity); cam -= glm::degrees(Events::delta / (float)Window::height * sensitivity);
if (cam.y < -89.9f) { if (cam.y < -89.9f) {
@@ -66,66 +72,93 @@ void CameraControl::updateMouse(PlayerInput& input) {
camera->rotate(glm::radians(cam.y), glm::radians(cam.x), 0); camera->rotate(glm::radians(cam.y), glm::radians(cam.x), 0);
} }
void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) { glm::vec3 CameraControl::updateCameraShaking(float delta) {
Hitbox* hitbox = player->hitbox.get(); glm::vec3 offset {};
auto hitbox = player->hitbox.get();
const float k = CAM_SHAKE_DELTA_K;
const float oh = CAM_SHAKE_OFFSET;
const float ov = CAM_SHAKE_OFFSET_Y;
const glm::vec3& vel = hitbox->velocity;
interpVel = interpVel * (1.0f - delta * 5) + vel * delta * 0.1f;
if (hitbox->grounded && interpVel.y < 0.0f){
interpVel.y *= -30.0f;
}
shake = shake * (1.0f - delta * k);
if (hitbox->grounded) {
float f = glm::length(glm::vec2(vel.x, vel.z));
shakeTimer += delta * f * CAM_SHAKE_SPEED;
shake += f * delta * k;
}
offset += camera->right * glm::sin(shakeTimer) * oh * shake;
offset += camera->up * glm::abs(glm::cos(shakeTimer)) * ov * shake;
offset -= glm::min(interpVel * 0.05f, 1.0f);
return offset;
}
void CameraControl::updateFovEffects(const PlayerInput& input, float delta) {
auto hitbox = player->hitbox.get();
bool crouch = input.shift && hitbox->grounded && !input.sprint;
float dt = fmin(1.0f, delta * ZOOM_SPEED);
float zoomValue = 1.0f;
if (crouch){
offset += glm::vec3(0.f, CROUCH_SHIFT_Y, 0.f);
zoomValue = CROUCH_ZOOM;
} else if (input.sprint){
zoomValue = RUN_ZOOM;
}
if (input.zoom)
zoomValue *= C_ZOOM;
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
}
// temporary solution
// more extensible but uglier
void CameraControl::switchCamera() {
const std::vector<std::shared_ptr<Camera>> playerCameras {
camera, player->tpCamera, player->spCamera
};
auto index = std::distance(
playerCameras.begin(),
std::find_if(
playerCameras.begin(),
playerCameras.end(),
[=](auto ptr) {
return ptr.get() == player->currentCamera.get();
}
)
);
if (static_cast<size_t>(index) != playerCameras.size()) {
index = (index + 1) % playerCameras.size();
player->currentCamera = playerCameras.at(index);
}
}
void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
offset = glm::vec3(0.0f, 0.7f, 0.0f); offset = glm::vec3(0.0f, 0.7f, 0.0f);
if (settings.shaking && !input.cheat) { if (settings.shaking && !input.cheat) {
const float k = CAM_SHAKE_DELTA_K; offset += updateCameraShaking(delta);
const float oh = CAM_SHAKE_OFFSET;
const float ov = CAM_SHAKE_OFFSET_Y;
const glm::vec3& vel = hitbox->velocity;
interpVel = interpVel * (1.0f - delta * 5) + vel * delta * 0.1f;
if (hitbox->grounded && interpVel.y < 0.0f){
interpVel.y *= -30.0f;
}
shake = shake * (1.0f - delta * k);
if (hitbox->grounded) {
float f = glm::length(glm::vec2(vel.x, vel.z));
shakeTimer += delta * f * CAM_SHAKE_SPEED;
shake += f * delta * k;
}
offset += camera->right * glm::sin(shakeTimer) * oh * shake;
offset += camera->up * glm::abs(glm::cos(shakeTimer)) * ov * shake;
offset -= glm::min(interpVel * 0.05f, 1.0f);
} }
if (settings.fovEvents){ if (settings.fovEvents){
bool crouch = input.shift && hitbox->grounded && !input.sprint; updateFovEffects(input, delta);
}
float dt = fmin(1.0f, delta * ZOOM_SPEED); if (input.cameraMode) {
float zoomValue = 1.0f; switchCamera();
if (crouch){
offset += glm::vec3(0.f, CROUCH_SHIFT_Y, 0.f);
zoomValue = CROUCH_ZOOM;
} else if (input.sprint){
zoomValue = RUN_ZOOM;
}
if (input.zoom)
zoomValue *= C_ZOOM;
camera->zoom = zoomValue * dt + camera->zoom * (1.0f - dt);
} }
auto spCamera = player->spCamera; auto spCamera = player->spCamera;
auto tpCamera = player->tpCamera; auto tpCamera = player->tpCamera;
if (input.cameraMode) { //ugly but effective
if (player->currentCamera == camera)
player->currentCamera = tpCamera;
else if (player->currentCamera == spCamera)
player->currentCamera = camera;
else if (player->currentCamera == tpCamera)
player->currentCamera = spCamera;
}
if (player->currentCamera == spCamera) { if (player->currentCamera == spCamera) {
spCamera->position = chunks->rayCastToObstacle(camera->position, camera->front, 3.0f) - 0.2f*(camera->front); spCamera->position = chunks->rayCastToObstacle(camera->position, camera->front, 3.0f) - 0.2f * camera->front;
spCamera->dir = -camera->dir; spCamera->dir = -camera->dir;
spCamera->front = -camera->front; spCamera->front = -camera->front;
} }
else if (player->currentCamera == tpCamera) { else if (player->currentCamera == tpCamera) {
tpCamera->position = chunks->rayCastToObstacle(camera->position, -camera->front, 3.0f) + 0.2f * (camera->front); tpCamera->position = chunks->rayCastToObstacle(camera->position, -camera->front, 3.0f) + 0.2f * camera->front;
tpCamera->dir = camera->dir; tpCamera->dir = camera->dir;
tpCamera->front = camera->front; tpCamera->front = camera->front;
} }
@@ -140,11 +173,60 @@ int PlayerController::selectedBlockStates = 0;
PlayerController::PlayerController( PlayerController::PlayerController(
Level* level, Level* level,
const EngineSettings& settings, const EngineSettings& settings,
BlocksController* blocksController) BlocksController* blocksController
: level(level), ) : level(level),
player(level->getObject<Player>(0)), player(level->getObject<Player>(0)),
camControl(player, settings.camera), camControl(player, settings.camera),
blocksController(blocksController) { blocksController(blocksController)
{}
void PlayerController::onBlockInteraction(
glm::ivec3 pos,
const Block* def,
BlockInteraction type
) {
for (auto callback : blockInteractionCallbacks) {
callback(player.get(), pos, def, type);
}
}
void PlayerController::onFootstep() {
auto hitbox = player->hitbox.get();
glm::vec3 pos = hitbox->position;
glm::vec3 half = hitbox->halfsize;
for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
for (int offsetX = -1; offsetX <= 1; offsetX++) {
int x = std::floor(pos.x+half.x*offsetX);
int y = std::floor(pos.y-half.y*1.1f);
int z = std::floor(pos.z+half.z*offsetZ);
auto vox = level->chunks->get(x, y, z);
if (vox) {
auto def = level->content->getIndices()->getBlockDef(vox->id);
if (!def->obstacle)
continue;
onBlockInteraction(
glm::ivec3(x, y, z), def,
BlockInteraction::step
);
return;
}
}
}
}
void PlayerController::updateFootsteps(float delta) {
auto hitbox = player->hitbox.get();
if (hitbox->grounded) {
const glm::vec3& vel = hitbox->velocity;
float f = glm::length(glm::vec2(vel.x, vel.z));
stepsTimer += delta * f * STEPS_SPEED;
if (stepsTimer >= M_PI) {
stepsTimer = fmod(stepsTimer, M_PI);
onFootstep();
}
}
} }
void PlayerController::update(float delta, bool input, bool pause) { void PlayerController::update(float delta, bool input, bool pause) {
@@ -154,6 +236,7 @@ void PlayerController::update(float delta, bool input, bool pause) {
} else { } else {
resetKeyboard(); resetKeyboard();
} }
updateFootsteps(delta);
updateCamera(delta, input); updateCamera(delta, input);
updateControls(delta); updateControls(delta);
@@ -289,6 +372,11 @@ void PlayerController::updateInteraction(){
uint8_t states = determine_rotation(def, norm, camera->dir); uint8_t states = determine_rotation(def, norm, camera->dir);
if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) { if (lclick && !input.shift && item->rt.funcsset.on_block_break_by) {
onBlockInteraction(
glm::ivec3(x, y, z), def,
BlockInteraction::destruction
);
// TODO: move scripting to interaction callbacks
if (scripting::on_item_break_block(player.get(), item, x, y, z)) if (scripting::on_item_break_block(player.get(), item, x, y, z))
return; return;
} }
@@ -334,6 +422,11 @@ void PlayerController::updateInteraction(){
chunks->set(x, y, z, chosenBlock, states); chunks->set(x, y, z, chosenBlock, states);
lighting->onBlockSet(x,y,z, chosenBlock); lighting->onBlockSet(x,y,z, chosenBlock);
if (def->rt.funcsset.onplaced) { if (def->rt.funcsset.onplaced) {
onBlockInteraction(
glm::ivec3(x, y, z), def,
BlockInteraction::placing
);
// TODO: move scripting to interaction callbacks
scripting::on_block_placed(player.get(), def, x, y, z); scripting::on_block_placed(player.get(), def, x, y, z);
} }
blocksController->updateSides(x, y, z); blocksController->updateSides(x, y, z);
@@ -358,3 +451,7 @@ void PlayerController::updateInteraction(){
Player* PlayerController::getPlayer() { Player* PlayerController::getPlayer() {
return player.get(); return player.get();
} }
void PlayerController::listenBlockInteraction(on_block_interaction callback) {
blockInteractionCallbacks.push_back(callback);
}
+45 -4
View File
@@ -2,6 +2,8 @@
#define PLAYER_CONTROL_H_ #define PLAYER_CONTROL_H_
#include <memory> #include <memory>
#include <vector>
#include <functional>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "../settings.h" #include "../settings.h"
@@ -9,16 +11,30 @@
class Camera; class Camera;
class Level; class Level;
class Block;
class BlocksController; class BlocksController;
class CameraControl { class CameraControl {
std::shared_ptr<Player> player; std::shared_ptr<Player> player;
std::shared_ptr<Camera> camera, currentViewCamera; std::shared_ptr<Camera> camera;
const CameraSettings& settings; const CameraSettings& settings;
glm::vec3 offset; glm::vec3 offset;
float shake = 0.0f; float shake = 0.0f;
float shakeTimer = 0.0f; float shakeTimer = 0.0f;
glm::vec3 interpVel {0.0f}; glm::vec3 interpVel {0.0f};
/// @brief Update shaking timer and calculate camera offset
/// @param delta delta time
/// @return camera offset
glm::vec3 updateCameraShaking(float delta);
/// @brief Update field-of-view effects
/// @param input player inputs
/// @param delta delta time
void updateFovEffects(const PlayerInput& input, float delta);
/// @brief Switch active player camera
void switchCamera();
public: public:
CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings); CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings);
void updateMouse(PlayerInput& input); void updateMouse(PlayerInput& input);
@@ -26,6 +42,16 @@ public:
void refresh(); void refresh();
}; };
enum class BlockInteraction {
step,
destruction,
placing
};
using on_block_interaction = std::function<void(
Player*, glm::ivec3, const Block*, BlockInteraction type
)>;
class PlayerController { class PlayerController {
Level* level; Level* level;
std::shared_ptr<Player> player; std::shared_ptr<Player> player;
@@ -33,11 +59,22 @@ class PlayerController {
CameraControl camControl; CameraControl camControl;
BlocksController* blocksController; BlocksController* blocksController;
std::vector<on_block_interaction> blockInteractionCallbacks;
void updateKeyboard(); void updateKeyboard();
void updateCamera(float delta, bool movement); void updateCamera(float delta, bool movement);
void resetKeyboard(); void resetKeyboard();
void updateControls(float delta); void updateControls(float delta);
void updateInteraction(); void updateInteraction();
void onBlockInteraction(
glm::ivec3 pos,
const Block* def,
BlockInteraction type
);
float stepsTimer = 0.0f;
void onFootstep();
void updateFootsteps(float delta);
public: public:
static glm::vec3 selectedBlockPosition; static glm::vec3 selectedBlockPosition;
static glm::ivec3 selectedBlockNormal; static glm::ivec3 selectedBlockNormal;
@@ -45,12 +82,16 @@ public:
static int selectedBlockId; static int selectedBlockId;
static int selectedBlockStates; static int selectedBlockStates;
PlayerController(Level* level, PlayerController(
const EngineSettings& settings, Level* level,
BlocksController* blocksController); const EngineSettings& settings,
BlocksController* blocksController
);
void update(float delta, bool input, bool pause); void update(float delta, bool input, bool pause);
Player* getPlayer(); Player* getPlayer();
void listenBlockInteraction(on_block_interaction callback);
}; };
#endif /* PLAYER_CONTROL_H_ */ #endif /* PLAYER_CONTROL_H_ */