I am trying to implement a wrapping function named: Shape& move_up(int index), that will access and modify1 elements of vector<T*> v, in the derived class, named: class Group.
I am trying to do that by wrapping the T& operator[](int i) { return *v[i]; } of the base class:
Group.h:
// class Group is a container of Shapes
class Group: public Graph_lib::Vector_ref<Shape>{
public:
// constructors
Group::Group()
: upperLeft(0, 0), gridSideX(50), gridSideY(50), gridRowNumber(5), gridColumnNumber(5)
{
// create grid
for (size_t i = 0; i <= gridRowNumber; ++i){
for (size_t j = 0; j <= gridColumnNumber; ++j){
Graph_lib::Rectangle* rec = new Graph_lib::Rectangle(Point(upperLeft.x + gridSideX * j, upperLeft.y + gridSideY * i), gridSideX, gridSideY);
rec->set_fill_color(((i + j) % 2 == 0) ? Color::black : Color::white);
push_back(rec);
}
}
}
Shape& move_up(int i) { return operator[](i).move(0, 70); }
private:
Point upperLeft;
int gridSideX;
int gridSideY;
int gridRowNumber;
int gridColumnNumber;
};
main.cpp
#include <iostream>
#include <vector>
#include "Graph.h"
#include "Simple_window.h"
#include "Group.h"
int main(){
// define a window
Point tl(x_max()/2,0);
int width = 700;
int height = 700;
string label = "class Group";
Simple_window sw(tl, width, height, label);
// instantiate a class Group object
Group gr();
for (size_t i = 0; i < gr.size(); ++i) sw.attach(gr[i]);
sw.wait_for_button();
}
Currently the wrapping function is getting underlined in red, when hover above it displays the following message:
Error: initial value to reference to non-const must be an lvalue
The problem is that I can't find a right way of accessing and modifying the elements in the vector of the base class, thus the following question:
What am I doing wrong? How to correctly implement the Shape& move_up(int index); function?
1. Apply the function move(); that changes the coordinates of a Shape element of the vector.
2. All the additional files for compilation could be found: here and here.
Your function move() returns void:
virtual void move(int dx, int dy);
What do you expect then when you try to have your move_up() return the result of move():
return <something>.move(0, 70);
especially that you previously told the compiler that move_up() shall returns Shape&?
The function move_up() has to:
modify Shape's coordinate
return Shape& such that it could be attache()d to the window object, and its new location displayed on the screen.
To do that it just needs to be separated into two lines, where the first line modifies the Shape object and the second line returns it by reference:
Shape& move_up(int i) {
operator[](i).move(0, 70);
return operator[](i);
}
or as suggested by molbdnilo:
Shape& move_up(int i) {
auto& el = (*this)[i];
el.move(0, 70);
return el;
}
Related
I have taken sample code from ch9 Open Closed Principle in Agile Software Development, as below, which is supposed to sort shapes by precedence in the order given by the table typeOrderTable in the code below. Well, I did have to add a main and test code but pretty much copied the book code. But the output shows it is not sorting as per the table. And if I try to debug the code, the code path does not enter the Shape::Precedes function.
How can I fix this?
Code:
#include <typeinfo>
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Shape {
public:
virtual void Draw() const = 0;
bool Precedes(const Shape& s) const;
bool operator<(const Shape& s) const {
return Precedes(s);
}
private:
static const char* typeOrderTable[];
};
bool Shape::Precedes(const Shape& s) const {
const char* thisType = typeid(*this).name();
const char* argType = typeid(s).name();
bool done{ false };
int thisOrd{ -1 };
int argOrd{ -1 };
for (int i = 0; !done; ++i) {
const char* tableEntry = typeOrderTable[i];
if (tableEntry != 0) {
if (strcmp(tableEntry, thisType) == 0)
thisOrd = i;
if (strcmp(tableEntry, argType) == 0)
argOrd = i;
if (argOrd >= 0 && thisOrd >= 0)
done = true;
}
else done = true;
}
return thisOrd < argOrd;
}
class Square : public Shape {
public:
virtual void Draw() const {
cout << "square\n";
}
};
class Circle : public Shape {
public:
virtual void Draw() const {
cout << "circle\n";
}
};
class Rectangle : public Shape {
public:
virtual void Draw() const {
std::cout << "rectangle\n";
}
};
const char* Shape::typeOrderTable[] = {
typeid(Circle).name(),
typeid(Rectangle).name(),
typeid(Square).name(),
0
};
void DrawAllShapes(vector<Shape*> shapes) {
vector<Shape*> orderedList = shapes;
sort(orderedList.begin(), orderedList.end());
for (auto shape : orderedList) {
shape->Draw();
}
}
int main() {
Shape* circle = new Circle();
Shape* square = new Square();
Shape* rectangle = new Rectangle();
Shape* rectangle2 = new Rectangle();
vector<Shape*> shapes{ rectangle, square, circle, rectangle2 };
DrawAllShapes(shapes);
/* should print:
circle
rectangle
rectangle
square
but instead prints:
rectangle
square
rectangle
circle
ie unsorted - actually it is random in the output
*/
}
You need to change your call to std::sort(...) to use a comparator. The way you have it, it is pointers to shapes being sorted not shapes so the operator< defined for shapes will not be called, instead the numeric values of the pointers will be compared.
One way to fix this is to sort like this
sort(orderedList.begin(), orderedList.end(),
[](Shape* s1, Shape* s2) { return s1->Precedes(*s2); }
);
providing a lambda taking Shape*'s to do the actual comparing.
Hello I I have problem on my assignment which I need to init base constructor which is point multiple time in derived constructor which is polygon.
The polygon have at least 3 point , each point have a coordinate value. any one have ideas how to init base constructor multiple time in constructor init?
The inheritance ideas is not my ideas , is the assignment question.
this is the question
Polygon (constructor) creates a polygon with npoints vertices, the vertices take their values from those stored in the array points. Note that the array points should not be assumed to persist; it may be deleted after the constructor is invoked.
struct PointType
{
float x;
float y;
};
class Point
{
public:
Point(const PointType& center );
virtual ~Point();
private:
PointType m_center;
};
class Polygon : public Point
{
public:
Polygon(const PointType* points, int npoints);
~Polygon();
const VectorType& operator[](int index) const;
private:
int m_npoints;
Object::PointType * m_pt;
};
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include "Object.hpp"
using namespace std;
const float eps = 1e-5f;
bool Near(float x, float y)
{
return abs(x-y) < eps;
}
float frand()
{
return 10.0f*float(rand())/float(RAND_MAX);
}
int main()
{
srand(unsigned(time(0)));
int count = 0,
max_count = 0;
// Polygon tests
int n = 3 + rand()%8;
float *xs = new float[n],
*ys = new float[n];
float x = 0, y = 0;
PointType *Ps = new PointType[n];
for (int i=0; i < n; ++i) {
xs[i] = frand(), ys[i] = frand();
Ps[i] = PointType(xs[i],ys[i]);
x += xs[i], y += ys[i];
}
}
Point::Point(const PointType& center)
: m_center{center}
{
}
// this is wrong, can correct me how to construct it?
Polygon::Polygon(const PointType* points, int npoints, float depth)
:m_npoints{npoints} , m_pt{new Object::PointType[npoints]}, Point (*m_pt ,depth)
{
for(int i=0; i < m_npoints ; ++i)
{
m_pt[i] = points[i];
}
}
enter code here
this the assignment structure like
enter image description here
I took away other object class implementation
Your assignment text doesn't say anything about inheritance. It essentially describes composition. Go from here:
class Polygon
{
public:
// constructor should allocate the array
Polygon(const PointType* points, int npoints);
~Polygon();
private:
Point *m_npoints; // or use smart pointer if you're allowed to.
};
It is a trick question, is actually want me to find centroid point of polygon.
So I need a private compute center point of polygon function and return the result of center point of polygon, and then call the function in point constructor when init.
i am having problem getting the correct object out from the lines
Cell cF = fList[rand() % fList.size()];//choose random frontier cell
Cell cl = inList[rand() % inList.size()];//choose random in cell
whenever i debug using visual studio, i can see a Cell will have it's members added due to the method pushToPrimsFrontierList(Cell& c), however when i try to get the object from the inList or fList, it seems like im not getting that same object reference, because its neighbour list is 0 again.what is happening here?
You can see from the image that during the first iteration a startCell is added to the inList, so when im accessing it it will return me only that one object, however that is not the case, it seems like my object is not even push_backed to the inList vector.
#ifndef __CELL_H_
#define __CELL_H_
#include <vector>
using namespace std;
class Cell{
private:
int x, y, val; // cell co-ordinate
bool visited;
void setX(int);
void setY(int);
vector<Cell> neighbourList;
public:
Cell();
Cell(int,int);
int getX();
int getY();
int getVal();
vector<Cell>& getNeighbourList();
void pushToNeighbourList(Cell&);
void setVal(int);
void setVisited(bool);
bool IsVisited();
bool equals(Cell&);
};
#endif
#ifndef GENMAZE_H
#define GENMAZE_H
#include <vector>
#include <iostream>
#include "cell.h"
using namespace std;
class GenMaze{
private:
int rows;
int cols;
int gridSize;
vector<vector<Cell>> mazeGrid;
vector<Cell> inList;
vector<Cell> fList;
public:
GenMaze(int,int);
void setRows(int);
void setCols(int);
void setGridSize(int);
int getGridSize();
int getRows();
int getCols();
vector<vector<Cell>>& getMazeGrid();
void setMazeGrid(vector<vector<Cell>>);
void setValAt(int,int, Cell);
void printMazeCoords();
void printMazeValue();
bool isOddBlock(int,int);
void Prims();
void pushToPrimsFrontierList(Cell&);
void printCell(Cell&);
void makePath(Cell&, Cell&);
void removeFromfList(Cell&);
};
#endif
void GenMaze::Prims(){
Cell startCell = mazeGrid[1][1];//startCell
inList.push_back(startCell);
pushToPrimsFrontierList(startCell);
int randomFrontier= 0;
int randomIn = 0;
while (!fList.empty()){
cout<< "e";
Cell cF = fList[rand() % fList.size()];//choose random frontier cell
Cell cl = inList[rand() % inList.size()];//choose random in cell
for (vector<Cell>::size_type i = 0; i != cl.getNeighbourList().size(); i++) {
if (cl.getNeighbourList()[i].equals(cF)){
inList.push_back(cF);
pushToPrimsFrontierList(cF);
makePath(cl, cF);
removeFromfList(cF);
}
}
}
}
void GenMaze::removeFromfList(Cell& c){
for (vector<Cell>::size_type i = 0; i != fList.size(); i++) {
if (fList[i].equals(c)){
fList.erase(fList.begin() + i);
}
}
}
void GenMaze::makePath(Cell& from, Cell& to){
cout << "making path";
//on top
if ((from.getX() - 2 == to.getX()) & (from.getY() == to.getY())){
mazeGrid[from.getX() - 1][from.getY()].setVal(0);
}
//on right
if ((from.getX() == to.getX()) & (from.getY() + 2 == to.getY())){
mazeGrid[to.getX()][from.getY() - 1].setVal(0);
}
//on bottom
if ((from.getX() + 2 == to.getX()) & (from.getY() == to.getY())){
mazeGrid[from.getX() + 1][from.getY()].setVal(0);
}
//on left
if ((from.getX() == to.getX()) & (from.getY() - 2 == to.getY())){
mazeGrid[from.getX()][from.getY() - 1].setVal(0);
}
}
void GenMaze::printCell(Cell& c){
cout << "(" << c.getX() << "," << c.getY() << ")";
}
void GenMaze::pushToPrimsFrontierList(Cell& c){
//push all Cells around the given Cell c, into the frontier list.
if (!(c.getX() - 2 < 0)){
Cell topCell = mazeGrid[c.getX() - 2][c.getY()];
fList.push_back(topCell);
c.pushToNeighbourList(topCell);
}
if (!(c.getY() - 2 < 0)){
Cell leftCell = mazeGrid[c.getX()][c.getY() - 2];
fList.push_back(leftCell);
c.pushToNeighbourList(leftCell);
}
if (!(c.getY() + 2 > getCols() - 1)){
Cell rightCell = mazeGrid[c.getX()][c.getY() + 2];
fList.push_back(rightCell);
c.pushToNeighbourList(rightCell);
}
if (!(c.getX() + 2 > getRows() - 1)){
Cell bottomCell = mazeGrid[c.getX() + 2][c.getY()];
fList.push_back(bottomCell);
c.pushToNeighbourList(bottomCell);
}
}
To the std::vector as pretty much to every STL collection you cannot put the reference to the object. If you do:
Cell c;
std::vector<Cell> myvector1;
std::vector<Cell> myvector2;
myvector1.push_back(c);
myvector2.push_back(c);
When you try to modify c in myvector1 the value won't be propagated to myvector2. This is because push_back adds the element by value not by reference. If you need the real reference to some object you should create collection of pointers to elements and the code should rather look like this:
Cell *c = new Cell;
std::vector<Cell*> myvector1;
std::vector<Cell*> myvector2;
myvector1.push_back(c);
myvector2.push_back(c);
Now when you want to modify element beneith c you just do:
myvector1[indexofc]->somecellfield = othervalue
When I declare the "Level" object in the "LevelEditor" class definition like so, everything works fine:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
}
//...
private:
//...
Level level = Level(50, 50);
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
But when I declare the "Level" object in the "LevelEditor" constructor like so, I get a stack overflow:
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader)
{
width = w;
height = h;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y, tileWidth, tileHeight, shader);
}
}
//NOTE: width and height both equal 50
level = Level(width, height);
}
//...
private:
//...
Level level;
WorldSprite* tile[300][300];
//tile characteristics
int tileWidth = 50;
int tileHeight = 50;
//flags
bool editing = true;
};
This makes me wonder what the difference is between declaring a variable in the class definition and in the constructor is besides the fact of the time of defining the variable. Any idea of what the cause could be? and how I could declare the "Level" object in the constructor without having to put anything on the heap?
EDIT:
"Level" class definition in case it is helpful:
class Level
{
public:
Level(int w, int h)
{
Worldwidth = w;
Worldheight = h;
for (unsigned int y = 0; y < Worldheight; y++)
{
for (unsigned int x = 0; x < Worldwidth; x++)
{
grid[x][y] = -1;
}
}
}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
int grid[300][300];
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
There are several issues with your code. I will try to address the stack overflow error. The other issue is that your Level class is not safely copyable -- that can be taken care of by utilizing smart pointers such as std::unique_ptr and std::shared_ptr.
First, your classes use 300 x 300 arrays of T, in one case, T is a WorldSprite* the other is int. Arrays this size declared as members will balloon the size of each of your objects that contain them to hundreds of kilobytes in size. This will at some point take a toll on the stack.
So you should remove these definitions, and instead use std::vector.
#include <vector>
class LevelEditor
{
public:
LevelEditor(int w, int h, Shader* shader) :
tile(w,std::vector<WorldSprite*>(h))
editing(true), width(w), height(h)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
tile[x][y] = new WorldSprite(tileWidth * x, tileHeight * y,
tileWidth, tileHeight, shader);
}
level = Level(width, height);
}
private:
Level level;
int width, height;
std::vector<std::vector<WorldSprite*>> tile;
bool editing;
};
Here is the Level class with the same type of changes:
#include <vector>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
~Level()
{
for (auto it = tiles.begin(); it != tiles.end(); ++it)
{
delete *it;
}
tiles.clear();
for (auto it = entities.begin(); it != entities.end(); ++it)
{
delete *it;
}
entities.clear();
}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int> >grid;
std::vector<Tile*> tiles;
std::vector<Entity*> entities;
};
Note that the vector replaces the array, and it will use heap memory to initialize. In the Level class, we initialize the vector and set all the entries to -1 in one single call of the vector's constructor.
The reason why this will not hike the size of your objects to very high amounts is that vector will create its data on the heap (unless you have some sort of custom allocator that gets the memory from another source). Thus the size of your classes will be reasonable (probably less than 100 bytes).
The other issue is that your Level class is not safely copyable (neither is the LevelEditor, but I will leave it alone, as the same set of changes can be done).
The problem will be this line:
level = Level(width, height);
The problem with this line is that the assignment operator will be called and the copy constructor may be called. If you look at your Level class, it has a destructor that removes all the pointers from the vectors that contain pointers. This will be disastrous if you copy Level objects, since you will be destroying all of your data due to temporaries being destroyed.
If there is no sense of which Level actually owns the pointers, and it comes down to "whoever is the last man standing is the owner", and you will actually be sharing pointers between Level instances (that's why it's called shared_ptr) then you can use this solution:
#include <vector>
#include <memory>
//...
class Level
{
public:
Level(int w, int h) : Worldwidth(w), Worldheight(h),
grid(300, std::vector<int>(300, -1))
{}
Level(){}
void draw()
{
}
private:
int Worldwidth;
int Worldheight;
std::vector<std::vector<int>> grid;
std::vector<std::shared_ptr<Tile>> tiles;
std::vector<std::shared_ptr<Entity>> entities;
};
Note how there is no destructor code -- there need not be any. The deletion is all done by the shared_ptr, so there is no work for you to do -- everything is managed. What will happen is that the last Level that gets destroyed that you shared the pointers with will do the actual deletion. So when this line is done
level = Level(width, height);
the copying of the Level objects bumps up and down the internal shared_ptr's reference count, leaving you with a reference count of 1 (that is the final level on the left-hand side of the = sign).
See here for usage of std::shared_ptr: http://en.cppreference.com/w/cpp/memory/shared_ptr
Please note that you may want to use std::unique_ptr if ownership is an issue. I suggest you search SO for usages of std::unique_ptr. I showed you std::shared_ptr since it is the most straightforward at this point (but again, may not suit all your needs - YMMV).
I have a TileMap class that has a std::vector<Tile>. While just generating the vector, i notice that the Tiles are getting deleted shortly after creation, thus not letting the TileMap class do anything with them.
TileMap is a kind of information class that will be used by a Stage class for various things, so it will need to access TileMap.tiles() (which returns the mTiles_ TileMap.
TileMap constructor:
TileMap::TileMap(std::vector<int> pTiles, int pWidth):mWidth_(pWidth)
{
for(int i = 0; i < pTiles.size(); i++)
{
int x = (i % mWidth_);
int y = floorf(i / mWidth_);
Tile tile((Tile::TileType)pTiles[i]);
tile.x = x;
tile.y = y;
tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
mTiles_.push_back(tile);
}
}
Previously it was a std::vector<std::shared_ptr<Tile>> but i was seeing if i could get around using pointers. Is there a way to do this?
EDIT: Tile definition added -
class Tile : public SquareCollidableObject
{
public:
enum TileType {
TILE_GRASS,
TILE_OUTSIDE_WALL_TOP_LEFT_OUTER,
TILE_OUTSIDE_WALL_TOP,
TILE_OUTSIDE_WALL_TOP_RIGHT_OUTER,
TILE_OUTSIDE_WALL_LEFT,
TILE_OUTSIDE_WALL_RIGHT,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_OUTSIDE_WALL_BOTTOM,
TILE_OUTSIDE_WALL_TOP_RIGHT_INNER,
TILE_OUTSIDE_WALL_TOP_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_WALL,
TILE_INSIDE_WALL_TOP_LEFT_INNER,
TILE_INSIDE_WALL_TOP,
TILE_INSIDE_WALL_TOP_RIGHT_INNER,
TILE_INSIDE_WALL_LEFT,
TILE_INSIDE_WALL_RIGHT,
TILE_INSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_INSIDE_WALL_BOTTOM,
TILE_INSIDE_WALL_TOP_RIGHT_OUTER,
TILE_INSIDE_WALL_TOP_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_FLOOR
};
Tile(TileType);
virtual ~Tile();
virtual void update(float);
virtual void draw(sf::RenderWindow&, sf::Vector2f);
TileType tileType;
static int TILE_WIDTH;
static int TILE_HEIGHT;
int x;
int y;
// pathfinding
std::shared_ptr<Tile> previousTile;
float g; // cost to tile (total cost from previous tiles + cost to this tile)
float h; // cost to next tile
float f; // g + h
bool walkable;
};
Tile needs to have a copy (or move) constructor and assignment operator for use with std::vector.
nTiles_.push_back(tile) copy-constructs a new Tile object from the local tile.
In that for loop, at each iteration, the local object tile gets constructed, then a copy gets pushed into the vector, and then the local tile gets destructed. This is why destructors get called during the for loop.
One way to avoid this and instead only construct the Tile object that will be in the vector, you could write
TileMap::TileMap(std::vector<int> pTiles, int pWidth):mWidth_(pWidth)
{
for(int i = 0; i < pTiles.size(); i++)
{
int x = (i % mWidth_);
int y = floorf(i / mWidth_);
mTiles_.emplace_back( (Tile::TileType)pTiles[i] );
Tile& tile = mTiles_.back();
tile.x = x;
tile.y = y;
tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
}
}
emplace_back takes the arguments of the Tile constructor, and constructs an object in-place at the end of the vector. back returns a reference to the last item.
If Tile objects are heavy-weight (i.e. copying them is expensive), it may be better to use pointers instead as before, or implement move-constructor and move-assignment operator. std::vector will copy (or move) its items if new items get inserted/erased, or when the vector gets resized.
Also the tiles() function needs to return the vector by reference.
There is 2 reasons of Tile destruction in your code:
The local variable that you copy inside vector, and the internal copy when vector resizes internal memory.
To avoid the former, you have to emplace back the new element; for the later, you have to reserve place in vector. It results in something like:
TileMap::TileMap(const std::vector<int>& pTiles, int pWidth) : mWidth_(pWidth)
{
mTiles_.reserve(pTiles.size());
for(int i = 0; i != pTiles.size(); ++i)
{
const int x = i % mWidth_;
const int y = i / mWidth_;
mTiles_.emplace_back(static_cast<Tile::TileType>(pTiles[i]));
Tile& tile = mTiles_.back();
tile.x = x;
tile.y = y;
tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
}
}
First of all, your TileMap constructor calls .position which isn't a member of the Tile class.
Secondly, #tmlen's answer looks like it works as expected to me. If I run this code:
#include <stdlib.h>
#include <memory>
#include <vector>
#include <iostream>
using namespace std;
class Tile
{
public:
enum TileType {
TILE_GRASS,
TILE_OUTSIDE_WALL_TOP_LEFT_OUTER,
TILE_OUTSIDE_WALL_TOP,
TILE_OUTSIDE_WALL_TOP_RIGHT_OUTER,
TILE_OUTSIDE_WALL_LEFT,
TILE_OUTSIDE_WALL_RIGHT,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_OUTSIDE_WALL_BOTTOM,
TILE_OUTSIDE_WALL_TOP_RIGHT_INNER,
TILE_OUTSIDE_WALL_TOP_LEFT_INNER,
TILE_OUTSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_WALL,
TILE_INSIDE_WALL_TOP_LEFT_INNER,
TILE_INSIDE_WALL_TOP,
TILE_INSIDE_WALL_TOP_RIGHT_INNER,
TILE_INSIDE_WALL_LEFT,
TILE_INSIDE_WALL_RIGHT,
TILE_INSIDE_WALL_BOTTOM_RIGHT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_LEFT_INNER,
TILE_INSIDE_WALL_BOTTOM,
TILE_INSIDE_WALL_TOP_RIGHT_OUTER,
TILE_INSIDE_WALL_TOP_LEFT_OUTER,
TILE_INSIDE_WALL_BOTTOM_RIGHT_INNER,
TILE_FLOOR
};
Tile(TileType t):
tileType(t)
{
cout << "Constructing tile\n";
}
virtual ~Tile()
{
cout << "Destructing tile\n";
}
TileType tileType;
static int TILE_WIDTH;
static int TILE_HEIGHT;
int x;
int y;
// pathfinding
std::shared_ptr<Tile> previousTile;
float g; // cost to tile (total cost from previous tiles + cost to this tile)
float h; // cost to next tile
float f; // g + h
bool walkable;
};
class TileMap
{
int mWidth_;
std::vector<Tile> mTiles_;
public:
TileMap(const std::vector<int>& pTiles, int pWidth) : mWidth_(pWidth)
{
mTiles_.reserve(pTiles.size());
for (int i = 0; i != pTiles.size(); ++i)
{
const int x = i % mWidth_;
const int y = i / mWidth_;
mTiles_.emplace_back(static_cast<Tile::TileType>(pTiles[i]));
Tile& tile = mTiles_.back();
tile.x = x;
tile.y = y;
//tile.position(sf::Vector2f(x * Tile::TILE_WIDTH, y * Tile::TILE_HEIGHT));
}
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> tiles;
tiles.push_back(Tile::TileType::TILE_GRASS);
cout << "Creating tilemap\n";
TileMap t(tiles, tiles.size());
cout << "Tilemap created\n";
cout << "Exiting\n";
return 0;
}
I get the following result:
Creating tilemap
Constructing tile
Tilemap created
Exiting
Destructing tile