diff --git a/asset/art/little_game/弹珠/弹珠.png b/asset/art/little_game/弹珠/弹珠.png new file mode 100755 index 00000000..2819c386 Binary files /dev/null and b/asset/art/little_game/弹珠/弹珠.png differ diff --git a/asset/art/little_game/弹珠/弹珠.png.import b/asset/art/little_game/弹珠/弹珠.png.import new file mode 100644 index 00000000..cd2e09f7 --- /dev/null +++ b/asset/art/little_game/弹珠/弹珠.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b4enynkq50qys" +path="res://.godot/imported/弹珠.png-e10caf11116f1e26bd6fea05ca02ca42.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://asset/art/little_game/弹珠/弹珠.png" +dest_files=["res://.godot/imported/弹珠.png-e10caf11116f1e26bd6fea05ca02ca42.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 diff --git a/asset/art/little_game/弹珠/手.png b/asset/art/little_game/弹珠/手.png new file mode 100755 index 00000000..c4c6ff94 Binary files /dev/null and b/asset/art/little_game/弹珠/手.png differ diff --git a/asset/art/little_game/弹珠/手.png.import b/asset/art/little_game/弹珠/手.png.import new file mode 100644 index 00000000..5e3489fa --- /dev/null +++ b/asset/art/little_game/弹珠/手.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmtuhpsvejcwg" +path="res://.godot/imported/手.png-75b93104170675910e60d236d6b2e6e4.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://asset/art/little_game/弹珠/手.png" +dest_files=["res://.godot/imported/手.png-75b93104170675910e60d236d6b2e6e4.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 diff --git a/asset/art/little_game/弹珠/桌面.png b/asset/art/little_game/弹珠/桌面.png new file mode 100755 index 00000000..775f8c21 Binary files /dev/null and b/asset/art/little_game/弹珠/桌面.png differ diff --git a/asset/art/little_game/弹珠/桌面.png.import b/asset/art/little_game/弹珠/桌面.png.import new file mode 100644 index 00000000..62948b53 --- /dev/null +++ b/asset/art/little_game/弹珠/桌面.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://djvd0ud50p75h" +path="res://.godot/imported/桌面.png-b9bcb7853ff976d0fd317fd381f1a3cc.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://asset/art/little_game/弹珠/桌面.png" +dest_files=["res://.godot/imported/桌面.png-b9bcb7853ff976d0fd317fd381f1a3cc.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 diff --git a/project.godot b/project.godot index 65c7c26d..a707adbd 100644 --- a/project.godot +++ b/project.godot @@ -197,6 +197,7 @@ locale/fallback="zh" 2d_physics/layer_5="journal" 2d_physics/layer_6="journal_wall" 2d_physics/layer_7="npc" +2d_physics/layer_8="little_game" [rendering] diff --git a/scene/ground/scene/c02/s01_街道.tscn b/scene/ground/scene/c02/s01_街道.tscn index 1265f52d..6bd47700 100644 --- a/scene/ground/scene/c02/s01_街道.tscn +++ b/scene/ground/scene/c02/s01_街道.tscn @@ -29,6 +29,7 @@ immediately = true [node name="portal_right" parent="Ground/DeployLayer" index="1"] position = Vector2(392, 2) target_scene = "c02_s02" +target_portal = "left" [node name="Note寻人启事" parent="Ground/DeployLayer" index="2" instance=ExtResource("3_6lnxd")] position = Vector2(250, -22) diff --git a/scene/little_game/弹珠游戏/ball.gd b/scene/little_game/弹珠游戏/ball.gd new file mode 100644 index 00000000..37316102 --- /dev/null +++ b/scene/little_game/弹珠游戏/ball.gd @@ -0,0 +1,69 @@ +@tool + +extends RigidBody2D + +signal hit_ball +signal hit_boundary + +@export_enum("1", "2", "3") var id := "1": + set(value): + id = value + if Engine.is_editor_hint() and is_node_ready(): + _set_up_texture() +@export var is_shooter := false: + set(value): + is_shooter = value +@export var enable := true: + set(value): + enable = value + if is_node_ready(): + $CollisionShape2D.set_deferred("disabled", !value) + +@onready var sprite2d = $Sprite2D as Sprite2D + +const texture_dict = { + "1": preload("res://scene/little_game/弹珠游戏/ball_texture1.tres"), + "2": preload("res://scene/little_game/弹珠游戏/ball_texture2.tres"), + "3": preload("res://scene/little_game/弹珠游戏/ball_texture3.tres"), +} + + +func _ready() -> void: + contact_monitor = true + max_contacts_reported = 1 + _set_up_texture() + body_entered.connect(_on_body_entered) + +func rand_id(): + # 随机 id + var rand = randi() % 3 + 1 + id = str(rand) + _set_up_texture() + +func _set_up_texture(): + sprite2d.texture = texture_dict[id] + + +var recycling = false + +func _on_body_entered(node: Node): + print("hit node", node.get_path()) + if recycling or not is_shooter: + return + recycling = true + var tween = create_tween() + if node is StaticBody2D: + tween.tween_property(sprite2d, "modulate:a", 0.0, 1.0) + tween.tween_callback(hit_boundary.emit) + tween.tween_callback(queue_free) + return + tween.tween_property(sprite2d, "modulate:a", 0.0, 1.0) + tween.tween_property(node.sprite2d, "modulate:a", 0.0, 1.0) + tween.tween_callback(hit_ball.emit) + tween.tween_callback(node.queue_free) + tween.tween_callback(queue_free) + +func _process(_delta: float) -> void: + # 根据 y 坐标缩放 + var ball_scale = 0.6 + (global_position.y / 600.0) + sprite2d.scale = Vector2(ball_scale, ball_scale) \ No newline at end of file diff --git a/scene/little_game/弹珠游戏/ball.gd.uid b/scene/little_game/弹珠游戏/ball.gd.uid new file mode 100644 index 00000000..783440e1 --- /dev/null +++ b/scene/little_game/弹珠游戏/ball.gd.uid @@ -0,0 +1 @@ +uid://by5avn2jd7vd1 diff --git a/scene/little_game/弹珠游戏/ball.tscn b/scene/little_game/弹珠游戏/ball.tscn new file mode 100644 index 00000000..2474afc9 --- /dev/null +++ b/scene/little_game/弹珠游戏/ball.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=3 uid="uid://bbcfjksjlyfx5"] + +[ext_resource type="Texture2D" uid="uid://nkv0bwow4yy3" path="res://scene/little_game/弹珠游戏/ball_texture1.tres" id="1_fx3cc"] +[ext_resource type="Script" uid="uid://by5avn2jd7vd1" path="res://scene/little_game/弹珠游戏/ball.gd" id="2_ni48t"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_ni48t"] +radius = 7.0 + +[node name="Ball" type="RigidBody2D"] +collision_layer = 128 +collision_mask = 128 +gravity_scale = 0.0 +script = ExtResource("2_ni48t") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +shape = SubResource("CircleShape2D_ni48t") + +[node name="Sprite2D" type="Sprite2D" parent="."] +texture = ExtResource("1_fx3cc") diff --git a/scene/little_game/弹珠游戏/ball_texture1.tres b/scene/little_game/弹珠游戏/ball_texture1.tres new file mode 100644 index 00000000..5ee14bd3 --- /dev/null +++ b/scene/little_game/弹珠游戏/ball_texture1.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://nkv0bwow4yy3"] + +[ext_resource type="Texture2D" uid="uid://b4enynkq50qys" path="res://asset/art/little_game/弹珠/弹珠.png" id="1_55t1p"] + +[resource] +atlas = ExtResource("1_55t1p") +region = Rect2(1, 1, 14, 14) diff --git a/scene/little_game/弹珠游戏/ball_texture2.tres b/scene/little_game/弹珠游戏/ball_texture2.tres new file mode 100644 index 00000000..55f9b89c --- /dev/null +++ b/scene/little_game/弹珠游戏/ball_texture2.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://0vonig4c0phu"] + +[ext_resource type="Texture2D" uid="uid://b4enynkq50qys" path="res://asset/art/little_game/弹珠/弹珠.png" id="1_7d3fr"] + +[resource] +atlas = ExtResource("1_7d3fr") +region = Rect2(17, 1, 14, 14) diff --git a/scene/little_game/弹珠游戏/ball_texture3.tres b/scene/little_game/弹珠游戏/ball_texture3.tres new file mode 100644 index 00000000..0416d00a --- /dev/null +++ b/scene/little_game/弹珠游戏/ball_texture3.tres @@ -0,0 +1,7 @@ +[gd_resource type="AtlasTexture" load_steps=2 format=3 uid="uid://nha2mm5cbp73"] + +[ext_resource type="Texture2D" uid="uid://b4enynkq50qys" path="res://asset/art/little_game/弹珠/弹珠.png" id="1_cwpkm"] + +[resource] +atlas = ExtResource("1_cwpkm") +region = Rect2(1, 17, 14, 14) diff --git a/scene/little_game/弹珠游戏/弹珠游戏.gd b/scene/little_game/弹珠游戏/弹珠游戏.gd new file mode 100644 index 00000000..3af74284 --- /dev/null +++ b/scene/little_game/弹珠游戏/弹珠游戏.gd @@ -0,0 +1,64 @@ +extends CanvasLayer + +@onready var pivot = $Pivot as Node2D + + +func _ready() -> void: + layer = GlobalConfig.CANVAS_LAYER_LITTLE_GAME + wave_hand() + + +func reload() -> void: + # 重新加载 + var ball_scene = preload("res://scene/little_game/弹珠游戏/ball.tscn") + var ball = ball_scene.instantiate() + ball.is_shooter = true + pivot.add_child(ball) + pivot.move_child(ball, 0) + ball.rand_id() + + +var wave_tween: Tween +var shooting = false + +func wave_hand() -> void: + # 转动 pivot + if wave_tween and wave_tween.is_running(): + return + wave_tween = create_tween() + wave_tween.tween_property(pivot, "rotation", 0.5, 2.0).set_ease(Tween.EASE_IN_OUT) + wave_tween.tween_property(pivot, "rotation", -0.5, 2.0).set_ease(Tween.EASE_IN_OUT) + wave_tween.set_loops(9999999) + + +func shoot() -> void: + if shooting: + return + shooting = true + # 触发射击事件 + if wave_tween and wave_tween.is_running(): + wave_tween.kill() + var ball = pivot.get_child(0) as RigidBody2D + var direction = Vector2(0, -1).rotated(pivot.rotation) + ball.linear_velocity = direction * 200 + ball.angular_velocity = 10.0 + ball.hit_ball.connect(_on_hit_ball) + ball.hit_boundary.connect(_on_hit_boundary) + +func _on_hit_ball(): + print("_on_hit_ball") + reload() + wave_hand() + shooting = false + +func _on_hit_boundary(): + # 重开游戏 + print("hit boundary, restart") + reload() + wave_hand() + shooting = false + + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("interact"): + shoot() diff --git a/scene/little_game/弹珠游戏/弹珠游戏.gd.uid b/scene/little_game/弹珠游戏/弹珠游戏.gd.uid new file mode 100644 index 00000000..aab6e60b --- /dev/null +++ b/scene/little_game/弹珠游戏/弹珠游戏.gd.uid @@ -0,0 +1 @@ +uid://c5s4giu182isu diff --git a/scene/little_game/弹珠游戏/弹珠游戏.tscn b/scene/little_game/弹珠游戏/弹珠游戏.tscn new file mode 100644 index 00000000..488f25e7 --- /dev/null +++ b/scene/little_game/弹珠游戏/弹珠游戏.tscn @@ -0,0 +1,77 @@ +[gd_scene load_steps=6 format=3 uid="uid://cjx7o685ox8c1"] + +[ext_resource type="Script" uid="uid://c5s4giu182isu" path="res://scene/little_game/弹珠游戏/弹珠游戏.gd" id="1_p2trd"] +[ext_resource type="Texture2D" uid="uid://djvd0ud50p75h" path="res://asset/art/little_game/弹珠/桌面.png" id="2_kl3gx"] +[ext_resource type="Texture2D" uid="uid://bmtuhpsvejcwg" path="res://asset/art/little_game/弹珠/手.png" id="3_kl3gx"] +[ext_resource type="PackedScene" uid="uid://bbcfjksjlyfx5" path="res://scene/little_game/弹珠游戏/ball.tscn" id="4_bm1k0"] + +[sub_resource type="CircleShape2D" id="CircleShape2D_bm1k0"] +radius = 300.0 + +[node name="弹珠游戏" type="CanvasLayer"] +script = ExtResource("1_p2trd") + +[node name="TextureRect" type="TextureRect" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -1.0 +offset_top = 4.0 +offset_right = 11.0 +offset_bottom = 5.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("2_kl3gx") + +[node name="Area2D" type="Area2D" parent="."] +position = Vector2(274, 158) +collision_layer = 128 +collision_mask = 128 +monitorable = false +linear_damp_space_override = 3 +angular_damp_space_override = 3 + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] +shape = SubResource("CircleShape2D_bm1k0") + +[node name="StaticBody2D" type="StaticBody2D" parent="."] +collision_layer = 128 +collision_mask = 128 + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="StaticBody2D"] +build_mode = 1 +polygon = PackedVector2Array(125, 56, 171, 36, 219, 29, 318, 27, 405, 45, 459, 76, 510, 136, 507, 197, 465, 250, 366, 283, 305, 289, 244, 289, 150, 268, 72, 225, 48, 178, 66, 103) + +[node name="Pivot" type="Marker2D" parent="."] +position = Vector2(276, 263) + +[node name="Ball" parent="Pivot" instance=ExtResource("4_bm1k0")] +contact_monitor = true +max_contacts_reported = 1 +is_shooter = true + +[node name="Hand" type="Sprite2D" parent="Pivot"] +position = Vector2(3, -17) +texture = ExtResource("3_kl3gx") + +[node name="Balls" type="Node2D" parent="."] + +[node name="Ball" parent="Balls" instance=ExtResource("4_bm1k0")] +position = Vector2(257, 74) +collision_layer = 132 +contact_monitor = true +max_contacts_reported = 1 +id = "2" + +[node name="Ball2" parent="Balls" instance=ExtResource("4_bm1k0")] +position = Vector2(333, 87) +collision_layer = 132 +contact_monitor = true +max_contacts_reported = 1 +id = "3" + +[node name="Ball3" parent="Balls" instance=ExtResource("4_bm1k0")] +position = Vector2(182, 91) +collision_layer = 132 +contact_monitor = true +max_contacts_reported = 1