player blocks interaction callbacks
This commit is contained in:
parent
ec10c77707
commit
87dd1dd6b2
@ -20,10 +20,14 @@
|
||||
|
||||
#include "../core_defs.h"
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
|
||||
const float CAM_SHAKE_OFFSET = 0.025f;
|
||||
const float CAM_SHAKE_OFFSET_Y = 0.031f;
|
||||
const float CAM_SHAKE_SPEED = 1.75f;
|
||||
const float CAM_SHAKE_DELTA_K = 10.0f;
|
||||
const float STEPS_SPEED = 1.75f;
|
||||
const float ZOOM_SPEED = 16.0f;
|
||||
const float CROUCH_ZOOM = 0.9f;
|
||||
const float RUN_ZOOM = 1.1f;
|
||||
@ -33,8 +37,7 @@ const float CROUCH_SHIFT_Y = -0.2f;
|
||||
|
||||
CameraControl::CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings)
|
||||
: player(player),
|
||||
camera(player->camera),
|
||||
currentViewCamera(player->currentCamera),
|
||||
camera(player->camera),
|
||||
settings(settings),
|
||||
offset(0.0f, 0.7f, 0.0f) {
|
||||
}
|
||||
@ -46,7 +49,10 @@ void CameraControl::refresh() {
|
||||
void CameraControl::updateMouse(PlayerInput& input) {
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void CameraControl::update(PlayerInput& input, float delta, Chunks* chunks) {
|
||||
Hitbox* hitbox = player->hitbox.get();
|
||||
glm::vec3 CameraControl::updateCameraShaking(float delta) {
|
||||
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);
|
||||
|
||||
if (settings.shaking && !input.cheat) {
|
||||
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);
|
||||
offset += updateCameraShaking(delta);
|
||||
}
|
||||
|
||||
if (settings.fovEvents){
|
||||
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);
|
||||
updateFovEffects(input, delta);
|
||||
}
|
||||
if (input.cameraMode) {
|
||||
switchCamera();
|
||||
}
|
||||
|
||||
auto spCamera = player->spCamera;
|
||||
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) {
|
||||
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->front = -camera->front;
|
||||
}
|
||||
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->front = camera->front;
|
||||
}
|
||||
@ -140,11 +173,60 @@ int PlayerController::selectedBlockStates = 0;
|
||||
PlayerController::PlayerController(
|
||||
Level* level,
|
||||
const EngineSettings& settings,
|
||||
BlocksController* blocksController)
|
||||
: level(level),
|
||||
player(level->getObject<Player>(0)),
|
||||
camControl(player, settings.camera),
|
||||
blocksController(blocksController) {
|
||||
BlocksController* blocksController
|
||||
) : level(level),
|
||||
player(level->getObject<Player>(0)),
|
||||
camControl(player, settings.camera),
|
||||
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) {
|
||||
@ -154,6 +236,7 @@ void PlayerController::update(float delta, bool input, bool pause) {
|
||||
} else {
|
||||
resetKeyboard();
|
||||
}
|
||||
updateFootsteps(delta);
|
||||
updateCamera(delta, input);
|
||||
updateControls(delta);
|
||||
|
||||
@ -289,6 +372,11 @@ void PlayerController::updateInteraction(){
|
||||
uint8_t states = determine_rotation(def, norm, camera->dir);
|
||||
|
||||
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))
|
||||
return;
|
||||
}
|
||||
@ -334,6 +422,11 @@ void PlayerController::updateInteraction(){
|
||||
chunks->set(x, y, z, chosenBlock, states);
|
||||
lighting->onBlockSet(x,y,z, chosenBlock);
|
||||
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);
|
||||
}
|
||||
blocksController->updateSides(x, y, z);
|
||||
@ -358,3 +451,7 @@ void PlayerController::updateInteraction(){
|
||||
Player* PlayerController::getPlayer() {
|
||||
return player.get();
|
||||
}
|
||||
|
||||
void PlayerController::listenBlockInteraction(on_block_interaction callback) {
|
||||
blockInteractionCallbacks.push_back(callback);
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#define PLAYER_CONTROL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "../settings.h"
|
||||
@ -9,16 +11,30 @@
|
||||
|
||||
class Camera;
|
||||
class Level;
|
||||
class Block;
|
||||
class BlocksController;
|
||||
|
||||
class CameraControl {
|
||||
std::shared_ptr<Player> player;
|
||||
std::shared_ptr<Camera> camera, currentViewCamera;
|
||||
std::shared_ptr<Camera> camera;
|
||||
const CameraSettings& settings;
|
||||
glm::vec3 offset;
|
||||
float shake = 0.0f;
|
||||
float shakeTimer = 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:
|
||||
CameraControl(std::shared_ptr<Player> player, const CameraSettings& settings);
|
||||
void updateMouse(PlayerInput& input);
|
||||
@ -26,6 +42,16 @@ public:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
enum class BlockInteraction {
|
||||
step,
|
||||
destruction,
|
||||
placing
|
||||
};
|
||||
|
||||
using on_block_interaction = std::function<void(
|
||||
Player*, glm::ivec3, const Block*, BlockInteraction type
|
||||
)>;
|
||||
|
||||
class PlayerController {
|
||||
Level* level;
|
||||
std::shared_ptr<Player> player;
|
||||
@ -33,11 +59,22 @@ class PlayerController {
|
||||
CameraControl camControl;
|
||||
BlocksController* blocksController;
|
||||
|
||||
std::vector<on_block_interaction> blockInteractionCallbacks;
|
||||
|
||||
void updateKeyboard();
|
||||
void updateCamera(float delta, bool movement);
|
||||
void resetKeyboard();
|
||||
void updateControls(float delta);
|
||||
void updateInteraction();
|
||||
void onBlockInteraction(
|
||||
glm::ivec3 pos,
|
||||
const Block* def,
|
||||
BlockInteraction type
|
||||
);
|
||||
|
||||
float stepsTimer = 0.0f;
|
||||
void onFootstep();
|
||||
void updateFootsteps(float delta);
|
||||
public:
|
||||
static glm::vec3 selectedBlockPosition;
|
||||
static glm::ivec3 selectedBlockNormal;
|
||||
@ -45,12 +82,16 @@ public:
|
||||
static int selectedBlockId;
|
||||
static int selectedBlockStates;
|
||||
|
||||
PlayerController(Level* level,
|
||||
const EngineSettings& settings,
|
||||
BlocksController* blocksController);
|
||||
PlayerController(
|
||||
Level* level,
|
||||
const EngineSettings& settings,
|
||||
BlocksController* blocksController
|
||||
);
|
||||
void update(float delta, bool input, bool pause);
|
||||
|
||||
Player* getPlayer();
|
||||
|
||||
void listenBlockInteraction(on_block_interaction callback);
|
||||
};
|
||||
|
||||
#endif /* PLAYER_CONTROL_H_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user