Commit 5ff933cc authored by louiz’'s avatar louiz’

Big ugly commit, but mostly MPFRcpp. #86

Use mpfr for world positions and heights.
Add a visible hud
Change some little camera/selection/movement stuff
And maybe other things.
parent 9388c004
......@@ -71,4 +71,5 @@ EntityEvent::EntityEvent(const Command* command):
else
this->valid = true;
}
unsigned long int Event::current_id = 0;
......@@ -12,9 +12,12 @@
#ifndef __EVENT_HPP__
# define __EVENT_HPP__
#include <world/entity.hpp>
#include <serialization/serializable.hpp>
#include <world/serializable_entity.hpp>
#include <network/command.hpp>
#include <mpreal/mpreal.h>
using namespace mpfr;
class Event: public Serializable
{
......@@ -113,7 +116,7 @@ private:
class EntityEvent: public ActionEvent
{
public:
EntityEvent(Entity* entity):
EntityEvent(SerializableEntity* entity):
ActionEvent("NEW_ENTITY"),
entity(entity)
{}
......@@ -129,7 +132,7 @@ public:
ActionEvent::serialize(ar, v);
ar & entity;
}
Entity* entity;
SerializableEntity* entity;
private:
EntityEvent(const EntityEvent&);
......@@ -153,8 +156,8 @@ public:
}
std::vector<unsigned short> actors_ids;
unsigned int x;
unsigned int y;
uint x;
uint y;
private:
MoveEvent(const MoveEvent&);
......@@ -187,8 +190,8 @@ public:
y(e.y)
{}
std::vector<unsigned short> actors_ids;
unsigned int x;
unsigned int y;
uint x;
uint y;
};
#endif // __EVENT_HPP__
......
......@@ -29,8 +29,6 @@ void TurnHandler::tick(bool force)
this->turn_advancement += 1;
if (this->turn_advancement == TURN_TIME)
{
if (force == false)
log_debug(*this);
if ((this->is_next_turn_validated() == false) && (force == false))
{
log_debug("Next turn is not validated");
......
......@@ -6,7 +6,7 @@ Camera::Camera(ClientWorld* world, GraphMap* map, sf::RenderWindow* win):
y(0),
zoom(1),
focused(true),
movement_speed(0.2),
movement_speed(0.35),
previous_position(0, 0),
start_drag_position(0, 0),
world(world),
......@@ -19,53 +19,170 @@ Camera::~Camera()
{
}
void Camera::draw_entity(const Entity* entity)
void Camera::draw_entity(const Entity* entity, const uint x, const uint y,
const bool in_mouse_selection, sf::RectangleShape& rectangle)
{
// TODO check against its position, etc.
sf::CircleShape circle;
circle.setRadius(entity->width / 2);
if (entity->is_selected())
circle.setOutlineColor(sf::Color::Red);
else
circle.setOutlineColor(sf::Color::Blue);
circle.setOutlineThickness(5);
circle.setPosition(entity->x, entity->y);
this->win->draw(circle);
std::ostringstream os;
os << entity->health;
sf::Text health_text(os.str());
health_text.setPosition(entity->x - 5, entity->y - 40);
this->win->draw(health_text);
if (in_mouse_selection)
{
sf::CircleShape in_mouse_circle;
in_mouse_circle.setRadius(entity->width/2 + 6);
in_mouse_circle.setOutlineColor(sf::Color(0x32, 0xcb, 0x36, 40));
in_mouse_circle.setFillColor(sf::Color::Transparent);
in_mouse_circle.setOutlineThickness(2);
in_mouse_circle.setPosition(x - entity->width/2 - 6, y - entity->width + 4);
in_mouse_circle.setScale(sf::Vector2f(1, 3.f/4.f));
this->win->draw(in_mouse_circle);
}
if (entity->selected)
{
sf::CircleShape selection_circle;
selection_circle.setRadius(entity->width/2 + 8);
selection_circle.setOutlineColor(sf::Color(0x32, 0xcb, 0x36, 100));
selection_circle.setFillColor(sf::Color::Transparent);
selection_circle.setOutlineThickness(3);
selection_circle.setPosition(x - entity->width/2 - 8, y - entity->width + 5);
selection_circle.setScale(sf::Vector2f(1, 3.f/4.f));
this->win->draw(selection_circle);
}
rectangle.setPosition(x - entity->width/2, y - entity->width);
this->win->draw(rectangle);
}
void Camera::handle_event(const sf::Event& event)
bool Camera::handle_event(const sf::Event& event)
{
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == 0)
if (event.type == sf::Event::LostFocus)
this->focused = false;
else if (event.type == sf::Event::GainedFocus)
this->focused = true;
else if (event.type == sf::Event::MouseButtonPressed)
{
switch (event.mouseButton.button)
{
case sf::Mouse::Left:
this->handle_left_click(event);
break;
case sf::Mouse::Middle:
this->handle_middle_click(event);
break;
case sf::Mouse::Right:
this->handle_right_click(event);
break;
default:
log_debug("Mouse button not implemented.");
}
}
else if (event.type == sf::Event::MouseButtonReleased)
{
switch (event.mouseButton.button)
{
case sf::Mouse::Left:
this->handle_left_release(event);
break;
case sf::Mouse::Middle:
this->handle_middle_release(event);
break;
default:
log_debug("Mouse button not implemented.");
}
}
if (event.type == sf::Event::MouseButtonPressed &&
event.mouseButton.button == sf::Mouse::Middle)
{
this->previous_position = sf::Mouse::getPosition(*this->win);
this->start_drag_position = this->previous_position;
this->win->setMouseCursorVisible(false);
}
if (event.type == sf::Event::MouseButtonReleased && event.mouseButton.button == sf::Mouse::Middle)
else if (event.type == sf::Event::MouseButtonReleased &&
event.mouseButton.button == sf::Mouse::Middle)
{
sf::Mouse::setPosition(this->start_drag_position);
this->win->setMouseCursorVisible(true);
this->previous_position = sf::Vector2i(0, 0);
}
this->fixup_camera_position();
if (this->mouse_selection.ongoing == true)
return true;
return false;
}
void Camera::handle_middle_click(const sf::Event& event)
{
}
void Camera::handle_right_click(const sf::Event& event)
{
const sf::Vector2u pos = this->camera_to_world_position(event.mouseButton.x,
event.mouseButton.y);
int x;
int y;
this->world->get_cell_at_position(pos.x,
pos.y,
x, y);
this->world->handle_event(actions::Move, pos.x, pos.y);
}
void Camera::handle_left_click(const sf::Event& event)
{
// TODO do nothing if the click is not in the screen.
const sf::Vector2i pos(event.mouseButton.x + this->x,
event.mouseButton.y + this->y);
this->mouse_selection.start(pos);
}
void Camera::handle_left_release(const sf::Event& event)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::RShift) ||
sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
this->add_mouse_selection_to_selection();
else
this->set_mouse_selection_to_selection();
}
void Camera::set_mouse_selection_to_selection()
{
this->world->reset_entity_iterator();
Entity* entity;
sf::Vector2i mouse_pos = sf::Mouse::getPosition(*this->win);
mouse_pos.x += this->x;
mouse_pos.y += this->y;
while ((entity = this->world->get_next_entity()) != 0)
{
if (this->mouse_selection.contains(mouse_pos,
this->world_to_camera_position(entity->x, entity->y),
entity->width + 4))
entity->selected = true;
else
entity->selected = false;
}
this->mouse_selection.end();
}
void Camera::add_mouse_selection_to_selection()
{
this->world->reset_entity_iterator();
Entity* entity;
sf::Vector2i mouse_pos = sf::Mouse::getPosition(*this->win);
mouse_pos.x += this->x;
mouse_pos.y += this->y;
while ((entity = this->world->get_next_entity()) != 0)
{
if (this->mouse_selection.contains(mouse_pos,
this->world_to_camera_position(entity->x, entity->y),
entity->width + 4))
entity->selected = true;
}
this->mouse_selection.end();
}
void Camera::handle_middle_release(const sf::Event& event)
{
}
void Camera::update(const Duration& dt)
{
sf::Vector2i pos = sf::Mouse::getPosition(*this->win);
const sf::Vector2u win_size = this->win->getSize();
if (sf::Mouse::isButtonPressed(sf::Mouse::Middle) &&
(this->previous_position != sf::Vector2i(0, 0)))
{
this->x -= 2 * this->movement_speed * sec(dt) * (this->previous_position.x - pos.x);
this->y -= 2 * this->movement_speed * sec(dt) * (this->previous_position.y - pos.y);
this->previous_position = sf::Vector2i(pos.x, pos.y);
}
else if (this->focused)
if (this->focused)
{
if ((pos.x > 0) && (static_cast<uint>(pos.x) > (win_size.x - 2)))
pos.x = (win_size.x - 2);
......@@ -85,14 +202,7 @@ void Camera::update(const Duration& dt)
if ((pos.x > 0) && static_cast<uint>(pos.x) > (win_size.x - 20))
this->x += this->movement_speed * sec(dt);
}
if (this->x < 0)
this->x = 0;
else if (this->x > (this->map->get_width_in_pixels() - win_size.x))
this->x = this->map->get_width_in_pixels() - win_size.x;
if (this->y < 0)
this->y = 0;
else if (this->y > (this->map->get_height_in_pixels() - win_size.y))
this->y = this->map->get_height_in_pixels() - win_size.y;
this->fixup_camera_position();
}
void Camera::draw()
......@@ -101,40 +211,47 @@ void Camera::draw()
Layer* layer;
uint yoffset;
uint xoffset = 0;
/**
* The position of the layer tile containing the top left
* corner of the camera.
*/
uint start_y = static_cast<uint>(this->y) / TILE_HEIGHT * 2;
if (start_y > 0)
start_y--;
start_y -= start_y % 2;
uint end_y = start_y + win_size.y / TILE_HEIGHT * 2 + 4;
// The position of the layer tile containing the top left corner of the
//camera.
uint start_y = static_cast<uint>(this->y) / TILE_HEIGHT;
uint end_y = start_y + win_size.y / TILE_HEIGHT + 2;
uint start_x = static_cast<uint>(this->x) / TILE_WIDTH;
if (start_x > 0)
start_x--;
uint end_x = start_x + win_size.x / TILE_WIDTH + 4;
uint end_x = start_x + win_size.x / TILE_WIDTH + 2;
int cellx;
int celly;
this->world->sort_entities();
GraphTile* tile;
uint level = 0;
this->world->sort_entities();
std::vector<std::vector<Entity*> > entities;
entities.resize(5);
this->world->reset_entity_iterator();
Entity* entity;
this->map->reset_layers_iterator();
while ((layer = this->map->get_next_layer()) != 0)
sf::Vector2i mouse_pos = sf::Mouse::getPosition(*this->win);
mouse_pos.x += this->x;
mouse_pos.y += this->y;
sf::RectangleShape rectangle(sf::Vector2f(30, 30));
rectangle.setOutlineColor(sf::Color::Blue);
rectangle.setOutlineThickness(1);
int level;
for (uint y = start_y;
y < end_y;
y++)
{
if (layer->cells == 0)
continue ;
if (end_y >= layer->height)
end_y = layer->height - 1;
if (end_x >= layer->width * 2)
end_x = layer->width * 2 - 1;
xoffset = 0;
yoffset = level++ * LEVEL_HEIGHT;
for (uint y = start_y;
y < end_y;
y++)
this->map->reset_layers_iterator();
level = 0;
yoffset = (level * LEVEL_HEIGHT);
while ((layer = this->map->get_next_layer()) != 0)
{
if (layer->cells == 0)
{
level++;
continue;
}
yoffset = (level * LEVEL_HEIGHT);
for (uint x = start_x;
x < end_x;
x++)
......@@ -143,15 +260,113 @@ void Camera::draw()
tile = this->map->tiles[gid];
if (tile != 0)
{
tile->sprite.setPosition(x * TILE_WIDTH + xoffset - this->x,
y * TILE_HEIGHT/2 - yoffset - this->y);
tile->sprite.setColor(sf::Color::White);
tile->sprite.setPosition(x * TILE_WIDTH - this->x,
- 64 + y * TILE_HEIGHT - yoffset - this->y);
this->win->draw(tile->sprite);
}
}
if (xoffset != 0)
xoffset = 0;
else
xoffset = TILE_WIDTH/2;
// Draw entites on that line.
std::vector<Entity*> entities_at_that_level = entities[level];
std::vector<Entity*>::iterator it;
int i = 0;
this->world->reset_entity_iterator();
while ((entity = this->world->get_next_entity()) != 0)
{
this->world->get_cell_at_position(entity->x, entity->y, cellx, celly);
sf::Vector2u entpos = this->world_to_camera_position(entity->x, entity->y);
if ((celly == y) && ((entpos.x > this->x) && (entpos.x < this->x + win_size.x) &&
(entpos.y > this->y) && (entpos.y < this->y + win_size.y)))
{
this->draw_entity(entity, entpos.x - this->x, entpos.y - this->y,
this->mouse_selection.contains(mouse_pos,
entpos, entity->width + 4),
rectangle);
}
}
level++;
}
}
this->draw_mouse_selection();
}
void Camera::draw_mouse_selection()
{
if (this->mouse_selection.ongoing == false)
return ;
sf::Vector2i mouse_pos = sf::Mouse::getPosition(*this->win);
mouse_pos.x += this->x;
mouse_pos.y += this->y;
sf::RectangleShape rect(sf::Vector2f(::abs(mouse_pos.x - this->mouse_selection.start_pos.x),
::abs(mouse_pos.y- this->mouse_selection.start_pos.y)));
rect.setOutlineThickness(1);
rect.setFillColor(sf::Color(0x32, 0xcb, 0x36, 40));
rect.setOutlineColor(sf::Color(0x32, 0xcb, 0x36));
sf::Vector2f rect_pos;
if (this->mouse_selection.start_pos.x < mouse_pos.x)
rect_pos.x = this->mouse_selection.start_pos.x - this->x;
else
rect_pos.x = mouse_pos.x - this->x;
if (this->mouse_selection.start_pos.y < mouse_pos.y)
rect_pos.y = this->mouse_selection.start_pos.y - this->y;
else
rect_pos.y = mouse_pos.y - this->y;
rect.setPosition(rect_pos);
this->win->draw(rect);
}
void Camera::fixup_camera_position()
{
const sf::Vector2u win_size = this->win->getSize();
if (this->x < 0)
this->x = 0;
else if (this->x > (this->map->get_width_in_pixels() - win_size.x))
this->x = this->map->get_width_in_pixels() - win_size.x;
if (this->y < 0)
this->y = 0;
else if (this->y > (this->map->get_height_in_pixels() - win_size.y))
this->y = this->map->get_height_in_pixels() - win_size.y;
}
sf::Vector2u Camera::world_to_camera_position(const mpreal& x, const mpreal& y) const
{
sf::Vector2u res;
res.x = ((x * TILE_WIDTH) / CELL_SIZE).toLong();
res.y = ((y * TILE_HEIGHT) / CELL_SIZE).toLong();
mpreal height = this->world->get_position_height(x, y) * 32;
res.y -= height.toLong();
return res;
}
sf::Vector2u Camera::camera_to_world_position(const int x,
const int y) const
{
sf::Vector2u res;
const uint cell_size = static_cast<const uint>(CELL_SIZE);
res.x = (x + this->x) * (CELL_SIZE / static_cast<const float>(TILE_WIDTH));
res.y = (y + this->y) * (CELL_SIZE / static_cast<const float>(TILE_HEIGHT));
uint offset = (cell_size - (res.y % cell_size));
uint i = 0;
mpreal height_of_bottom_cell = this->world->get_position_height(res.x, res.y + offset);
if (height_of_bottom_cell > ((offset) * (1.f/LAYER_HEIGHT)))
res.y += (height_of_bottom_cell * LAYER_HEIGHT).toLong();
else
{
offset += cell_size;
height_of_bottom_cell = this->world->get_position_height(res.x, res.y + offset);
if (height_of_bottom_cell > (offset * (1.f/LAYER_HEIGHT)))
res.y += (height_of_bottom_cell * LAYER_HEIGHT).toLong();
else
{
mpreal height_of_current_cell = this->world->get_position_height(res.x, res.y);
res.y += (height_of_current_cell * LAYER_HEIGHT).toLong();
}
}
return res;
}
bool Camera::is_mouse_selection_ongoing() const
{
return this->mouse_selection.ongoing;
}
......@@ -9,16 +9,21 @@
* @class Camera
*/
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#ifndef __CAMERA__HPP__
# define __CAMERA__HPP__
#include <cstdlib>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <logging/logging.hpp>
#include <world/client_world.hpp>
#include <world/time.hpp>
#include <gui/camera/map.hpp>
#include <gui/camera/mouse_selection.hpp>
#include <mpreal/mpreal.h>
using namespace mpfr;
class Minimap;
......@@ -32,15 +37,54 @@ public:
* Draw the world viewed through the camera.
*/
void draw();
/**
* Draw the rectangle representing the mouse selection.
*/
void draw_mouse_selection();
/**
* Draw the entity on the screen, taking the on-screen position of the
* entity.
*/
void draw_entity(const Entity* entity, const uint x, const uint y,
const bool in_mouse_selection, sf::RectangleShape& rectangle);
/**
* handle one user input event.
*/
void handle_event(const sf::Event&);
bool handle_event(const sf::Event&);
void handle_right_click(const sf::Event&);
void handle_middle_click(const sf::Event&);
void handle_left_click(const sf::Event&);
void handle_left_release(const sf::Event&);
void handle_middle_release(const sf::Event&);
/**
* Update the camera position or other stuff according to previous
* input etc.
*/
void update(const Duration& dt);
sf::Vector2u world_to_camera_position(const mpreal&, const mpreal&) const;
sf::Vector2u camera_to_world_position(const int, const int) const;
/**
* Start a mouse selection, i.e. drawing a rectangle to select entities
* inside it. The position is a world-static position, not a camera
* position; this means that if the camera moves while there's an ongoing
* mouse selection, the start position of the mouse selection may go out
* of the camera's sight.
*/
void start_mouse_selection(const sf::Vector2u& pos);
/**
* Takes everything under mouse selection and add it to the selection.
*/
void add_mouse_selection_to_selection();
/**
* Takes everything under mouse selection and set it as the selection.
* Replaces the previous selection completely.
*/
void set_mouse_selection_to_selection();
/**
* Returns whether or not a mouse selection (by dragging) is currently
* ongoing or not.
*/
bool is_mouse_selection_ongoing() const;
private:
Camera(const Camera&);
......@@ -50,6 +94,10 @@ private:
* Does nothing otherwise.
*/
void draw_entity(const Entity*);
/**
* Check if the camera is at a valid position. If not, fix it.
*/
void fixup_camera_position();
/**
* The left position of the camera
*/
......@@ -86,6 +134,7 @@ private:
ClientWorld* world;
GraphMap* map;
sf::RenderWindow* win;
MouseSelection mouse_selection;
};
#endif // __CAMERA__HPP__
......@@ -27,9 +27,9 @@ GraphMap::~GraphMap()
bool GraphMap::load_from_file(const std::string& map_name, bool load_minimap)
{
// TODO, don't duplicate parsing.
Map::load_from_file(map_name);
std::string filename(MAPS_DIRECTORY);
filename += map_name;
Map::load_from_file(filename);
if (load_minimap)
{
......@@ -138,7 +138,6 @@ void GraphMap::draw_full_map(sf::RenderTarget& target)
{
if (layer->cells == 0)
continue ;
uint xoffset = 0;
uint yoffset = level++ * LEVEL_HEIGHT;
for (uint y = 0;
y < layer->height;
......@@ -152,15 +151,11 @@ void GraphMap::draw_full_map(sf::RenderTarget& target)
tile = this->tiles[gid];
if (tile != 0)
{
tile->sprite.setPosition(x * TILE_WIDTH + xoffset,
y * TILE_HEIGHT/2 - yoffset);
tile->sprite.setPosition(x * TILE_WIDTH,
-64 + y * TILE_HEIGHT - yoffset);
target.draw(tile->sprite);
}
}
if (xoffset != 0)
xoffset = 0;
else
xoffset = TILE_WIDTH/2;
}