* 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
|
game_window.cpp
|
||||||
renderer_simple.cpp
|
renderer_simple.cpp
|
||||||
renderer_shader.cpp
|
renderer_shader.cpp
|
||||||
|
session.hpp
|
||||||
|
|
||||||
util.cpp
|
util.cpp
|
||||||
game.cpp
|
game.cpp
|
||||||
|
@ -38,7 +39,8 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
include_directories(${OPENGL_INCLUDE_DIR})
|
include_directories(${OPENGL_INCLUDE_DIR})
|
||||||
include_directories(${CMAKE_SOURCE_DIR}/libs/glm/)
|
include_directories(${CMAKE_SOURCE_DIR}/libs/glm/)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/libs/asio/asio/include/)
|
||||||
|
|
||||||
add_executable(game ${GAME_SRC} ${GAME_HEADERS})
|
add_executable(game ${GAME_SRC} ${GAME_HEADERS})
|
||||||
setup_target(game)
|
setup_target(game)
|
||||||
target_link_libraries(game X11 epoxy)
|
target_link_libraries(game X11 epoxy pthread)
|
||||||
|
|
|
@ -6,39 +6,56 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
Game::Game() {
|
Game::Game()
|
||||||
// advance simulation with 100 Hz
|
{
|
||||||
|
// advance simulation in fixed steps with 100 Hz
|
||||||
m_time_step = 1.0 / 100.0;
|
m_time_step = 1.0 / 100.0;
|
||||||
m_time_for_next_step = 0.0;
|
m_time_for_next_step = 0.0;
|
||||||
|
|
||||||
m_state = new game::State();
|
m_state = new game::State();
|
||||||
m_state->init();
|
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;
|
static float acc = 0.0;
|
||||||
|
|
||||||
|
//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;
|
acc += dt;
|
||||||
|
total += dt;
|
||||||
|
|
||||||
float spawnInterval = 0.1;
|
float spawnInterval = 0.1;
|
||||||
while (acc > spawnInterval) {
|
while (acc > spawnInterval) {
|
||||||
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;
|
float speed = 0.005;
|
||||||
m_state->players[0]->addCommand(new game::ShootCommand(a, speed));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 1
|
m_state->players[0]->addCommand(new game::SetSpeedCommand(speed));
|
||||||
if (dt >= 10.0) {
|
m_state->players[0]->addCommand(new game::ShootCommand(angle));
|
||||||
// std::cout<<"time to big: " << dt << std::endl;
|
|
||||||
dt = m_time_step;
|
//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;
|
// std::cout<<"adding dt: " << dt << std::endl;
|
||||||
m_time_for_next_step += dt;
|
m_time_for_next_step += dt;
|
||||||
|
@ -56,11 +73,4 @@ bool Game::cycle(float dt) {
|
||||||
// steps taken." << std::endl;
|
// steps taken." << std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
|
||||||
(void)dt;
|
|
||||||
|
|
||||||
m_state->advance(dt);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Game {
|
||||||
bool cycle(float dt);
|
bool cycle(float dt);
|
||||||
|
|
||||||
// for rendering
|
// for rendering
|
||||||
const game::State *state() const { return m_state; }
|
game::State *state() const { return m_state; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
game::State *m_state;
|
game::State *m_state;
|
||||||
|
|
|
@ -25,11 +25,11 @@ class GameWindow : public endofthejedi::GLWindow {
|
||||||
// if (!once) {
|
// if (!once) {
|
||||||
// once = true;
|
// once = true;
|
||||||
// for (int i=0; i<1000; i++) {
|
// 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))) {
|
if (!m_game->cycle(static_cast<float>(time/1000000000.0))) {
|
||||||
std::cout<<"stopping the game..." << std::endl;
|
std::cout<<"stopping the game..." << std::endl;
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
#include "opengl.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <asio.hpp>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "opengl.hpp"
|
||||||
#include "game_window.hpp"
|
#include "game_window.hpp"
|
||||||
|
#include "server.hpp"
|
||||||
#include "options.hpp"
|
#include "options.hpp"
|
||||||
|
|
||||||
uint64_t optionsFlags;
|
uint64_t optionsFlags;
|
||||||
|
|
||||||
|
using asio::ip::tcp;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
|
||||||
|
char port[]="3490";
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
static struct option long_options[] =
|
static struct option long_options[] =
|
||||||
|
@ -24,7 +30,7 @@ int main(int argc, char *argv[]) {
|
||||||
// {"add", no_argument, 0, 'a'},
|
// {"add", no_argument, 0, 'a'},
|
||||||
// {"append", no_argument, 0, 'b'},
|
// {"append", no_argument, 0, 'b'},
|
||||||
// {"delete", required_argument, 0, 'd'},
|
// {"delete", required_argument, 0, 'd'},
|
||||||
// {"create", required_argument, 0, 'c'},
|
{"port", required_argument, 0, 'p'},
|
||||||
{"fps", no_argument, 0, 'f'},
|
{"fps", no_argument, 0, 'f'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
@ -32,7 +38,7 @@ int main(int argc, char *argv[]) {
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
|
||||||
while(1){
|
while(1){
|
||||||
c = getopt_long (argc, argv, "abc:d:f",
|
c = getopt_long (argc, argv, "p:f",
|
||||||
long_options, &option_index);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -42,10 +48,10 @@ int main(int argc, char *argv[]) {
|
||||||
case 'f':
|
case 'f':
|
||||||
SET_FLAG(SHOW_FPS,true);
|
SET_FLAG(SHOW_FPS,true);
|
||||||
break;
|
break;
|
||||||
/*case 'c':
|
case 'p':
|
||||||
cvalue = optarg;
|
strcpy(port,optarg);
|
||||||
break;
|
break;
|
||||||
*/
|
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
/* getopt_long already printed an error message. */
|
/* 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.set_maxfps(60.0);
|
||||||
window.loop();
|
|
||||||
window.stop();
|
while(window.running()){
|
||||||
|
window.poll();
|
||||||
|
io_service.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,18 +102,11 @@ void endofthejedi::GLWindow::handle(XEvent event) {
|
||||||
|
|
||||||
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); }
|
||||||
|
|
||||||
void endofthejedi::GLWindow::loop() {
|
void endofthejedi::GLWindow::poll() {
|
||||||
m_running = true;
|
|
||||||
|
|
||||||
timespec prev;
|
|
||||||
timespec current;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
|
clock_gettime(CLOCK_MONOTONIC_RAW, &prev);
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
clock_gettime(CLOCK_MONOTONIC_RAW, ¤t);
|
||||||
|
|
||||||
double delta = 0.0;
|
|
||||||
double sleeptime = 0.0;
|
|
||||||
|
|
||||||
while (m_running) {
|
|
||||||
handleevents();
|
handleevents();
|
||||||
render(delta);
|
render(delta);
|
||||||
swap();
|
swap();
|
||||||
|
@ -125,21 +118,10 @@ void endofthejedi::GLWindow::loop() {
|
||||||
sleeptime = sleeptime - (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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void endofthejedi::GLWindow::stop() { m_running = false; }
|
void endofthejedi::GLWindow::stop() { m_running = false; }
|
||||||
|
bool endofthejedi::GLWindow::running() { return m_running; }
|
||||||
void endofthejedi::GLWindow::init() {}
|
void endofthejedi::GLWindow::init() { m_running = true; }
|
||||||
void endofthejedi::GLWindow::render(double time) { UNUSED(time) }
|
void endofthejedi::GLWindow::render(double time) { UNUSED(time) }
|
||||||
void endofthejedi::GLWindow::resize() {}
|
void endofthejedi::GLWindow::resize() {}
|
||||||
|
|
|
@ -39,6 +39,10 @@ class GLWindow {
|
||||||
|
|
||||||
unsigned int m_width;
|
unsigned int m_width;
|
||||||
unsigned int m_height;
|
unsigned int m_height;
|
||||||
|
double delta = 0.0;
|
||||||
|
double sleeptime = 0.0;
|
||||||
|
timespec prev;
|
||||||
|
timespec current;
|
||||||
|
|
||||||
//mainloop condition
|
//mainloop condition
|
||||||
bool m_running = false;
|
bool m_running = false;
|
||||||
|
@ -47,8 +51,6 @@ class GLWindow {
|
||||||
//if maxfps = 0 there's no fps limit
|
//if maxfps = 0 there's no fps limit
|
||||||
double m_maxfps;
|
double m_maxfps;
|
||||||
|
|
||||||
void handleevents();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//ancestors shall override these methods
|
//ancestors shall override these methods
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
@ -61,16 +63,19 @@ class GLWindow {
|
||||||
//as it handles the close calls & resizing
|
//as it handles the close calls & resizing
|
||||||
virtual void handle(XEvent event);
|
virtual void handle(XEvent event);
|
||||||
|
|
||||||
|
virtual void handleevents();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//initializes the X Window & creates an OpenGL context
|
//initializes the X Window & creates an OpenGL context
|
||||||
GLWindow(unsigned int width, unsigned int height);
|
GLWindow(unsigned int width, unsigned int height);
|
||||||
~GLWindow();
|
~GLWindow();
|
||||||
|
|
||||||
//mainloop does event handling & calls render/swap
|
//mainloop does event handling & calls render/swap
|
||||||
void loop();
|
void poll();
|
||||||
void swap();
|
void swap();
|
||||||
//stops the mainloop by setting m_running false
|
//stops the mainloop by setting m_running false
|
||||||
void stop();
|
void stop();
|
||||||
|
bool running();
|
||||||
|
|
||||||
//getters
|
//getters
|
||||||
unsigned int getheight() const {
|
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 "trace.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
void ShootCommand::apply(Player *player, State *state) const
|
void ShootCommand::apply(Player *player, State *state) const
|
||||||
{
|
{
|
||||||
|
@ -10,23 +12,72 @@ namespace game {
|
||||||
// TODO: idea
|
// TODO: idea
|
||||||
// shoot multiple rockets at once or from different positions after
|
// shoot multiple rockets at once or from different positions after
|
||||||
// level up / upgrade ...
|
// 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);
|
Trace *trace = new Trace(missile);
|
||||||
missile->trace = trace;
|
missile->trace = trace;
|
||||||
|
|
||||||
player->energy -= m_speed;
|
player->energy -= player->speed;
|
||||||
player->missiles.push_back(missile);
|
player->missiles.push_back(missile);
|
||||||
|
|
||||||
state->addTrace(trace);
|
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;
|
(void) state;
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
return player->alive && player->energy >= m_speed;
|
return player->alive && player->energy >= player->speed;
|
||||||
//return player->alive;
|
//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>
|
#include <iostream>
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
|
/**
|
||||||
|
* Base class for commands.
|
||||||
|
* must derive from this.
|
||||||
|
*/
|
||||||
class Command {
|
class Command {
|
||||||
public:
|
public:
|
||||||
Command()
|
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) player;
|
||||||
(void) state;
|
(void) state;
|
||||||
|
@ -38,19 +46,95 @@ namespace game {
|
||||||
virtual std::string name() const { return "<unnamed>"; }
|
virtual std::string name() const { return "<unnamed>"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
/* Implemented commands */
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shoot at angle and optional speed.
|
||||||
|
* TODO
|
||||||
|
*/
|
||||||
class ShootCommand : public Command {
|
class ShootCommand : public Command {
|
||||||
public:
|
public:
|
||||||
ShootCommand(float angle, float speed) : m_angle(angle), m_speed(speed)
|
ShootCommand(float angle) : m_angle(angle)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name() const { return "<shoot>"; }
|
std::string name() const { return "<shoot>"; }
|
||||||
|
|
||||||
void apply( Player *player, State *state) const;
|
void apply( Player *player, State *state) const;
|
||||||
bool allowed(const Player *player, const State *state) const;
|
bool ready(const Player *player, const State *state) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_angle;
|
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;
|
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) {
|
if (dist <= planet->radius) {
|
||||||
// TODO: collect all hits and return the first one only
|
// TODO: collect all hits and return the first one only
|
||||||
// TODO: find exact hit position!
|
// TODO: find exact hit position!
|
||||||
return Missile::Event(position, Hit::Planet);
|
return Missile::Event(position, planet->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
dist *= 20.0;
|
dist *= 20.0;
|
||||||
|
|
|
@ -22,7 +22,8 @@ namespace game {
|
||||||
// stops existing afterwards.
|
// stops existing afterwards.
|
||||||
class Event {
|
class Event {
|
||||||
public:
|
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(const glm::vec2 &pos, int playerIdKiller, int playerIdVictim)
|
||||||
: Event(pos, Hit::Ship)
|
: Event(pos, Hit::Ship)
|
||||||
{
|
{
|
||||||
|
@ -41,8 +47,12 @@ namespace game {
|
||||||
Hit hit;
|
Hit hit;
|
||||||
glm::vec2 position;
|
glm::vec2 position;
|
||||||
|
|
||||||
|
// if a player was hit, these are valid.
|
||||||
int playerIdKiller;
|
int playerIdKiller;
|
||||||
int playerIdVictim;
|
int playerIdVictim;
|
||||||
|
|
||||||
|
// if a planet was hit, this is valid
|
||||||
|
int planetId;
|
||||||
};
|
};
|
||||||
|
|
||||||
Missile(Player *player, const glm::vec2 &pos, float angle, float speed);
|
Missile(Player *player, const glm::vec2 &pos, float angle, float speed);
|
||||||
|
|
|
@ -2,11 +2,39 @@
|
||||||
|
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
class Planet : public Object {
|
class Planet : public Object {
|
||||||
public:
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -15,12 +16,14 @@ namespace game {
|
||||||
public:
|
public:
|
||||||
int id;
|
int id;
|
||||||
bool alive;
|
bool alive;
|
||||||
|
float speed;
|
||||||
float energy;
|
float energy;
|
||||||
float deadTimeCounter;
|
float deadTimeCounter;
|
||||||
Ship *ship;
|
Ship *ship;
|
||||||
|
std::string name;
|
||||||
std::vector<Missile*> missiles;
|
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"
|
#include "util.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
void State::init()
|
void State::init()
|
||||||
{
|
{
|
||||||
|
@ -25,6 +27,7 @@ namespace game {
|
||||||
m_maxMissileDistance = 2.0;
|
m_maxMissileDistance = 2.0;
|
||||||
m_playerRespawnTime = 2.0;
|
m_playerRespawnTime = 2.0;
|
||||||
m_defaultEnergy = 10.0;
|
m_defaultEnergy = 10.0;
|
||||||
|
m_maxNumTraces = 10;
|
||||||
|
|
||||||
bool planetsOnCircle = false;
|
bool planetsOnCircle = false;
|
||||||
|
|
||||||
|
@ -45,7 +48,7 @@ namespace game {
|
||||||
}
|
}
|
||||||
} while(glm::length(pos) < 0.2 && tries++ < 1000);
|
} 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void State::addPlayer(int playerId)
|
int State::addPlayer()
|
||||||
{
|
{
|
||||||
|
int playerId = m_nextId++;
|
||||||
Player *player = new Player(playerId);
|
Player *player = new Player(playerId);
|
||||||
players.push_back(player);
|
players.push_back(player);
|
||||||
|
return playerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void State::playerLeft(int playerId)
|
void State::quitPlayer(int playerId)
|
||||||
{
|
{
|
||||||
(void) 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)
|
void State::advancePlayerShipSpawns(float dt)
|
||||||
|
@ -108,7 +137,7 @@ namespace game {
|
||||||
// try to execute as much queued commands as possible.
|
// try to execute as much queued commands as possible.
|
||||||
while (player->hasCommandInQueue()) {
|
while (player->hasCommandInQueue()) {
|
||||||
Command *command = player->peekCommand();
|
Command *command = player->peekCommand();
|
||||||
if (!command->allowed(player, this)) {
|
if (!command->ready(player, this)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +174,9 @@ namespace game {
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// add points
|
// add points
|
||||||
//
|
|
||||||
// TODO
|
// TODO
|
||||||
// message
|
// message
|
||||||
//
|
|
||||||
// TODO
|
|
||||||
// respawn timer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void State::advancePlayerMissiles(float dt)
|
void State::advancePlayerMissiles(float dt)
|
||||||
|
@ -166,7 +192,9 @@ namespace game {
|
||||||
|
|
||||||
const bool isHit = (evt.hit != Hit::Nothing);
|
const bool isHit = (evt.hit != Hit::Nothing);
|
||||||
|
|
||||||
|
if (missile->trace != nullptr) {
|
||||||
missile->trace->addPointFromMissile(isHit); // force point if missile gets destroyed a
|
missile->trace->addPointFromMissile(isHit); // force point if missile gets destroyed a
|
||||||
|
}
|
||||||
|
|
||||||
if (!isHit) {
|
if (!isHit) {
|
||||||
i++;
|
i++;
|
||||||
|
@ -192,6 +220,10 @@ namespace game {
|
||||||
|
|
||||||
addExplosionFromHit(&evt);
|
addExplosionFromHit(&evt);
|
||||||
|
|
||||||
|
if (missile->trace != nullptr) {
|
||||||
|
missile->trace->finish();
|
||||||
|
}
|
||||||
|
|
||||||
player->missiles.erase(player->missiles.begin() + i);
|
player->missiles.erase(player->missiles.begin() + i);
|
||||||
delete(missile);
|
delete(missile);
|
||||||
//std::cout<<std::endl;
|
//std::cout<<std::endl;
|
||||||
|
@ -287,9 +319,50 @@ namespace game {
|
||||||
|
|
||||||
void State::addTrace(Trace *trace)
|
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);
|
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)
|
void State::addExplosionFromHit(const Missile::Event *evt)
|
||||||
{
|
{
|
||||||
if (evt->hit == Hit::Nothing || evt->hit == Hit::BorderOfUniverse) {
|
if (evt->hit == Hit::Nothing || evt->hit == Hit::BorderOfUniverse) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -9,6 +10,18 @@
|
||||||
|
|
||||||
#include "missile.hpp"
|
#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 {
|
namespace game {
|
||||||
// forward declarations
|
// forward declarations
|
||||||
class Command;
|
class Command;
|
||||||
|
@ -38,8 +51,11 @@ namespace game {
|
||||||
|
|
||||||
// The upper layer (network/renderer) calling these three functions
|
// The upper layer (network/renderer) calling these three functions
|
||||||
// should keep id's unique and give one (network) input an id.
|
// should keep id's unique and give one (network) input an id.
|
||||||
void addPlayer(int playerId);
|
int addPlayer();
|
||||||
void playerLeft(int playerId);
|
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);
|
void commandForPlayer(int playerId, Command *cmd);
|
||||||
|
|
||||||
// lookup. return nullptr on invalid playerId
|
// lookup. return nullptr on invalid playerId
|
||||||
|
@ -57,6 +73,10 @@ namespace game {
|
||||||
// add a trace to the list of traces.
|
// add a trace to the list of traces.
|
||||||
void addTrace(Trace *trace);
|
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 */
|
/* Rendering */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
@ -95,5 +115,7 @@ namespace game {
|
||||||
float m_playerRespawnTime;
|
float m_playerRespawnTime;
|
||||||
float m_shipRadius;
|
float m_shipRadius;
|
||||||
float m_defaultEnergy;
|
float m_defaultEnergy;
|
||||||
|
int m_nextId=0;
|
||||||
|
int m_maxNumTraces;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include "missile.hpp"
|
#include "missile.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
Trace::TracePoint::TracePoint(const Missile *missile)
|
Trace::TracePoint::TracePoint(const Missile *missile)
|
||||||
: position(missile->position)
|
: 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));
|
points.push_back(TracePoint(missile));
|
||||||
}
|
}
|
||||||
|
@ -24,4 +35,10 @@ namespace game {
|
||||||
points.push_back(TracePoint(missile));
|
points.push_back(TracePoint(missile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Trace::finish()
|
||||||
|
{
|
||||||
|
//std::cout<<"trace finished now!" << std::endl;
|
||||||
|
missile = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
class Missile;
|
class Missile;
|
||||||
|
class Player;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trace of a missile through the space.
|
* Trace of a missile through the space.
|
||||||
|
@ -12,7 +13,8 @@ namespace game {
|
||||||
*/
|
*/
|
||||||
class Trace {
|
class Trace {
|
||||||
public:
|
public:
|
||||||
Trace(const Missile *missile);
|
Trace(Missile *missile);
|
||||||
|
~Trace();
|
||||||
|
|
||||||
// Add the current position of the missile as a new point on the
|
// Add the current position of the missile as a new point on the
|
||||||
// trace.
|
// trace.
|
||||||
|
@ -21,6 +23,10 @@ namespace game {
|
||||||
// the missile) in case the fidelityCounter would skip the current position.
|
// the missile) in case the fidelityCounter would skip the current position.
|
||||||
void addPointFromMissile(bool forceAdd=false);
|
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 /
|
// TODO: add extendLastPointToPosition() method for saving points /
|
||||||
// optimization later on
|
// optimization later on
|
||||||
|
|
||||||
|
@ -35,11 +41,16 @@ namespace game {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<TracePoint> points;
|
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.
|
// counter which is incremented each time addPointFromMissile() is called.
|
||||||
// when reaching a certain value the point is saved for
|
// when reaching a certain value the point is saved for
|
||||||
// optimization.
|
// optimization.
|
||||||
int fidelityCounter;
|
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