1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-18 16:32:32 +02:00

Refactor states

This commit is contained in:
Daniel Evans 2014-05-26 05:34:49 +01:00
parent 623a1f4ce2
commit 6fe65d725b
9 changed files with 378 additions and 279 deletions

View File

@ -1,4 +1,9 @@
add_executable(rwgame main.cpp)
add_executable(rwgame
main.cpp
ingamestate.cpp
pausestate.cpp
menustate.cpp
)
include_directories("${CMAKE_SOURCE_DIR}/rwengine/include" /usr/include/bullet)

28
rwgame/game.hpp Normal file
View File

@ -0,0 +1,28 @@
#ifndef GAME_HPP
#define GAME_HPP
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <engine/GameObject.hpp>
#include <engine/GameWorld.hpp>
constexpr double PiOver180 = 3.1415926535897932384626433832795028/180;
bool hitWorldRay(glm::vec3& hit, glm::vec3& normal, GameObject** object = nullptr);
sf::Window& getWindow();
GameWorld* getWorld();
sf::Font& getFont();
/**
Set view parameters.
*/
void setViewParameters(const glm::vec3& center, const glm::vec2 &angles);
#endif // GAME_HPP

138
rwgame/ingamestate.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "ingamestate.hpp"
#include "game.hpp"
#include "pausestate.hpp"
#include <objects/GTACharacter.hpp>
#include <objects/GTAVehicle.hpp>
IngameState::IngameState()
: _player(nullptr), _playerCharacter(nullptr)
{
_playerCharacter = getWorld()->createPedestrian(1, {100.f, 100.f, 50.f});
_player = new GTAPlayerAIController(_playerCharacter);
}
void IngameState::spawnPlayerVehicle()
{
if(! _player) return;
glm::vec3 hit, normal;
if(hitWorldRay(hit, normal)) {
// Pick random vehicle.
auto it = getWorld()->vehicleTypes.begin();
std::uniform_int_distribution<int> uniform(0, 9);
for(size_t i = 0, n = uniform(getWorld()->randomEngine); i != n; i++) {
it++;
}
auto spawnpos = hit + normal;
auto vehicle = getWorld()->createVehicle(it->first, spawnpos,
glm::quat(glm::vec3(0.f, 0.f, -_lookAngles.x * PiOver180)));
_playerCharacter->enterVehicle(vehicle, 0);
}
}
void IngameState::enter()
{
}
void IngameState::exit()
{
}
void IngameState::tick(float dt)
{
float qpi = glm::half_pi<float>();
sf::Vector2i screenCenter{sf::Vector2i{getWindow().getSize()} / 2};
sf::Vector2i mousePos = sf::Mouse::getPosition(getWindow());
sf::Vector2i deltaMouse = mousePos - screenCenter;
sf::Mouse::setPosition(screenCenter, getWindow());
_lookAngles.x += deltaMouse.x / 100.0;
_lookAngles.y += deltaMouse.y / 100.0;
if (_lookAngles.y > qpi)
_lookAngles.y = qpi;
else if (_lookAngles.y < -qpi)
_lookAngles.y = -qpi;
glm::quat vR = glm::normalize(glm::angleAxis(_lookAngles.x, glm::vec3{0.f, 0.f, 1.f}));
_player->updateMovementDirection(vR * _movement);
float viewDistance = _playerCharacter->getCurrentVehicle() ? -3.5f : -2.5f;
glm::vec3 localView{0.f, -viewDistance, 1.f};
localView = vR * localView;
glm::vec3 viewPos = _playerCharacter->getPosition();
if(_playerCharacter->getCurrentVehicle()) {
viewPos = _playerCharacter->getCurrentVehicle()->getPosition();
}
setViewParameters( viewPos + localView, _lookAngles );
}
void IngameState::handleEvent(const sf::Event &event)
{
switch(event.type) {
case sf::Event::KeyPressed:
switch(event.key.code) {
case sf::Keyboard::Escape:
StateManager::get().enter(new PauseState);
break;
case sf::Keyboard::Space:
if(_playerCharacter) {
_playerCharacter->jump();
}
break;
case sf::Keyboard::W:
_movement.y =-1.f;
break;
case sf::Keyboard::S:
_movement.y = 1.f;
break;
case sf::Keyboard::A:
_movement.x = 1.f;
break;
case sf::Keyboard::D:
_movement.x =-1.f;
break;
case sf::Keyboard::LShift:
_player->setRunning(true);
break;
case sf::Keyboard::F:
if(_playerCharacter) {
if(_playerCharacter->getCurrentVehicle()) {
_player->exitVehicle();
}
else {
_player->enterNearestVehicle();
}
}
break;
default: break;
}
break;
case sf::Event::KeyReleased:
switch(event.key.code) {
case sf::Keyboard::W:
case sf::Keyboard::S:
_movement.y = 0.f;
break;
case sf::Keyboard::A:
case sf::Keyboard::D:
_movement.x = 0.f;
break;
case sf::Keyboard::LShift:
_player->setRunning(false);
break;
default: break;
}
break;
default: break;
}
State::handleEvent(event);
}

