diff --git a/assets/games/rose/prefabs/Urchin.xml b/assets/games/rose/prefabs/Urchin.xml
index 0b8e0dfb..500e52a4 100644
--- a/assets/games/rose/prefabs/Urchin.xml
+++ b/assets/games/rose/prefabs/Urchin.xml
@@ -1,10 +1,19 @@
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/games/rose/textures/Urchin.png b/assets/games/rose/textures/Urchin.png
new file mode 100644
index 00000000..a562f6f1
Binary files /dev/null and b/assets/games/rose/textures/Urchin.png differ
diff --git a/src/dawn/display/Transform.cpp b/src/dawn/display/Transform.cpp
index c01a9218..710de272 100644
--- a/src/dawn/display/Transform.cpp
+++ b/src/dawn/display/Transform.cpp
@@ -175,6 +175,15 @@ Transform * Transform::getParent() {
return this->parent;
}
+bool_t Transform::isChildOf(Transform *parent) {
+ Transform *current = this->getParent();
+ while(current != nullptr) {
+ if(current == parent) return true;
+ current = current->getParent();
+ }
+ return false;
+}
+
Transform::~Transform() {
this->setParent(nullptr);
diff --git a/src/dawn/display/Transform.hpp b/src/dawn/display/Transform.hpp
index e3708b8a..4a0f9562 100644
--- a/src/dawn/display/Transform.hpp
+++ b/src/dawn/display/Transform.hpp
@@ -162,6 +162,15 @@ namespace Dawn {
*/
Transform * getParent();
+ /**
+ * Returns true if this transform is a child of the given transform, this
+ * climbs up the heirarchy until it finds a match.
+ *
+ * @param p Transform to check if this transform is a child of.
+ * @return True if this transform is a child of the given transform.
+ */
+ bool_t isChildOf(Transform *p);
+
/**
* Dispose and clenaup this transform, also removes self from parent.
*/
diff --git a/src/dawn/physics/2d/Box.cpp b/src/dawn/physics/2d/Box.cpp
index e51da607..52cd74ae 100644
--- a/src/dawn/physics/2d/Box.cpp
+++ b/src/dawn/physics/2d/Box.cpp
@@ -85,15 +85,13 @@ bool_t Dawn::boxIsBoxColliding(
glm::vec2 posB, glm::vec2 minB, glm::vec2 maxB
) {
// Check for no overlap in X axis
- if (posA.x + maxA.x < posB.x + minB.x || posA.x + minA.x > posB.x + maxB.x) {
+ if (posA.x + maxA.x < posB.x + minB.x || posB.x + maxB.x < posA.x + minA.x) {
return false;
}
// Check for no overlap in Y axis
- if (posA.y + maxA.y < posB.y + minB.y || posA.y + minA.y > posB.y + maxB.y) {
+ if (posA.y + maxA.y < posB.y + minB.y || posB.y + maxB.y < posA.y + minA.y) {
return false;
}
-
- // There is overlap in both X and Y axis, so the boxes are colliding
return true;
}
\ No newline at end of file
diff --git a/src/dawn/physics/2d/Physics2D.hpp b/src/dawn/physics/2d/Physics2D.hpp
new file mode 100644
index 00000000..3c1872d2
--- /dev/null
+++ b/src/dawn/physics/2d/Physics2D.hpp
@@ -0,0 +1,13 @@
+// Copyright (c) 2023 Dominic Masters
+//
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "dawnlibs.hpp"
+
+namespace Dawn {
+ static inline glm::vec2 physics3Dto2D(glm::vec3 v) {
+ return glm::vec2(v.x, v.z);
+ }
+}
\ No newline at end of file
diff --git a/src/dawn/scene/components/physics/2d/BoxCollider.hpp b/src/dawn/scene/components/physics/2d/BoxCollider.hpp
index 903b6a05..edf2d80c 100644
--- a/src/dawn/scene/components/physics/2d/BoxCollider.hpp
+++ b/src/dawn/scene/components/physics/2d/BoxCollider.hpp
@@ -6,6 +6,7 @@
#pragma once
#include "Collider2D.hpp"
#include "physics/2d/Box.hpp"
+#include "physics/2d/Physics2D.hpp"
namespace Dawn {
class BoxCollider : public Collider2D {
diff --git a/src/dawn/scene/components/physics/2d/CharacterController2D.cpp b/src/dawn/scene/components/physics/2d/CharacterController2D.cpp
index bf72d931..21fafefa 100644
--- a/src/dawn/scene/components/physics/2d/CharacterController2D.cpp
+++ b/src/dawn/scene/components/physics/2d/CharacterController2D.cpp
@@ -16,10 +16,6 @@ void CharacterController2D::onStart() {
useEvent([&](float_t delta){
// Common variables
auto myCollider = item->getComponent();
- glm::vec2 currentPosition(
- this->transform->getLocalPosition().x,
- this->transform->getLocalPosition().z
- );
// Friction
velocity -= velocity * friction * delta;
@@ -40,7 +36,7 @@ void CharacterController2D::onStart() {
while(itColliders != allColliders.end()) {
auto c = *itColliders;
++itColliders;
- if(c->item == this->item) continue;
+ if(c->item == this->item || c->transform->isChildOf(this->transform)) continue;
result = c->getCollidingResult(
velocity,
myCollider,
@@ -66,10 +62,10 @@ void CharacterController2D::onStart() {
}
}
- if(
- mathAbs(moveAmount.x) <= 0.001f &&
- mathAbs(moveAmount.y) <= 0.001f
- ) return;
+ // if(
+ // mathAbs(moveAmount.x) <= 0.001f &&
+ // mathAbs(moveAmount.y) <= 0.001f
+ // ) return;
transform->setLocalPosition(
transform->getLocalPosition() + (glm::vec3(moveAmount.x, 0, moveAmount.y) * delta)
@@ -81,7 +77,7 @@ void CharacterController2D::onStart() {
while(itTriggers != allTriggers.end()) {
auto c = *itTriggers;
++itTriggers;
- if(c->item == this->item) continue;
+ if(c->item == this->item || c->transform->isChildOf(this->transform)) continue;
if(c->getCollidingResult(myCollider)) {
c->eventTriggerEnter.invoke(this);
}
diff --git a/src/dawn/scene/components/physics/2d/SolidController2D.cpp b/src/dawn/scene/components/physics/2d/SolidController2D.cpp
index 1dca0682..265f8690 100644
--- a/src/dawn/scene/components/physics/2d/SolidController2D.cpp
+++ b/src/dawn/scene/components/physics/2d/SolidController2D.cpp
@@ -29,8 +29,7 @@ bool_t SolidController2D::getCollidingResult(
assertNotNull(movingObject);
if(movement.x == 0 && movement.y == 0) return false;
- auto localPos = movingObject->transform->getWorldPosition();
- glm::vec2 myPos(localPos.x, localPos.z);
+ auto myPos = physics3Dto2D(movingObject->transform->getWorldPosition());
// Check what the moving object is
switch(movingObject->getColliderType()) {
@@ -43,8 +42,7 @@ bool_t SolidController2D::getCollidingResult(
case COLLIDER2D_TYPE_BOX: {
auto box2 = dynamic_cast(this->collider);
assertNotNull(box2);
- auto localPos2 = box2->transform->getWorldPosition();
- glm::vec2 otherPos(localPos2.x, localPos2.z);
+ auto otherPos = physics3Dto2D(box2->transform->getWorldPosition());
return boxCheckCollision(
myPos, box1->min, box1->max,
diff --git a/src/dawn/scene/components/physics/2d/TriggerController2D.cpp b/src/dawn/scene/components/physics/2d/TriggerController2D.cpp
index 0e3b303d..a0e1a6bb 100644
--- a/src/dawn/scene/components/physics/2d/TriggerController2D.cpp
+++ b/src/dawn/scene/components/physics/2d/TriggerController2D.cpp
@@ -32,8 +32,8 @@ bool_t TriggerController2D::getCollidingResult(Collider2D* movingObject) {
auto box2 = dynamic_cast(collider);
assertNotNull(box2);
return boxIsBoxColliding(
- box1->transform->getWorldPosition(), box1->min, box1->max,
- box2->transform->getWorldPosition(), box2->min, box2->max
+ physics3Dto2D(box1->transform->getWorldPosition()), box1->min, box1->max,
+ physics3Dto2D(box2->transform->getWorldPosition()), box2->min, box2->max
);
}
diff --git a/src/dawn/scene/components/physics/2d/TriggerController2D.hpp b/src/dawn/scene/components/physics/2d/TriggerController2D.hpp
index 00b14d97..3cbefcb1 100644
--- a/src/dawn/scene/components/physics/2d/TriggerController2D.hpp
+++ b/src/dawn/scene/components/physics/2d/TriggerController2D.hpp
@@ -13,7 +13,6 @@ namespace Dawn {
class TriggerController2D : public SceneItemComponent {
public:
Collider2D *collider = nullptr;
-
StateEvent eventTriggerEnter;
TriggerController2D(SceneItem *i);
diff --git a/src/dawnrose/scene/components/HurtHazard.cpp b/src/dawnrose/scene/components/HurtHazard.cpp
index b26f863d..05cd6ebe 100644
--- a/src/dawnrose/scene/components/HurtHazard.cpp
+++ b/src/dawnrose/scene/components/HurtHazard.cpp
@@ -7,5 +7,41 @@
using namespace Dawn;
-HurtHazard::HurtHazard(SceneItem* item) : SceneItemComponent(item) {}
+HurtHazard::HurtHazard(SceneItem* item) :
+ trigger(nullptr),
+ SceneItemComponent(item)
+{
+}
+void HurtHazard::onStart() {
+ this->evtTriggerEnter = [&]{};
+
+ useEffect([&]{
+ this->evtTriggerEnter();
+ if(this->trigger == nullptr) return;
+
+ this->evtTriggerEnter = useEvent([&](CharacterController2D *controller) {
+ // Check faction(s)
+ auto otherFaction = controller->item->getComponent();
+ if(otherFaction != nullptr && faction == otherFaction->faction) return;
+
+ // Check health
+ auto otherHealth = controller->item->getComponent();
+ if(otherHealth == nullptr) return;
+
+ // Damage
+ if(otherHealth->isInvincible()) return;
+
+ glm::vec2 back = (
+ physics3Dto2D(this->transform->getWorldPosition()) -
+ physics3Dto2D(controller->transform->getWorldPosition())
+ );
+ controller->velocity = back * -hitKnockback;
+ otherHealth->damage({
+ .amount = damage
+ });
+
+ std::cout << "Trigger" << std::endl;
+ }, this->trigger->eventTriggerEnter);
+ }, this->trigger)();
+}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/HurtHazard.hpp b/src/dawnrose/scene/components/HurtHazard.hpp
index 6c1f7aa0..947e75d1 100644
--- a/src/dawnrose/scene/components/HurtHazard.hpp
+++ b/src/dawnrose/scene/components/HurtHazard.hpp
@@ -6,13 +6,26 @@
#pragma once
#include "scene/SceneItemComponent.hpp"
#include "scene/components/entity/EntityFaction.hpp"
+#include "scene/components/physics/2d/TriggerController2D.hpp"
+#include "scene/components/entity/EntityHealth.hpp"
+#include "scene/components/entity/EntityFaction.hpp"
namespace Dawn {
class HurtHazard : public SceneItemComponent {
+ private:
+ std::function evtTriggerEnter;
+
public:
+ // @optional
+ float_t hitKnockback = 20.0f;
+ // @optional
int32_t damage = 1;
enum Faction faction = FACTION_NONE;
+ // @optional
+ StateProperty trigger;
HurtHazard(SceneItem* item);
+
+ void onStart() override;
};
}
\ No newline at end of file
diff --git a/src/dawnrose/scene/components/entity/EntityHealth.cpp b/src/dawnrose/scene/components/entity/EntityHealth.cpp
index 9c96b8cf..79a78339 100644
--- a/src/dawnrose/scene/components/entity/EntityHealth.cpp
+++ b/src/dawnrose/scene/components/entity/EntityHealth.cpp
@@ -11,13 +11,6 @@ EntityHealth::EntityHealth(SceneItem* item) : SceneItemComponent(item) {
}
-std::vector EntityHealth::getDependencies() {
- return {
- this->characterController = this->item->getComponent(),
- this->entityFaction = this->item->getComponent()
- };
-}
-
void EntityHealth::onStart() {
// Update
useEvent([&](float_t delta){
@@ -32,29 +25,31 @@ void EntityHealth::onStart() {
// Hurt Hazard Processing
- useEvent([&](struct CharacterController2DCollisionEventInfo info) {
- if(this->isInvincible()) return;
+ // if(this->characterController != nullptr) {
+ // useEvent([&](struct CharacterController2DCollisionEventInfo info) {
+ // if(this->isInvincible()) return;
- auto hurtHazard = info.collider->item->getComponent();
- if(hurtHazard == nullptr) return;
- if(
- entityFaction != nullptr &&
- hurtHazard->faction == this->entityFaction->faction
- ) return;
+ // auto hurtHazard = info.collider->item->getComponent();
+ // if(hurtHazard == nullptr) return;
+ // if(
+ // entityFaction != nullptr &&
+ // hurtHazard->faction == this->entityFaction->faction
+ // ) return;
- glm::vec2 back = glm::vec2(
- info.collider->transform->getLocalPosition().x,
- info.collider->transform->getLocalPosition().z
- ) - glm::vec2(
- this->transform->getLocalPosition().x,
- this->transform->getLocalPosition().z
- );
+ // glm::vec2 back = glm::vec2(
+ // info.collider->transform->getLocalPosition().x,
+ // info.collider->transform->getLocalPosition().z
+ // ) - glm::vec2(
+ // this->transform->getLocalPosition().x,
+ // this->transform->getLocalPosition().z
+ // );
- this->characterController->velocity = back * -hitKnockback;
- this->damage({
- .amount = hurtHazard->damage
- });
- }, this->characterController->eventCollision);
+ // this->characterController->velocity = back * -hitKnockback;
+ // this->damage({
+ // .amount = hurtHazard->damage
+ // });
+ // }, this->characterController->eventCollision);
+ // }
}
bool_t EntityHealth::isInvincible() {
diff --git a/src/dawnrose/scene/components/entity/EntityHealth.hpp b/src/dawnrose/scene/components/entity/EntityHealth.hpp
index 419a57b6..b93742c9 100644
--- a/src/dawnrose/scene/components/entity/EntityHealth.hpp
+++ b/src/dawnrose/scene/components/entity/EntityHealth.hpp
@@ -5,9 +5,7 @@
#pragma once
#include "scene/SceneItemComponent.hpp"
-#include "scene/components/entity/EntityFaction.hpp"
#include "scene/components/physics/2d/CharacterController2D.hpp"
-#include "scene/components/HurtHazard.hpp"
namespace Dawn {
struct DamageInformation {
@@ -17,10 +15,6 @@ namespace Dawn {
};
class EntityHealth : public SceneItemComponent {
- protected:
- EntityFaction *entityFaction = nullptr;
- CharacterController2D *characterController = nullptr;
-
public:
// @optional
int32_t health = 10;
@@ -30,11 +24,8 @@ namespace Dawn {
float_t invincibleTime = 0.0f;
// @optional
float_t stunTime = 0.0f;
- // @optional
- float_t hitKnockback = 20.0f;
EntityHealth(SceneItem* item);
- std::vector getDependencies() override;
void onStart() override;
/**
diff --git a/src/dawnrose/scenes/HelloWorldScene.hpp b/src/dawnrose/scenes/HelloWorldScene.hpp
index f469571a..91c27b6d 100644
--- a/src/dawnrose/scenes/HelloWorldScene.hpp
+++ b/src/dawnrose/scenes/HelloWorldScene.hpp
@@ -24,10 +24,8 @@ namespace Dawn {
auto player = Player::create(this);
- auto wall = Wall::create(this);
-
- // auto urchin = Urchin::create(this);
- // urchin->transform.setLocalPosition(glm::vec3(0, 0, -5));
+ auto urchin = Urchin::create(this);
+ urchin->transform.setLocalPosition(glm::vec3(0, 0, -5));
// auto crab = Crab::create(this);
// crab->transform.setLocalPosition(glm::vec3(3, 0, 0));
diff --git a/src/dawntools/prefabtool/PrefabRegistry.cpp b/src/dawntools/prefabtool/PrefabRegistry.cpp
index 9473d408..8f910ef5 100644
--- a/src/dawntools/prefabtool/PrefabRegistry.cpp
+++ b/src/dawntools/prefabtool/PrefabRegistry.cpp
@@ -64,7 +64,15 @@ struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type)
// Find each instance of "@optional" when it's used within a comment
// e.g. // @optional or /* @optional */ in the string data.
- std::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@optional\\s*(?:\\*\\/)?\\s*$", std::regex_constants::ECMAScript | std::regex_constants::multiline);
+
+ std::regex_constants::syntax_option_type regexFlags;
+ #if defined(__GNUC__)
+ regexFlags = std::regex_constants::ECMAScript | std::regex_constants::multiline;
+ #else
+ regexFlags = std::regex_constants::ECMAScript;
+ #endif
+
+ std::regex regex("^\\s*(?:\\/\\/|\\/\\*){1}\\s*\\@optional\\s*(?:\\*\\/)?\\s*$", regexFlags);
std::sregex_iterator it(data.begin(), data.end(), regex);
std::sregex_iterator end;
while(it != end) {
@@ -92,7 +100,7 @@ struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type)
auto variableString = data.substr(varStart, varLength);
// Now (should) be able to extract the type;
- std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", std::regex_constants::ECMAScript | std::regex_constants::multiline);
+ std::regex regex2("^\\s*(?:[\\S]+<)?([\\w*:_\\s]+)(?:[\\S]+)? (\\**[\\w]+)\\s*$", regexFlags);
std::smatch match;
if(!std::regex_search(variableString, match, regex2)) {
std::cout << "Failed to extract type and name from variable string! " << variableString << std::endl;