diff --git a/PlatformerGame/Game/Game.vcxproj b/PlatformerGame/Game/Game.vcxproj
index 364e78c..86b2a36 100644
--- a/PlatformerGame/Game/Game.vcxproj
+++ b/PlatformerGame/Game/Game.vcxproj
@@ -95,37 +95,53 @@
+
+
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
@@ -133,6 +149,7 @@
+
@@ -149,6 +166,7 @@
+
diff --git a/PlatformerGame/Game/Game.vcxproj.filters b/PlatformerGame/Game/Game.vcxproj.filters
index d970210..4db0418 100644
--- a/PlatformerGame/Game/Game.vcxproj.filters
+++ b/PlatformerGame/Game/Game.vcxproj.filters
@@ -30,7 +30,7 @@
Modules
-
+
Entities
@@ -57,8 +57,32 @@
Modules
+
+ Entities
+
+
+ Entities
+
+
+ Modules
+
- Tools
+ Modules
+
+
+ Entities
+
+
+ Modules
+
+
+ Entities
+
+
+ Entities
+
+
+ Entities
@@ -111,7 +135,7 @@
Modules
-
+
Entities
@@ -147,8 +171,35 @@
Modules
+
+ Entities
+
+
+ Entities
+
+
+ Modules
+
- Tools
+ Modules
+
+
+ Utils
+
+
+ Entities
+
+
+ Modules
+
+
+ Entities
+
+
+ Entities
+
+
+ Entities
@@ -173,5 +224,6 @@
+
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/Animation.h b/PlatformerGame/Game/Source/Animation.h
index 529b279..671889e 100644
--- a/PlatformerGame/Game/Source/Animation.h
+++ b/PlatformerGame/Game/Source/Animation.h
@@ -90,12 +90,12 @@ class Animation
return frames[actualFrame];
}
- void LoadAnimations(const char* name)
+ void LoadAnimations(const char* animationFrame, const char* entity)
{
pugi::xml_parse_result result = animFile.load_file("config.xml");
if (result != NULL)
{
- pugi::xml_node animationName = animFile.child("config").child("animations").child(name);
+ pugi::xml_node animationName = animFile.child("config").child("animations").child(entity).child(animationFrame);
loop = animationName.attribute("loop").as_bool();
speed = animationName.attribute("speed").as_float();
for (pugi::xml_node animation = animationName.child("animation"); animation; animation = animation.next_sibling("animation"))
diff --git a/PlatformerGame/Game/Source/App.cpp b/PlatformerGame/Game/Source/App.cpp
index 0b476a5..f06dbaf 100644
--- a/PlatformerGame/Game/Source/App.cpp
+++ b/PlatformerGame/Game/Source/App.cpp
@@ -8,6 +8,7 @@
#include "Map.h"
#include "Physics.h"
#include "FadeToBlack.h"
+#include "ParticleManager.h"
#include "Defs.h"
#include "Log.h"
@@ -35,6 +36,7 @@ App::App(int argc, char* args[]) : argc(argc), args(args)
map = new Map();
entityManager = new EntityManager();
fade = new FadeToBlack();
+ particleManager = new ParticleManager();
// Ordered for awake / Start / Update
@@ -47,6 +49,7 @@ App::App(int argc, char* args[]) : argc(argc), args(args)
AddModule(scene);
AddModule(map);
AddModule(entityManager);
+ AddModule(particleManager);
AddModule(fade);
// Render last to swap buffer
@@ -224,6 +227,16 @@ void App::FinishUpdate()
gameTitle.GetString(), framesPerSecond, averageFps, dt, vsync);
app->win->SetTitle(title);
+
+ if (loadRequest) {
+ loadRequest = false;
+ LoadFromFile();
+ }
+
+ if (saveRequest) {
+ saveRequest = false;
+ SaveFromFile();
+ }
}
// Call modules before each loop iteration
@@ -343,3 +356,79 @@ float App::GetDT()
return dt;
}
+// Request a save data in an XML file
+bool App::LoadRequest() {
+
+ bool ret = true;
+ loadRequest = true;
+ return ret;
+}
+
+// Request to load data from XML file
+bool App::SaveRequest() {
+ bool ret = true;
+ saveRequest = true;
+ return true;
+}
+
+bool App::LoadFromFile() {
+
+ bool ret = true;
+
+ pugi::xml_document saveFile;
+ pugi::xml_parse_result result = saveFile.load_file("save_game.xml");
+
+ if (result)
+ {
+ LOG("save_game.xml parsed without errors");
+
+ // Iterates all modules and call the load of each with the part of the XML node that corresponds to the module
+ ListItem* item;
+ item = modules.start;
+
+ while (item != NULL && ret == true)
+ {
+ ret = item->data->LoadState(saveFile.child("game_state").child(item->data->name.GetString()));
+ item = item->next;
+ }
+
+ }
+ else
+ {
+ LOG("Error loading save_game.xml: %s", result.description());
+ ret = false;
+ }
+
+
+
+ return ret;
+
+}
+
+bool App::SaveFromFile() {
+
+ bool ret = true;
+
+ pugi::xml_document saveFile;
+ pugi::xml_node gameState = saveFile.append_child("game_state");
+
+ // Iterates all modules and call the save of each with the part of the XML node that corresponds to the module
+ ListItem* item;
+ item = modules.start;
+
+ while (item != NULL && ret == true)
+ {
+ pugi::xml_node module = gameState.append_child(item->data->name.GetString());
+ ret = item->data->SaveState(module);
+ item = item->next;
+ }
+
+ ret = saveFile.save_file("save_game.xml");
+
+ if (ret) LOG("Saved");
+ else LOG("Error saving game state");
+
+ return ret;
+
+}
+
diff --git a/PlatformerGame/Game/Source/App.h b/PlatformerGame/Game/Source/App.h
index ba92713..578466b 100644
--- a/PlatformerGame/Game/Source/App.h
+++ b/PlatformerGame/Game/Source/App.h
@@ -20,6 +20,7 @@ class EntityManager;
class Map;
class Physics;
class FadeToBlack;
+class ParticleManager;
class App
{
@@ -53,6 +54,12 @@ class App
const char* GetOrganization() const;
float GetDT();
+ // Request a save data in an XML file
+ bool LoadRequest();
+
+ // Request to load data from XML file
+ bool SaveRequest();
+
private:
// Load config file
@@ -73,6 +80,12 @@ class App
// Call modules after each loop iteration
bool PostUpdate();
+ // Reads XML file and loads the data
+ bool LoadFromFile();
+
+ // Sace XML file with modules data
+ bool SaveFromFile();
+
public:
// Modules
@@ -86,11 +99,15 @@ class App
Map* map;
Physics* physics;
FadeToBlack* fade;
+ ParticleManager* particleManager;
uint32 maxFrameDuration = 16;
uint32 initialMaxFrameDuration = 16;
uint32 capMaxFrameDuration = 32;
+ bool loadRequest = false;
+ bool saveRequest = false;
+
private:
int argc;
diff --git a/PlatformerGame/Game/Source/Audio.cpp b/PlatformerGame/Game/Source/Audio.cpp
index 6dd81e1..bd847b5 100644
--- a/PlatformerGame/Game/Source/Audio.cpp
+++ b/PlatformerGame/Game/Source/Audio.cpp
@@ -175,4 +175,22 @@ bool Audio::PlayFx(unsigned int id, int repeat)
}
return ret;
+}
+
+void Audio::PauseFx(unsigned int id)
+{
+ if (!active)
+ return;
+
+ if (id > 0 && id <= fx.Count())
+ {
+ for (int i = 0; i < MIX_CHANNELS; ++i)
+ {
+ if (Mix_GetChunk(i) == fx[id - 1] && Mix_Playing(i))
+ {
+ Mix_HaltChannel(i);
+ break;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/Audio.h b/PlatformerGame/Game/Source/Audio.h
index 10d0538..4380953 100644
--- a/PlatformerGame/Game/Source/Audio.h
+++ b/PlatformerGame/Game/Source/Audio.h
@@ -32,6 +32,9 @@ class Audio : public Module
// Play a previously loaded WAV
bool PlayFx(unsigned int fx, int repeat = 0);
+ // Pause FX audio
+ void PauseFx(unsigned int id);
+
private:
_Mix_Music* music;
diff --git a/PlatformerGame/Game/Source/Chest.cpp b/PlatformerGame/Game/Source/Chest.cpp
new file mode 100644
index 0000000..911a9b3
--- /dev/null
+++ b/PlatformerGame/Game/Source/Chest.cpp
@@ -0,0 +1,123 @@
+#include "Chest.h"
+#include "App.h"
+#include "Textures.h"
+#include "Audio.h"
+#include "Input.h"
+#include "Render.h"
+#include "Scene.h"
+#include "Log.h"
+#include "Point.h"
+#include "Physics.h"
+#include "EntityManager.h"
+
+Chest::Chest() : Entity(EntityType::CHEST)
+{
+ name.Create("chest");
+}
+
+Chest::~Chest() {}
+
+bool Chest::Awake() {
+
+ position.x = parameters.attribute("x").as_int();
+ position.y = parameters.attribute("y").as_int();
+ texturePath = parameters.attribute("texturepath").as_string();
+ chestAudioFxId = app->audio->LoadFx(parameters.child("chestAudio").attribute("path").as_string());
+
+ return true;
+}
+
+bool Chest::Start() {
+
+ //initilize textures
+ texture = app->tex->Load(texturePath);
+ pbody = app->physics->CreateRectangleSensor(position.x + 38, position.y + 38, 25, 200, bodyType::STATIC);
+ pbody->ctype = ColliderType::CHEST;
+ pbody->listener = this;
+
+ pbody2 = app->physics->CreateCircle(position.x + 38, position.y + 38, 250, bodyType::STATIC);
+ pbody2->body->GetFixtureList()->SetSensor(true);
+ pbody2->ctype = ColliderType::CHEST_AREA;
+ pbody2->listener = this;
+
+ chestClosedIdleAnim.LoadAnimations("chestClosedIdleAnim", "chest");
+ chestOpenAnim.LoadAnimations("chestOpenAnim", "chest");
+ chestOpenPotionAnim.LoadAnimations("chestOpenPotionAnim", "chest");
+ chestOpenedIdleAnim.LoadAnimations("chestOpenedIdleAnim", "chest");
+ currentAnim = &chestClosedIdleAnim;
+
+
+ return true;
+}
+
+bool Chest::Update(float dt)
+{
+ if (isPicked) OnPicked();
+ if (chestArea) {
+ currentAnim = &chestOpenAnim;
+ app->audio->PlayFx(chestAudioFxId);
+ OnSensor();
+ }
+ if (currentAnim == &chestOpenAnim && currentAnim->HasFinished())
+ {
+ currentAnim = &chestOpenPotionAnim;
+ }
+
+
+ position.x = METERS_TO_PIXELS(pbody->body->GetTransform().p.x) - 38;
+ position.y = METERS_TO_PIXELS(pbody->body->GetTransform().p.y) - 38;
+
+ app->render->DrawTexture(texture, position.x, position.y, ¤tAnim->GetCurrentFrame());
+
+ currentAnim->Update();
+ return true;
+}
+
+bool Chest::CleanUp()
+{
+ return true;
+}
+
+void Chest::OnCollision(PhysBody* physA, PhysBody* physB)
+{
+ if (physA == pbody) {
+ switch (physB->ctype)
+ {
+ case ColliderType::PLAYER:
+ LOG("Collision PLAYER");
+ if (!isPicked && app->scene->player->canOpen)
+ {
+ pbody->body->SetActive(false);
+ app->scene->player->canPush = true;
+ app->scene->player->isDrinking = true;
+ isPicked = true;
+ }
+ break;
+ }
+ }
+ else if (physA == pbody2) {
+ switch (physB->ctype)
+ {
+ case ColliderType::PLAYER:
+ LOG("Collision PLAYER");
+ if (!chestArea && app->scene->player->canOpen)
+ {
+ pbody2->body->SetActive(false);
+ chestArea = true;
+ }
+ break;
+ }
+ }
+}
+
+void Chest::OnPicked()
+{
+ currentAnim = &chestOpenedIdleAnim;
+ isPicked = false;
+}
+
+void Chest::OnSensor()
+{
+ app->physics->world->DestroyBody(pbody2->body);
+ chestArea = false;
+}
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/Chest.h b/PlatformerGame/Game/Source/Chest.h
new file mode 100644
index 0000000..4efb566
--- /dev/null
+++ b/PlatformerGame/Game/Source/Chest.h
@@ -0,0 +1,55 @@
+#ifndef __CHEST_H__
+#define __CHEST_H__
+
+#include "Entity.h"
+#include "Point.h"
+#include "SDL/include/SDL.h"
+#include "Animation.h"
+
+struct SDL_Texture;
+
+class Chest : public Entity
+{
+public:
+
+ Chest();
+ virtual ~Chest();
+
+ bool Awake();
+
+ bool Start();
+
+ bool Update(float dt);
+
+ bool CleanUp();
+
+ void OnCollision(PhysBody* physA, PhysBody* physB);
+
+ void OnPicked();
+
+ void OnSensor();
+
+public:
+
+ bool isPicked = false;
+ bool chestArea = false;
+ bool chestIdleWaiting = false;
+ float followTimer = 0.0f;
+ float acceleration = 1.0f;
+ int chestAudioFxId;
+
+private:
+
+ SDL_Texture* texture;
+ const char* texturePath;
+ PhysBody* pbody;
+ PhysBody* pbody2;
+
+ Animation* currentAnim;
+ Animation chestClosedIdleAnim;
+ Animation chestOpenAnim;
+ Animation chestOpenPotionAnim;
+ Animation chestOpenedIdleAnim;
+};
+
+#endif // __CHEST_H__
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/CrumblingPlatform.cpp b/PlatformerGame/Game/Source/CrumblingPlatform.cpp
index 0b5ad25..8505cf8 100644
--- a/PlatformerGame/Game/Source/CrumblingPlatform.cpp
+++ b/PlatformerGame/Game/Source/CrumblingPlatform.cpp
@@ -34,8 +34,8 @@ bool CrumblingPlatform::Start() {
pbody->ctype = ColliderType::PLATFORM;
pbody->listener = this;
- platformIdleAnim.LoadAnimations("platformIdleAnim");
- platformBreakingAnim.LoadAnimations("platformBreakingAnim");
+ platformIdleAnim.LoadAnimations("platformIdleAnim", "platform");
+ platformBreakingAnim.LoadAnimations("platformBreakingAnim", "platform");
currentAnim = &platformIdleAnim;
diff --git a/PlatformerGame/Game/Source/Entity.h b/PlatformerGame/Game/Source/Entity.h
index 5b55cf7..b1af2c0 100644
--- a/PlatformerGame/Game/Source/Entity.h
+++ b/PlatformerGame/Game/Source/Entity.h
@@ -11,10 +11,16 @@ class PhysBody;
enum class EntityType
{
PLAYER,
- ITEM,
+ KEY,
+ EQUIPMENT,
+ CHEST,
JUMPER,
CRUMBLING_PLATFORM,
LOCK_DOOR,
+ SKELETON,
+ GHOST,
+ OBSTACLE,
+ LOG_OBSTACLE,
UNKNOWN
};
@@ -76,6 +82,14 @@ class Entity
};
+ virtual void OnExitCollision(PhysBody* physA, PhysBody* physB) {
+
+ };
+
+ virtual void Entity::ResetEntity() {
+
+ };
+
public:
SString name;
@@ -87,6 +101,10 @@ class Entity
// want our Entity class, maybe it's not renderable...
iPoint position;
bool renderable = true;
+
+ bool isDead = false;
+ int health = 100;
+ bool setLoadPosition = false;
};
#endif // __ENTITY_H__
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/EntityManager.cpp b/PlatformerGame/Game/Source/EntityManager.cpp
index 9759982..6fa4991 100644
--- a/PlatformerGame/Game/Source/EntityManager.cpp
+++ b/PlatformerGame/Game/Source/EntityManager.cpp
@@ -3,10 +3,16 @@
#include "App.h"
#include "Textures.h"
#include "Scene.h"
-#include "Item.h"
+#include "Key.h"
#include "Jumper.h"
#include "CrumblingPlatform.h"
#include "LockDoor.h"
+#include "Skeleton.h"
+#include "Ghost.h"
+#include "Equipment.h"
+#include "Obstacle.h"
+#include "Chest.h"
+#include "LogObstacle.h"
#include "Defs.h"
#include "Log.h"
@@ -88,8 +94,11 @@ Entity* EntityManager::CreateEntity(EntityType type)
case EntityType::PLAYER:
entity = new Player();
break;
- case EntityType::ITEM:
- entity = new Item();
+ case EntityType::KEY:
+ entity = new Key();
+ break;
+ case EntityType::EQUIPMENT:
+ entity = new Equipment();
break;
case EntityType::JUMPER:
entity = new Jumper();
@@ -100,6 +109,21 @@ Entity* EntityManager::CreateEntity(EntityType type)
case EntityType::LOCK_DOOR:
entity = new LockDoor();
break;
+ case EntityType::SKELETON:
+ entity = new Skeleton();
+ break;
+ case EntityType::GHOST:
+ entity = new Ghost();
+ break;
+ case EntityType::OBSTACLE:
+ entity = new Obstacle();
+ break;
+ case EntityType::CHEST:
+ entity = new Chest();
+ break;
+ case EntityType::LOG_OBSTACLE:
+ entity = new LogObstacle();
+ break;
default:
break;
}
@@ -139,4 +163,24 @@ bool EntityManager::Update(float dt)
}
return ret;
-}
\ No newline at end of file
+}
+
+void EntityManager::GetEnemies(List& skeletonsList, List& ghostsList) const
+{
+ skeletonsList.Clear();
+ ghostsList.Clear();
+
+ ListItem* entity;
+
+ for (entity = entities.start; entity != NULL; entity = entity->next)
+ {
+ if (entity->data->type == EntityType::SKELETON)
+ {
+ skeletonsList.Add(entity->data);
+ }
+ else if (entity->data->type == EntityType::GHOST)
+ {
+ ghostsList.Add(entity->data);
+ }
+ }
+}
diff --git a/PlatformerGame/Game/Source/EntityManager.h b/PlatformerGame/Game/Source/EntityManager.h
index 155a21c..88215dd 100644
--- a/PlatformerGame/Game/Source/EntityManager.h
+++ b/PlatformerGame/Game/Source/EntityManager.h
@@ -33,6 +33,8 @@ class EntityManager : public Module
void AddEntity(Entity* entity);
+ void GetEnemies(List& skeletonsList, List& ghostsList) const;
+
public:
List entities;
diff --git a/PlatformerGame/Game/Source/Equipment.cpp b/PlatformerGame/Game/Source/Equipment.cpp
new file mode 100644
index 0000000..6a2555f
--- /dev/null
+++ b/PlatformerGame/Game/Source/Equipment.cpp
@@ -0,0 +1,131 @@
+#include "Equipment.h"
+#include "App.h"
+#include "Textures.h"
+#include "Audio.h"
+#include "Input.h"
+#include "Render.h"
+#include "Scene.h"
+#include "Log.h"
+#include "Point.h"
+#include "Physics.h"
+#include "EntityManager.h"
+
+Equipment::Equipment() : Entity(EntityType::EQUIPMENT)
+{
+ name.Create("equipment");
+}
+
+Equipment::~Equipment() {}
+
+bool Equipment::Awake() {
+
+ position.x = parameters.attribute("x").as_int();
+ position.y = parameters.attribute("y").as_int();
+ texturePath = parameters.attribute("texturepath").as_string();
+ equipmentReleaseFxId = app->audio->LoadFx(parameters.child("equipmentReleaseAudio").attribute("path").as_string());
+ equipmentPickUpFxId = app->audio->LoadFx(parameters.child("equipmentPickUpAudio").attribute("path").as_string());
+
+ return true;
+}
+
+bool Equipment::Start() {
+
+ //initilize textures
+ texture = app->tex->Load(texturePath);
+ pbody = app->physics->CreateRectangleSensor(position.x + 90, position.y + 120, 25, 200, bodyType::STATIC);
+ pbody->ctype = ColliderType::EQUIPMENT;
+ pbody->listener = this;
+
+ pbody2 = app->physics->CreateCircle(position.x + 90, position.y + 190, 250, bodyType::STATIC);
+ pbody2->body->GetFixtureList()->SetSensor(true);
+ pbody2->ctype = ColliderType::EQUIPMENT_AREA;
+ pbody2->listener = this;
+
+ equipmentWithSword.LoadAnimations("equipmentWithSword", "equipment");
+ equipmentAnim.LoadAnimations("equipmentAnim", "equipment");
+ equipmentWithoutSword.LoadAnimations("equipmentWithoutSword", "equipment");
+ equipmentAnimIdle.LoadAnimations("equipmentAnimIdle", "equipment");
+ currentAnim = &equipmentWithSword;
+
+
+ return true;
+}
+
+bool Equipment::Update(float dt)
+{
+ if (isPicked) OnPicked();
+ if (equipmentArea) {
+ currentAnim = &equipmentAnim;
+ OnSensor();
+ }
+ if (currentAnim == &equipmentAnim && currentAnim->HasFinished())
+ {
+ currentAnim= &equipmentAnimIdle;
+ }
+ if (currentAnim == &equipmentAnim && currentAnim->GetCurrentFrameCount() >= 17 && !soundPlayed) {
+ app->audio->PlayFx(app->scene->player->swordAudio2FxId);
+ soundPlayed = true;
+ }
+
+ position.x = METERS_TO_PIXELS(pbody->body->GetTransform().p.x) - 90;
+ position.y = METERS_TO_PIXELS(pbody->body->GetTransform().p.y) - 120;
+
+ app->render->DrawTexture(texture, position.x, position.y, ¤tAnim->GetCurrentFrame());
+
+ currentAnim->Update();
+ return true;
+}
+
+bool Equipment::CleanUp()
+{
+ return true;
+}
+
+void Equipment::OnCollision(PhysBody* physA, PhysBody* physB)
+{
+ if (physA == pbody) {
+ switch (physB->ctype)
+ {
+ case ColliderType::PLAYER:
+ LOG("Collision PLAYER");
+ if (!isPicked)
+ {
+ pbody->body->SetActive(false);
+ app->scene->player->activeSword = true;
+ app->scene->player->isEquipped = true;
+ isPicked = true;
+ }
+ break;
+ }
+ }
+ else if (physA == pbody2) {
+ switch (physB->ctype)
+ {
+ case ColliderType::PLAYER:
+ LOG("Collision PLAYER");
+ if (!equipmentArea)
+ {
+ pbody2->body->SetActive(false);
+ equipmentArea = true;
+ }
+ break;
+ }
+ }
+
+}
+
+void Equipment::OnPicked()
+{
+ currentAnim = &equipmentWithoutSword;
+ //app->entityManager->DestroyEntity(this);
+ //app->physics->world->DestroyBody(pbody->body);
+ app->audio->PlayFx(equipmentPickUpFxId);
+ isPicked = false;
+}
+
+void Equipment::OnSensor()
+{
+ app->physics->world->DestroyBody(pbody2->body);
+ app->audio->PlayFx(equipmentReleaseFxId);
+ equipmentArea = false;
+}
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/Equipment.h b/PlatformerGame/Game/Source/Equipment.h
new file mode 100644
index 0000000..fce49bb
--- /dev/null
+++ b/PlatformerGame/Game/Source/Equipment.h
@@ -0,0 +1,57 @@
+#ifndef __EQUIPMENT_H__
+#define __EQUIPMENT_H__
+
+#include "Entity.h"
+#include "Point.h"
+#include "SDL/include/SDL.h"
+#include "Animation.h"
+
+struct SDL_Texture;
+
+class Equipment : public Entity
+{
+public:
+
+ Equipment();
+ virtual ~Equipment();
+
+ bool Awake();
+
+ bool Start();
+
+ bool Update(float dt);
+
+ bool CleanUp();
+
+ void OnCollision(PhysBody* physA, PhysBody* physB);
+
+ void OnPicked();
+
+ void OnSensor();
+
+public:
+
+ bool isPicked = false;
+ bool equipmentArea = false;
+ bool equipmentIdleWaiting = false;
+ bool soundPlayed = false;
+ float followTimer = 0.0f;
+ float acceleration = 1.0f;
+ int equipmentReleaseFxId;
+ int equipmentPickUpFxId;
+
+private:
+
+ SDL_Texture* texture;
+ const char* texturePath;
+ PhysBody* pbody;
+ PhysBody* pbody2;
+
+ Animation* currentAnim;
+ Animation equipmentWithSword;
+ Animation equipmentAnim;
+ Animation equipmentWithoutSword;
+ Animation equipmentAnimIdle;
+};
+
+#endif // __EQUIPMENT_H__
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/FadeToBlack.cpp b/PlatformerGame/Game/Source/FadeToBlack.cpp
index 039ff73..71f0387 100644
--- a/PlatformerGame/Game/Source/FadeToBlack.cpp
+++ b/PlatformerGame/Game/Source/FadeToBlack.cpp
@@ -12,6 +12,7 @@ FadeToBlack::FadeToBlack() : Module()
{
screenRect = {0, 0, 2000, 2000 };
+ name.Create("fadetoblack");
}
FadeToBlack::~FadeToBlack()
@@ -45,12 +46,14 @@ bool FadeToBlack::Update(float dt)
if (frameCount <= 0)
{
currentStep = Fade_Step::NONE;
+ fadeFinished = true;
}
if (!activated)
{
activated = true;
if (levelIdx == 1) app->scene->StartLevel1();
else if (levelIdx == 2) app->scene->StartLevel2();
+ else if (levelIdx == 3) app->scene->StartLevel3();
}
}
@@ -85,6 +88,7 @@ bool FadeToBlack::Fade(int levelIdx, float frames)
ret = true;
}
activated = false;
+ fadeFinished = false;
return ret;
}
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/FadeToBlack.h b/PlatformerGame/Game/Source/FadeToBlack.h
index dcb9dc6..b4ff972 100644
--- a/PlatformerGame/Game/Source/FadeToBlack.h
+++ b/PlatformerGame/Game/Source/FadeToBlack.h
@@ -30,6 +30,9 @@ class FadeToBlack : public Module
// After the first step, the modules should be switched
bool Fade(int cameraIdx, float frames = 60);
+public:
+ bool fadeFinished = true;
+
private:
enum Fade_Step
diff --git a/PlatformerGame/Game/Source/Ghost.cpp b/PlatformerGame/Game/Source/Ghost.cpp
new file mode 100644
index 0000000..9f40fcb
--- /dev/null
+++ b/PlatformerGame/Game/Source/Ghost.cpp
@@ -0,0 +1,249 @@
+#include "Ghost.h"
+#include "App.h"
+#include "Textures.h"
+#include "Audio.h"
+#include "Input.h"
+#include "Render.h"
+#include "Scene.h"
+#include "Log.h"
+#include "Point.h"
+#include "Physics.h"
+#include "EntityManager.h"
+#include "Map.h"
+
+Ghost::Ghost() : Entity(EntityType::GHOST)
+{
+ name.Create("Ghost");
+}
+
+Ghost::~Ghost() {}
+
+bool Ghost::Awake() {
+
+ position.x = parameters.attribute("x").as_int();
+ position.y = parameters.attribute("y").as_int();
+ texturePath = parameters.attribute("texturepath").as_string();
+ speed = parameters.attribute("speed").as_float();
+ summonPosition.x = parameters.attribute("x").as_int() - 200;
+ summonPosition.y = parameters.attribute("y").as_int();
+ ghostSummonFxId = app->audio->LoadFx(parameters.child("ghostSummonAudio").attribute("path").as_string());
+ lightTexturePath = parameters.attribute("lightTexture").as_string();
+ bigLightTexturePath = parameters.attribute("bigLightTexture").as_string();
+
+ initialIdlePosition = summonPosition;
+
+ return true;
+}
+
+bool Ghost::Start() {
+
+ //initilize textures
+ texture = app->tex->Load(texturePath);
+ pathTexture = app->tex->Load("Assets/Textures/path.png");
+ lightTexture = app->tex->Load(lightTexturePath);
+ bigLightTexture = app->tex->Load(bigLightTexturePath);
+ pbody = app->physics->CreateCircle(position.x, position.y, 20, bodyType::STATIC);
+ pbody->ctype = ColliderType::GHOST;
+ pbody->listener = this;
+
+ summonPbody = app->physics->CreateCircle(summonPosition.x, summonPosition.y, 20, bodyType::KINEMATIC);
+ summonPbody->ctype = ColliderType::GHOST_SUMMON;
+ summonPbody->body->GetFixtureList()->SetSensor(true);
+ summonPbody->listener = this;
+
+ initialTransform = pbody->body->GetTransform();
+ initialSummonTransform = summonPbody->body->GetTransform();
+
+ LoadAnimations();
+
+ return true;
+}
+
+bool Ghost::Update(float dt)
+{
+ playerTilePos = app->map->WorldToMap(app->scene->player->position.x + 50, app->scene->player->position.y);
+
+ //ghost
+ if (currentAnim == &ghostSummonAnim && currentAnim->HasFinished())
+ {
+ currentAnim = &ghostIdleAnim;
+ }
+
+ if (setLoadPosition)
+ {
+ pbody->body->SetTransform({ PIXEL_TO_METERS(position.x), PIXEL_TO_METERS(position.y) }, 0);
+ setLoadPosition = false;
+ }
+ else
+ {
+ position.x = METERS_TO_PIXELS(pbody->body->GetTransform().p.x);
+ position.y = METERS_TO_PIXELS(pbody->body->GetTransform().p.y);
+ }
+
+ // draw light
+ app->render->DrawTexture(bigLightTexture, position.x - 80, position.y - 200);
+
+ //draw ghost
+ SDL_Rect rect = currentAnim->GetCurrentFrame();
+ if (isFacingRight) app->render->DrawTexture(texture, position.x - 110, position.y - 130, &rect);
+ else app->render->DrawTexture(texture, position.x - 110, position.y - 130, &rect, SDL_FLIP_HORIZONTAL);
+ currentAnim->Update();
+
+ //ghost summon
+ summonTilePos = app->map->WorldToMap(summonPosition.x, summonPosition.y);
+
+ distance = playerTilePos.DistanceTo(summonTilePos);
+
+ // spawn summon
+ if (distance < 18 && !summonSpawned)
+ {
+ currentAnim = &ghostSummonAnim;
+ currentAnim->ResetLoopCount();
+ currentAnim->Reset();
+ currentSummonAnim = &ghostSummonAppearAnim;
+ currentSummonAnim->ResetLoopCount();
+ currentSummonAnim->Reset();
+ summonSpawned = true;
+ app->audio->PlayFx(ghostSummonFxId);
+ }
+
+ // move summon to player
+ if (distance < 10)
+ {
+ app->map->pathfinding->CreatePath(summonTilePos, playerTilePos, true);
+ path = app->map->pathfinding->GetLastPath();
+
+ if (distance < 2)
+ {
+ velocity = { 0, 0 };
+ if (isSummonFollowing) isSummonFollowing = false;
+ }
+ else if (distance >= 2)
+ {
+ const DynArray* path = app->map->pathfinding->GetLastPath();
+ if (path->Count() > 1) {
+ nextTilePath = { path->At(1)->x, path->At(1)->y };
+ Move(summonTilePos, nextTilePath);
+ }
+
+ if (!isSummonFollowing) isSummonFollowing = true;
+ }
+ else
+ {
+ velocity = { 0, 0 };
+ app->map->pathfinding->ClearLastPath();
+ }
+ }
+ else if (summonSpawned && isSummonFollowing)
+ {
+ // idle movement
+ const int idleDistance = 2;
+
+ if (summonPosition.x >= initialIdlePosition.x + idleDistance * 32)
+ {
+ isSummonFacingRight = false;
+ }
+ else if (summonPosition.x <= initialIdlePosition.x - idleDistance * 32)
+ {
+ isSummonFacingRight = true;
+ }
+
+ velocity.x = isSummonFacingRight ? 1 : -1;
+ velocity.y = isSummonFacingRight ? -1 : 1;
+
+ summonPosition.x += velocity.x;
+ summonPosition.y += velocity.y;
+
+ currentSummonAnim = &ghostSummonIdleAnim;
+
+ if (path == app->map->pathfinding->GetLastPath()) app->map->pathfinding->ClearLastPath();
+
+ }
+
+ if (currentSummonAnim == &ghostSummonAppearAnim && currentSummonAnim->HasFinished() && summonSpawned)
+ {
+ isSummonFollowing = true;
+ currentSummonAnim = &ghostSummonIdleAnim;
+ }
+
+ summonPosition.x = METERS_TO_PIXELS(summonPbody->body->GetTransform().p.x);
+ summonPosition.y = METERS_TO_PIXELS(summonPbody->body->GetTransform().p.y);
+
+ summonPbody->body->SetLinearVelocity(velocity);
+
+ if (summonSpawned)
+ {
+ // draw light
+ if (isSummonFacingRight) app->render->DrawTexture(lightTexture, summonPosition.x - 60, summonPosition.y - 50);
+ else app->render->DrawTexture(lightTexture, summonPosition.x - 50, summonPosition.y - 50);
+
+ // draw summon
+ SDL_Rect summonRect = currentSummonAnim->GetCurrentFrame();
+ if (isSummonFollowing)
+ {
+ if (isSummonFacingRight) app->render->DrawTexture(texture, summonPosition.x - 100, summonPosition.y - 90, &summonRect, SDL_FLIP_NONE, 1.0f, -90);
+ else app->render->DrawTexture(texture, summonPosition.x - 100, summonPosition.y - 90, &summonRect, SDL_FLIP_HORIZONTAL, 1.0f, 90);
+ }
+ else
+ {
+ if (isSummonFacingRight) app->render->DrawTexture(texture, summonPosition.x - 100, summonPosition.y - 90, &summonRect);
+ else app->render->DrawTexture(texture, summonPosition.x - 100, summonPosition.y - 90, &summonRect, SDL_FLIP_HORIZONTAL);
+ }
+ currentSummonAnim->Update();
+ }
+
+ // draw path
+ if (app->physics->debug)
+ {
+ const DynArray* path = app->map->pathfinding->GetLastPath();
+ for (uint i = 0; i < path->Count(); ++i)
+ {
+ iPoint pos = app->map->MapToWorld(path->At(i)->x, path->At(i)->y);
+ app->render->DrawTexture(pathTexture, pos.x, pos.y);
+ }
+ }
+
+ return true;
+}
+
+bool Ghost::CleanUp()
+{
+ return true;
+}
+
+void Ghost::OnCollision(PhysBody* physA, PhysBody* physB)
+{
+ switch (physB->ctype)
+ {
+
+ }
+}
+
+void Ghost::LoadAnimations()
+{
+ ghostAttackAnim.LoadAnimations("ghostAttackAnim", "ghost");
+ ghostDeadAnim.LoadAnimations("ghostDeadAnim", "ghost");
+ ghostIdleAnim.LoadAnimations("ghostIdleAnim", "ghost");
+ ghostIdle2Anim.LoadAnimations("ghostIdle2Anim", "ghost");
+ ghosSkillAnim.LoadAnimations("ghosSkillAnim", "ghost");
+ ghostSummonAnim.LoadAnimations("ghostSummonAnim", "ghost");
+
+ ghostSummonIdleAnim.LoadAnimations("ghostSummonIdleAnim", "ghost");
+ ghostSummonAppearAnim.LoadAnimations("ghostSummonAppearAnim", "ghost");
+ ghostSummonDeathAnim.LoadAnimations("ghostSummonDeathAnim", "ghost");
+
+ currentAnim = &ghostSummonAnim;
+ currentSummonAnim = &ghostSummonAppearAnim;
+}
+
+void Ghost::Move(const iPoint& origin, const iPoint& destination) {
+
+ float xDiff = destination.x - origin.x;
+ float yDiff = destination.y - origin.y;
+
+ velocity.x = (xDiff < 0) ? -2 : (xDiff > 0) ? 2 : 0;
+ velocity.y = (yDiff < 0) ? -2 : (yDiff > 0) ? 2 : 0;
+
+ isSummonFacingRight = (xDiff > 0);
+
+}
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/Ghost.h b/PlatformerGame/Game/Source/Ghost.h
new file mode 100644
index 0000000..4dfa9f9
--- /dev/null
+++ b/PlatformerGame/Game/Source/Ghost.h
@@ -0,0 +1,81 @@
+#ifndef __GHOST_H__
+#define __GHOST_H__
+
+#include "Entity.h"
+#include "Point.h"
+#include "Physics.h"
+#include "SDL/include/SDL.h"
+#include "Animation.h"
+#include "Point.h"
+#include "DynArray.h"
+
+struct SDL_Texture;
+
+class Ghost : public Entity
+{
+public:
+
+ Ghost();
+ virtual ~Ghost();
+
+ bool Awake();
+
+ bool Start();
+
+ bool Update(float dt);
+
+ bool CleanUp();
+
+ void OnCollision(PhysBody* physA, PhysBody* physB);
+
+ void LoadAnimations();
+
+ void Move(const iPoint& origin, const iPoint& destination);
+
+public:
+ float speed = 0.2f;
+ bool isActivated = false;
+ bool isFacingRight = false;
+ bool isSummonFacingRight = false;
+ bool isSummonFollowing = false;
+ int ghostSummonFxId;
+
+ iPoint originPos;
+ b2Vec2 velocity;
+
+ iPoint summonOriginPos;
+ b2Vec2 summonVelocity;
+
+private:
+
+ Animation* currentAnim;
+ Animation* currentSummonAnim;
+
+ Animation ghostAttackAnim, ghostDeadAnim, ghostIdleAnim, ghostIdle2Anim, ghosSkillAnim, ghostSummonAnim;
+ Animation ghostSummonIdleAnim, ghostSummonAppearAnim, ghostSummonDeathAnim;
+
+ SDL_Texture* texture;
+ SDL_Texture* lightTexture;
+ SDL_Texture* bigLightTexture;
+ SDL_Texture* pathTexture;
+ const char* texturePath;
+ const char* lightTexturePath;
+ const char* bigLightTexturePath;
+ PhysBody* pbody;
+ PhysBody* summonPbody;
+ b2Transform initialTransform, initialSummonTransform;
+ iPoint summonPosition;
+
+ iPoint playerTilePos;
+ iPoint summonTilePos;
+ iPoint nextTilePath;
+
+ float distance;
+ bool summonSpawned = false;
+
+ iPoint initialIdlePosition;
+
+ const DynArray* path;
+};
+
+#endif // __GHOST_H__
diff --git a/PlatformerGame/Game/Source/Jumper.cpp b/PlatformerGame/Game/Source/Jumper.cpp
index 848a73d..a05f602 100644
--- a/PlatformerGame/Game/Source/Jumper.cpp
+++ b/PlatformerGame/Game/Source/Jumper.cpp
@@ -22,6 +22,8 @@ bool Jumper::Awake() {
position.x = parameters.attribute("x").as_int();
position.y = parameters.attribute("y").as_int();
texturePath = parameters.attribute("texturepath").as_string();
+ jumperAudio1FxId = app->audio->LoadFx(parameters.child("boingAudio1").attribute("path").as_string());
+ jumperAudio2FxId = app->audio->LoadFx(parameters.child("boingAudio2").attribute("path").as_string());
return true;
}
@@ -34,8 +36,8 @@ bool Jumper::Start() {
pbody->ctype = ColliderType::JUMP;
pbody->listener = this;
- jumperIdleAnim.LoadAnimations("jumperIdleAnim");
- jumperAnim.LoadAnimations("jumperAnim");
+ jumperIdleAnim.LoadAnimations("jumperIdleAnim", "jumper");
+ jumperAnim.LoadAnimations("jumperAnim", "jumper");
currentAnim = &jumperIdleAnim;
@@ -52,6 +54,17 @@ bool Jumper::Update(float dt)
{
currentAnim->Reset();
currentAnim = &jumperAnim;
+ int random = rand() % 2;
+ switch (random)
+ {
+ case 0:
+ app->audio->PlayFx(jumperAudio1FxId);
+ break;
+ case 1:
+ app->audio->PlayFx(jumperAudio2FxId);
+ break;
+
+ }
isActivated = false;
}
diff --git a/PlatformerGame/Game/Source/Jumper.h b/PlatformerGame/Game/Source/Jumper.h
index 8897ac9..d26b2f3 100644
--- a/PlatformerGame/Game/Source/Jumper.h
+++ b/PlatformerGame/Game/Source/Jumper.h
@@ -28,6 +28,8 @@ class Jumper : public Entity
public:
bool isActivated = false;
+ int jumperAudio1FxId;
+ int jumperAudio2FxId;
private:
diff --git a/PlatformerGame/Game/Source/Item.cpp b/PlatformerGame/Game/Source/Key.cpp
similarity index 83%
rename from PlatformerGame/Game/Source/Item.cpp
rename to PlatformerGame/Game/Source/Key.cpp
index 10d5a88..44c2c7e 100644
--- a/PlatformerGame/Game/Source/Item.cpp
+++ b/PlatformerGame/Game/Source/Key.cpp
@@ -1,4 +1,4 @@
-#include "Item.h"
+#include "Key.h"
#include "App.h"
#include "Textures.h"
#include "Audio.h"
@@ -10,14 +10,14 @@
#include "Physics.h"
#include "EntityManager.h"
-Item::Item() : Entity(EntityType::ITEM)
+Key::Key() : Entity(EntityType::KEY)
{
- name.Create("item");
+ name.Create("key");
}
-Item::~Item() {}
+Key::~Key() {}
-bool Item::Awake() {
+bool Key::Awake() {
position.x = parameters.attribute("x").as_int();
position.y = parameters.attribute("y").as_int();
@@ -26,22 +26,22 @@ bool Item::Awake() {
return true;
}
-bool Item::Start() {
+bool Key::Start() {
//initilize textures
texture = app->tex->Load(texturePath);
pbody = app->physics->CreateCircle(position.x + 16, position.y + 16, 16, bodyType::STATIC);
- pbody->ctype = ColliderType::ITEM;
+ pbody->ctype = ColliderType::KEY;
pbody->listener = this;
- keyIdleAnim.LoadAnimations("keyIdleAnim");
+ keyIdleAnim.LoadAnimations("keyIdleAnim", "key");
followTimer = 0.0f;
currentAnim = &keyIdleAnim;
return true;
}
-bool Item::Update(float dt)
+bool Key::Update(float dt)
{
if (isPicked) OnPicked();
@@ -54,12 +54,12 @@ bool Item::Update(float dt)
return true;
}
-bool Item::CleanUp()
+bool Key::CleanUp()
{
return true;
}
-void Item::OnCollision(PhysBody* physA, PhysBody* physB)
+void Key::OnCollision(PhysBody* physA, PhysBody* physB)
{
switch (physB->ctype)
{
@@ -71,7 +71,7 @@ void Item::OnCollision(PhysBody* physA, PhysBody* physB)
}
}
-void Item::OnPicked()
+void Key::OnPicked()
{
followTimer += 0.1f;
diff --git a/PlatformerGame/Game/Source/Item.h b/PlatformerGame/Game/Source/Key.h
similarity index 81%
rename from PlatformerGame/Game/Source/Item.h
rename to PlatformerGame/Game/Source/Key.h
index 0fcf9d9..a610d51 100644
--- a/PlatformerGame/Game/Source/Item.h
+++ b/PlatformerGame/Game/Source/Key.h
@@ -1,5 +1,5 @@
-#ifndef __ITEM_H__
-#define __ITEM_H__
+#ifndef __KEY_H__
+#define __KEY_H__
#include "Entity.h"
#include "Point.h"
@@ -8,12 +8,12 @@
struct SDL_Texture;
-class Item : public Entity
+class Key : public Entity
{
public:
- Item();
- virtual ~Item();
+ Key();
+ virtual ~Key();
bool Awake();
@@ -44,4 +44,4 @@ class Item : public Entity
Animation keyIdleAnim;
};
-#endif // __ITEM_H__
\ No newline at end of file
+#endif // __KEY_H__
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/LockDoor.cpp b/PlatformerGame/Game/Source/LockDoor.cpp
index 1791328..d440e19 100644
--- a/PlatformerGame/Game/Source/LockDoor.cpp
+++ b/PlatformerGame/Game/Source/LockDoor.cpp
@@ -23,6 +23,7 @@ bool LockDoor::Awake() {
position.x = parameters.attribute("x").as_int();
position.y = parameters.attribute("y").as_int();
texturePath = parameters.attribute("texturepath").as_string();
+ doorAudioFxId = app->audio->LoadFx(parameters.child("doorAudio").attribute("path").as_string());
return true;
}
@@ -31,12 +32,12 @@ bool LockDoor::Start() {
//initilize textures
texture = app->tex->Load(texturePath);
- pbody = app->physics->CreateRectangleSensor(position.x, position.y, 64, 64, bodyType::STATIC);
+ pbody = app->physics->CreateRectangleSensor(position.x, position.y, 32, 64, bodyType::STATIC);
pbody->ctype = ColliderType::DOOR;
pbody->listener = this;
- doorIdleAnim.LoadAnimations("doorIdleAnim");
- doorOpenAnim.LoadAnimations("doorOpenAnim");
+ doorIdleAnim.LoadAnimations("doorIdleAnim", "door");
+ doorOpenAnim.LoadAnimations("doorOpenAnim", "door");
currentAnim = &doorIdleAnim;
@@ -45,18 +46,24 @@ bool LockDoor::Start() {
bool LockDoor::Update(float dt)
{
- position.x = METERS_TO_PIXELS(pbody->body->GetTransform().p.x) - 192/2;
- position.y = METERS_TO_PIXELS(pbody->body->GetTransform().p.y) - 128/2;
+ position.x = METERS_TO_PIXELS(pbody->body->GetTransform().p.x) - 192 / 2;
+ position.y = METERS_TO_PIXELS(pbody->body->GetTransform().p.y) - 128 / 2;
if (isActivated)
{
isActivated = false;
currentAnim = &doorOpenAnim;
+ app->audio->PlayFx(doorAudioFxId);
}
- if (currentAnim == &doorOpenAnim && currentAnim->HasFinished())
+ if (currentAnim == &doorOpenAnim && currentAnim->GetCurrentFrameCount() >= 4 && !fade)
{
+ fade = true;
app->fade->Fade(2, 60);
+ }
+
+ if (currentAnim == &doorOpenAnim && currentAnim->HasFinished())
+ {
app->physics->world->DestroyBody(pbody->body);
app->entityManager->DestroyEntity(this);
}
@@ -83,6 +90,7 @@ void LockDoor::OnCollision(PhysBody* physA, PhysBody* physB)
{
isActivated = true;
app->scene->player->keys--;
+ app->scene->player->enterDoor = true;
}
break;
}
diff --git a/PlatformerGame/Game/Source/LockDoor.h b/PlatformerGame/Game/Source/LockDoor.h
index 29c9cc0..b830d96 100644
--- a/PlatformerGame/Game/Source/LockDoor.h
+++ b/PlatformerGame/Game/Source/LockDoor.h
@@ -29,6 +29,8 @@ class LockDoor : public Entity
public:
bool isActivated = false;
+ bool fade = false;
+ int doorAudioFxId;
private:
diff --git a/PlatformerGame/Game/Source/LogObstacle.cpp b/PlatformerGame/Game/Source/LogObstacle.cpp
new file mode 100644
index 0000000..ff6dca9
--- /dev/null
+++ b/PlatformerGame/Game/Source/LogObstacle.cpp
@@ -0,0 +1,103 @@
+#include "LogObstacle.h"
+#include "App.h"
+#include "Textures.h"
+#include "Audio.h"
+#include "Input.h"
+#include "Render.h"
+#include "Scene.h"
+#include "Log.h"
+#include "Point.h"
+#include "Physics.h"
+#include "EntityManager.h"
+#include "FadeToBlack.h"
+
+LogObstacle::LogObstacle() : Entity(EntityType::LOG_OBSTACLE)
+{
+ name.Create("log");
+}
+
+LogObstacle::~LogObstacle() {}
+
+bool LogObstacle::Awake() {
+
+ position.x = parameters.attribute("x").as_int();
+ position.y = parameters.attribute("y").as_int();
+ texturePath = parameters.attribute("texturepath").as_string();
+ logAudioKnock1FxId = app->audio->LoadFx(parameters.child("logAudioKnock1").attribute("path").as_string());
+ logAudioKnock2FxId = app->audio->LoadFx(parameters.child("logAudioKnock2").attribute("path").as_string());
+ logAudioKnock3FxId = app->audio->LoadFx(parameters.child("logAudioKnock3").attribute("path").as_string());
+ logAudioBreakFxId = app->audio->LoadFx(parameters.child("logAudioBreak").attribute("path").as_string());
+
+ return true;
+}
+
+bool LogObstacle::Start() {
+
+ //initilize textures
+ texture = app->tex->Load(texturePath);
+ pbody = app->physics->CreateRectangle(position.x + 270, position.y + 200, 100, 130, bodyType::DYNAMIC);
+ pbody->body->SetGravityScale(0);
+ pbody->ctype = ColliderType::LOG_OBSTACLE;
+ pbody->listener = this;
+ pbody->body->SetFixedRotation(true);
+
+ logIdleAnim.LoadAnimations("logIdleAnim", "log");
+ logDownAnim.LoadAnimations("logDownAnim", "log");
+ logDownIdle.LoadAnimations("logDownIdle", "log");
+ currentAnim = &logIdleAnim;
+
+ initialPosition.x = (pbody->body->GetTransform().p.x);
+ initialPosition.y = (pbody->body->GetTransform().p.y);
+
+ return true;
+}
+
+bool LogObstacle::Update(float dt)
+{
+ pbody->body->SetTransform(initialPosition, 0);
+
+ if(app->input->GetKey(SDL_SCANCODE_H) == KEY_DOWN) health -= 1;
+ if (health <= 0 && logUp) {
+ currentAnim= &logDownAnim;
+ logUp = false;
+ }
+ if (!logUp && currentAnim == &logDownAnim && currentAnim->HasFinished()) {
+ pbody->body->SetActive(false);
+ currentAnim = &logDownIdle;
+ }
+
+ if (!logUp && app->scene->player->position.x > (position.x + 100) && !changeLevel)
+ {
+ app->scene->newCameraIdx = 3;
+ app->fade->Fade(3, 60);
+ changeLevel = true;
+ }
+
+ position.x = METERS_TO_PIXELS(pbody->body->GetTransform().p.x) - 124;
+ position.y = METERS_TO_PIXELS(pbody->body->GetTransform().p.y) - 120;
+
+ app->render->DrawTexture(texture, position.x - 30, position.y, ¤tAnim->GetCurrentFrame());
+
+ currentAnim->Update();
+ return true;
+}
+
+bool LogObstacle::CleanUp()
+{
+ return true;
+}
+
+void LogObstacle::OnCollision(PhysBody* physA, PhysBody* physB)
+{
+ switch (physB->ctype)
+ {
+ case ColliderType::SWORD:
+ health -= 1;
+ if (health == 3) app->audio->PlayFx(logAudioKnock1FxId);
+ if (health == 2) app->audio->PlayFx(logAudioKnock2FxId);
+ if (health == 1) app->audio->PlayFx(logAudioKnock3FxId);
+ if (health <= 0) app->audio->PlayFx(logAudioBreakFxId);
+
+ break;
+ }
+}
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/LogObstacle.h b/PlatformerGame/Game/Source/LogObstacle.h
new file mode 100644
index 0000000..963a498
--- /dev/null
+++ b/PlatformerGame/Game/Source/LogObstacle.h
@@ -0,0 +1,58 @@
+#ifndef __LOGOBSTACLE_H__
+#define __LOGOBSTACLE_H__
+
+#include "Entity.h"
+#include "Point.h"
+#include "SDL/include/SDL.h"
+#include "Animation.h"
+#include "Physics.h"
+
+struct SDL_Texture;
+
+class LogObstacle : public Entity
+{
+public:
+
+ LogObstacle();
+ virtual ~LogObstacle();
+
+ bool Awake();
+
+ bool Start();
+
+ bool Update(float dt);
+
+ bool CleanUp();
+
+ void OnCollision(PhysBody* physA, PhysBody* physB);
+
+
+public:
+
+ bool isPicked = false;
+ float followTimer = 0.0f;
+ float acceleration = 1.0f;
+ int health = 4;
+ bool logUp = true;
+ bool changeLevel = false;
+ int logAudioKnock1FxId;
+ int logAudioKnock2FxId;
+ int logAudioKnock3FxId;
+ int logAudioBreakFxId;
+
+
+private:
+
+ SDL_Texture* texture;
+ const char* texturePath;
+ PhysBody* pbody;
+
+ Animation* currentAnim;
+ Animation logIdleAnim;
+ Animation logDownAnim;
+ Animation logDownIdle;
+
+ b2Vec2 initialPosition;
+};
+
+#endif // __LOGOBSTACLE_H__
\ No newline at end of file
diff --git a/PlatformerGame/Game/Source/Map.cpp b/PlatformerGame/Game/Source/Map.cpp
index 03c6001..e470827 100644
--- a/PlatformerGame/Game/Source/Map.cpp
+++ b/PlatformerGame/Game/Source/Map.cpp
@@ -4,6 +4,7 @@
#include "Textures.h"
#include "Map.h"
#include "Physics.h"
+#include "Scene.h"
#include "Defs.h"
#include "Log.h"
@@ -11,6 +12,7 @@
#include
#include "SDL_image/include/SDL_image.h"
+
Map::Map() : Module(), mapLoaded(false)
{
name.Create("map");
@@ -34,93 +36,89 @@ bool Map::Start() {
//Calls the functon to load the map, make sure that the filename is assigned
SString mapPath = path;
mapPath += name;
- bool ret = Load(mapPath);
+ Load(mapPath);
- return ret;
+ //Initialize the pathfinding
+ pathfinding = new PathFinding();
+
+ //Initialize the navigation map
+ uchar* navigationMap = NULL;
+ CreateNavigationMap(mapData.width, mapData.height, &navigationMap);
+ pathfinding->SetNavigationMap((uint)mapData.width, (uint)mapData.height, navigationMap);
+ RELEASE_ARRAY(navigationMap);
+
+ UpdateMapSize();
+
+ return true;
}
bool Map::Update(float dt)
{
- if(mapLoaded == false)
+ bool ret = true;
+
+ if (mapLoaded == false)
return false;
- ListItem* mapLayerItem;
- mapLayerItem = mapData.maplayers.start;
+ ListItem* mapLayer;
+ mapLayer = mapData.layers.start;
- while (mapLayerItem != NULL) {
+ // iterates the layers in the map
+ while (mapLayer != NULL) {
+ //Check if the property Draw exist get the value, if it's true draw the lawyer
+ if (mapLayer->data->properties.GetProperty("Draw") != NULL && mapLayer->data->properties.GetProperty("Draw")->value) {
+ //iterate all tiles in a layer
- if (mapLayerItem->data->properties.GetProperty("Draw") != NULL && mapLayerItem->data->properties.GetProperty("Draw")->value) {
+ UpdateTileLoadSize();
+
+ for (int i = startWidth; i < endWidth; i++) {
+ for (int j = startHeight; j < endHeight; j++) {
+ //Get the gid from tile
+ int gid = mapLayer->data->Get(i, j);
- for (int x = 0; x < mapLayerItem->data->width; x++)
- {
- for (int y = 0; y < mapLayerItem->data->height; y++)
- {
- int gid = mapLayerItem->data->Get(x, y);
- TileSet* tileset = GetTilesetFromTileId(gid);
- SDL_Rect r = tileset->GetTileRect(gid);
- iPoint pos = MapToWorld(x, y);
+ TileSet* tileSet = GetTilesetFromTileId(gid);
+ SDL_Rect tileRect = tileSet->GetRect(gid);
+
+ iPoint mapCoord = MapToWorld(i, j);
+
+ app->render->DrawTexture(tileSet->texture, mapCoord.x, mapCoord.y, &tileRect);
- app->render->DrawTexture(tileset->texture,
- pos.x,
- pos.y,
- &r);
}
}
}
- mapLayerItem = mapLayerItem->next;
-
+ mapLayer = mapLayer->next;
}
- return true;
-}
-
-iPoint Map::MapToWorld(int x, int y) const
-{
- iPoint ret;
-
- ret.x = x * mapData.tileWidth;
- ret.y = y * mapData.tileHeight;
-
- return ret;
-}
-
-iPoint Map::WorldToMap(int x, int y)
-{
- iPoint ret(0, 0);
-
- //
-
- return ret;
-}
-
-// Get relative Tile rectangle
-SDL_Rect TileSet::GetTileRect(int gid) const
-{
- SDL_Rect rect = { 0 };
- int relativeIndex = gid - firstgid;
-
- rect.w = tileWidth;
- rect.h = tileHeight;
- rect.x = margin + (tileWidth + spacing) * (relativeIndex % columns);
- rect.y = margin + (tileWidth + spacing) * (relativeIndex / columns);
+ if (!app->scene->player->wallRight && !app->scene->player->wallLeft)
+ {
+ for (int i = 0; i < wallEndCollision.Count(); i++)
+ {
+ PhysBody* wall = wallEndCollision.At(i)->data;
+ wall->body->SetActive(false);
+ }
+ }
+ else if (app->scene->player->wallRight || app->scene->player->wallLeft)
+ {
+ for (int i = 0; i < wallEndCollision.Count(); i++)
+ {
+ PhysBody* wall = wallEndCollision.At(i)->data;
+ wall->body->SetActive(true);
+ }
+ }
- return rect;
+ return true;
}
TileSet* Map::GetTilesetFromTileId(int gid) const
{
- ListItem* item = mapData.tilesets.start;
TileSet* set = NULL;
- while (item)
- {
- set = item->data;
- if (gid < (item->data->firstgid + item->data->tilecount))
- {
- break;
- }
- item = item->next;
+ ListItem* tileSet;
+ tileSet = mapData.tilesets.start;
+ while (tileSet != NULL) {
+ set = tileSet->data;
+ if (gid >= tileSet->data->firstgid && gid < (tileSet->data->firstgid + tileSet->data->tilecount)) break;
+ tileSet = tileSet->next;
}
return set;
@@ -131,31 +129,33 @@ bool Map::CleanUp()
{
LOG("Unloading map");
+ //Clean up pathfing class
+ pathfinding->CleanUp();
+
+ // Remove all tilesets
+ ListItem* item;
+ item = mapData.tilesets.start;
+
+ while (item != NULL)
+ {
+ RELEASE(item->data);
+ item = item->next;
+ }
+ mapData.tilesets.Clear();
+
// Remove all layers
ListItem* layerItem;
- layerItem = mapData.maplayers.start;
+ layerItem = mapData.layers.start;
while (layerItem != NULL)
{
- RELEASE_ARRAY(layerItem->data->data);
RELEASE(layerItem->data);
layerItem = layerItem->next;
}
- mapData.maplayers.Clear();
-
- // Remove all tilesets
- ListItem* tilesetItem;
- tilesetItem = mapData.tilesets.start;
-
- while (tilesetItem != NULL)
- {
- app->tex->UnLoad(tilesetItem->data->texture);
- RELEASE(tilesetItem->data);
- tilesetItem = tilesetItem->next;
- }
- mapData.tilesets.Clear();
+ mapData.layers.Clear();
DestroyAllColliders();
+
return true;
}
@@ -164,204 +164,258 @@ bool Map::Load(SString mapFileName)
{
bool ret = true;
+ // retrieve the paremeters of the