Made the hurt hazard work better.
This commit is contained in:
		@@ -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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
       */
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/dawn/physics/2d/Physics2D.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/dawn/physics/2d/Physics2D.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,10 +16,6 @@ void CharacterController2D::onStart() {
 | 
			
		||||
  useEvent([&](float_t delta){
 | 
			
		||||
    // Common variables
 | 
			
		||||
    auto myCollider = item->getComponent<Collider2D>();
 | 
			
		||||
    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<float_t>(moveAmount.x) <= 0.001f &&
 | 
			
		||||
      mathAbs<float_t>(moveAmount.y) <= 0.001f
 | 
			
		||||
    ) return;
 | 
			
		||||
    // if(
 | 
			
		||||
    //   mathAbs<float_t>(moveAmount.x) <= 0.001f &&
 | 
			
		||||
    //   mathAbs<float_t>(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);
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -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<BoxCollider*>(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,
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,8 @@ bool_t TriggerController2D::getCollidingResult(Collider2D* movingObject) {
 | 
			
		||||
          auto box2 = dynamic_cast<BoxCollider*>(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
 | 
			
		||||
          );
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@ namespace Dawn {
 | 
			
		||||
  class TriggerController2D : public SceneItemComponent {
 | 
			
		||||
    public:
 | 
			
		||||
      Collider2D *collider = nullptr;
 | 
			
		||||
 | 
			
		||||
      StateEvent<CharacterController2D*> eventTriggerEnter;
 | 
			
		||||
 | 
			
		||||
      TriggerController2D(SceneItem *i);
 | 
			
		||||
 
 | 
			
		||||
@@ -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<EntityFaction>();
 | 
			
		||||
      if(otherFaction != nullptr && faction == otherFaction->faction) return;
 | 
			
		||||
 | 
			
		||||
      // Check health
 | 
			
		||||
      auto otherHealth = controller->item->getComponent<EntityHealth>();
 | 
			
		||||
      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)();
 | 
			
		||||
}
 | 
			
		||||
@@ -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<void()> evtTriggerEnter;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
      // @optional
 | 
			
		||||
      float_t hitKnockback = 20.0f;
 | 
			
		||||
      // @optional
 | 
			
		||||
      int32_t damage = 1;
 | 
			
		||||
      enum Faction faction = FACTION_NONE;
 | 
			
		||||
      // @optional
 | 
			
		||||
      StateProperty<TriggerController2D*> trigger;
 | 
			
		||||
      
 | 
			
		||||
      HurtHazard(SceneItem* item);
 | 
			
		||||
 | 
			
		||||
      void onStart() override;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -11,13 +11,6 @@ EntityHealth::EntityHealth(SceneItem* item) : SceneItemComponent(item) {
 | 
			
		||||
  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<SceneItemComponent*> EntityHealth::getDependencies() {
 | 
			
		||||
  return {
 | 
			
		||||
    this->characterController = this->item->getComponent<CharacterController2D>(),
 | 
			
		||||
    this->entityFaction = this->item->getComponent<EntityFaction>()
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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<HurtHazard>();
 | 
			
		||||
    if(hurtHazard == nullptr) return;
 | 
			
		||||
    if(
 | 
			
		||||
      entityFaction != nullptr &&
 | 
			
		||||
      hurtHazard->faction == this->entityFaction->faction
 | 
			
		||||
    ) return;
 | 
			
		||||
  //     auto hurtHazard = info.collider->item->getComponent<HurtHazard>();
 | 
			
		||||
  //     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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<SceneItemComponent*> getDependencies() override;
 | 
			
		||||
      void onStart() override;
 | 
			
		||||
 | 
			
		||||
      /**
 | 
			
		||||
 
 | 
			
		||||
@@ -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));
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user