Thanks for the helpfull replies
As I'm not so sure with Vertexarrays I went following way:
For the hexagonal grid I made a hexagon class(drawable) which holds the vertexarray to be more precise std::vector<vertex>. A templated GameGrid class holds a std::vector of Hexagons for example and generates the field.
I did some refractoring on it and except a pointer to a maploader - that holds the map information in an array - and three member function pointers on this class for the getters in this way I could remove the maploader header from the GameGrid header.
I was wondering if that is still good c++ or overengineering things?
Well before describing it lengthily I post the source code for GameGrid and the hexagon class
The code for GameGrid template is all in a header now, moving things to an .inl when I played around with this format.
In so far the code for GameGrid is lengthy:
#pragma once
#ifndef GAMEGRID_H_INCLUDED
#define GAMEGRID_H_INCLUDED
#include <SFML/Graphics.hpp>
#include <functional>
#include <vector>
#include <cassert>
#include "Hexagon.h"
template <typename Identifier, typename Fieldtype, typename Mapstorage>
class GameGrid :public sf::Drawable
{
private:
//GameGrid Object is drawable, calls draw function of each field instance
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
for (Fieldtype a : mGrid)
{
target.draw(a);
}
}
protected:
//Storage of fieldobjects, field objects have to be drawable
std::vector<Fieldtype> mGrid;
//Texturehandler with textures
//Wrapper class for a std::map<Keyvalue, sf::Texture>
ResourceHolder<Identifier, sf::Texture>* pmResources;
//MapHolder
//pointer to Wrapper class for two dimensional array of ints that provides three functions
//one that returns number of lines of array
//one that returns number of rows of array
//one that returns value of specific array member
Mapstorage* mMap;
//wrapper class function that provides row ammount
int (Mapstorage::*Rower)();
//wrapper class function that provides line ammount
int (Mapstorage::*Liner)();
//wrapper class function that provides int value of specific cell
int (Mapstorage::*Celling)(int, int);
//function that cuts down value from wrapper class to value for texture
std::function<int(int)> mCutter;
//function that calculates X coordinate of center of field
std::function<float(float, float, float,int, int)> mCoordinateX;
//function that calculates Y coordinate of center of field
std::function<float(float, float, float,int, int)> mCoordinateY;
//top-left position of the grid
sf::Vector2f mPosition;
//size of field
float mFieldsize;
//factor by which fieldsize is streched in x
float mFactorX;
//factor by which fieldsize is streched in y
float mFactorY;
//factor by which the spacing in x direction between fields is calculated
float mSpacingX;
//factor by which the spacing in y direction between fields is calculated
float mSpacingY;
//are the field textured
bool mTextured;
//are all fields added to the field container or are some sorted out
bool mOnlyUnMarked;
//Markervalue is compared with value from mapholder, in case of equal no field instance is created
int mMarker;
//exact Key value for the texture holder
Identifier mIdentity;
public:
//Constructor, only requires values for the TextureHandler, and exact Key rest of variables has an intial value
GameGrid(ResourceHolder<Identifier, sf::Texture>* aResource, Identifier anIdentity, Mapstorage* aMap = nullptr, int (Mapstorage::*Rowing)() = nullptr, int (Mapstorage::*getCells)(int, int) = nullptr, int (Mapstorage::*Lining)() = nullptr, std::function<int(int)> aCut = [](int a) {return 0; }, std::function<float(float, float, float, int, int)> aXCalc = [](float a, float b, float c, int d, int e)->float {return 0.f; }, std::function<float(float, float, float, int, int)>aYCalc = [](float a, float b, float c, int d, int e)->float {return 0.f; }, sf::Vector2f aPosition = sf::Vector2f(0.f, 0.f), float aSize = 0.f, float aFactorX = 0.f, float aFactorY = 0.f, float aspaceX = 0.f, float aspaceY = 0.f, bool isTextured = false, bool onlyunmarked = false, int amarker = 0) :
pmResources(aResource),mIdentity(anIdentity),mMap(aMap),Rower(Rowing), Liner(Lining),Celling(getCells),mCutter(aCut), mCoordinateX(aXCalc), mCoordinateY(aYCalc), mPosition(aPosition), mFactorX(aFactorX),mFactorY(aFactorY),mSpacingX(aspaceX), mSpacingY(aspaceY), mTextured(isTextured), mOnlyUnMarked(onlyunmarked),mMarker(amarker)
{}
//MapHolder and getter functions for MapHolder
void setUpMap(Mapstorage* aMap, int (Mapstorage::*Rows)(), int (Mapstorage::*Lines)(), int (Mapstorage::*Cells)(int, int))
{
mMap = aMap;
Rower = Rows;
Liner = Lines;
Celling = Cells;
}
//exact Identifier can be changed
void setIdentifier(Identifier identity)
{
mIdentity = identity;
}
//setter for Calculations of center coordinates for each field object
void setCoordinateCalcs(std::function<float(float, float, float, int, int)> CalcX, std::function<float(float, float, float, int, int)>CalcY)
{
mCoordinateX = CalcX;
mCoordinateY = CalcY;
}
//setter for function that cuts down
void setCutter(std::function<int(int)> Cutfunction)
{
mCutter = Cutfunction;
}
//setter for upper-left position of grid
void setPosition(sf::Vector2f Position)
{
mPosition = Position;
}
//setter for the fieldsize
void setFieldsize(float Size)
{
mFieldsize = Size;
}
//setter for Factors for streching and spacing of field instances
void setFactors(float stretchX, float stretchY, float spaceX, float spaceY)
{
mFactorX = stretchX;
mFactorY = stretchY;
mSpacingX = spaceX;
mSpacingY = spaceY;
}
//setter if fieldinstances are texturized
void setTextured(bool texturized)
{
mTextured = texturized;
}
//setter if Only fields whos value from map is unequal Marker get added to container
void setOnlyUnMarked(bool OnlyUnMarked)
{
mOnlyUnMarked = OnlyUnMarked;
}
void createGrid()
{
float FieldWidth = mFieldsize * mFactorX;
float FieldHeight = mFieldsize * mFactorY;
float InitialWidth = FieldWidth / 2;
float InitialHeight = FieldHeight / 2;
float SpacingWidth = mSpacingX * FieldWidth;
float SpacingHeight = mSpacingY * FieldHeight;
assert(mMap != nullptr);
int ammountX = (mMap->*Rower)();
int ammountY = (mMap->*Liner)();
int value;
for (int i =0; i < ammountX; ++i)
{
for (int j = 0; j < ammountY; ++j)
{
if (j % 2 == 0)
{
value = mCutter((mMap->*Celling)(i, j));
if (!mOnlyUnMarked || (mOnlyUnMarked && mMarker != value))
{
sf::Vector2f currpos = sf::Vector2f(mCoordinateX(mPosition.x, InitialWidth, SpacingWidth, i, 1), mCoordinateY(mPosition.y, InitialHeight, SpacingHeight, j, 1));
Fieldtype h(currpos, mFieldsize, value, &pmResources->get(mIdentity), sf::Vector2i(i, j), mTextured);
mGrid.push_back(h);
}
}
if (j % 2 == 1)
{
value = mCutter((mMap->*Celling)(i, j));
if (!mOnlyUnMarked || (mOnlyUnMarked && mMarker != value))
{
sf::Vector2f currpos = sf::Vector2f(mCoordinateX(mPosition.x, InitialWidth, SpacingWidth, i, 2), mCoordinateY(mPosition.y, InitialHeight, SpacingHeight, j, 1));
Fieldtype h(currpos, mFieldsize, value, &pmResources->get(mIdentity), sf::Vector2i(i, j), mTextured);
mGrid.push_back(h);
}
}
}
}
}
//aquiering the field position for a coordinate
void GridPosition(sf::Vector2f avec, sf::Vector2i& destvec, int& gridValue, bool& delivered)
{
for (Fieldtype a : mGrid)
{
if (a.isinRange(avec))
{
delivered = true;
destvec = a.getGridPos();
gridValue = mCutter((mMap->*Celling)(destvec.x, destvec.y)) / 10;
}
delivered = false;
}
}
};
#endif
Here the code for the Hexagon class:
the header
#ifndef HEXAGON_H_INCLUDED
#define HEXAGON_H_INCLUDED
#include<vector>
#include <SFML/Graphics.hpp>
#include<SFML/System.hpp>
#include <math.h>
class Hexagon :public sf::Drawable//, public sf::NonCopyable
{
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
protected:
int mTilenumber;
int mTileline;
sf::Texture* m_TileSet;
//Vertices that are textured
std::vector<sf::Vertex> oneHex;
//Vertices that are displayed as a line surrounding the field
std::vector<sf::Vertex> twoHex;
float mSize;
sf::Vector2f mPosition;
void claculatePoints();
sf::Vector2i mGridPos;
bool showField;
public:
Hexagon(sf::Vector2f pos, float size, int tilenumber, sf::Texture* tileset, sf::Vector2i aGridPos, bool aShow);
bool isinRange(sf::Vector2f avec);
sf::Vector2f getLocation();
sf::Vector2i getGridPos();
};
#endif
and here the .cpp with the bodies of the memberfunction for Hexagon:
I left out the dependecy for VisualStudio
#include "Hexagon.h"
#include <math.h>
Hexagon::Hexagon(sf::Vector2f pos, float size, int tilenumber, sf::Texture* tileset, sf::Vector2i aGridPos, bool aShow) : mPosition(pos), mSize(size), m_TileSet(tileset), mGridPos(aGridPos), showField(aShow)
{
mTilenumber = tilenumber % 10;
mTileline = tilenumber / 10;
claculatePoints();
}
void Hexagon::claculatePoints()
{
float width = mSize * (float)sqrt(3);
float height = mSize * 2;
if (showField)
{
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y - height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f(mPosition.x, (mPosition.y - height / 2))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y - height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y + height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f(mPosition.x, (mPosition.y + height / 2))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y + height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y + height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y - height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y - height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y - height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y + height / 4))));
oneHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y + height / 4))));
oneHex[0].texCoords = sf::Vector2f((float)mTilenumber*height + width * 0.25f, (float)mTileline*height + mSize - height / 4);
oneHex[1].texCoords = sf::Vector2f((float)mTilenumber*height + mSize, (float)mTileline*height + mSize - height / 2);
oneHex[2].texCoords = sf::Vector2f((float)mTilenumber*height + width, (float)mTileline*height + mSize - height / 4);
oneHex[3].texCoords = sf::Vector2f((float)mTilenumber*height + width, (float)mTileline*height + mSize + height / 4);
oneHex[4].texCoords = sf::Vector2f((float)mTilenumber*height + mSize, (float)mTileline*height + mSize + height / 2 - 1);
oneHex[5].texCoords = sf::Vector2f((float)mTilenumber*height + width * 0.25f, (float)mTileline*height + mSize + height / 4);
oneHex[6].texCoords = sf::Vector2f((float)mTilenumber*height + width * 0.25f, (float)mTileline*height + mSize + height / 4);
oneHex[7].texCoords = sf::Vector2f((float)mTilenumber*height + width * 0.25f, (float)mTileline*height + mSize - height / 4);
oneHex[8].texCoords = sf::Vector2f((float)mTilenumber*height + width, (float)mTileline*height + mSize - height / 4);
oneHex[9].texCoords = sf::Vector2f((float)mTilenumber*height + width, (float)mTileline*height + mSize - height / 4);
oneHex[10].texCoords = sf::Vector2f((float)mTilenumber*height + width, (float)mTileline*height + mSize + height / 4);
oneHex[11].texCoords = sf::Vector2f((float)mTilenumber*height + width * 0.25f, (float)mTileline*height + mSize + height / 4);
}
else
{
twoHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y - height / 4))));
twoHex.push_back(sf::Vertex(sf::Vector2f(mPosition.x, (mPosition.y - height / 2))));
twoHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y - height / 4))));
twoHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x + width / 2), (mPosition.y + height / 4))));
twoHex.push_back(sf::Vertex(sf::Vector2f(mPosition.x, (mPosition.y + height / 2))));
twoHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y + height / 4))));
twoHex.push_back(sf::Vertex(sf::Vector2f((mPosition.x - width / 2), (mPosition.y - height / 4))));
}
}
void Hexagon::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.texture = &(*m_TileSet);
if(showField)
target.draw(&oneHex[0], oneHex.size(), sf::Triangles,states);
else
target.draw(&twoHex[0], twoHex.size(), sf::LineStrip);
}
sf::Vector2f Hexagon::getLocation() {
return mPosition;
}
sf::Vector2i Hexagon::getGridPos() {
return mGridPos;
}
bool Hexagon::isinRange(sf::Vector2f avec)
{
return (((avec.x) <= (mPosition.x + mSize * (float)(sqrt(3)/2.0f)) && (avec.x) >= (mPosition.x - mSize * ((float)sqrt(3)/2.0f))) && ((avec.y) <= (mPosition.y + mSize) && (avec.y) >= (mPosition.y - mSize)));
}