Select Git revision
demo4-scale-out-lb-in-aws.py
Forked from
Sebastian Rieger / cloud-computing-msc-ai-examples
Source project has a limited visibility.
Spritesheet.cpp 16.31 KiB
/**
* Spritesheet.hpp
*
* @date 30.1.2025
* @author David Maul
* @author Frederik Keens
*/
#include "Spritesheet.hpp"
#include "Engine.hpp"
#include <SDL_image.h>
#include <SDL_render.h>
#include <cstddef>
#include <cstdint>
#include <highfive/H5File.hpp>
#include <stdexcept>
#include <string>
#include <vector>
namespace advanced_wars
{
Spritesheet::Spritesheet(std::string path, Engine& engine)
: m_tileWidth(16), m_tileHeight(16), m_buildingWidth(16), m_buildingHeight(32)
{
HighFive::File file(path, HighFive::File::ReadOnly);
// Tiles
std::vector<std::string> tiles(
{"plain",
"water",
"forest",
"mountain",
"bridge_horizontal",
"bridge_vertical",
"street_horizontal",
"street_vertical",
"street_crossing",
"street_junction_right",
"street_junction_left",
"street_junction_down",
"street_junction_up",
"street_corner_top_left",
"street_corner_top_right",
"street_corner_bottom_left",
"street_corner_bottom_right",
"riff",
"cliff_top",
"cliff_bottom",
"cliff_left",
"cliff_right",
"cliff_corner_top_left",
"cliff_corner_top_right",
"cliff_corner_bottom_left",
"cliff_corner_bottom_right",
"cliff_inverse_corner_top_left",
"cliff_inverse_corner_top_right",
"cliff_inverse_corner_bottom_left",
"cliff_inverse_corner_bottom_right"});
// every sub data set of tiles
for (const auto& tile : tiles)
{
HighFive::DataSet unitsDs = file.getDataSet("tiles/" + tile);
std::vector<std::vector<std::vector<uint32_t>>> tileFrames;
unitsDs.read(tileFrames);
std::vector<uint32_t> tileBuffer(16 * 16 * tileFrames.size(), 0);
// every animation frame
for (size_t n = 0; n < tileFrames.size(); n++)
{
for (size_t y = 0; y < 16; y++)
{
for (size_t x = 0; x < 16; x++)
{
size_t index = (y * tileFrames.size() * 16) + (n * 16 + x);
tileBuffer.at(index) = tileFrames.at(n).at(16 - y - 1).at(x);
}
}
}
SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
tileFrames.size() * 16, 16);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Tiles: " + std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(
tmp, nullptr, tileBuffer.data(), tileFrames.size() * 16 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Tiles: " + std::string(SDL_GetError()));
}
m_tileTextures.emplace_back(tmp, tileFrames.size());
}
// Buildings
std::vector<std::string> buildingFactions(
{"red", "blue", "green", "yellow", "purple", "neutral"});
// every sub data set of buildings
for (const std::string& faction : buildingFactions)
{
HighFive::DataSet buildingsDs = file.getDataSet("buildings/" + faction);
std::vector<std::vector<std::vector<uint32_t>>> buildingsFrames;
buildingsDs.read(buildingsFrames);
std::vector<uint32_t> buildingBuffer(32 * 16 * buildingsFrames.size(), 0);
// every type of building
for (size_t n = 0; n < buildingsFrames.size(); n++)
{
for (size_t y = 0; y < 32; y++)
{
for (size_t x = 0; x < 16; x++)
{
size_t index = (y * buildingsFrames.size() * 16) + (n * 16 + x);
buildingBuffer.at(index) = buildingsFrames.at(n).at(32 - y - 1).at(x);
}
}
}
SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
buildingsFrames.size() * 16, 32);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Buildings: " +
std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(
tmp, nullptr, buildingBuffer.data(),
buildingsFrames.size() * 16 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Buildings: " + std::string(SDL_GetError()));
}
this->m_buildingTextures.push_back(tmp);
}
// Units
std::vector<std::string> unitFactions({"red", "blue", "green", "yellow", "purple"});
std::vector<std::string> units(
{"infantery", "mechanized_infantery", "recon", "medium_tank", "heavy_tank", "neo_tank",
"apc", "anti_air_tank", "artillery", "rocket_artillery", "anti_air_missile_launcher",
"fighter", "bomber", "battle_helicopter", "transport_helicopter", "battleship", "cruiser",
"lander", "submarine"});
std::vector<std::string> unitStates({"idle", "unavailable"});
std::vector<std::string> unitMovementStates({"left", "right", "down", "up"});
// every factions sub data set
for (size_t factionIdx = 0; factionIdx < unitFactions.size(); factionIdx++)
{
const std::string& faction = unitFactions.at(factionIdx);
// Create entry for units for in a faction
m_unitTextures.emplace_back();
// every unit sub data set
for (size_t unitIdx = 0; unitIdx < units.size(); unitIdx++)
{
const std::string& unit = units.at(unitIdx);
// Create entry for states for a unit
m_unitTextures.at(factionIdx).emplace_back();
// every state sub data set
for (const auto& unitState : unitStates)
{
HighFive::DataSet unitsDs =
file.getDataSet("units/" + faction + "/" + unit + "/" + unitState);
std::vector<std::vector<std::vector<uint32_t>>> unitFrames;
unitsDs.read(unitFrames);
std::vector<uint32_t> unitBuffer(16 * 16 * unitFrames.size(), 0);
for (size_t n = 0; n < unitFrames.size(); n++)
{
for (size_t y = 0; y < 16; y++)
{
for (size_t x = 0; x < 16; x++)
{
size_t index = (y * unitFrames.size() * 16) + (n * 16 + x);
unitBuffer.at(index) = unitFrames.at(n).at(16 - y - 1).at(x);
}
}
}
SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
unitFrames.size() * 16, 16);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Units: " +
std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(
tmp, nullptr, unitBuffer.data(),
unitFrames.size() * 16 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Units: " +
std::string(SDL_GetError()));
}
m_unitTextures.at(factionIdx).at(unitIdx).emplace_back(tmp, unitFrames.size());
}
// every movement state sub data set
for (const auto& movementState : unitMovementStates)
{
HighFive::DataSet unitsDs =
file.getDataSet("units/" + faction + "/" + unit + "/movement/" + movementState);
std::vector<std::vector<std::vector<uint32_t>>> unitFrames;
unitsDs.read(unitFrames);
std::vector<uint32_t> unitBuffer(24 * 24 * unitFrames.size(), 0);
for (size_t n = 0; n < unitFrames.size(); n++)
{
for (size_t y = 0; y < 24; y++)
{
for (size_t x = 0; x < 24; x++)
{
size_t index = (y * unitFrames.size() * 24) + (n * 24 + x);
unitBuffer.at(index) = unitFrames.at(n).at(24 - y - 1).at(x);
}
}
}
SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
unitFrames.size() * 24, 24);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Units: " +
std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(
tmp, nullptr, unitBuffer.data(),
unitFrames.size() * 24 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Units: " +
std::string(SDL_GetError()));
}
m_unitTextures.at(factionIdx).at(unitIdx).emplace_back(tmp, unitFrames.size());
}
}
}
this->m_unitWidth = 16;
this->m_unitHeight = 16;
this->m_unitMovingWidth = 24;
this->m_unitMovingHeight = 24;
// Effects
std::vector<std::string> effects(
{"land_explosion", "air_explosion", "naval_explosion", "submarine_hide",
"submarine_appear"});
// Every effect sub data set
for (size_t effectIdx = 0; effectIdx < effects.size(); effectIdx++)
{
HighFive::DataSet effectDs = file.getDataSet("effects/" + effects[effectIdx]);
std::vector<std::vector<std::vector<uint32_t>>> effectFrames;
effectDs.read(effectFrames);
std::vector<uint32_t> effectBuffer(32 * 32 * effectFrames.size(), 0);
// every animation frame
for (size_t n = 0; n < effectFrames.size(); n++)
{
for (size_t y = 0; y < 32; y++)
{
for (size_t x = 0; x < 32; x++)
{
size_t index = (y * effectFrames.size() * 32) + (n * 32 + x);
effectBuffer.at(index) = effectFrames.at(n).at(32 - y - 1).at(x);
}
}
}
SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC,
effectFrames.size() * 32, 32);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Effects: " + std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(
tmp, nullptr, effectBuffer.data(), effectFrames.size() * 32 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Tiles: " + std::string(SDL_GetError()));
}
m_effectTextures.emplace_back(tmp, effectFrames.size());
}
this->m_effectWidth = 32;
this->m_effectHeight = 32;
// Numbers
HighFive::DataSet numberDs = file.getDataSet("/misc/numbers");
std::vector<std::vector<uint32_t>> numberFrames;
numberDs.read(numberFrames);
std::vector<uint32_t> numberBuffer(8 * 80, 0);
for (int y = 0; y < 8; y++)
{
for (int x = 0; x < 80; x++)
{
int index = (y * 80) + x;
numberBuffer.at(index) = numberFrames.at(8 - y - 1).at(x);
}
}
SDL_Texture* tmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, 80, 8);
SDL_SetTextureBlendMode(tmp, SDL_BLENDMODE_BLEND);
if (tmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Numbers: " + std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(tmp, nullptr, numberBuffer.data(), 80 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Numbers: " + std::string(SDL_GetError()));
}
this->m_numberTextures = tmp;
this->m_numberWidth = 8;
this->m_numberHeight = 8;
// Bullet
HighFive::DataSet bulletDs = file.getDataSet("/misc/bullet");
std::vector<std::vector<uint32_t>> bulletFrames;
bulletDs.read(bulletFrames);
std::vector<uint32_t> bulletBuffer(8 * 8, 0);
// every animation frame
for (size_t y = 0; y < 8; y++)
{
for (size_t x = 0; x < 8; x++)
{
size_t index = (y * 8) + x;
numberBuffer.at(index) = bulletFrames.at(8 - y - 1).at(x);
}
}
SDL_Texture* bulletTmp = SDL_CreateTexture(
engine.renderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, 8, 8);
SDL_SetTextureBlendMode(bulletTmp, SDL_BLENDMODE_BLEND);
if (bulletTmp == nullptr)
{
throw std::runtime_error(
"Fehler beim Erstellen der Textur für die Bullets: " + std::string(SDL_GetError()));
}
if (SDL_UpdateTexture(bulletTmp, nullptr, numberBuffer.data(), 8 * sizeof(int32_t)) != 0)
{
throw std::runtime_error(
"Fehler beim updaten der Textur für die Bullets: " + std::string(SDL_GetError()));
}
this->m_bulletTexture = bulletTmp;
this->m_bulletWidth = 8;
this->m_bulletHeight = 8;
}
// Tiles
int Spritesheet::getTileWidth()
{
return m_tileWidth;
}
int Spritesheet::getTileHeight()
{
return m_tileHeight;
}
std::vector<std::pair<SDL_Texture*, int>>& Spritesheet::getTileTextures()
{
return m_tileTextures;
}
// Buildings
int Spritesheet::getBuildingWidth()
{
return this->m_buildingWidth;
}
int Spritesheet::getBuildingHeight()
{
return this->m_buildingHeight;
}
std::vector<SDL_Texture*>& Spritesheet::getBuildingTextures()
{
return m_buildingTextures;
}
// Units
int Spritesheet::getUnitWidth()
{
return this->m_unitWidth;
}
int Spritesheet::getUnitHeight()
{
return this->m_unitHeight;
}
int Spritesheet::getUnitMovingWidth()
{
return this->m_unitMovingWidth;
}
int Spritesheet::getUnitMovingHeight()
{
return this->m_unitMovingHeight;
}
std::vector<std::vector<std::vector<std::pair<SDL_Texture*, int>>>>& Spritesheet::getUnitTextures()
{
return this->m_unitTextures;
}
// Effects
int Spritesheet::getEffectWidth()
{
return this->m_effectWidth;
}
int Spritesheet::getEffectHeight()
{
return this->m_effectHeight;
}
std::vector<std::pair<SDL_Texture*, int>>& Spritesheet::getEffectTextures()
{
return this->m_effectTextures;
}
// Numbers
int Spritesheet::getNumberWidth()
{
return this->m_numberWidth;
}
int Spritesheet::getNumberHeight()
{
return this->m_numberHeight;
}
SDL_Texture* Spritesheet::getNumberTexture()
{
return this->m_numberTextures;
}
// Bullet
SDL_Texture* Spritesheet::getBulletTexture()
{
return this->m_bulletTexture;
}
int Spritesheet::getBulletWidth()
{
return this->m_bulletWidth;
}
int Spritesheet::getBulletHeight()
{
return this->m_bulletHeight;
}
Spritesheet::~Spritesheet()
{
for (std::pair<SDL_Texture*, int> tileTexture : m_tileTextures)
{
SDL_DestroyTexture(tileTexture.first);
}
for (SDL_Texture* buildingTexture : m_buildingTextures)
{
SDL_DestroyTexture(buildingTexture);
}
for (const std::vector<std::vector<std::pair<SDL_Texture*, int>>>& faction : m_unitTextures)
{
for (const std::vector<std::pair<SDL_Texture*, int>>& unit : faction)
{
for (std::pair<SDL_Texture*, int> state : unit)
{
SDL_DestroyTexture(state.first);
}
}
}
for (auto& [texture, i] : m_effectTextures)
{
SDL_DestroyTexture(texture);
}
SDL_DestroyTexture(m_numberTextures);
SDL_DestroyTexture(m_bulletTexture);
}
} // namespace advanced_wars