enhance the AI movement process
This commit is contained in:
parent
acf6ed6f73
commit
9068d4fb25
@ -2,7 +2,7 @@
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
@ -15,16 +15,11 @@ repos:
|
||||
- id: no-commit-to-branch
|
||||
args: [--branch, master, --branch, develop]
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v14.0.6
|
||||
rev: v15.0.7
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c++, c]
|
||||
args: ["-style=file"]
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.3.1
|
||||
hooks:
|
||||
- id: forbid-crlf
|
||||
- id: forbid-tabs
|
||||
#- repo: https://github.com/pocc/pre-commit-hooks
|
||||
# rev: v1.3.5
|
||||
# hooks:
|
||||
|
@ -6,39 +6,50 @@ export var direction = -1
|
||||
export var detect_edges = true
|
||||
export var speed = 25
|
||||
export var gravity = 9.8
|
||||
var timer := Timer.new()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if direction == 1:
|
||||
$AnimatedSprite.flip_h = true
|
||||
$FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
|
||||
$FloorChecker.enabled = detect_edges
|
||||
Event.connect("level_loaded", self, "_on_level_loaded")
|
||||
if direction == 1:
|
||||
$AnimatedSprite.flip_h = true
|
||||
$FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
|
||||
$FloorChecker.enabled = detect_edges
|
||||
Event.connect("level_loaded", self, "_on_level_loaded")
|
||||
|
||||
add_child(timer)
|
||||
timer.wait_time = 0.1
|
||||
var err = timer.connect("timeout", self, "_on_timer_timeout")
|
||||
if err == OK:
|
||||
timer.start()
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if is_on_wall() or not $FloorChecker.is_colliding() and is_on_floor() and $FloorChecker.enabled:
|
||||
direction *= -1
|
||||
$AnimatedSprite.flip_h = not $AnimatedSprite.flip_h
|
||||
$FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
|
||||
if is_on_wall() or not $FloorChecker.is_colliding() and is_on_floor() and $FloorChecker.enabled:
|
||||
direction *= -1
|
||||
$AnimatedSprite.flip_h = not $AnimatedSprite.flip_h
|
||||
$FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction
|
||||
|
||||
velocity.y += gravity
|
||||
velocity.x = speed * direction
|
||||
velocity = move_and_slide(velocity, Vector2.UP)
|
||||
velocity.y += gravity
|
||||
velocity.x = speed * direction
|
||||
velocity = move_and_slide(velocity, Vector2.UP)
|
||||
|
||||
for i in get_slide_count():
|
||||
var collision = get_slide_collision(i)
|
||||
if collision.collider.name == "Player":
|
||||
Event.emit_signal("player_touched", 3)
|
||||
for i in get_slide_count():
|
||||
var collision = get_slide_collision(i)
|
||||
if collision.collider.name == "Player":
|
||||
Event.emit_signal("player_touched", 3)
|
||||
|
||||
Event.emit_signal("object_updated", self.get_name(), "Walking", global_position, velocity)
|
||||
Event.emit_signal("report_object", self.get_name(), "Walking", global_position, velocity)
|
||||
Event.emit_signal("object_updated", self.get_name(), "Walking", global_position, velocity)
|
||||
|
||||
|
||||
func squash() -> void:
|
||||
Event.emit_signal("object_removed", self.get_name())
|
||||
queue_free()
|
||||
Event.emit_signal("object_removed", self.get_name())
|
||||
queue_free()
|
||||
|
||||
|
||||
func _on_level_loaded() -> void:
|
||||
Event.emit_signal("object_created", self.get_name(), "Walking", global_position, Vector2(0, 0))
|
||||
Event.emit_signal("object_created", self.get_name(), "Walking", global_position, Vector2(0, 0))
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
Event.emit_signal("report_object", self.get_name(), "walking", global_position, velocity)
|
||||
timer.start()
|
||||
|
@ -1,5 +1,17 @@
|
||||
extends Area2D
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
Event.emit_signal("report_object", self.get_name(), "not collected", global_position, Vector2())
|
||||
var timer := Timer.new()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_child(timer)
|
||||
timer.wait_time = 0.1
|
||||
var err = timer.connect("timeout", self, "_on_timer_timeout")
|
||||
if err == OK:
|
||||
timer.start()
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
Event.emit_signal("report_object", self.get_name(), "not collected", global_position, Vector2())
|
||||
timer.start()
|
||||
|
@ -1,5 +1,17 @@
|
||||
extends Area2D
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
Event.emit_signal("report_object", self.get_name(), "not touched", global_position, Vector2())
|
||||
var timer := Timer.new()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_child(timer)
|
||||
timer.wait_time = 0.1
|
||||
var err = timer.connect("timeout", self, "_on_timer_timeout")
|
||||
if err == OK:
|
||||
timer.start()
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
Event.emit_signal("report_object", self.get_name(), "not touched", global_position, Vector2())
|
||||
timer.start()
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "player/AI.h"
|
||||
|
||||
#include <InputEventAction.hpp>
|
||||
|
||||
void alai::player::AI::_register_methods()
|
||||
{
|
||||
godot::register_method("_ready", &AI::_ready);
|
||||
godot::register_method("_physics_process", &AI::_physics_process);
|
||||
godot::register_method("_on_object_report", &AI::_on_object_report);
|
||||
godot::register_method("_on_timer_timeout", &AI::_on_timer_timeout);
|
||||
}
|
||||
|
||||
alai::player::AI::AI()
|
||||
@ -27,78 +30,142 @@ void alai::player::AI::_ready()
|
||||
|
||||
event = get_node<alai::Event>("/root/Event");
|
||||
event->connect("report_object", this, "_on_object_report");
|
||||
|
||||
add_child(timer);
|
||||
timer->set_wait_time(1);
|
||||
auto err = timer->connect("timeout", this, "_on_timer_timeout");
|
||||
if (err != godot::Error::OK)
|
||||
{
|
||||
godot::Godot::print("Timer could not be connected!");
|
||||
}
|
||||
}
|
||||
|
||||
void alai::player::AI::_physics_process(float delta)
|
||||
{
|
||||
auto player_position = parent->get_global_position();
|
||||
auto player_direction = parent->get_velocity();
|
||||
bool walking = false;
|
||||
|
||||
std::sort(entities.begin(), entities.end(), [](const Entity &a, const Entity &b) -> bool
|
||||
{
|
||||
return a.position.x < b.position.x;
|
||||
});
|
||||
|
||||
while (!entities.empty())
|
||||
{
|
||||
const auto& entity = entities.front();
|
||||
const auto &entity = entities.front();
|
||||
|
||||
if (obelisk->query(entity.name.utf8().get_data(), "is", "touchable") > 0)
|
||||
auto entityName = entity.name.utf8().get_data();
|
||||
|
||||
double distance = std::abs(player_position.x - entity.position.x);
|
||||
|
||||
int jump_distance = -1;
|
||||
auto action = obelisk->queryAction(entityName, "is", "bouncable");
|
||||
if (action == "jump on")
|
||||
{
|
||||
jump_distance = 100;
|
||||
}
|
||||
else if (action == "jump over")
|
||||
{
|
||||
jump_distance = 50;
|
||||
}
|
||||
|
||||
if (lastEntity == "")
|
||||
{
|
||||
if (jump_distance != -1 && distance < jump_distance)
|
||||
{
|
||||
lastEntity = entity.originalName;
|
||||
timer->start();
|
||||
if (player_position.x < entity.position.x)
|
||||
{
|
||||
auto ev = godot::InputEventAction()._new();
|
||||
ev->set_action("jump");
|
||||
ev->set_pressed(true);
|
||||
_input->parse_input_event(ev);
|
||||
}
|
||||
else if (player_position.x > entity.position.x)
|
||||
{
|
||||
auto ev = godot::InputEventAction()._new();
|
||||
ev->set_action("jump");
|
||||
ev->set_pressed(true);
|
||||
_input->parse_input_event(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obelisk->query(entityName, "is", "gold") > 0 && obelisk->query(std::string("gold ") + entityName, "is", "collectable") > 0)
|
||||
{
|
||||
auto player_position = parent->get_global_position();
|
||||
if (entity.position.x > player_position.x)
|
||||
{
|
||||
_input->action_press("right");
|
||||
if (!walking && !_input->is_action_pressed("left") && !_input->is_action_pressed("right"))
|
||||
{
|
||||
walking = true;
|
||||
_input->action_press("right");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_input->action_press("left");
|
||||
}
|
||||
}
|
||||
|
||||
if (obelisk->query(entity.name.utf8().get_data(), "is", "bouncable") > 0)
|
||||
{
|
||||
auto player_position = parent->get_global_position();
|
||||
auto distance = sqrt(pow(player_position.x - entity.position.x, 2) + pow(player_position.y - entity.position.y, 2));
|
||||
int jump_distance = 0;
|
||||
|
||||
auto player_direction = parent->get_velocity();
|
||||
|
||||
auto action = obelisk->queryAction(entity.name.utf8().get_data(), "is", "bouncable");
|
||||
if (action == "jump on")
|
||||
{
|
||||
jump_distance = 100;
|
||||
}
|
||||
else if (action == "jump over")
|
||||
{
|
||||
jump_distance = 50;
|
||||
}
|
||||
|
||||
if (distance < jump_distance)
|
||||
{
|
||||
if (_input->is_action_pressed("right") && player_position.x < entity.position.x)
|
||||
if (!walking && !_input->is_action_pressed("left") && !_input->is_action_pressed("right"))
|
||||
{
|
||||
_input->action_press("jump");
|
||||
}
|
||||
else if (_input->is_action_pressed("left") && player_position.x > entity.position.x)
|
||||
{
|
||||
_input->action_press("jump");
|
||||
walking = true;
|
||||
_input->action_press("left");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (obelisk->query(entity.name.utf8().get_data(), "is", "gold") > 0 && obelisk->query(std::string("gold ") + entity.name.utf8().get_data(), "is", "collectable") > 0)
|
||||
{
|
||||
auto player_position = parent->get_global_position();
|
||||
float distance = player_position.x - entity.position.x;
|
||||
if (distance > -10 && distance < 10 && player_position.y - entity.position.y > 20)
|
||||
{
|
||||
_input->action_press("jump");
|
||||
timer->stop();
|
||||
lastEntity = "";
|
||||
if (!_input->is_action_pressed("jump"))
|
||||
{
|
||||
_input->action_press("jump");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entities.pop();
|
||||
if (obelisk->query(entityName, "is", "touchable") > 0)
|
||||
{
|
||||
if (!walking && !_input->is_action_pressed("left") && !_input->is_action_pressed("right"))
|
||||
{
|
||||
walking = true;
|
||||
if (entity.position.x > player_position.x)
|
||||
{
|
||||
_input->action_press("right");
|
||||
}
|
||||
else
|
||||
{
|
||||
_input->action_press("left");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entities.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void alai::player::AI::unset_action(godot::String action)
|
||||
{
|
||||
auto ev = godot::InputEventAction()._new();
|
||||
ev->set_action(action);
|
||||
ev->set_pressed(false);
|
||||
_input->parse_input_event(ev);
|
||||
}
|
||||
|
||||
void alai::player::AI::_on_timer_timeout()
|
||||
{
|
||||
unset_action("left");
|
||||
unset_action("right");
|
||||
unset_action("jump");
|
||||
lastEntity = "";
|
||||
}
|
||||
|
||||
void alai::player::AI::_on_object_report(godot::String name, godot::String state, godot::Vector2 position, godot::Vector2 velocity)
|
||||
{
|
||||
auto entity = Entity();
|
||||
entity.name = name.to_lower().rstrip("0123456789");
|
||||
entity.state = state;
|
||||
entity.position = position;
|
||||
entity.velocity = velocity;
|
||||
entities.push(entity);
|
||||
auto entity = Entity();
|
||||
entity.originalName = name;
|
||||
entity.name = name.to_lower().rstrip("0123456789");
|
||||
entity.state = state;
|
||||
entity.position = position;
|
||||
entity.velocity = velocity;
|
||||
entities.emplace_front(entity);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <Godot.hpp>
|
||||
#include <Input.hpp>
|
||||
#include <Node.hpp>
|
||||
#include <Timer.hpp>
|
||||
#include <Vector2.hpp>
|
||||
#include <queue>
|
||||
|
||||
@ -18,6 +19,7 @@ namespace alai
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
godot::String originalName;
|
||||
godot::String name;
|
||||
godot::String state;
|
||||
godot::Vector2 position;
|
||||
@ -43,10 +45,14 @@ namespace alai
|
||||
|
||||
alai::Event* event;
|
||||
|
||||
std::queue<alai::player::Entity> entities;
|
||||
std::deque<alai::player::Entity> entities;
|
||||
|
||||
alai::player::Player* parent;
|
||||
|
||||
godot::String lastEntity;
|
||||
|
||||
godot::Timer* timer = godot::Timer()._new();
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief This method registers classes with Godot.
|
||||
@ -56,7 +62,16 @@ namespace alai
|
||||
static void
|
||||
_register_methods();
|
||||
|
||||
/**
|
||||
* @brief Construct a new AI object.
|
||||
*
|
||||
*/
|
||||
AI();
|
||||
|
||||
/**
|
||||
* @brief Destroy the AI object.
|
||||
*
|
||||
*/
|
||||
~AI();
|
||||
|
||||
/**
|
||||
@ -80,6 +95,18 @@ namespace alai
|
||||
*/
|
||||
void _physics_process(float delta);
|
||||
|
||||
void _on_timer_timeout();
|
||||
|
||||
void unset_action(godot::String action);
|
||||
|
||||
/**
|
||||
* @brief Callback that receives information about the game environment.
|
||||
*
|
||||
* @param[in] name The name of the object.
|
||||
* @param[in] state The state the object is in.
|
||||
* @param[in] position The position of the object.
|
||||
* @param[in] velocity The object's velocity.
|
||||
*/
|
||||
void _on_object_report(godot::String name, godot::String state, godot::Vector2 position, godot::Vector2 velocity);
|
||||
};
|
||||
} // namespace player
|
||||
|
Loading…
Reference in New Issue
Block a user