Skip to content

Commit

Permalink
Added basic foundation for Virtual Pet game: Pet has needs, they deca…
Browse files Browse the repository at this point in the history
…y over time, actions affect them.
  • Loading branch information
ShyPiano committed Apr 13, 2024
1 parent 88b9eba commit 782e333
Show file tree
Hide file tree
Showing 12 changed files with 339 additions and 0 deletions.
30 changes: 30 additions & 0 deletions notes/idea.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# LUDUM DARE 55
## Virtual Pet game
- take care of a little demon!
- Sims-like needs:
- Hunger
- Energy
- Confort
- Fun
- Bladder
- Hygiene
- no Social(?) (demons are lonely creatures)
- no Room(?)
- have them learn skills:
- Scaryness
- Possession
- Future vision
- Manipulation
- Barganing
- demon gets summoned from time to time
- each summoning has a list of requeriments
- certain skill levels
- failing (a certain amount of) summonings will lose you the game
- demon must be in a good mood to do a good job
- gain currency as a result of good pperformance
- better Barganing gets you more currency!
- player gets notified of imminent summoning sometime before they are summoned
- buy new stuff for your demon!
- successful summonings give you currency (souls)
- better objects allow faster skill building and need fulfilment
- some are decorative only?
8 changes: 8 additions & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@ config_version=5
[application]

config/name="ludum-dare-55"
run/main_scene="res://scenes/world.tscn"
config/features=PackedStringArray("4.2", "GL Compatibility")
config/icon="res://icon.svg"

[display]

window/size/viewport_width=720
window/size/viewport_height=940
window/size/resizable=false
window/handheld/orientation=5

[rendering]

renderer/rendering_method="gl_compatibility"
Expand Down
55 changes: 55 additions & 0 deletions scenes/demon.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[gd_scene load_steps=5 format=3 uid="uid://cxr45r0ukiibw"]

[ext_resource type="Script" path="res://scripts/Demon.gd" id="1_458ae"]
[ext_resource type="Texture2D" uid="uid://bl8vphjt2m81k" path="res://icon.svg" id="2_usy3u"]
[ext_resource type="PackedScene" uid="uid://cd5qy7i6kth1g" path="res://scenes/demon_need.tscn" id="3_23rv5"]
[ext_resource type="Script" path="res://scripts/DemonAction.gd" id="4_xwqmp"]

[node name="Demon" type="Node2D"]
script = ExtResource("1_458ae")

