mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
Move game code into RWGame class and refactor
This commit is contained in:
parent
c3956ac888
commit
f47fad4bc2
@ -1,6 +1,8 @@
|
|||||||
add_executable(rwgame
|
add_executable(rwgame
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
|
RWGame.cpp
|
||||||
|
|
||||||
State.cpp
|
State.cpp
|
||||||
|
|
||||||
loadingstate.cpp
|
loadingstate.cpp
|
||||||
|
292
rwgame/RWGame.cpp
Normal file
292
rwgame/RWGame.cpp
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
#include "RWGame.hpp"
|
||||||
|
#include "State.hpp"
|
||||||
|
#include "loadingstate.hpp"
|
||||||
|
|
||||||
|
#include <engine/GameObject.hpp>
|
||||||
|
#include <render/GameRenderer.hpp>
|
||||||
|
#include <script/ScriptMachine.hpp>
|
||||||
|
|
||||||
|
#include <data/CutsceneData.hpp>
|
||||||
|
#include <ai/PlayerController.hpp>
|
||||||
|
|
||||||
|
RWGame::RWGame(const std::string& gamepath)
|
||||||
|
: engine(nullptr), inFocus(true),
|
||||||
|
accum(0.f), timescale(1.f)
|
||||||
|
{
|
||||||
|
if(! font.loadFromFile(gamepath + "/DejaVuSansMono.ttf")) {
|
||||||
|
std::cerr << "Failed to load font" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t w = GAME_WINDOW_WIDTH, h = GAME_WINDOW_HEIGHT;
|
||||||
|
|
||||||
|
sf::ContextSettings cs;
|
||||||
|
cs.depthBits = 32;
|
||||||
|
window.create(sf::VideoMode(w, h), "", sf::Style::Default, cs);
|
||||||
|
window.setVerticalSyncEnabled(true);
|
||||||
|
window.setMouseCursorVisible(false);
|
||||||
|
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
glewInit();
|
||||||
|
|
||||||
|
engine = new GameWorld(gamepath);
|
||||||
|
|
||||||
|
// Initalize all the archives.
|
||||||
|
engine->gameData.loadIMG("/models/gta3");
|
||||||
|
engine->gameData.loadIMG("/models/txd");
|
||||||
|
engine->gameData.loadIMG("/anim/cuts");
|
||||||
|
|
||||||
|
/// @TODO expand this here.
|
||||||
|
engine->load();
|
||||||
|
|
||||||
|
engine->gameData.loadDynamicObjects(gamepath + "/data/object.dat");
|
||||||
|
|
||||||
|
/// @TODO language choices.
|
||||||
|
engine->gameData.loadGXT("english.gxt");
|
||||||
|
|
||||||
|
StateManager::get().enter(new LoadingState(this));
|
||||||
|
|
||||||
|
engine->logInfo("Started");
|
||||||
|
}
|
||||||
|
|
||||||
|
RWGame::~RWGame()
|
||||||
|
{
|
||||||
|
delete engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RWGame::run()
|
||||||
|
{
|
||||||
|
clock.restart();
|
||||||
|
|
||||||
|
// Loop until the window is closed or we run out of state.
|
||||||
|
while (window.isOpen() && StateManager::get().states.size()) {
|
||||||
|
sf::Event event;
|
||||||
|
while (window.pollEvent(event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case sf::Event::GainedFocus:
|
||||||
|
inFocus = true;
|
||||||
|
break;
|
||||||
|
case sf::Event::LostFocus:
|
||||||
|
inFocus = false;
|
||||||
|
break;
|
||||||
|
case sf::Event::KeyPressed:
|
||||||
|
globalKeyEvent(event);
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
StateManager::get().states.back()->handleEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
accum += clock.restart().asSeconds() * timescale;
|
||||||
|
|
||||||
|
while ( accum >= GAME_TIMESTEP ) {
|
||||||
|
|
||||||
|
StateManager::get().tick(GAME_TIMESTEP);
|
||||||
|
|
||||||
|
tick(GAME_TIMESTEP);
|
||||||
|
accum -= GAME_TIMESTEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
float alpha = accum / GAME_TIMESTEP;
|
||||||
|
|
||||||
|
render(alpha);
|
||||||
|
|
||||||
|
StateManager::get().draw(window);
|
||||||
|
|
||||||
|
window.display();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RWGame::tick(float dt)
|
||||||
|
{
|
||||||
|
// Process the Engine's background work.
|
||||||
|
engine->_work->update();
|
||||||
|
|
||||||
|
static float clockAccumulator = 0.f;
|
||||||
|
if (inFocus) {
|
||||||
|
engine->gameTime += dt;
|
||||||
|
|
||||||
|
clockAccumulator += dt;
|
||||||
|
while( clockAccumulator >= 1.f ) {
|
||||||
|
engine->state.minute ++;
|
||||||
|
if( engine->state.minute >= 60 ) {
|
||||||
|
engine->state.minute = 0;
|
||||||
|
engine->state.hour ++;
|
||||||
|
if( engine->state.hour >= 24 ) {
|
||||||
|
engine->state.hour = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clockAccumulator -= 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( GameObject* object : engine->objects ) {
|
||||||
|
object->_updateLastTransform();
|
||||||
|
object->tick(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
engine->destroyQueuedObjects();
|
||||||
|
engine->state.texts.clear();
|
||||||
|
|
||||||
|
engine->dynamicsWorld->stepSimulation(dt, 2, dt);
|
||||||
|
|
||||||
|
if( engine->script ) {
|
||||||
|
try {
|
||||||
|
engine->script->execute(dt);
|
||||||
|
}
|
||||||
|
catch( SCMException& ex ) {
|
||||||
|
std::cerr << ex.what() << std::endl;
|
||||||
|
engine->logError( ex.what() );
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// render() needs two cameras to smoothly interpolate between ticks.
|
||||||
|
lastCam = nextCam;
|
||||||
|
nextCam = StateManager::get().states.back()->getCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RWGame::render(float alpha)
|
||||||
|
{
|
||||||
|
ViewCamera viewCam;
|
||||||
|
if( engine->state.currentCutscene != nullptr && engine->state.cutsceneStartTime >= 0.f )
|
||||||
|
{
|
||||||
|
auto cutscene = engine->state.currentCutscene;
|
||||||
|
float cutsceneTime = std::min(engine->gameTime - engine->state.cutsceneStartTime,
|
||||||
|
cutscene->tracks.duration);
|
||||||
|
cutsceneTime += GAME_TIMESTEP * alpha;
|
||||||
|
glm::vec3 cameraPos = cutscene->tracks.getPositionAt(cutsceneTime),
|
||||||
|
targetPos = cutscene->tracks.getTargetAt(cutsceneTime);
|
||||||
|
float zoom = cutscene->tracks.getZoomAt(cutsceneTime);
|
||||||
|
viewCam.frustum.fov = glm::radians(zoom);
|
||||||
|
float tilt = cutscene->tracks.getRotationAt(cutsceneTime);
|
||||||
|
|
||||||
|
auto direction = glm::normalize(targetPos - cameraPos);
|
||||||
|
auto right = glm::normalize(glm::cross(glm::vec3(0.f, 0.f, 1.f), direction));
|
||||||
|
auto up = glm::normalize(glm::cross(direction, right));
|
||||||
|
|
||||||
|
glm::mat3 m;
|
||||||
|
m[0][0] = direction.x;
|
||||||
|
m[0][1] = right.x;
|
||||||
|
m[0][2] = up.x;
|
||||||
|
|
||||||
|
m[1][0] = direction.y;
|
||||||
|
m[1][1] = right.y;
|
||||||
|
m[1][2] = up.y;
|
||||||
|
|
||||||
|
m[2][0] = direction.z;
|
||||||
|
m[2][1] = right.z;
|
||||||
|
m[2][2] = up.z;
|
||||||
|
|
||||||
|
auto qtilt = glm::angleAxis(glm::radians(tilt), direction);
|
||||||
|
|
||||||
|
cameraPos += cutscene->meta.sceneOffset;
|
||||||
|
targetPos += cutscene->meta.sceneOffset;
|
||||||
|
|
||||||
|
viewCam.position = cameraPos;
|
||||||
|
viewCam.rotation = glm::inverse(glm::quat_cast(m)) * qtilt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There's no cutscene playing - use the camera returned by the State.
|
||||||
|
viewCam.position = glm::mix(lastCam.position, nextCam.position, alpha);
|
||||||
|
viewCam.rotation = glm::slerp(lastCam.rotation, nextCam.rotation, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewCam.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
engine->renderer.renderWorld(viewCam, alpha);
|
||||||
|
|
||||||
|
window.resetGLStates();
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::setfill('0') << "Time: " << std::setw(2) << engine->getHour()
|
||||||
|
<< ":" << std::setw(2) << engine->getMinute() << " (" << engine->gameTime << "s)\n";
|
||||||
|
ss << "View: " << viewCam.position.x << " " << viewCam.position.y << " " << viewCam.position.z << "\n";
|
||||||
|
ss << "Drawn " << engine->renderer.rendered << " / " << engine->renderer.culled << " Culled " << " " << engine->renderer.frames << " " << engine->renderer.geoms << "\n";
|
||||||
|
if( engine->state.player ) {
|
||||||
|
ss << "Activity: ";
|
||||||
|
if( engine->state.player->getCurrentActivity() ) {
|
||||||
|
ss << engine->state.player->getCurrentActivity()->name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ss << "Idle";
|
||||||
|
}
|
||||||
|
ss << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Text text(ss.str(), font, 14);
|
||||||
|
text.setPosition(10, 10);
|
||||||
|
window.draw(text);
|
||||||
|
|
||||||
|
while( engine->log.size() > 0 && engine->log.front().time + 10.f < engine->gameTime ) {
|
||||||
|
engine->log.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Vector2f tpos(10.f, window.getSize().y - 30.f);
|
||||||
|
text.setCharacterSize(14);
|
||||||
|
for(auto it = engine->log.begin(); it != engine->log.end(); ++it) {
|
||||||
|
text.setString(it->message);
|
||||||
|
switch(it->type) {
|
||||||
|
case GameWorld::LogEntry::Error:
|
||||||
|
text.setColor(sf::Color::Red);
|
||||||
|
break;
|
||||||
|
case GameWorld::LogEntry::Warning:
|
||||||
|
text.setColor(sf::Color::Yellow);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
text.setColor(sf::Color::White);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolate the color
|
||||||
|
auto c = text.getColor();
|
||||||
|
c.a = (engine->gameTime - it->time > 5.f) ? 255 - (((engine->gameTime - it->time) - 5.f)/5.f) * 255 : 255;
|
||||||
|
text.setColor(c);
|
||||||
|
|
||||||
|
text.setPosition(tpos);
|
||||||
|
window.draw(text);
|
||||||
|
tpos.y -= text.getLocalBounds().height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @todo this should be done by GameRenderer? but it doesn't have any font support yet
|
||||||
|
if( engine->gameTime < engine->state.osTextStart + engine->state.osTextTime ) {
|
||||||
|
sf::Text messageText(engine->state.osTextString, font, 15);
|
||||||
|
auto sz = window.getSize();
|
||||||
|
|
||||||
|
auto b = messageText.getLocalBounds();
|
||||||
|
float lowerBar = sz.y - sz.y * 0.1f;
|
||||||
|
messageText.setPosition(sz.x / 2.f - std::round(b.width / 2.f), lowerBar - std::round(b.height / 2.f));
|
||||||
|
window.draw(messageText);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& t : engine->state.texts) {
|
||||||
|
sf::Text messageText(t.text, font, 15);
|
||||||
|
|
||||||
|
glm::vec2 scpos(t.position.x, t.position.y);
|
||||||
|
auto s = window.getSize();
|
||||||
|
scpos /= glm::vec2(640.f, 480.f);
|
||||||
|
scpos *= glm::vec2(s.x, s.y);
|
||||||
|
|
||||||
|
messageText.setPosition(scpos.x, scpos.y);
|
||||||
|
|
||||||
|
window.draw(messageText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RWGame::globalKeyEvent(const sf::Event& event)
|
||||||
|
{
|
||||||
|
switch (event.key.code) {
|
||||||
|
case sf::Keyboard::LBracket:
|
||||||
|
engine->state.minute -= 30.f;
|
||||||
|
break;
|
||||||
|
case sf::Keyboard::RBracket:
|
||||||
|
engine->state.minute += 30.f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
79
rwgame/RWGame.hpp
Normal file
79
rwgame/RWGame.hpp
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef _RWGAME_HPP_
|
||||||
|
#define _RWGAME_HPP_
|
||||||
|
#include <engine/GameWorld.hpp>
|
||||||
|
#include "game.hpp"
|
||||||
|
|
||||||
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
class RWGame
|
||||||
|
{
|
||||||
|
GameWorld* engine;
|
||||||
|
sf::RenderWindow window;
|
||||||
|
sf::Clock clock;
|
||||||
|
bool inFocus;
|
||||||
|
ViewCamera lastCam, nextCam;
|
||||||
|
|
||||||
|
float accum;
|
||||||
|
float timescale;
|
||||||
|
|
||||||
|
sf::Font font;
|
||||||
|
public:
|
||||||
|
|
||||||
|
RWGame(const std::string& gamepath);
|
||||||
|
~RWGame();
|
||||||
|
|
||||||
|
int run();
|
||||||
|
|
||||||
|
GameWorld* getWorld() const
|
||||||
|
{
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::RenderWindow& getWindow()
|
||||||
|
{
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Font& getFont()
|
||||||
|
{
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hitWorldRay(glm::vec3 &hit, glm::vec3 &normal, GameObject** object = nullptr)
|
||||||
|
{
|
||||||
|
auto vc = nextCam;
|
||||||
|
glm::vec3 from(vc.position.x, vc.position.y, vc.position.z);
|
||||||
|
glm::vec3 tmp = vc.rotation * glm::vec3(1000.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
return hitWorldRay(from, tmp, hit, normal, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hitWorldRay(const glm::vec3 &start, const glm::vec3 &direction, glm::vec3 &hit, glm::vec3 &normal, GameObject **object = nullptr)
|
||||||
|
{
|
||||||
|
auto from = btVector3(start.x, start.y, start.z);
|
||||||
|
auto to = btVector3(start.x+direction.x, start.y+direction.y, start.z+direction.z);
|
||||||
|
btCollisionWorld::ClosestRayResultCallback ray(from, to);
|
||||||
|
|
||||||
|
engine->dynamicsWorld->rayTest(from, to, ray);
|
||||||
|
if( ray.hasHit() )
|
||||||
|
{
|
||||||
|
hit = glm::vec3(ray.m_hitPointWorld.x(), ray.m_hitPointWorld.y(),
|
||||||
|
ray.m_hitPointWorld.z());
|
||||||
|
normal = glm::vec3(ray.m_hitNormalWorld.x(), ray.m_hitNormalWorld.y(),
|
||||||
|
ray.m_hitNormalWorld.z());
|
||||||
|
if(object) {
|
||||||
|
*object = static_cast<GameObject*>(ray.m_collisionObject->getUserPointer());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void tick(float dt);
|
||||||
|
void render(float alpha);
|
||||||
|
|
||||||
|
void globalKeyEvent(const sf::Event& event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
#include "State.hpp"
|
#include "State.hpp"
|
||||||
|
#include "RWGame.hpp"
|
||||||
|
|
||||||
// This serves as the "initial" camera position.
|
// This serves as the "initial" camera position.
|
||||||
ViewCamera defaultView({-250.f, -550.f, 75.f}, glm::angleAxis(glm::radians(5.f), glm::vec3(0.f, 1.f, 0.f)));
|
ViewCamera defaultView({-250.f, -550.f, 75.f}, glm::angleAxis(glm::radians(5.f), glm::vec3(0.f, 1.f, 0.f)));
|
||||||
@ -7,3 +8,13 @@ const ViewCamera& State::getCamera()
|
|||||||
{
|
{
|
||||||
return defaultView;
|
return defaultView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GameWorld* State::getWorld()
|
||||||
|
{
|
||||||
|
return game->getWorld();
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::RenderWindow& State::getWindow()
|
||||||
|
{
|
||||||
|
return game->getWindow();
|
||||||
|
}
|
||||||
|
@ -7,14 +7,19 @@
|
|||||||
#include "MenuSystem.hpp"
|
#include "MenuSystem.hpp"
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
|
class RWGame;
|
||||||
|
class GameWorld;
|
||||||
|
|
||||||
struct State
|
struct State
|
||||||
{
|
{
|
||||||
// Helper for global menu behaviour
|
// Helper for global menu behaviour
|
||||||
Menu* currentMenu;
|
Menu* currentMenu;
|
||||||
Menu* nextMenu;
|
Menu* nextMenu;
|
||||||
|
|
||||||
State()
|
RWGame* game;
|
||||||
: currentMenu(nullptr), nextMenu(nullptr) {}
|
|
||||||
|
State(RWGame* game)
|
||||||
|
: currentMenu(nullptr), nextMenu(nullptr), game(game) {}
|
||||||
|
|
||||||
virtual void enter() = 0;
|
virtual void enter() = 0;
|
||||||
virtual void exit() = 0;
|
virtual void exit() = 0;
|
||||||
@ -80,6 +85,9 @@ struct State
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual const ViewCamera& getCamera();
|
virtual const ViewCamera& getCamera();
|
||||||
|
|
||||||
|
GameWorld* getWorld();
|
||||||
|
sf::RenderWindow& getWindow();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StateManager
|
struct StateManager
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
#include "debugstate.hpp"
|
#include "debugstate.hpp"
|
||||||
#include "game.hpp"
|
#include "RWGame.hpp"
|
||||||
#include <ai/PlayerController.hpp>
|
#include <ai/PlayerController.hpp>
|
||||||
#include <objects/CharacterObject.hpp>
|
#include <objects/CharacterObject.hpp>
|
||||||
#include <objects/VehicleObject.hpp>
|
#include <objects/VehicleObject.hpp>
|
||||||
|
|
||||||
DebugState::DebugState(const glm::vec3& vp, const glm::quat& vd)
|
DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
|
||||||
: _freeLook( false ), _sonicMode( false )
|
: State(game), _freeLook( false ), _sonicMode( false )
|
||||||
{
|
{
|
||||||
Menu *m = new Menu(getFont());
|
Menu *m = new Menu(game->getFont());
|
||||||
m->offset = glm::vec2(50.f, 100.f);
|
m->offset = glm::vec2(50.f, 100.f);
|
||||||
float entryHeight = 24.f;
|
float entryHeight = 24.f;
|
||||||
m->addEntry(Menu::lambda("Random Vehicle", [this] {
|
m->addEntry(Menu::lambda("Random Vehicle", [this] {
|
||||||
@ -18,7 +18,7 @@ DebugState::DebugState(const glm::vec3& vp, const glm::quat& vd)
|
|||||||
}
|
}
|
||||||
spawnVehicle(it->first);
|
spawnVehicle(it->first);
|
||||||
}, entryHeight));
|
}, entryHeight));
|
||||||
m->addEntry(Menu::lambda("Open All Doors/Flaps", [this] {
|
m->addEntry(Menu::lambda("Open All Doors/Flaps", [=] {
|
||||||
auto pc = getWorld()->state.player->getCharacter();
|
auto pc = getWorld()->state.player->getCharacter();
|
||||||
auto pv = pc->getCurrentVehicle();
|
auto pv = pc->getCurrentVehicle();
|
||||||
if( pv ) {
|
if( pv ) {
|
||||||
@ -28,9 +28,9 @@ DebugState::DebugState(const glm::vec3& vp, const glm::quat& vd)
|
|||||||
}
|
}
|
||||||
}, entryHeight));
|
}, entryHeight));
|
||||||
|
|
||||||
m->addEntry(Menu::lambda("Spawn Pedestrians", [this] {
|
m->addEntry(Menu::lambda("Spawn Pedestrians", [=] {
|
||||||
glm::vec3 hit, normal;
|
glm::vec3 hit, normal;
|
||||||
if(hitWorldRay(hit, normal)) {
|
if(game->hitWorldRay(hit, normal)) {
|
||||||
glm::vec3 spawnPos = hit + glm::vec3(-5, 0.f, 0.0) + normal;
|
glm::vec3 spawnPos = hit + glm::vec3(-5, 0.f, 0.0) + normal;
|
||||||
size_t k = 1;
|
size_t k = 1;
|
||||||
// Spawn every pedestrian.
|
// Spawn every pedestrian.
|
||||||
@ -175,7 +175,7 @@ void DebugState::spawnVehicle(unsigned int id)
|
|||||||
glm::vec3 fwd = ch->rotation * glm::vec3(0.f, 1.f, 0.f);
|
glm::vec3 fwd = ch->rotation * glm::vec3(0.f, 1.f, 0.f);
|
||||||
|
|
||||||
glm::vec3 hit, normal;
|
glm::vec3 hit, normal;
|
||||||
if(hitWorldRay(ch->position + (fwd * 5.f), {0.f, 0.f, -2.f}, hit, normal)) {
|
if(game->hitWorldRay(ch->position + (fwd * 5.f), {0.f, 0.f, -2.f}, hit, normal)) {
|
||||||
auto spawnpos = hit + normal;
|
auto spawnpos = hit + normal;
|
||||||
getWorld()->createVehicle(id, spawnpos, glm::quat());
|
getWorld()->createVehicle(id, spawnpos, glm::quat());
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ class DebugState : public State
|
|||||||
bool _freeLook;
|
bool _freeLook;
|
||||||
bool _sonicMode;
|
bool _sonicMode;
|
||||||
public:
|
public:
|
||||||
DebugState(const glm::vec3& vp = {}, const glm::quat& vd = {});
|
DebugState(RWGame* game, const glm::vec3& vp = {}, const glm::quat& vd = {});
|
||||||
|
|
||||||
virtual void enter();
|
virtual void enter();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <engine/GameObject.hpp>
|
#include <engine/GameObject.hpp>
|
||||||
#include <engine/GameWorld.hpp>
|
#include <engine/GameWorld.hpp>
|
||||||
|
|
||||||
|
|
||||||
constexpr double PiOver180 = 3.1415926535897932384626433832795028/180;
|
constexpr double PiOver180 = 3.1415926535897932384626433832795028/180;
|
||||||
|
|
||||||
// TODO: Move all of this stuff so it's not just lying around.
|
// TODO: Move all of this stuff so it's not just lying around.
|
||||||
@ -15,13 +14,10 @@ bool hitWorldRay(glm::vec3& hit, glm::vec3& normal, GameObject** object = nullpt
|
|||||||
bool hitWorldRay(const glm::vec3& start, const glm::vec3& direction,
|
bool hitWorldRay(const glm::vec3& start, const glm::vec3& direction,
|
||||||
glm::vec3& hit, glm::vec3& normal, GameObject** object = nullptr);
|
glm::vec3& hit, glm::vec3& normal, GameObject** object = nullptr);
|
||||||
|
|
||||||
sf::Window& getWindow();
|
#define ENV_GAME_PATH_NAME ("OPENRW_GAME_PATH")
|
||||||
|
#define GAME_TIMESTEP (1.f/30.f)
|
||||||
GameWorld* getWorld();
|
#define GAME_WINDOW_WIDTH 800
|
||||||
|
#define GAME_WINDOW_HEIGHT 600
|
||||||
sf::Font& getFont();
|
|
||||||
|
|
||||||
void skipTime(float time);
|
|
||||||
|
|
||||||
#endif // GAME_HPP
|
#endif // GAME_HPP
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "ingamestate.hpp"
|
#include "ingamestate.hpp"
|
||||||
#include "game.hpp"
|
#include "RWGame.hpp"
|
||||||
#include "pausestate.hpp"
|
#include "pausestate.hpp"
|
||||||
#include "debugstate.hpp"
|
#include "debugstate.hpp"
|
||||||
|
|
||||||
@ -10,7 +10,8 @@
|
|||||||
#include <render/Model.hpp>
|
#include <render/Model.hpp>
|
||||||
#include <items/WeaponItem.hpp>
|
#include <items/WeaponItem.hpp>
|
||||||
|
|
||||||
IngameState::IngameState(bool test)
|
IngameState::IngameState(RWGame* game, bool test)
|
||||||
|
: State(game)
|
||||||
{
|
{
|
||||||
if( test ) {
|
if( test ) {
|
||||||
startTest();
|
startTest();
|
||||||
@ -67,7 +68,7 @@ void IngameState::spawnPlayerVehicle()
|
|||||||
{
|
{
|
||||||
if(! getWorld()->state.player ) return;
|
if(! getWorld()->state.player ) return;
|
||||||
glm::vec3 hit, normal;
|
glm::vec3 hit, normal;
|
||||||
if(hitWorldRay(hit, normal)) {
|
if(game->hitWorldRay(hit, normal)) {
|
||||||
|
|
||||||
// Pick random vehicle.
|
// Pick random vehicle.
|
||||||
auto it = getWorld()->vehicleTypes.begin();
|
auto it = getWorld()->vehicleTypes.begin();
|
||||||
@ -226,10 +227,10 @@ void IngameState::handleEvent(const sf::Event &event)
|
|||||||
case sf::Event::KeyPressed:
|
case sf::Event::KeyPressed:
|
||||||
switch(event.key.code) {
|
switch(event.key.code) {
|
||||||
case sf::Keyboard::Escape:
|
case sf::Keyboard::Escape:
|
||||||
StateManager::get().enter(new PauseState);
|
StateManager::get().enter(new PauseState(game));
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::M:
|
case sf::Keyboard::M:
|
||||||
StateManager::get().enter(new DebugState(_look.position, _look.rotation));
|
StateManager::get().enter(new DebugState(game, _look.position, _look.rotation));
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::Space:
|
case sf::Keyboard::Space:
|
||||||
if( player ) {
|
if( player ) {
|
||||||
@ -277,9 +278,6 @@ void IngameState::handleEvent(const sf::Event &event)
|
|||||||
case sf::Keyboard::LShift:
|
case sf::Keyboard::LShift:
|
||||||
player->setRunning(false);
|
player->setRunning(false);
|
||||||
break;
|
break;
|
||||||
case sf::Keyboard::F12:
|
|
||||||
skipTime(10.f);
|
|
||||||
break;
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -11,7 +11,7 @@ class IngameState : public State
|
|||||||
glm::vec2 _lookAngles;
|
glm::vec2 _lookAngles;
|
||||||
glm::vec3 _movement;
|
glm::vec3 _movement;
|
||||||
public:
|
public:
|
||||||
IngameState(bool test = false);
|
IngameState(RWGame* game, bool test = false);
|
||||||
|
|
||||||
void startTest();
|
void startTest();
|
||||||
void spawnPlayerVehicle();
|
void spawnPlayerVehicle();
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "loadingstate.hpp"
|
#include "loadingstate.hpp"
|
||||||
#include "menustate.hpp"
|
#include "menustate.hpp"
|
||||||
#include "game.hpp"
|
#include "RWGame.hpp"
|
||||||
|
|
||||||
LoadingState::LoadingState()
|
LoadingState::LoadingState(RWGame* game)
|
||||||
|
: State(game)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ void LoadingState::tick(float dt)
|
|||||||
// Check to see if the GameWorld has run out of jobs
|
// Check to see if the GameWorld has run out of jobs
|
||||||
// (i.e. it's time to open the main menu)
|
// (i.e. it's time to open the main menu)
|
||||||
if( getWorld()->_work->isEmpty() ) {
|
if( getWorld()->_work->isEmpty() ) {
|
||||||
StateManager::get().exec(new MenuState);
|
StateManager::get().exec(new MenuState(game));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ void LoadingState::handleEvent(const sf::Event &e)
|
|||||||
void LoadingState::draw(sf::RenderWindow &w)
|
void LoadingState::draw(sf::RenderWindow &w)
|
||||||
{
|
{
|
||||||
// Display some manner of loading screen.
|
// Display some manner of loading screen.
|
||||||
sf::Text loadingText("Loading...", getFont(), 28);
|
sf::Text loadingText("Loading...", game->getFont(), 28);
|
||||||
loadingText.setPosition({30.f, 20.f});
|
loadingText.setPosition({30.f, 20.f});
|
||||||
w.draw(loadingText);
|
w.draw(loadingText);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
class LoadingState : public State
|
class LoadingState : public State
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LoadingState();
|
LoadingState(RWGame* game);
|
||||||
|
|
||||||
virtual void enter();
|
virtual void enter();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
472
rwgame/main.cpp
472
rwgame/main.cpp
@ -1,408 +1,7 @@
|
|||||||
#define GLEW_STATIC
|
#define GLEW_STATIC
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include <engine/GameWorld.hpp>
|
#include "RWGame.hpp"
|
||||||
#include <loaders/LoaderDFF.hpp>
|
|
||||||
#include <render/DebugDraw.hpp>
|
|
||||||
#include <render/Model.hpp>
|
|
||||||
#include <objects/VehicleObject.hpp>
|
|
||||||
#include <objects/CharacterObject.hpp>
|
|
||||||
#include <objects/InstanceObject.hpp>
|
|
||||||
#include <ai/PlayerController.hpp>
|
|
||||||
|
|
||||||
#include <script/ScriptMachine.hpp>
|
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
#include <data/CutsceneData.hpp>
|
|
||||||
|
|
||||||
#include "loadingstate.hpp"
|
|
||||||
#include <SFML/Graphics.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include "game.hpp"
|
|
||||||
|
|
||||||
#define ENV_GAME_PATH_NAME ("OPENRW_GAME_PATH")
|
|
||||||
#define GAME_TIMESTEP (1.f/30.f)
|
|
||||||
|
|
||||||
constexpr int WIDTH = 800,
|
|
||||||
HEIGHT = 600;
|
|
||||||
|
|
||||||
sf::RenderWindow window;
|
|
||||||
|
|
||||||
GameWorld* gta = nullptr;
|
|
||||||
|
|
||||||
DebugDraw* debugDrawer = nullptr;
|
|
||||||
|
|
||||||
bool inFocus = true;
|
|
||||||
int debugMode = 0;
|
|
||||||
float accum = 0.f;
|
|
||||||
|
|
||||||
// Camera poisitions to interpolate between ticks.
|
|
||||||
ViewCamera lastCam, nextCam;
|
|
||||||
|
|
||||||
sf::Font font;
|
|
||||||
|
|
||||||
sf::Window& getWindow()
|
|
||||||
{
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameWorld* getWorld()
|
|
||||||
{
|
|
||||||
return gta;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Font& getFont()
|
|
||||||
{
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
void skipTime(float time)
|
|
||||||
{
|
|
||||||
accum += time;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hitWorldRay(glm::vec3 &hit, glm::vec3 &normal, GameObject** object)
|
|
||||||
{
|
|
||||||
const ViewCamera& vc = StateManager::get().states.back()->getCamera();
|
|
||||||
btVector3 from(vc.position.x, vc.position.y, vc.position.z);
|
|
||||||
glm::vec3 tmp = vc.rotation * glm::vec3(1000.f, 0.f, 0.f);
|
|
||||||
btVector3 to(from.x() + tmp.x, from.y() + tmp.y, from.x() + tmp.z);
|
|
||||||
|
|
||||||
btCollisionWorld::ClosestRayResultCallback ray(from, to);
|
|
||||||
gta->dynamicsWorld->rayTest(from, to, ray);
|
|
||||||
if( ray.hasHit() )
|
|
||||||
{
|
|
||||||
hit = glm::vec3(ray.m_hitPointWorld.x(), ray.m_hitPointWorld.y(),
|
|
||||||
ray.m_hitPointWorld.z());
|
|
||||||
normal = glm::vec3(ray.m_hitNormalWorld.x(), ray.m_hitNormalWorld.y(),
|
|
||||||
ray.m_hitNormalWorld.z());
|
|
||||||
if(object) {
|
|
||||||
*object = static_cast<GameObject*>(ray.m_collisionObject->getUserPointer());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hitWorldRay(const glm::vec3 &start, const glm::vec3 &direction, glm::vec3 &hit, glm::vec3 &normal, GameObject **object)
|
|
||||||
{
|
|
||||||
auto from = btVector3(start.x, start.y, start.z);
|
|
||||||
auto to = btVector3(start.x+direction.x, start.y+direction.y, start.z+direction.z);
|
|
||||||
btCollisionWorld::ClosestRayResultCallback ray(from, to);
|
|
||||||
gta->dynamicsWorld->rayTest(from, to, ray);
|
|
||||||
if( ray.hasHit() )
|
|
||||||
{
|
|
||||||
hit = glm::vec3(ray.m_hitPointWorld.x(), ray.m_hitPointWorld.y(),
|
|
||||||
ray.m_hitPointWorld.z());
|
|
||||||
normal = glm::vec3(ray.m_hitNormalWorld.x(), ray.m_hitNormalWorld.y(),
|
|
||||||
ray.m_hitNormalWorld.z());
|
|
||||||
if(object) {
|
|
||||||
*object = static_cast<GameObject*>(ray.m_collisionObject->getUserPointer());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleGlobalEvent(sf::Event &event)
|
|
||||||
{
|
|
||||||
switch (event.type) {
|
|
||||||
case sf::Event::KeyPressed:
|
|
||||||
break;
|
|
||||||
case sf::Event::GainedFocus:
|
|
||||||
inFocus = true;
|
|
||||||
break;
|
|
||||||
case sf::Event::LostFocus:
|
|
||||||
inFocus = false;
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleInputEvent(sf::Event &event)
|
|
||||||
{
|
|
||||||
switch(event.type) {
|
|
||||||
case sf::Event::KeyPressed:
|
|
||||||
switch (event.key.code) {
|
|
||||||
case sf::Keyboard::P:
|
|
||||||
debugMode+=1;
|
|
||||||
while(debugMode > 2) debugMode -= 3;
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case sf::Event::KeyReleased:
|
|
||||||
switch(event.key.code) {
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleCommandEvent(sf::Event &event)
|
|
||||||
{
|
|
||||||
switch(event.type) {
|
|
||||||
case sf::Event::KeyPressed:
|
|
||||||
switch (event.key.code) {
|
|
||||||
case sf::Keyboard::LBracket:
|
|
||||||
gta->state.minute -= 30.f;
|
|
||||||
break;
|
|
||||||
case sf::Keyboard::RBracket:
|
|
||||||
gta->state.minute += 30.f;
|
|
||||||
break;
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init(std::string gtapath)
|
|
||||||
{
|
|
||||||
// GTA GET
|
|
||||||
gta = new GameWorld(gtapath);
|
|
||||||
|
|
||||||
// This is harcoded in GTA III for some reason
|
|
||||||
gta->gameData.loadIMG("/models/gta3");
|
|
||||||
gta->gameData.loadIMG("/models/txd");
|
|
||||||
gta->gameData.loadIMG("/anim/cuts");
|
|
||||||
|
|
||||||
gta->load();
|
|
||||||
|
|
||||||
// Load dynamic object data
|
|
||||||
gta->gameData.loadDynamicObjects(gtapath + "/data/object.dat");
|
|
||||||
|
|
||||||
gta->gameData.loadGXT("english.gxt");
|
|
||||||
|
|
||||||
gta->gameTime = 0.f;
|
|
||||||
|
|
||||||
debugDrawer = new DebugDraw;
|
|
||||||
//debugDrawer->setShaderProgram(gta->renderer.worldProgram);
|
|
||||||
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
|
||||||
gta->dynamicsWorld->setDebugDrawer(debugDrawer);
|
|
||||||
|
|
||||||
//setViewParameters( { -260.f, -151.5f, 9.f }, { -0.3f, 0.05f } );
|
|
||||||
|
|
||||||
std::cout << "Loaded "
|
|
||||||
<< gta->gameData.models.size() << " models, "
|
|
||||||
<< gta->gameData.textures.size() << " textures" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(float dt)
|
|
||||||
{
|
|
||||||
gta->_work->update();
|
|
||||||
|
|
||||||
static float clockAccumulator = 0.f;
|
|
||||||
if (inFocus) {
|
|
||||||
gta->gameTime += dt;
|
|
||||||
|
|
||||||
clockAccumulator += dt;
|
|
||||||
while( clockAccumulator >= 1.f ) {
|
|
||||||
gta->state.minute ++;
|
|
||||||
if( gta->state.minute >= 60 ) {
|
|
||||||
gta->state.minute = 0;
|
|
||||||
gta->state.hour ++;
|
|
||||||
if( gta->state.hour >= 24 ) {
|
|
||||||
gta->state.hour = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clockAccumulator -= 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( GameObject* object : gta->objects ) {
|
|
||||||
object->_updateLastTransform();
|
|
||||||
object->tick(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
gta->destroyQueuedObjects();
|
|
||||||
gta->state.texts.clear();
|
|
||||||
|
|
||||||
gta->dynamicsWorld->stepSimulation(dt, 2, dt);
|
|
||||||
|
|
||||||
if( getWorld()->script ) {
|
|
||||||
try {
|
|
||||||
getWorld()->script->execute(dt);
|
|
||||||
}
|
|
||||||
catch( SCMException& ex ) {
|
|
||||||
std::cerr << ex.what() << std::endl;
|
|
||||||
getWorld()->logError( ex.what() );
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// render() needs two cameras to smoothly interpolate between ticks.
|
|
||||||
lastCam = nextCam;
|
|
||||||
nextCam = StateManager::get().states.back()->getCamera();
|
|
||||||
}
|
|
||||||
|
|
||||||
void render(float alpha)
|
|
||||||
{
|
|
||||||
ViewCamera viewCam;
|
|
||||||
if( gta->state.currentCutscene != nullptr && gta->state.cutsceneStartTime >= 0.f )
|
|
||||||
{
|
|
||||||
auto cutscene = gta->state.currentCutscene;
|
|
||||||
float cutsceneTime = std::min(gta->gameTime - gta->state.cutsceneStartTime,
|
|
||||||
cutscene->tracks.duration);
|
|
||||||
cutsceneTime += GAME_TIMESTEP * alpha;
|
|
||||||
glm::vec3 cameraPos = cutscene->tracks.getPositionAt(cutsceneTime),
|
|
||||||
targetPos = cutscene->tracks.getTargetAt(cutsceneTime);
|
|
||||||
float zoom = cutscene->tracks.getZoomAt(cutsceneTime);
|
|
||||||
viewCam.frustum.fov = glm::radians(zoom);
|
|
||||||
float tilt = cutscene->tracks.getRotationAt(cutsceneTime);
|
|
||||||
|
|
||||||
auto direction = glm::normalize(targetPos - cameraPos);
|
|
||||||
auto right = glm::normalize(glm::cross(glm::vec3(0.f, 0.f, 1.f), direction));
|
|
||||||
auto up = glm::normalize(glm::cross(direction, right));
|
|
||||||
|
|
||||||
glm::mat3 m;
|
|
||||||
m[0][0] = direction.x;
|
|
||||||
m[0][1] = right.x;
|
|
||||||
m[0][2] = up.x;
|
|
||||||
|
|
||||||
m[1][0] = direction.y;
|
|
||||||
m[1][1] = right.y;
|
|
||||||
m[1][2] = up.y;
|
|
||||||
|
|
||||||
m[2][0] = direction.z;
|
|
||||||
m[2][1] = right.z;
|
|
||||||
m[2][2] = up.z;
|
|
||||||
|
|
||||||
auto qtilt = glm::angleAxis(glm::radians(tilt), direction);
|
|
||||||
|
|
||||||
cameraPos += cutscene->meta.sceneOffset;
|
|
||||||
targetPos += cutscene->meta.sceneOffset;
|
|
||||||
|
|
||||||
viewCam.position = cameraPos;
|
|
||||||
viewCam.rotation = glm::inverse(glm::quat_cast(m)) * qtilt;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// There's no cutscene playing - use the camera returned by the State.
|
|
||||||
viewCam.position = glm::mix(lastCam.position, nextCam.position, alpha);
|
|
||||||
viewCam.rotation = glm::slerp(lastCam.rotation, nextCam.rotation, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
viewCam.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y;
|
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
gta->renderer.renderWorld(viewCam, alpha);
|
|
||||||
|
|
||||||
switch( debugMode ) {
|
|
||||||
case 0: break;
|
|
||||||
|
|
||||||
case 1: {
|
|
||||||
//glUseProgram(gta->renderer.worldProgram);
|
|
||||||
/*gta->renderer.uploadUBO<ObjectUniformData>(
|
|
||||||
gta->renderer.uboObject, {
|
|
||||||
glm::mat4(),
|
|
||||||
glm::vec4(1.f),
|
|
||||||
1.f, 1.f
|
|
||||||
});*/
|
|
||||||
gta->renderer.renderPaths();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
//glUseProgram(gta->renderer.worldProgram);
|
|
||||||
/*gta->renderer.uploadUBO<ObjectUniformData>(
|
|
||||||
gta->renderer.uboObject, {
|
|
||||||
glm::mat4(),
|
|
||||||
glm::vec4(1.f),
|
|
||||||
1.f, 1.f
|
|
||||||
});*/
|
|
||||||
gta->dynamicsWorld->debugDrawWorld();
|
|
||||||
debugDrawer->drawAllLines();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.resetGLStates();
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::setfill('0') << "Time: " << std::setw(2) << gta->getHour()
|
|
||||||
<< ":" << std::setw(2) << gta->getMinute() << " (" << gta->gameTime << "s)\n";
|
|
||||||
ss << "View: " << viewCam.position.x << " " << viewCam.position.y << " " << viewCam.position.z << "\n";
|
|
||||||
ss << "Drawn " << gta->renderer.rendered << " / " << gta->renderer.culled << " Culled " << " " << gta->renderer.frames << " " << gta->renderer.geoms << "\n";
|
|
||||||
if( gta->state.player ) {
|
|
||||||
ss << "Activity: ";
|
|
||||||
if( gta->state.player->getCurrentActivity() ) {
|
|
||||||
ss << gta->state.player->getCurrentActivity()->name();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ss << "Idle";
|
|
||||||
}
|
|
||||||
ss << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Text text(ss.str(), font, 14);
|
|
||||||
text.setPosition(10, 10);
|
|
||||||
window.draw(text);
|
|
||||||
|
|
||||||
while( gta->log.size() > 0 && gta->log.front().time + 10.f < gta->gameTime ) {
|
|
||||||
gta->log.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Vector2f tpos(10.f, window.getSize().y - 30.f);
|
|
||||||
text.setCharacterSize(14);
|
|
||||||
for(auto it = gta->log.begin(); it != gta->log.end(); ++it) {
|
|
||||||
text.setString(it->message);
|
|
||||||
switch(it->type) {
|
|
||||||
case GameWorld::LogEntry::Error:
|
|
||||||
text.setColor(sf::Color::Red);
|
|
||||||
break;
|
|
||||||
case GameWorld::LogEntry::Warning:
|
|
||||||
text.setColor(sf::Color::Yellow);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
text.setColor(sf::Color::White);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interpolate the color
|
|
||||||
auto c = text.getColor();
|
|
||||||
c.a = (gta->gameTime - it->time > 5.f) ? 255 - (((gta->gameTime - it->time) - 5.f)/5.f) * 255 : 255;
|
|
||||||
text.setColor(c);
|
|
||||||
|
|
||||||
text.setPosition(tpos);
|
|
||||||
window.draw(text);
|
|
||||||
tpos.y -= text.getLocalBounds().height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @todo this should be done by GameRenderer? but it doesn't have any font support yet
|
|
||||||
if( gta->gameTime < gta->state.osTextStart + gta->state.osTextTime ) {
|
|
||||||
sf::Text messageText(gta->state.osTextString, font, 15);
|
|
||||||
auto sz = window.getSize();
|
|
||||||
|
|
||||||
auto b = messageText.getLocalBounds();
|
|
||||||
float lowerBar = sz.y - sz.y * 0.1f;
|
|
||||||
messageText.setPosition(sz.x / 2.f - std::round(b.width / 2.f), lowerBar - std::round(b.height / 2.f));
|
|
||||||
window.draw(messageText);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& t : gta->state.texts) {
|
|
||||||
sf::Text messageText(t.text, font, 15);
|
|
||||||
|
|
||||||
glm::vec2 scpos(t.position.x, t.position.y);
|
|
||||||
auto s = window.getSize();
|
|
||||||
scpos /= glm::vec2(640.f, 480.f);
|
|
||||||
scpos *= glm::vec2(s.x, s.y);
|
|
||||||
|
|
||||||
messageText.setPosition(scpos.x, scpos.y);
|
|
||||||
|
|
||||||
window.draw(messageText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getGamePath()
|
std::string getGamePath()
|
||||||
{
|
{
|
||||||
@ -412,73 +11,8 @@ std::string getGamePath()
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if(! font.loadFromFile(getGamePath() + "/DejaVuSansMono.ttf")) {
|
|
||||||
std::cerr << "Failed to load font" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
glewExperimental = GL_TRUE;
|
RWGame game(getGamePath());
|
||||||
glewInit();
|
|
||||||
|
|
||||||
size_t w = WIDTH, h = HEIGHT;
|
return game.run();
|
||||||
int c;
|
|
||||||
while( (c = getopt(argc, argv, "w:h:")) != -1) {
|
|
||||||
switch(c) {
|
|
||||||
case 'w':
|
|
||||||
w = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
h = atoi(optarg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::ContextSettings cs;
|
|
||||||
cs.depthBits = 32;
|
|
||||||
window.create(sf::VideoMode(w, h), "", sf::Style::Default, cs);
|
|
||||||
window.setVerticalSyncEnabled(true);
|
|
||||||
window.setMouseCursorVisible(false);
|
|
||||||
|
|
||||||
init(getGamePath());
|
|
||||||
|
|
||||||
sf::Clock clock;
|
|
||||||
|
|
||||||
StateManager::get().enter(new LoadingState);
|
|
||||||
|
|
||||||
float ts = GAME_TIMESTEP;
|
|
||||||
float timescale = 1.f;
|
|
||||||
|
|
||||||
// Loop until the window is closed or we run out of state.
|
|
||||||
while (window.isOpen() && StateManager::get().states.size()) {
|
|
||||||
sf::Event event;
|
|
||||||
while (window.pollEvent(event)) {
|
|
||||||
handleGlobalEvent(event);
|
|
||||||
handleCommandEvent(event);
|
|
||||||
handleInputEvent(event);
|
|
||||||
|
|
||||||
StateManager::get().states.back()->handleEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
accum += clock.restart().asSeconds() * timescale;
|
|
||||||
|
|
||||||
while ( accum >= ts ) {
|
|
||||||
|
|
||||||
StateManager::get().tick(ts);
|
|
||||||
|
|
||||||
update(ts);
|
|
||||||
accum -= ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
float alpha = accum / ts;
|
|
||||||
|
|
||||||
render(alpha);
|
|
||||||
|
|
||||||
StateManager::get().draw(window);
|
|
||||||
|
|
||||||
window.display();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
delete gta;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,17 @@
|
|||||||
#include "game.hpp"
|
#include "game.hpp"
|
||||||
#include "ingamestate.hpp"
|
#include "ingamestate.hpp"
|
||||||
|
|
||||||
MenuState::MenuState()
|
#include "RWGame.hpp"
|
||||||
|
|
||||||
|
MenuState::MenuState(RWGame* game)
|
||||||
|
: State(game)
|
||||||
{
|
{
|
||||||
Menu *m = new Menu(getFont());
|
Menu *m = new Menu(game->getFont());
|
||||||
m->offset = glm::vec2(50.f, 100.f);
|
m->offset = glm::vec2(50.f, 100.f);
|
||||||
m->addEntry(Menu::lambda("Start", [] { StateManager::get().enter(new IngameState); }));
|
m->addEntry(Menu::lambda("Start", [=] { StateManager::get().enter(new IngameState(game)); }));
|
||||||
m->addEntry(Menu::lambda("Test", [] { StateManager::get().enter(new IngameState(true)); }));
|
m->addEntry(Menu::lambda("Test", [=] { StateManager::get().enter(new IngameState(game, true)); }));
|
||||||
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
|
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
|
||||||
m->addEntry(Menu::lambda("Exit", [] { getWindow().close(); }));
|
m->addEntry(Menu::lambda("Exit", [=] { getWindow().close(); }));
|
||||||
this->enterMenu(m);
|
this->enterMenu(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
class MenuState : public State
|
class MenuState : public State
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MenuState();
|
MenuState(RWGame* game);
|
||||||
|
|
||||||
virtual void enter();
|
virtual void enter();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#include "pausestate.hpp"
|
#include "pausestate.hpp"
|
||||||
#include "game.hpp"
|
#include "RWGame.hpp"
|
||||||
|
|
||||||
PauseState::PauseState()
|
PauseState::PauseState(RWGame* game)
|
||||||
|
: State(game)
|
||||||
{
|
{
|
||||||
Menu *m = new Menu(getFont());
|
Menu *m = new Menu(game->getFont());
|
||||||
m->offset = glm::vec2(50.f, 100.f);
|
m->offset = glm::vec2(50.f, 100.f);
|
||||||
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
|
m->addEntry(Menu::lambda("Continue", [] { StateManager::get().exit(); }));
|
||||||
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
|
m->addEntry(Menu::lambda("Options", [] { std::cout << "Options" << std::endl; }));
|
||||||
m->addEntry(Menu::lambda("Exit", [] { getWindow().close(); }));
|
m->addEntry(Menu::lambda("Exit", [&] { getWindow().close(); }));
|
||||||
this->enterMenu(m);
|
this->enterMenu(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
class PauseState : public State
|
class PauseState : public State
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PauseState();
|
PauseState(RWGame* game);
|
||||||
|
|
||||||
virtual void enter();
|
virtual void enter();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
Loading…
Reference in New Issue
Block a user