Compare commits

...

2 Commits

23 changed files with 384 additions and 7 deletions

View File

@ -126,3 +126,11 @@ Asset credits
*** Author: soneproject
*** License: CC BY 3.0
** heal.wav
*** Retrieved from https://freesound.org/people/lulyc/sounds/346116/
*** Author: lulyc
*** License CC0

Binary file not shown.

BIN
asset_dev/soda/Soda.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
asset_dev/soda/Soda.xcf Normal file

Binary file not shown.

BIN
asset_dev/soda/soda.blend (Stored with Git LFS) Normal file

Binary file not shown.

BIN
asset_dev/soda/soda.blend1 Normal file

Binary file not shown.

BIN
assets/models/items/soda/Soda.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dboi03l4xicib"
path="res://.godot/imported/Soda.png-de28f19d7b13e19defdbdcc490a1e11e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/models/items/soda/Soda.png"
dest_files=["res://.godot/imported/Soda.png-de28f19d7b13e19defdbdcc490a1e11e.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=true
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=0

Binary file not shown.

View File

@ -0,0 +1,138 @@
{
"asset":{
"generator":"Khronos glTF Blender I/O v4.2.60",
"version":"2.0"
},
"scene":0,
"scenes":[
{
"name":"Scene",
"nodes":[
0
]
}
],
"nodes":[
{
"mesh":0,
"name":"Soda"
}
],
"materials":[
{
"alphaMode":"BLEND",
"doubleSided":true,
"name":"Soda",
"pbrMetallicRoughness":{
"baseColorTexture":{
"index":0
},
"metallicFactor":0,
"roughnessFactor":0.5
}
}
],
"meshes":[
{
"name":"Cylinder",
"primitives":[
{
"attributes":{
"POSITION":0,
"NORMAL":1,
"TEXCOORD_0":2
},
"indices":3,
"material":0
}
]
}
],
"textures":[
{
"sampler":0,
"source":0
}
],
"images":[
{
"mimeType":"image/png",
"name":"Soda",
"uri":"Soda.png"
}
],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":42,
"max":[
0.19498558342456818,
0.25,
0.18019376695156097
],
"min":[
-0.19498558342456818,
-0.25,
-0.20000000298023224
],
"type":"VEC3"
},
{
"bufferView":1,
"componentType":5126,
"count":42,
"type":"VEC3"
},
{
"bufferView":2,
"componentType":5126,
"count":42,
"type":"VEC2"
},
{
"bufferView":3,
"componentType":5123,
"count":72,
"type":"SCALAR"
}
],
"bufferViews":[
{
"buffer":0,
"byteLength":504,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":504,
"byteOffset":504,
"target":34962
},
{
"buffer":0,
"byteLength":336,
"byteOffset":1008,
"target":34962
},
{
"buffer":0,
"byteLength":144,
"byteOffset":1344,
"target":34963
}
],
"samplers":[
{
"magFilter":9728,
"minFilter":9984
}
],
"buffers":[
{
"byteLength":1488,
"uri":"soda.bin"
}
]
}

View File

