Przeglądaj źródła

Initial commit

main
Noëlle 6 dni temu
commit
337c459b06
Nie znaleziono w bazie danych klucza dla tego podpisu

+ 2
- 0
.gitattributes Wyświetl plik

@@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

+ 4
- 0
.gitignore Wyświetl plik

@@ -0,0 +1,4 @@
# Godot 4+ specific ignores
.godot/
../
../*

+ 1
- 0
icon.svg Wyświetl plik

@@ -0,0 +1 @@
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="124" height="124" rx="14" fill="#363d52" stroke="#212532" stroke-width="4"/><g transform="scale(.101) translate(122 122)"><g fill="#fff"><path d="M105 673v33q407 354 814 0v-33z"/><path d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z" fill="#478cbf"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></g></svg>

+ 37
- 0
icon.svg.import Wyświetl plik

@@ -0,0 +1,37 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://bjunj6kcndj3j"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

+ 28
- 0
project.godot Wyświetl plik

@@ -0,0 +1,28 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters

config_version=5

[application]

config/name="DNA Idle Game"
run/main_scene="res://scenes/main.tscn"
config/features=PackedStringArray("4.2", "Mobile")
config/icon="res://icon.svg"

[input]

ClickItem={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}

[rendering]

renderer/rendering_method="mobile"

+ 10
- 0
scenes/analyzers.tscn Wyświetl plik

@@ -0,0 +1,10 @@
[gd_scene load_steps=2 format=3 uid="uid://fe1lihrecu3u"]

[ext_resource type="Script" path="res://scripts/Analyzers/analyzers.gd" id="1_u0rar"]

[node name="Analyzers" type="Node"]
script = ExtResource("1_u0rar")

[node name="Level 1" type="Node" parent="."]

[node name="Timer" type="Timer" parent="."]

+ 32
- 0
scenes/click_target.tscn Wyświetl plik

@@ -0,0 +1,32 @@
[gd_scene load_steps=5 format=3 uid="uid://bc2qthu8tugim"]

[ext_resource type="Script" path="res://scripts/ClickTarget/click_target.gd" id="1_ki655"]
[ext_resource type="Script" path="res://scripts/ClickTarget/energy_creator.gd" id="2_17jgy"]
[ext_resource type="Script" path="res://scripts/ClickTarget/buy_l1_generator.gd" id="3_yqqol"]
[ext_resource type="Script" path="res://scripts/ClickTarget/buy_l1_analyzer.gd" id="4_fpmpw"]

[node name="ClickTarget" type="Node"]
script = ExtResource("1_ki655")

[node name="Energy Creator" type="Button" parent="."]
visible = false
offset_left = 394.0
offset_top = 301.0
offset_right = 402.0
offset_bottom = 309.0
text = "Click me!"
script = ExtResource("2_17jgy")

[node name="Buy L1 Generator" type="Button" parent="."]
visible = false
offset_left = 536.0
offset_top = 301.0
offset_right = 544.0
offset_bottom = 309.0
script = ExtResource("3_yqqol")

[node name="Buy L1 Analyzer" type="Button" parent="."]
visible = false
offset_right = 8.0
offset_bottom = 8.0
script = ExtResource("4_fpmpw")

+ 23
- 0
scenes/generators.tscn Wyświetl plik

@@ -0,0 +1,23 @@
[gd_scene load_steps=3 format=3 uid="uid://b6w7cs7fffyv7"]

[ext_resource type="Script" path="res://scripts/Generators/generators.gd" id="1_yc76t"]
[ext_resource type="Script" path="res://scripts/Generators/generator_level_1.gd" id="2_nlfwd"]

[node name="Generators" type="Node"]
script = ExtResource("1_yc76t")

[node name="Level 1" type="Node" parent="."]
script = ExtResource("2_nlfwd")
click_value = 0

[node name="L1 Display" type="Node2D" parent="Level 1"]
visible = false
position = Vector2(542, 178)

[node name="L1 Text" type="RichTextLabel" parent="Level 1/L1 Display"]
offset_right = 210.0
offset_bottom = 25.0

[node name="GeneratorTimer" type="Timer" parent="."]

[connection signal="timeout" from="GeneratorTimer" to="Level 1" method="_on_generator_timer_timeout"]

+ 38
- 0
scenes/main.tscn Wyświetl plik

@@ -0,0 +1,38 @@
[gd_scene load_steps=6 format=3 uid="uid://daggped4nujna"]

[ext_resource type="Script" path="res://scripts/Main Interface.gd" id="1_ltn0e"]
[ext_resource type="PackedScene" uid="uid://bc2qthu8tugim" path="res://scenes/click_target.tscn" id="2_2hdm6"]
[ext_resource type="PackedScene" uid="uid://c4ocioaw64kq2" path="res://scenes/messages.tscn" id="2_d66gc"]
[ext_resource type="PackedScene" uid="uid://b6w7cs7fffyv7" path="res://scenes/generators.tscn" id="3_qm46o"]
[ext_resource type="PackedScene" uid="uid://fe1lihrecu3u" path="res://scenes/analyzers.tscn" id="4_kptdw"]

[node name="Main" type="Node2D"]

[node name="Messages" parent="." instance=ExtResource("2_d66gc")]

[node name="Generators" parent="." instance=ExtResource("3_qm46o")]

[node name="Analyzers" parent="." instance=ExtResource("4_kptdw")]

[node name="Main Interface" type="CanvasLayer" parent="."]
script = ExtResource("1_ltn0e")

[node name="ClickTarget" parent="Main Interface" instance=ExtResource("2_2hdm6")]

[connection signal="narration_end_introduction" from="Messages" to="Main Interface" method="_on_messages_narration_end_introduction"]
[connection signal="end_introduction" from="Messages/Narration" to="Main Interface" method="_on_narration_end_introduction"]
[connection signal="gl1_click" from="Generators/Level 1" to="Messages/Score" method="_on_level_1_gl_1_click"]
[connection signal="interface_ready" from="Main Interface" to="Messages/Narration" method="_on_interface_ready"]
[connection signal="interface_ready" from="Main Interface" to="Messages/Score" method="_on_interface_ready"]
[connection signal="interface_ready" from="Main Interface" to="Generators" method="_on_interface_ready"]
[connection signal="interface_ready" from="Main Interface" to="Generators/Level 1" method="_on_interface_ready"]
[connection signal="interface_ready" from="Main Interface" to="Analyzers" method="_on_interface_ready"]
[connection signal="score_update" from="Main Interface" to="Messages/Score" method="_on_score_update"]
[connection signal="pressed" from="Main Interface/ClickTarget/Energy Creator" to="Main Interface" method="_on_energy_creator_pressed"]
[connection signal="pressed" from="Main Interface/ClickTarget/Buy L1 Generator" to="Main Interface" method="_on_buy_l_1_generator_pressed"]
[connection signal="pressed" from="Main Interface/ClickTarget/Buy L1 Analyzer" to="Main Interface" method="_on_buy_l_1_analyzer_pressed"]

[editable path="Messages"]
[editable path="Generators"]
[editable path="Analyzers"]
[editable path="Main Interface/ClickTarget"]

+ 39
- 0
scenes/messages.tscn Wyświetl plik

@@ -0,0 +1,39 @@
[gd_scene load_steps=4 format=3 uid="uid://c4ocioaw64kq2"]

[ext_resource type="Script" path="res://scripts/Messages/messages.gd" id="1_logqo"]
[ext_resource type="Script" path="res://scripts/Messages/narration.gd" id="2_jrcmu"]
[ext_resource type="Script" path="res://scripts/Messages/score.gd" id="3_tungw"]

[node name="Messages" type="Node"]
script = ExtResource("1_logqo")

[node name="Narration" type="RichTextLabel" parent="."]
offset_left = 63.0
offset_top = 222.0
offset_right = 806.0
offset_bottom = 286.0
bbcode_enabled = true
scroll_following = true
script = ExtResource("2_jrcmu")

[node name="MessageTimer" type="Timer" parent="Narration"]

[node name="Score" type="RichTextLabel" parent="."]
offset_left = 331.0
offset_top = 160.0
offset_right = 526.0
offset_bottom = 186.0
script = ExtResource("3_tungw")

[node name="Score Per Second" type="RichTextLabel" parent="."]
visible = false
offset_left = 339.0
offset_top = 186.0
offset_right = 531.0
offset_bottom = 216.0
metadata/_edit_use_anchors_ = true

[node name="SPS Timer" type="Timer" parent="Score Per Second"]
autostart = true

[connection signal="end_introduction" from="Narration" to="." method="_on_narration_end_introduction"]

+ 18
- 0
scripts/Analyzers/analyzers.gd Wyświetl plik

@@ -0,0 +1,18 @@
extends Node

@onready var l1 = $"Level 1"
@onready var timer = $Timer


# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass


func _on_interface_ready():
pass # Replace with function body.

+ 13
- 0
scripts/ClickTarget/buy_l1_analyzer.gd Wyświetl plik

@@ -0,0 +1,13 @@
extends Button

@export var cost_per_tick: int = -1

# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass


+ 13
- 0
scripts/ClickTarget/buy_l1_generator.gd Wyświetl plik

@@ -0,0 +1,13 @@
extends Button

@export var current_cost = 10

# Called when the node enters the scene tree for the first time.
func _ready():
pass


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass


+ 13
- 0
scripts/ClickTarget/click_target.gd Wyświetl plik

@@ -0,0 +1,13 @@
extends Node

@onready var energy_creator = $"Energy Creator"
@onready var buy_l1 = $"Buy L1 Generator"

# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

+ 11
- 0
scripts/ClickTarget/energy_creator.gd Wyświetl plik

@@ -0,0 +1,11 @@
extends Button

@export var energy_created = 1

# Called when the node enters the scene tree for the first time.
func _ready():
pressed.connect($"../..::_on_energy_creator_pressed".bind(energy_created))

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

+ 39
- 0
scripts/Generators/generator_level_1.gd Wyświetl plik

@@ -0,0 +1,39 @@
extends Node

@export var cost = 10
@export var click_value = 1
@export var active = false
@onready var generator_timer = $"../GeneratorTimer"
@onready var l1_display = $"L1 Display"
@onready var score
@onready var l1_text
@onready var my_timer

@onready var text1 = "Clicking "
@onready var text2 = " per second!"

signal gl1_click(value)

# Called when the node enters the scene tree for the first time.
func _ready():
# Don't use this unless you want it to happen before the interface loads! Use _on_interface_ready instead.
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

func start_clicking():
active = true
generator_timer.start()

func _on_generator_timer_timeout():
if active:
print("Emitted click.")
gl1_click.emit(click_value)
generator_timer.start()

func _on_interface_ready():
l1_text = $"L1 Display/L1 Text"
score = $"../../Messages/Score"

+ 20
- 0
scripts/Generators/generators.gd Wyświetl plik

@@ -0,0 +1,20 @@
extends Node

@onready var l1 = $"Level 1"
@onready var l1_display = $"Level 1/L1 Display"
@onready var l1_text = $"Level 1/L1 Display/L1 Text"
@onready var generator_timer = $GeneratorTimer

# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass


func _on_interface_ready():
pass # Replace with function body.

+ 124
- 0
scripts/Main Interface.gd Wyświetl plik

@@ -0,0 +1,124 @@
extends CanvasLayer

signal button_click
# Local imports
@onready var click_target = $ClickTarget

# Other scene imports
@onready var messages = $"../Messages"
#@onready var narration = $"../Messages/Narration"
@onready var generators = $"../Generators"
@onready var analyzers = $"../Analyzers"

# Global variables
@onready var line_thresholds = [1, 5, 10, 25, 75, 300]
@onready var next_threshold: int
@onready var autoclicker_cost: int = 10
@onready var current_per_second_score: float = 0.0
@onready var second_scores = []

@export var energy_creator_click_value = 1
@export var l1_generator_initial_cost = 10
@export var l1_generator_click_value = 1
@export var l1_analyzer_initial_cost = 25
@export var l1_analyzer_click_cost = -1

signal interface_ready
signal score_update(value)

# Called when the node enters the scene tree for the first time.
func _ready():
# SETUP
# This is set in inspector options, but just in case.
messages.narration.json_content = get_json_file_content(messages.narration.lines_file_path)
click_target.buy_l1.visible = false
click_target.buy_l1.text = "Add L1 Generator (costs " + str(generators.l1.cost) + ")"
print("Emitting interface_ready signal.")
interface_ready.emit()

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

func update_score(new_score):
messages.score.update(new_score)
if messages.score.total_score == 1:
await get_tree().create_timer(0.5).timeout
messages.message.show_message_by_id(2)
await get_tree().create_timer(1).timeout
messages.message.show_message_by_id(3)
elif messages.score.total_score == 10:
await get_tree().create_timer(0.5).timeout
messages.message.show_message_by_id(4)
await get_tree().create_timer(1).timeout
messages.message.show_message_by_id(5)
await get_tree().create_timer(1).timeout
messages.message.show_message_by_id(6)
await get_tree().create_timer(1).timeout
messages.message.show_message_by_id(7)
await get_tree().create_timer(1).timeout
messages.message.show_message_by_id(8)
await get_tree().create_timer(1).timeout
click_target.buy_l1.visible = true
messages.message.show_message_by_id(9)


func _on_add_item_target_pressed():
if messages.score.current_score < autoclicker_cost:
pass
else:
generators.l1.click_value += 1
if not generators.l1.l1_auto_display.visible:
generators.l1.l1_auto_text.text = generators.l1.text1 + str(generators.l1.click_value) + "x" + generators.l1.text2
generators.l1.l1_auto_display.show()
generators.l1.start_clicking()
messages.message.show_message_by_id(10)
messages.score.update(0 - autoclicker_cost)
autoclicker_cost = (autoclicker_cost * 1 + (generators.l1.click_value)) * 1.5
click_target.buy_l1.text = "Buy Autoclicker (costs " + str(autoclicker_cost) + ")"

func _on_sps_timer_timeout():
if len(messages.score.prev_second_scores) >= 5:
messages.score.prev_second_scores.pop_at(0)
messages.score.prev_second_scores.append(messages.score.current_second_score)
messages.score.current_second_score = 0
var avg_score: float = messages.score.prev_second_scores.reduce(func(acc, c): return acc + c, 0)
current_per_second_score = avg_score / len(messages.score.prev_second_scores)
messages.sps.text = str(current_per_second_score) + " per second"
messages.sps_timer.start()

func get_text_file_content(file_path):
var file = FileAccess.open(file_path, FileAccess.READ)
var content = file.get_as_text()
return content

func get_json_file_content(file_path):
var file = FileAccess.open(file_path, FileAccess.READ)
var content = file.get_as_text()
var json_content = JSON.parse_string(content)
return json_content

func _on_message_timer_timeout():
pass # Replace with function body.

func update_second_score(new_score):
pass

func _on_narration_end_introduction():
click_target.energy_creator.visible = true


func _on_energy_creator_pressed():
messages.sps.visible = true
update_score(energy_creator_click_value)


func _on_buy_l_1_generator_pressed():
update_score(l1_generator_initial_cost)


func _on_buy_l_1_analyzer_pressed():
update_score(l1_analyzer_initial_cost)

+ 22
- 0
scripts/Messages/messages.gd Wyświetl plik

@@ -0,0 +1,22 @@
extends Node

@onready var narration = $Narration
@onready var narration_timer = $Narration/MessageTimer
@onready var score = $Score
@onready var sps = $"Score Per Second"
@onready var sps_timer = $"Score Per Second/SPS Timer"

signal narration_end_introduction

# Called when the node enters the scene tree for the first time.
func _ready():
pass

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass



func _on_narration_end_introduction():
narration_end_introduction.emit()

+ 61
- 0
scripts/Messages/narration.gd Wyświetl plik

@@ -0,0 +1,61 @@
extends RichTextLabel

@onready var message_timer = $MessageTimer

@onready var json_content: Dictionary
@onready var message_lines: Dictionary
@onready var messages_seen: Array

@onready var lines_file_path = "res://text/message_lines.json"

@export var lines_displayed = []

signal end_introduction

# Called when the node enters the scene tree for the first time.
func _ready():
set_scroll_follow(true)

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
pass

func show_message_by_id(section: String, idnum: int):
var unique_id = section + str(idnum)
if unique_id not in messages_seen:
show_message(message_lines[section][idnum])
messages_seen.append(unique_id)

func show_message(msg):
lines_displayed.append(_centered_message(msg))
#var new_text = _nl_append(message.text, _centered_message(msg))
text = ("\n").join(lines_displayed)
show()

func _nl_append(msg1, msg2):
return msg1 + "\n" + msg2

func _centered_message(msg):
return "[center]" + msg + "[/center]"
func display_introduction():
print("Displaying introduction.")
show_message_by_id("introduction", 0)
await get_tree().create_timer(1.0).timeout
show_message_by_id("introduction", 1)
await get_tree().create_timer(0.5).timeout
end_introduction.emit()


func _on_interface_ready():
print("Narration received interface_ready signal.")
var main_sequence_messages = json_content["main_sequence_messages"]
print("Got JSON content keys " + ", ".join(main_sequence_messages.keys()))
for section in main_sequence_messages.keys():
message_lines[section] = []
var section_lines = main_sequence_messages[section]
section_lines.sort_custom(func(a,b): return a["id"] < b["id"])
for line in section_lines:
message_lines[section].append(line["text"])
display_introduction()

+ 35
- 0
scripts/Messages/score.gd Wyświetl plik

@@ -0,0 +1,35 @@
extends RichTextLabel

@export var current_score = 0
@export var current_second_score = 0
@export var total_score = 0
@export var prev_second_scores: Array

@onready var score_per_second = $"../Score Per Second"
@onready var narration = $"../Narration"

# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

func update(score):
if score >= 0:
current_second_score += score
current_score += score
total_score += score
update_text(current_score)
func update_text(score_num):
text = "Energy: " + str(current_score)


func _on_interface_ready():
pass # Replace with function body.

func _on_score_update(click_value):
update(click_value)

+ 77
- 0
text/message_lines.json Wyświetl plik

@@ -0,0 +1,77 @@
{
"main_sequence_messages": {
"introduction": [
{
"id": 0,
"text": "Welcome to SPARK, the Species Preservation and Reconstruction Kit.",
},
{
"id": 1,
"text": "I'll add a button below this text. Please click it once."
}
],
"get_to_10": [
{
"id": 0,
"text": "Well done! You'll notice that your energy total has gone up."
},
{
"id": 1,
"text": "Go ahead and click a few more times. Your target energy is 10."
}
],
"explain_mechanism": [
{
"id": 0,
"text": "Good work. The SPARK click mechanism works a little like an old engine."
},
{
"id": 1,
"text": "You have to crank it a few times to get it started."
},
{
"id": 2,
"text": "Each click provides a little bit of the energy that SPARK needs to operate."
},
{
"id": 3,
"text": "But now that we've got some energy in the bank, we can start the engines up, so to speak."
},
{
"id": 4,
"text": "With the energy your clicks have yielded, you can start up an automated generator."
},
{
"id": 5,
"text": "I've added a button where you can do just that."
}
],
"bought_generator": [
{ "id": 0,
"text": "The generator will yield the equivalent of one click per second."
},
{
"id": 1,
"text": "You can use your energy to activate additional generators. Their total output is shown above."
}
],
"afford_analyzer": [
{
"id": 0,
"text": "Once you have enough energy stored, you can turn on an analyzer."
},
{
"id": 1,
"text": "Analyzers use energy to scan DNA fragments and work out how they fit together."
},
{
"id": 3,
"text": "And before you ask, we know all of these fragments are less than a myriad old."
},
{
"id": 4,
"text": "They've decayed a bit, but they're still readable."
}
]
}
}

+ 6
- 0
text/message_lines.txt Wyświetl plik

@@ -0,0 +1,6 @@
Click the button.
Good job! Now click it again a few times.
A couple more...
Nice. The clicker interface works.
You should see an "Add Item" button - click that.
Click the "Add Item" button again.

Ładowanie…
Anuluj
Zapisz