Files
Tower-Defense2/src/main.cpp
2025-07-16 13:38:02 +02:00

212 lines
6.1 KiB
C++

#include <iostream>
#include <sp/common/DataBuffer.h>
#include <sp/extensions/Compress.h>
#include <td/input/Display.h>
#include <td/game/World.h>
#include <td/protocol/packet/Packets.h>
#include <td/render/renderer/WorldRenderer.h>
namespace td {
namespace game {
sp::DataBuffer& operator>>(sp::DataBuffer& buffer, game::TilePtr& tile) {
game::TileType tileType;
buffer >> tileType;
switch (tileType) {
case game::TileType::Tower: {
auto tilePtr = std::make_shared<game::TowerTile>();
buffer >> tilePtr->color_palette_ref >> tilePtr->team_owner;
tile = tilePtr;
break;
}
case game::TileType::Walk: {
auto tilePtr = std::make_shared<game::WalkableTile>();
buffer >> tilePtr->direction;
tile = tilePtr;
break;
}
case game::TileType::Decoration: {
auto tilePtr = std::make_shared<game::DecorationTile>();
buffer >> tilePtr->color_palette_ref;
tile = tilePtr;
break;
}
default:
break;
}
return buffer;
}
} // namespace game
} // namespace td
namespace sp {
namespace details {
template <>
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::WorldHeader& a_Header) {
a_Buffer >> a_Header.m_TowerPlacePalette >> a_Header.m_WalkablePalette;
std::uint16_t decoPaletteSize;
a_Buffer >> decoPaletteSize;
std::size_t decoPalletteSizeByte = decoPaletteSize * sizeof(td::Color);
a_Header.m_DecorationPalette.resize(decoPaletteSize);
memcpy(reinterpret_cast<std::uint8_t*>(a_Header.m_DecorationPalette.data()), a_Buffer.data() + a_Buffer.GetReadOffset(),
decoPalletteSizeByte);
a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() + decoPalletteSizeByte);
a_Buffer >> a_Header.m_Background;
td::utils::shape::Rectangle redCastle, blueCastle;
a_Buffer >> a_Header.m_RedSpawn >> redCastle;
a_Buffer >> a_Header.m_BlueSpawn >> blueCastle;
a_Header.m_RedCastle.SetShape(redCastle);
a_Header.m_BlueCastle.SetShape(blueCastle);
std::uint64_t tilePaletteSize;
a_Buffer >> tilePaletteSize;
a_Header.m_TilePalette.reserve(tilePaletteSize);
for (std::uint64_t tileNumber = 0; tileNumber < tilePaletteSize; tileNumber++) {
td::game::TilePtr tile;
a_Buffer >> tile;
a_Header.m_TilePalette.push_back(tile);
}
a_Buffer >> a_Header.m_SpawnColorPalette;
}
typedef std::vector<uint64_t> ChunkPackedData;
const int BITS_IN_BYTE = 8;
const int BITS_IN_LONG = BITS_IN_BYTE * sizeof(std::uint64_t);
static unsigned int countBits(unsigned int number) {
// log function in base 2
// take only integer part
return static_cast<unsigned int>(std::log2(number) + 1);
}
template <>
void ReadMessage(DataBuffer& a_Buffer, td::protocol::pdata::WorldData& a_WorldData) {
std::uint64_t chunkCount;
a_Buffer >> chunkCount;
for (std::uint64_t chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) {
td::game::ChunkPtr chunk = std::make_shared<td::game::Chunk>();
td::game::ChunkCoord chunkCoords;
a_Buffer >> chunkCoords.x >> chunkCoords.y;
std::uint64_t chunkPaletteSize;
// std::reverse(reinterpret_cast<std::uint8_t*>(&chunkPaletteSize), reinterpret_cast<std::uint8_t*>(&chunkPaletteSize) + 4);
a_Buffer >> chunkPaletteSize;
td::game::ChunkPalette chunkPalette(chunkPaletteSize);
memcpy(reinterpret_cast<void*>(chunkPalette.data()), a_Buffer.data() + a_Buffer.GetReadOffset(),
chunkPaletteSize * sizeof(td::game::ChunkPalette::value_type));
a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() + chunkPaletteSize * sizeof(td::game::ChunkPalette::value_type));
chunk->palette = chunkPalette;
std::uint8_t bitsPerTile = countBits(chunkPaletteSize);
// A bitmask that contains bitsPerTile set bits
td::game::Chunk::ChunkData::value_type individualValueMask = ((1 << bitsPerTile) - 1);
ChunkPackedData chunkData(td::game::Chunk::ChunkSize / (BITS_IN_BYTE * sizeof(ChunkPackedData::value_type) / bitsPerTile), 0);
memcpy(reinterpret_cast<void*>(chunkData.data()), a_Buffer.data() + a_Buffer.GetReadOffset(),
chunkData.size() * sizeof(ChunkPackedData::value_type));
a_Buffer.SetReadOffset(a_Buffer.GetReadOffset() + chunkData.size() * sizeof(ChunkPackedData::value_type));
for (unsigned int tileNumber = 0; tileNumber < td::game::Chunk::ChunkSize; tileNumber++) {
std::size_t startLong = (tileNumber * bitsPerTile) / BITS_IN_LONG;
std::size_t startOffset = (tileNumber * bitsPerTile) % BITS_IN_LONG;
std::size_t endLong = ((tileNumber + 1) * bitsPerTile - 1) / BITS_IN_LONG;
td::game::Chunk::ChunkData::value_type value;
if (startLong == endLong) {
value = (chunkData[startLong] >> startOffset);
} else {
int endOffset = BITS_IN_LONG - startOffset;
value = (chunkData[startLong] >> startOffset | chunkData[endLong] << endOffset);
}
value &= individualValueMask;
chunk->tiles[tileNumber] = value;
}
a_WorldData.m_Chunks.insert({chunkCoords, chunk});
}
}
} // namespace details
} // namespace sp
class WorldApply : public td::protocol::PacketHandler {
private:
td::game::World& m_World;
public:
WorldApply(td::game::World& a_World) : m_World(a_World) {}
void Handle(const td::protocol::pdata::WorldHeader& a_Header) override {
m_World.LoadMap(a_Header);
}
void Handle(const td::protocol::pdata::WorldData& a_Data) override {
m_World.LoadMap(a_Data);
}
};
int main(int argc, char** argv) {
sp::DataBuffer buffer;
buffer.ReadFile("test/tdmap.tdmap2");
sp::DataBuffer buffer1 = sp::zlib::Decompress(buffer, 84);
buffer.SetReadOffset(buffer.GetReadOffset() + 83);
sp::DataBuffer buffer2 = sp::zlib::Decompress(buffer, 511);
td::protocol::packets::WorldHeaderPacket header;
header.Read(buffer1);
td::protocol::packets::WorldDataPacket data;
data.Read(buffer2);
td::game::World w;
WorldApply wa(w);
td::protocol::PacketDispatcher d;
d.RegisterHandler(td::protocol::PacketID::WorldData, &wa);
d.RegisterHandler(td::protocol::PacketID::WorldHeader, &wa);
d.Dispatch(header);
d.Dispatch(data);
td::Display display(1920, 1080, "Tower-Defense 2");
td::render::Camera cam;
td::render::RenderPipeline renderer;
renderer.AddRenderer<td::render::WorldRenderer>(cam, w);
cam.SetCamPos({77, 25, 13});
cam.UpdatePerspective(display.GetAspectRatio());
while (!display.IsCloseRequested()) {
display.PollEvents();
renderer.Render();
display.Update();
}
return 0;
}