diff --git a/.gitmodules b/.gitmodules index 481cc20..b7d210e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "godot-cpp"] path = godot-cpp url = https://github.com/godotengine/godot-cpp - branch = 3.4 + branch = 3.5 diff --git a/godot-cpp b/godot-cpp index ced274f..867374d 160000 --- a/godot-cpp +++ b/godot-cpp @@ -1 +1 @@ -Subproject commit ced274fbe62c07dd9bb6791a77392f4bdc625152 +Subproject commit 867374da404887337909e8b7b9de5a8acbc47569 diff --git a/godot/Main.tscn b/godot/Main.tscn index a9c8579..06271a1 100644 --- a/godot/Main.tscn +++ b/godot/Main.tscn @@ -4,5 +4,9 @@ [ext_resource path="res://levels/Level2.tscn" type="PackedScene" id=2] [node name="Main" type="Node"] +pause_mode = 2 script = ExtResource( 1 ) level = ExtResource( 2 ) + +[node name="Level" type="Node" parent="."] +pause_mode = 1 diff --git a/godot/assets/fonts/data/PixelOperator-Bold.tres b/godot/assets/fonts/data/PixelOperator-Bold.tres new file mode 100644 index 0000000..4860407 --- /dev/null +++ b/godot/assets/fonts/data/PixelOperator-Bold.tres @@ -0,0 +1,4 @@ +[gd_resource type="DynamicFontData" format=2] + +[resource] +font_path = "res://assets/fonts/ttf/PixelOperator8-Bold.ttf" diff --git a/godot/assets/fonts/data/PixelOperator.tres b/godot/assets/fonts/data/PixelOperator.tres new file mode 100644 index 0000000..8817659 --- /dev/null +++ b/godot/assets/fonts/data/PixelOperator.tres @@ -0,0 +1,4 @@ +[gd_resource type="DynamicFontData" format=2] + +[resource] +font_path = "res://assets/fonts/ttf/PixelOperatorHB8.ttf" diff --git a/godot/assets/fonts/ttf/PixelOperator-Bold.ttf b/godot/assets/fonts/ttf/PixelOperator-Bold.ttf new file mode 100644 index 0000000..5f4d9f0 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperator-Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1963fa21043a357212e0a9e8ae1986bc375c1759e68bd3533c4f71b164614b0 +size 16984 diff --git a/godot/assets/fonts/ttf/PixelOperator.ttf b/godot/assets/fonts/ttf/PixelOperator.ttf new file mode 100644 index 0000000..7eeeec2 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperator.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d805274eaf227855147153182a96a86ff395ddbc7d2d378095af8831b764a3e +size 17272 diff --git a/godot/assets/fonts/ttf/PixelOperator8-Bold.ttf b/godot/assets/fonts/ttf/PixelOperator8-Bold.ttf new file mode 100644 index 0000000..3f95f88 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperator8-Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b46a109cdac6c2f7acb4a57451dc3c8f7e2d391b871500270eadf139f0ac906e +size 18624 diff --git a/godot/assets/fonts/ttf/PixelOperator8.ttf b/godot/assets/fonts/ttf/PixelOperator8.ttf new file mode 100644 index 0000000..6dd6601 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperator8.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cccb9ef6cf18977b6e5721d49a1a6e78dd6a6f1c4f69537470f7dc1dc829ffc +size 19944 diff --git a/godot/assets/fonts/ttf/PixelOperatorHB.ttf b/godot/assets/fonts/ttf/PixelOperatorHB.ttf new file mode 100644 index 0000000..a141a96 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorHB.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fba7efcd1595f795e7ced3dd88bcac890a4fd00a3d7a2212ec0ba67f9d7bff49 +size 17204 diff --git a/godot/assets/fonts/ttf/PixelOperatorHB8.ttf b/godot/assets/fonts/ttf/PixelOperatorHB8.ttf new file mode 100644 index 0000000..5ac3f34 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorHB8.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3569a5481727cc277be02ffa72348d40bf3ad9f03b9687b0da3b19fb717d00c8 +size 19076 diff --git a/godot/assets/fonts/ttf/PixelOperatorMono-Bold.ttf b/godot/assets/fonts/ttf/PixelOperatorMono-Bold.ttf new file mode 100644 index 0000000..7c8738f --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorMono-Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b8a5f6cfd5fdb06ddac7d976935babf05afa5ef7bf6b8c1b8cf919b481d33e1 +size 16744 diff --git a/godot/assets/fonts/ttf/PixelOperatorMono.ttf b/godot/assets/fonts/ttf/PixelOperatorMono.ttf new file mode 100644 index 0000000..ee4e92c --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorMono.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e171000f12d196e7a8a1a91c1a429ef3264a0ff007d5f62fa3dc44ef8df51226 +size 16972 diff --git a/godot/assets/fonts/ttf/PixelOperatorMono8-Bold.ttf b/godot/assets/fonts/ttf/PixelOperatorMono8-Bold.ttf new file mode 100644 index 0000000..90af97f --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorMono8-Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11704bf2bddcde0996909166ad9d10a7ff38eb311a59cb07991f63e5f0185f76 +size 18624 diff --git a/godot/assets/fonts/ttf/PixelOperatorMono8.ttf b/godot/assets/fonts/ttf/PixelOperatorMono8.ttf new file mode 100644 index 0000000..2fc70fa --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorMono8.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b627505e178c0c51b0ce7d432f2974fdc2064339f17fb5242b7237becad3c467 +size 19872 diff --git a/godot/assets/fonts/ttf/PixelOperatorMonoHB.ttf b/godot/assets/fonts/ttf/PixelOperatorMonoHB.ttf new file mode 100644 index 0000000..11d13d2 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorMonoHB.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae7eda40c2fb15e3672a79dee3860d13ab62b3e25f0cccee770b3f45b84c4955 +size 17120 diff --git a/godot/assets/fonts/ttf/PixelOperatorMonoHB8.ttf b/godot/assets/fonts/ttf/PixelOperatorMonoHB8.ttf new file mode 100644 index 0000000..56b4a78 --- /dev/null +++ b/godot/assets/fonts/ttf/PixelOperatorMonoHB8.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cc07440ab17ad773fb2814c028d8fe70ecab835f2a577c081a3d226b256be92 +size 19020 diff --git a/godot/assets/music/level2.ogg b/godot/assets/music/level2.ogg new file mode 100644 index 0000000..548241f --- /dev/null +++ b/godot/assets/music/level2.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f80b1f828f132293790f730b899596631e3f5de834dca0bc66d4335ba648893 +size 1053717 diff --git a/godot/assets/music/level2.ogg.import b/godot/assets/music/level2.ogg.import new file mode 100644 index 0000000..54354c0 --- /dev/null +++ b/godot/assets/music/level2.ogg.import @@ -0,0 +1,15 @@ +[remap] + +importer="ogg_vorbis" +type="AudioStreamOGGVorbis" +path="res://.import/level2.ogg-0cba17639fcb1c4e45dc4f01c5837760.oggstr" + +[deps] + +source_file="res://assets/music/level2.ogg" +dest_files=[ "res://.import/level2.ogg-0cba17639fcb1c4e45dc4f01c5837760.oggstr" ] + +[params] + +loop=true +loop_offset=0 diff --git a/godot/assets/sounds/coin.wav b/godot/assets/sounds/coin.wav new file mode 100644 index 0000000..437d810 --- /dev/null +++ b/godot/assets/sounds/coin.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3feda8ae12b154d33c41d286bfc8423acb5bd30027de8590b44179ccdaefe0f6 +size 132564 diff --git a/godot/assets/sounds/coin.wav.import b/godot/assets/sounds/coin.wav.import new file mode 100644 index 0000000..f7e7100 --- /dev/null +++ b/godot/assets/sounds/coin.wav.import @@ -0,0 +1,23 @@ +[remap] + +importer="wav" +type="AudioStreamSample" +path="res://.import/coin.wav-9081ee1c6d81d9c34d08bc916297b892.sample" + +[deps] + +source_file="res://assets/sounds/coin.wav" +dest_files=[ "res://.import/coin.wav-9081ee1c6d81d9c34d08bc916297b892.sample" ] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/godot/assets/sounds/died.wav b/godot/assets/sounds/died.wav new file mode 100644 index 0000000..96f68c5 --- /dev/null +++ b/godot/assets/sounds/died.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ef38b521ccfa436c210c13ba14731b093fc1c6564da6e6d5a008c959c9cb517 +size 857132 diff --git a/godot/assets/sounds/died.wav.import b/godot/assets/sounds/died.wav.import new file mode 100644 index 0000000..b92b919 --- /dev/null +++ b/godot/assets/sounds/died.wav.import @@ -0,0 +1,23 @@ +[remap] + +importer="wav" +type="AudioStreamSample" +path="res://.import/died.wav-fc4528ad616bbce5115ae092cb80d346.sample" + +[deps] + +source_file="res://assets/sounds/died.wav" +dest_files=[ "res://.import/died.wav-fc4528ad616bbce5115ae092cb80d346.sample" ] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/godot/assets/sounds/gem.wav b/godot/assets/sounds/gem.wav new file mode 100644 index 0000000..b4eb998 --- /dev/null +++ b/godot/assets/sounds/gem.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec7fa9358699bc8f9be0cb47c027efc2099803f5fc81d24aac066ae5f2b3a406 +size 145348 diff --git a/godot/assets/sounds/gem.wav.import b/godot/assets/sounds/gem.wav.import new file mode 100644 index 0000000..60eb36b --- /dev/null +++ b/godot/assets/sounds/gem.wav.import @@ -0,0 +1,23 @@ +[remap] + +importer="wav" +type="AudioStreamSample" +path="res://.import/gem.wav-49535e5638777427fa416449f386aaf6.sample" + +[deps] + +source_file="res://assets/sounds/gem.wav" +dest_files=[ "res://.import/gem.wav-49535e5638777427fa416449f386aaf6.sample" ] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/godot/assets/sounds/jump.wav b/godot/assets/sounds/jump.wav new file mode 100644 index 0000000..03982ea --- /dev/null +++ b/godot/assets/sounds/jump.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:147904084c9eaea71eae200292905b3adb41d862e0e09b5aab866cfb28ba4576 +size 176602 diff --git a/godot/assets/sounds/jump.wav.import b/godot/assets/sounds/jump.wav.import new file mode 100644 index 0000000..f8e1faf --- /dev/null +++ b/godot/assets/sounds/jump.wav.import @@ -0,0 +1,23 @@ +[remap] + +importer="wav" +type="AudioStreamSample" +path="res://.import/jump.wav-395b727cde98999423d5c020c9c3492f.sample" + +[deps] + +source_file="res://assets/sounds/jump.wav" +dest_files=[ "res://.import/jump.wav-395b727cde98999423d5c020c9c3492f.sample" ] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/godot/assets/sounds/ui_popup.wav b/godot/assets/sounds/ui_popup.wav new file mode 100644 index 0000000..f00a22a --- /dev/null +++ b/godot/assets/sounds/ui_popup.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7af5be9759b98365633e251a6a0c72f4840975f141a9d57e40ea70ab4beebbc2 +size 51772 diff --git a/godot/assets/sounds/ui_popup.wav.import b/godot/assets/sounds/ui_popup.wav.import new file mode 100644 index 0000000..679a364 --- /dev/null +++ b/godot/assets/sounds/ui_popup.wav.import @@ -0,0 +1,23 @@ +[remap] + +importer="wav" +type="AudioStreamSample" +path="res://.import/ui_popup.wav-b70bc280bf50aa4e775c08111118c3ae.sample" + +[deps] + +source_file="res://assets/sounds/ui_popup.wav" +dest_files=[ "res://.import/ui_popup.wav-b70bc280bf50aa4e775c08111118c3ae.sample" ] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/godot/assets/sounds/ui_select.wav b/godot/assets/sounds/ui_select.wav new file mode 100644 index 0000000..ec3580d --- /dev/null +++ b/godot/assets/sounds/ui_select.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e43e035f6953c9854eee64f2f45b8d7d7107a412b82bbbe625253e1103c1bbb1 +size 62564 diff --git a/godot/assets/sounds/ui_select.wav.import b/godot/assets/sounds/ui_select.wav.import new file mode 100644 index 0000000..3e3d8c0 --- /dev/null +++ b/godot/assets/sounds/ui_select.wav.import @@ -0,0 +1,23 @@ +[remap] + +importer="wav" +type="AudioStreamSample" +path="res://.import/ui_select.wav-a1e6656879b8474ab79f3a15e3073001.sample" + +[deps] + +source_file="res://assets/sounds/ui_select.wav" +dest_files=[ "res://.import/ui_select.wav-a1e6656879b8474ab79f3a15e3073001.sample" ] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/godot/characters/enemies/WalkingEnemy.gd b/godot/characters/enemies/WalkingEnemy.gd new file mode 100644 index 0000000..c1c54b5 --- /dev/null +++ b/godot/characters/enemies/WalkingEnemy.gd @@ -0,0 +1,38 @@ +extends KinematicBody2D + + +signal player_touched + + +var velocity = Vector2() +export var direction = -1 +export var detect_edges = true +export var speed = 25 +export var gravity = 9.8 + + +func _ready() -> void: + if direction == 1: + $AnimatedSprite.flip_h = true + $FloorChecker.position.x = $CollisionShape2D.shape.get_extents().x * direction + $FloorChecker.enabled = detect_edges + + +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 + + 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": + emit_signal("player_touched") + + +func squash() -> void: + queue_free() diff --git a/godot/characters/enemies/blightwing/Blightwing.gd b/godot/characters/enemies/blightwing/Blightwing.gd new file mode 100644 index 0000000..6186bea --- /dev/null +++ b/godot/characters/enemies/blightwing/Blightwing.gd @@ -0,0 +1,82 @@ +extends KinematicBody2D + + +signal player_touched + + +export var direction = -1 +export var speed = 50 +export var follow_path = false +var target: Vector2 = Vector2(0, 0) +var target_id = 0 +var start_position = Vector2() + + +func _ready() -> void: + start_position = position + if follow_path: + if $Path.get_child_count() == 0: + follow_path = false + else: + target = $Path.get_child(0).position + if direction == 1: + $AnimatedSprite.flip_h = true + + +func _physics_process(delta: float) -> void: + if $LeftWallChecker.is_colliding(): + wall_checker_collided($LeftWallChecker) + elif $RightWallChecker.is_colliding(): + wall_checker_collided($RightWallChecker) + + 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) + 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) + + var collision = move_and_collide(velocity, true, true, true) + if collision and collision.collider.name != "Player": + var _collision = move_and_collide(velocity) + else: + position = position.move_toward(start_position + target, round(speed * delta)) + + if position == start_position + target: + if $Path.get_child_count() - 1 == target_id: + target_id = -1 + target = $Path.position + else: + target_id += 1 + target = $Path.get_child(target_id).position + + if start_position.x + target.x > position.x: + $AnimatedSprite.flip_h = true + elif start_position.x + target.x < position.x: + $AnimatedSprite.flip_h = false + + +func get_velocity_towards_target(delta: float) -> Vector2: + var velocity = Vector2(0, 0) + if start_position.x + target.x > position.x: + velocity.x = speed * delta + elif start_position.x + target.x < position.x: + velocity.x = -speed * delta + + if start_position.y + target.y > position.y: + velocity.y = speed * delta + elif start_position.y + target.y < position.y: + velocity.y = -speed * delta + return velocity + + +func wall_checker_collided(wall_checker: RayCast2D) -> void: + if wall_checker.get_collider().name == "Player": + emit_signal("player_touched") + direction *= -1 + $AnimatedSprite.flip_h = not $AnimatedSprite.flip_h diff --git a/godot/characters/enemies/blightwing/Blightwing.tscn b/godot/characters/enemies/blightwing/Blightwing.tscn new file mode 100644 index 0000000..4173207 --- /dev/null +++ b/godot/characters/enemies/blightwing/Blightwing.tscn @@ -0,0 +1,55 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] +[ext_resource path="res://characters/enemies/blightwing/Blightwing.gd" type="Script" id=2] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 144, 48, 24, 24 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 168, 48, 24, 24 ) + +[sub_resource type="AtlasTexture" id=3] +atlas = ExtResource( 1 ) +region = Rect2( 192, 48, 24, 24 ) + +[sub_resource type="SpriteFrames" id=4] +animations = [ { +"frames": [ SubResource( 1 ), SubResource( 2 ), SubResource( 3 ), SubResource( 2 ) ], +"loop": true, +"name": "fly", +"speed": 6.0 +} ] + +[sub_resource type="RectangleShape2D" id=5] +extents = Vector2( 4.5, 5 ) + +[node name="Blightwing" type="KinematicBody2D" groups=["enemy", "rideable"]] +collision_layer = 8 +collision_mask = 11 +script = ExtResource( 2 ) + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 4 ) +animation = "fly" +frame = 3 +playing = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( 1.66894e-06, 1.5 ) +rotation = 1.5708 +shape = SubResource( 5 ) + +[node name="LeftWallChecker" type="RayCast2D" parent="."] +rotation = 1.5708 +enabled = true +cast_to = Vector2( 0, 10 ) +collision_mask = 11 + +[node name="RightWallChecker" type="RayCast2D" parent="."] +rotation = -1.5708 +enabled = true +cast_to = Vector2( 0, 10 ) +collision_mask = 11 diff --git a/godot/characters/enemies/blockface/Blockface.gd b/godot/characters/enemies/blockface/Blockface.gd new file mode 100644 index 0000000..b307882 --- /dev/null +++ b/godot/characters/enemies/blockface/Blockface.gd @@ -0,0 +1,27 @@ +extends KinematicBody2D + + +signal player_touched + + +onready var start_position = position +var velocity = Vector2() +export var speed = 50.0 +export var fall_speed = 75.0 +var return_to_start: bool = false + + +func _physics_process(delta: float) -> void: + if return_to_start: + position = position.move_toward(start_position, speed * delta) + else: + var collision = move_and_collide(Vector2(0, (position.y + fall_speed) * delta)) + if collision: + return_to_start = true + $AnimatedSprite.play("normal") + if collision.collider.name == "Player": + emit_signal("player_touched") + + if position.y <= start_position.y: + return_to_start = false + $AnimatedSprite.play("angry") diff --git a/godot/characters/enemies/blockface/Blockface.tscn b/godot/characters/enemies/blockface/Blockface.tscn new file mode 100644 index 0000000..afd9d0d --- /dev/null +++ b/godot/characters/enemies/blockface/Blockface.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=7 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] +[ext_resource path="res://characters/enemies/blockface/Blockface.gd" type="Script" id=2] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 96, 24, 24, 24 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 120, 24, 24, 24 ) + +[sub_resource type="SpriteFrames" id=3] +animations = [ { +"frames": [ SubResource( 1 ) ], +"loop": true, +"name": "normal", +"speed": 5.0 +}, { +"frames": [ SubResource( 2 ) ], +"loop": true, +"name": "angry", +"speed": 5.0 +} ] + +[sub_resource type="RectangleShape2D" id=4] +extents = Vector2( 9, 9 ) + +[node name="Blockface" type="KinematicBody2D" groups=["enemy", "rideable"]] +collision_layer = 8 +collision_mask = 11 +script = ExtResource( 2 ) + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 3 ) +animation = "normal" + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 4 ) diff --git a/godot/characters/enemies/dreadtooth/Dreadtooth.gd b/godot/characters/enemies/dreadtooth/Dreadtooth.gd new file mode 100644 index 0000000..32e2fdf --- /dev/null +++ b/godot/characters/enemies/dreadtooth/Dreadtooth.gd @@ -0,0 +1 @@ +extends "res://characters/enemies/WalkingEnemy.gd" diff --git a/godot/characters/enemies/dreadtooth/Dreadtooth.tscn b/godot/characters/enemies/dreadtooth/Dreadtooth.tscn new file mode 100644 index 0000000..0315c52 --- /dev/null +++ b/godot/characters/enemies/dreadtooth/Dreadtooth.tscn @@ -0,0 +1,55 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] +[ext_resource path="res://characters/enemies/dreadtooth/Dreadtooth.gd" type="Script" id=2] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 192, 24, 24, 24 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 144, 24, 24, 24 ) + +[sub_resource type="AtlasTexture" id=3] +atlas = ExtResource( 1 ) +region = Rect2( 168, 24, 24, 24 ) + +[sub_resource type="SpriteFrames" id=4] +animations = [ { +"frames": [ SubResource( 1 ) ], +"loop": true, +"name": "hide", +"speed": 5.0 +}, { +"frames": [ SubResource( 2 ), SubResource( 3 ) ], +"loop": true, +"name": "walk", +"speed": 5.0 +} ] + +[sub_resource type="RectangleShape2D" id=5] +extents = Vector2( 7.5, 6.5 ) + +[node name="Dreadtooth" type="KinematicBody2D" groups=["enemy"]] +collision_layer = 8 +collision_mask = 11 +script = ExtResource( 2 ) + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 4 ) +animation = "walk" +frame = 1 +playing = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( -0.5, 5.5 ) +shape = SubResource( 5 ) + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."] +polygon = PoolVector2Array( 0, -7, 3, -4, 3, -1, -4, -1, -4, -4, -1, -7 ) + +[node name="FloorChecker" type="RayCast2D" parent="."] +enabled = true +cast_to = Vector2( 0, 20 ) +collision_mask = 10 diff --git a/godot/characters/enemies/gravevine/Gravevine.tscn b/godot/characters/enemies/gravevine/Gravevine.tscn new file mode 100644 index 0000000..386a83f --- /dev/null +++ b/godot/characters/enemies/gravevine/Gravevine.tscn @@ -0,0 +1,35 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 48, 24, 24, 24 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 72, 24, 24, 24 ) + +[sub_resource type="SpriteFrames" id=3] +animations = [ { +"frames": [ SubResource( 1 ), SubResource( 2 ) ], +"loop": true, +"name": "default", +"speed": 5.0 +} ] + +[sub_resource type="RectangleShape2D" id=4] +extents = Vector2( 5.5, 7.5 ) + +[node name="Gravevine" type="KinematicBody2D" groups=["enemy"]] +collision_layer = 8 +collision_mask = 11 + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 3 ) +frame = 1 +playing = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( -0.5, 0.5 ) +shape = SubResource( 4 ) diff --git a/godot/characters/enemies/shelly/Shelly.gd b/godot/characters/enemies/shelly/Shelly.gd new file mode 100644 index 0000000..32e2fdf --- /dev/null +++ b/godot/characters/enemies/shelly/Shelly.gd @@ -0,0 +1 @@ +extends "res://characters/enemies/WalkingEnemy.gd" diff --git a/godot/characters/enemies/shelly/Shelly.tscn b/godot/characters/enemies/shelly/Shelly.tscn new file mode 100644 index 0000000..0b23ae6 --- /dev/null +++ b/godot/characters/enemies/shelly/Shelly.tscn @@ -0,0 +1,51 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] +[ext_resource path="res://characters/enemies/shelly/Shelly.gd" type="Script" id=2] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 48, 48, 24, 24 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 0, 48, 24, 24 ) + +[sub_resource type="AtlasTexture" id=3] +atlas = ExtResource( 1 ) +region = Rect2( 24, 48, 24, 24 ) + +[sub_resource type="SpriteFrames" id=4] +animations = [ { +"frames": [ SubResource( 1 ) ], +"loop": true, +"name": "hide", +"speed": 5.0 +}, { +"frames": [ SubResource( 2 ), SubResource( 3 ) ], +"loop": true, +"name": "walk", +"speed": 3.0 +} ] + +[sub_resource type="RectangleShape2D" id=5] +extents = Vector2( 7.5, 6.5 ) + +[node name="Shelly" type="KinematicBody2D" groups=["enemy", "squashable"]] +collision_layer = 8 +collision_mask = 11 +script = ExtResource( 2 ) + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 4 ) +animation = "walk" +playing = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( 1, 5.5 ) +shape = SubResource( 5 ) + +[node name="FloorChecker" type="RayCast2D" parent="."] +enabled = true +cast_to = Vector2( 0, 20 ) +collision_mask = 10 diff --git a/godot/characters/enemies/spikeball/Spikeball.tscn b/godot/characters/enemies/spikeball/Spikeball.tscn new file mode 100644 index 0000000..ce2caad --- /dev/null +++ b/godot/characters/enemies/spikeball/Spikeball.tscn @@ -0,0 +1,28 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 192, 0, 24, 24 ) + +[sub_resource type="SpriteFrames" id=2] +animations = [ { +"frames": [ SubResource( 1 ) ], +"loop": true, +"name": "default", +"speed": 5.0 +} ] + +[sub_resource type="CircleShape2D" id=3] +radius = 9.05539 + +[node name="Spikeball" type="KinematicBody2D" groups=["enemy"]] +collision_layer = 8 +collision_mask = 11 + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 2 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource( 3 ) diff --git a/godot/characters/enemies/super_shelly/SuperShelly.gd b/godot/characters/enemies/super_shelly/SuperShelly.gd new file mode 100644 index 0000000..32e2fdf --- /dev/null +++ b/godot/characters/enemies/super_shelly/SuperShelly.gd @@ -0,0 +1 @@ +extends "res://characters/enemies/WalkingEnemy.gd" diff --git a/godot/characters/enemies/super_shelly/SuperShelly.tscn b/godot/characters/enemies/super_shelly/SuperShelly.tscn new file mode 100644 index 0000000..a7259db --- /dev/null +++ b/godot/characters/enemies/super_shelly/SuperShelly.tscn @@ -0,0 +1,52 @@ +[gd_scene load_steps=8 format=2] + +[ext_resource path="res://assets/characters/characters.png" type="Texture" id=1] +[ext_resource path="res://characters/enemies/super_shelly/SuperShelly.gd" type="Script" id=2] + +[sub_resource type="AtlasTexture" id=1] +atlas = ExtResource( 1 ) +region = Rect2( 120, 48, 24, 24 ) + +[sub_resource type="AtlasTexture" id=2] +atlas = ExtResource( 1 ) +region = Rect2( 72, 48, 24, 24 ) + +[sub_resource type="AtlasTexture" id=3] +atlas = ExtResource( 1 ) +region = Rect2( 96, 48, 24, 24 ) + +[sub_resource type="SpriteFrames" id=4] +animations = [ { +"frames": [ SubResource( 1 ) ], +"loop": true, +"name": "hide", +"speed": 5.0 +}, { +"frames": [ SubResource( 2 ), SubResource( 3 ) ], +"loop": true, +"name": "walk", +"speed": 3.0 +} ] + +[sub_resource type="RectangleShape2D" id=5] +extents = Vector2( 12, 10.5 ) + +[node name="SuperShelly" type="KinematicBody2D" groups=["enemy", "squashable"]] +collision_layer = 8 +collision_mask = 11 +script = ExtResource( 2 ) + +[node name="AnimatedSprite" type="AnimatedSprite" parent="."] +frames = SubResource( 4 ) +animation = "walk" +frame = 1 +playing = true + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2( 0, 1.5 ) +shape = SubResource( 5 ) + +[node name="FloorChecker" type="RayCast2D" parent="."] +enabled = true +cast_to = Vector2( 0, 20 ) +collision_mask = 10 diff --git a/godot/characters/player/Player.tscn b/godot/characters/player/Player.tscn index 858efb3..89b38d9 100644 --- a/godot/characters/player/Player.tscn +++ b/godot/characters/player/Player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://characters/player/sprites/green.tres" type="SpriteFrames" id=1] [ext_resource path="res://characters/player/states/Idle.gdns" type="Script" id=2] @@ -7,12 +7,13 @@ [ext_resource path="res://characters/player/Player.gdns" type="Script" id=5] [ext_resource path="res://characters/player/states/Jump.gdns" type="Script" id=6] [ext_resource path="res://characters/player/states/Fall.gdns" type="Script" id=7] +[ext_resource path="res://assets/sounds/jump.wav" type="AudioStream" id=8] [sub_resource type="RectangleShape2D" id=1] extents = Vector2( 7, 12 ) [node name="Player" type="KinematicBody2D"] -collision_mask = 2 +collision_mask = 10 script = ExtResource( 5 ) [node name="AnimatedSprite" type="AnimatedSprite" parent="."] @@ -40,3 +41,14 @@ script = ExtResource( 6 ) [node name="Fall" type="Node" parent="StateMachine"] script = ExtResource( 7 ) + +[node name="PlatformDetector" type="RayCast2D" parent="."] +position = Vector2( 12, 0 ) +enabled = true +cast_to = Vector2( 0, 32 ) +collision_mask = 24 + +[node name="Sounds" type="Node" parent="."] + +[node name="Jump" type="AudioStreamPlayer" parent="Sounds"] +stream = ExtResource( 8 ) diff --git a/godot/levels/Level2.tscn b/godot/levels/Level2.tscn index 717c1fe..811360b 100644 --- a/godot/levels/Level2.tscn +++ b/godot/levels/Level2.tscn @@ -1,9 +1,11 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://CameraLimit.gdns" type="Script" id=1] [ext_resource path="res://characters/player/Player.tscn" type="PackedScene" id=2] [ext_resource path="res://assets/backgrounds/hills.png" type="Texture" id=3] [ext_resource path="res://levels/Level2.tmx" type="PackedScene" id=4] +[ext_resource path="res://assets/music/level2.ogg" type="AudioStream" id=5] +[ext_resource path="res://levels/MusicPlayer.gd" type="Script" id=6] [node name="Level2" type="Node2D"] @@ -39,3 +41,8 @@ centered = false [node name="Level2" parent="Map" instance=ExtResource( 4 )] script = ExtResource( 1 ) + +[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] +pause_mode = 2 +stream = ExtResource( 5 ) +script = ExtResource( 6 ) diff --git a/godot/levels/MusicPlayer.gd b/godot/levels/MusicPlayer.gd new file mode 100644 index 0000000..ab397b1 --- /dev/null +++ b/godot/levels/MusicPlayer.gd @@ -0,0 +1,16 @@ +extends AudioStreamPlayer + + +# there is currently a bug with AudioStreamPlayer +# it doesn't pause when the tree is paused +# so let's manually check if paused and pause the audio +# for this to work pause mode for the node is set to process instead of inherit + + +func _physics_process(_delta: float) -> void: + if get_tree().paused and playing: + stop() + playing = false + elif not get_tree().paused and not playing: + play() + playing = true diff --git a/godot/levels/PrototypeEnemies.tmx b/godot/levels/PrototypeEnemies.tmx new file mode 100644 index 0000000..34a536c --- /dev/null +++ b/godot/levels/PrototypeEnemies.tmx @@ -0,0 +1,40 @@ + + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24 + + + diff --git a/godot/levels/PrototypeEnemies.tmx.import b/godot/levels/PrototypeEnemies.tmx.import new file mode 100644 index 0000000..2113587 --- /dev/null +++ b/godot/levels/PrototypeEnemies.tmx.import @@ -0,0 +1,24 @@ +[remap] + +importer="vnen.tiled_importer" +type="PackedScene" +path="res://.import/PrototypeEnemies.tmx-5728a1d35b5e3ba88a2df2406b1cd931.scn" + +[deps] + +source_file="res://levels/PrototypeEnemies.tmx" +dest_files=[ "res://.import/PrototypeEnemies.tmx-5728a1d35b5e3ba88a2df2406b1cd931.scn" ] + +[params] + +custom_properties=true +tile_metadata=false +uv_clip=false +y_sort=false +image_flags=0 +collision_layer=2 +collision_mask=0 +embed_internal_images=false +save_tiled_properties=false +add_background=true +post_import_script="" diff --git a/godot/levels/PrototypeEnemies.tscn b/godot/levels/PrototypeEnemies.tscn new file mode 100644 index 0000000..d53033f --- /dev/null +++ b/godot/levels/PrototypeEnemies.tscn @@ -0,0 +1,98 @@ +[gd_scene load_steps=12 format=2] + +[ext_resource path="res://CameraLimit.gdns" type="Script" id=1] +[ext_resource path="res://characters/player/Player.tscn" type="PackedScene" id=2] +[ext_resource path="res://levels/PrototypeEnemies.tmx" type="PackedScene" id=3] +[ext_resource path="res://assets/backgrounds/mountains.png" type="Texture" id=4] +[ext_resource path="res://characters/enemies/gravevine/Gravevine.tscn" type="PackedScene" id=5] +[ext_resource path="res://characters/enemies/dreadtooth/Dreadtooth.tscn" type="PackedScene" id=6] +[ext_resource path="res://characters/enemies/super_shelly/SuperShelly.tscn" type="PackedScene" id=7] +[ext_resource path="res://characters/enemies/spikeball/Spikeball.tscn" type="PackedScene" id=8] +[ext_resource path="res://characters/enemies/shelly/Shelly.tscn" type="PackedScene" id=9] +[ext_resource path="res://characters/enemies/blockface/Blockface.tscn" type="PackedScene" id=10] +[ext_resource path="res://characters/enemies/blightwing/Blightwing.tscn" type="PackedScene" id=11] + +[node name="PrototypeEnemies" type="Node"] + +[node name="Player" parent="." instance=ExtResource( 2 )] +position = Vector2( 156, 438 ) +collision/safe_margin = 0.12 + +[node name="Camera2D" type="Camera2D" parent="Player"] +current = true +limit_left = 0 +limit_top = 0 +limit_right = 512 +limit_bottom = 288 +drag_margin_h_enabled = true +drag_margin_v_enabled = true +__meta__ = { +"_edit_bone_": true +} + +[node name="VisibilityNotifier2D" type="VisibilityNotifier2D" parent="Player/Camera2D"] +rect = Rect2( 0, 0, 24, 24 ) + +[node name="ParallaxBackground" type="ParallaxBackground" parent="."] + +[node name="ParallaxLayer" type="ParallaxLayer" parent="ParallaxBackground"] +motion_scale = Vector2( 0.2, 0.1 ) +motion_offset = Vector2( 0, -288 ) +motion_mirroring = Vector2( 528, 0 ) + +[node name="Sprite" type="Sprite" parent="ParallaxBackground/ParallaxLayer"] +texture = ExtResource( 4 ) +centered = false + +[node name="Map" type="Node" parent="."] + +[node name="PrototypeEnemies" parent="Map" instance=ExtResource( 3 )] +script = ExtResource( 1 ) + +[node name="Enemies" type="Node" parent="."] +unique_name_in_owner = true + +[node name="Spikeball" parent="Enemies" instance=ExtResource( 8 )] +position = Vector2( 106, 547 ) + +[node name="Blightwing" parent="Enemies" instance=ExtResource( 11 )] +position = Vector2( 488, 400 ) +follow_path = true + +[node name="Path" type="Node2D" parent="Enemies/Blightwing"] + +[node name="Node2D" type="Node2D" parent="Enemies/Blightwing/Path"] +position = Vector2( 0, 96 ) + +[node name="Node2D2" type="Node2D" parent="Enemies/Blightwing/Path"] +position = Vector2( -128, 96 ) + +[node name="Node2D3" type="Node2D" parent="Enemies/Blightwing/Path"] +position = Vector2( -128, 0 ) + +[node name="Blockface" parent="Enemies" instance=ExtResource( 10 )] +position = Vector2( 206, 404 ) + +[node name="Dreadtooth" parent="Enemies" instance=ExtResource( 6 )] +position = Vector2( 316, 379 ) + +[node name="Dreadtooth2" parent="Enemies" instance=ExtResource( 6 )] +position = Vector2( 350, 263 ) +direction = 1 +detect_edges = false + +[node name="Gravevine" parent="Enemies" instance=ExtResource( 5 )] +position = Vector2( 250, 550 ) + +[node name="Shelly" parent="Enemies" instance=ExtResource( 9 )] +position = Vector2( 247, 439 ) + +[node name="SuperShelly" parent="Enemies" instance=ExtResource( 7 )] +position = Vector2( 62, 546 ) + +[connection signal="player_touched" from="Enemies/Blightwing" to="Player" method="_on_player_touched"] +[connection signal="player_touched" from="Enemies/Blockface" to="Player" method="_on_player_touched"] +[connection signal="player_touched" from="Enemies/Dreadtooth" to="Player" method="_on_player_touched"] +[connection signal="player_touched" from="Enemies/Dreadtooth2" to="Player" method="_on_player_touched"] +[connection signal="player_touched" from="Enemies/Shelly" to="Player" method="_on_player_touched"] +[connection signal="player_touched" from="Enemies/SuperShelly" to="Player" method="_on_player_touched"] diff --git a/godot/monitor/EnterButton.gd b/godot/monitor/EnterButton.gd new file mode 100644 index 0000000..de051dd --- /dev/null +++ b/godot/monitor/EnterButton.gd @@ -0,0 +1,123 @@ +extends Button + + +signal input_validated(player) + + +func is_valid_name(name: String) -> bool: + if name.strip_edges() == "": + print_debug("Name is empty!") + return false + if name.split(" ").size() == 1: + print_debug("Doesn't contain at least a first and last name!") + return false + return true + + +func is_valid_rut(rut: String) -> bool: + var rut_node = get_node("%Rut") + rut = rut_node.clean_rut(rut) + if rut.length() < 8 or rut.length() > 9: + print_debug("RUT length is invalid!") + return false + + var rut_temp: String = rut.substr(0, rut.length() - 1) + var verifier: String = rut.substr(rut.length() - 1, 1) + + if not rut_temp.is_valid_integer(): + print_debug("RUT isn't a valid integer!") + return false + + if rut_temp.to_int() > 50000000: + print_debug("RUT is too large, that is a company!") + return false + + if verifier != generate_verifier(rut_temp): + return false + + return true + + +func generate_verifier(rut: String) -> String: + if not rut.is_valid_integer(): + print_debug("RUT isn't a valid integer!") + return "" + + var multiplier: int = 2 + var sum: int = 0 + var remainder: int = 0 + var division: int = 0 + var rut_length: int = rut.length() + + var i: int = rut_length - 1 + while i >= 0: + sum = sum + rut.substr(i, 1).to_int() * multiplier + multiplier = multiplier + 1 + if multiplier == 8: + multiplier = 2 + i = i - 1 + + var tempSum: float = sum + division = int(floor(tempSum / 11)) + division = division * 11 + remainder = sum - division + + if remainder != 0: + remainder = 11 - remainder + + if remainder == 10: + return "k" + else: + return String(remainder) + + +func is_valid_email(email: String) -> bool: + var regex = RegEx.new() + regex.compile("\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+") + if regex.search(email) == null: + print_debug("Isn't a valid email address!") + return false + return true + + +func _on_Button_pressed() -> void: + var name = get_node("%Name") + var rut = get_node("%Rut") + var email = get_node("%Email") + var player: Dictionary = { + "name" : name.text, + "rut" : get_node("%Rut").clean_rut(rut.text), + "email" : email.text + } + + if not is_valid_name(player.name): + show_error_message("Ingresa un nombre completo valido por favor!") + return + + if not is_valid_rut(player.rut): + show_error_message("Ingresa un RUT valido por favor!") + return + + if not is_valid_email(player.email): + show_error_message("Ingresa un email valido por favor!") + return + + emit_signal("input_validated", player) + + +func show_error_message(message: String) -> void: + var popup = get_node("%PopupDialog") + popup.get_node("ErrorMessage").text = message + popup.popup() + popup.focus_mode = Control.FOCUS_ALL + popup.grab_focus() + + +func _on_PopupDialog_gui_input(event: InputEvent) -> void: + var popup = get_node("%PopupDialog") + if popup.visible and event.is_pressed(): + popup.call_deferred("hide") + + +func _on_text_entered(_new_text: String) -> void: + call_deferred("_on_Button_pressed") diff --git a/godot/monitor/GUI.tscn b/godot/monitor/GUI.tscn new file mode 100644 index 0000000..c5d0203 --- /dev/null +++ b/godot/monitor/GUI.tscn @@ -0,0 +1,249 @@ +[gd_scene load_steps=18 format=2] + +[ext_resource path="res://assets/fonts/data/PixelOperator.tres" type="DynamicFontData" id=1] +[ext_resource path="res://assets/fonts/data/PixelOperator-Bold.tres" type="DynamicFontData" id=2] +[ext_resource path="res://monitor/Rut.gd" type="Script" id=3] +[ext_resource path="res://monitor/UISounds.gd" type="Script" id=4] +[ext_resource path="res://monitor/EnterButton.gd" type="Script" id=5] +[ext_resource path="res://assets/sounds/ui_popup.wav" type="AudioStream" id=6] +[ext_resource path="res://assets/sounds/ui_select.wav" type="AudioStream" id=7] +[ext_resource path="res://monitor/MonitorGUI.gd" type="Script" id=8] + +[sub_resource type="DynamicFont" id=1] +font_data = ExtResource( 1 ) + +[sub_resource type="DynamicFont" id=14] +size = 8 +extra_spacing_top = 4 +font_data = ExtResource( 1 ) + +[sub_resource type="StyleBoxFlat" id=13] +content_margin_left = 5.0 +content_margin_right = 5.0 +content_margin_top = 2.0 +content_margin_bottom = 2.0 +bg_color = Color( 0.313726, 0.290196, 0.290196, 0.752941 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="DynamicFont" id=11] +size = 12 +extra_spacing_top = 2 +extra_spacing_bottom = 2 +extra_spacing_char = 2 +extra_spacing_space = 2 +font_data = ExtResource( 2 ) + +[sub_resource type="StyleBoxFlat" id=12] +content_margin_left = 5.0 +content_margin_right = 5.0 +content_margin_top = 5.0 +content_margin_bottom = 5.0 +bg_color = Color( 0.313726, 0.290196, 0.290196, 0.752941 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="InputEventAction" id=17] +action = "ui_accept" +pressed = true + +[sub_resource type="ShortCut" id=18] +shortcut = SubResource( 17 ) + +[sub_resource type="StyleBoxFlat" id=15] +bg_color = Color( 0.239216, 0.239216, 0.239216, 1 ) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 +expand_margin_left = 5.0 +expand_margin_right = 5.0 +expand_margin_top = 5.0 +expand_margin_bottom = 5.0 + +[sub_resource type="DynamicFont" id=16] +font_data = ExtResource( 2 ) + +[node name="MonitorGUI" type="CanvasLayer"] +pause_mode = 2 +script = ExtResource( 8 ) + +[node name="ColorRect" type="ColorRect" parent="."] +margin_right = 40.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 512, 288 ) +color = Color( 0.0117647, 0.00784314, 0.00784314, 0.376471 ) + +[node name="GUI" type="Control" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +rect_min_size = Vector2( 512, 0 ) + +[node name="Sounds" type="Node" parent="GUI"] +script = ExtResource( 4 ) + +[node name="Popup" type="AudioStreamPlayer" parent="GUI/Sounds"] +stream = ExtResource( 6 ) + +[node name="Menu" type="AudioStreamPlayer" parent="GUI/Sounds"] +stream = ExtResource( 7 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="GUI"] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +custom_constants/separation = 0 + +[node name="CenterContainer" type="CenterContainer" parent="GUI/VBoxContainer"] +margin_right = 512.0 +margin_bottom = 96.0 +rect_min_size = Vector2( 0, 96 ) +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="GUI/VBoxContainer/CenterContainer"] +margin_top = 30.0 +margin_right = 512.0 +margin_bottom = 65.0 +rect_min_size = Vector2( 512, 0 ) +custom_fonts/font = SubResource( 1 ) +text = "Ingresa su nombre completo, RUT y email por favor!" +align = 1 +autowrap = true + +[node name="CenterContainer2" type="CenterContainer" parent="GUI/VBoxContainer"] +margin_top = 96.0 +margin_right = 512.0 +margin_bottom = 192.0 +rect_min_size = Vector2( 0, 96 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VBoxContainer2" type="VBoxContainer" parent="GUI/VBoxContainer/CenterContainer2"] +margin_left = 16.0 +margin_top = 14.0 +margin_right = 496.0 +margin_bottom = 82.0 +rect_min_size = Vector2( 480, 0 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Name" type="LineEdit" parent="GUI/VBoxContainer/CenterContainer2/VBoxContainer2"] +unique_name_in_owner = true +margin_right = 480.0 +margin_bottom = 20.0 +focus_neighbour_left = NodePath("../../../CenterContainer3/Button") +focus_neighbour_top = NodePath("../../../CenterContainer3/Button") +focus_neighbour_right = NodePath("../Rut") +focus_neighbour_bottom = NodePath("../Rut") +focus_next = NodePath("../Rut") +focus_previous = NodePath("../../../CenterContainer3/Button") +custom_fonts/font = SubResource( 14 ) +custom_styles/normal = SubResource( 13 ) +max_length = 256 +context_menu_enabled = false +clear_button_enabled = true +placeholder_text = "Nombre Completo" +caret_blink = true + +[node name="Rut" type="LineEdit" parent="GUI/VBoxContainer/CenterContainer2/VBoxContainer2"] +unique_name_in_owner = true +margin_top = 24.0 +margin_right = 480.0 +margin_bottom = 44.0 +focus_neighbour_left = NodePath("../Name") +focus_neighbour_top = NodePath("../Name") +focus_neighbour_right = NodePath("../Email") +focus_neighbour_bottom = NodePath("../Email") +focus_next = NodePath("../Email") +focus_previous = NodePath("../Name") +custom_fonts/font = SubResource( 14 ) +custom_styles/normal = SubResource( 13 ) +max_length = 12 +context_menu_enabled = false +clear_button_enabled = true +placeholder_text = "RUT" +caret_blink = true +script = ExtResource( 3 ) + +[node name="Email" type="LineEdit" parent="GUI/VBoxContainer/CenterContainer2/VBoxContainer2"] +unique_name_in_owner = true +margin_top = 48.0 +margin_right = 480.0 +margin_bottom = 68.0 +focus_neighbour_left = NodePath("../Rut") +focus_neighbour_top = NodePath("../Rut") +focus_neighbour_right = NodePath("../../../CenterContainer3/Button") +focus_neighbour_bottom = NodePath("../../../CenterContainer3/Button") +focus_next = NodePath("../../../CenterContainer3/Button") +focus_previous = NodePath("../Rut") +custom_fonts/font = SubResource( 14 ) +custom_styles/normal = SubResource( 13 ) +max_length = 256 +context_menu_enabled = false +clear_button_enabled = true +placeholder_text = "Email" +caret_blink = true + +[node name="CenterContainer3" type="CenterContainer" parent="GUI/VBoxContainer"] +margin_top = 192.0 +margin_right = 512.0 +margin_bottom = 288.0 +rect_min_size = Vector2( 0, 96 ) +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Button" type="Button" parent="GUI/VBoxContainer/CenterContainer3"] +margin_left = 197.0 +margin_top = 34.0 +margin_right = 314.0 +margin_bottom = 61.0 +focus_neighbour_left = NodePath("../../CenterContainer2/VBoxContainer2/Email") +focus_neighbour_top = NodePath("../../CenterContainer2/VBoxContainer2/Email") +focus_neighbour_right = NodePath("../../CenterContainer2/VBoxContainer2/Name") +focus_neighbour_bottom = NodePath("../../CenterContainer2/VBoxContainer2/Name") +focus_next = NodePath("../../CenterContainer2/VBoxContainer2/Name") +focus_previous = NodePath("../../CenterContainer2/VBoxContainer2/Email") +custom_fonts/font = SubResource( 11 ) +custom_styles/normal = SubResource( 12 ) +shortcut_in_tooltip = false +shortcut = SubResource( 18 ) +text = "Ingresar" +script = ExtResource( 5 ) + +[node name="PopupDialog" type="PopupDialog" parent="."] +unique_name_in_owner = true +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 96.0 +margin_top = 96.0 +margin_right = -96.0 +margin_bottom = -96.0 +custom_styles/panel = SubResource( 15 ) + +[node name="ErrorMessage" type="Label" parent="PopupDialog"] +anchor_right = 1.0 +anchor_bottom = 1.0 +size_flags_horizontal = 3 +size_flags_vertical = 7 +custom_fonts/font = SubResource( 16 ) +text = "Error Message" +align = 1 +valign = 1 +autowrap = true + +[connection signal="focus_entered" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Name" to="GUI/Sounds" method="_play_ui_select_sound"] +[connection signal="text_entered" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Name" to="GUI/VBoxContainer/CenterContainer3/Button" method="_on_text_entered"] +[connection signal="focus_entered" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Rut" to="GUI/Sounds" method="_play_ui_select_sound"] +[connection signal="text_changed" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Rut" to="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Rut" method="_on_Rut_text_changed"] +[connection signal="text_entered" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Rut" to="GUI/VBoxContainer/CenterContainer3/Button" method="_on_text_entered"] +[connection signal="focus_entered" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Email" to="GUI/Sounds" method="_play_ui_select_sound"] +[connection signal="text_entered" from="GUI/VBoxContainer/CenterContainer2/VBoxContainer2/Email" to="GUI/VBoxContainer/CenterContainer3/Button" method="_on_text_entered"] +[connection signal="focus_entered" from="GUI/VBoxContainer/CenterContainer3/Button" to="GUI/Sounds" method="_play_ui_select_sound"] +[connection signal="pressed" from="GUI/VBoxContainer/CenterContainer3/Button" to="GUI/VBoxContainer/CenterContainer3/Button" method="_on_Button_pressed"] +[connection signal="focus_entered" from="PopupDialog" to="GUI/Sounds" method="_play_popup_sound"] +[connection signal="gui_input" from="PopupDialog" to="GUI/VBoxContainer/CenterContainer3/Button" method="_on_PopupDialog_gui_input"] diff --git a/godot/monitor/Monitor.gd b/godot/monitor/Monitor.gd new file mode 100644 index 0000000..004c1f9 --- /dev/null +++ b/godot/monitor/Monitor.gd @@ -0,0 +1,227 @@ +extends Node + + +signal monitor_loaded() + + +export var monitor_enabled: 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 +onready var url: String = development_url if use_development_url else url_real + +var start_time: int = 0 +var started: bool = false + +var player: Dictionary = {} +var os_id: int = 0 +var godot_version: Dictionary = Engine.get_version_info() +var processor_count: int = OS.get_processor_count() +var screen_count: int = OS.get_screen_count() +var screen_dpi: int = OS.get_screen_dpi() +var screen_size: Vector2 = OS.get_screen_size() +var machine_id: String = OS.get_unique_id() +var locale: String = OS.get_locale() +var game_version: String +var frames: Array = [] + +var coins: int = 0 +var points: int = 0 +var objects: Array = [] + +const empty_object: Dictionary = { + "name": "Object Name", + "state": "Object State", + "position_x": 0, + "position_y": 0, + "velocity_x": 0, + "velocity_y": 0 +} +const empty_frame: Dictionary = { + "coins": 0, + "points": 0, + "fps": 0, + "elapsed_time": 0, + "objects": [], +} + +# The game dictionary holds all data to be sent to the server +var game: Dictionary = {} + + +func _ready() -> void: + game_version = get_parent().game_version + + player["rut"] = "" + player["name"] = "" + player["email"] = "" + + var os_name = OS.get_name() + if os_name == "Android": + os_id = 1 + elif os_name == "iOS": + os_id = 2 + elif os_name == "HTML5": + os_id = 3 + elif os_name == "OSX": + os_id = 4 + elif os_name == "Server": + os_id = 5 + elif os_name == "Windows": + os_id = 6 + elif os_name == "UWP": + os_id = 7 + elif os_name == "X11": + os_id = 8 + else: + os_id = 0 + + game["player"] = player + game["level_id"] = 0 + game["os_id"] = os_id + game["godot_version"] = godot_version + game["processor_count"] = processor_count + game["machine_id"] = machine_id + game["locale"] = locale + game["screen_count"] = screen_count + game["screen_dpi"] = screen_dpi + game["screen_size"] = screen_size + game["game_version"] = game_version + game["won"] = false + game["timestamp"] = int(Time.get_unix_time_from_system()) + game["frames"] = frames + + var err = $HTTPRequest.connect("request_completed", self, "_on_request_completed") + if err != OK: + print(err) + + err = $MonitorGUI.find_node("Button").connect("input_validated", self, "_on_input_validated") + if err != OK: + print(err) + + +func _physics_process(_delta: float) -> void: + if monitor_enabled: + if has_node("MonitorGUI") and not $MonitorGUI.visible: + $MonitorGUI.visible = true + emit_signal("monitor_loaded") + + if started and not get_tree().paused: + var frame = empty_frame.duplicate(true) + frame["coins"] = coins + frame["points"] = points + frame["fps"] = Engine.get_frames_per_second() + frame["elapsed_time"] = Time.get_ticks_msec() - start_time + + var frame_objects = objects.duplicate() + frame["objects"] = frame_objects + + frames.append(frame) + + if Input.is_action_just_pressed("Send"): + stop_monitor() + send_data() + else: + if Input.is_action_just_pressed("Send"): + start_monitor() + else: + get_tree().paused = false + emit_signal("monitor_loaded") + queue_free() + + +func _on_input_validated(validated_player: Dictionary) -> void: + $MonitorGUI.queue_free() + get_tree().paused = false + player = validated_player.duplicate(true) + game["player"] = player + + +func _object_created(name: String, state: String, position: Vector2, velocity: Vector2) -> void: + if monitor_enabled: + add_object(name, state, position, velocity) + + +func _object_updated(name: String, state: String, position: Vector2, velocity: Vector2) -> void: + if monitor_enabled: + remove_object(name) + add_object(name, state, position, velocity) + + +func _object_removed(name: String) -> void: + if monitor_enabled: + remove_object(name) + + +func start_monitor() -> void: + frames.clear() + game["level_id"] = 2 # PrototypeR + game["won"] = false + game["timestamp"] = int(Time.get_unix_time_from_system()) + start_time = Time.get_ticks_msec() + started = true + + +func stop_monitor() -> void: + started = false + + +func add_object(name: String, state: String, position: Vector2, velocity: Vector2) -> void: + var object = empty_object.duplicate(true) + object["name"] = name + object["state"] = state + object["position_x"] = position.x + object["position_y"] = position.y + object["velocity_x"] = velocity.x + object["velocity_y"] = velocity.y + + objects.append(object) + + +func remove_object(name: String) -> void: + for i in range(0, objects.size()): + if objects[i]["name"] == name: + objects.remove(i) + + +func _on_coin_update(amount: int) -> void: + coins = coins + amount + + +func _on_request_completed(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void: + if result != HTTPRequest.RESULT_SUCCESS: + print_debug("Error: Failed to connect with error code: " + str(result)) + return + + if response_code != HTTPClient.RESPONSE_OK: + print_debug("Error: Failed response with error code: " + str(response_code)) + + print_debug(headers) + if body.size() > 0: + var json = JSON.parse(body.get_string_from_utf8()) + print_debug(JSON.print(json.result, "\t")) + + +func send_data() -> void: + var json = JSON.print(game) + var headers = ["Content-Type: application/json", "Content-Encoding: gzip", "Content-Transfer-Encoding: base64"] + + var body = compress_payload(json) + + print("JSON B: " + String(json.length())) + print("JSON MB: " + String(json.length() / pow(2, 20))) + 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) + + +func compress_payload(payload: String) -> String: + var bytes = payload.to_utf8() + var compressed = bytes.compress(File.COMPRESSION_GZIP) + + var new_payload = Marshalls.raw_to_base64(compressed) + + return new_payload + + diff --git a/godot/monitor/Monitor.tscn b/godot/monitor/Monitor.tscn new file mode 100644 index 0000000..58f135d --- /dev/null +++ b/godot/monitor/Monitor.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://monitor/Monitor.gd" type="Script" id=1] +[ext_resource path="res://monitor/GUI.tscn" type="PackedScene" id=3] + +[node name="Monitor" type="Node"] +pause_mode = 2 +script = ExtResource( 1 ) + +[node name="MonitorGUI" parent="." instance=ExtResource( 3 )] +visible = false + +[node name="HTTPRequest" type="HTTPRequest" parent="."] +pause_mode = 2 diff --git a/godot/monitor/MonitorGUI.gd b/godot/monitor/MonitorGUI.gd new file mode 100644 index 0000000..7502599 --- /dev/null +++ b/godot/monitor/MonitorGUI.gd @@ -0,0 +1,12 @@ +extends CanvasLayer + + +export var default_name = "" +export var default_rut = "" +export var default_email = "" + + +func _ready() -> void: + get_node("%Name").text = default_name + get_node("%Rut").text = default_rut + get_node("%Email").text = default_email diff --git a/godot/monitor/Rut.gd b/godot/monitor/Rut.gd new file mode 100644 index 0000000..85b66d0 --- /dev/null +++ b/godot/monitor/Rut.gd @@ -0,0 +1,71 @@ +extends LineEdit + + +var previous_text: String = "" + + +func _on_Rut_text_changed(_new_text: String) -> void: + var old_pos = caret_position + if text.length() > 12: + text = previous_text + old_pos = old_pos - 2 + text = pretty_rut(text) + caret_position = old_pos + 1 + previous_text = text + + +func clean_rut(rut: String) -> String: + rut = rut.strip_escapes() + rut = rut.strip_edges(true, true) + rut = rut.to_lower() + rut = rut.replace(".", "") + rut = rut.replace("-", "") + + var rut_temp: String = rut.substr(0, rut.length() - 1) + var verifier: String = rut.substr(rut.length() - 1, 1) + + var regex = RegEx.new() + regex.compile("\\D") + rut_temp = regex.sub(rut_temp, "", true) + + regex.compile("[^kK\\d]") + verifier = regex.sub(verifier, "", true) + + rut = rut_temp + verifier + + return rut + + +func pretty_rut(rut: String) -> String: + rut = clean_rut(rut) + + var rut_temp: String = rut.substr(0, rut.length() - 1) + var verifier: String = rut.substr(rut.length() - 1, 1) + + var regex = RegEx.new() + regex.compile("[^kK\\d]") + verifier = regex.sub(verifier, "", true) + + var byte_array = rut_temp.to_utf8() + byte_array.invert() + + var new_byte_array: PoolByteArray = PoolByteArray() + var i = 1 + for symbol in byte_array: + new_byte_array.append(symbol) + if i == 3: + new_byte_array.append(".".to_utf8()[0]) + i = 0 + i = i + 1 + if new_byte_array.size() > 0 and new_byte_array[new_byte_array.size() - 1] == ".".to_utf8()[0]: + new_byte_array.resize(new_byte_array.size() - 1) + + new_byte_array.invert() + rut_temp = new_byte_array.get_string_from_utf8() + + if rut_temp.length() == 0 and verifier.length() > 0: + rut_temp = verifier + elif rut_temp.length() > 0 and verifier.length() > 0: + rut_temp = rut_temp + "-" + verifier + + return rut_temp diff --git a/godot/monitor/UISounds.gd b/godot/monitor/UISounds.gd new file mode 100644 index 0000000..b0821c6 --- /dev/null +++ b/godot/monitor/UISounds.gd @@ -0,0 +1,9 @@ +extends Node + + +func _play_popup_sound() -> void: + $Popup.play() + + +func _play_ui_select_sound() -> void: + $Menu.play() diff --git a/godot/project.godot b/godot/project.godot index b52d977..b01c12e 100644 --- a/godot/project.godot +++ b/godot/project.godot @@ -19,7 +19,7 @@ config/icon="res://icon.png" window/size/width=512 window/size/height=288 -window/stretch/mode="viewport" +window/stretch/mode="2d" window/stretch/aspect="keep" [editor] @@ -100,6 +100,8 @@ Send={ 2d_physics/layer_1="Player" 2d_physics/layer_2="Tiles" +2d_physics/layer_4="Enemies" +2d_physics/layer_5="Platforms" [physics] diff --git a/godot/shaders/crt/crt.shader b/godot/shaders/crt/crt.shader new file mode 100644 index 0000000..aa146a4 --- /dev/null +++ b/godot/shaders/crt/crt.shader @@ -0,0 +1,73 @@ +shader_type canvas_item; + +const float PI = 3.14159; + +uniform vec2 resolution = vec2(1024.0, 576.0); + +uniform bool show_curve = false; +uniform bool show_vignette = false; +uniform bool show_horizontal_scan_lines = true; +uniform bool show_vertical_scan_lines = false; +uniform bool gray_scale = false; + +uniform float curvature_x_amount : hint_range(3.0, 15.0, 0.01) = 6.0; +uniform float curvature_y_amount : hint_range(3.0, 15.0, 0.01) = 6.0; +uniform vec4 corner_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0); + +uniform float vignette_size : hint_range(1, 300, 0.1) = 4.0; +uniform float vignette_opacity : hint_range(0.0, 1.0, 0.01) = 1.0; + +const float brightness = 3.0; + +vec2 uv_curve(vec2 uv) { + if (show_curve) { + uv = uv * 2.0 - 1.0; + vec2 offset = abs(uv.yx) / vec2(curvature_x_amount, curvature_y_amount); + uv = uv + uv * offset * offset; + uv = uv * 0.5 + 0.5; + } + return uv; +} + +void fragment() { + vec2 screen_uv = uv_curve(SCREEN_UV); + vec3 color = texture(SCREEN_TEXTURE, screen_uv).rgb; + + if (show_horizontal_scan_lines || show_vertical_scan_lines) { + color.r = texture(SCREEN_TEXTURE, uv_curve(SCREEN_UV) + vec2(SCREEN_PIXEL_SIZE.x * 0.0), 0.0).r; + color.g = texture(SCREEN_TEXTURE, uv_curve(SCREEN_UV) + vec2(SCREEN_PIXEL_SIZE.x * 0.0), 0.0).g; + color.b = texture(SCREEN_TEXTURE, uv_curve(SCREEN_UV) + vec2(SCREEN_PIXEL_SIZE.x * 0.0), 0.0).b; + } + + if (show_vignette) { + float vignette = UV.x * UV.y * (1.0 - UV.x) * (1.0 - UV.y); + vignette = clamp(pow((resolution.x / vignette_size) * vignette, vignette_opacity), 0.0, 1.0); + color *= vignette; + } + + if (show_horizontal_scan_lines) { + float s = sin(uv_curve(SCREEN_UV).y * resolution.y / 2.0 * PI); + s = (s * 0.5 + 0.5) * 0.9 + 0.1; + vec4 scan_line = vec4(vec3(pow(s, 0.25)), 1.0); + color *= scan_line.rgb; + } + + if (show_vertical_scan_lines) { + float s = sin(uv_curve(SCREEN_UV).x * resolution.x / 2.0 * PI); + s = (s * 0.5 + 0.5) * 0.9 + 0.1; + vec4 scan_line = vec4(vec3(pow(s, 0.25)), 1.0); + color *= scan_line.rgb; + } + + if (show_curve) { + if (screen_uv.x < 0.0 || screen_uv.x > 1.0 || screen_uv.y < 0.0 || screen_uv.y > 1.0) { + color = corner_color.rgb; + } + } + + if (gray_scale) { + float avg = (color.r + color.g + color.b) / brightness; + color = vec3(avg); + } + COLOR = vec4(color, 1.0); +} \ No newline at end of file diff --git a/godot/shaders/crt/crt.tres b/godot/shaders/crt/crt.tres new file mode 100644 index 0000000..7215bcc --- /dev/null +++ b/godot/shaders/crt/crt.tres @@ -0,0 +1,17 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=2] + +[ext_resource path="res://shaders/crt/crt.shader" type="Shader" id=1] + +[resource] +shader = ExtResource( 1 ) +shader_param/resolution = Vector2( 1280, 720 ) +shader_param/show_curve = false +shader_param/show_vignette = false +shader_param/show_horizontal_scan_lines = true +shader_param/show_vertical_scan_lines = false +shader_param/gray_scale = false +shader_param/curvature_x_amount = 6.0 +shader_param/curvature_y_amount = 6.0 +shader_param/corner_color = Color( 0, 0, 0, 1 ) +shader_param/vignette_size = 4.0 +shader_param/vignette_opacity = 1.0 diff --git a/godot/shaders/crt/crt.tscn b/godot/shaders/crt/crt.tscn new file mode 100644 index 0000000..bfdef34 --- /dev/null +++ b/godot/shaders/crt/crt.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://shaders/crt/crt.tres" type="Material" id=1] + +[node name="CRT" type="CanvasLayer"] + +[node name="ColorRect" type="ColorRect" parent="."] +material = ExtResource( 1 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 diff --git a/src/Main.cpp b/src/Main.cpp index 4f91c0c..6bc13fb 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -9,10 +9,13 @@ void Main::_register_methods() { register_method("_ready", &Main::_ready); register_method("_physics_process", &Main::_physics_process); + register_method("_on_monitor_loaded", &Main::_on_monitor_loaded); + register_property("game_version", &Main::set_game_version, &Main::get_game_version, String(main::game_version.c_str())); register_property>("level", &Main::set_level, &Main::get_level, NULL, GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RESOURCE_TYPE, String("PackedScene")); register_property("full_screen", &Main::set_full_screen, &Main::get_full_screen, main::full_screen); register_property("window_size", &Main::set_window_size, &Main::get_window_size, main::window_size); register_property("launch_screen", &Main::set_launch_screen, &Main::get_launch_screen, main::launch_screen); + register_signal
("monitor_loaded"); } Main::Main() @@ -27,7 +30,10 @@ void Main::_init() { _os = OS::get_singleton(); _input = Input::get_singleton(); + _project_settings = ProjectSettings::get_singleton(); + _resource_loader = ResourceLoader::get_singleton(); + game_version = String(main::game_version.c_str()); full_screen = main::full_screen; window_size = main::window_size; launch_screen = main::launch_screen; @@ -35,6 +41,24 @@ void Main::_init() void Main::_ready() { + auto success = _project_settings->load_resource_pack("monitor.pck"); + if (success) + { + // Load monitor from pck + Godot::print("Monitor pck found, loading..."); + load_monitor(); + } + else if (_resource_loader->exists("res://monitor/Monitor.tscn")) + { + // Load monitor from alai's pck + load_monitor(); + } + else + { + // There is no monitor included + _on_monitor_loaded(); + } + if (get_full_screen()) { _os->set_window_fullscreen(true); @@ -47,10 +71,52 @@ void Main::_ready() ); } - if (level != NULL) + success = _project_settings->load_resource_pack("crt.pck"); + if (success) { - add_child(level->instance()); + // Load crt from pck + Godot::print("CRT pck found, loading..."); + Ref crt_scene = _resource_loader->load("res://shaders/crt/crt.tscn"); + add_child(crt_scene->instance()); } + else if (_resource_loader->exists("res://shaders/crt/crt.tscn")) + { + // Load crt from alai's pck + Ref crt_scene = _resource_loader->load("res://shaders/crt/crt.tscn"); + add_child(crt_scene->instance()); + } +} + +void 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"); + } +} + +void Main::load_monitor() +{ + 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); +} + +Node *Main::load_level() +{ + if (level != nullptr) + { + auto path = level->get_path(); + auto loaded_level = level->instance(); + auto level_node = get_node("Level"); + level_node->add_child(loaded_level); + return level_node; + } + return nullptr; } void Main::_physics_process(float delta) @@ -71,6 +137,16 @@ Ref Main::get_level() return this->level; } +void Main::set_game_version(String game_version) +{ + this->game_version = game_version; +} + +String Main::get_game_version() +{ + return this->game_version; +} + void Main::set_full_screen(bool full_screen) { this->full_screen = full_screen; diff --git a/src/Main.h b/src/Main.h index d89c5c9..4c04cc9 100644 --- a/src/Main.h +++ b/src/Main.h @@ -1,12 +1,15 @@ #ifndef ALAI_MAIN_H #define ALAI_MAIN_H +#include #include #include #include #include #include #include +#include +#include /** * @brief This is the godot namespace for all the code included in the library. @@ -21,6 +24,11 @@ namespace godot */ namespace main { + /** + * @brief The default value for the game version. + * + */ + const std::string game_version = "0.1.0"; /** * @brief The default value for if the game should start in full screen. * @@ -58,12 +66,27 @@ namespace godot * */ Input *_input; + /** + * @brief ProjectSettings singleton. + * + */ + ProjectSettings *_project_settings; + /** + * @brief ResourceLoader singleton. + * + */ + ResourceLoader *_resource_loader; /** * @brief The first level to load * */ Ref level; + /** + * @brief The current version of the game. + * + */ + String game_version; /** * @brief If the window is full screen or not. * @@ -137,6 +160,20 @@ namespace godot */ Ref get_level(); + /** + * @brief Set the game version object. + * + * @param[in] game_version The new version fo the game. + */ + void set_game_version(String game_version); + + /** + * @brief Get the game version object. + * + * @return String The current version of the game. + */ + String get_game_version(); + /** * @brief Set the full screen object. * @@ -179,6 +216,11 @@ namespace godot * @return int8_t The launch screen. */ int8_t get_launch_screen(); + + void _on_monitor_loaded(); + + void load_monitor(); + Node *load_level(); }; } } diff --git a/src/player/Player.cpp b/src/player/Player.cpp index 843043b..868156b 100644 --- a/src/player/Player.cpp +++ b/src/player/Player.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include using namespace godot; using namespace player; @@ -15,12 +18,18 @@ void Player::_register_methods() register_method("_physics_process", &Player::_physics_process); register_method("set_velocity", &Player::set_velocity); register_method("get_velocity", &Player::get_velocity); + register_method("_on_player_touched", &Player::_on_player_touched); + register_method("_on_monitor_loaded", &Player::_on_monitor_loaded); //register_property>("sprite_frames", &Player::set_sprite_frames, &Player::get_sprite_frames, Ref(), GODOT_METHOD_RPC_MODE_DISABLED, GODOT_PROPERTY_USAGE_DEFAULT, GODOT_PROPERTY_HINT_RESOURCE_TYPE, String("SpriteFrames")); register_property("speed", &Player::set_speed, &Player::get_speed, player::speed); register_property("jump_force", &Player::set_jump_force, &Player::get_jump_force, player::jump_force); + register_property("bounce_force", &Player::set_bounce_force, &Player::get_bounce_force, player::bounce_force); register_property("gravity", &Player::set_gravity, &Player::get_gravity, player::gravity); register_property("run_speed", &Player::set_run_speed, &Player::get_run_speed, player::run_speed); register_property("double_jump", &Player::set_double_jump, &Player::get_double_jump, player::double_jump); + register_signal("object_created", "name", GODOT_VARIANT_TYPE_STRING, "state", GODOT_VARIANT_TYPE_STRING, "position", GODOT_VARIANT_TYPE_VECTOR2, "velocity", GODOT_VARIANT_TYPE_VECTOR2); + register_signal("object_updated", "name", GODOT_VARIANT_TYPE_STRING, "state", GODOT_VARIANT_TYPE_STRING, "position", GODOT_VARIANT_TYPE_VECTOR2, "velocity", GODOT_VARIANT_TYPE_VECTOR2); + register_signal("object_removed", "name", GODOT_VARIANT_TYPE_STRING); } Player::Player() @@ -38,6 +47,7 @@ void Player::_init() //sprite_frames = _resource_loader->load(player::sprite_frames); set_speed(player::speed); set_jump_force(player::jump_force); + set_bounce_force(player::bounce_force); set_gravity(player::gravity); set_run_speed(player::run_speed); set_double_jump(player::double_jump); @@ -58,7 +68,6 @@ void Player::_ready() //animated_sprite->set_sprite_frames(sprite_frames); auto node = get_parent()->find_node("Middleground"); - if (node != nullptr) { auto tile_map = Object::cast_to(node); @@ -71,13 +80,83 @@ void Player::_ready() } } +void Player::_on_monitor_loaded() { + auto object_node = get_tree()->get_root()->find_node("Monitor", true, false); + if (object_node != nullptr) + { + auto state = get_node("StateMachine")->get_child(0); + if (state != nullptr) + { + connect("object_created", object_node, "_object_created"); + connect("object_updated", object_node, "_object_updated"); + connect("object_removed", object_node, "_object_removed"); + emit_signal("object_created", this->get_name(), state->get_name(), get_global_position(), velocity); + } + else + { + WARN_PRINT("State not found!"); + } + } +#ifndef NDEBUG + else + { + WARN_PRINT("Monitor not found!"); + } +#endif +} + void Player::_physics_process(float delta) { velocity.y += get_gravity(); - velocity = move_and_slide(velocity, Vector2::UP, true); + auto snap_vector = Vector2::ZERO; + if (!is_on_floor()) + { + snap_vector = Vector2::DOWN * 20.0; + } + + auto platform_detector = get_node("PlatformDetector"); + auto is_on_platform = platform_detector->is_colliding(); + + velocity = move_and_slide_with_snap(velocity, snap_vector, Vector2::UP, !is_on_platform, 4, 0.9, false); + //velocity = move_and_slide(velocity, Vector2::UP, !is_on_platform); velocity.x = Math::lerp((float) velocity.x, (float) 0, (float) 0.2); + auto count = get_slide_count(); + for (int64_t i = 0; i < count; i++) + { + auto collision = get_slide_collision(i); + auto collision_object = collision->get_collider(); + auto collider = Object::cast_to(collision_object); + if (collider->is_in_group("squashable") && Vector2::UP.dot(collision->get_normal()) > 0.1) + { + collider->call_deferred("squash"); + /*auto dup_node = collider->duplicate(); + auto dup = Object::cast_to(dup_node); + auto dup_pos = dup->get_position(); + dup_pos.x += 24; + dup->set_position(dup_pos); + auto enemies = get_tree()->get_root()->get_node("Main")->find_node("Enemies", true, false); + if (enemies != nullptr) { + enemies->add_child(dup); + } + else + { + WARN_PRINT("Enemies not found!"); + dup->queue_free(); + }*/ + velocity.y = -get_bounce_force(); + } + else if (collider->is_in_group("enemy") && (collider->is_in_group("rideable") && Vector2::DOWN.dot(collision->get_normal()) > 0)) + { + _on_player_touched(); + } + else if (collider->is_in_group("enemy") && !collider->is_in_group("rideable")) + { + _on_player_touched(); + } + } + // Clamp the player's position inside the camera's limits auto camera = get_node("Camera2D"); auto position = get_global_position(); @@ -110,6 +189,16 @@ void Player::_physics_process(float delta) } } } + + auto state = get_node("StateMachine")->get_child(0); + if (state != nullptr) + { + emit_signal("object_updated", this->get_name(), state->get_name(), get_global_position(), velocity); + } + else + { + WARN_PRINT("State not found!"); + } } void Player::set_sprite_frames(Ref sprite_frames) @@ -142,6 +231,16 @@ float Player::get_jump_force() return this->jump_force; } +void Player::set_bounce_force(float bounce_force) +{ + this->bounce_force = bounce_force; +} + +float Player::get_bounce_force() +{ + return this->bounce_force; +} + void Player::set_gravity(float gravity) { this->gravity = gravity; @@ -181,3 +280,12 @@ Vector2 Player::get_velocity() { return this->velocity; } + +void Player::_on_player_touched() +{ + auto error = get_tree()->change_scene("res://Main.tscn"); + if (error != Error::OK) + { + ERR_PRINT(String().num((int) error) + " Could not load scene!"); + } +} diff --git a/src/player/Player.h b/src/player/Player.h index ee710ae..ee505a0 100644 --- a/src/player/Player.h +++ b/src/player/Player.h @@ -31,6 +31,11 @@ namespace godot * */ const float jump_force = 300.0; + /** + * @brief The default bounce force applied when bouncing on something. + * + */ + const float bounce_force = 200.0; /** * @brief The default gravity applied to the player. * @@ -93,6 +98,11 @@ namespace godot * */ float jump_force; + /** + * @brief The force applied to the player when bouncing off something. + * + */ + float bounce_force; /** * @brief The gravity applied to the player. * @@ -194,6 +204,20 @@ namespace godot */ float get_jump_force(); + /** + * @brief Set the bounce force object. + * + * @param[in] bounce_force The new force applied to the player to make him bounce. + */ + void set_bounce_force(float bounce_force); + + /** + * @brief Get the bounce force object. + * + * @return float The current force being applied to the player. + */ + float get_bounce_force(); + /** * @brief Set the gravity object. * @@ -250,6 +274,14 @@ namespace godot * @return Vector2 Returns the velocity of the player. */ Vector2 get_velocity(); + + /** + * @brief This function is called when an enemy touches the player. + * + */ + void _on_player_touched(); + + void _on_monitor_loaded(); }; } } diff --git a/src/player/states/PlayerJump.cpp b/src/player/states/PlayerJump.cpp index 8255e1b..e9f9082 100644 --- a/src/player/states/PlayerJump.cpp +++ b/src/player/states/PlayerJump.cpp @@ -1,6 +1,8 @@ #include "player/states/PlayerJump.h" #include "player/Player.h" +#include + using namespace godot; using namespace player; @@ -26,6 +28,9 @@ void PlayerJump::_init() void PlayerJump::_state_enter(const String state) { + auto jump_sound = get_parent()->get_node("Sounds/Jump"); + jump_sound->play(); + animated_sprite = get_parent()->get_node("AnimatedSprite"); animated_sprite->stop(); animated_sprite->set_animation("air");