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