Merged in holtrop/master

This commit is contained in:
xethm55 2012-10-01 21:22:50 -04:00
commit 7c7b4a7088
7 changed files with 217 additions and 71 deletions

View File

@ -1,5 +1,5 @@
void main(void)
{
gl_FragColor = vec4(1.0, 0.1, 0.1, 1.0);
gl_FragColor = vec4(1.0, 0.1, 0.1, 0.5);
}

View File

@ -2,12 +2,13 @@
uniform mat4 projection;
uniform mat4 modelview;
uniform float scale;
uniform float width;
/* pos.xyz is position, pos.w is offset */
/* pos.xyz is position, pos.w is 0/1 for inner/outer ring */
attribute vec4 pos;
void main(void)
{
vec3 pos3 = pos.xyz * (scale + pos.w);
vec3 pos3 = pos.xyz * (scale + width * pos.w);
gl_Position = projection * modelview * vec4(pos3, 1);
}

View File

@ -17,7 +17,7 @@ using namespace std;
#define SKY_DIST 2000
#define NUM_SKY_STEPS 9
#define LAVA_SIZE 100
#define SHOT_RING_WIDTH 20.0f
#define SHOT_RING_WIDTH 10.0f
#define NUM_SHOT_RING_STEPS 24
/* points of a horizontal hexagon 1.0 units high */
@ -125,6 +125,12 @@ bool Client::initgl()
"pos", 0, "tex_coord", 1, NULL,
"projection", "modelview", "tex", "shift", NULL))
return false;
if (!m_shot_ring_program.create(
CFS.get_file("shaders/shot-ring.v.glsl"),
CFS.get_file("shaders/shot-ring.f.glsl"),
"pos", 0, NULL,
"projection", "modelview", "scale", "width", NULL))
return false;
if (!m_tank_obj.load("models/tank.obj", load_file))
{
cerr << "Error loading tank model" << endl;
@ -199,7 +205,7 @@ bool Client::initgl()
shot_ring_attributes[idx++] = x;
shot_ring_attributes[idx++] = y;
shot_ring_attributes[idx++] = 0.0f;
shot_ring_attributes[idx++] = SHOT_RING_WIDTH;
shot_ring_attributes[idx++] = 1.0f;
}
if (!m_shot_ring_attributes.create(GL_ARRAY_BUFFER, GL_STATIC_DRAW,
&shot_ring_attributes[0],
@ -221,7 +227,7 @@ bool Client::initgl()
cerr << "Error creating lava texture" << endl;
return false;
}
m_obj_program.use();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
return true;
}
@ -240,27 +246,31 @@ void Client::redraw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
double dir_x = cos(m_players[current_player]->direction);
double dir_y = sin(m_players[current_player]->direction);
m_modelview.load_identity();
m_modelview.look_at(
m_players[current_player]->x - dir_x * 25, m_players[current_player]->y - dir_y * 25, 30,
m_players[current_player]->x, m_players[current_player]->y, 20,
0, 0, 1);
// TODO: call draw_player() for each networked player
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
if (m_players.size() > 0)
{
draw_player(piter->second);
m_modelview.load_identity();
m_modelview.look_at(
m_players[m_current_player]->x - m_player_dir_x * 25,
m_players[m_current_player]->y - m_player_dir_y * 25,
30,
m_players[m_current_player]->x,
m_players[m_current_player]->y,
20,
0, 0, 1);
for(std::map<sf::Uint8, refptr<Player> >::iterator piter = m_players.begin(); piter != m_players.end(); piter++)
{
draw_player(piter->second);
}
draw_map();
draw_sky();
draw_lava();
draw_shot_ring();
draw_overlay();
}
draw_map();
draw_sky();
draw_lava();
draw_overlay();
m_window->display();
}
@ -379,15 +389,15 @@ void Client::draw_overlay()
overlay_size, overlay_size);
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_overlay_program.use();
GLMatrix proj;
const float span = 50 * 8;
proj.ortho(-span, span, -span, span, -1, 1);
proj.to_uniform(m_overlay_program.uniform("projection"));
GLMatrix modelview;
modelview.rotate(90 - m_players[current_player]->direction * 180 / M_PI, 0, 0, 1);
modelview.translate(-m_players[current_player]->x, -m_players[current_player]->y, 0);
modelview.rotate(90 - m_players[m_current_player]->direction * 180 / M_PI, 0, 0, 1);
modelview.translate(-m_players[m_current_player]->x,
-m_players[m_current_player]->y, 0);
m_overlay_hex_attributes.bind();
m_overlay_hex_indices.bind();
glEnableVertexAttribArray(0);
@ -438,8 +448,8 @@ void Client::draw_overlay()
GLMatrix::Identity.to_uniform(
m_overlay_hover_program.uniform("projection"));
modelview.load_identity();
modelview.translate(m_players[current_player]->hover - 1, 0, 0);
modelview.scale(m_players[current_player]->hover * 2, 2.0, 1.0);
modelview.translate(m_players[m_current_player]->hover - 1, 0, 0);
modelview.scale(m_players[m_current_player]->hover * 2, 2.0, 1.0);
modelview.to_uniform(m_overlay_hover_program.uniform("modelview"));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@ -479,8 +489,10 @@ void Client::draw_sky()
m_sky_attributes.bind();
m_projection.to_uniform(m_sky_program.uniform("projection"));
m_modelview.push();
m_modelview.translate(m_players[current_player]->x, m_players[current_player]->y, 0);
m_modelview.rotate(m_players[current_player]->direction * 180.0 / M_PI, 0, 0, 1);
m_modelview.translate(m_players[m_current_player]->x,
m_players[m_current_player]->y, 0);
m_modelview.rotate(m_players[m_current_player]->direction * 180.0 / M_PI,
0, 0, 1);
m_modelview.to_uniform(m_sky_program.uniform("modelview"));
m_modelview.pop();
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
@ -528,3 +540,49 @@ void Client::draw_lava()
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
}
void Client::draw_shot_ring()
{
if (m_drawing_shot)
{
m_shot_ring_program.use();
m_shot_ring_attributes.bind();
glEnableVertexAttribArray(0);
m_modelview.push();
m_modelview.translate(m_players[m_current_player]->x,
m_players[m_current_player]->y, 0.4);
m_projection.to_uniform(m_shot_ring_program.uniform("projection"));
m_modelview.to_uniform(m_shot_ring_program.uniform("modelview"));
glUniform1f(m_shot_ring_program.uniform("scale"),
m_drawing_shot_distance);
glUniform1f(m_shot_ring_program.uniform("width"), SHOT_RING_WIDTH);
draw_shot_ring_instance();
float mid_dist = m_drawing_shot_distance + SHOT_RING_WIDTH / 2.0;
m_modelview.translate(mid_dist * m_player_dir_x,
mid_dist * m_player_dir_y, 0.01);
m_modelview.to_uniform(m_shot_ring_program.uniform("modelview"));
glUniform1f(m_shot_ring_program.uniform("scale"),
0.45 * SHOT_RING_WIDTH);
glUniform1f(m_shot_ring_program.uniform("width"),
0.05 * SHOT_RING_WIDTH);
draw_shot_ring_instance();
m_modelview.pop();
glDisableVertexAttribArray(0);
}
}
void Client::draw_shot_ring_instance()
{
glEnable(GL_BLEND);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), NULL);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (NUM_SHOT_RING_STEPS + 1) * 2);
glDisable(GL_BLEND);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE,
8 * sizeof(GLfloat), NULL);
glDrawArrays(GL_LINE_STRIP, 0, NUM_SHOT_RING_STEPS + 1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE,
8 * sizeof(GLfloat), (void *) (4 * sizeof(GLfloat)));
glDrawArrays(GL_LINE_STRIP, 0, NUM_SHOT_RING_STEPS + 1);
}

