mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-06-08 17:42:05 +00:00
wip towards Element draw refactor; still using old render path
This commit is contained in:
parent
578c8ecc45
commit
c09098e13c
12 changed files with 444 additions and 151 deletions
169
Aquaria/Game.cpp
169
Aquaria/Game.cpp
|
@ -318,14 +318,7 @@ void Game::transitionToScene(std::string scene)
|
||||||
|
|
||||||
ElementTemplate *Game::getElementTemplateByIdx(size_t idx)
|
ElementTemplate *Game::getElementTemplateByIdx(size_t idx)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < elementTemplates.size(); i++)
|
return tileset.getByIdx(idx);
|
||||||
{
|
|
||||||
if (elementTemplates[i].idx == idx)
|
|
||||||
{
|
|
||||||
return &elementTemplates[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Element* Game::createElement(size_t idx, Vector position, size_t bgLayer, RenderObject *copy, ElementTemplate *et)
|
Element* Game::createElement(size_t idx, Vector position, size_t bgLayer, RenderObject *copy, ElementTemplate *et)
|
||||||
|
@ -338,8 +331,7 @@ Element* Game::createElement(size_t idx, Vector position, size_t bgLayer, Render
|
||||||
Element *element = new Element();
|
Element *element = new Element();
|
||||||
if (et)
|
if (et)
|
||||||
{
|
{
|
||||||
element->setTexture(et->gfx);
|
element->setTexturePointer(et->getTexture());
|
||||||
element->alpha = et->alpha;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
element->position = position;
|
element->position = position;
|
||||||
|
@ -377,7 +369,6 @@ Element* Game::createElement(size_t idx, Vector position, size_t bgLayer, Render
|
||||||
}
|
}
|
||||||
addRenderObject(element, LR_ELEMENTS1+bgLayer);
|
addRenderObject(element, LR_ELEMENTS1+bgLayer);
|
||||||
dsq->addElement(element);
|
dsq->addElement(element);
|
||||||
//element->updateCullVariables();
|
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
@ -1335,6 +1326,8 @@ bool Game::loadSceneXML(std::string scene)
|
||||||
}
|
}
|
||||||
clearObsRows();
|
clearObsRows();
|
||||||
|
|
||||||
|
std::string tilesetToLoad;
|
||||||
|
|
||||||
XMLElement *level = doc.FirstChildElement("Level");
|
XMLElement *level = doc.FirstChildElement("Level");
|
||||||
if (level)
|
if (level)
|
||||||
{
|
{
|
||||||
|
@ -1344,7 +1337,7 @@ bool Game::loadSceneXML(std::string scene)
|
||||||
tileset = level->Attribute("elementTemplatePack"); // legacy, still present in some very old maps
|
tileset = level->Attribute("elementTemplatePack"); // legacy, still present in some very old maps
|
||||||
if (tileset)
|
if (tileset)
|
||||||
{
|
{
|
||||||
loadElementTemplates(tileset);
|
tilesetToLoad = tileset;
|
||||||
levelSF->SetAttribute("tileset", tileset);
|
levelSF->SetAttribute("tileset", tileset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1756,6 +1749,7 @@ bool Game::loadSceneXML(std::string scene)
|
||||||
if(fullTilesetReload)
|
if(fullTilesetReload)
|
||||||
{
|
{
|
||||||
fullTilesetReload = false;
|
fullTilesetReload = false;
|
||||||
|
tileset.clear();
|
||||||
// used by SceneEditor
|
// used by SceneEditor
|
||||||
// no elements exist right now -> textures will be cleared and reloaded
|
// no elements exist right now -> textures will be cleared and reloaded
|
||||||
dsq->texmgr.clearUnused();
|
dsq->texmgr.clearUnused();
|
||||||
|
@ -1763,6 +1757,10 @@ bool Game::loadSceneXML(std::string scene)
|
||||||
|
|
||||||
// figure out which textures in the tileset are used and preload those that are actually used
|
// figure out which textures in the tileset are used and preload those that are actually used
|
||||||
{
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Scene has " << elemsDefs.size() << " elements";
|
||||||
|
debugLog(os.str());
|
||||||
|
|
||||||
unsigned char usedIdx[1024] = {0};
|
unsigned char usedIdx[1024] = {0};
|
||||||
for(size_t i = 0; i < elemsDefs.size(); ++i)
|
for(size_t i = 0; i < elemsDefs.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -1770,27 +1768,8 @@ bool Game::loadSceneXML(std::string scene)
|
||||||
if(idx < Countof(usedIdx))
|
if(idx < Countof(usedIdx))
|
||||||
usedIdx[idx] = 1;
|
usedIdx[idx] = 1;
|
||||||
}
|
}
|
||||||
std::vector<std::string> usedTex;
|
|
||||||
usedTex.reserve(elementTemplates.size()); // optimistically assume all textures in the tileset are used
|
|
||||||
|
|
||||||
for (size_t i = 0; i < elementTemplates.size(); i++)
|
loadElementTemplates(tilesetToLoad, &usedIdx[0], Countof(usedIdx));
|
||||||
{
|
|
||||||
unsigned idx = elementTemplates[i].idx;
|
|
||||||
if (idx < Countof(usedIdx) && usedIdx[idx])
|
|
||||||
usedTex.push_back(elementTemplates[i].gfx);
|
|
||||||
}
|
|
||||||
std::sort(usedTex.begin(), usedTex.end());
|
|
||||||
// drop duplicates
|
|
||||||
usedTex.resize(std::distance(usedTex.begin(), std::unique(usedTex.begin(), usedTex.end())));
|
|
||||||
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "Scene has " << elemsDefs.size() << " elements that use " << usedTex.size()
|
|
||||||
<< " distinct textures out of the " << elementTemplates.size() << " entries in the tileset";
|
|
||||||
debugLog(os.str());
|
|
||||||
|
|
||||||
// preload all used textures
|
|
||||||
if(usedTex.size())
|
|
||||||
dsq->texmgr.loadBatch(NULL, &usedTex[0], usedTex.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that all SE tags have been processed, spawn them
|
// Now that all SE tags have been processed, spawn them
|
||||||
|
@ -4690,79 +4669,55 @@ void Game::snapCam()
|
||||||
warpCameraTo(*cameraFollow);
|
warpCameraTo(*cameraFollow);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementTemplate Game::getElementTemplateForLetter(int i)
|
bool Game::loadElementTemplates(std::string pack, const unsigned char *usedIdx, size_t usedIdxLen)
|
||||||
{
|
|
||||||
float cell = 64.0f/512.0f;
|
|
||||||
//for (int i = 0; i < 27; i++)
|
|
||||||
ElementTemplate t;
|
|
||||||
t.idx = 1024+i;
|
|
||||||
t.gfx = "Aquarian";
|
|
||||||
int x = i,y=0;
|
|
||||||
while (x >= 6)
|
|
||||||
{
|
|
||||||
x -= 6;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
|
|
||||||
t.tu1 = x*cell;
|
|
||||||
t.tv1 = y*cell;
|
|
||||||
t.tu2 = t.tu1 + cell;
|
|
||||||
t.tv2 = t.tv1 + cell;
|
|
||||||
|
|
||||||
t.tv2 = 1 - t.tv2;
|
|
||||||
t.tv1 = 1 - t.tv1;
|
|
||||||
std::swap(t.tv1,t.tv2);
|
|
||||||
|
|
||||||
t.w = 512*cell;
|
|
||||||
t.h = 512*cell;
|
|
||||||
//elementTemplates.push_back(t);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::loadElementTemplates(std::string pack)
|
|
||||||
{
|
{
|
||||||
stringToLower(pack);
|
stringToLower(pack);
|
||||||
|
|
||||||
elementTemplates.clear();
|
|
||||||
|
|
||||||
std::string fn;
|
std::string fn;
|
||||||
if (dsq->mod.isActive())
|
if (dsq->mod.isActive())
|
||||||
fn = dsq->mod.getPath() + "tilesets/" + pack + ".txt";
|
fn = dsq->mod.getPath() + "tilesets/" + pack + ".txt";
|
||||||
else
|
else
|
||||||
fn = "data/tilesets/" + pack + ".txt";
|
fn = "data/tilesets/" + pack + ".txt";
|
||||||
|
|
||||||
if (!exists(fn))
|
if(!tileset.loadFile(fn.c_str(), usedIdx, usedIdxLen))
|
||||||
{
|
{
|
||||||
errorLog ("Could not open tileset [" + fn + "]");
|
errorLog ("Could not load tileset [" + fn + "]");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InStream in(fn.c_str());
|
// Aquarian alphabet letters
|
||||||
std::string line;
|
if(const CountedPtr<Texture> aqtex = dsq->getTexture("aquarian"))
|
||||||
while (std::getline(in, line))
|
|
||||||
{
|
{
|
||||||
int idx=-1, w=-1, h=-1;
|
const float cell = 64.0f/512.0f;
|
||||||
std::string gfx;
|
for (int i = 0; i < 27; i++)
|
||||||
std::istringstream is(line);
|
{
|
||||||
is >> idx >> gfx >> w >> h;
|
ElementTemplate t;
|
||||||
ElementTemplate t;
|
t.idx = 1024+i;
|
||||||
t.idx = idx;
|
t.tex = aqtex;
|
||||||
t.gfx = gfx;
|
int x = i,y=0;
|
||||||
if (w==0) w=-1;
|
while (x >= 6)
|
||||||
if (h==0) h=-1;
|
{
|
||||||
t.w = w;
|
x -= 6;
|
||||||
t.h = h;
|
y++;
|
||||||
elementTemplates.push_back(t);
|
}
|
||||||
|
|
||||||
|
t.tu1 = x*cell;
|
||||||
|
t.tv1 = y*cell;
|
||||||
|
t.tu2 = t.tu1 + cell;
|
||||||
|
t.tv2 = t.tv1 + cell;
|
||||||
|
|
||||||
|
t.tv2 = 1 - t.tv2;
|
||||||
|
t.tv1 = 1 - t.tv1;
|
||||||
|
std::swap(t.tv1,t.tv2);
|
||||||
|
|
||||||
|
t.w = 512*cell;
|
||||||
|
t.h = 512*cell;
|
||||||
|
|
||||||
|
tileset.elementTemplates.push_back(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
in.close();
|
|
||||||
|
|
||||||
|
return true;
|
||||||
std::sort(elementTemplates.begin(), elementTemplates.end());
|
|
||||||
|
|
||||||
for (int i = 0; i < 27; i++)
|
|
||||||
{
|
|
||||||
elementTemplates.push_back(getElementTemplateForLetter(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::clearGrid(int v)
|
void Game::clearGrid(int v)
|
||||||
|
@ -4778,40 +4733,6 @@ void Game::resetFromTitle()
|
||||||
overrideMusic = "";
|
overrideMusic = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::setGrid(ElementTemplate *et, Vector position, float rot360)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < et->grid.size(); i++)
|
|
||||||
{
|
|
||||||
TileVector t(position);
|
|
||||||
int x = et->grid[i].x;
|
|
||||||
int y = et->grid[i].y;
|
|
||||||
if (rot360 >= 0 && rot360 < 90)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (rot360 >= 90 && rot360 < 180)
|
|
||||||
{
|
|
||||||
int swap = y;
|
|
||||||
y = x;
|
|
||||||
x = swap;
|
|
||||||
x = -x;
|
|
||||||
}
|
|
||||||
else if (rot360 >= 180 && rot360 < 270)
|
|
||||||
{
|
|
||||||
x = -x;
|
|
||||||
y = -y;
|
|
||||||
}
|
|
||||||
else if (rot360 >= 270 && rot360 < 360)
|
|
||||||
{
|
|
||||||
int swap = y;
|
|
||||||
y = x;
|
|
||||||
x = swap;
|
|
||||||
y = -y;
|
|
||||||
}
|
|
||||||
TileVector s(t.x+x, t.y+y);
|
|
||||||
setGrid(s, OT_INVISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::removeState()
|
void Game::removeState()
|
||||||
{
|
{
|
||||||
const float fadeTime = 0.25;
|
const float fadeTime = 0.25;
|
||||||
|
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#include "ScriptedEntity.h"
|
#include "ScriptedEntity.h"
|
||||||
#include "TileVector.h"
|
#include "TileVector.h"
|
||||||
#include "SceneEditor.h"
|
#include "SceneEditor.h"
|
||||||
|
#include "Tileset.h"
|
||||||
|
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
using namespace tinyxml2;
|
using namespace tinyxml2;
|
||||||
|
@ -84,20 +85,6 @@ struct MinimapIcon
|
||||||
|
|
||||||
typedef std::list<Ingredient*> Ingredients;
|
typedef std::list<Ingredient*> Ingredients;
|
||||||
|
|
||||||
class ElementTemplate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ElementTemplate() { alpha = 1; cull = true; w=-1; h=-1; idx=-1; tu1=tu2=tv1=tv2=0; }
|
|
||||||
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
|
|
||||||
std::string gfx;
|
|
||||||
std::vector <TileVector> grid;
|
|
||||||
int w,h;
|
|
||||||
float tu1, tu2, tv1, tv2;
|
|
||||||
bool cull;
|
|
||||||
float alpha;
|
|
||||||
size_t idx;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ObsRow
|
class ObsRow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -171,9 +158,10 @@ public:
|
||||||
|
|
||||||
InGameMenu *getInGameMenu() { return themenu; }
|
InGameMenu *getInGameMenu() { return themenu; }
|
||||||
|
|
||||||
void loadElementTemplates(std::string pack);
|
// pass usedIdx == NULL to preload all textures from tileset
|
||||||
|
// pass usedIdx != NULL to preload only textures where usedIdx[i] != 0
|
||||||
|
bool loadElementTemplates(std::string pack, const unsigned char *usedIdx, size_t usedIdxLen);
|
||||||
Element* createElement(size_t etidx, Vector position, size_t bgLayer=0, RenderObject *copy=0, ElementTemplate *et=0);
|
Element* createElement(size_t etidx, Vector position, size_t bgLayer=0, RenderObject *copy=0, ElementTemplate *et=0);
|
||||||
void setGrid(ElementTemplate *et, Vector position, float rot360=0);
|
|
||||||
|
|
||||||
void updateParticlePause();
|
void updateParticlePause();
|
||||||
|
|
||||||
|
@ -196,7 +184,7 @@ public:
|
||||||
void handleShotCollisionsSkeletal(Entity *e);
|
void handleShotCollisionsSkeletal(Entity *e);
|
||||||
void handleShotCollisionsHair(Entity *e, int num = 0, float perc = 0);
|
void handleShotCollisionsHair(Entity *e, int num = 0, float perc = 0);
|
||||||
|
|
||||||
std::vector<ElementTemplate> elementTemplates;
|
Tileset tileset;
|
||||||
std::string sceneName, sceneDisplayName;
|
std::string sceneName, sceneDisplayName;
|
||||||
|
|
||||||
ElementTemplate *getElementTemplateByIdx(size_t idx);
|
ElementTemplate *getElementTemplateByIdx(size_t idx);
|
||||||
|
@ -362,7 +350,6 @@ public:
|
||||||
void setMusicToPlay(const std::string &musicToPlay);
|
void setMusicToPlay(const std::string &musicToPlay);
|
||||||
Vector lastCollidePosition;
|
Vector lastCollidePosition;
|
||||||
void switchBgLoop(int v);
|
void switchBgLoop(int v);
|
||||||
ElementTemplate getElementTemplateForLetter(int i);
|
|
||||||
CurrentRender *currentRender;
|
CurrentRender *currentRender;
|
||||||
SteamRender *steamRender;
|
SteamRender *steamRender;
|
||||||
SongLineRender *songLineRender;
|
SongLineRender *songLineRender;
|
||||||
|
|
|
@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "../BBGE/Vector.h"
|
#include "../BBGE/Vector.h"
|
||||||
|
|
||||||
const int TILE_SIZE = 20;
|
enum { TILE_SIZE = 20 };
|
||||||
|
|
||||||
class TileVector
|
class TileVector
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,6 +109,12 @@ set(BBGE_SRCS
|
||||||
TextureMgr.h
|
TextureMgr.h
|
||||||
TTFFont.cpp
|
TTFFont.cpp
|
||||||
TTFFont.h
|
TTFFont.h
|
||||||
|
Tile.cpp
|
||||||
|
Tile.h
|
||||||
|
TileRender.cpp
|
||||||
|
TileRender.h
|
||||||
|
Tileset.cpp
|
||||||
|
Tileset.h
|
||||||
Vector.cpp
|
Vector.cpp
|
||||||
Vector.h
|
Vector.h
|
||||||
Window.cpp
|
Window.cpp
|
||||||
|
|
|
@ -205,6 +205,7 @@ public:
|
||||||
|
|
||||||
// Defined in RenderObject_inline.h
|
// Defined in RenderObject_inline.h
|
||||||
inline Vector getFollowCameraPosition() const;
|
inline Vector getFollowCameraPosition() const;
|
||||||
|
inline Vector getFollowCameraPosition(const Vector& pos) const;
|
||||||
|
|
||||||
void lookAt(const Vector &pos, float t, float minAngle, float maxAngle, float offset=0);
|
void lookAt(const Vector &pos, float t, float minAngle, float maxAngle, float offset=0);
|
||||||
inline RenderObject *getParent() const {return parent;}
|
inline RenderObject *getParent() const {return parent;}
|
||||||
|
|
|
@ -33,19 +33,42 @@ inline bool RenderObject::isOnScreen() const
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector RenderObject::getFollowCameraPosition() const
|
Vector RenderObject::getFollowCameraPosition() const
|
||||||
|
{
|
||||||
|
return getFollowCameraPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector RenderObject::getFollowCameraPosition(const Vector& v) const
|
||||||
{
|
{
|
||||||
assert(layer != LR_NONE);
|
assert(layer != LR_NONE);
|
||||||
assert(!parent); // this makes no sense when we're not a root object
|
assert(!parent); // this makes no sense when we're not a root object
|
||||||
const RenderObjectLayer &rl = core->renderObjectLayers[layer];
|
const RenderObjectLayer &rl = core->renderObjectLayers[layer];
|
||||||
Vector mul = rl.followCameraMult;
|
Vector M = rl.followCameraMult;
|
||||||
float f = followCamera;
|
float F = followCamera;
|
||||||
if(!f)
|
if(!F)
|
||||||
f = rl.followCamera;
|
F = rl.followCamera;
|
||||||
if (f <= 0)
|
if (F <= 0)
|
||||||
return position;
|
return v;
|
||||||
|
|
||||||
const Vector pos = (position - core->screenCenter) * f + core->screenCenter;
|
/* Originally, not accounting for parallax lock on an axis, this was:
|
||||||
return position * (Vector(1,1) - mul) + (pos * mul); // lerp
|
pos = v - core->screenCenter;
|
||||||
|
pos *= F;
|
||||||
|
pos = core->screenCenter + pos;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// uppercase are effectively constants that are not per-object
|
||||||
|
// lowercase are per-object
|
||||||
|
|
||||||
|
// more concise math:
|
||||||
|
//const Vector pos = (v - core->screenCenter) * F + core->screenCenter;
|
||||||
|
//return v * (Vector(1,1) - M) + (pos * M); // lerp
|
||||||
|
|
||||||
|
// optimized and rearranged
|
||||||
|
const Vector C = core->screenCenter;
|
||||||
|
const Vector M1 = Vector(1,1) - M;
|
||||||
|
const Vector T = C * (1 - F);
|
||||||
|
|
||||||
|
const Vector pos = T + (F * v);
|
||||||
|
return v * M1 + (pos * M); // lerp, used to select whether to use original v or parallax-corrected v
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
2
BBGE/Tile.cpp
Normal file
2
BBGE/Tile.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#include "Tile.h"
|
||||||
|
|
60
BBGE/Tile.h
Normal file
60
BBGE/Tile.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef BBGE_TILE_H
|
||||||
|
#define BBGE_TILE_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
class ElementTemplate;
|
||||||
|
class Texture;
|
||||||
|
|
||||||
|
// A Tile is a very stripped down RenderObject that bypasses the default
|
||||||
|
// rendering pipeline for efficiency reasons.
|
||||||
|
// Use a TileRender to draw a list of Tiles.
|
||||||
|
|
||||||
|
/* Properties of tiles:
|
||||||
|
- Lots of these exist. Need to store & render efficiently
|
||||||
|
- Usually no dynamic behavior, BUT:
|
||||||
|
* can have a TileEffect that requires updating (sometimes)
|
||||||
|
* can react to entities nearby (rare)
|
||||||
|
* may have a draw grid (wobbly plants etc)
|
||||||
|
- Only modified in the editor -> Can be slow to modify or reorder
|
||||||
|
- Render order must be strictly followed to get the correct visual overlapping
|
||||||
|
- Never part of a parent/child hierarchy, all tiles are standalone
|
||||||
|
- Does not have offset, internalOffset, gravity, etc etc that RenderObject has
|
||||||
|
- Parallax scroll factor is solely influenced by layer, not individually
|
||||||
|
- RGB is never tinted, alpha may come from efx
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum TileFlags
|
||||||
|
{
|
||||||
|
TILEFLAG_NONE = 0,
|
||||||
|
TILEFLAG_REPEAT = 0x01, // texture repeats and uses texscale for the repeat factor
|
||||||
|
TILEFLAG_SOLID = 0x02, // generates OT_INVISIBLE
|
||||||
|
TILEFLAG_SOLID_THICK = 0x04, // generates more OT_INVISIBLE
|
||||||
|
TILEFLAG_SOLID_IN = 0x08, // instead of OT_INVISIBLE, generate OT_INVISIBLEIN
|
||||||
|
TILEFLAG_HURT = 0x10, // always generate OT_HURT
|
||||||
|
TILEFLAG_FH = 0x20, // flipped horizontally
|
||||||
|
};
|
||||||
|
|
||||||
|
// sort-of-POD
|
||||||
|
struct TileData
|
||||||
|
{
|
||||||
|
float x, y, rotation, texscale;
|
||||||
|
Vector scale, beforeScaleOffset;
|
||||||
|
int efx;
|
||||||
|
unsigned flags; // TileFlags
|
||||||
|
unsigned tag;
|
||||||
|
ElementTemplate *et;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class TileStorage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<TileData> tiles;
|
||||||
|
void refresh(); // call when adding/removing/reordering tiles or changing efx
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BBGE_TILE_H
|
135
BBGE/TileRender.cpp
Normal file
135
BBGE/TileRender.cpp
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
#include "TileRender.h"
|
||||||
|
#include "RenderBase.h"
|
||||||
|
#include "Core.h"
|
||||||
|
#include "Tileset.h"
|
||||||
|
|
||||||
|
TileRender::TileRender(const TileStorage& tiles)
|
||||||
|
: storage(tiles)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TileRender::~TileRender()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileRender::onRender(const RenderState& rs) const
|
||||||
|
{
|
||||||
|
// prepare. get parallax scroll factors
|
||||||
|
const RenderObjectLayer& rl = core->renderObjectLayers[this->layer];
|
||||||
|
Vector M = rl.followCameraMult; // affected by parallaxLock
|
||||||
|
const float F = rl.followCamera;
|
||||||
|
|
||||||
|
// Formula from RenderObject::getFollowCameraPosition() and optimized for speed
|
||||||
|
const Vector C = core->screenCenter;
|
||||||
|
const Vector M1 = Vector(1,1) - M;
|
||||||
|
const Vector T = C * (1 - F);
|
||||||
|
|
||||||
|
unsigned lastTexRepeat = false;
|
||||||
|
unsigned lastTexId = 0;
|
||||||
|
BlendType blend = BLEND_DEFAULT; // TODO: influenced by efx
|
||||||
|
const bool renderBorders = true; // TODO: when layer selected in editor
|
||||||
|
|
||||||
|
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
||||||
|
{
|
||||||
|
const TileData& tile = storage.tiles[i];
|
||||||
|
const Vector tilepos(tile.x, tile.y);
|
||||||
|
const Vector tmp = T + (F * tilepos);
|
||||||
|
const Vector pos = tilepos * M1 + (tmp * M); // lerp, used to select whether to use original v or parallax-corrected v
|
||||||
|
|
||||||
|
rs.gpu.setBlend(blend);
|
||||||
|
|
||||||
|
ElementTemplate * const et = tile.et;
|
||||||
|
if(Texture * const tex = et->tex.content())
|
||||||
|
{
|
||||||
|
unsigned texid = tex->gltexid;
|
||||||
|
unsigned rep = tile.flags & TILEFLAG_REPEAT;
|
||||||
|
if(texid != lastTexId || rep != lastTexRepeat)
|
||||||
|
{
|
||||||
|
lastTexId = texid;
|
||||||
|
lastTexRepeat = rep;
|
||||||
|
tex->apply(!!rep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0); // unlikely
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(pos.x, pos.y, pos.z);
|
||||||
|
|
||||||
|
glRotatef(tile.rotation, 0, 0, 1);
|
||||||
|
if(tile.flags & TILEFLAG_FH)
|
||||||
|
glRotatef(180, 0, 1, 0);
|
||||||
|
|
||||||
|
// this is only relevant in editor mode and is always 0 otherwise
|
||||||
|
glTranslatef(tile.beforeScaleOffset.x, tile.beforeScaleOffset.y, tile.beforeScaleOffset.z);
|
||||||
|
|
||||||
|
glScalef(tile.scale.x, tile.scale.y, 1);
|
||||||
|
|
||||||
|
// TODO: only need to do this when prev. tile had different alpha
|
||||||
|
{
|
||||||
|
const float alpha = 1; // TODO: via efx
|
||||||
|
Vector col = rs.color;
|
||||||
|
glColor4f(col.x, col.y, col.z, rs.alpha*alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float _w2 = float(int(et->w)) * 0.5f;
|
||||||
|
const float _h2 = float(int(et->h)) * 0.5f;
|
||||||
|
|
||||||
|
// render texture
|
||||||
|
{
|
||||||
|
const Vector upperLeftTextureCoordinates(et->tu1, et->tv1);
|
||||||
|
const Vector lowerRightTextureCoordinates(et->tu2, et->tv2);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
{
|
||||||
|
glTexCoord2f(upperLeftTextureCoordinates.x, 1.0f-upperLeftTextureCoordinates.y);
|
||||||
|
glVertex2f(-_w2, +_h2);
|
||||||
|
|
||||||
|
glTexCoord2f(lowerRightTextureCoordinates.x, 1.0f-upperLeftTextureCoordinates.y);
|
||||||
|
glVertex2f(+_w2, +_h2);
|
||||||
|
|
||||||
|
glTexCoord2f(lowerRightTextureCoordinates.x, 1.0f-lowerRightTextureCoordinates.y);
|
||||||
|
glVertex2f(+_w2, -_h2);
|
||||||
|
|
||||||
|
glTexCoord2f(upperLeftTextureCoordinates.x, 1.0f-lowerRightTextureCoordinates.y);
|
||||||
|
glVertex2f(-_w2, -_h2);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(renderBorders)
|
||||||
|
{
|
||||||
|
lastTexId = 0;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
Vector color(0.5f,0.5f,0.5f); // TODO: (1,1,1) when selected
|
||||||
|
|
||||||
|
|
||||||
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
||||||
|
glPointSize(16);
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
glVertex2f(0,0);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glLineWidth(2);
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
glVertex2f(_w2, _h2);
|
||||||
|
glVertex2f(_w2, -_h2);
|
||||||
|
glVertex2f(-_w2, -_h2);
|
||||||
|
glVertex2f(-_w2, _h2);
|
||||||
|
glVertex2f(_w2, _h2);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RenderObject::lastTextureApplied = lastTexId;
|
||||||
|
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileRender::onUpdate(float dt)
|
||||||
|
{
|
||||||
|
}
|
24
BBGE/TileRender.h
Normal file
24
BBGE/TileRender.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef BBGE_TILERENDER_H
|
||||||
|
#define BBGE_TILERENDER_H
|
||||||
|
|
||||||
|
#include "RenderObject.h"
|
||||||
|
#include "Tile.h"
|
||||||
|
|
||||||
|
class Tileset;
|
||||||
|
|
||||||
|
class TileRender : public RenderObject
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const TileStorage& storage;
|
||||||
|
public:
|
||||||
|
|
||||||
|
TileRender(const TileStorage& tiles);
|
||||||
|
virtual ~TileRender();
|
||||||
|
virtual void onRender(const RenderState& rs) const;
|
||||||
|
virtual void onUpdate(float dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BBGE_TILERENDER_H
|
94
BBGE/Tileset.cpp
Normal file
94
BBGE/Tileset.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#include "Tileset.h"
|
||||||
|
#include "SimpleIStringStream.h"
|
||||||
|
#include "Base.h"
|
||||||
|
#include "ttvfs_stdio.h"
|
||||||
|
#include "TextureMgr.h"
|
||||||
|
#include "Core.h"
|
||||||
|
|
||||||
|
bool Tileset::loadFile(const char *fn, const unsigned char *usedIdx, size_t usedIdxLen)
|
||||||
|
{
|
||||||
|
elementTemplates.clear();
|
||||||
|
|
||||||
|
InStream in(fn);
|
||||||
|
if(!in)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string line, gfx;
|
||||||
|
while (std::getline(in, line))
|
||||||
|
{
|
||||||
|
int idx=-1, w=0, h=0;
|
||||||
|
SimpleIStringStream is(line.c_str(), SimpleIStringStream::REUSE);
|
||||||
|
is >> idx >> gfx >> w >> h;
|
||||||
|
if(idx > 0)
|
||||||
|
{
|
||||||
|
ElementTemplate t;
|
||||||
|
t.idx = idx;
|
||||||
|
t.gfx = gfx;
|
||||||
|
t.w = w;
|
||||||
|
t.h = h;
|
||||||
|
elementTemplates.push_back(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
std::sort(elementTemplates.begin(), elementTemplates.end());
|
||||||
|
|
||||||
|
// begin preloading textures
|
||||||
|
|
||||||
|
std::vector<std::string> usedTex;
|
||||||
|
usedTex.reserve(elementTemplates.size()); // optimistically assume all textures in the tileset are used
|
||||||
|
|
||||||
|
for (size_t i = 0; i < elementTemplates.size(); i++)
|
||||||
|
{
|
||||||
|
size_t idx = elementTemplates[i].idx;
|
||||||
|
if (!usedIdx || (idx < usedIdxLen && usedIdx[idx]))
|
||||||
|
usedTex.push_back(elementTemplates[i].gfx);
|
||||||
|
}
|
||||||
|
std::sort(usedTex.begin(), usedTex.end());
|
||||||
|
// drop duplicates
|
||||||
|
usedTex.resize(std::distance(usedTex.begin(), std::unique(usedTex.begin(), usedTex.end())));
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
os << "Loading " << usedTex.size()
|
||||||
|
<< " used textures out of the " << elementTemplates.size() << " tileset entries";
|
||||||
|
debugLog(os.str());
|
||||||
|
|
||||||
|
// preload all used textures
|
||||||
|
if(usedTex.size())
|
||||||
|
core->texmgr.loadBatch(NULL, &usedTex[0], usedTex.size());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tileset::clear()
|
||||||
|
{
|
||||||
|
elementTemplates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ElementTemplate *Tileset::getByIdx(size_t idx)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < elementTemplates.size(); i++)
|
||||||
|
{
|
||||||
|
if (elementTemplates[i].idx == idx)
|
||||||
|
{
|
||||||
|
return &elementTemplates[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture* ElementTemplate::getTexture()
|
||||||
|
{
|
||||||
|
if(tex)
|
||||||
|
return tex.content();
|
||||||
|
|
||||||
|
tex = core->getTexture(gfx);
|
||||||
|
if(!w)
|
||||||
|
w = tex->width;
|
||||||
|
if(!h)
|
||||||
|
h = tex->height;
|
||||||
|
|
||||||
|
return tex.content();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
40
BBGE/Tileset.h
Normal file
40
BBGE/Tileset.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef BBGE_TILESET_H
|
||||||
|
#define BBGE_TILESET_H
|
||||||
|
|
||||||
|
#include "Vector.h"
|
||||||
|
#include <vector>
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
class ElementTemplate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; }
|
||||||
|
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
|
||||||
|
|
||||||
|
Texture *getTexture(); // loads if not already loaded
|
||||||
|
|
||||||
|
// lazily assigned when tex is loaded
|
||||||
|
CountedPtr<Texture> tex;
|
||||||
|
unsigned w,h; // custom size if used, otherwise texture size
|
||||||
|
|
||||||
|
// fixed
|
||||||
|
float tu1, tu2, tv1, tv2; // texcoords
|
||||||
|
size_t idx;
|
||||||
|
std::string gfx;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Tileset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// pass usedIdx == NULL to preload all textures from tileset
|
||||||
|
// pass usedIdx != NULL to preload only textures where usedIdx[i] != 0
|
||||||
|
bool loadFile(const char *fn, const unsigned char *usedIdx, size_t usedIdxLen);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
ElementTemplate *getByIdx(size_t idx);
|
||||||
|
|
||||||
|
std::vector<ElementTemplate> elementTemplates;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Reference in a new issue