Implemented grid. Modified map renderer so that it can render tiles that have a different size than the map tiles. (Note: this change is not tested yet).

This commit is contained in:
2016-12-06 00:29:43 +02:00
parent 0dc77aacb4
commit c12a8ede5a
42 changed files with 1090 additions and 288 deletions

View File

@ -0,0 +1,146 @@
/*
* Grid.cpp
*
* Created on: Dec 4, 2016
* Author: tibi
*/
#include <components/basic/Grid.h>
#include <components/basic/Transform.h>
#include <utils/Assert.h>
#include <utils/Exceptions.h>
#include <iostream>
using namespace farmlands::model;
using namespace farmlands::utils;
namespace farmlands {
namespace components {
namespace basic {
Grid::Grid()
: m_bounds(0, 0, 1, 1),
m_grid(nullptr)
{
}
Grid::~Grid()
{
if (m_grid != nullptr)
delete[] m_grid;
}
model::Component* Grid::clone()
{
Grid* clone = new Grid();
clone->m_bounds = m_bounds;
return clone;
}
void Grid::dump(unsigned level)
{
for (unsigned i = 0; i < level; i++)
std::cout<<" ";
std::cout << " .Component: Grid bounds=[";
std::cout << m_bounds.x << "," << m_bounds.y << ",";
std::cout << m_bounds.w << "," << m_bounds.h << "]\n";
}
void Grid::onInitialize()
{
// Allocate memory
m_grid = new model::GameObject*[m_bounds.w * m_bounds.h];
memset(m_grid, 0, sizeof(model::GameObject*) * m_bounds.w * m_bounds.h);
// Add objects
for (auto it = gameObject->childrenBegin(); it != gameObject->childrenEnd(); it++)
{
GameObject* obj = *it;
// Get transform
Transform* tr = obj->component<Transform>();
if (tr == nullptr)
{
std::cerr << "Grid: ignoring object " << obj->name << ": object has no transform.";
continue;
}
// Compute grid position(s)
Rect<int> bounds(tr->x, tr->y, roundf(tr->w), roundf(tr->h));
if (!bounds.intersects(m_bounds))
{
std::cerr << "Grid: ignoring object " << obj->name << ": object outside allowed bounds.";
continue;
}
// Set
for (int y = bounds.y; y < bounds.y + bounds.h; y++)
for (int x = bounds.x; x < bounds.x + bounds.w; x++)
set(obj, x, y, false);
}
}
void Grid::setBounds(const utils::Rect<int>& bounds)
{
if (m_grid == nullptr)
m_bounds = bounds;
else
{
// Get rid of old grid
delete[] m_grid;
m_grid = nullptr;
m_bounds = bounds;
// Reinitialize
onInitialize();
}
}
utils::Rect<int> Grid::bounds() const
{
return m_bounds;
}
model::GameObject* Grid::get(int x, int y)
{
Assert(m_grid != nullptr, "Grid not initialized!!!");
if (m_bounds.contains(x, y))
{
int gx = x - m_bounds.x;
int gy = y - m_bounds.y;
return m_grid[gy * m_bounds.w + gx];
}
return nullptr;
}
void Grid::set(model::GameObject* obj, int x, int y, bool throwOnOverwrite)
{
int gx = x - m_bounds.x;
int gy = y - m_bounds.y;
int index = gy * m_bounds.w + gx;
if (m_grid[index] != nullptr)
{
if (throwOnOverwrite)
THROW(InvalidArgumentException, "Position already occupied!");
else
{
std::cerr << "Grid: cannot set " << obj->name << " to position " << x << ", " << y;
std::cerr << ": cell already occupied";
}
}
m_grid[index] = obj;
}
} /* namespace basic */
} /* namespace components */
} /* namespace farmlands */

View File

@ -0,0 +1,82 @@
/*
* Grid.h
*
* Created on: Dec 4, 2016
* Author: tibi
*/
#ifndef COMPONENTS_BASIC_GRID_H_
#define COMPONENTS_BASIC_GRID_H_
#include <model/Component.h>
#include <model/GameObject.h>
#include <utils/Rect.h>
namespace farmlands {
namespace components {
namespace basic {
/**
* Manages all the children components so that they are in a grid.
* Uses the x and y positions of the game objects to find the grid position.
*
* Positions are read in the initialize method.
* If there are multiple objects in the same cell position, only the first one is considered.
* If there are objects outside the given bounds, they are ignored.
*
*
* Operation:
* After initialization, use get to obtain the element in a specific grid position.
* When adding a game object to the parent, make sure to call "update on the grid".
*
* The update/move methods check if a non-empty cell will be written over, and they throw
* an exception.
*/
class Grid: public model::Component
{
public:
Grid();
virtual ~Grid();
virtual model::Component* clone() override;
virtual void dump(unsigned level) override;
/**
* Initializes the grid component.
*
* When this method gets called, the grid puts all the children game objects in corresponding
* cells. The object transform is used to calculate what cells the objects occupy (x, y, w, h).
*
* If there are multiple objects in the same cell position, only the first one is considered.
* (a warning is printed to stderr).
* Also, if there are objects outside the given bounds, they are ignored.
*/
virtual void onInitialize() override;
// Setters
/**
* Sets the bounds of the grid.
*
* If the bounds are changed after initialization, the positions will be updated.
*/
void setBounds(const utils::Rect<int>& bounds);
// Getters
utils::Rect<int> bounds() const;
// Operations
model::GameObject* get(int x, int y);
private:
void set(model::GameObject* obj, int x, int y, bool throwOnOverwrite);
utils::Rect<int> m_bounds;
model::GameObject** m_grid;
};
} /* namespace basic */
} /* namespace components */
} /* namespace farmlands */
#endif /* COMPONENTS_BASIC_GRID_H_ */

View File

@ -6,6 +6,7 @@
*/
#include <GameState.h>
#include <components/basic/Transform.h>
#include <components/basic/Sprite.h>
#include <utils/Assert.h>