Arrow shooters and better cell to cell movement for players
parent
c8eaba5591
commit
c06e5a6ada
|
@ -2,7 +2,9 @@ class_name Player
|
||||||
extends CharacterBody2D
|
extends CharacterBody2D
|
||||||
|
|
||||||
@onready var raycast: RayCast2D = $RayCast2D
|
@onready var raycast: RayCast2D = $RayCast2D
|
||||||
@onready var tile_map: MainLevel = $"../TileMap"
|
@onready var sprite: Sprite2D = $Sprite2D
|
||||||
|
@onready var map: MainLevel = get_tree().root.get_child(0).get_node("TileMap")
|
||||||
|
@onready var tile_map: TileMapLayer = get_tree().root.get_child(0).get_node("TileMap/TileMapLayer")
|
||||||
|
|
||||||
@export var speed: float = 40
|
@export var speed: float = 40
|
||||||
@export var respawn_point: Marker2D
|
@export var respawn_point: Marker2D
|
||||||
|
@ -11,23 +13,35 @@ const TILE_SIZE = 8
|
||||||
|
|
||||||
var is_moving = false
|
var is_moving = false
|
||||||
var should_move = false
|
var should_move = false
|
||||||
|
var is_dead = false
|
||||||
var input_dir: Vector2
|
var input_dir: Vector2
|
||||||
|
var respawn_time: int = 10
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
_respawn()
|
_respawn()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
_try_interact()
|
if not is_dead:
|
||||||
pass
|
_try_get_input()
|
||||||
|
_try_interact()
|
||||||
|
if is_dead:
|
||||||
|
if respawn_time > 0:
|
||||||
|
respawn_time -= 1
|
||||||
|
elif respawn_time <= 0:
|
||||||
|
_respawn()
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
_try_move()
|
_try_move(delta)
|
||||||
|
|
||||||
func _respawn():
|
func _respawn():
|
||||||
position = respawn_point.position
|
position = respawn_point.position
|
||||||
|
sprite.global_position = position
|
||||||
|
is_dead = false
|
||||||
|
is_moving = false
|
||||||
|
should_move = false
|
||||||
|
|
||||||
func _try_move():
|
func _try_get_input():
|
||||||
should_move = false
|
should_move = false
|
||||||
if Input.is_action_pressed("move_up"):
|
if Input.is_action_pressed("move_up"):
|
||||||
input_dir = Vector2.UP
|
input_dir = Vector2.UP
|
||||||
|
@ -42,28 +56,44 @@ func _try_move():
|
||||||
input_dir = Vector2.LEFT
|
input_dir = Vector2.LEFT
|
||||||
should_move = true
|
should_move = true
|
||||||
|
|
||||||
if should_move and !is_moving:
|
if should_move and not is_moving:
|
||||||
raycast.target_position = input_dir * 8
|
raycast.target_position = input_dir * 8
|
||||||
raycast.force_raycast_update()
|
raycast.force_raycast_update()
|
||||||
|
|
||||||
if raycast.is_colliding():
|
if raycast.is_colliding():
|
||||||
return
|
return
|
||||||
|
|
||||||
is_moving = true
|
var current_tile: Vector2i = tile_map.local_to_map(global_position)
|
||||||
var tween = create_tween()
|
var target_tile: Vector2i = Vector2i(
|
||||||
tween.tween_property(self, "position", position + input_dir * TILE_SIZE, 0.25)
|
current_tile.x + input_dir.x,
|
||||||
tween.tween_callback(func():
|
current_tile.y + input_dir.y
|
||||||
is_moving = false
|
|
||||||
_post_movement_check()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func _post_movement_check():
|
global_position = tile_map.map_to_local(target_tile)
|
||||||
var is_death_tile = tile_map.is_death_tile(global_position)
|
|
||||||
if is_death_tile:
|
var is_death_tile = map.is_death_tile(global_position)
|
||||||
die()
|
if is_death_tile:
|
||||||
|
die()
|
||||||
|
return
|
||||||
|
|
||||||
|
is_moving = true
|
||||||
|
sprite.global_position = tile_map.map_to_local(current_tile)
|
||||||
|
|
||||||
|
|
||||||
|
func _try_move(delta: int):
|
||||||
|
if not is_moving or is_dead:
|
||||||
|
return
|
||||||
|
|
||||||
|
sprite.global_position = sprite.global_position.move_toward(global_position, 0.5)
|
||||||
|
|
||||||
|
if global_position == sprite.global_position:
|
||||||
|
is_moving = false
|
||||||
|
return
|
||||||
|
|
||||||
func die():
|
func die():
|
||||||
_respawn()
|
is_dead = true
|
||||||
|
is_moving = false
|
||||||
|
respawn_time = 10
|
||||||
|
|
||||||
func _try_interact():
|
func _try_interact():
|
||||||
raycast.target_position = input_dir * 8
|
raycast.target_position = input_dir * 8
|
||||||
|
|
|
@ -46,16 +46,16 @@ size = Vector2(8, 8)
|
||||||
|
|
||||||
[node name="Player" type="CharacterBody2D"]
|
[node name="Player" type="CharacterBody2D"]
|
||||||
z_index = 10
|
z_index = 10
|
||||||
collision_mask = 3
|
collision_mask = 15
|
||||||
script = ExtResource("1_jrd75")
|
script = ExtResource("1_jrd75")
|
||||||
|
|
||||||
[node name="Camera2D" type="Camera2D" parent="."]
|
|
||||||
|
|
||||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
texture_filter = 1
|
texture_filter = 1
|
||||||
texture = ExtResource("1_qfnf0")
|
texture = ExtResource("1_qfnf0")
|
||||||
hframes = 2
|
hframes = 2
|
||||||
|
|
||||||
|
[node name="Camera2D" type="Camera2D" parent="Sprite2D"]
|
||||||
|
|
||||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||||
libraries = {
|
libraries = {
|
||||||
"": SubResource("AnimationLibrary_dx4e7")
|
"": SubResource("AnimationLibrary_dx4e7")
|
||||||
|
|
|
@ -53,6 +53,13 @@ jump={
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[layer_names]
|
||||||
|
|
||||||
|
2d_physics/layer_1="Entities"
|
||||||
|
2d_physics/layer_2="Terrain"
|
||||||
|
2d_physics/layer_3="Puzzle"
|
||||||
|
2d_physics/layer_4="Projectiles"
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
textures/canvas_textures/default_texture_filter=0
|
textures/canvas_textures/default_texture_filter=0
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
class_name Arrow
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
@onready var sprite: Sprite2D = $Sprite2D
|
||||||
|
|
||||||
|
var _direction: Vector2i
|
||||||
|
var _speed: int = 50
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
if _direction.x > 0:
|
||||||
|
sprite.flip_h = true
|
||||||
|
|
||||||
|
func shoot(dir: Vector2i, speed: int):
|
||||||
|
_direction = dir
|
||||||
|
_speed = speed
|
||||||
|
|
||||||
|
func _physics_process(delta):
|
||||||
|
var move = _direction * _speed * delta
|
||||||
|
position = position + move
|
||||||
|
|
||||||
|
|
||||||
|
func _on_area_2d_body_entered(body):
|
||||||
|
if body is Player:
|
||||||
|
body.die()
|
||||||
|
queue_free()
|
Binary file not shown.
After Width: | Height: | Size: 117 B |
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://de8lejw21tx6h"
|
||||||
|
path="res://.godot/imported/arrow.png-a9a36bfbd72d1cbac04ba2d3bfba852e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://puzzles/arrow/arrow.png"
|
||||||
|
dest_files=["res://.godot/imported/arrow.png-a9a36bfbd72d1cbac04ba2d3bfba852e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
|
@ -0,0 +1,21 @@
|
||||||
|
[gd_scene load_steps=4 format=3 uid="uid://0p0jl4g1ha4v"]
|
||||||
|
|
||||||
|
[ext_resource type="Texture2D" uid="uid://de8lejw21tx6h" path="res://puzzles/arrow/arrow.png" id="1_nkjxg"]
|
||||||
|
[ext_resource type="Script" path="res://puzzles/arrow/arrow.gd" id="1_v7o4i"]
|
||||||
|
|
||||||
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_2m4dq"]
|
||||||
|
size = Vector2(8, 3)
|
||||||
|
|
||||||
|
[node name="Arrow" type="Node2D"]
|
||||||
|
script = ExtResource("1_v7o4i")
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||||
|
texture = ExtResource("1_nkjxg")
|
||||||
|
|
||||||
|
[node name="Area2D" type="Area2D" parent="."]
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
|
||||||
|
position = Vector2(0, -0.5)
|
||||||
|
shape = SubResource("RectangleShape2D_2m4dq")
|
||||||
|
|
||||||
|
[connection signal="body_entered" from="Area2D" to="." method="_on_area_2d_body_entered"]
|
|
@ -0,0 +1,19 @@
|
||||||
|
extends RayCast2D
|
||||||
|
|
||||||
|
@onready var arrow: PackedScene = preload("res://puzzles/arrow/arrow.tscn")
|
||||||
|
@onready var timer: Timer = $ShootTimer
|
||||||
|
@onready var shoot_dir: Vector2i = self.target_position.normalized()
|
||||||
|
|
||||||
|
@export var arrow_speed: int = 400
|
||||||
|
@export var shoot_timer: float = 3.0
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
timer.start(shoot_timer)
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_shoot_timer_timeout():
|
||||||
|
var inst: Arrow = arrow.instantiate()
|
||||||
|
inst.shoot(shoot_dir, arrow_speed)
|
||||||
|
add_child(inst)
|
|
@ -0,0 +1,11 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://dpkj44krp378g"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://puzzles/arrow/arrow_shooter.gd" id="1_tk6ny"]
|
||||||
|
|
||||||
|
[node name="ArrowShooter" type="RayCast2D"]
|
||||||
|
target_position = Vector2(0, 8)
|
||||||
|
script = ExtResource("1_tk6ny")
|
||||||
|
|
||||||
|
[node name="ShootTimer" type="Timer" parent="."]
|
||||||
|
|
||||||
|
[connection signal="timeout" from="ShootTimer" to="." method="_on_shoot_timer_timeout"]
|
|
@ -4,10 +4,13 @@ extends Area2D
|
||||||
|
|
||||||
@export var nodes: Array[Node2D]
|
@export var nodes: Array[Node2D]
|
||||||
|
|
||||||
|
var state = false
|
||||||
|
|
||||||
func _on_body_entered(body):
|
func _on_body_entered(body):
|
||||||
if body is Player:
|
if body is Player:
|
||||||
|
state = not state
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
if node is TileMapLayer:
|
if node is TileMapLayer:
|
||||||
var layer = node as TileMapLayer
|
var layer = node as TileMapLayer
|
||||||
layer.enabled = !layer.enabled
|
layer.enabled = !layer.enabled
|
||||||
sprite.frame = 1 if not layer.enabled else 0
|
sprite.frame = 1 if state else 0
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
class_name MainLevel
|
class_name MainLevel
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
func _get_tile_data(position: Vector2):
|
func _get_tile_data(position: Vector2) -> Array[TileData]:
|
||||||
var results = []
|
var results: Array[TileData] = []
|
||||||
for layer in self.get_children():
|
for layer in self.get_children():
|
||||||
if not (layer as TileMapLayer).enabled:
|
if not (layer as TileMapLayer).enabled:
|
||||||
continue
|
continue
|
||||||
|
@ -12,14 +12,14 @@ func _get_tile_data(position: Vector2):
|
||||||
results.push_back(tile_data)
|
results.push_back(tile_data)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
func is_walkable_tile(position: Vector2):
|
func is_walkable_tile(position: Vector2) -> bool:
|
||||||
var results = _get_tile_data(position)
|
var results = _get_tile_data(position)
|
||||||
for tile_data in results:
|
for tile_data in results:
|
||||||
if (tile_data as TileData).get_custom_data("walkable"):
|
if (tile_data as TileData).get_custom_data("walkable"):
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|
||||||
func is_death_tile(position: Vector2):
|
func is_death_tile(position: Vector2) -> bool:
|
||||||
var is_death_tile = false
|
var is_death_tile = false
|
||||||
var results = _get_tile_data(position)
|
var results = _get_tile_data(position)
|
||||||
for tile_data in results:
|
for tile_data in results:
|
||||||
|
|
|
@ -9,7 +9,7 @@ signal finish_room
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func is_room_finished():
|
func is_room_finished() -> bool:
|
||||||
for puzzle in mandatory_puzzles:
|
for puzzle in mandatory_puzzles:
|
||||||
if !puzzle.is_complete:
|
if !puzzle.is_complete:
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -41,15 +41,17 @@ texture_region_size = Vector2i(8, 8)
|
||||||
3:0/0 = 0
|
3:0/0 = 0
|
||||||
3:0/0/probability = 0.05
|
3:0/0/probability = 0.05
|
||||||
3:0/0/custom_data_0 = true
|
3:0/0/custom_data_0 = true
|
||||||
0:6/0 = 0
|
6:2/0 = 0
|
||||||
1:6/0 = 0
|
6:2/0/physics_layer_1/polygon_0/points = PackedVector2Array(-4, -4, 4, -4, 4, 4, -4, 4)
|
||||||
2:6/0 = 0
|
7:2/0 = 0
|
||||||
1:7/0 = 0
|
7:2/0/physics_layer_1/polygon_0/points = PackedVector2Array(-4, -4, 4, -4, 4, 4, -4, 4)
|
||||||
0:7/0 = 0
|
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
tile_size = Vector2i(8, 8)
|
tile_size = Vector2i(8, 8)
|
||||||
physics_layer_0/collision_layer = 1
|
physics_layer_0/collision_layer = 1
|
||||||
|
physics_layer_0/collision_mask = 9
|
||||||
|
physics_layer_1/collision_layer = 2
|
||||||
|
physics_layer_1/collision_mask = 3
|
||||||
custom_data_layer_0/name = "walkable"
|
custom_data_layer_0/name = "walkable"
|
||||||
custom_data_layer_0/type = 1
|
custom_data_layer_0/type = 1
|
||||||
custom_data_layer_1/name = "death"
|
custom_data_layer_1/name = "death"
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 645 B |
File diff suppressed because one or more lines are too long
Reference in New Issue