diff --git a/SConstruct b/SConstruct index a17df99..27e219b 100644 --- a/SConstruct +++ b/SConstruct @@ -82,6 +82,8 @@ elif env['platform'] == "windows": # that way you can run scons in a vs 2017 prompt and it will find all the required tools env.Append(ENV=os.environ) + env.Append(CXXFLAGS=['-std=c++17']) + env.Append(LINKFLAGS=[ '--static', '-Wl,--no-undefined', diff --git a/godot/GUI/GameOver.tscn b/godot/GUI/GameOver.tscn deleted file mode 100644 index ba0990d..0000000 --- a/godot/GUI/GameOver.tscn +++ /dev/null @@ -1,48 +0,0 @@ -[gd_scene load_steps=7 format=2] - -[ext_resource path="res://assets/fonts/ttf/PixelOperator8.ttf" type="DynamicFontData" id=1] -[ext_resource path="res://assets/fonts/ttf/PixelOperatorHB8.ttf" type="DynamicFontData" id=2] -[ext_resource path="res://GUI/botonreiniciar.gdns" type="Script" id=3] - -[sub_resource type="DynamicFont" id=1] -size = 50 -font_data = ExtResource( 1 ) - -[sub_resource type="DynamicFont" id=2] -font_data = ExtResource( 2 ) - -[sub_resource type="StyleBoxFlat" id=3] -bg_color = Color( 0.0705882, 0.917647, 0, 1 ) - -[node name="GameOver" type="CanvasLayer"] -script = ExtResource( 3 ) - -[node name="Control" type="Control" parent="."] -margin_right = 40.0 -margin_bottom = 40.0 - -[node name="ColorRect" type="ColorRect" parent="Control"] -margin_right = 512.0 -margin_bottom = 288.0 -rect_min_size = Vector2( 512, 288 ) -color = Color( 0, 0, 0, 1 ) - -[node name="Label" type="Label" parent="Control"] -margin_left = 66.0 -margin_top = 17.0 -margin_right = 456.0 -margin_bottom = 71.0 -custom_fonts/font = SubResource( 1 ) -text = "GAME OVER" -align = 1 - -[node name="RestartButton" type="Button" parent="Control"] -margin_left = 194.0 -margin_top = 150.0 -margin_right = 338.0 -margin_bottom = 180.0 -custom_fonts/font = SubResource( 2 ) -custom_styles/hover = SubResource( 3 ) -text = "REINICIAR" - -[connection signal="pressed" from="Control/RestartButton" to="." method="_on_restart_button_pressed"] diff --git a/godot/GUI/botonreiniciar.gdns b/godot/GUI/botonreiniciar.gdns deleted file mode 100644 index 750e9bf..0000000 --- a/godot/GUI/botonreiniciar.gdns +++ /dev/null @@ -1,8 +0,0 @@ -[gd_resource type="NativeScript" load_steps=2 format=2] - -[ext_resource path="res://gdnative/alai.tres" type="GDNativeLibrary" id=1] - -[resource] -resource_name = "GameOverScreen" -class_name = "GameOverScreen" -library = ExtResource( 1 ) diff --git a/godot/characters/enemies/WalkingEnemy.gd b/godot/characters/enemies/WalkingEnemy.gd index c1c54b5..94a01b5 100644 --- a/godot/characters/enemies/WalkingEnemy.gd +++ b/godot/characters/enemies/WalkingEnemy.gd @@ -16,6 +16,7 @@ func _ready() -> void: $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") func _physics_process(_delta: float) -> void: @@ -33,6 +34,13 @@ func _physics_process(_delta: float) -> void: if collision.collider.name == "Player": emit_signal("player_touched") + 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() + + +func _on_level_loaded() -> void: + Event.emit_signal("object_created", self.get_name(), "Walking", global_position, Vector2(0, 0)) diff --git a/godot/characters/enemies/blightwing/Blightwing.gd b/godot/characters/enemies/blightwing/Blightwing.gd index 6186bea..1446628 100644 --- a/godot/characters/enemies/blightwing/Blightwing.gd +++ b/godot/characters/enemies/blightwing/Blightwing.gd @@ -22,6 +22,8 @@ func _ready() -> void: if direction == 1: $AnimatedSprite.flip_h = true + Event.connect("level_loaded", self, "_on_level_loaded") + func _physics_process(delta: float) -> void: if $LeftWallChecker.is_colliding(): @@ -29,17 +31,18 @@ func _physics_process(delta: float) -> void: elif $RightWallChecker.is_colliding(): wall_checker_collided($RightWallChecker) + var velocity: Vector2 = Vector2(0, 0) if not follow_path: var target_position = position target_position.x *= 2 * direction position = position.move_toward(target_position, round(speed * delta)) - var velocity = get_velocity_towards_target(delta) + velocity = get_velocity_towards_target(delta) var collision = move_and_collide(velocity, true, true, true) if collision and collision.collider.name != "Player": var _collision = move_and_collide(velocity) else: - var velocity = get_velocity_towards_target(delta) + velocity = get_velocity_towards_target(delta) var collision = move_and_collide(velocity, true, true, true) if collision and collision.collider.name != "Player": @@ -60,6 +63,8 @@ func _physics_process(delta: float) -> void: elif start_position.x + target.x < position.x: $AnimatedSprite.flip_h = false + Event.emit_signal("object_updated", self.get_name(), "Flying", global_position, velocity) + func get_velocity_towards_target(delta: float) -> Vector2: var velocity = Vector2(0, 0) @@ -80,3 +85,7 @@ func wall_checker_collided(wall_checker: RayCast2D) -> void: emit_signal("player_touched") direction *= -1 $AnimatedSprite.flip_h = not $AnimatedSprite.flip_h + + +func _on_level_loaded() -> void: + Event.emit_signal("object_created", self.get_name(), "Flying", global_position, Vector2(0, 0)) diff --git a/godot/characters/enemies/blockface/Blockface.gd b/godot/characters/enemies/blockface/Blockface.gd index b307882..3f52a5a 100644 --- a/godot/characters/enemies/blockface/Blockface.gd +++ b/godot/characters/enemies/blockface/Blockface.gd @@ -11,9 +11,14 @@ export var fall_speed = 75.0 var return_to_start: bool = false +func _ready() -> void: + Event.connect("level_loaded", self, "_on_level_loaded") + + func _physics_process(delta: float) -> void: if return_to_start: position = position.move_toward(start_position, speed * delta) + Event.emit_signal("object_updated", self.get_name(), "Rising", global_position, velocity) else: var collision = move_and_collide(Vector2(0, (position.y + fall_speed) * delta)) if collision: @@ -21,7 +26,12 @@ func _physics_process(delta: float) -> void: $AnimatedSprite.play("normal") if collision.collider.name == "Player": emit_signal("player_touched") + Event.emit_signal("object_updated", self.get_name(), "Falling", global_position, velocity) if position.y <= start_position.y: return_to_start = false $AnimatedSprite.play("angry") + + +func _on_level_loaded() -> void: + Event.emit_signal("object_created", self.get_name(), "Falling", global_position, Vector2(0, 0)) diff --git a/godot/monitor/Monitor.gd b/godot/monitor/Monitor.gd index 5e34c64..99404ac 100644 --- a/godot/monitor/Monitor.gd +++ b/godot/monitor/Monitor.gd @@ -1,10 +1,8 @@ extends Node -signal monitor_loaded() - - export var monitor_enabled: bool = false +export var debug: bool = false export var development_url: String = "http://localhost:4050/api/v1" var url_real: String = "https://alai.cromer.cl/api/v1" export var use_development_url: bool = false @@ -53,7 +51,11 @@ func _ready() -> void: Event.connect("object_created", self, "_object_created") Event.connect("object_updated", self, "_object_updated") Event.connect("object_removed", self, "_object_removed") + Event.connect("game_started", self, "_on_game_started") + Event.connect("player_died", self, "_on_game_over") + Event.connect("player_won", self, "_on_game_won") Event.connect("coin_collected", self, "_on_coin_update") + game_version = get_parent().game_version player["rut"] = "" @@ -108,7 +110,7 @@ func _physics_process(_delta: float) -> void: if monitor_enabled: if has_node("MonitorGUI") and not $MonitorGUI.visible: $MonitorGUI.visible = true - emit_signal("monitor_loaded") + Event.emit_signal("monitor_loaded") if started and not get_tree().paused: var frame = empty_frame.duplicate(true) @@ -130,13 +132,14 @@ func _physics_process(_delta: float) -> void: start_monitor() else: get_tree().paused = false - emit_signal("monitor_loaded") + Event.emit_signal("monitor_loaded") queue_free() func _on_input_validated(validated_player: Dictionary) -> void: $MonitorGUI.queue_free() get_tree().paused = false + Event.emit_signal("game_started") player = validated_player.duplicate(true) game["player"] = player @@ -188,6 +191,7 @@ func remove_object(name: String) -> void: for i in range(0, objects.size()): if objects[i]["name"] == name: objects.remove(i) + return func _on_coin_update(amount: int) -> void: @@ -219,7 +223,16 @@ func send_data() -> void: print("Body B: " + String(body.length())) print("Body MB: " + String(body.length() / pow(2, 20))) - $HTTPRequest.request(url + "/game", headers, false, HTTPClient.METHOD_POST, body) + if not debug: + $HTTPRequest.request(url + "/game", headers, false, HTTPClient.METHOD_POST, body) + else: + var file = File.new() + if file.open("user://game.json", File.WRITE) != 0: + print_debug("Could not open game.json for writing!") + return + + file.store_string(json) + file.close() func compress_payload(payload: String) -> String: @@ -231,3 +244,21 @@ func compress_payload(payload: String) -> String: return new_payload +func _on_game_started() -> void: + print_debug("started game") + if not started: + start_monitor() + + +func _on_game_over() -> void: + if started: + stop_monitor() + game["won"] = false + send_data() + + +func _on_game_won() -> void: + if started: + stop_monitor() + game["won"] = true + send_data() diff --git a/src/Event.cpp b/src/Event.cpp index e457ae7..8795d1e 100644 --- a/src/Event.cpp +++ b/src/Event.cpp @@ -2,6 +2,9 @@ void alai::Event::_register_methods() { + godot::register_signal("game_started"); + godot::register_signal("monitor_loaded"); + godot::register_signal("level_loaded"); godot::register_signal("object_created", "name", GODOT_VARIANT_TYPE_STRING, "state", GODOT_VARIANT_TYPE_STRING, "position", GODOT_VARIANT_TYPE_VECTOR2, "velocity", GODOT_VARIANT_TYPE_VECTOR2); godot::register_signal("object_updated", "name", GODOT_VARIANT_TYPE_STRING, "state", GODOT_VARIANT_TYPE_STRING, "position", GODOT_VARIANT_TYPE_VECTOR2, "velocity", GODOT_VARIANT_TYPE_VECTOR2); godot::register_signal("object_removed", "name", GODOT_VARIANT_TYPE_STRING); diff --git a/src/Main.cpp b/src/Main.cpp index 4f895bd..353882b 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -1,5 +1,7 @@ #include "Main.h" +#include "Event.h" + #include void alai::Main::_register_methods() @@ -86,24 +88,21 @@ void alai::Main::_ready() void alai::Main::_on_monitor_loaded() { - if (level != nullptr) - { - auto level_node = load_level(); - connect("monitor_loaded", level_node->get_child(0)->find_node("Player", true, false), "_on_monitor_loaded"); - emit_signal("monitor_loaded"); - } + load_level(); + auto event = get_node("/root/Event"); + event->emit_signal("level_loaded"); } void alai::Main::load_monitor() { + auto event = get_node("/root/Event"); + event->connect("monitor_loaded", this, "_on_monitor_loaded"); godot::Ref monitor_scene = _resource_loader->load("res://monitor/Monitor.tscn"); add_child(monitor_scene->instance()); - auto monitor = get_node("Monitor"); - monitor->connect("monitor_loaded", this, "_on_monitor_loaded"); get_tree()->set_pause(true); } -godot::Node *alai::Main::load_level() +void alai::Main::load_level() { if (level != nullptr) { @@ -111,9 +110,7 @@ godot::Node *alai::Main::load_level() auto loaded_level = level->instance(); auto level_node = get_node("Level"); level_node->add_child(loaded_level); - return level_node; } - return nullptr; } void alai::Main::_physics_process(float delta) diff --git a/src/Main.h b/src/Main.h index 9487338..a3cb313 100644 --- a/src/Main.h +++ b/src/Main.h @@ -224,9 +224,8 @@ namespace alai /** * @brief Loads the selected level. * - * @return Node* The level node which we will later add the monitor to. */ - Node *load_level(); + void load_level(); }; } diff --git a/src/gui/game_over/GameOverScreen.cpp b/src/gui/game_over/GameOverScreen.cpp index f6f604f..9627b2c 100644 --- a/src/gui/game_over/GameOverScreen.cpp +++ b/src/gui/game_over/GameOverScreen.cpp @@ -1,4 +1,5 @@ #include "gui/game_over/GameOverScreen.h" + #include "Event.h" #include @@ -11,6 +12,7 @@ void alai::GameOverScreen::_register_methods() { godot::register_method("_on_restart_button_pressed", &GameOverScreen::_on_restart_button_pressed); godot::register_method("_ready", &GameOverScreen::_ready); + godot::register_method("restart_game", &GameOverScreen::restart_game); godot::register_method("connect_signal", &GameOverScreen::connect_signal); godot::register_method("_on_player_died", &GameOverScreen::_on_player_died); } @@ -45,7 +47,7 @@ void alai::GameOverScreen::_on_restart_button_pressed() { level_node->add_child(level); set_visible(false); - call_deferred("connect_signal"); + call_deferred("restart_game"); } else { @@ -79,6 +81,13 @@ void alai::GameOverScreen::_on_player_died() } } +void alai::GameOverScreen::restart_game() +{ + auto event = get_node("/root/Event"); + event->emit_signal("game_started"); + connect_signal(); +} + void alai::GameOverScreen::connect_signal() { auto event = get_node("/root/Event"); diff --git a/src/gui/game_over/GameOverScreen.h b/src/gui/game_over/GameOverScreen.h index cb79374..d3315c6 100644 --- a/src/gui/game_over/GameOverScreen.h +++ b/src/gui/game_over/GameOverScreen.h @@ -52,6 +52,7 @@ namespace alai void _ready(); void _on_player_died(); void _on_restart_button_pressed(); + void restart_game(); void connect_signal(); }; } diff --git a/src/gui/game_won/GameWonScreen.cpp b/src/gui/game_won/GameWonScreen.cpp index d57f950..f51822e 100644 --- a/src/gui/game_won/GameWonScreen.cpp +++ b/src/gui/game_won/GameWonScreen.cpp @@ -1,4 +1,5 @@ #include "gui/game_won/GameWonScreen.h" + #include "Event.h" #include diff --git a/src/player/Player.cpp b/src/player/Player.cpp index 68df74f..9a128f9 100644 --- a/src/player/Player.cpp +++ b/src/player/Player.cpp @@ -19,7 +19,7 @@ void alai::player::Player::_register_methods() godot::register_method("set_velocity", &Player::set_velocity); godot::register_method("get_velocity", &Player::get_velocity); godot::register_method("_on_player_touched", &Player::_on_player_touched); - godot::register_method("_on_monitor_loaded", &Player::_on_monitor_loaded); + godot::register_method("_on_level_loaded", &Player::_on_level_loaded); //godot::register_property>("sprite_frames", &Player::set_sprite_frames, &Player::get_sprite_frames, godot::Ref(), GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RESOURCE_TYPE, godot::String("SpriteFrames")); godot::register_property("speed", &Player::set_speed, &Player::get_speed, player::speed); godot::register_property("jump_force", &Player::set_jump_force, &Player::get_jump_force, player::jump_force); @@ -51,11 +51,16 @@ void alai::player::Player::_init() coins = 0; + notifier_initialized = false; + velocity = godot::Vector2(); } void alai::player::Player::_ready() { + auto event = get_node("/root/Event"); + event->connect("level_loaded", this, "_on_level_loaded"); + animated_sprite = get_node("AnimatedSprite"); if (!animated_sprite) { @@ -77,7 +82,7 @@ void alai::player::Player::_ready() } } -void alai::player::Player::_on_monitor_loaded() { +void alai::player::Player::_on_level_loaded() { auto state = get_node("StateMachine")->get_child(0); if (state != nullptr) { @@ -186,10 +191,17 @@ void alai::player::Player::_physics_process(float delta) auto notifier = get_node("Camera2D/VisibilityNotifier2D"); if (notifier != nullptr) { - if (!notifier->is_on_screen()) + if (notifier->is_inside_tree() && !notifier->is_on_screen()) { - auto event = get_node("/root/Event"); - event->emit_signal("player_died"); + // The first time the notifier is checked always returns false in the first frame + // So skip the check from the first frame + if (notifier_initialized) { + auto event = get_node("/root/Event"); + event->emit_signal("player_died"); + } + else { + notifier_initialized = true; + } } } else diff --git a/src/player/Player.h b/src/player/Player.h index cedcfb5..578840a 100644 --- a/src/player/Player.h +++ b/src/player/Player.h @@ -117,6 +117,11 @@ namespace alai * */ bool double_jump; + /** + * @brief If the notifier for the player being on screen has been initialized or not. + * + */ + bool notifier_initialized; public: /** @@ -284,7 +289,7 @@ namespace alai * @brief Called when the monitor is loaded to connect the player to it for tracking. * */ - void _on_monitor_loaded(); + void _on_level_loaded(); }; } }