Переписал тут на днях код,завернув в классы и для удобства,набросав базовую архитектуру и добавив некоторый функционал
В архиве также приложен исходный код,если кто захочет поиграться или добавить чего своего или просто любопытно посмотреть
Для совсем ленивых исходный код под катами
Game.cpp
#include "ResManager.h"
#include "UnitManager.h"
#include "CellManager.h"
class Game
{
public:
int State;
ResManager resManager;
UnitManager unitManager;
CellManager cellManager;
Clock clock;
int elapsed;
VideoMode videomode;
RenderWindow window;
View defaultView;
View currView;
Input input;
Sprite cursor;
Vector2f cursorPos;
void Init()
{
State=1;
srand(time(0));
videomode=videomode.getDesktopMode();
defaultView.reset(FloatRect(0, 0, videomode.width, videomode.height));
currView.reset(FloatRect(0, 0, videomode.width, videomode.height));
window.create(videomode, "Neverland",Style::Default);
window.setView(currView);
window.setMouseCursorVisible(false);
resManager.LoadFont("arial.ttf");
resManager.Load(Textures::Skeleton,"skeleton5.png");
resManager.Load(Textures::Cursor,"cursor.png");
resManager.Load(Textures::Tileset,"tileset.png");
resManager.Load(Textures::Hero,"hero.png");
cursor.setTexture(resManager.Get(Textures::Cursor));
}
void Update()
{
Event event;
if (Keyboard::isKeyPressed(Keyboard::Escape))
{
window.setMouseCursorVisible(true);
window.close();
}
while (window.pollEvent(event))
{
switch(event.type)
{
// отлавливаем,нажато ли что-нибудь
case Event::KeyPressed:
case Event::KeyReleased:
case Event::MouseButtonPressed:
case Event::MouseButtonReleased:
case Event::MouseMoved:
input.CheckInput();
break;
//отлавливаем,произошло ли события закрытия
case Event::Closed:
window.setMouseCursorVisible(true);
window.close();
}
}
cursorPos=window.mapPixelToCoords(Vector2i(input.MouseX,input.MouseY));
cursor.setPosition(Vector2f(int(cursorPos.x/64)*64,int(cursorPos.y/64)*64));
elapsed = elapsed+clock.restart().asMilliseconds();
currView.setCenter(currView.getCenter()+input.UpdateView());
window.setView(currView);
input.ClearInput();
}
void Draw()
{
window.clear();
window.draw(cellManager.tileMap);
unitManager.Draw(window);
unitManager.DrawUnitText(window);
window.draw(cursor);
window.display();
}
};
main.cpp
#include "main.h"
#include "Game.cpp"
int main()
{
Game game;
game.Init();
game.cellManager.GenCells();
game.cellManager.tileMap.LoadTileMap(game.resManager,Textures::Tileset,Vector2u(64,64),100,100);
game.unitManager.LoadUnit(game.resManager,Textures::Hero,"Nerevar",64,64,100,game.resManager.MainFont);
game.unitManager.LoadUnit(game.resManager,Textures::Skeleton,"Skeleton",128,128,100,game.resManager.MainFont);
for (unsigned int i=0;i<game.unitManager.count;i++)
{
if (game.cellManager.tileMap.IsPathableCell(game.unitManager.units[i].sprite.getPosition().x/64,game.unitManager.units[i].sprite.getPosition().y/64)==0)
{
Vector2f v=game.cellManager.tileMap.FindPathableCell(game.unitManager.units[i].sprite.getPosition().x/64,game.unitManager.units[i].sprite.getPosition().y/64);
game.unitManager.units[i].sprite.setPosition(v.x*64,v.y*64);
}
}
while (game.window.isOpen())
{
game.Update();
game.Draw();
}
return 0;
}
main.h
#ifndef MAIN_H
#define MAIN_H
#include <SFML/Graphics.hpp>
#include <iostream>
#include <ctime>
#include <vector>
#include <map>
#include <memory>
using namespace std;
using namespace sf;
#define GetRandomInt(min,max) rand() % ((max + 1) - min) + min;
namespace Textures
{
enum ID { Hero , Skeleton , Cursor ,Tileset };
}
class Input
{
public:
unsigned int Up,Down,Left,Right;
unsigned int MouseLeft,MouseRight;
unsigned int MouseX,MouseY;
unsigned int Esc,Enter;
Input()
{
Up,Down,Left,Right=0;
MouseLeft,MouseRight=0;
Esc,Enter=0;
MouseX=Mouse::getPosition().x;
MouseY=Mouse::getPosition().y;
}
Vector2f UpdateView()
{
Vector2f update=Vector2f(0,0);
if (Up!=0)
{
update=Vector2f(0,-64);
}
if (Down==1)
{
update=Vector2f(0,64);
}
if (Left==1)
{
update=Vector2f(-64,0);
}
if (Right==1)
{
update=Vector2f(64,0);
}
return update;
}
void CheckInput()
{
Up=Keyboard::isKeyPressed(Keyboard::W);
Down=Keyboard::isKeyPressed(Keyboard::S);
Left=Keyboard::isKeyPressed(Keyboard::A);
Right=Keyboard::isKeyPressed(Keyboard::D);
Esc=Keyboard::isKeyPressed(Keyboard::Escape);
Enter=Keyboard::isKeyPressed(Keyboard::Comma);
MouseX=Mouse::getPosition().x;
MouseY=Mouse::getPosition().y;
}
void ClearInput()
{
Up=0;
Down=0;
Left=0;
Right=0;
Esc=0;
Enter=0;
}
};
#endif
Unit.h
#include "main.h"
class Unit: public Drawable, public Transformable
{
public:
Sprite sprite;
Texture texture;
Text text;
string name;
Uint32 x;
Uint32 y;
Uint32 hp;
Unit(){}
void SetPosition(Uint32 newX,Uint32 newY)
{
x=newX;
y=newY;
}
Vector2i GetPosition()
{
return Vector2i(x,y);
}
void DamageTarget(Unit &caster,Unit &target,float damage)
{
target.hp=target.hp-damage;
}
virtual void draw(RenderTarget& target) const
{
target.draw(sprite);
}
virtual void draw(RenderTarget& target, RenderStates states) const
{
// apply the transform
states.transform *= getTransform();
// apply the tileset texture
states.texture = &texture;
// draw the vertex array
target.draw(sprite, states);
}
};
Cell.h
#include "main.h"
#include "ResManager.h"
class Cell
{
public:
unsigned int pathable;
unsigned int x,y;
unsigned int textureId;
Cell(){}
Cell(unsigned int _pathable,unsigned int _x,unsigned int _y,unsigned int _textureId)
{
pathable=_pathable;
x=_x;
y=_y;
textureId=_textureId;
}
};
class TileMap : public Drawable, public Transformable
{
public:
VertexArray vertices;
Texture texture;
Vector2u tileSize;
unsigned int width;
unsigned int height;
vector<Cell> cells;
unsigned int IsPathableCell(int x,int y)
{
return cells[y*width+x].pathable;
}
Vector2f FindPathableCell(int x,int y)
{
int tx=x;
int ty=y;
while(IsPathableCell(tx,ty)==0)
{
int random=GetRandomInt(0,4);
if (random==0&&tx+1<100&&ty+1<100)
{
tx=tx+1;
ty=ty+1;
}
else if (random==1&&tx-1>=0&&ty-1>=0)
{
tx=tx-1;
ty=ty-1;
}
else if (random==2&&tx+1<100&&ty-1>=0)
{
tx=tx+1;
ty=ty-1;
}
else if (random==3&&tx-1>=0&&ty+1<100)
{
tx=tx-1;
ty=ty+1;
}
else if (random==4&&tx-1>=0&&ty-1>=0)
{
tx=tx-1;
ty=ty-1;
}
}
return Vector2f(tx,ty);
}
bool UpdateCell(int x,int y,unsigned int newPathable,unsigned int newTextureId)
{
cells[y*width+x].pathable=newPathable;
cells[y*width+x].textureId=newTextureId;
int tu = cells[y*width+x].textureId % (texture.getSize().x / tileSize.x);
int tv = cells[y*width+x].textureId / (texture.getSize().x / tileSize.x);
Vertex* quad = &vertices[(x + y * width) * 4];
// define its 4 texture coordinates
quad[0].texCoords = Vector2f(tu * tileSize.x, tv * tileSize.y);
quad[1].texCoords = Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
quad[2].texCoords = Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
quad[3].texCoords = Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
return true;
}
bool LoadTileMap(ResManager &resManager,Textures::ID id, Vector2u _tileSize, unsigned int _width, unsigned int _height)
{
tileSize=_tileSize;
width=_width;
height=_height;
texture=resManager.Get(id);
vertices.setPrimitiveType(Quads);
vertices.resize(width * height * 4);
for (unsigned int i = 0; i < width; ++i)
for (unsigned int j = 0; j < height; ++j)
{
int tileNumber = cells[i + j * width].textureId;
int tu = tileNumber % (texture.getSize().x / tileSize.x);
int tv = tileNumber / (texture.getSize().x / tileSize.x);
Vertex* quad = &vertices[(i + j * width) * 4];
quad[0].position = Vector2f(i * tileSize.x, j * tileSize.y);
quad[1].position = Vector2f((i + 1) * tileSize.x, j * tileSize.y);
quad[2].position = Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
quad[3].position = Vector2f(i * tileSize.x, (j + 1) * tileSize.y);
quad[0].texCoords = Vector2f(tu * tileSize.x, tv * tileSize.y);
quad[1].texCoords = Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
quad[2].texCoords = Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
quad[3].texCoords = Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
}
return true;
}
virtual void draw(RenderTarget& target, RenderStates states) const
{
states.transform *= getTransform();
states.texture = &texture;
target.draw(vertices, states);
}
};
UnitManager.h
#include "main.h"
#include "Unit.h"
#include "ResManager.h"
class UnitManager
{
public:
vector<Unit> units;
unsigned int count;
UnitManager()
{
count=0;
}
void DrawUnitText(RenderTarget& target)
{
for (unsigned int i=0;i<count;i++)
{
int dx=units[i].text.getLocalBounds().width/2;
units[i].text.setPosition(units[i].sprite.getPosition().x+32-dx,units[i].sprite.getPosition().y-20);
target.draw(units[i].text);
}
}
void Draw(RenderTarget& target) const
{
for (unsigned int i=0;i<count;i++)
{
units[i].draw(target);
}
}
void LoadUnit(ResManager &resManager,Textures::ID id,const string &_name,Uint32 _x,Uint32 _y,Uint32 _hp,Font &font)
{
Unit unit;
unit.sprite.setTexture(resManager.Get(id));
unit.sprite.setPosition(_x,_y);
unit.name=_name;
unit.x=_x;
unit.y=_y;
unit.hp=_hp;
unit.text.setFont(font);
unit.text.setString(unit.name);
unit.text.setCharacterSize(16);
unit.text.setColor(Color::White);
units.push_back(unit);
count=count+1;
}
};
CellManager.h
#include "main.h"
#include "Cell.h"
class CellManager
{
public:
TileMap tileMap;
void GenCells()
{
int x=0,y=0;
for (unsigned int i=0;i<10000;i++)
{
if (x<19)
{
x=x+1;
}
else
{
x=0;
}
if (i%19==0)
{
y=y+1;
}
int random=GetRandomInt(0,2);
if (random==0)
{
tileMap.cells.push_back(Cell(1,x,y,0));
}
else if (random==1)
{
tileMap.cells.push_back(Cell(1,x,y,1));
}
else if (random==2)
{
tileMap.cells.push_back(Cell(0,x,y,2));
}
}
}
};
ResManager.h
#include "main.h"
#ifndef RESMANAGER_H
#define RESMANAGER_H
class ResManager
{
public:
map<Textures::ID,unique_ptr<Texture>>TextureMap;
vector <Texture> Textures;
Font MainFont;
bool LoadFont(const string &Name)
{
return MainFont.loadFromFile(Name);
}
void Load(Textures::ID id, const string& filename)
{
unique_ptr<Texture> texture(new Texture());
texture->loadFromFile(filename);
TextureMap.insert(make_pair(id, move(texture)));
}
Texture& Get(Textures::ID id)
{
auto found = TextureMap.find(id);
return *found->second;
}
};
#endif
Ред. SageOne