Multiplayer framework in place (can now connect multiple clients and view them in game)
Fixed some bugs with multiplayer Changed from refptr<map<U8, Player> > to map<U8, refptr<player> >
This commit is contained in:
parent
7df681082a
commit
ba0bc9b77d
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include GL_INCLUDE_FILE
|
#include GL_INCLUDE_FILE
|
||||||
@ -216,16 +215,21 @@ void Client::redraw()
|
|||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
double dir_x = cos(m_player->direction);
|
double dir_x = cos(m_players[current_player]->direction);
|
||||||
double dir_y = sin(m_player->direction);
|
double dir_y = sin(m_players[current_player]->direction);
|
||||||
m_modelview.load_identity();
|
m_modelview.load_identity();
|
||||||
m_modelview.look_at(
|
m_modelview.look_at(
|
||||||
m_player->x - dir_x * 25, m_player->y - dir_y * 25, 30,
|
m_players[current_player]->x - dir_x * 25, m_players[current_player]->y - dir_y * 25, 30,
|
||||||
m_player->x, m_player->y, 20,
|
m_players[current_player]->x, m_players[current_player]->y, 20,
|
||||||
0, 0, 1);
|
0, 0, 1);
|
||||||
|
|
||||||
// TODO: call draw_player() for each networked player
|
// TODO: call draw_player() for each networked player
|
||||||
draw_player(m_player);
|
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
|
||||||
|
{
|
||||||
|
draw_player(piter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
draw_map();
|
draw_map();
|
||||||
draw_sky();
|
draw_sky();
|
||||||
draw_lava();
|
draw_lava();
|
||||||
@ -357,8 +361,8 @@ void Client::draw_overlay()
|
|||||||
proj.ortho(-span, span, -span, span, -1, 1);
|
proj.ortho(-span, span, -span, span, -1, 1);
|
||||||
proj.to_uniform(m_overlay_program.uniform("projection"));
|
proj.to_uniform(m_overlay_program.uniform("projection"));
|
||||||
GLMatrix modelview;
|
GLMatrix modelview;
|
||||||
modelview.rotate(90 - m_player->direction * 180 / M_PI, 0, 0, 1);
|
modelview.rotate(90 - m_players[current_player]->direction * 180 / M_PI, 0, 0, 1);
|
||||||
modelview.translate(-m_player->x, -m_player->y, 0);
|
modelview.translate(-m_players[current_player]->x, -m_players[current_player]->y, 0);
|
||||||
m_overlay_hex_attributes.bind();
|
m_overlay_hex_attributes.bind();
|
||||||
m_overlay_hex_indices.bind();
|
m_overlay_hex_indices.bind();
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
@ -409,8 +413,8 @@ void Client::draw_overlay()
|
|||||||
GLMatrix::Identity.to_uniform(
|
GLMatrix::Identity.to_uniform(
|
||||||
m_overlay_hover_program.uniform("projection"));
|
m_overlay_hover_program.uniform("projection"));
|
||||||
modelview.load_identity();
|
modelview.load_identity();
|
||||||
modelview.translate(m_player->hover - 1, 0, 0);
|
modelview.translate(m_players[current_player]->hover - 1, 0, 0);
|
||||||
modelview.scale(m_player->hover * 2, 2.0, 1.0);
|
modelview.scale(m_players[current_player]->hover * 2, 2.0, 1.0);
|
||||||
modelview.to_uniform(m_overlay_hover_program.uniform("modelview"));
|
modelview.to_uniform(m_overlay_hover_program.uniform("modelview"));
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
|
||||||
@ -450,8 +454,8 @@ void Client::draw_sky()
|
|||||||
m_sky_attributes.bind();
|
m_sky_attributes.bind();
|
||||||
m_projection.to_uniform(m_sky_program.uniform("projection"));
|
m_projection.to_uniform(m_sky_program.uniform("projection"));
|
||||||
m_modelview.push();
|
m_modelview.push();
|
||||||
m_modelview.translate(m_player->x, m_player->y, 0);
|
m_modelview.translate(m_players[current_player]->x, m_players[current_player]->y, 0);
|
||||||
m_modelview.rotate(m_player->direction * 180.0 / M_PI, 0, 0, 1);
|
m_modelview.rotate(m_players[current_player]->direction * 180.0 / M_PI, 0, 0, 1);
|
||||||
m_modelview.to_uniform(m_sky_program.uniform("modelview"));
|
m_modelview.to_uniform(m_sky_program.uniform("modelview"));
|
||||||
m_modelview.pop();
|
m_modelview.pop();
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
Client::Client()
|
Client::Client()
|
||||||
{
|
{
|
||||||
m_net_client = new Network();
|
m_net_client = new Network();
|
||||||
m_net_client->Create(59243, "127.0.0.1"); // Just connect to local host for now - testing
|
m_net_client->Create(59243, "127.0.0.1"); // Just connect to local host for now - testing
|
||||||
client_has_focus = true;
|
client_has_focus = true;
|
||||||
|
m_players.clear();
|
||||||
|
current_player = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
@ -15,16 +18,16 @@ Client::~Client()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Client::run(bool fullscreen, int width, int height)
|
void Client::run(bool fullscreen, int width, int height, std::string pname)
|
||||||
{
|
{
|
||||||
|
Timer client_timer;
|
||||||
|
client_timer.Init();
|
||||||
|
current_player_name = pname;
|
||||||
if (!create_window(fullscreen, width, height))
|
if (!create_window(fullscreen, width, height))
|
||||||
return;
|
return;
|
||||||
m_player = new Player();
|
|
||||||
m_player->x = 0;
|
|
||||||
m_player->y = 0;
|
|
||||||
m_player->direction = M_PI_2;
|
|
||||||
m_clock.restart();
|
m_clock.restart();
|
||||||
sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window);
|
sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window);
|
||||||
|
|
||||||
double last_time = 0.0;
|
double last_time = 0.0;
|
||||||
while (m_window->isOpen())
|
while (m_window->isOpen())
|
||||||
{
|
{
|
||||||
@ -63,8 +66,16 @@ void Client::run(bool fullscreen, int width, int height)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time must be updated before any messages are sent
|
||||||
|
// Especially guaranteed messages, since the time needs to be
|
||||||
|
// non zero.
|
||||||
|
client_timer.Update();
|
||||||
|
|
||||||
update(elapsed_time);
|
update(elapsed_time);
|
||||||
redraw();
|
if(m_players.size() > 0)
|
||||||
|
{
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
|
|
||||||
// temporary for now. otherwise this thread consumed way too processing
|
// temporary for now. otherwise this thread consumed way too processing
|
||||||
@ -74,81 +85,150 @@ void Client::run(bool fullscreen, int width, int height)
|
|||||||
|
|
||||||
void Client::update(double elapsed_time)
|
void Client::update(double elapsed_time)
|
||||||
{
|
{
|
||||||
static sf::Uint8 w_pressed_prev = KEY_NOT_PRESSED;
|
static bool registered_player = false;
|
||||||
static sf::Uint8 a_pressed_prev = KEY_NOT_PRESSED;
|
|
||||||
static sf::Uint8 s_pressed_prev = KEY_NOT_PRESSED;
|
|
||||||
static sf::Uint8 d_pressed_prev = KEY_NOT_PRESSED;
|
|
||||||
static sf::Int32 rel_mouse_movement_prev = 0;
|
|
||||||
|
|
||||||
sf::Packet client_packet;
|
sf::Packet client_packet;
|
||||||
|
|
||||||
|
|
||||||
m_net_client->Receive();
|
m_net_client->Receive();
|
||||||
client_packet.clear();
|
client_packet.clear();
|
||||||
// Handle all received data (only really want the latest)
|
// Handle all received data (only really want the latest)
|
||||||
while(m_net_client->getData(client_packet))
|
while(m_net_client->getData(client_packet))
|
||||||
{
|
{
|
||||||
// Update player position as calculated from the server.
|
sf::Uint8 packet_type;
|
||||||
client_packet >> m_player->direction;
|
client_packet >> packet_type;
|
||||||
client_packet >> m_player->x;
|
switch(packet_type)
|
||||||
client_packet >> m_player->y;
|
{
|
||||||
|
case PLAYER_CONNECT:
|
||||||
|
{
|
||||||
|
sf::Uint8 pindex;
|
||||||
|
std::string name = "";
|
||||||
|
client_packet >> pindex;
|
||||||
|
client_packet >> name;
|
||||||
|
// Should be a much better way of doing this.
|
||||||
|
// Perhaps generate a random number
|
||||||
|
if(name == current_player_name)
|
||||||
|
{
|
||||||
|
current_player = pindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new player if one does not exist.
|
||||||
|
if(m_players.end() == m_players.find(pindex))
|
||||||
|
{
|
||||||
|
refptr<Player> p = new Player();
|
||||||
|
p->name = name;
|
||||||
|
client_packet >> p->direction;
|
||||||
|
client_packet >> p->x;
|
||||||
|
client_packet >> p->y;
|
||||||
|
m_players[pindex] = p;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PLAYER_UPDATE:
|
||||||
|
{
|
||||||
|
sf::Uint8 player_index;
|
||||||
|
// Update player position as calculated from the server.
|
||||||
|
client_packet >> player_index;
|
||||||
|
if(m_players.end() != m_players.find(player_index))
|
||||||
|
{
|
||||||
|
client_packet >> m_players[player_index]->direction;
|
||||||
|
client_packet >> m_players[player_index]->x;
|
||||||
|
client_packet >> m_players[player_index]->y;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PLAYER_DISCONNECT:
|
||||||
|
{
|
||||||
|
// This will remove the player once the disconnect algorithm is implemented
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PLAYER_DEATH:
|
||||||
|
{
|
||||||
|
// This will set a death flag in the player struct.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default :
|
||||||
|
{
|
||||||
|
// Eat the packet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, we are going to do a very crude shove data into
|
// For now, we are going to do a very crude shove data into
|
||||||
// packet from keyboard and mouse events.
|
// packet from keyboard and mouse events.
|
||||||
// TODO: Clean this up and make it more robust
|
// TODO: Clean this up and make it more robust
|
||||||
client_packet.clear();
|
if(m_players.size() > 0)
|
||||||
|
|
||||||
sf::Uint8 w_pressed = KEY_NOT_PRESSED;
|
|
||||||
sf::Uint8 a_pressed = KEY_NOT_PRESSED;
|
|
||||||
sf::Uint8 s_pressed = KEY_NOT_PRESSED;
|
|
||||||
sf::Uint8 d_pressed = KEY_NOT_PRESSED;
|
|
||||||
sf::Int32 rel_mouse_movement = 0;
|
|
||||||
|
|
||||||
// This is a fix so that the mouse will not move outside the window and
|
|
||||||
// cause the user to click on another program.
|
|
||||||
// Note: Does not work well with fast movement.
|
|
||||||
if(client_has_focus)
|
|
||||||
{
|
{
|
||||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
|
sf::Uint8 w_pressed = KEY_NOT_PRESSED;
|
||||||
|
sf::Uint8 a_pressed = KEY_NOT_PRESSED;
|
||||||
|
sf::Uint8 s_pressed = KEY_NOT_PRESSED;
|
||||||
|
sf::Uint8 d_pressed = KEY_NOT_PRESSED;
|
||||||
|
sf::Int32 rel_mouse_movement = 0;
|
||||||
|
|
||||||
|
// This is a fix so that the mouse will not move outside the window and
|
||||||
|
// cause the user to click on another program.
|
||||||
|
// Note: Does not work well with fast movement.
|
||||||
|
if(client_has_focus)
|
||||||
{
|
{
|
||||||
a_pressed = KEY_PRESSED;
|
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
|
||||||
|
{
|
||||||
|
a_pressed = KEY_PRESSED;
|
||||||
|
}
|
||||||
|
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
|
||||||
|
{
|
||||||
|
d_pressed = KEY_PRESSED;
|
||||||
|
}
|
||||||
|
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
|
||||||
|
{
|
||||||
|
w_pressed = KEY_PRESSED;
|
||||||
|
}
|
||||||
|
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
|
||||||
|
{
|
||||||
|
s_pressed = KEY_PRESSED;
|
||||||
|
}
|
||||||
|
rel_mouse_movement = sf::Mouse::getPosition(*m_window).x - m_width / 2;
|
||||||
|
sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window);
|
||||||
}
|
}
|
||||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
|
|
||||||
|
// Send an update to the server if something has changed
|
||||||
|
if((m_players[current_player]->w_pressed != w_pressed) ||
|
||||||
|
(m_players[current_player]->a_pressed != a_pressed) ||
|
||||||
|
(m_players[current_player]->s_pressed != s_pressed) ||
|
||||||
|
(m_players[current_player]->d_pressed != d_pressed) ||
|
||||||
|
(m_players[current_player]->rel_mouse_movement != rel_mouse_movement))
|
||||||
{
|
{
|
||||||
d_pressed = KEY_PRESSED;
|
sf::Uint8 packet_type = PLAYER_UPDATE;
|
||||||
|
client_packet.clear();
|
||||||
|
client_packet << packet_type;
|
||||||
|
client_packet << current_player;
|
||||||
|
client_packet << w_pressed;
|
||||||
|
client_packet << a_pressed;
|
||||||
|
client_packet << s_pressed;
|
||||||
|
client_packet << d_pressed;
|
||||||
|
client_packet << rel_mouse_movement;
|
||||||
|
|
||||||
|
m_net_client->sendData(client_packet);
|
||||||
|
|
||||||
|
m_players[current_player]->w_pressed = w_pressed;
|
||||||
|
m_players[current_player]->a_pressed = a_pressed;
|
||||||
|
m_players[current_player]->s_pressed = s_pressed;
|
||||||
|
m_players[current_player]->d_pressed = d_pressed;
|
||||||
|
m_players[current_player]->rel_mouse_movement = rel_mouse_movement;
|
||||||
}
|
}
|
||||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
|
|
||||||
{
|
|
||||||
w_pressed = KEY_PRESSED;
|
|
||||||
}
|
|
||||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
|
|
||||||
{
|
|
||||||
s_pressed = KEY_PRESSED;
|
|
||||||
}
|
|
||||||
rel_mouse_movement = sf::Mouse::getPosition(*m_window).x - m_width / 2;
|
|
||||||
sf::Mouse::setPosition(sf::Vector2i(m_width / 2, m_height / 2), *m_window);
|
|
||||||
}
|
}
|
||||||
|
else if(!registered_player)
|
||||||
// Send an update to the server if something has changed
|
|
||||||
if((w_pressed_prev != w_pressed) ||
|
|
||||||
(a_pressed_prev != a_pressed) ||
|
|
||||||
(s_pressed_prev != s_pressed) ||
|
|
||||||
(d_pressed_prev != d_pressed) ||
|
|
||||||
(rel_mouse_movement_prev != rel_mouse_movement))
|
|
||||||
{
|
{
|
||||||
client_packet << w_pressed;
|
sf::Uint8 packet_type = PLAYER_CONNECT;
|
||||||
client_packet << a_pressed;
|
client_packet.clear();
|
||||||
client_packet << s_pressed;
|
client_packet << packet_type;
|
||||||
client_packet << d_pressed;
|
client_packet << current_player;
|
||||||
client_packet << rel_mouse_movement;
|
client_packet << current_player_name;
|
||||||
|
m_net_client->sendData(client_packet, true);
|
||||||
m_net_client->sendData(client_packet);
|
registered_player = true;
|
||||||
|
}
|
||||||
w_pressed_prev = w_pressed;
|
else
|
||||||
a_pressed_prev = a_pressed;
|
{
|
||||||
s_pressed_prev = s_pressed;
|
// Do nothing.
|
||||||
d_pressed_prev = d_pressed;
|
|
||||||
rel_mouse_movement_prev = rel_mouse_movement;
|
|
||||||
}
|
}
|
||||||
m_net_client->Transmit();
|
m_net_client->Transmit();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#ifndef CLIENT_H
|
#ifndef CLIENT_H
|
||||||
#define CLIENT_H
|
#define CLIENT_H
|
||||||
|
|
||||||
@ -18,7 +17,7 @@ class Client
|
|||||||
public:
|
public:
|
||||||
Client();
|
Client();
|
||||||
~Client();
|
~Client();
|
||||||
void run(bool fullscreen, int width, int height);
|
void run(bool fullscreen, int width, int height, std::string pname);
|
||||||
protected:
|
protected:
|
||||||
bool create_window(bool fullscreen, int width, int height);
|
bool create_window(bool fullscreen, int width, int height);
|
||||||
bool initgl();
|
bool initgl();
|
||||||
@ -34,7 +33,9 @@ class Client
|
|||||||
refptr<sf::Window> m_window;
|
refptr<sf::Window> m_window;
|
||||||
sf::Clock m_clock;
|
sf::Clock m_clock;
|
||||||
Map m_map;
|
Map m_map;
|
||||||
refptr<Player> m_player;
|
sf::Uint8 current_player;
|
||||||
|
std::string current_player_name;
|
||||||
|
std::map<sf::Uint8, refptr<Player> > m_players;
|
||||||
int m_width;
|
int m_width;
|
||||||
int m_height;
|
int m_height;
|
||||||
GLProgram m_obj_program;
|
GLProgram m_obj_program;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include "Client.h"
|
#include "Client.h"
|
||||||
@ -8,11 +7,13 @@ int main(int argc, char *argv[])
|
|||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
int width = 1200;
|
int width = 1200;
|
||||||
int height = 900;
|
int height = 900;
|
||||||
|
std::string player_name = "Player";
|
||||||
|
|
||||||
struct option longopts[] = {
|
struct option longopts[] = {
|
||||||
{"fullscreen", no_argument, NULL, 'f'},
|
{"fullscreen", no_argument, NULL, 'f'},
|
||||||
{"height", required_argument, NULL, 'h'},
|
{"height", required_argument, NULL, 'h'},
|
||||||
{"width", required_argument, NULL, 'w'},
|
{"width", required_argument, NULL, 'w'},
|
||||||
|
{"name", required_argument, NULL, 'n'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -31,12 +32,15 @@ int main(int argc, char *argv[])
|
|||||||
case 'w':
|
case 'w':
|
||||||
width = atoi(optarg);
|
width = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'n':
|
||||||
|
player_name = std::string(optarg);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Client client;
|
Client client;
|
||||||
|
|
||||||
client.run(fullscreen, width, height);
|
client.run(fullscreen, width, height, player_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "HexTile.h"
|
#include "HexTile.h"
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#ifndef HEXTILE_H
|
#ifndef HEXTILE_H
|
||||||
#define HEXTILE_H
|
#define HEXTILE_H
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include "HexTile.h"
|
#include "HexTile.h"
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#ifndef MAP_H
|
#ifndef MAP_H
|
||||||
#define MAP_H
|
#define MAP_H
|
||||||
|
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
Player::Player()
|
Player::Player()
|
||||||
{
|
{
|
||||||
x = 0.0;
|
x = 0.0;
|
||||||
y = 0.0;
|
y = 0.0;
|
||||||
direction = 0.0;
|
direction = M_PI_2;
|
||||||
hover = 1.0;
|
hover = 1.0;
|
||||||
|
name = "";
|
||||||
|
w_pressed = KEY_NOT_PRESSED;
|
||||||
|
a_pressed = KEY_NOT_PRESSED;
|
||||||
|
s_pressed = KEY_NOT_PRESSED;
|
||||||
|
d_pressed = KEY_NOT_PRESSED;
|
||||||
|
rel_mouse_movement = 0;
|
||||||
|
updated = false;
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
|
||||||
#ifndef PLAYER_H
|
#ifndef PLAYER_H
|
||||||
#define PLAYER_H
|
#define PLAYER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "Types.h"
|
||||||
|
#include "SFML/Config.hpp"
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
@ -12,6 +13,12 @@ class Player
|
|||||||
double y;
|
double y;
|
||||||
double direction; /* 0 = East, M_PI_2 = North, M_PI = West, ... */
|
double direction; /* 0 = East, M_PI_2 = North, M_PI = West, ... */
|
||||||
double hover;
|
double hover;
|
||||||
|
sf::Uint8 w_pressed;
|
||||||
|
sf::Uint8 a_pressed;
|
||||||
|
sf::Uint8 s_pressed;
|
||||||
|
sf::Uint8 d_pressed;
|
||||||
|
sf::Int32 rel_mouse_movement;
|
||||||
|
bool updated;
|
||||||
|
|
||||||
Player();
|
Player();
|
||||||
};
|
};
|
||||||
|
@ -23,7 +23,6 @@ void Timer::Update(void)
|
|||||||
{
|
{
|
||||||
// Record the time step
|
// Record the time step
|
||||||
stepTime = ((myClock.getElapsedTime().asSeconds() / 1000.0f) * gameSpeed);
|
stepTime = ((myClock.getElapsedTime().asSeconds() / 1000.0f) * gameSpeed);
|
||||||
//stepTime = ((((sf::Window*)screen)->GetFrameTime() / 1000.0f) * gameSpeed);
|
|
||||||
myClock.restart();
|
myClock.restart();
|
||||||
|
|
||||||
// Add the time to the total time
|
// Add the time to the total time
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#define KEY_PRESSED 0xA5u
|
#define KEY_PRESSED 0xA5u
|
||||||
#define KEY_NOT_PRESSED 0x5Au
|
#define KEY_NOT_PRESSED 0x5Au
|
||||||
|
|
||||||
|
#define PLAYER_CONNECT 0x1Au
|
||||||
|
#define PLAYER_DISCONNECT 0x2Bu
|
||||||
|
#define PLAYER_DEATH 0x3Cu
|
||||||
|
#define PLAYER_UPDATE 0x4Du
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
#ifndef REFPTR_H
|
#ifndef REFPTR_H
|
||||||
#define REFPTR_H REFPTR_H
|
#define REFPTR_H REFPTR_H
|
||||||
|
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
Server::Server(sf::Uint16 port)
|
Server::Server(sf::Uint16 port)
|
||||||
{
|
{
|
||||||
m_net_server = new Network();
|
m_net_server = new Network();
|
||||||
m_net_server->Create(port, sf::IpAddress::None);
|
m_net_server->Create(port, sf::IpAddress::None);
|
||||||
m_player = new Player();
|
m_players.clear();
|
||||||
m_player->x = 0;
|
|
||||||
m_player->y = 0;
|
|
||||||
m_player->direction = M_PI_2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
@ -22,10 +20,18 @@ void Server::run( void )
|
|||||||
double current_time;
|
double current_time;
|
||||||
double elapsed_time;
|
double elapsed_time;
|
||||||
double last_time = 0.0;
|
double last_time = 0.0;
|
||||||
|
Timer server_timer;
|
||||||
|
server_timer.Init();
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
current_time = m_clock.getElapsedTime().asSeconds();
|
current_time = m_clock.getElapsedTime().asSeconds();
|
||||||
elapsed_time = current_time - last_time;
|
elapsed_time = current_time - last_time;
|
||||||
|
|
||||||
|
// Time must be updated before any messages are sent
|
||||||
|
// Especially guaranteed messages, since the time needs to be
|
||||||
|
// non zero.
|
||||||
|
server_timer.Update();
|
||||||
|
|
||||||
update( elapsed_time );
|
update( elapsed_time );
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
|
|
||||||
@ -40,65 +46,143 @@ void Server::update( double elapsed_time )
|
|||||||
static Player player_prev;
|
static Player player_prev;
|
||||||
const double move_speed = 75.0;
|
const double move_speed = 75.0;
|
||||||
sf::Packet server_packet;
|
sf::Packet server_packet;
|
||||||
static sf::Uint8 w_pressed = KEY_NOT_PRESSED;
|
|
||||||
static sf::Uint8 a_pressed = KEY_NOT_PRESSED;
|
|
||||||
static sf::Uint8 s_pressed = KEY_NOT_PRESSED;
|
|
||||||
static sf::Uint8 d_pressed = KEY_NOT_PRESSED;
|
|
||||||
static sf::Int32 rel_mouse_movement = 0;
|
|
||||||
|
|
||||||
m_net_server->Receive();
|
m_net_server->Receive();
|
||||||
// Handle all received data (only really want the latest)
|
// Handle all received data (only really want the latest)
|
||||||
while(m_net_server->getData(server_packet))
|
while(m_net_server->getData(server_packet))
|
||||||
{
|
{
|
||||||
server_packet >> w_pressed;
|
sf::Uint8 ptype;
|
||||||
server_packet >> a_pressed;
|
// Get packet type
|
||||||
server_packet >> s_pressed;
|
server_packet >> ptype;
|
||||||
server_packet >> d_pressed;
|
switch(ptype)
|
||||||
server_packet >> rel_mouse_movement;
|
{
|
||||||
|
case PLAYER_CONNECT:
|
||||||
|
{
|
||||||
|
refptr<Player> p = new Player();
|
||||||
|
std::string pname;
|
||||||
|
sf::Uint8 pindex;
|
||||||
|
|
||||||
|
server_packet >> pindex;
|
||||||
|
server_packet >> pname;
|
||||||
|
// When a player connects, we need to associate
|
||||||
|
// that player with a new ID. find first unused id
|
||||||
|
// player zero means a player does not exist.
|
||||||
|
if(pindex == 0)
|
||||||
|
{
|
||||||
|
for(pindex = 1u; pindex < 255u; pindex++ )
|
||||||
|
{
|
||||||
|
if(m_players.end() == m_players.find(pindex))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->name = pname;
|
||||||
|
m_players[pindex] = p;
|
||||||
|
|
||||||
|
// Alert all connected clients of all the connected players.
|
||||||
|
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
|
||||||
|
{
|
||||||
|
server_packet.clear();
|
||||||
|
server_packet << ptype;
|
||||||
|
server_packet << piter->first;
|
||||||
|
server_packet << piter->second->name;
|
||||||
|
// Send correct starting locations so that they match
|
||||||
|
// the other players screens.
|
||||||
|
server_packet << piter->second->direction;
|
||||||
|
server_packet << piter->second->x;
|
||||||
|
server_packet << piter->second->y;
|
||||||
|
m_net_server->sendData(server_packet, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PLAYER_UPDATE:
|
||||||
|
{
|
||||||
|
// Need to determine the correct player id
|
||||||
|
// then update the stored contents.
|
||||||
|
sf::Uint8 pindex;
|
||||||
|
server_packet >> pindex;
|
||||||
|
if(m_players.end() != m_players.find(pindex))
|
||||||
|
{
|
||||||
|
server_packet >> m_players[pindex]->w_pressed;
|
||||||
|
server_packet >> m_players[pindex]->a_pressed;
|
||||||
|
server_packet >> m_players[pindex]->s_pressed;
|
||||||
|
server_packet >> m_players[pindex]->d_pressed;
|
||||||
|
server_packet >> m_players[pindex]->rel_mouse_movement;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PLAYER_DISCONNECT:
|
||||||
|
{
|
||||||
|
// This completely removes the player from the game
|
||||||
|
// Deletes member from the player list
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PLAYER_DEATH:
|
||||||
|
{
|
||||||
|
// This just forces the player to dissapper from the
|
||||||
|
// playing field.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Just eat the packet
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KEY_PRESSED == a_pressed)
|
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
|
||||||
{
|
{
|
||||||
double direction = m_player->direction + M_PI_2;
|
sf::Uint8 pindex = piter->first;
|
||||||
m_player->x += cos(direction) * move_speed * elapsed_time;
|
if (KEY_PRESSED == m_players[pindex]->a_pressed)
|
||||||
m_player->y += sin(direction) * move_speed * elapsed_time;
|
{
|
||||||
}
|
double direction = m_players[pindex]->direction + M_PI_2;
|
||||||
if (KEY_PRESSED == d_pressed)
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
{
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
double direction = m_player->direction - M_PI_2;
|
m_players[pindex]->updated = true;
|
||||||
m_player->x += cos(direction) * move_speed * elapsed_time;
|
}
|
||||||
m_player->y += sin(direction) * move_speed * elapsed_time;
|
if (KEY_PRESSED == m_players[pindex]->d_pressed)
|
||||||
}
|
{
|
||||||
if (KEY_PRESSED == w_pressed)
|
double direction = m_players[pindex]->direction - M_PI_2;
|
||||||
{
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
double direction = m_player->direction;
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
m_player->x += cos(direction) * move_speed * elapsed_time;
|
m_players[pindex]->updated = true;
|
||||||
m_player->y += sin(direction) * move_speed * elapsed_time;
|
}
|
||||||
}
|
if (KEY_PRESSED == m_players[pindex]->w_pressed)
|
||||||
if (KEY_PRESSED == s_pressed)
|
{
|
||||||
{
|
double direction = m_players[pindex]->direction;
|
||||||
double direction = m_player->direction + M_PI;
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
m_player->x += cos(direction) * move_speed * elapsed_time;
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
m_player->y += sin(direction) * move_speed * elapsed_time;
|
m_players[pindex]->updated = true;
|
||||||
}
|
}
|
||||||
m_player->direction -= M_PI * 0.5 * rel_mouse_movement / 1000;
|
if (KEY_PRESSED == m_players[pindex]->s_pressed)
|
||||||
|
{
|
||||||
|
double direction = m_players[pindex]->direction + M_PI;
|
||||||
|
m_players[pindex]->x += cos(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->y += sin(direction) * move_speed * elapsed_time;
|
||||||
|
m_players[pindex]->updated = true;
|
||||||
|
}
|
||||||
|
if(0 != m_players[pindex]->rel_mouse_movement)
|
||||||
|
{
|
||||||
|
m_players[pindex]->direction -= M_PI * 0.5 * m_players[pindex]->rel_mouse_movement / 1000;
|
||||||
|
m_players[pindex]->updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
server_packet.clear();
|
server_packet.clear();
|
||||||
|
|
||||||
// Send the player update if there were changes
|
|
||||||
if((player_prev.direction != m_player->direction) ||
|
|
||||||
(player_prev.x != m_player->x) ||
|
|
||||||
(player_prev.y != m_player->y))
|
|
||||||
{
|
|
||||||
server_packet << m_player->direction;
|
|
||||||
server_packet << m_player->x;
|
|
||||||
server_packet << m_player->y;
|
|
||||||
m_net_server->sendData(server_packet);
|
|
||||||
|
|
||||||
player_prev.direction = m_player->direction;
|
|
||||||
player_prev.x = m_player->x;
|
|
||||||
player_prev.y = m_player->y;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Send the player update if there were changes
|
||||||
|
if(m_players[pindex]->updated)
|
||||||
|
{
|
||||||
|
sf::Uint8 ptype = PLAYER_UPDATE;
|
||||||
|
server_packet << ptype;
|
||||||
|
server_packet << pindex;
|
||||||
|
server_packet << m_players[pindex]->direction;
|
||||||
|
server_packet << m_players[pindex]->x;
|
||||||
|
server_packet << m_players[pindex]->y;
|
||||||
|
m_net_server->sendData(server_packet);
|
||||||
|
m_players[pindex]->updated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
m_net_server->Transmit();
|
m_net_server->Transmit();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "refptr.h"
|
#include "refptr.h"
|
||||||
|
#include "SFML/Config.hpp"
|
||||||
|
|
||||||
class Server{
|
class Server{
|
||||||
public:
|
public:
|
||||||
@ -11,6 +12,6 @@ class Server{
|
|||||||
protected:
|
protected:
|
||||||
void update(double elapsed_time);
|
void update(double elapsed_time);
|
||||||
refptr<Network> m_net_server;
|
refptr<Network> m_net_server;
|
||||||
refptr<Player> m_player;
|
std::map<sf::Uint8, refptr<Player> > m_players;
|
||||||
sf::Clock m_clock;
|
sf::Clock m_clock;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user