Merge pull request 'feature/finishing_touches' (#62) from feature/finishing_touches into develop
Reviewed-on: #62
This commit is contained in:
commit
77d844c911
@ -2,7 +2,7 @@
|
|||||||
# See https://pre-commit.com/hooks.html for more hooks
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.3.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
@ -15,16 +15,11 @@ repos:
|
|||||||
- id: no-commit-to-branch
|
- id: no-commit-to-branch
|
||||||
args: [--branch, master, --branch, develop]
|
args: [--branch, master, --branch, develop]
|
||||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
rev: v14.0.6
|
rev: v15.0.7
|
||||||
hooks:
|
hooks:
|
||||||
- id: clang-format
|
- id: clang-format
|
||||||
types_or: [c++, c]
|
types_or: [c++, c]
|
||||||
args: ["-style=file"]
|
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
|
#- repo: https://github.com/pocc/pre-commit-hooks
|
||||||
# rev: v1.3.5
|
# rev: v1.3.5
|
||||||
# hooks:
|
# hooks:
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
[node name="Main" type="Node"]
|
[node name="Main" type="Node"]
|
||||||
pause_mode = 2
|
pause_mode = 2
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
game_version = "1.0.0"
|
game_version = "1.1.0"
|
||||||
level = ExtResource( 2 )
|
level = ExtResource( 2 )
|
||||||
|
|
||||||
[node name="Level" type="Node" parent="."]
|
[node name="Level" type="Node" parent="."]
|
||||||
|
BIN
godot/alai.kb
BIN
godot/alai.kb
Binary file not shown.
@ -6,6 +6,7 @@ export var direction = -1
|
|||||||
export var detect_edges = true
|
export var detect_edges = true
|
||||||
export var speed = 25
|
export var speed = 25
|
||||||
export var gravity = 9.8
|
export var gravity = 9.8
|
||||||
|
var timer := Timer.new()
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
@ -15,6 +16,12 @@ func _ready() -> void:
|
|||||||
$FloorChecker.enabled = detect_edges
|
$FloorChecker.enabled = detect_edges
|
||||||
Event.connect("level_loaded", self, "_on_level_loaded")
|
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:
|
func _physics_process(_delta: float) -> void:
|
||||||
if is_on_wall() or not $FloorChecker.is_colliding() and is_on_floor() and $FloorChecker.enabled:
|
if is_on_wall() or not $FloorChecker.is_colliding() and is_on_floor() and $FloorChecker.enabled:
|
||||||
@ -32,7 +39,6 @@ func _physics_process(_delta: float) -> void:
|
|||||||
Event.emit_signal("player_touched", 3)
|
Event.emit_signal("player_touched", 3)
|
||||||
|
|
||||||
Event.emit_signal("object_updated", self.get_name(), "Walking", global_position, velocity)
|
Event.emit_signal("object_updated", self.get_name(), "Walking", global_position, velocity)
|
||||||
Event.emit_signal("report_object", self.get_name(), "Walking", global_position, velocity)
|
|
||||||
|
|
||||||
|
|
||||||
func squash() -> void:
|
func squash() -> void:
|
||||||
@ -42,3 +48,8 @@ func squash() -> void:
|
|||||||
|
|
||||||
func _on_level_loaded() -> void:
|
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
|
extends Area2D
|
||||||
|
|
||||||
|
|
||||||
func _process(_delta: float) -> void:
|
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())
|
Event.emit_signal("report_object", self.get_name(), "not collected", global_position, Vector2())
|
||||||
|
timer.start()
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
extends Area2D
|
extends Area2D
|
||||||
|
|
||||||
|
|
||||||
func _process(_delta: float) -> void:
|
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())
|
Event.emit_signal("report_object", self.get_name(), "not touched", global_position, Vector2())
|
||||||
|
timer.start()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=10 format=2]
|
[gd_scene load_steps=11 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://characters/enemies/shelly/Shelly.tscn" type="PackedScene" id=1]
|
[ext_resource path="res://characters/enemies/shelly/Shelly.tscn" type="PackedScene" id=1]
|
||||||
[ext_resource path="res://collectables/coin/Coin.tscn" type="PackedScene" id=2]
|
[ext_resource path="res://collectables/coin/Coin.tscn" type="PackedScene" id=2]
|
||||||
@ -9,6 +9,7 @@
|
|||||||
[ext_resource path="res://assets/backgrounds/hills.png" type="Texture" id=7]
|
[ext_resource path="res://assets/backgrounds/hills.png" type="Texture" id=7]
|
||||||
[ext_resource path="res://levels/TestLevel.tmx" type="PackedScene" id=8]
|
[ext_resource path="res://levels/TestLevel.tmx" type="PackedScene" id=8]
|
||||||
[ext_resource path="res://CameraLimit.gdns" type="Script" id=9]
|
[ext_resource path="res://CameraLimit.gdns" type="Script" id=9]
|
||||||
|
[ext_resource path="res://characters/enemies/dreadtooth/Dreadtooth.tscn" type="PackedScene" id=10]
|
||||||
|
|
||||||
[node name="TestLevel" type="Node2D"]
|
[node name="TestLevel" type="Node2D"]
|
||||||
|
|
||||||
@ -79,5 +80,5 @@ position = Vector2( 656, 504 )
|
|||||||
[node name="Shelly" parent="Enemies" instance=ExtResource( 1 )]
|
[node name="Shelly" parent="Enemies" instance=ExtResource( 1 )]
|
||||||
position = Vector2( 379, 510 )
|
position = Vector2( 379, 510 )
|
||||||
|
|
||||||
[node name="Shelly2" parent="Enemies" instance=ExtResource( 1 )]
|
[node name="Dreadtooth" parent="Enemies" instance=ExtResource( 10 )]
|
||||||
position = Vector2( 628, 510 )
|
position = Vector2( 640, 510 )
|
||||||
|
17
obelisk/alai.obk
Normal file
17
obelisk/alai.obk
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
fact("coin" is "gold");
|
||||||
|
rule("gold coin" is "collectable" if "coin" is "gold");
|
||||||
|
|
||||||
|
fact("goal" is "touchable");
|
||||||
|
|
||||||
|
fact("shelly" is "dangerous");
|
||||||
|
fact("shelly" is "bouncable");
|
||||||
|
fact("shelly" can "walk");
|
||||||
|
|
||||||
|
fact("dreadtooth" is "dangerous");
|
||||||
|
fact("dreadtooth" can "walk");
|
||||||
|
|
||||||
|
action(if "shelly" is "bouncable" then "jump on" else "jump over");
|
||||||
|
action(if "dreadtooth" is "bouncable" then "jump on" else "jump over");
|
||||||
|
|
||||||
|
action(if "coin" is "collectable" then "collect" else "avoid");
|
||||||
|
action(if "goal" is "touchable" then "touch" else "avoid");
|
@ -1,10 +1,13 @@
|
|||||||
#include "player/AI.h"
|
#include "player/AI.h"
|
||||||
|
|
||||||
|
#include <InputEventAction.hpp>
|
||||||
|
|
||||||
void alai::player::AI::_register_methods()
|
void alai::player::AI::_register_methods()
|
||||||
{
|
{
|
||||||
godot::register_method("_ready", &AI::_ready);
|
godot::register_method("_ready", &AI::_ready);
|
||||||
godot::register_method("_physics_process", &AI::_physics_process);
|
godot::register_method("_physics_process", &AI::_physics_process);
|
||||||
godot::register_method("_on_object_report", &AI::_on_object_report);
|
godot::register_method("_on_object_report", &AI::_on_object_report);
|
||||||
|
godot::register_method("_on_timer_timeout", &AI::_on_timer_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
alai::player::AI::AI()
|
alai::player::AI::AI()
|
||||||
@ -27,36 +30,37 @@ void alai::player::AI::_ready()
|
|||||||
|
|
||||||
event = get_node<alai::Event>("/root/Event");
|
event = get_node<alai::Event>("/root/Event");
|
||||||
event->connect("report_object", this, "_on_object_report");
|
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)
|
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())
|
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();
|
||||||
{
|
|
||||||
auto player_position = parent->get_global_position();
|
|
||||||
if (entity.position.x > player_position.x)
|
|
||||||
{
|
|
||||||
_input->action_press("right");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_input->action_press("left");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obelisk->query(entity.name.utf8().get_data(), "is", "bouncable") > 0)
|
double distance = std::abs(player_position.x - entity.position.x);
|
||||||
{
|
|
||||||
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();
|
int jump_distance = -1;
|
||||||
|
auto action = obelisk->queryAction(entityName, "is", "bouncable");
|
||||||
auto action = obelisk->queryAction(entity.name.utf8().get_data(), "is", "bouncable");
|
|
||||||
if (action == "jump on")
|
if (action == "jump on")
|
||||||
{
|
{
|
||||||
jump_distance = 100;
|
jump_distance = 100;
|
||||||
@ -66,39 +70,102 @@ void alai::player::AI::_physics_process(float delta)
|
|||||||
jump_distance = 50;
|
jump_distance = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (distance < jump_distance)
|
if (lastEntity == "")
|
||||||
{
|
{
|
||||||
if (_input->is_action_pressed("right") && player_position.x < entity.position.x)
|
if (jump_distance != -1 && distance < jump_distance)
|
||||||
{
|
{
|
||||||
_input->action_press("jump");
|
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 (_input->is_action_pressed("left") && player_position.x > entity.position.x)
|
else if (player_position.x > entity.position.x)
|
||||||
{
|
{
|
||||||
_input->action_press("jump");
|
auto ev = godot::InputEventAction()._new();
|
||||||
|
ev->set_action("jump");
|
||||||
|
ev->set_pressed(true);
|
||||||
|
_input->parse_input_event(ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obelisk->query(entity.name.utf8().get_data(), "is", "gold") > 0 && obelisk->query(std::string("gold ") + entity.name.utf8().get_data(), "is", "collectable") > 0)
|
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)
|
||||||
float distance = player_position.x - entity.position.x;
|
{
|
||||||
|
if (!walking && !_input->is_action_pressed("left") && !_input->is_action_pressed("right"))
|
||||||
|
{
|
||||||
|
walking = true;
|
||||||
|
_input->action_press("right");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!walking && !_input->is_action_pressed("left") && !_input->is_action_pressed("right"))
|
||||||
|
{
|
||||||
|
walking = true;
|
||||||
|
_input->action_press("left");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (distance > -10 && distance < 10 && player_position.y - entity.position.y > 20)
|
if (distance > -10 && distance < 10 && player_position.y - entity.position.y > 20)
|
||||||
|
{
|
||||||
|
timer->stop();
|
||||||
|
lastEntity = "";
|
||||||
|
if (!_input->is_action_pressed("jump"))
|
||||||
{
|
{
|
||||||
_input->action_press("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)
|
void alai::player::AI::_on_object_report(godot::String name, godot::String state, godot::Vector2 position, godot::Vector2 velocity)
|
||||||
{
|
{
|
||||||
auto entity = Entity();
|
auto entity = Entity();
|
||||||
|
entity.originalName = name;
|
||||||
entity.name = name.to_lower().rstrip("0123456789");
|
entity.name = name.to_lower().rstrip("0123456789");
|
||||||
entity.state = state;
|
entity.state = state;
|
||||||
entity.position = position;
|
entity.position = position;
|
||||||
entity.velocity = velocity;
|
entity.velocity = velocity;
|
||||||
entities.push(entity);
|
entities.emplace_front(entity);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <Godot.hpp>
|
#include <Godot.hpp>
|
||||||
#include <Input.hpp>
|
#include <Input.hpp>
|
||||||
#include <Node.hpp>
|
#include <Node.hpp>
|
||||||
|
#include <Timer.hpp>
|
||||||
#include <Vector2.hpp>
|
#include <Vector2.hpp>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ namespace alai
|
|||||||
class Entity
|
class Entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
godot::String originalName;
|
||||||
godot::String name;
|
godot::String name;
|
||||||
godot::String state;
|
godot::String state;
|
||||||
godot::Vector2 position;
|
godot::Vector2 position;
|
||||||
@ -43,10 +45,14 @@ namespace alai
|
|||||||
|
|
||||||
alai::Event* event;
|
alai::Event* event;
|
||||||
|
|
||||||
std::queue<alai::player::Entity> entities;
|
std::deque<alai::player::Entity> entities;
|
||||||
|
|
||||||
alai::player::Player* parent;
|
alai::player::Player* parent;
|
||||||
|
|
||||||
|
godot::String lastEntity;
|
||||||
|
|
||||||
|
godot::Timer* timer = godot::Timer()._new();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief This method registers classes with Godot.
|
* @brief This method registers classes with Godot.
|
||||||
@ -56,7 +62,16 @@ namespace alai
|
|||||||
static void
|
static void
|
||||||
_register_methods();
|
_register_methods();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a new AI object.
|
||||||
|
*
|
||||||
|
*/
|
||||||
AI();
|
AI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy the AI object.
|
||||||
|
*
|
||||||
|
*/
|
||||||
~AI();
|
~AI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,6 +95,18 @@ namespace alai
|
|||||||
*/
|
*/
|
||||||
void _physics_process(float delta);
|
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);
|
void _on_object_report(godot::String name, godot::String state, godot::Vector2 position, godot::Vector2 velocity);
|
||||||
};
|
};
|
||||||
} // namespace player
|
} // namespace player
|
||||||
|
Loading…
Reference in New Issue
Block a user