1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-25 11:52:40 +01:00

Detect event starts by double-buffering state

This commit is contained in:
Daniel Evans 2016-11-10 22:00:02 +00:00
parent 9f2fb5aa19
commit 57edc3648b
5 changed files with 41 additions and 19 deletions

View File

@ -55,14 +55,17 @@ struct GameInputState {
*
* For buttons, this will result in either 0 or 1.
*/
float currentLevels[_MaxControls] = {};
float levels[_MaxControls] = {};
float operator[](Control c) const {
return currentLevels[c];
return levels[c];
}
/**
* @return if cotrol is held down
*/
bool pressed(Control c) const {
return currentLevels[c] > kButtonOnThreshold;
return levels[c] > kButtonOnThreshold;
}
};

View File

@ -337,9 +337,9 @@ public:
std::bitset<32> importExportUnused;
/**
* State of the game input
* State of the game input for the last 2 frames
*/
GameInputState input;
GameInputState input[2];
/**
* World to use for this state, this isn't saved, just used at runtime
@ -362,6 +362,13 @@ public:
* Removes a blip
*/
void removeBlip(int blip);
/**
* Swaps input state
*/
void swapInputState() {
input[1] = input[0];
}
};
#endif

View File

@ -2459,7 +2459,7 @@ bool opcode_00e1(const ScriptArguments& args, const ScriptPad player, const Scri
// Hack: not implemented correctly.
if (player == 0) {
if (buttonID == 19) { // Look behind / sub mission
return args.getState()->input.pressed(GameInputState::Submission);
return args.getState()->input[0].pressed(GameInputState::Submission);
}
}
return false;

View File

@ -420,6 +420,8 @@ int RWGame::run() {
tick(GAME_TIMESTEP);
RW_PROFILE_END();
getState()->swapInputState();
accum -= GAME_TIMESTEP;
// Throw away time if the accumulator reaches too high.

View File

@ -186,7 +186,18 @@ void IngameState::tick(float dt) {
}
auto player = game->getPlayer();
const auto& input = world->state->input;
auto input = [&](GameInputState::Control c) {
return world->state->input[0][c];
};
auto pressed = [&](GameInputState::Control c) {
return world->state->input[0].pressed(c) &&
!world->state->input[1].pressed(c);
};
auto held = [&](GameInputState::Control c) {
return world->state->input[0].pressed(c);
};
if (player && player->isInputEnabled()) {
float viewDistance = 4.f;
switch (camMode) {
@ -274,8 +285,8 @@ void IngameState::tick(float dt) {
// Non-topdown camera can orbit
if (camMode != IngameState::CAMERA_TOPDOWN) {
bool lookleft = input.pressed(GameInputState::LookLeft);
bool lookright = input.pressed(GameInputState::LookRight);
bool lookleft = held(GameInputState::LookLeft);
bool lookright = held(GameInputState::LookRight);
if ((lookleft || lookright) && vehicle != nullptr) {
auto rotation = vehicle->getRotation();
if (!lookright) {
@ -319,17 +330,17 @@ void IngameState::tick(float dt) {
angle = glm::quat(glm::vec3(0.f, 0.f, angleYaw));
glm::vec3 movement;
movement.x = input[GameInputState::GoForward] -
input[GameInputState::GoBackwards];
movement.x = input(GameInputState::GoForward) -
input(GameInputState::GoBackwards);
movement.y =
input[GameInputState::GoLeft] - input[GameInputState::GoRight];
input(GameInputState::GoLeft) - input(GameInputState::GoRight);
/// @todo replace with correct sprint behaviour
float speed = input.pressed(GameInputState::Sprint) ? 2.f : 1.f;
float speed = held(GameInputState::Sprint) ? 2.f : 1.f;
if (player->isInputEnabled()) {
player->setRunning(!input.pressed(GameInputState::Walk));
player->setRunning(!held(GameInputState::Walk));
/// @todo find the correct behaviour for entering & exiting
if (input.pressed(GameInputState::EnterExitVehicle)) {
if (pressed(GameInputState::EnterExitVehicle)) {
/// @todo move me
if (player->getCharacter()->getCurrentVehicle()) {
player->exitVehicle();
@ -347,11 +358,10 @@ void IngameState::tick(float dt) {
if (player->getCharacter()->getCurrentVehicle()) {
auto vehicle = player->getCharacter()->getCurrentVehicle();
vehicle->setHandbraking(
input.pressed(GameInputState::Handbrake));
vehicle->setHandbraking(held(GameInputState::Handbrake));
player->setMoveDirection(movement);
} else {
if (input.pressed(GameInputState::Jump)) {
if (pressed(GameInputState::Jump)) {
player->jump();
}
@ -495,7 +505,7 @@ void IngameState::updateInputState(const SDL_Event& event) {
case SDL_KEYUP: {
auto sym = event.key.keysym.sym;
auto level = event.type == SDL_KEYDOWN ? 1.f : 0.f;
auto& levels = getWorld()->state->input.currentLevels;
auto& levels = getWorld()->state->input[0].levels;
auto range = kDefaultControls.equal_range(sym);
for (auto it = range.first; it != range.second; ++it) {