@ -0,0 +1,36 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://sr234l6v26ta"
path="res://.godot/imported/soda.gltf-2170d63a99b0c523c4e3c0057027d256.scn"
[deps]
source_file="res://assets/models/items/soda/soda.gltf"
dest_files=["res://.godot/imported/soda.gltf-2170d63a99b0c523c4e3c0057027d256.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
assets/sound/sfx/player/heal.wav (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://csbrinugqepk3"
path="res://.godot/imported/heal.wav-f1b0fa8bf42c414c0e735c123bc00fea.sample"
[deps]
source_file="res://assets/sound/sfx/player/heal.wav"
dest_files=["res://.godot/imported/heal.wav-f1b0fa8bf42c414c0e735c123bc00fea.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

BIN
assets/sprites/particles/health.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://y07v10c8r1s6"
path="res://.godot/imported/health.png-c53c1eca35551099e5d2579b37f41427.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/sprites/particles/health.png"
dest_files=["res://.godot/imported/health.png-c53c1eca35551099e5d2579b37f41427.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

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=65 format=3 uid="uid://bm2o3mex10v11"]
[gd_scene load_steps=66 format=3 uid="uid://bm2o3mex10v11"]
[ext_resource type="Terrain3DAssets" uid="uid://cwl34gstabgrx" path="res://levels/debug_level/terrain_assets.res" id="1_5smdk"]
[ext_resource type="Shader" path="res://src/shaders/psx_water.gdshader" id="6_0efu4"]
@ -8,6 +8,7 @@
[ext_resource type="Script" path="res://src/world/ball_zone/ball_zone.gd" id="9_jwlau"]
[ext_resource type="PackedScene" uid="uid://dagh38vap4t1d" path="res://src/props/scenery/city/concrete_building_1.tscn" id="10_lf15j"]
[ext_resource type="PackedScene" uid="uid://cjubxs7peir5k" path="res://src/props/scenery/city/kana_signboard.tscn" id="11_evxup"]
[ext_resource type="PackedScene" uid="uid://1ud01tasevho" path="res://src/items/health/health_item.tscn" id="12_jiuxh"]
[ext_resource type="PackedScene" uid="uid://di7aql54lksn7" path="res://src/props/scenery/trees/palm_tree/palm_tree.tscn" id="12_sswxf"]
[ext_resource type="PackedScene" uid="uid://cjne55s85x7jy" path="res://src/items/extra_ball/brick_item.tscn" id="12_tj0lh"]
[ext_resource type="PackedScene" uid="uid://c7l58wuuahn7w" path="res://src/props/flag/flag.tscn" id="13_6jtao"]
@ -395,6 +396,14 @@ amount = 5
spawn_on_ready = true
spawn_turns = 1
[node name="HealthSpawner" type="Marker3D" parent="Course/TestSpawners"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 13.651, 1, 7.92)
script = ExtResource("8_5kaye")
item = ExtResource("12_jiuxh")
amount = 25
spawn_on_ready = true
spawn_turns = 1
[node name="PlayerSpawn1" type="Marker3D" parent="Course" groups=["PlayerSpawn"]]
transform = Transform3D(-0.842697, 0, -0.538388, 0, 1, 0, 0.538388, 0, -0.842697, 212.717, 4, 294.073)

View File

@ -0,0 +1,9 @@
extends Item
## Item which restores life when picked up.
func _collect(player: WorldPlayer) -> void:
player.heal(amount)
player.shot_setup.hud.peek_life_bar()
player.shot_setup.hud.life_particles.emit_spatial(amount, global_position)

View File

@ -0,0 +1,25 @@
[gd_scene load_steps=6 format=3 uid="uid://1ud01tasevho"]
[ext_resource type="PackedScene" uid="uid://comd88yp45mnb" path="res://src/items/item/item.tscn" id="1_bb232"]
[ext_resource type="PackedScene" uid="uid://sr234l6v26ta" path="res://assets/models/items/soda/soda.gltf" id="2_bsxys"]
[ext_resource type="Script" path="res://src/items/health/health_item.gd" id="2_rwv0k"]
[ext_resource type="Texture2D" uid="uid://dboi03l4xicib" path="res://assets/models/items/soda/Soda.png" id="3_7jrce"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_6ujhj"]
albedo_texture = ExtResource("3_7jrce")
texture_filter = 2
[node name="HealthItem" instance=ExtResource("1_bb232")]
script = ExtResource("2_rwv0k")
[node name="Pivot" parent="Pivot/Octahedron/ItemMeshContainer" index="0"]
transform = Transform3D(0.99863, 0.052336, 0, -0.052336, 0.99863, 0, 0, 0, 1, 0, 0, 0)
[node name="soda" parent="Pivot/Octahedron/ItemMeshContainer/Pivot" index="1" instance=ExtResource("2_bsxys")]
transform = Transform3D(1.15911, -0.310583, 0, 0.3, 1.11962, 0.310583, -0.0803848, -0.3, 1.15911, 0, 0, 0)
[node name="Soda" parent="Pivot/Octahedron/ItemMeshContainer/Pivot/soda" index="0"]
surface_material_override/0 = SubResource("StandardMaterial3D_6ujhj")
[editable path="Pivot/Octahedron"]
[editable path="Pivot/Octahedron/ItemMeshContainer/Pivot/soda"]

View File

@ -5,7 +5,9 @@ signal on_life_changed(new_value: float)
signal on_balls_changed(type: GameBall.Type, new_value: int)
signal on_death(player: WorldPlayer)
@export_range(0, 100) var life: float = 100.0:
const MAX_LIFE := 100.0
@export_range(0, MAX_LIFE) var life: float = MAX_LIFE:
set(value):
if value != life:
life = value
@ -89,6 +91,12 @@ func prev_ball(type: GameBall.Type) -> GameBall.Type:
return keys[j]
## Restore life up to the MAX_LIFE cap.
## If the player's life is greater than or equal to MAX_LIFE, they will not be healed.
func heal(amount: float) -> void:
life += minf(amount, maxf(MAX_LIFE - life, 0))
func die() -> void:
on_death.emit(self)

View File

@ -17,6 +17,8 @@ func emit_at_location(_amount: int, source_location: Vector2) -> void:
## Emit the given number of particles from the screen location of the given point in 3D space.
func emit_spatial(_amount: int, source_location: Vector3) -> void:
var screen_location := get_viewport().get_camera_3d().unproject_position(source_location)
var screen_location := (
get_viewport().get_camera_3d().unproject_position(source_location) - global_position
)
# TODO: what to do if this is outside the viewport?
emit_at_location(_amount, screen_location)

View File

@ -7,12 +7,18 @@ const NICE_ALERT_SCENE := preload("res://src/ui/shot_hud/nice_alert.tscn")
const LIFE_BAR_DAMAGE_RUMBLE_SCALE := 0.2
## Time it takes to dampen the life bar rumble on taking damage, in seconds
const LIFE_BAR_DAMAGE_RUMBLE_TIME := 0.2
## Time from restoring health to starting to fill the life bar, in seconds
const LIFE_BAR_HEAL_DELAY := 0.8
## Time it takes the life bar to fill when restoring life, in seconds
const LIFE_BAR_HEAL_TIME := 1.0
var player: WorldPlayer
@onready var power_bar: TextureProgressBar = %PowerBar
@onready var curve_bar: CurveBar = %CurveBar
@onready var life_bar: TextureProgressBar = %LifeBar
@onready var life_particles: HUDParticles = %LifeParticles
@onready var club_selector: ClubSelector = %ClubSelector
@onready var ball_selector: BallSelector = %BallSelector
@ -33,6 +39,8 @@ var player: WorldPlayer
@onready var _life_bar_rumbler: Rumbler = %LifeBarRumbler
@onready var _heal_sfx: AudioStreamPlayer = %HealSFX
static var scene: PackedScene = preload("res://src/ui/shot_hud/shot_hud.tscn")
@ -125,11 +133,15 @@ func set_life_value(new_value: float) -> void:
. tween_property(_life_bar_rumbler, "intensity", 0, LIFE_BAR_DAMAGE_RUMBLE_TIME)
. set_trans(Tween.TRANS_CUBIC)
)
life_bar.value = new_value
elif difference > 0:
# Restoring health
# TODO: something for this?
pass
life_bar.value = new_value
var tween := get_tree().create_tween()
tween.tween_interval(LIFE_BAR_HEAL_DELAY)
tween.tween_callback(_heal_sfx.play)
tween.tween_property(life_bar, "value", new_value, LIFE_BAR_HEAL_TIME).set_trans(
Tween.TRANS_CUBIC
)
static func create(_player: WorldPlayer) -> ShotHUD:

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=44 format=3 uid="uid://c4ifdiohng830"]
[gd_scene load_steps=46 format=3 uid="uid://c4ifdiohng830"]
[ext_resource type="Script" path="res://src/ui/shot_hud/shot_hud.gd" id="1_x5b4c"]
[ext_resource type="Shader" path="res://src/shaders/canvas_retro.gdshader" id="1_ybxxp"]
@ -15,6 +15,8 @@
[ext_resource type="PackedScene" uid="uid://dfh0bv7lwewj5" path="res://src/ui/decorations/hud_particles/hud_particles.tscn" id="11_ie5ih"]
[ext_resource type="Texture2D" uid="uid://dtsdecae83ah3" path="res://assets/sprites/particles/ball.png" id="12_fdbqt"]
[ext_resource type="PackedScene" uid="uid://b47goj32i6sdh" path="res://src/ui/elements/input_prompt/input_prompt.tscn" id="14_ik4gg"]
[ext_resource type="Texture2D" uid="uid://y07v10c8r1s6" path="res://assets/sprites/particles/health.png" id="15_eyqdi"]
[ext_resource type="AudioStream" uid="uid://csbrinugqepk3" path="res://assets/sound/sfx/player/heal.wav" id="16_pub5c"]
[sub_resource type="Animation" id="Animation_2gt87"]
resource_name = "RESET"
@ -798,6 +800,26 @@ script = ExtResource("3_6groq")
unique_name_in_owner = true
layout_mode = 1
[node name="ParticleContainer" type="Control" parent="SouthWest/VBoxContainer/MarginContainer/LifeBarRumbler/LifeBar"]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
grow_horizontal = 2
grow_vertical = 2
[node name="LifeParticles" parent="SouthWest/VBoxContainer/MarginContainer/LifeBarRumbler/LifeBar/ParticleContainer" instance=ExtResource("11_ie5ih")]
unique_name_in_owner = true
texture = ExtResource("15_eyqdi")
[node name="HealSFX" type="AudioStreamPlayer" parent="SouthWest/VBoxContainer/MarginContainer/LifeBarRumbler/LifeBar"]
unique_name_in_owner = true
stream = ExtResource("16_pub5c")
volume_db = -8.0
bus = &"SFX"
[node name="SWAnimation" type="AnimationPlayer" parent="SouthWest"]
unique_name_in_owner = true
root_node = NodePath("../..")

View File

@ -2,6 +2,7 @@ class_name PlayManager extends Resource
## Abstract base type for strategies to manage the flow of gameplay
## Emitted at the start of each new turn
@warning_ignore("unused_signal")
signal turn_started(player: WorldPlayer)
## List of game player instances