KlassischeKeplerKriege/game/state/state.hpp
2016-10-04 19:12:04 +02:00

191 lines
6.1 KiB
C++

#pragma once
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <iostream>
#include <glm/vec2.hpp>
#include "missile.hpp"
#include "planet.hpp"
#include "state_update_event.hpp"
// TODO:
// give points for equipment / better weapons / more energy when:
// - player discovers the universe
//
// - the shot which made a kill was much longer than the direkt line between
// player and his target
//
// - add wormholes
// - add blackholes
// - shoot through suns which add a fire mantle to the rocket to make it more
// thick and dangerous but it gets destroyed after some time.
namespace game {
// forward declarations
class Command;
class Player;
class Ship;
class Trace;
class Explosion;
class IdGenerator {
public:
IdGenerator() : m_nextId(0)
{
}
size_t makeNextId()
{
return m_nextId++;
if (m_nextId == 0) {
std::cerr << "note: id counter just wrapped to 0, "
"funny things can happen now." << std::endl;
}
}
private:
size_t m_nextId;
};
class State {
public:
/*************************************************************************/
/* State management */
/*************************************************************************/
// called to setup the state (randomize planets, kill
// traces/missiles/ships etc.)
void init(int numPlanets=15);
// main method to advance the simulation by the given timestamp in
// seconds.
void advance(float dt);
/*************************************************************************/
/* Network / Input */
/*************************************************************************/
// The upper layer (network/renderer) calling these three functions
// should keep id's unique and give one (network) input an id.
size_t addPlayer();
void clear(size_t playerId);
void setName(size_t playerId, std::string name);
void setSpeed(size_t playerId, double speed);
void quitPlayer(size_t playerId);
void commandForPlayer(size_t playerId, Command *cmd);
// lookup. return nullptr on invalid playerId
Player *playerForId(size_t playerId);
/*************************************************************************/
/* Mixed stuff */
// distance after which missiles get lost in space (and explode)
float maxMissileDistance() const { return m_maxMissileDistance; }
// each ship has the same radius
float shipRadius() const { return m_shipRadius; }
// add a trace to the state
void addTrace(Trace *trace);
// add a missile to the state
void addMissile(Missile *missile);
// add a ship to the state
void addShip(Ship *ship);
// delete traces with this command
void deleteTrace(Trace *trace); // using a pointer
// get the current time
float timestamp() const { return m_time; }
// check if game is in dev. mode.
// custom commands will then work etc.
bool developerMode() const { return m_developerMode; }
// change the mode.
void setDeveloperMode(bool on)
{
std::cout<<"[state] developer mode is: " << (on ? "on" : "off") << std::endl;
m_developerMode = on;
}
// called when the rendering window changes
// TODO: give dpi as information too
void setPlayingFieldSize(int width, int height);
void setPlayingFieldCenter(int width, int height);
size_t generateId();
void applyAndClearAllOldStateUpdates();
// delete the items for events that are to be removed in proper way
// after the events were given to other parts of the application.
const std::list<StateUpdateEvent*> &currentStateUpdateEvents() const;
/*************************************************************************/
/* Rendering */
/*************************************************************************/
// TODO: hide and replace by events
// Game items which should be rendered are here:
// (access missiles by iterating over player's missiles attribute)
std::vector<Planet*> planets;
std::list<Ship*> ships;
std::list<Player*> players;
std::list<Trace*> traces;
std::list<Explosion*> explosions;
private:
/*************************************************************************/
/* Internal */
/*************************************************************************/
void playerKillsPlayer(Player *killer, Player *victim);
void addExplosionFromHit(const Missile::Event *evt);
bool findPlanetSpawnPosition(bool planetIsSun, float radius, glm::vec2 *pos);
void advanceTraceAges(float dt);
void advanceExplosions(float dt);
void advancePlayerShipSpawns(float dt);
void advancePlayerCommands(float dt);
void advancePlayerMissiles(float dt);
void setupPlanets(int numPlanets);
Planet::Material materialForStandardPlanetDistribution(int index);
// try to spawn a ship for this player.
// return true on success, false on failure to find a spot.
bool spawnShipForPlayer(Player *player);
// find some place where nothing is placed nearby (ships/planets).
// usefule for spanwing things
bool findFreePositionWithRadius(float r, glm::vec2 &pos);
float m_maxMissileDistance;
float m_playerRespawnTime;
float m_shipRadius;
float m_defaultEnergy;
int m_maxNumTraces;
IdGenerator m_ids;
float m_time;
bool m_developerMode;
glm::vec2 m_playingFieldCenter;
glm::vec2 m_playingFieldSize;
std::list<StateUpdateEvent*> m_nextEvents;
std::list<StateUpdateEvent*> m_allEvents;
};
}