]> git.localhorst.tv Git - l2e.git/blob - src/map/Map.cpp
823847c92213eae625b86469ded3b80ba38a5084
[l2e.git] / src / map / Map.cpp
1 #include "Map.h"
2
3 #include "Area.h"
4 #include "Tile.h"
5 #include "Trigger.h"
6 #include "../graphics/Sprite.h"
7 #include "../loader/Interpreter.h"
8 #include "../loader/TypeDescription.h"
9 #include "../sdl/utility.h"
10
11 #include <stdexcept>
12
13 using math::Vector;
14 using graphics::Sprite;
15 using loader::FieldDescription;
16 using loader::Interpreter;
17 using loader::TypeDescription;
18
19 namespace map {
20
21 Map::Map()
22 : tileset(0)
23 , battlebg(0)
24 , areas(0)
25 , numAreas(0)
26 , triggers(0)
27 , numTriggers(0)
28 , entities(0)
29 , numEntities(0)
30 , width(0) {
31
32 }
33
34
35 Area *Map::AreaAt(const Vector<int> &offset) {
36         if (numAreas > 0) {
37                 Vector<int> coords(TileCoordinates(offset));
38                 Vector<int> areaOffset(coords / areas[0].Size());
39                 int areaIndex(areaOffset.Index(width));
40                 if (areaIndex < numAreas) {
41                         return areas + areaIndex;
42                 }
43         }
44         return 0;
45 }
46
47 const Area *Map::AreaAt(const Vector<int> &offset) const {
48         if (numAreas > 0) {
49                 Vector<int> coords(TileCoordinates(offset));
50                 Vector<int> areaOffset(coords / areas[0].Size());
51                 int areaIndex(areaOffset.Index(width));
52                 if (areaIndex < numAreas) {
53                         return areas + areaIndex;
54                 }
55         }
56         return 0;
57 }
58
59 Tile *Map::TileAt(const Vector<int> &offset) {
60         Area *area(AreaAt(offset));
61         if (area) {
62                 Vector<int> tileOffset(TileCoordinates(offset) % area->Size());
63                 return area->TileAt(tileOffset);
64         } else {
65                 return 0;
66         }
67 }
68
69 const Tile *Map::TileAt(const Vector<int> &offset) const {
70         const Area *area(AreaAt(offset));
71         if (area) {
72                 Vector<int> tileOffset(TileCoordinates(offset) % area->Size());
73                 return area->TileAt(tileOffset);
74         } else {
75                 return 0;
76         }
77 }
78
79 Trigger *Map::TriggerAt(const math::Vector<int> &offset) {
80         // TODO: add support for multiple triggers on a tile?
81         Vector<int> coords(TileCoordinates(offset));
82         for (Trigger *i(triggers); i != triggers + numTriggers; ++i) {
83                 if (i->TilePosition() == coords) {
84                         return i;
85                 }
86         }
87         return 0;
88 }
89
90 SDL_Surface *Map::BattleBackgroundAt(const math::Vector<int> &position) {
91         Tile *tile(TileAt(position));
92         if (tile && tile->BattleBackground()) {
93                 return tile->BattleBackground();
94         }
95         Area *area(AreaAt(position));
96         if (area && area->BattleBackground()) {
97                 return area->BattleBackground();
98         }
99         return battlebg;
100 }
101
102 Vector<int> Map::TileCoordinates(const Vector<int> &position) const {
103         return position / tileset->Size();
104 }
105
106
107 void Map::Render(SDL_Surface *dest, const Vector<int> &inOffset) const {
108         // TODO: skip invisible areas
109         for (int i(0); i < numAreas; ++i) {
110                 const Area &area(areas[i]);
111                 Vector<int> offset(inOffset + Vector<int>::FromIndex(i, width) * area.Size() * tileset->Size());
112                 area.Render(dest, tileset, offset);
113         }
114 }
115
116 void Map::RenderDebug(SDL_Surface *dest, const Vector<int> &inOffset) const {
117         // TODO: skip invisible areas
118         for (int i(0); i < numAreas; ++i) {
119                 const Area &area(areas[i]);
120                 Vector<int> offset(inOffset + Vector<int>::FromIndex(i, width) * area.Size() * tileset->Size());
121                 area.RenderDebug(dest, tileset, offset);
122         }
123         for (int i(0); i < numTriggers; ++i) {
124                 Vector<int> offset((triggers[i].TilePosition() * tileset->Size()) + inOffset);
125                 switch (triggers[i].GetType()) {
126                         case Trigger::TYPE_NORTH:
127                                 sdl::HorizontalLine(dest, offset + (tileset->Size() / 4), tileset->Width() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF));
128                                 break;
129                         case Trigger::TYPE_EAST:
130                                 sdl::VerticalLine(dest, offset + Vector<int>(tileset->Width() * 3 / 4, tileset->Height() / 4), tileset->Height() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF));
131                                 break;
132                         case Trigger::TYPE_SOUTH:
133                                 sdl::HorizontalLine(dest, offset + Vector<int>(tileset->Width() / 4, tileset->Height() * 3 / 4), tileset->Width() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF));
134                                 break;
135                         case Trigger::TYPE_WEST:
136                                 sdl::VerticalLine(dest, offset + (tileset->Size() / 4), tileset->Width() / 2, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF));
137                                 break;
138                         case Trigger::TYPE_CONTACT: {
139                                         SDL_Rect destRect;
140                                         destRect.x = offset.X() + (tileset->Width() / 4);
141                                         destRect.y = offset.Y() + (tileset->Height() / 4);
142                                         destRect.w = tileset->Width() / 2;
143                                         destRect.h = tileset->Height() / 2;
144                                         SDL_FillRect(dest, &destRect, SDL_MapRGB(dest->format, 0x00, 0xFF, 0xFF));
145                                 }
146                                 break;
147                 }
148         }
149 }
150
151
152 void Map::CreateTypeDescription() {
153         Map m;
154
155         TypeDescription &td(TypeDescription::Create(TYPE_ID, "Map"));
156         td.SetConstructor(&Construct);
157         td.SetSize(sizeof(Map));
158
159         td.AddField("tileset", FieldDescription(((char *)&m.tileset) - ((char *)&m), Sprite::TYPE_ID).SetReferenced());
160         td.AddField("battlebg", FieldDescription(((char *)&m.battlebg) - ((char *)&m), Interpreter::IMAGE_ID).SetReferenced());
161         td.AddField("areas", FieldDescription(((char *)&m.areas) - ((char *)&m), Area::TYPE_ID).SetReferenced().SetAggregate());
162         td.AddField("triggers", FieldDescription(((char *)&m.triggers) - ((char *)&m), Trigger::TYPE_ID).SetReferenced().SetAggregate());
163         td.AddField("entities", FieldDescription(((char *)&m.entities) - ((char *)&m), Entity::TYPE_ID).SetReferenced().SetAggregate());
164         td.AddField("width", FieldDescription(((char *)&m.width) - ((char *)&m), Interpreter::NUMBER_ID));
165 }
166
167 void Map::Construct(void *data) {
168         new (data) Map;
169 }
170
171 }