summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--cmake/FindMxml.cmake31
-rw-r--r--entities/checkpoint.xml5
-rw-r--r--maps/embarass.xml (renamed from maps/embarass.txt)9
-rw-r--r--maps/second.xml (renamed from maps/second.txt)15
-rw-r--r--src/components.cpp12
-rw-r--r--src/components.h4
-rw-r--r--src/entity.cpp3
-rw-r--r--src/entity.h1
-rw-r--r--src/entityfactory.cpp101
-rw-r--r--src/entityfactory.h15
-rw-r--r--src/game.cpp34
-rw-r--r--src/game.h6
-rw-r--r--src/map.cpp158
-rw-r--r--src/map.h31
-rw-r--r--src/renderer.cpp2
-rw-r--r--src/renderer.h2
17 files changed, 345 insertions, 92 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b28397..e86cd95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -27,6 +27,7 @@ find_package(GLEW REQUIRED)
27find_package(GLFW REQUIRED) 27find_package(GLFW REQUIRED)
28find_package(portaudio REQUIRED) 28find_package(portaudio REQUIRED)
29find_package(libsndfile REQUIRED) 29find_package(libsndfile REQUIRED)
30find_package(libxml2 REQUIRED)
30 31
31set(ALL_LIBS 32set(ALL_LIBS
32 ${OPENGL_LIBRARY} 33 ${OPENGL_LIBRARY}
@@ -34,10 +35,15 @@ set(ALL_LIBS
34 ${GLFW_LIBRARY} 35 ${GLFW_LIBRARY}
35 ${PORTAUDIO_LIBRARIES} 36 ${PORTAUDIO_LIBRARIES}
36 ${LIBSNDFILE_LIBRARY} 37 ${LIBSNDFILE_LIBRARY}
38 ${LIBXML2_LIBRARIES}
39)
40
41include_directories(
42 ${LIBXML2_INCLUDE_DIR}
37) 43)
38 44
39# include_directories(${SDL2_INCLUDE_DIR}) 45# include_directories(${SDL2_INCLUDE_DIR})
40set(CMAKE_BUILD_TYPE Debug) 46set(CMAKE_BUILD_TYPE Debug)
41add_executable(Aromatherapy src/main.cpp src/map.cpp src/renderer.cpp src/entity.cpp src/components.cpp src/game.cpp src/muxer.cpp) 47add_executable(Aromatherapy src/main.cpp src/map.cpp src/renderer.cpp src/entity.cpp src/components.cpp src/game.cpp src/muxer.cpp src/entityfactory.cpp)
42target_link_libraries(Aromatherapy ${ALL_LIBS}) 48target_link_libraries(Aromatherapy ${ALL_LIBS})
43install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR}) 49install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR})
diff --git a/cmake/FindMxml.cmake b/cmake/FindMxml.cmake new file mode 100644 index 0000000..49daa4f --- /dev/null +++ b/cmake/FindMxml.cmake
@@ -0,0 +1,31 @@
1# - Try to find Motif (or lesstif)
2# Once done this will define:
3# MXML_FOUND - system has MXML
4# MXML_INCLUDE_DIR - incude paths to use Motif
5# MXML_LIBRARIES - Link these to use Motif
6
7SET(MXML_FOUND 0)
8
9IF(UNIX)
10 FIND_PATH(MXML_INCLUDE_DIR
11 mxml.h
12 /usr/include
13 )
14
15 FIND_LIBRARY(MXML_LIBRARIES
16 mxml
17 /usr/lib
18 )
19
20ENDIF(UNIX)
21
22# handle the QUIETLY and REQUIRED arguments and set MXML_FOUND to TRUE if
23# all listed variables are TRUE
24INCLUDE(FindPackageHandleStandardArgs)
25FIND_PACKAGE_HANDLE_STANDARD_ARGS(MXML DEFAULT_MSG MXML_LIBRARIES MXML_INCLUDE_DIR)
26
27
28MARK_AS_ADVANCED(
29 MXML_INCLUDE_DIR
30 MXML_LIBRARIES
31) \ No newline at end of file
diff --git a/entities/checkpoint.xml b/entities/checkpoint.xml new file mode 100644 index 0000000..5b081ed --- /dev/null +++ b/entities/checkpoint.xml
@@ -0,0 +1,5 @@
1<entity-def>
2 <sprite>../res/keyring.png</sprite>
3 <action>save</action>
4 <size>8,11</size>
5</entity-def> \ No newline at end of file
diff --git a/maps/embarass.txt b/maps/embarass.xml index 0407733..950854c 100644 --- a/maps/embarass.txt +++ b/maps/embarass.xml
@@ -1,4 +1,6 @@
10,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,20,0,0,0,0,0,0,0,18,9,8,10,8,11,8,10,10,8,11,8,9,10,21,0, 1<map-def>
2 <name>Everything Is Embarrassing</name>
3 <environment>0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,20,0,0,0,0,0,0,0,18,9,8,10,8,11,8,10,10,8,11,8,9,10,21,0,
20,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,8,8,17,0,0,0,0,0,0,0,0,0,0,0,0,0,22,21, 40,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,8,8,17,0,0,0,0,0,0,0,0,0,0,0,0,0,22,21,
30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,8,8,8,8,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12, 50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,8,8,8,8,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,
40,19,-1,-1,-1,0,0,0,0,0,0,0,0,18,8,8,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12, 60,19,-1,-1,-1,0,0,0,0,0,0,0,0,18,8,8,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,
@@ -21,5 +23,6 @@
210,0,0,0,0,0,0,0,0,0,24,4,2,1,3,3,1,4,2,2,1,1,1,3,1,2,4,1,3,26,0,0,0,0,0,0,0,0,0,0, 230,0,0,0,0,0,0,0,0,0,24,4,2,1,3,3,1,4,2,2,1,1,1,3,1,2,4,1,3,26,0,0,0,0,0,0,0,0,0,0,
220,0,0,0,24,3,1,2,1,1,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,27,1,3,2,26,0,0,0,0,0,0, 240,0,0,0,24,3,1,2,1,1,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,27,1,3,2,26,0,0,0,0,0,0,
231,2,3,1,25,0,0,0,0,0,20,0,0,0,0,0,0,19,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,27,1,2,2,4,3,1, 251,2,3,1,25,0,0,0,0,0,20,0,0,0,0,0,0,19,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,27,1,2,2,4,3,1,
240,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0, 260,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,</environment>
25Everything Is Embarrassing \ No newline at end of file 27 <leftmap>second</leftmap>
28</map-def>
diff --git a/maps/second.txt b/maps/second.xml index de5ec83..b6c2419 100644 --- a/maps/second.txt +++ b/maps/second.xml
@@ -1,4 +1,6 @@
10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1<map-def>
2 <name>It's A Trap!</name>
3 <environment>0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0, 40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,
30,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0, 50,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,
40,0,0,0,0,0,0,19,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 60,0,0,0,0,0,0,19,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -21,5 +23,12 @@
210,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 230,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
220,0,0,27,2,2,3,3,3,4,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 240,0,0,27,2,2,3,3,3,4,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
230,20,0,0,0,0,0,19,0,0,27,1,1,1,2,2,2,26,0,0,0,0,0,0,0,0,0,0,24,4,2,2,1,3,2,2,1,2,2,3, 250,20,0,0,0,0,0,19,0,0,27,1,1,1,2,2,2,26,0,0,0,0,0,0,0,0,0,0,24,4,2,2,1,3,2,2,1,2,2,3,
240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,42,42,42,42,42,42,42,42,42,42,12,0,0,0,0,0,19,0,0,0,0,0, 260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,42,42,42,42,42,42,42,42,42,42,12,0,0,0,0,0,19,0,0,0,0,0,</environment>
25It's A Trap! \ No newline at end of file 27 <entities>
28 <entity>
29 <entity-type>checkpoint</entity-type>
30 <entity-position>257,160</entity-position>
31 </entity>
32 </entities>
33 <rightmap>embarass</rightmap>
34</map-def>
diff --git a/src/components.cpp b/src/components.cpp index 26aa5d2..ba4fe72 100644 --- a/src/components.cpp +++ b/src/components.cpp
@@ -309,7 +309,7 @@ MapRenderComponent::MapRenderComponent(const Map& map)
309 309
310 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++) 310 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++)
311 { 311 {
312 int tile = map.mapdata()[i]; 312 int tile = map.getMapdata()[i];
313 int x = i % MAP_WIDTH; 313 int x = i % MAP_WIDTH;
314 int y = i / MAP_WIDTH; 314 int y = i / MAP_WIDTH;
315 Rectangle dst {x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT}; 315 Rectangle dst {x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT};
@@ -322,7 +322,7 @@ MapRenderComponent::MapRenderComponent(const Map& map)
322 } 322 }
323 323
324 Texture font("../res/font.bmp"); 324 Texture font("../res/font.bmp");
325 const char* map_name = map.title(); 325 const char* map_name = map.getTitle();
326 int start_x = (40/2) - (strlen(map_name)/2); 326 int start_x = (40/2) - (strlen(map_name)/2);
327 for (size_t i=0; i<strlen(map_name); i++) 327 for (size_t i=0; i<strlen(map_name); i++)
328 { 328 {
@@ -348,7 +348,7 @@ MapCollisionComponent::MapCollisionComponent(const Map& map) : map(map)
348 { 348 {
349 int x = i % MAP_WIDTH; 349 int x = i % MAP_WIDTH;
350 int y = i / MAP_WIDTH; 350 int y = i / MAP_WIDTH;
351 int tile = map.mapdata()[i]; 351 int tile = map.getMapdata()[i];
352 352
353 if ((tile > 0) && (tile < 28) && (!((tile >= 5) && (tile <= 7)))) 353 if ((tile > 0) && (tile < 28) && (!((tile >= 5) && (tile <= 7))))
354 { 354 {
@@ -600,15 +600,15 @@ void StaticImageComponent::render(Game&, Entity& entity, Texture& buffer)
600 600
601// Simple collision 601// Simple collision
602 602
603SimpleColliderComponent::SimpleColliderComponent(std::function<void (Entity& collider)> callback) : callback(callback) 603SimpleColliderComponent::SimpleColliderComponent(std::function<void (Game& game, Entity& collider)> callback) : callback(callback)
604{ 604{
605 605
606} 606}
607 607
608void SimpleColliderComponent::receive(Game&, Entity&, const Message& msg) 608void SimpleColliderComponent::receive(Game& game, Entity&, const Message& msg)
609{ 609{
610 if (msg.type == Message::Type::collision) 610 if (msg.type == Message::Type::collision)
611 { 611 {
612 callback(*(msg.collisionEntity)); 612 callback(game, *(msg.collisionEntity));
613 } 613 }
614} 614}
diff --git a/src/components.h b/src/components.h index f5c66d4..3d80d1a 100644 --- a/src/components.h +++ b/src/components.h
@@ -111,11 +111,11 @@ class StaticImageComponent : public Component {
111 111
112class SimpleColliderComponent : public Component { 112class SimpleColliderComponent : public Component {
113 public: 113 public:
114 SimpleColliderComponent(std::function<void (Entity& collider)> callback); 114 SimpleColliderComponent(std::function<void (Game& game, Entity& collider)> callback);
115 void receive(Game& game, Entity& entity, const Message& msg); 115 void receive(Game& game, Entity& entity, const Message& msg);
116 116
117 private: 117 private:
118 std::function<void (Entity& collider)> callback; 118 std::function<void (Game& game, Entity& collider)> callback;
119}; 119};
120 120
121#endif 121#endif
diff --git a/src/entity.cpp b/src/entity.cpp index 2b6cd7f..0ede567 100644 --- a/src/entity.cpp +++ b/src/entity.cpp
@@ -1,4 +1,7 @@
1#include "entity.h" 1#include "entity.h"
2#include <libxml/parser.h>
3#include "components.h"
4#include "muxer.h"
2 5
3void Entity::addComponent(std::shared_ptr<Component> c) 6void Entity::addComponent(std::shared_ptr<Component> c)
4{ 7{
diff --git a/src/entity.h b/src/entity.h index e22fd10..44ce973 100644 --- a/src/entity.h +++ b/src/entity.h
@@ -7,6 +7,7 @@ class Component;
7#include <list> 7#include <list>
8#include "renderer.h" 8#include "renderer.h"
9#include "game.h" 9#include "game.h"
10#include "map.h"
10 11
11class Message { 12class Message {
12 public: 13 public:
diff --git a/src/entityfactory.cpp b/src/entityfactory.cpp new file mode 100644 index 0000000..acf9b8e --- /dev/null +++ b/src/entityfactory.cpp
@@ -0,0 +1,101 @@
1#include "entityfactory.h"
2#include <libxml/parser.h>
3#include "components.h"
4#include "muxer.h"
5#include <cstdio>
6
7struct EntityData {
8 char* sprite;
9 char* action;
10 bool hasPhysics;
11 int width;
12 int height;
13};
14
15static std::map<std::string, EntityData> factories;
16
17std::shared_ptr<Entity> EntityFactory::createNamedEntity(const std::string name, const Map& map)
18{
19 auto it = factories.find(name);
20 EntityData data = factories[name];
21 if (it == factories.end())
22 {
23 xmlDocPtr doc = xmlParseFile(("../entities/" + name + ".xml").c_str());
24 if (doc == nullptr)
25 {
26 fprintf(stderr, "Error reading entity %s\n", name.c_str());
27 exit(-1);
28 }
29
30 xmlNodePtr top = xmlDocGetRootElement(doc);
31 if (top == nullptr)
32 {
33 fprintf(stderr, "Empty entity %s\n", name.c_str());
34 exit(-1);
35 }
36
37 if (xmlStrcmp(top->name, (const xmlChar*) "entity-def"))
38 {
39 fprintf(stderr, "Invalid entity definition %s\n", name.c_str());
40 exit(-1);
41 }
42
43 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next)
44 {
45 if (!xmlStrcmp(node->name, (const xmlChar*) "sprite"))
46 {
47 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
48 data.sprite = (char*) calloc(xmlStrlen(key)+1, sizeof(char));
49 strcpy(data.sprite, (char*) key);
50 xmlFree(key);
51 } else if (!xmlStrcmp(node->name, (const xmlChar*) "action"))
52 {
53 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
54 data.action = (char*) calloc(xmlStrlen(key)+1, sizeof(char));
55 strcpy(data.action, (char*) key);
56 xmlFree(key);
57 } else if (!xmlStrcmp(node->name, (const xmlChar*) "size"))
58 {
59 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
60 data.hasPhysics = true;
61 sscanf((char*) key, "%d,%d", &(data.width), &(data.height));
62 xmlFree(key);
63 }
64 }
65
66 xmlFreeDoc(doc);
67
68 factories[name] = data;
69 }
70
71 auto entity = std::make_shared<Entity>();
72
73 if (data.sprite)
74 {
75 auto component = std::make_shared<StaticImageComponent>(data.sprite);
76 entity->addComponent(component);
77 }
78
79 if (data.action)
80 {
81 if (!strcmp(data.action, "save"))
82 {
83 auto component = std::make_shared<SimpleColliderComponent>([&] (Game& game, Entity& collider) {
84 playSound("../res/Pickup_Coin23.wav", 0.25);
85
86 game.saveGame(map, collider.position);
87 });
88 entity->addComponent(component);
89 }
90 }
91
92 if (data.hasPhysics)
93 {
94 auto component = std::make_shared<PhysicsBodyComponent>();
95 entity->addComponent(component);
96
97 entity->size = std::make_pair(data.width, data.height);
98 }
99
100 return entity;
101}
diff --git a/src/entityfactory.h b/src/entityfactory.h new file mode 100644 index 0000000..a35b5f7 --- /dev/null +++ b/src/entityfactory.h
@@ -0,0 +1,15 @@
1#ifndef ENTITYFACTORY_H
2#define ENTITYFACTORY_H
3
4#include "entity.h"
5#include <memory>
6#include <string>
7#include <map>
8#include "map.h"
9
10class EntityFactory {
11 public:
12 static std::shared_ptr<Entity> createNamedEntity(const std::string name, const Map& map);
13};
14
15#endif
diff --git a/src/game.cpp b/src/game.cpp index b149392..7ec4460 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -2,12 +2,10 @@
2#include "renderer.h" 2#include "renderer.h"
3#include "components.h" 3#include "components.h"
4#include "muxer.h" 4#include "muxer.h"
5#include "entityfactory.h"
5 6
6Game::Game() 7Game::Game()
7{ 8{
8 m.setLeftMap(&m2);
9 m2.setRightMap(&m);
10
11 player = std::make_shared<Entity>(); 9 player = std::make_shared<Entity>();
12 player->position = std::make_pair(100.0,100.0); 10 player->position = std::make_pair(100.0,100.0);
13 player->size = std::make_pair(10.0,12.0); 11 player->size = std::make_pair(10.0,12.0);
@@ -116,32 +114,10 @@ void Game::loadMap(const Map& map)
116 auto map_collision = std::make_shared<MapCollisionComponent>(map); 114 auto map_collision = std::make_shared<MapCollisionComponent>(map);
117 mapEn->addComponent(map_collision); 115 mapEn->addComponent(map_collision);
118 116
117 // Map in the back, player on top, rest of entities in between
119 nextEntities.clear(); 118 nextEntities.clear();
120 nextEntities.push_back(mapEn); 119 nextEntities.push_back(mapEn);
121 120 map.createEntities(nextEntities);
122 // this is cheating but is just for testing
123 if (&map == &m2)
124 {
125 auto saveEn = std::make_shared<Entity>();
126 saveEn->position = std::make_pair(257.0, 160.0);
127 saveEn->size = std::make_pair(8.0, 11.0);
128
129 auto save_render = std::make_shared<StaticImageComponent>("../res/keyring.png");
130 saveEn->addComponent(save_render);
131
132 auto save_physics = std::make_shared<PhysicsBodyComponent>();
133 saveEn->addComponent(save_physics);
134
135 auto save_collide = std::make_shared<SimpleColliderComponent>([&] (Entity& collider) {
136 playSound("../res/Pickup_Coin23.wav", 0.25);
137
138 saveGame(map, collider.position);
139 });
140 saveEn->addComponent(save_collide);
141
142 nextEntities.push_back(saveEn);
143 }
144
145 nextEntities.push_back(player); 121 nextEntities.push_back(player);
146 122
147 newWorld = true; 123 newWorld = true;
@@ -160,9 +136,9 @@ void Game::saveGame(const Map& map, std::pair<double, double> position)
160 save = {&map, position}; 136 save = {&map, position};
161} 137}
162 138
163void Game::schedule(double time, std::function<void ()>&& callback) 139void Game::schedule(double time, std::function<void ()> callback)
164{ 140{
165 scheduled.emplace_front(time, callback); 141 scheduled.emplace_front(time, std::move(callback));
166} 142}
167 143
168void Game::playerDie(Entity& player, const Map& curMap) 144void Game::playerDie(Entity& player, const Map& curMap)
diff --git a/src/game.h b/src/game.h index c7c2625..33d1965 100644 --- a/src/game.h +++ b/src/game.h
@@ -30,7 +30,7 @@ class Game {
30 void loadMap(const Map& map); 30 void loadMap(const Map& map);
31 void detectCollision(Entity& collider, std::pair<double, double> old_position); 31 void detectCollision(Entity& collider, std::pair<double, double> old_position);
32 void saveGame(const Map& map, std::pair<double, double> position); 32 void saveGame(const Map& map, std::pair<double, double> position);
33 void schedule(double time, std::function<void ()>&& callback); 33 void schedule(double time, std::function<void ()> callback);
34 void playerDie(Entity& player, const Map& curMap); 34 void playerDie(Entity& player, const Map& curMap);
35 35
36 private: 36 private:
@@ -40,8 +40,8 @@ class Game {
40 std::list<std::shared_ptr<Entity>> nextEntities; 40 std::list<std::shared_ptr<Entity>> nextEntities;
41 bool newWorld; 41 bool newWorld;
42 std::shared_ptr<Entity> player; 42 std::shared_ptr<Entity> player;
43 Map m{"../maps/embarass.txt"}; 43 Map m {Map::getNamedMap("embarass")};
44 Map m2{"../maps/second.txt"}; 44 Map m2 {Map::getNamedMap("second")};
45 Savefile save; 45 Savefile save;
46 std::list<std::pair<double, std::function<void ()>>> scheduled; 46 std::list<std::pair<double, std::function<void ()>>> scheduled;
47 bool shouldQuit = false; 47 bool shouldQuit = false;
diff --git a/src/map.cpp b/src/map.cpp index 3976b63..8c1c6f0 100644 --- a/src/map.cpp +++ b/src/map.cpp
@@ -2,43 +2,111 @@
2#include "game.h" 2#include "game.h"
3#include <cstdlib> 3#include <cstdlib>
4#include <cstring> 4#include <cstring>
5#include <libxml/parser.h>
6#include <map>
7#include "entityfactory.h"
8
9static std::map<std::string, Map> maps;
5 10
6Map::Map() 11Map::Map()
7{ 12{
8 13 title = (char*) calloc(1, sizeof(char));
14 mapdata = (int*) calloc(1, sizeof(int));
9} 15}
10 16
11Map::Map(const char* filename) 17Map::Map(const std::string name)
12{ 18{
13 FILE* f = fopen(filename, "r"); 19 xmlDocPtr doc = xmlParseFile(("../maps/" + name + ".xml").c_str());
20 if (doc == nullptr)
21 {
22 fprintf(stderr, "Error reading map %s\n", name.c_str());
23 exit(-1);
24 }
14 25
15 m_mapdata = (int*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int)); 26 xmlNodePtr top = xmlDocGetRootElement(doc);
16 for (int i=0; i<MAP_HEIGHT-1; i++) 27 if (top == nullptr)
17 { 28 {
18 for (int j=0; j<MAP_WIDTH; j++) 29 fprintf(stderr, "Empty map %s\n", name.c_str());
30 exit(-1);
31 }
32
33 if (xmlStrcmp(top->name, (const xmlChar*) "map-def"))
34 {
35 fprintf(stderr, "Invalid map definition %s\n", name.c_str());
36 exit(-1);
37 }
38
39 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next)
40 {
41 if (!xmlStrcmp(node->name, (const xmlChar*) "name"))
42 {
43 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
44 title = (char*) calloc(xmlStrlen(key) + 1, sizeof(char));
45 strcpy(title, (char*) key);
46 xmlFree(key);
47 } else if (!xmlStrcmp(node->name, (const xmlChar*) "environment"))
48 {
49 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
50 mapdata = (int*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int));
51 mapdata[0] = atoi(strtok((char*) key, ",\n"));
52 for (int i=1; i<(MAP_WIDTH*(MAP_HEIGHT-1)); i++)
53 {
54 mapdata[i] = atoi(strtok(NULL, ",\n"));
55 }
56 xmlFree(key);
57 } else if (!xmlStrcmp(node->name, (const xmlChar*) "entities"))
19 { 58 {
20 fscanf(f, "%d,", &(m_mapdata[i*MAP_WIDTH + j])); 59 for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next)
60 {
61 if (!xmlStrcmp(entityNode->name, (const xmlChar*) "entity"))
62 {
63 EntityData data;
64 for (xmlNodePtr entityDataNode = entityNode->xmlChildrenNode; entityDataNode != NULL; entityDataNode = entityDataNode->next)
65 {
66 if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-type"))
67 {
68 xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1);
69 data.name = std::string((char*) key);
70 xmlFree(key);
71 } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position"))
72 {
73 xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1);
74 sscanf((char*) key, "%lf,%lf", &(data.position.first), &(data.position.second));
75 xmlFree(key);
76 }
77 }
78
79 entities.push_back(data);
80 }
81 }
82 } else if (!xmlStrcmp(node->name, (const xmlChar*) "leftmap"))
83 {
84 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
85 leftMap = &Map::getNamedMap(std::string((char*) key));
86 xmlFree(key);
87 } else if (!xmlStrcmp(node->name, (const xmlChar*) "rightmap"))
88 {
89 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
90 rightMap = &Map::getNamedMap(std::string((char*) key));
91 xmlFree(key);
21 } 92 }
22
23 fgetc(f);
24 } 93 }
25 94
26 m_title = (char*) calloc(41, sizeof(char)); 95 xmlFreeDoc(doc);
27 fgets(m_title, 41, f);
28
29 fclose(f);
30} 96}
31 97
32Map::Map(Map& map) 98Map::Map(const Map& map)
33{ 99{
34 m_mapdata = (int*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int)); 100 mapdata = (int*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int));
35 memcpy(m_mapdata, map.m_mapdata, MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int)); 101 memcpy(mapdata, map.mapdata, MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int));
102
103 title = (char*) malloc((MAP_WIDTH+1)*sizeof(char));
104 strncpy(title, map.title, MAP_WIDTH+1);
36 105
37 m_title = (char*) malloc((MAP_WIDTH+1)*sizeof(char)); 106 leftMap = map.leftMap;
38 strncpy(m_title, map.m_title, MAP_WIDTH+1); 107 rightMap = map.rightMap;
39 108
40 m_leftMap = map.m_leftMap; 109 entities = map.entities;
41 m_rightMap = map.m_rightMap;
42} 110}
43 111
44Map::Map(Map&& map) : Map() 112Map::Map(Map&& map) : Map()
@@ -48,8 +116,8 @@ Map::Map(Map&& map) : Map()
48 116
49Map::~Map() 117Map::~Map()
50{ 118{
51 free(m_mapdata); 119 free(mapdata);
52 free(m_title); 120 free(title);
53} 121}
54 122
55Map& Map::operator= (Map map) 123Map& Map::operator= (Map map)
@@ -61,38 +129,60 @@ Map& Map::operator= (Map map)
61 129
62void swap(Map& first, Map& second) 130void swap(Map& first, Map& second)
63{ 131{
64 std::swap(first.m_mapdata, second.m_mapdata); 132 std::swap(first.mapdata, second.mapdata);
65 std::swap(first.m_title, second.m_title); 133 std::swap(first.title, second.title);
66 std::swap(first.m_leftMap, second.m_leftMap); 134 std::swap(first.leftMap, second.leftMap);
67 std::swap(first.m_rightMap, second.m_rightMap); 135 std::swap(first.rightMap, second.rightMap);
136 std::swap(first.entities, second.entities);
68} 137}
69 138
70const int* Map::mapdata() const 139const int* Map::getMapdata() const
71{ 140{
72 return m_mapdata; 141 return mapdata;
73} 142}
74 143
75const char* Map::title() const 144const char* Map::getTitle() const
76{ 145{
77 return m_title; 146 return title;
78} 147}
79 148
80const Map* Map::getLeftMap() const 149const Map* Map::getLeftMap() const
81{ 150{
82 return m_leftMap; 151 return leftMap;
83} 152}
84 153
85const Map* Map::getRightMap() const 154const Map* Map::getRightMap() const
86{ 155{
87 return m_rightMap; 156 return rightMap;
88} 157}
89 158
90void Map::setLeftMap(const Map* m) 159void Map::setLeftMap(const Map* m)
91{ 160{
92 m_leftMap = m; 161 leftMap = m;
93} 162}
94 163
95void Map::setRightMap(const Map* m) 164void Map::setRightMap(const Map* m)
96{ 165{
97 m_rightMap = m; 166 rightMap = m;
167}
168
169void Map::createEntities(std::list<std::shared_ptr<Entity>>& entities) const
170{
171 for (auto data : this->entities)
172 {
173 auto entity = EntityFactory::createNamedEntity(data.name, *this);
174 entity->position = data.position;
175
176 entities.push_back(entity);
177 }
178}
179
180Map& Map::getNamedMap(const std::string name)
181{
182 if (maps.count(name) == 0)
183 {
184 maps[name] = Map {name};
185 }
186
187 return maps[name];
98} 188}
diff --git a/src/map.h b/src/map.h index 071b6f2..fa2edcc 100644 --- a/src/map.h +++ b/src/map.h
@@ -1,28 +1,41 @@
1#ifndef MAP_H 1#ifndef MAP_H
2#define MAP_H 2#define MAP_H
3 3
4#include <string>
5#include <list>
6
7class Entity;
8
4class Map { 9class Map {
5 public: 10 public:
6 Map(const char* filename); 11 Map();
7 Map(Map& map); 12 Map(const std::string name);
13 Map(const Map& map);
8 Map(Map&& map); 14 Map(Map&& map);
9 ~Map(); 15 ~Map();
10 Map& operator= (Map other); 16 Map& operator= (Map other);
11 friend void swap(Map& first, Map& second); 17 friend void swap(Map& first, Map& second);
12 18
13 const int* mapdata() const; 19 static Map& getNamedMap(const std::string name);
14 const char* title() const; 20
21 const int* getMapdata() const;
22 const char* getTitle() const;
15 const Map* getLeftMap() const; 23 const Map* getLeftMap() const;
16 const Map* getRightMap() const; 24 const Map* getRightMap() const;
17 void setLeftMap(const Map* m); 25 void setLeftMap(const Map* m);
18 void setRightMap(const Map* m); 26 void setRightMap(const Map* m);
27 void createEntities(std::list<std::shared_ptr<Entity>>& entities) const;
19 private: 28 private:
20 Map(); 29 struct EntityData {
30 std::string name;
31 std::pair<double, double> position;
32 };
21 33
22 int* m_mapdata; 34 int* mapdata;
23 char* m_title; 35 char* title;
24 const Map* m_leftMap = nullptr; 36 const Map* leftMap = nullptr;
25 const Map* m_rightMap = nullptr; 37 const Map* rightMap = nullptr;
38 std::list<EntityData> entities;
26}; 39};
27 40
28#endif 41#endif
diff --git a/src/renderer.cpp b/src/renderer.cpp index 64c9fd0..c2b37d2 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -513,7 +513,7 @@ Texture::Texture(const char* filename)
513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
514} 514}
515 515
516Texture::Texture(Texture& tex) 516Texture::Texture(const Texture& tex)
517{ 517{
518 if (!rendererInitialized) 518 if (!rendererInitialized)
519 { 519 {
diff --git a/src/renderer.h b/src/renderer.h index 90ec101..84ad688 100644 --- a/src/renderer.h +++ b/src/renderer.h
@@ -15,7 +15,7 @@ class Texture {
15 public: 15 public:
16 Texture(int width, int height); 16 Texture(int width, int height);
17 Texture(const char* file); 17 Texture(const char* file);
18 Texture(Texture& tex); 18 Texture(const Texture& tex);
19 Texture(Texture&& tex); 19 Texture(Texture&& tex);
20 ~Texture(); 20 ~Texture();
21 Texture& operator= (Texture tex); 21 Texture& operator= (Texture tex);