View File

@ -3,13 +3,19 @@
#include "Types.h"
#include "Timer.h"
/* TODO: this should be moved to common somewhere */
#define MAX_SHOT_DISTANCE 250.0
#define SHOT_EXPAND_SPEED 75.0
Client::Client()
{
m_net_client = new Network();
m_net_client->Create(59243, "127.0.0.1"); // Just connect to local host for now - testing
client_has_focus = true;
m_client_has_focus = true;
m_players.clear();
current_player = 0;
m_current_player = 0;
m_left_button_pressed = false;
m_drawing_shot = false;
}
Client::~Client()
@ -23,7 +29,7 @@ Client::~Client()
client_timer.Init();
client_packet.clear();
client_packet << packet_type;
client_packet << current_player;
client_packet << m_current_player;
m_net_client->sendData(client_packet, true);
// No time out needed here, since the
@ -51,7 +57,7 @@ Client::~Client()
// This completely removes the player from the game
// Deletes member from the player list
client_packet >> player_index;
if(player_index == current_player)
if(player_index == m_current_player)
{
connection_closed = true;
}
@ -82,7 +88,7 @@ void Client::run(bool fullscreen, int width, int height, std::string pname)
{
Timer client_timer;
client_timer.Init();
current_player_name = pname;
m_current_player_name = pname;
if (!create_window(fullscreen, width, height))
return;
m_clock.restart();
@ -112,14 +118,26 @@ void Client::run(bool fullscreen, int width, int height, std::string pname)
break;
}
break;
case sf::Event::MouseButtonPressed:
if (event.mouseButton.button == sf::Mouse::Left)
m_left_button_pressed = true;
break;
case sf::Event::MouseButtonReleased:
if (event.mouseButton.button == sf::Mouse::Left)
{
m_drawing_shot = false;
m_left_button_pressed = false;
/* TODO: trigger shot network message */
}
break;
case sf::Event::Resized:
resize_window(event.size.width, event.size.height);
break;
case sf::Event::LostFocus:
client_has_focus = false;
m_client_has_focus = false;
break;
case sf::Event::GainedFocus:
client_has_focus = true;
m_client_has_focus = true;
break;
default:
break;
@ -132,10 +150,7 @@ void Client::run(bool fullscreen, int width, int height, std::string pname)
client_timer.Update();
update(elapsed_time);
if(m_players.size() > 0)
{
redraw();
}
redraw();
last_time = current_time;
// temporary for now. otherwise this thread consumed way too processing
@ -148,7 +163,6 @@ void Client::update(double elapsed_time)
static bool registered_player = false;
sf::Packet client_packet;
m_net_client->Receive();
client_packet.clear();
// Handle all received data (only really want the latest)
@ -168,10 +182,9 @@ void Client::update(double elapsed_time)
client_packet >> players_port;
// Should be a much better way of doing this.
// Perhaps generate a random number
if((name == current_player_name) &&
(m_net_client->getLocalPort() == players_port))
if(name == m_current_player_name)
{
current_player = pindex;
m_current_player = pindex;
}
// Create a new player if one does not exist.
@ -235,7 +248,7 @@ void Client::update(double elapsed_time)
// 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(m_client_has_focus)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
{
@ -255,19 +268,46 @@ void Client::update(double elapsed_time)
}
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 (m_left_button_pressed)
{
if (m_drawing_shot)
{
m_drawing_shot_distance += SHOT_EXPAND_SPEED * elapsed_time;
if (m_drawing_shot_distance > MAX_SHOT_DISTANCE)
m_drawing_shot_distance = MAX_SHOT_DISTANCE;
}
else
{
m_drawing_shot = true;
m_drawing_shot_distance = 0.0f;
}
}
}
/* decrease player hover when not over a tile */
if (m_map.get_tile_at(m_players[m_current_player]->x,
m_players[m_current_player]->y).isNull())
{
m_players[m_current_player]->hover -= elapsed_time / 10;
if (m_players[m_current_player]->hover < 0)
m_players[m_current_player]->hover = 0;
}
m_player_dir_x = cos(m_players[m_current_player]->direction);
m_player_dir_y = sin(m_players[m_current_player]->direction);
// 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))
if((m_players[m_current_player]->w_pressed != w_pressed) ||
(m_players[m_current_player]->a_pressed != a_pressed) ||
(m_players[m_current_player]->s_pressed != s_pressed) ||
(m_players[m_current_player]->d_pressed != d_pressed) ||
(m_players[m_current_player]->rel_mouse_movement != rel_mouse_movement))
{
sf::Uint8 packet_type = PLAYER_UPDATE;
client_packet.clear();
client_packet << packet_type;
client_packet << current_player;
client_packet << m_current_player;
client_packet << w_pressed;
client_packet << a_pressed;
client_packet << s_pressed;
@ -276,11 +316,11 @@ void Client::update(double elapsed_time)
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;
m_players[m_current_player]->w_pressed = w_pressed;
m_players[m_current_player]->a_pressed = a_pressed;
m_players[m_current_player]->s_pressed = s_pressed;
m_players[m_current_player]->d_pressed = d_pressed;
m_players[m_current_player]->rel_mouse_movement = rel_mouse_movement;
}
}
else if(!registered_player)
@ -290,8 +330,8 @@ void Client::update(double elapsed_time)
sf::Uint8 packet_type = PLAYER_CONNECT;
client_packet.clear();
client_packet << packet_type;
client_packet << current_player;
client_packet << current_player_name;
client_packet << m_current_player;
client_packet << m_current_player_name;
// Send the players port. This will server as a unique
// identifier and prevent users with the same name from controlling
// each other.

View File

@ -29,12 +29,16 @@ class Client
void draw_overlay();
void draw_sky();
void draw_lava();
void draw_shot_ring();
void draw_shot_ring_instance();
double m_player_dir_x;
double m_player_dir_y;
refptr<sf::Window> m_window;
sf::Clock m_clock;
Map m_map;
sf::Uint8 current_player;
std::string current_player_name;
sf::Uint8 m_current_player;
std::string m_current_player_name;
std::map<sf::Uint8, refptr<Player> > m_players;
int m_width;
int m_height;
@ -43,6 +47,7 @@ class Client
GLProgram m_overlay_hover_program;
GLProgram m_sky_program;
GLProgram m_lava_program;
GLProgram m_shot_ring_program;
WFObj m_tank_obj;
WFObj m_tile_obj;
GLMatrix m_projection;
@ -54,8 +59,11 @@ class Client
GLBuffer m_quad_attributes;
GLBuffer m_shot_ring_attributes;
refptr<Network> m_net_client;
bool client_has_focus;
bool m_client_has_focus;
sf::Texture m_lava_texture;
bool m_left_button_pressed;
bool m_drawing_shot;
float m_drawing_shot_distance;
};
#endif

View File

@ -3,6 +3,15 @@
using namespace std;
/*
* The center of the tile at m_grid[i][j] is (x, y) where
* x = j * m_span_x + m_offset_x
* y = (i + ((j & 1) ? 0.5 : 0.0) * m_tile_size + m_offset_y
*
* The rectangular bounding box for a hex tile centered at (x, y)
* are ((x - HEX_WIDTH_TO_HEIGHT * m_tile_size / 2, y - m_tile_size / 2),
* (x + HEX_WIDTH_TO_HEIGHT * m_tile_size / 2, y + m_tile_size / 2))
*/
Map::Map(int width, int height, float tile_size)
{
m_width = width;
@ -10,13 +19,13 @@ Map::Map(int width, int height, float tile_size)
m_tile_size = tile_size;
/* construction of default map */
float span_x = HEX_WIDTH_TO_HEIGHT * 0.75 * tile_size;
float offset_x = -span_x * (width / 2.0);
float offset_y = -tile_size * (height / 2.0);
m_span_x = HEX_WIDTH_TO_HEIGHT * 0.75 * tile_size;
m_offset_x = -m_span_x * (width / 2.0);
m_offset_y = -tile_size * (height / 2.0);
HexTile outer_out(0, 0, 0.85 * span_x * width);
HexTile outer_in(0, 0, 0.5 * span_x * width);
HexTile inner_out(0, 0, 0.30 * span_x * width);
HexTile outer_out(0, 0, 0.85 * m_span_x * width);
HexTile outer_in(0, 0, 0.5 * m_span_x * width);
HexTile inner_out(0, 0, 0.30 * m_span_x * width);
for (int i = 0; i < height; i++)
{
@ -24,13 +33,14 @@ Map::Map(int width, int height, float tile_size)
for (int j = 0; j < width; j++)
{
refptr<HexTile> ht;
float x = j * span_x + offset_x;
float y = (i + ((j & 1) ? 0.5 : 0.0)) * tile_size + offset_y;
float x = j * m_span_x + m_offset_x;
float y = (i + ((j & 1) ? 0.5 : 0.0)) * tile_size + m_offset_y;
if (inner_out.point_within(y, x)
|| (outer_out.point_within(y, x)
&& !outer_in.point_within(y, x)))
{
refptr<HexTile> get_tile_at(float x, float y);
ht = new HexTile(x, y, tile_size);
}
@ -38,3 +48,28 @@ Map::Map(int width, int height, float tile_size)
}
}
}
/*
* Given a point (x, y) return the HexTile, if any, that the point is on.
* A NULL refptr is returned if the point is not on any tile.
*/
refptr<HexTile> Map::get_tile_at(float x, float y)
{
int i_base = (int) ((y - m_offset_y) / m_tile_size);
int j_base = (int) ((x - m_offset_x) / m_span_x);
for (int i_offset = 0; i_offset <= 1; i_offset++)
{
for (int j_offset = 0; j_offset <= 1; j_offset++)
{
int i = i_base + i_offset;
int j = j_base + j_offset;
if (i >= 0 && i < m_height && j >= 0 && j < m_width)
{
if (!m_grid[i][j].isNull())
if (m_grid[i][j]->point_within(x, y))
return m_grid[i][j];
}
}
}
return NULL;
}

View File

@ -11,12 +11,16 @@ class Map
Map(int width=21, int height=21, float tile_size=50);
bool tile_present(int x, int y) { return !m_grid[y][x].isNull(); }
refptr<HexTile> get_tile(int x, int y) { return m_grid[y][x]; }
refptr<HexTile> get_tile_at(float x, float y);
int get_width() { return m_width; }
int get_height() { return m_height; }
protected:
int m_width;
int m_height;
float m_tile_size;
float m_span_x;
float m_offset_x;
float m_offset_y;
std::vector< std::vector< refptr< HexTile > > > m_grid;
};