* temp
This commit is contained in:
commit
8b1c94cebb
19 changed files with 500 additions and 113 deletions
|
@ -12,6 +12,7 @@ set(GAME_SRC
|
|||
game_window.cpp
|
||||
renderer_simple.cpp
|
||||
renderer_shader.cpp
|
||||
session.hpp
|
||||
|
||||
util.cpp
|
||||
game.cpp
|
||||
|
@ -38,7 +39,8 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
|||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/libs/glm/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/)
|
||||
|
||||
add_executable(game ${GAME_SRC} ${GAME_HEADERS})
|
||||
setup_target(game)
|
||||
target_link_libraries(game X11 epoxy)
|
||||
target_link_libraries(game X11 epoxy pthread)
|
||||
|
|
|
@ -6,39 +6,56 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
Game::Game() {
|
||||
// advance simulation with 100 Hz
|
||||
m_time_step = 1.0 / 100.0;
|
||||
Game::Game()
|
||||
{
|
||||
// advance simulation in fixed steps with 100 Hz
|
||||
m_time_step = 1.0 / 100.0;
|
||||
m_time_for_next_step = 0.0;
|
||||
|
||||
m_state = new game::State();
|
||||
m_state->init();
|
||||
|
||||
m_state->addPlayer(0);
|
||||
m_state->addPlayer(1);
|
||||
m_state->addPlayer(2);
|
||||
m_state->addPlayer(3);
|
||||
// m_state->addPlayer(2);
|
||||
}
|
||||
|
||||
bool Game::cycle(float dt) {
|
||||
bool Game::cycle(float dt)
|
||||
{
|
||||
#if 0
|
||||
// XXX the following is just testing code to do things
|
||||
|
||||
static float total = 0.0;
|
||||
static float acc = 0.0;
|
||||
acc += dt;
|
||||
|
||||
//if (total == 0.0) {
|
||||
// float speed = 0.005;
|
||||
// m_state->players[0]->addCommand(new game::SetSpeedCommand(speed));
|
||||
// for (int i=0; i<100; i++) {
|
||||
// float a = 2.0 * M_PI * util::randf_0_1();
|
||||
// m_state->players[0]->addCommand(new game::ShootCommand(a));
|
||||
// }
|
||||
//}
|
||||
m_state->addPlayer();
|
||||
|
||||
acc += dt;
|
||||
total += dt;
|
||||
|
||||
float spawnInterval = 0.1;
|
||||
while (acc > spawnInterval) {
|
||||
acc -= spawnInterval;
|
||||
|
||||
float a = 2.0 * M_PI * util::randf_0_1();
|
||||
float angle = 2.0 * M_PI * util::randf_0_1();
|
||||
float speed = 0.005;
|
||||
m_state->players[0]->addCommand(new game::ShootCommand(a, speed));
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (dt >= 10.0) {
|
||||
// std::cout<<"time to big: " << dt << std::endl;
|
||||
dt = m_time_step;
|
||||
m_state->players[0]->addCommand(new game::SetSpeedCommand(speed));
|
||||
m_state->players[0]->addCommand(new game::ShootCommand(angle));
|
||||
|
||||
//static bool done = false;
|
||||
//if (total >= 10.0 && !done) {
|
||||
// done = true;
|
||||
|
||||
// m_state->players[0]->addCommand(new game::ClearTracesCommand());
|
||||
//}
|
||||
}
|
||||
#endif
|
||||
|
||||
// std::cout<<"adding dt: " << dt << std::endl;
|
||||
m_time_for_next_step += dt;
|
||||
|
@ -56,11 +73,4 @@ bool Game::cycle(float dt) {
|
|||
// steps taken." << std::endl;
|
||||
|
||||
return true;
|
||||
#else
|
||||
(void)dt;
|
||||
|
||||
m_state->advance(dt);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ class Game {
|
|||
bool cycle(float dt);
|
||||
|
||||
// for rendering
|
||||
const game::State *state() const { return m_state; }
|
||||
game::State *state() const { return m_state; }
|
||||
|
||||
private:
|
||||
game::State *m_state;
|
||||
|
|
|
@ -25,12 +25,12 @@ class GameWindow : public endofthejedi::GLWindow {
|
|||
// if (!once) {
|
||||
// once = true;
|
||||
// for (int i=0; i<1000; i++) {
|
||||
// m_game.cycle(time);
|
||||
// m_game->cycle(time);
|
||||
// }
|
||||
//}
|
||||
|
||||
if (!m_game.cycle(static_cast<float>(time / 1000000000.0))) {
|
||||
std::cout << "stopping the game..." << std::endl;
|
||||
if (!m_game->cycle(static_cast<float>(time/1000000000.0))) {
|
||||
std::cout<<"stopping the game..." << std::endl;
|
||||
stop();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
#include "opengl.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <getopt.h>
|
||||
#include <asio.hpp>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "opengl.hpp"
|
||||
#include "game_window.hpp"
|
||||
#include "server.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
uint64_t optionsFlags;
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
|
||||
char port[]="3490";
|
||||
char c;
|
||||
|
||||
static struct option long_options[] =
|
||||
|
@ -24,7 +30,7 @@ int main(int argc, char *argv[]) {
|
|||
// {"add", no_argument, 0, 'a'},
|
||||
// {"append", no_argument, 0, 'b'},
|
||||
// {"delete", required_argument, 0, 'd'},
|
||||
// {"create", required_argument, 0, 'c'},
|
||||
{"port", required_argument, 0, 'p'},
|
||||
{"fps", no_argument, 0, 'f'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
@ -32,7 +38,7 @@ int main(int argc, char *argv[]) {
|
|||
int option_index = 0;
|
||||
|
||||
while(1){
|
||||
c = getopt_long (argc, argv, "abc:d:f",
|
||||
c = getopt_long (argc, argv, "p:f",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
@ -42,10 +48,10 @@ int main(int argc, char *argv[]) {
|
|||
case 'f':
|
||||
SET_FLAG(SHOW_FPS,true);
|
||||
break;
|
||||
/*case 'c':
|
||||
cvalue = optarg;
|
||||
break;
|
||||
*/
|
||||
case 'p':
|
||||
strcpy(port,optarg);
|
||||
break;
|
||||
|
||||
|
||||
case '?':
|
||||
/* getopt_long already printed an error message. */
|
||||
|
@ -56,8 +62,18 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
GameWindow window(500, 500);
|
||||
Game game;
|
||||
|
||||
asio::io_service io_service;
|
||||
Server s(io_service, game.state(), atoi(port) );
|
||||
|
||||
GameWindow window(500, 500, &game);
|
||||
window.set_maxfps(60.0);
|
||||
window.loop();
|
||||
window.stop();
|
||||
|
||||
while(window.running()){
|
||||
window.poll();
|
||||
io_service.poll();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -102,44 +102,26 @@ void endofthejedi::GLWindow::handle(XEvent event) {
|
|||
|
||||
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
||||
|
||||
void endofthejedi::GLWindow::loop() {
|
||||
m_running = true;
|
||||
void endofthejedi::GLWindow::poll() {
|
||||
|
||||
timespec prev;
|
||||
timespec current;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
||||
|
||||
double delta = 0.0;
|
||||
double sleeptime = 0.0;
|
||||
handleevents();
|
||||
render(delta);
|
||||
swap();
|
||||
|
||||
while (m_running) {
|
||||
handleevents();
|
||||
render(delta);
|
||||
swap();
|
||||
|
||||
if (m_maxfps > 0) {
|
||||
sleeptime = ((1000000000.0 / m_maxfps) - delta) + sleeptime;
|
||||
if (sleeptime > 0.0) {
|
||||
usleep((unsigned int)(sleeptime / 1000.0));
|
||||
sleeptime = sleeptime - (unsigned int)(sleeptime / 1000.0);
|
||||
}
|
||||
}
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
||||
delta = diff(prev, current).tv_nsec;
|
||||
prev = current;
|
||||
if (delta > 0.0) {
|
||||
m_fps = (1000000000.0 / delta);
|
||||
if (ISSET_FLAG(SHOW_FPS)) {
|
||||
std::cout << m_fps << "\n";
|
||||
}
|
||||
}
|
||||
if (m_maxfps > 0) {
|
||||
sleeptime = ((1000000000.0/m_maxfps) - delta) + sleeptime;
|
||||
if (sleeptime > 0.0) {
|
||||
usleep((unsigned int)(sleeptime/1000.0));
|
||||
sleeptime = sleeptime - (unsigned int)(sleeptime/1000.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endofthejedi::GLWindow::stop() { m_running = false; }
|
||||
|
||||
void endofthejedi::GLWindow::init() {}
|
||||
bool endofthejedi::GLWindow::running() { return m_running; }
|
||||
void endofthejedi::GLWindow::init() { m_running = true; }
|
||||
void endofthejedi::GLWindow::render(double time) { UNUSED(time) }
|
||||
void endofthejedi::GLWindow::resize() {}
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
namespace endofthejedi {
|
||||
|
||||
class GLWindow {
|
||||
private:
|
||||
private:
|
||||
//X-related stuff
|
||||
Display* m_display;
|
||||
Window m_rootwnd;
|
||||
GLint m_attributes[23] =
|
||||
Display* m_display;
|
||||
Window m_rootwnd;
|
||||
GLint m_attributes[23] =
|
||||
{
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||
|
@ -28,17 +28,21 @@ class GLWindow {
|
|||
None
|
||||
};
|
||||
|
||||
XVisualInfo* m_visualinfo;
|
||||
Colormap m_colormap;
|
||||
XSetWindowAttributes m_swa;
|
||||
Window m_window;
|
||||
GLXContext m_glcontext;
|
||||
XWindowAttributes m_gwa;
|
||||
XVisualInfo* m_visualinfo;
|
||||
Colormap m_colormap;
|
||||
XSetWindowAttributes m_swa;
|
||||
Window m_window;
|
||||
GLXContext m_glcontext;
|
||||
XWindowAttributes m_gwa;
|
||||
Atom m_atomWmDeleteWindow;
|
||||
//End of X related stuff
|
||||
|
||||
unsigned int m_width;
|
||||
unsigned int m_height;
|
||||
double delta = 0.0;
|
||||
double sleeptime = 0.0;
|
||||
timespec prev;
|
||||
timespec current;
|
||||
|
||||
//mainloop condition
|
||||
bool m_running = false;
|
||||
|
@ -47,9 +51,7 @@ class GLWindow {
|
|||
//if maxfps = 0 there's no fps limit
|
||||
double m_maxfps;
|
||||
|
||||
void handleevents();
|
||||
|
||||
protected:
|
||||
protected:
|
||||
//ancestors shall override these methods
|
||||
virtual void init();
|
||||
//called by mainloop periodically
|
||||
|
@ -61,16 +63,19 @@ class GLWindow {
|
|||
//as it handles the close calls & resizing
|
||||
virtual void handle(XEvent event);
|
||||
|
||||
virtual void handleevents();
|
||||
|
||||
public:
|
||||
//initializes the X Window & creates an OpenGL context
|
||||
GLWindow(unsigned int width, unsigned int height);
|
||||
~GLWindow();
|
||||
GLWindow(unsigned int width, unsigned int height);
|
||||
~GLWindow();
|
||||
|
||||
//mainloop does event handling & calls render/swap
|
||||
void loop();
|
||||
void poll();
|
||||
void swap();
|
||||
//stops the mainloop by setting m_running false
|
||||
void stop();
|
||||
bool running();
|
||||
|
||||
//getters
|
||||
unsigned int getheight() const {
|
||||
|
|
38
game/server.hpp
Normal file
38
game/server.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include <asio.hpp>
|
||||
|
||||
#include "session.hpp"
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
Server(asio::io_service& io_service,game::State* s, short port)
|
||||
: acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
|
||||
socket_(io_service)
|
||||
{
|
||||
state=s;
|
||||
do_accept();
|
||||
}
|
||||
|
||||
private:
|
||||
void do_accept()
|
||||
{
|
||||
acceptor_.async_accept(socket_,
|
||||
[this](std::error_code ec)
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
std::make_shared<Session>(std::move(socket_),state)->start();
|
||||
}
|
||||
|
||||
do_accept();
|
||||
});
|
||||
}
|
||||
|
||||
tcp::acceptor acceptor_;
|
||||
tcp::socket socket_;
|
||||
game::State* state;
|
||||
};
|
35
game/session.hpp
Normal file
35
game/session.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <asio.hpp>
|
||||
|
||||
#include "game.hpp"
|
||||
|
||||
using asio::ip::tcp;
|
||||
|
||||
class Session
|
||||
: public std::enable_shared_from_this<Session>
|
||||
{
|
||||
public:
|
||||
Session(tcp::socket socket, game::State* state)
|
||||
: m_socket(std::move(socket))
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
void start();
|
||||
|
||||
private:
|
||||
void do_read();
|
||||
void do_write(char m_snd_data[], std::size_t length);
|
||||
bool parse(std::string);
|
||||
tcp::socket m_socket;
|
||||
enum { max_length = 1024 };
|
||||
char m_rcv_data[max_length];
|
||||
game::State* m_state;
|
||||
bool m_started = false;
|
||||
int m_pid;
|
||||
};
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "trace.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace game {
|
||||
void ShootCommand::apply(Player *player, State *state) const
|
||||
{
|
||||
|
@ -10,23 +12,72 @@ namespace game {
|
|||
// TODO: idea
|
||||
// shoot multiple rockets at once or from different positions after
|
||||
// level up / upgrade ...
|
||||
Missile *missile = new Missile(player, player->ship->position, m_angle, m_speed);
|
||||
Missile *missile = new Missile(player, player->ship->position, m_angle, player->speed);
|
||||
|
||||
Trace *trace = new Trace(missile);
|
||||
missile->trace = trace;
|
||||
|
||||
player->energy -= m_speed;
|
||||
player->energy -= player->speed;
|
||||
player->missiles.push_back(missile);
|
||||
|
||||
state->addTrace(trace);
|
||||
}
|
||||
|
||||
bool ShootCommand::allowed(const Player *player, const State *state) const
|
||||
bool ShootCommand::ready(const Player *player, const State *state) const
|
||||
{
|
||||
(void) state;
|
||||
|
||||
// TODO
|
||||
return player->alive && player->energy >= m_speed;
|
||||
return player->alive && player->energy >= player->speed;
|
||||
//return player->alive;
|
||||
}
|
||||
|
||||
void ChangeNameCommand::apply(Player *player, State *state) const
|
||||
{
|
||||
// discard if not unique
|
||||
for (const Player *other : state->players) {
|
||||
if (m_name == other->name) {
|
||||
std::cout << "name '" << m_name << "' already given to player #" << other->id << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
player->name = m_name;
|
||||
}
|
||||
|
||||
void SetSpeedCommand::apply(Player *player, State *state) const
|
||||
{
|
||||
(void) state;
|
||||
player->speed = m_speed;
|
||||
}
|
||||
|
||||
void ClearTracesCommand::apply(Player *player, State *state) const
|
||||
{
|
||||
std::cout<<"clearing traces!!!" << std::endl;
|
||||
|
||||
size_t i = 0;
|
||||
while(i < state->traces.size()) {
|
||||
Trace *trace = state->traces[i];
|
||||
if (trace->missile == nullptr && trace->player == player) {
|
||||
state->deleteTrace(i);
|
||||
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool TakeOverPlayerCommand::ready(const Player *player, const State *state) const
|
||||
{
|
||||
(void) state;
|
||||
return state->havePlayerGrantFor(player->id, m_otherPlayerId);
|
||||
}
|
||||
|
||||
void TakeOverPlayerCommand::apply(Player *player, State *state) const
|
||||
{
|
||||
if (
|
||||
state->playerGrant(player->id, m_otherPlayerId);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
#include <iostream>
|
||||
|
||||
namespace game {
|
||||
/**
|
||||
* Base class for commands.
|
||||
* must derive from this.
|
||||
*/
|
||||
class Command {
|
||||
public:
|
||||
Command()
|
||||
|
@ -19,7 +23,11 @@ namespace game {
|
|||
{
|
||||
}
|
||||
|
||||
virtual bool allowed(const Player *player, const State *state) const
|
||||
// check whether the command is ready to execute.
|
||||
// if not, wait.
|
||||
// note: stuff like for admin should be done in execute() to discard the
|
||||
// command and not block the queue.
|
||||
virtual bool ready(const Player *player, const State *state) const
|
||||
{
|
||||
(void) player;
|
||||
(void) state;
|
||||
|
@ -38,19 +46,95 @@ namespace game {
|
|||
virtual std::string name() const { return "<unnamed>"; }
|
||||
};
|
||||
|
||||
/**********************************************************************/
|
||||
/* Implemented commands */
|
||||
/**********************************************************************/
|
||||
|
||||
/*
|
||||
* Shoot at angle and optional speed.
|
||||
* TODO
|
||||
*/
|
||||
class ShootCommand : public Command {
|
||||
public:
|
||||
ShootCommand(float angle, float speed) : m_angle(angle), m_speed(speed)
|
||||
ShootCommand(float angle) : m_angle(angle)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name() const { return "<shoot>"; }
|
||||
|
||||
void apply( Player *player, State *state) const;
|
||||
bool allowed(const Player *player, const State *state) const;
|
||||
void apply( Player *player, State *state) const;
|
||||
bool ready(const Player *player, const State *state) const;
|
||||
|
||||
private:
|
||||
float m_angle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the name of the player if it will be uniuqe.
|
||||
*/
|
||||
class ChangeNameCommand : public Command {
|
||||
public:
|
||||
ChangeNameCommand(const std::string &name) : m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name() const { return "<change name>"; }
|
||||
|
||||
void apply(Player *player, State *state) const;
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
/**
|
||||
* clear all traces of this player that are done
|
||||
*/
|
||||
class ClearTracesCommand : public Command {
|
||||
public:
|
||||
ClearTracesCommand()
|
||||
{
|
||||
}
|
||||
|
||||
std::string name() const { return "<clear traces>"; }
|
||||
|
||||
void apply(Player *player, State *state) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set default speed of next shots for this player.
|
||||
*/
|
||||
class SetSpeedCommand : public Command {
|
||||
public:
|
||||
SetSpeedCommand(float speed) : m_speed(speed)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name() const { return "<set speed>"; }
|
||||
|
||||
void apply(Player *player, State *state) const;
|
||||
|
||||
private:
|
||||
float m_speed;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Take over a session for a player that left.
|
||||
* An admin must confirm this command.
|
||||
*/
|
||||
class TakeOverPlayerCommand : public Command {
|
||||
public:
|
||||
TakeOverPlayerCommand(int otherPlayerId) : m_otherPlayerId(otherPlayerId)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name() const { return "<take over player>"; }
|
||||
|
||||
void apply( Player *player, State *state) const;
|
||||
bool ready(const Player *player, const State *state) const;
|
||||
|
||||
private:
|
||||
int m_otherPlayerId;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace game {
|
|||
if (dist <= planet->radius) {
|
||||
// TODO: collect all hits and return the first one only
|
||||
// TODO: find exact hit position!
|
||||
return Missile::Event(position, Hit::Planet);
|
||||
return Missile::Event(position, planet->id);
|
||||
}
|
||||
|
||||
dist *= 20.0;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace game {
|
|||
// stops existing afterwards.
|
||||
class Event {
|
||||
public:
|
||||
Event(const glm::vec2 &pos) : Event(pos, Hit::Nothing)
|
||||
Event(const glm::vec2 &pos)
|
||||
: Event(pos, Hit::Nothing)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -31,6 +32,11 @@ namespace game {
|
|||
{
|
||||
}
|
||||
|
||||
Event(const glm::vec2 &pos, int planetId) : Event(pos, Hit::Planet)
|
||||
{
|
||||
this->planetId = planetId;
|
||||
}
|
||||
|
||||
Event(const glm::vec2 &pos, int playerIdKiller, int playerIdVictim)
|
||||
: Event(pos, Hit::Ship)
|
||||
{
|
||||
|
@ -41,8 +47,12 @@ namespace game {
|
|||
Hit hit;
|
||||
glm::vec2 position;
|
||||
|
||||
// if a player was hit, these are valid.
|
||||
int playerIdKiller;
|
||||
int playerIdVictim;
|
||||
|
||||
// if a planet was hit, this is valid
|
||||
int planetId;
|
||||
};
|
||||
|
||||
Missile(Player *player, const glm::vec2 &pos, float angle, float speed);
|
||||
|
|
|
@ -2,11 +2,39 @@
|
|||
|
||||
#include "object.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace game {
|
||||
class Planet : public Object {
|
||||
public:
|
||||
Planet(const glm::vec2 &pos, float r) : Object(pos, r)
|
||||
/**
|
||||
* Planets are build out of one material.
|
||||
* TODO: support mixture or multiple material per planet.
|
||||
*/
|
||||
enum class Material {
|
||||
Rock,
|
||||
Metal,
|
||||
Sand,
|
||||
Gas,
|
||||
Ice,
|
||||
Water,
|
||||
Sun
|
||||
};
|
||||
|
||||
Planet(const glm::vec2 &pos, int id, float r) : Planet(pos, id, r, Material::Rock)
|
||||
{
|
||||
}
|
||||
|
||||
Planet(const glm::vec2 &pos, int id, float r, Material mat)
|
||||
: Object(pos, r)
|
||||
, id(id)
|
||||
, material(mat)
|
||||
, seed(rand())
|
||||
{
|
||||
}
|
||||
|
||||
int id;
|
||||
Material material; // for rendering and physics (can fly through sun and outer gas planets)
|
||||
int seed; // just for rendering variation
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
|
@ -15,12 +16,14 @@ namespace game {
|
|||
public:
|
||||
int id;
|
||||
bool alive;
|
||||
float speed;
|
||||
float energy;
|
||||
float deadTimeCounter;
|
||||
Ship *ship;
|
||||
std::string name;
|
||||
std::vector<Missile*> missiles;
|
||||
|
||||
Player(int id) : id(id), alive(true), energy(0.0), ship(nullptr)
|
||||
Player(int id) : id(id), alive(true), speed(0.01), energy(0.0), ship(nullptr), name("<unnamed>")
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#include "util.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace game {
|
||||
void State::init()
|
||||
{
|
||||
|
@ -25,6 +27,7 @@ namespace game {
|
|||
m_maxMissileDistance = 2.0;
|
||||
m_playerRespawnTime = 2.0;
|
||||
m_defaultEnergy = 10.0;
|
||||
m_maxNumTraces = 10;
|
||||
|
||||
bool planetsOnCircle = false;
|
||||
|
||||
|
@ -45,7 +48,7 @@ namespace game {
|
|||
}
|
||||
} while(glm::length(pos) < 0.2 && tries++ < 1000);
|
||||
|
||||
planets.push_back(new Planet(pos, 0.03 + 0.07*util::randf_0_1()));
|
||||
planets.push_back(new Planet(pos, i, 0.03 + 0.07*util::randf_0_1()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,15 +67,41 @@ namespace game {
|
|||
return true;
|
||||
}
|
||||
|
||||
void State::addPlayer(int playerId)
|
||||
int State::addPlayer()
|
||||
{
|
||||
int playerId = m_nextId++;
|
||||
Player *player = new Player(playerId);
|
||||
players.push_back(player);
|
||||
return playerId;
|
||||
}
|
||||
|
||||
void State::playerLeft(int playerId)
|
||||
void State::quitPlayer(int playerId)
|
||||
{
|
||||
(void) playerId;
|
||||
cout << playerId << " quit" << endl;
|
||||
}
|
||||
|
||||
void State::clear(int playerId)
|
||||
{
|
||||
cout << playerId << " clear" << endl;
|
||||
}
|
||||
|
||||
void State::setName(int playerId, std::string name)
|
||||
{
|
||||
// discard if not unique
|
||||
for (const Player *other : players) {
|
||||
if (name == other->name) {
|
||||
std::cout << "name '" << name << "' already given to player #" << other->id << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
playerForId(playerId)->name = name;
|
||||
}
|
||||
|
||||
void State::setSpeed(int playerId, double speed)
|
||||
{
|
||||
playerForId(playerId)->speed = speed;
|
||||
}
|
||||
|
||||
void State::advancePlayerShipSpawns(float dt)
|
||||
|
@ -108,7 +137,7 @@ namespace game {
|
|||
// try to execute as much queued commands as possible.
|
||||
while (player->hasCommandInQueue()) {
|
||||
Command *command = player->peekCommand();
|
||||
if (!command->allowed(player, this)) {
|
||||
if (!command->ready(player, this)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -145,12 +174,9 @@ namespace game {
|
|||
|
||||
// TODO
|
||||
// add points
|
||||
//
|
||||
|
||||
// TODO
|
||||
// message
|
||||
//
|
||||
// TODO
|
||||
// respawn timer
|
||||
}
|
||||
|
||||
void State::advancePlayerMissiles(float dt)
|
||||
|
@ -166,7 +192,9 @@ namespace game {
|
|||
|
||||
const bool isHit = (evt.hit != Hit::Nothing);
|
||||
|
||||
missile->trace->addPointFromMissile(isHit); // force point if missile gets destroyed a
|
||||
if (missile->trace != nullptr) {
|
||||
missile->trace->addPointFromMissile(isHit); // force point if missile gets destroyed a
|
||||
}
|
||||
|
||||
if (!isHit) {
|
||||
i++;
|
||||
|
@ -192,6 +220,10 @@ namespace game {
|
|||
|
||||
addExplosionFromHit(&evt);
|
||||
|
||||
if (missile->trace != nullptr) {
|
||||
missile->trace->finish();
|
||||
}
|
||||
|
||||
player->missiles.erase(player->missiles.begin() + i);
|
||||
delete(missile);
|
||||
//std::cout<<std::endl;
|
||||
|
@ -287,9 +319,50 @@ namespace game {
|
|||
|
||||
void State::addTrace(Trace *trace)
|
||||
{
|
||||
//int count = 0;
|
||||
//for (Trace *old : traces) {
|
||||
// if (old->playerId == trace->playerId) {
|
||||
// count++;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (count > m_maxNumTraces) {
|
||||
//}
|
||||
|
||||
traces.push_back(trace);
|
||||
}
|
||||
|
||||
void State::deleteTrace(size_t index)
|
||||
{
|
||||
if (index >= traces.size()) {
|
||||
std::cerr << "can't find trace with invalid index " << index << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Trace *trace = traces[index];
|
||||
|
||||
//std::cout<<"removing a trace" << std::endl;
|
||||
if (trace->missile != nullptr) {
|
||||
// delete backlink.
|
||||
// XXX: there's a missile without a trace now.
|
||||
trace->missile->trace = nullptr;
|
||||
}
|
||||
|
||||
traces.erase(traces.begin() + index);
|
||||
delete(trace);
|
||||
}
|
||||
|
||||
void State::deleteTrace(Trace *trace)
|
||||
{
|
||||
size_t i = 0;
|
||||
while(i < traces.size()) {
|
||||
if (traces[i] == trace) {
|
||||
deleteTrace(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void State::addExplosionFromHit(const Missile::Event *evt)
|
||||
{
|
||||
if (evt->hit == Hit::Nothing || evt->hit == Hit::BorderOfUniverse) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -9,6 +10,18 @@
|
|||
|
||||
#include "missile.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;
|
||||
|
@ -38,8 +51,11 @@ namespace game {
|
|||
|
||||
// The upper layer (network/renderer) calling these three functions
|
||||
// should keep id's unique and give one (network) input an id.
|
||||
void addPlayer(int playerId);
|
||||
void playerLeft(int playerId);
|
||||
int addPlayer();
|
||||
void clear(int playerId);
|
||||
void setName(int playerId, std::string name);
|
||||
void setSpeed(int playerId, double speed);
|
||||
void quitPlayer(int playerId);
|
||||
void commandForPlayer(int playerId, Command *cmd);
|
||||
|
||||
// lookup. return nullptr on invalid playerId
|
||||
|
@ -57,6 +73,10 @@ namespace game {
|
|||
// add a trace to the list of traces.
|
||||
void addTrace(Trace *trace);
|
||||
|
||||
// delete traces with this command
|
||||
void deleteTrace(Trace *trace); // using a pointer
|
||||
void deleteTrace(size_t index); // using an index
|
||||
|
||||
/*************************************************************************/
|
||||
/* Rendering */
|
||||
/*************************************************************************/
|
||||
|
@ -95,5 +115,7 @@ namespace game {
|
|||
float m_playerRespawnTime;
|
||||
float m_shipRadius;
|
||||
float m_defaultEnergy;
|
||||
int m_nextId=0;
|
||||
int m_maxNumTraces;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "missile.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace game {
|
||||
Trace::TracePoint::TracePoint(const Missile *missile)
|
||||
: position(missile->position)
|
||||
|
@ -11,7 +13,16 @@ namespace game {
|
|||
{
|
||||
}
|
||||
|
||||
Trace::Trace(const Missile *missile) : missile(missile), fidelityCounter(0)
|
||||
Trace::~Trace()
|
||||
{
|
||||
//std::cout<<"~Trace()" << std::endl;
|
||||
}
|
||||
|
||||
Trace::Trace(Missile *missile)
|
||||
: missile(missile)
|
||||
, player(missile->player)
|
||||
, fidelityCounter(0)
|
||||
, age(0.0)
|
||||
{
|
||||
points.push_back(TracePoint(missile));
|
||||
}
|
||||
|
@ -24,4 +35,10 @@ namespace game {
|
|||
points.push_back(TracePoint(missile));
|
||||
}
|
||||
}
|
||||
|
||||
void Trace::finish()
|
||||
{
|
||||
//std::cout<<"trace finished now!" << std::endl;
|
||||
missile = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace game {
|
||||
class Missile;
|
||||
class Player;
|
||||
|
||||
/*
|
||||
* Trace of a missile through the space.
|
||||
|
@ -12,7 +13,8 @@ namespace game {
|
|||
*/
|
||||
class Trace {
|
||||
public:
|
||||
Trace(const Missile *missile);
|
||||
Trace(Missile *missile);
|
||||
~Trace();
|
||||
|
||||
// Add the current position of the missile as a new point on the
|
||||
// trace.
|
||||
|
@ -21,6 +23,10 @@ namespace game {
|
|||
// the missile) in case the fidelityCounter would skip the current position.
|
||||
void addPointFromMissile(bool forceAdd=false);
|
||||
|
||||
// call this to mark the trace as finish and disconnect it from the
|
||||
// missile.
|
||||
void finish();
|
||||
|
||||
// TODO: add extendLastPointToPosition() method for saving points /
|
||||
// optimization later on
|
||||
|
||||
|
@ -35,11 +41,16 @@ namespace game {
|
|||
};
|
||||
|
||||
std::vector<TracePoint> points;
|
||||
const Missile *missile; // missile which creates this path.
|
||||
Missile *missile; // missile which creates this path.
|
||||
Player *player;
|
||||
|
||||
// counter which is incremented each time addPointFromMissile() is called.
|
||||
// when reaching a certain value the point is saved for
|
||||
// optimization.
|
||||
int fidelityCounter;
|
||||
|
||||
// age of the trace. if too old, it can be removed to save
|
||||
// space/power
|
||||
float age;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue