Cytopia  0.3
A city building simulation game
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Sprite.cxx
Go to the documentation of this file.
1 #include "Sprite.hxx"
2 
3 #include "ResourcesManager.hxx"
4 #include "WindowManager.hxx"
5 #include "basics/Camera.hxx"
6 #include "basics/isoMath.hxx"
7 #include "map/MapLayers.hxx"
8 #include "common/enums.hxx"
9 #include "LOG.hxx"
10 #include "Exception.hxx"
11 #include "GameStates.hxx"
12 
13 #ifdef MICROPROFILE_ENABLED
14 #include "microprofile/microprofile.h"
15 #endif
16 
17 Sprite::Sprite(Point _isoCoordinates)
18  : isoCoordinates(_isoCoordinates), m_SpriteData(LAYERS_COUNT), m_renderLayer(LAYERS_COUNT, true)
19 {
21 }
22 
23 void Sprite::render() const
24 {
25 #ifdef MICROPROFILE_ENABLED
26  MICROPROFILE_SCOPEI("Map", "Sprite render", MP_RED);
27 #endif
28  for (auto currentLayer : allLayersOrdered)
29  {
30  if (MapLayers::isLayerActive(currentLayer) && m_SpriteData[currentLayer].texture && m_renderLayer[currentLayer])
31  {
32  // Don't draw zones when there is a building on this sprite
33  if (currentLayer == Layer::ZONE && m_SpriteData[Layer::BUILDINGS].texture)
34  {
35  continue;
36  }
37  if (highlightSprite)
38  {
39  SDL_SetTextureColorMod(m_SpriteData[currentLayer].texture, highlightColor.r, highlightColor.g, highlightColor.b);
40  }
41 
42  if (GameStates::instance().layerEditMode == LayerEditMode::BLUEPRINT && currentLayer != Layer::BLUEPRINT &&
43  currentLayer != Layer::UNDERGROUND)
44  {
45  SDL_SetTextureAlphaMod(m_SpriteData[currentLayer].texture, 80);
46  }
47  else
48  {
49  SDL_SetTextureAlphaMod(m_SpriteData[currentLayer].texture, m_SpriteData[currentLayer].alpha);
50  }
51 
52  if (m_SpriteData[currentLayer].clipRect.w != 0)
53  {
54  SDL_RenderCopy(WindowManager::instance().getRenderer(), m_SpriteData[currentLayer].texture,
55  &m_SpriteData[currentLayer].clipRect, &m_SpriteData[currentLayer].destRect);
56  }
57  else
58  {
59  SDL_RenderCopy(WindowManager::instance().getRenderer(), m_SpriteData[currentLayer].texture, nullptr,
60  &m_SpriteData[currentLayer].destRect);
61  }
62 
63  if (highlightSprite)
64  {
65  SDL_SetTextureColorMod(m_SpriteData[currentLayer].texture, 255, 255, 255);
66  }
67 
68  SDL_SetTextureAlphaMod(m_SpriteData[currentLayer].texture, 255);
69  }
70  }
71 }
72 
73 void Sprite::refresh(const Layer &layer)
74 {
75  if (m_currentZoomLevel != Camera::instance().zoomLevel() || m_needsRefresh)
76  {
77  for (auto currentLayer : allLayersOrdered)
78  {
79  if (m_SpriteData[currentLayer].texture)
80  {
81  if (layer != NONE && currentLayer != layer)
82  {
83  continue;
84  }
86  int spriteSheetHeight = 0;
87  SDL_QueryTexture(m_SpriteData[currentLayer].texture, nullptr, nullptr, nullptr, &spriteSheetHeight);
88  // we need to offset the cliprect.y coodinate, because we've moved the "originpoint" for drawing the sprite to the screen on the bottom.
89  // the sprites need to start at the bottom, so the cliprect must too.
90  m_SpriteData[currentLayer].clipRect.y = spriteSheetHeight - m_SpriteData[currentLayer].clipRect.h;
91 
92  if (m_SpriteData[currentLayer].clipRect.w != 0)
93  {
94  m_SpriteData[currentLayer].destRect.w =
95  static_cast<int>(std::round(static_cast<double>(m_SpriteData[currentLayer].clipRect.w) * m_currentZoomLevel));
96  m_SpriteData[currentLayer].destRect.h =
97  static_cast<int>(std::round(static_cast<double>(m_SpriteData[currentLayer].clipRect.h) * m_currentZoomLevel));
98  }
99  else
100  {
101  SDL_QueryTexture(m_SpriteData[currentLayer].texture, nullptr, nullptr, &m_SpriteData[currentLayer].destRect.w,
102  &m_SpriteData[currentLayer].destRect.h);
103 
104  m_SpriteData[currentLayer].destRect.w =
105  static_cast<int>(std::round(static_cast<double>(m_SpriteData[currentLayer].clipRect.w) * m_currentZoomLevel));
106  m_SpriteData[currentLayer].destRect.h =
107  static_cast<int>(std::round(static_cast<double>(m_SpriteData[currentLayer].clipRect.h) * m_currentZoomLevel));
108  }
109  }
110  }
111  }
112 
113  // convert this tiles isometric coordinates to screen coordinates (with camera offset / zoomlevel taken into account.
115 
116  for (auto &it : m_SpriteData)
117  {
118  if (it.texture != nullptr)
119  {
120  // render the sprite in the middle of its bounding box so bigger than 1x1 sprites will render correctly
121  it.destRect.x = m_screenCoordinates.x - (it.destRect.w / 2);
122  // change y coordinates with sprites height taken into account to render the sprite at its base and not at its top.
123  it.destRect.y = m_screenCoordinates.y - it.destRect.h;
124  }
125  }
126 
127  m_needsRefresh = false;
128 }
129 
130 void Sprite::setTexture(SDL_Texture *texture, Layer layer)
131 {
132  if (!texture)
133  throw UIError(TRACE_INFO "Called Sprite::setTexture() with a non valid texture");
134  m_SpriteData[layer].texture = texture;
135  m_needsRefresh = true;
136  refresh(layer);
137 }
138 
139 void Sprite::setClipRect(SDL_Rect clipRect, const Layer layer) { m_SpriteData[layer].clipRect = clipRect; }
140 void Sprite::setDestRect(SDL_Rect destRect, Layer layer) { m_SpriteData[layer].destRect = destRect; }
141 
143 {
145  m_SpriteData[Layer::BUILDINGS].clipRect.h != 0)
146  {
147  return m_SpriteData[Layer::BUILDINGS].clipRect;
148  }
150  {
151  return m_SpriteData[Layer::TERRAIN].clipRect;
152  }
153  return {0, 0, 0, 0};
154 }
156 {
157  return (MapLayers::isLayerActive(layer) && m_SpriteData[layer].clipRect.w != 0 && m_SpriteData[layer].clipRect.h != 0);
158 }
159 
161 {
163  m_SpriteData[Layer::BUILDINGS].destRect.h != 0)
164  {
165  return m_SpriteData[Layer::BUILDINGS].destRect;
166  }
168  {
169  return m_SpriteData[Layer::TERRAIN].destRect;
170  }
171  return {0, 0, 0, 0};
172 }
173 
175 {
176  m_SpriteData[layer].clipRect = {0, 0, 0, 0};
177  m_SpriteData[layer].destRect = {0, 0, 0, 0};
178  m_SpriteData[layer].texture = nullptr;
179 }
TRACE_INFO
#define TRACE_INFO
Definition: Exception.hxx:12
Sprite::m_screenCoordinates
SDL_Point m_screenCoordinates
Definition: Sprite.hxx:68
UIError
A UI-related error occured.
Definition: Exception.hxx:76
Sprite::getActiveClipRect
SDL_Rect getActiveClipRect()
Definition: Sprite.cxx:142
isoMath.hxx
Sprite::highlightSprite
bool highlightSprite
Definition: Sprite.hxx:55
Sprite.hxx
TerrainEdit::NONE
@ NONE
Sprite::m_SpriteData
std::vector< SpriteData > m_SpriteData
Definition: Sprite.hxx:73
Sprite::Sprite
Sprite(Point isoCoordinates)
Definition: Sprite.cxx:17
SpriteRGBColor::r
uint8_t r
Definition: Sprite.hxx:20
LOG.hxx
Sprite::render
void render() const
Definition: Sprite.cxx:23
SpriteRGBColor::g
uint8_t g
Definition: Sprite.hxx:21
Sprite::isLayerUsed
bool isLayerUsed(Layer layer)
Definition: Sprite.cxx:155
enums.hxx
Camera.hxx
Sprite::m_currentZoomLevel
double m_currentZoomLevel
Definition: Sprite.hxx:71
GameStates.hxx
WindowManager.hxx
ZONE
@ ZONE
4- Optional layer, zones(Industrial/Residential/Commercial).
Definition: enums.hxx:15
BLUEPRINT
@ BLUEPRINT
1- Optional layer - Map Blueprint
Definition: enums.hxx:12
Sprite::m_needsRefresh
bool m_needsRefresh
Definition: Sprite.hxx:70
BUILDINGS
@ BUILDINGS
8- Buildings, Streets and everything that goes on the terrain
Definition: enums.hxx:19
Camera::zoomLevel
const double & zoomLevel() const noexcept
Definition: Camera.cxx:97
ResourcesManager.hxx
Sprite::getActiveDestRect
SDL_Rect getActiveDestRect()
Definition: Sprite.cxx:160
Sprite::setClipRect
void setClipRect(SDL_Rect clipRect, Layer layer=Layer::TERRAIN)
Definition: Sprite.cxx:139
Sprite::highlightColor
SpriteRGBColor highlightColor
Definition: Sprite.hxx:56
MapLayers::isLayerActive
static bool isLayerActive(unsigned int layer)
Check if given Layer is being drawn.
Definition: MapLayers.hxx:34
MapLayers.hxx
TERRAIN
@ TERRAIN
3- Terrain tiles, decorations, ... - must always be a "full" tile
Definition: enums.hxx:14
Sprite::setTexture
void setTexture(SDL_Texture *m_texture, Layer layer=Layer::TERRAIN)
Definition: Sprite.cxx:130
Sprite::isoCoordinates
Point isoCoordinates
Definition: Sprite.hxx:65
Sprite::m_renderLayer
std::vector< bool > m_renderLayer
Definition: Sprite.hxx:74
Sprite::refresh
void refresh(const Layer &layer=Layer::NONE)
Definition: Sprite.cxx:73
Point
Definition: Point.hxx:7
Sprite::clearSprite
void clearSprite(Layer layer)
Definition: Sprite.cxx:174
SpriteRGBColor::b
uint8_t b
Definition: Sprite.hxx:22
allLayersOrdered
static Layer allLayersOrdered[]
This is a ordered list of all relevant layers we need to interact with.
Definition: enums.hxx:29
Singleton< GameStates >::instance
static GameStates & instance(void)
Get an instance of the singleton.
Definition: Singleton.hxx:15
LAYERS_COUNT
@ LAYERS_COUNT
this must be LAST !!!
Definition: enums.hxx:25
Exception.hxx
Sprite::setDestRect
void setDestRect(SDL_Rect clipRect, Layer layer=Layer::TERRAIN)
Definition: Sprite.cxx:140
LayerEditMode::BLUEPRINT
@ BLUEPRINT
Placing water pipes and underground transportation on the Blueprint layer.
Layer
Layer
All Layers we have.
Definition: enums.hxx:9
UNDERGROUND
@ UNDERGROUND
2- Optional layer - Pipes, Subway-pipes and so onn
Definition: enums.hxx:13
convertIsoToScreenCoordinates
SDL_Point convertIsoToScreenCoordinates(const Point &isoCoordinates, bool calcWithoutOffset)
converts coordinates from isometric to screen space
Definition: isoMath.cxx:25