[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_usy3u")

[node name="Needs" type="Node" parent="."]

[node name="Hunger" parent="Needs" instance=ExtResource("3_23rv5")]
need_name = "Hunger"
decay = 4

[node name="Energy" parent="Needs" instance=ExtResource("3_23rv5")]
need_name = "Energy"

[node name="Bladder" parent="Needs" instance=ExtResource("3_23rv5")]
need_name = "Bladder"
decay = 4

[node name="Hygiene" parent="Needs" instance=ExtResource("3_23rv5")]
need_name = "Hygiene"

[node name="Comfort" parent="Needs" instance=ExtResource("3_23rv5")]
need_name = "Comfort"
decay = 6

[node name="Fun" parent="Needs" instance=ExtResource("3_23rv5")]
need_name = "Fun"
decay = 10

[node name="ActionTemplates" type="Node" parent="."]

[node name="HaveMeal" type="Node" parent="ActionTemplates"]
script = ExtResource("4_xwqmp")
action_name = "Have a Meal"
needs_effect = {
"Bladder": -6,
"Comfort": 1,
"Hunger": 10
}
action_duration = 5

[connection signal="need_update" from="Needs/Hunger" to="." method="_on_need_update"]
[connection signal="need_update" from="Needs/Energy" to="." method="_on_need_update"]
[connection signal="need_update" from="Needs/Bladder" to="." method="_on_need_update"]
[connection signal="need_update" from="Needs/Hygiene" to="." method="_on_need_update"]
[connection signal="need_update" from="Needs/Comfort" to="." method="_on_need_update"]
[connection signal="need_update" from="Needs/Fun" to="." method="_on_need_update"]
6 changes: 6 additions & 0 deletions scenes/demon_action.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://do5kg1fbtty5g"]

[ext_resource type="Script" path="res://scripts/DemonAction.gd" id="1_vo2i8"]

[node name="DemonAction" type="Node"]
script = ExtResource("1_vo2i8")
6 changes: 6 additions & 0 deletions scenes/demon_need.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://cd5qy7i6kth1g"]

[ext_resource type="Script" path="res://scripts/DemonNeed.gd" id="1_wwgsx"]

[node name="Need" type="Node"]
script = ExtResource("1_wwgsx")
79 changes: 79 additions & 0 deletions scenes/ui/hud.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
[gd_scene load_steps=2 format=3 uid="uid://bh4d73stc2rt"]

[ext_resource type="Script" path="res://scripts/ui/Hud.gd" id="1_1vslh"]

[node name="HUD" type="CanvasLayer"]
script = ExtResource("1_1vslh")
need_bars = {
"Bladder": NodePath("NeedBarsBox/BladderNeedBar"),
"Comfort": NodePath("NeedBarsBox/ComfortNeedBar"),
"Energy": NodePath("NeedBarsBox/EnergyNeedBar"),
"Fun": NodePath("NeedBarsBox/FunNeedBar"),
"Hunger": NodePath("NeedBarsBox/HungerNeedBar"),
"Hygiene": NodePath("NeedBarsBox/HygieneNeedBar")
}

[node name="PauseBtn" type="Button" parent="."]
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -64.0
offset_bottom = 64.0
grow_horizontal = 0
toggle_mode = true
text = "Pause"

[node name="NeedBarsBox" type="VBoxContainer" parent="."]
anchors_preset = -1
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_top = -92.0
offset_bottom = -3.0
grow_horizontal = 2
grow_vertical = 0
alignment = 1

[node name="HungerNeedBar" type="ProgressBar" parent="NeedBarsBox"]
layout_mode = 2
min_value = -1000.0
max_value = 1000.0
step = 1.0
value = 750.0

[node name="EnergyNeedBar" type="ProgressBar" parent="NeedBarsBox"]
layout_mode = 2
min_value = -1000.0
max_value = 1000.0
step = 1.0
value = 750.0

[node name="BladderNeedBar" type="ProgressBar" parent="NeedBarsBox"]
layout_mode = 2
min_value = -1000.0
max_value = 1000.0
step = 1.0
value = 750.0

[node name="HygieneNeedBar" type="ProgressBar" parent="NeedBarsBox"]
layout_mode = 2
min_value = -1000.0
max_value = 1000.0
step = 1.0
value = 750.0

[node name="ComfortNeedBar" type="ProgressBar" parent="NeedBarsBox"]
layout_mode = 2
min_value = -1000.0
max_value = 1000.0
step = 1.0
value = 750.0

[node name="FunNeedBar" type="ProgressBar" parent="NeedBarsBox"]
layout_mode = 2
min_value = -1000.0
max_value = 1000.0
step = 1.0
value = 750.0

[connection signal="pressed" from="PauseBtn" to="." method="_on_pause_btn_pressed"]
23 changes: 23 additions & 0 deletions scenes/world.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[gd_scene load_steps=4 format=3 uid="uid://cfoypma2ump0p"]

[ext_resource type="Script" path="res://scripts/World.gd" id="1_1ap2o"]
[ext_resource type="PackedScene" uid="uid://cxr45r0ukiibw" path="res://scenes/demon.tscn" id="2_6t0hy"]
[ext_resource type="PackedScene" uid="uid://bh4d73stc2rt" path="res://scenes/ui/hud.tscn" id="3_oqr52"]

[node name="World" type="Node" node_paths=PackedStringArray("demon", "ticker", "hud")]
script = ExtResource("1_1ap2o")
demon = NodePath("Demon")
ticker = NodePath("Ticker")
hud = NodePath("HUD")

[node name="Demon" parent="." instance=ExtResource("2_6t0hy")]
position = Vector2(368, 384)

[node name="Ticker" type="Timer" parent="."]
autostart = true

[node name="HUD" parent="." instance=ExtResource("3_oqr52")]

[connection signal="need_update" from="Demon" to="." method="_on_demon_need_update"]
[connection signal="timeout" from="Ticker" to="." method="_on_ticker_timeout"]
[connection signal="pause_pressed" from="HUD" to="." method="_on_pause_pressed"]
41 changes: 41 additions & 0 deletions scripts/Demon.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class_name Demon
extends Node

var curr_action: DemonAction = null :
set(action_template):
if action_template == null:
curr_action = null
return
curr_action = action_template.duplicate()
curr_action.action_end.connect(end_action)

@export var needs: Dictionary = {
"Hunger": NodePath(^"Needs/Hunger"),
"Energy": NodePath(^"Needs/Energy"),
"Bladder": NodePath(^"Needs/Bladder"),
"Hygiene": NodePath(^"Needs/Hygiene"),
"Comfort": NodePath(^"Needs/Comfort"),
"Fun": NodePath(^"Needs/Fun")
}

func _ready():
for n in needs:
needs[n] = (get_node(needs[n]) as DemonNeed)
# TODO remove debug action:
curr_action = get_node(^"ActionTemplates/HaveMeal")

func tick():
if curr_action != null:
for n_name in curr_action.needs_effect:
needs[n_name].replenish(curr_action.needs_effect[n_name])
curr_action.tick()

for n_name in needs:
needs[n_name].tick()

func end_action():
curr_action = null

signal need_update(need_name: String, old_val: int, new_val: int)
func _on_need_update(need_name, old_val, new_val):
need_update.emit(need_name, old_val, new_val)
24 changes: 24 additions & 0 deletions scripts/DemonAction.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class_name DemonAction
extends Node

signal action_end

@export var action_name: String
@export var needs_effect: Dictionary = {
"Hunger": 0,
"Energy": 0,
"Bladder": 0,
"Hygiene": 0,
"Comfort": 0,
"Fun": 0
}
@export var action_duration: int = -1

func tick():
if action_duration > 0:
action_duration -= 1
if action_duration == 0:
end_action()

func end_action():
action_end.emit()
26 changes: 26 additions & 0 deletions scripts/DemonNeed.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class_name DemonNeed
extends Node

signal need_catastrophy(need_name: String)
signal need_update(need_name: String, old_val: int, new_val: int)

@export var need_name: String
@export var curr_val: int = 750
const MAX_VAL: int = 1000
const MIN_VAL:int = -1000
@export var decay: int = 1
var next_tick_delta: int = -decay

func tick():
var old_val: int = curr_val
set_value(curr_val + next_tick_delta)
if curr_val == MIN_VAL:
need_catastrophy.emit(need_name)
need_update.emit(need_name, old_val, curr_val)
next_tick_delta = -decay

func replenish(val: int):
next_tick_delta = val

func set_value(val: int):
curr_val = clamp(val, MIN_VAL, MAX_VAL)
26 changes: 26 additions & 0 deletions scripts/World.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
extends Node

@export var demon: Demon
@export var ticker: Timer
@export var hud: Hud

# curr_time: number of minutes passed since in-game midnight
# start at 09:00
const MINUTES_IN_DAY: int = 1440
@export var day_start_time: int = 540
var curr_time: int = day_start_time
var curr_day: int = 0

func _on_ticker_timeout():
demon.tick()
curr_time = (curr_time + 1) % MINUTES_IN_DAY
if curr_time == 0:
curr_day += 1


func _on_pause_pressed():
ticker.paused = !ticker.paused


func _on_demon_need_update(need_name: String, old_val: int, new_val: int):
hud.update_need_bar(need_name, old_val, new_val)
15 changes: 15 additions & 0 deletions scripts/ui/Hud.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class_name Hud
extends CanvasLayer

signal pause_pressed

@export var need_bars: Dictionary
func _ready():
for n in need_bars:
need_bars[n] = (get_node(need_bars[n]) as ProgressBar)

func _on_pause_btn_pressed():
pause_pressed.emit()

func update_need_bar(need_name: String, _old_val: int, new_val: int):
need_bars[need_name].value = new_val

0 comments on commit 782e333

Please sign in to comment.