X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fmap%2FMap.cpp;h=3f05962a43b2e55db519f84565b362b16d748cc0;hb=2ccc2369d32fb680a3047519d79c17de34c4e10a;hp=450c00463ab7d3aa28ae90fcafd067f3620d833f;hpb=59c4aea0762cbc5f1bf74c5b1b35629408fb92af;p=l2e.git diff --git a/src/map/Map.cpp b/src/map/Map.cpp index 450c004..3f05962 100644 --- a/src/map/Map.cpp +++ b/src/map/Map.cpp @@ -8,30 +8,175 @@ #include "Map.h" #include "Area.h" +#include "Tile.h" +#include "Trigger.h" #include "../graphics/Sprite.h" +#include "../loader/TypeDescription.h" +#include "../sdl/utility.h" + +#include using geometry::Vector; +using loader::FieldDescription; +using loader::TypeDescription; namespace map { Map::Map() : tileset(0) +, battlebg(0) , areas(0) , numAreas(0) +, triggers(0) +, numTriggers(0) +, entities(0) +, numEntities(0) , width(0) { } +Area *Map::AreaAt(const Vector &offset) { + if (numAreas > 0) { + Vector coords(TileCoordinates(offset)); + Vector areaOffset(coords / areas[0].Size()); + int areaIndex(areaOffset.Index(width)); + if (areaIndex < numAreas) { + return areas + areaIndex; + } + } + return 0; +} + +const Area *Map::AreaAt(const Vector &offset) const { + if (numAreas > 0) { + Vector coords(TileCoordinates(offset)); + Vector areaOffset(coords / areas[0].Size()); + int areaIndex(areaOffset.Index(width)); + if (areaIndex < numAreas) { + return areas + areaIndex; + } + } + return 0; +} + +Tile *Map::TileAt(const Vector &offset) { + Area *area(AreaAt(offset)); + if (area) { + Vector tileOffset(TileCoordinates(offset) % area->Size()); + return area->TileAt(tileOffset); + } else { + return 0; + } +} + +const Tile *Map::TileAt(const Vector &offset) const { + const Area *area(AreaAt(offset)); + if (area) { + Vector tileOffset(TileCoordinates(offset) % area->Size()); + return area->TileAt(tileOffset); + } else { + return 0; + } +} + +Trigger *Map::TriggerAt(const geometry::Vector &offset) { + // TODO: add support for multiple triggers on a tile? + Vector coords(TileCoordinates(offset)); + for (Trigger *i(triggers); i != triggers + numTriggers; ++i) { + if (i->TilePosition() == coords) { + return i; + } + } + return 0; +} + +SDL_Surface *Map::BattleBackgroundAt(const geometry::Vector &position) { + Tile *tile(TileAt(position)); + if (tile && tile->BattleBackground()) { + return tile->BattleBackground(); + } + Area *area(AreaAt(position)); + if (area && area->BattleBackground()) { + return area->BattleBackground(); + } + return battlebg; +} + +Vector Map::TileCoordinates(const Vector &position) const { + return position / tileset->Size(); +} + + void Map::Render(SDL_Surface *dest, const Vector &inOffset) const { // TODO: skip invisible areas for (int i(0); i < numAreas; ++i) { const Area &area(areas[i]); - Vector offset( - inOffset.X() + (i % width) * area.Width() * tileset->Width(), - inOffset.Y() + (i / width) * area.Height() * tileset->Height()); + Vector offset(inOffset + Vector::FromIndex(i, width) * area.Size() * tileset->Size()); area.Render(dest, tileset, offset); } } +void Map::RenderDebug(SDL_Surface *dest, const Vector &inOffset) const { + // TODO: skip invisible areas + for (int i(0); i < numAreas; ++i) { + const Area &area(areas[i]); + Vector offset(inOffset + Vector::FromIndex(i, width) * area.Size() * tileset->Size()); + area.RenderDebug(dest, tileset, offset); + } + for (int i(0); i < numTriggers; ++i) { + Vector offset((triggers[i].TilePosition() * tileset->Size()) + inOffset); + switch (triggers[i].GetType()) { + case Trigger::TYPE_NORTH: + sdl::HorizontalLine(dest, offset + (tileset->Size() / 4), tileset->Width() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF)); + break; + case Trigger::TYPE_EAST: + sdl::VerticalLine(dest, offset + Vector(tileset->Width() * 3 / 4, tileset->Height() / 4), tileset->Height() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF)); + break; + case Trigger::TYPE_SOUTH: + sdl::HorizontalLine(dest, offset + Vector(tileset->Width() / 4, tileset->Height() * 3 / 4), tileset->Width() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF)); + break; + case Trigger::TYPE_WEST: + sdl::VerticalLine(dest, offset + (tileset->Size() / 4), tileset->Width() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF)); + break; + case Trigger::TYPE_CONTACT: { + SDL_Rect destRect; + destRect.x = offset.X() + (tileset->Width() / 4); + destRect.y = offset.Y() + (tileset->Height() / 4); + destRect.w = tileset->Width() / 2; + destRect.h = tileset->Height() / 2; + SDL_FillRect(dest, &destRect, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF)); + } + break; + } + } +} + + +void Map::CreateTypeDescription() { + Map m; + + int areaId(TypeDescription::GetTypeId("Area")); + int entityId(TypeDescription::GetTypeId("Entity")); + int imageId(TypeDescription::GetTypeId("Image")); + int numberId(TypeDescription::GetTypeId("Number")); + int spriteId(TypeDescription::GetTypeId("Sprite")); + int triggerId(TypeDescription::GetTypeId("Trigger")); + + TypeDescription &td(TypeDescription::CreateOrGet("Map")); + td.SetConstructor(&Construct); + td.SetSize(sizeof(Map)); + + td.AddField("tileset", FieldDescription(((char *)&m.tileset) - ((char *)&m), spriteId).SetReferenced()); + td.AddField("battlebg", FieldDescription(((char *)&m.battlebg) - ((char *)&m), imageId).SetReferenced()); + td.AddField("areas", FieldDescription(((char *)&m.areas) - ((char *)&m), areaId).SetReferenced().SetAggregate()); + td.AddField("triggers", FieldDescription(((char *)&m.triggers) - ((char *)&m), triggerId).SetReferenced().SetAggregate()); + td.AddField("entities", FieldDescription(((char *)&m.entities) - ((char *)&m), entityId).SetReferenced().SetAggregate()); + td.AddField("width", FieldDescription(((char *)&m.width) - ((char *)&m), numberId)); +} + +void Map::Construct(void *data) { + new (data) Map; +} + }