29
rwgame/ingamestate.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef INGAMESTATE_HPP
#define INGAMESTATE_HPP
#include "State.hpp"
#include <ai/GTAAIController.hpp>
#include <ai/GTAPlayerAIController.hpp>
class IngameState : public State
{
GTAPlayerAIController* _player;
GTACharacter* _playerCharacter;
glm::vec2 _lookAngles;
glm::vec3 _movement;
public:
IngameState();
void spawnPlayerVehicle();
virtual void enter();
virtual void exit();
virtual void tick(float dt);
virtual void handleEvent(const sf::Event& event);
};
#endif // INGAMESTATE_HPP

View File

@ -5,8 +5,6 @@
#include <loaders/LoaderDFF.hpp>
#include <render/DebugDraw.hpp>
#include <render/Model.hpp>
#include <ai/GTAAIController.hpp>
#include <ai/GTAPlayerAIController.hpp>
#include <objects/GTACharacter.hpp>
#include <objects/GTAVehicle.hpp>
@ -14,54 +12,67 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "MenuSystem.hpp"
#include "State.hpp"
#include "menustate.hpp"
#include <SFML/Graphics.hpp>
#include <memory>
#include <sstream>
#include <iomanip>
#include <getopt.h>
#include <boost/concept_check.hpp>
#include "game.hpp"
#define ENV_GAME_PATH_NAME ("OPENRW_GAME_PATH")
constexpr int WIDTH = 800,
HEIGHT = 600;
constexpr double PiOver180 = 3.1415926535897932384626433832795028/180;
sf::RenderWindow window;
GameWorld* gta = nullptr;
GTAPlayerAIController* player = nullptr;
GTACharacter* playerCharacter = nullptr;
DebugDraw* debugDrawer = nullptr;
GameObject* debugObject = nullptr;
glm::vec3 plyPos(87.f, -932.f, 58.f);
glm::vec2 plyLook;
glm::vec3 movement;
float moveSpeed = 20.0f;
bool inFocus = false;
bool mouseGrabbed = true;
int debugMode = 0;
sf::Font font;
bool showControls = false;
bool hitWorldRay(glm::vec3& hit, glm::vec3& normal, GameObject** object = nullptr)
glm::vec3 viewPosition;
glm::vec2 viewAngles;
void setViewParameters(const glm::vec3 &center, const glm::vec2 &angles)
{
viewPosition = center;
viewAngles = angles;
}
sf::Window& getWindow()
{
return window;
}
GameWorld* getWorld()
{
return gta;
}
sf::Font& getFont()
{
return font;
}
bool hitWorldRay(glm::vec3& hit, glm::vec3& normal, GameObject** object)
{
glm::mat4 view;
view = glm::rotate(view, -90.f, glm::vec3(1, 0, 0));
view = glm::rotate(view, plyLook.y, glm::vec3(1, 0, 0));
view = glm::rotate(view, plyLook.x, glm::vec3(0, 0, 1));
view = glm::rotate(view, viewAngles.y, glm::vec3(1, 0, 0));
view = glm::rotate(view, viewAngles.x, glm::vec3(0, 0, 1));
glm::vec3 dir = glm::inverse(glm::mat3(view)) * glm::vec3(0.f, 0.f, 1.f) * -50.f;
auto from = btVector3(plyPos.x, plyPos.y, plyPos.z);
auto to = btVector3(plyPos.x+dir.x, plyPos.y+dir.y, plyPos.z+dir.z);
auto from = btVector3(viewPosition.x, viewPosition.y, viewPosition.z);
auto to = btVector3(viewPosition.x+dir.x, viewPosition.y+dir.y, viewPosition.z+dir.z);
btCollisionWorld::ClosestRayResultCallback ray(from, to);
gta->dynamicsWorld->rayTest(from, to, ray);
if( ray.hasHit() )
@ -78,19 +89,13 @@ bool hitWorldRay(glm::vec3& hit, glm::vec3& normal, GameObject** object = nullpt
return false;
}
void lockCursor(bool lock)
{
mouseGrabbed = lock;
window.setMouseCursorVisible(! lock);
}
// Commands.
std::map<std::string, std::function<void (std::string)>> Commands = {
{"pedestrian-vehicle",
[&](std::string) {
glm::vec3 hit, normal;
if(hitWorldRay(hit, normal)) {
auto ped = gta->createPedestrian(2, plyPos+glm::vec3(0.f,10.f,0.f));
auto ped = gta->createPedestrian(2, hit+glm::vec3(0.f,10.f,0.f));
// Pick random vehicle.
auto it = gta->vehicleTypes.begin();
std::uniform_int_distribution<int> uniform(0, 9);
@ -98,33 +103,11 @@ std::map<std::string, std::function<void (std::string)>> Commands = {
it++;
}
auto spawnpos = hit + normal;
auto vehicle = gta->createVehicle(it->first, spawnpos, glm::quat(glm::vec3(0.f, 0.f, -plyLook.x * PiOver180)));
auto vehicle = gta->createVehicle(it->first, spawnpos, glm::quat(glm::vec3(0.f, 0.f, -viewAngles.x * PiOver180)));
ped->enterVehicle(vehicle, 0);
}
}
},
{"player-vehicle",
[&](std::string) {
glm::vec3 hit, normal;
if(hitWorldRay(hit, normal)) {
if(! playerCharacter) {
playerCharacter = gta->createPedestrian(1, plyPos+glm::vec3(0.f,10.f,0.f));
player = new GTAPlayerAIController(playerCharacter);
}
// Pick random vehicle.
auto it = gta->vehicleTypes.begin();
std::uniform_int_distribution<int> uniform(0, 9);
for(size_t i = 0, n = uniform(gta->randomEngine); i != n; i++) {
it++;
}
auto spawnpos = hit + normal;
auto vehicle = gta->createVehicle(it->first, spawnpos, glm::quat(glm::vec3(0.f, 0.f, -plyLook.x * PiOver180)));
playerCharacter->enterVehicle(vehicle, 0);
}
}
},
{"empty-vehicle",
[&](std::string) {
glm::vec3 hit, normal;
@ -137,16 +120,10 @@ std::map<std::string, std::function<void (std::string)>> Commands = {
}
auto spawnpos = hit + normal;
gta->createVehicle(it->first, spawnpos, glm::quat(glm::vec3(0.f, 0.f, -plyLook.x * PiOver180)));
gta->createVehicle(it->first, spawnpos, glm::quat(glm::vec3(0.f, 0.f, -viewAngles.x * PiOver180)));
}
}
},
{"player",
[&](std::string) {
playerCharacter = gta->createPedestrian(1, plyPos);
player = new GTAPlayerAIController(playerCharacter);
}
},
{"knock-down",
[&](std::string) {
for(auto it = gta->pedestrians.begin(); it != gta->pedestrians.end(); ++it) {
@ -211,21 +188,6 @@ std::map<std::string, std::function<void (std::string)>> Commands = {
}
}
},
{"create-instance",
[&](std::string line) {
if(line.find(' ') != line.npos) {
std::string ID = line.substr(line.find(' ')+1);
int intID = atoi(ID.c_str());
auto archit = gta->objectTypes.find(intID);
if(archit != gta->objectTypes.end()) {
gta->createInstance(archit->first, plyPos);
}
else {
gta->logInfo("Unkown Object: " + ID);
}
}
}
},
{"object-info",
[&](std::string) {
glm::vec3 hit, normal;
@ -293,63 +255,15 @@ void handleInputEvent(sf::Event &event)
switch(event.type) {
case sf::Event::KeyPressed:
switch (event.key.code) {
case sf::Keyboard::LShift:
moveSpeed = 60.f;
break;
case sf::Keyboard::Space:
if(playerCharacter) {
playerCharacter->jump();
}
break;
case sf::Keyboard::M:
lockCursor(! mouseGrabbed);
break;
case sf::Keyboard::P:
debugMode+=1;
while(debugMode > 2) debugMode -= 3;
break;
case sf::Keyboard::W:
movement.y = -1;
break;
case sf::Keyboard::S:
movement.y = 1;
break;
case sf::Keyboard::A:
movement.x = -1;
break;
case sf::Keyboard::D:
movement.x = 1;
break;
default: break;
}
break;
case sf::Event::KeyReleased:
switch(event.key.code) {
case sf::Keyboard::LShift:
moveSpeed = 20.f;
break;
case sf::Keyboard::W:
movement.y = 0;
break;
case sf::Keyboard::S:
movement.y = 0;
break;
case sf::Keyboard::A:
movement.x = 0;
break;
case sf::Keyboard::D:
movement.x = 0;
break;
case sf::Keyboard::F:
if(playerCharacter) {
if(playerCharacter->getCurrentVehicle()) {
player->exitVehicle();
}
else {
player->enterNearestVehicle();
}
}
break;
default: break;
}
break;
@ -445,72 +359,31 @@ void init(std::string gtapath, bool loadWorld)
void update(float dt)
{
if (inFocus) {
float qpi = glm::half_pi<float>();
if (mouseGrabbed) {
sf::Vector2i screenCenter{sf::Vector2i{window.getSize()} / 2};
sf::Vector2i mousePos = sf::Mouse::getPosition(window);
sf::Vector2i deltaMouse = mousePos - screenCenter;
sf::Mouse::setPosition(screenCenter, window);
plyLook.x += deltaMouse.x / 100.0;
plyLook.y += deltaMouse.y / 100.0;
if (plyLook.y > qpi)
plyLook.y = qpi;
else if (plyLook.y < -qpi)
plyLook.y = -qpi;
}
glm::mat4 view;
view = glm::rotate(view, qpi, glm::vec3(1, 0, 0));
view = glm::rotate(view, plyLook.y, glm::vec3(1, 0, 0));
view = glm::rotate(view, plyLook.x, glm::vec3(0, 0, 1));
if( player != nullptr ) {
glm::quat playerCamera(glm::vec3(0.f, 0.f, -plyLook.x * PiOver180));
player->updateCameraDirection(playerCamera);
player->updateMovementDirection(glm::vec3(movement.x, -movement.y, movement.z));
player->setRunning(moveSpeed > 21.f);
float viewDistance = playerCharacter->getCurrentVehicle() ? -3.5f : -2.5f;
glm::vec3 localView = glm::inverse(glm::mat3(view)) * glm::vec3(0.f, -0.5f, viewDistance);
if(playerCharacter->getCurrentVehicle()) {
plyPos = playerCharacter->getCurrentVehicle()->getPosition();
}
else {
plyPos = playerCharacter->getPosition();
}
view = glm::translate(view, -plyPos + localView);
}
else {
if (glm::length(movement) > 0.f) {
plyPos += dt * moveSpeed * (glm::inverse(glm::mat3(view)) * glm::vec3(movement.x, movement.z, movement.y));
}
view = glm::translate(view, -plyPos);
}
view = glm::translate(view, viewPosition);
view = glm::rotate(view, viewAngles.x, glm::vec3(0, 0, 1));
view = glm::rotate(view, viewAngles.y - qpi, glm::vec3(1, 0, 0));
view = glm::inverse(view);
gta->gameTime += dt;
gta->renderer.camera.worldPos = plyPos;
gta->renderer.camera.worldPos = viewPosition;
gta->renderer.camera.frustum.view = view;
// Update all objects.
for( size_t p = 0; p < gta->pedestrians.size(); ++p) {
for( size_t p = 0; p < gta->pedestrians.size(); ++p) {
gta->pedestrians[p]->tick(dt);
// For the time being, remove anything that isn't the player with no health.
if(gta->pedestrians[p]->mHealth <= 0.f) {
if(gta->pedestrians[p] != playerCharacter) {
if(gta->pedestrians[p] == debugObject) {
debugObject = nullptr;
}
gta->destroyObject(gta->pedestrians[p]);
p--;
if(gta->pedestrians[p] == debugObject) {
debugObject = nullptr;
}
gta->destroyObject(gta->pedestrians[p]);
p--;
}
}
}
for( size_t v = 0; v < gta->vehicleInstances.size(); ++v ) {
gta->vehicleInstances[v]->tick(dt);
if(gta->vehicleInstances[v]->mHealth <= 0.f) {
@ -571,7 +444,7 @@ void render()
ss << std::setfill('0') << "Time: " << std::setw(2) << gta->getHour()
<< ":" << std::setw(2) << gta->getMinute() << std::endl;
ss << "Game Time: " << gta->gameTime << std::endl;
ss << "Camera: " << plyPos.x << " " << plyPos.y << " " << plyPos.z << std::endl;
ss << "Camera: " << viewPosition.x << " " << viewPosition.y << " " << viewPosition.z << std::endl;
if(debugObject) {
auto p = debugObject->getPosition();
@ -653,109 +526,6 @@ void render()
}
}
GenericState pauseState(
[](State* self)
{
Menu *m = new Menu(font);
m->offset = glm::vec2(50.f, 100.f);
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [] { window.close(); }));
self->enterMenu(m);
lockCursor(false);
},
[](State* self, float dt)
{
},
[](State* self)
{
delete self->currentMenu;
},
[](State* self, const sf::Event& e)
{
switch(e.type) {
case sf::Event::KeyPressed:
switch(e.key.code) {
case sf::Keyboard::Escape:
StateManager::get().exit();
break;
default: break;
}
break;
default: break;
}
}
);
GenericState gameState(
[](State* self)
{
lockCursor(true);
// TODO: create game state object
// so we can track if we already
// Started or not.
if(! player) {
command("player");
}
},
[](State* self, float dt)
{
},
[](State* self)
{
},
[](State* self, const sf::Event& e)
{
switch(e.type) {
case sf::Event::KeyPressed:
switch(e.key.code) {
case sf::Keyboard::Escape:
StateManager::get().enter(&pauseState);
break;
default: break;
}
break;
default: break;
}
}
);
GenericState menuState(
[](State* self)
{
Menu *m = new Menu(font);
m->offset = glm::vec2(50.f, 100.f);
m->addEntry(Menu::lambda("Test", [] { StateManager::get().enter(&gameState); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [] { window.close(); }));
self->enterMenu(m);
lockCursor(false);
},
[](State* self, float dt)
{
},
[](State* self)
{
},
[](State* self, const sf::Event& e)
{
switch(e.type) {
case sf::Event::KeyPressed:
switch(e.key.code) {
case sf::Keyboard::Escape:
StateManager::get().exit();
default: break;
}
break;
default: break;
}
}
);
std::string getGamePath()
{
auto v = getenv(ENV_GAME_PATH_NAME);
@ -797,8 +567,10 @@ int main(int argc, char *argv[])
init(getGamePath(), loadWorld);
sf::Clock clock;
MenuState* menuState = new MenuState();
StateManager::get().enter(&menuState);
StateManager::get().enter(menuState);
float accum = 0.f;
float ts = 1.f / 60.f;
@ -817,6 +589,9 @@ int main(int argc, char *argv[])
accum += clock.restart().asSeconds();
while ( accum >= ts ) {
StateManager::get().tick(ts);
update(ts);
accum -= ts;
}

43
rwgame/menustate.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "menustate.hpp"
#include "game.hpp"
#include "ingamestate.hpp"
MenuState::MenuState()
{
Menu *m = new Menu(getFont());
m->offset = glm::vec2(50.f, 100.f);
m->addEntry(Menu::lambda("Test", [] { StateManager::get().enter(new IngameState); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [] { getWindow().close(); }));
this->enterMenu(m);
}
void MenuState::enter()
{
}
void MenuState::exit()
{
}
void MenuState::tick(float dt)
{
}
void MenuState::handleEvent(const sf::Event &e)
{
switch(e.type) {
case sf::Event::KeyPressed:
switch(e.key.code) {
case sf::Keyboard::Escape:
StateManager::get().exit();
default: break;
}
break;
default: break;
}
State::handleEvent(e);
}

19
rwgame/menustate.hpp Normal file
View File

@ -0,0 +1,19 @@
#ifndef MENUSTATE_HPP
#define MENUSTATE_HPP
#include "State.hpp"
class MenuState : public State
{
public:
MenuState();
virtual void enter();
virtual void exit();
virtual void tick(float dt);
virtual void handleEvent(const sf::Event& event);
};
#endif // MENUSTATE_HPP

43
rwgame/pausestate.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "pausestate.hpp"
#include "game.hpp"
PauseState::PauseState()
{
Menu *m = new Menu(getFont());
m->offset = glm::vec2(50.f, 100.f);
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
m->addEntry(Menu::lambda("Exit", [] { getWindow().close(); }));
this->enterMenu(m);
}
void PauseState::enter()
{
}
void PauseState::exit()
{
}
void PauseState::tick(float dt)
{
}
void PauseState::handleEvent(const sf::Event &e)
{
switch(e.type) {
case sf::Event::KeyPressed:
switch(e.key.code) {
case sf::Keyboard::Escape:
StateManager::get().exit();
break;
default: break;
}
break;
default: break;
}
State::handleEvent(e);
}

19
rwgame/pausestate.hpp Normal file
View File

@ -0,0 +1,19 @@
#ifndef PAUSESTATE_HPP
#define PAUSESTATE_HPP
#include "State.hpp"
class PauseState : public State
{
public:
PauseState();
virtual void enter();
virtual void exit();
virtual void tick(float dt);
virtual void handleEvent(const sf::Event& event);
};
#endif // PAUSESTATE_HPP