diff --git a/globals/inventory.gd b/globals/inventory.gd index bb16666..acfdfa3 100644 --- a/globals/inventory.gd +++ b/globals/inventory.gd @@ -1,12 +1,19 @@ extends Node +# SIGNALS +signal inventory_changed + +# The players current monsters in the inventory are saved here +var monsters: Array # Called when the node enters the scene tree for the first time. func _ready() -> void: - print("Hello from Inventory") - pass # Replace with function body. + setup_new_inventory() - -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass +func setup_new_inventory() -> void: + var stats = MonsterStats.new() + stats.manual_init() + monsters.append(stats) + # debug timeout to wait for the debug UI + await get_tree().create_timer(1.0).timeout + inventory_changed.emit() diff --git a/materials/CollisionDebugMaterial.tres b/materials/CollisionDebugMaterial.tres new file mode 100644 index 0000000..644f726 --- /dev/null +++ b/materials/CollisionDebugMaterial.tres @@ -0,0 +1,5 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://ctul3e67rcq23"] + +[resource] +transparency = 1 +albedo_color = Color(1, 0.435294, 0.356863, 0.392157) diff --git a/project.godot b/project.godot index b945baf..107ff9e 100644 --- a/project.godot +++ b/project.godot @@ -14,7 +14,11 @@ config/name="monsterfangen" run/main_scene="res://scenes/main.tscn" config/features=PackedStringArray("4.3", "Mobile") boot_splash/image="res://assets/logo/logo.png" -config/icon="res://icon.svg" +config/icon="res://assets/logo/logo.png" + +[autoload] + +Inventory="*res://globals/inventory.gd" [display] diff --git a/resources/monster_stats.gd b/resources/monster_stats.gd index b06d56b..9d34eb5 100644 --- a/resources/monster_stats.gd +++ b/resources/monster_stats.gd @@ -3,11 +3,26 @@ extends Resource @export var thumbnail: CompressedTexture2D = preload("res://assets/logo/logo.png") @export var name: String = "MISSINGNO" -@export var health: int = 100 -@export var attack_value: int = 10 -@export var defense_value: int = 10 -@export var speed_value: int = 10 +var spitzname: String = "" +@export var level: int = 1 +@export var base_health: int = 100 +@export var base_attack: int = 10 +@export var base_defense: int = 10 +@export var base_speed: int = 10 @export var model: PackedScene +var health: int +var max_health: int +var attack: int +var defense: int +var speed: int + func _init() -> void: - pass + max_health = base_health + 1.05 * level + health = max_health + attack = base_attack + defense = base_defense + speed = base_speed + +func manual_init() -> void: + print("TODO: Manual init") diff --git a/scenes/debug_level.tscn b/scenes/debug_level.tscn index d01b7aa..2caea11 100644 --- a/scenes/debug_level.tscn +++ b/scenes/debug_level.tscn @@ -1,9 +1,17 @@ -[gd_scene load_steps=15 format=3 uid="uid://p8agd0dfam0p"] +[gd_scene load_steps=11 format=3 uid="uid://p8agd0dfam0p"] [ext_resource type="PackedScene" uid="uid://be5bc5gjbo875" path="res://scenes/player.tscn" id="1_ra6oo"] -[ext_resource type="PackedScene" uid="uid://tyjgdu65yj3m" path="res://assets/models/round_bat/round_bat_skin.tscn" id="2_lks2w"] [ext_resource type="PackedScene" uid="uid://dawpmu4vvv3rs" path="res://scenes/monster_spawnpoint.tscn" id="3_esgto"] -[ext_resource type="PackedScene" uid="uid://cytaswycabcel" path="res://scenes/monster.tscn" id="4_bpsqy"] +[ext_resource type="Script" path="res://resources/monster_stats.gd" id="3_iktqp"] +[ext_resource type="Resource" uid="uid://ym438vedcdyl" path="res://resources/DebugMonster1.tres" id="4_3y7gi"] + +[sub_resource type="PlaneMesh" id="PlaneMesh_wak6a"] +size = Vector2(1000, 1000) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8wti1"] +albedo_color = Color(0.157906, 0.300646, 0.191269, 1) + +[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_m4bnl"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_g80j5"] sky_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) @@ -18,28 +26,23 @@ sky = SubResource("Sky_wlahx") tonemap_mode = 2 glow_enabled = true -[sub_resource type="PlaneMesh" id="PlaneMesh_wak6a"] -size = Vector2(1000, 1000) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_8wti1"] -albedo_color = Color(0.157906, 0.300646, 0.191269, 1) - -[sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_m4bnl"] - -[sub_resource type="BoxMesh" id="BoxMesh_5i27t"] -size = Vector3(2, 2, 2) - -[sub_resource type="BoxShape3D" id="BoxShape3D_xmo7q"] -size = Vector3(2, 2, 2) - -[sub_resource type="BoxMesh" id="BoxMesh_h1buf"] -size = Vector3(2, 5, 2) - -[sub_resource type="BoxShape3D" id="BoxShape3D_522pk"] -size = Vector3(2, 5, 2) - [node name="DebugLevel" type="Node3D"] +[node name="Player" parent="." instance=ExtResource("1_ra6oo")] + +[node name="Floor" type="StaticBody3D" parent="."] +metadata/_edit_lock_ = true + +[node name="FloorMesh" type="MeshInstance3D" parent="Floor"] +mesh = SubResource("PlaneMesh_wak6a") +skeleton = NodePath("../..") +surface_material_override/0 = SubResource("StandardMaterial3D_8wti1") +metadata/_edit_lock_ = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor"] +shape = SubResource("WorldBoundaryShape3D_m4bnl") +metadata/_edit_lock_ = true + [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(0.224144, 0.474445, -0.851271, 0.12941, 0.851271, 0.508518, 0.965926, -0.224144, 0.129409, 0, 0, 0) shadow_enabled = true @@ -47,45 +50,8 @@ shadow_enabled = true [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_rwve8") -[node name="Floor" type="StaticBody3D" parent="."] - -[node name="FloorMesh" type="MeshInstance3D" parent="Floor"] -mesh = SubResource("PlaneMesh_wak6a") -skeleton = NodePath("../..") -surface_material_override/0 = SubResource("StandardMaterial3D_8wti1") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="Floor"] -shape = SubResource("WorldBoundaryShape3D_m4bnl") - -[node name="Player" parent="." instance=ExtResource("1_ra6oo")] - -[node name="DebugCube" type="StaticBody3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, -10) - -[node name="CubeMesh" type="MeshInstance3D" parent="DebugCube"] -mesh = SubResource("BoxMesh_5i27t") -skeleton = NodePath("../..") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="DebugCube"] -shape = SubResource("BoxShape3D_xmo7q") - -[node name="DebugCube2" type="StaticBody3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 9.03764, 1, -10) - -[node name="CubeMesh" type="MeshInstance3D" parent="DebugCube2"] -mesh = SubResource("BoxMesh_h1buf") -skeleton = NodePath("../..") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="DebugCube2"] -shape = SubResource("BoxShape3D_522pk") - -[node name="Monster" type="Node3D" parent="."] -transform = Transform3D(0.886107, 0, 0.463482, 0, 1, 0, -0.463482, 0, 0.886107, -2, 0, -4) - -[node name="RoundBatSkin" parent="Monster" instance=ExtResource("2_lks2w")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) -script = null - [node name="MonsterSpawnpoint" parent="." instance=ExtResource("3_esgto")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, -10) -spawnable_monsters = Array[PackedScene]([ExtResource("4_bpsqy")]) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -12) +spawnable_monsters = Array[ExtResource("3_iktqp")]([ExtResource("4_3y7gi")]) +ignore_visibility = true +max_monsters = 1 diff --git a/scenes/main.tscn b/scenes/main.tscn index bd70418..f3c40c4 100644 --- a/scenes/main.tscn +++ b/scenes/main.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=8 format=3 uid="uid://cswuap81n7t3f"] +[gd_scene load_steps=9 format=3 uid="uid://cswuap81n7t3f"] [ext_resource type="Texture2D" uid="uid://b6ylra30qxf30" path="res://assets/logo/logo.png" id="1_fpt28"] [ext_resource type="PackedScene" uid="uid://p8agd0dfam0p" path="res://scenes/debug_level.tscn" id="1_j851n"] +[ext_resource type="Script" path="res://scripts/inventory.gd" id="2_0mkyf"] [ext_resource type="FontFile" uid="uid://dmc6dygxrekja" path="res://assets/fonts/BreatheFireIii-PKLOB.ttf" id="2_vjast"] [ext_resource type="Script" path="res://scripts/joystick.gd" id="4_6b5cb"] [ext_resource type="Texture2D" uid="uid://8anyvhkcy4ng" path="res://assets/textures/Xbox Series/Vector/xbox_button_a.svg" id="5_pwhwh"] @@ -16,9 +17,50 @@ [node name="DebugLevel" parent="CurrentLevel" instance=ExtResource("1_j851n")] [node name="CanvasLayer" type="CanvasLayer" parent="."] -visible = false + +[node name="Inventory" type="Control" parent="CanvasLayer"] +layout_mode = 3 +anchors_preset = 10 +anchor_right = 1.0 +grow_horizontal = 2 +script = ExtResource("2_0mkyf") + +[node name="MonsterList" type="VBoxContainer" parent="CanvasLayer/Inventory"] +layout_mode = 1 +anchors_preset = 1 +anchor_left = 1.0 +anchor_right = 1.0 +offset_left = -137.0 +offset_bottom = 40.0 +grow_horizontal = 0 +theme_override_constants/separation = 10 + +[node name="Monster1" type="Label" parent="CanvasLayer/Inventory/MonsterList"] +layout_mode = 2 +text = "Monster 1: empty" + +[node name="Monster2" type="Label" parent="CanvasLayer/Inventory/MonsterList"] +layout_mode = 2 +text = "Monster 2: empty" + +[node name="Monster3" type="Label" parent="CanvasLayer/Inventory/MonsterList"] +layout_mode = 2 +text = "Monster 3: empty" + +[node name="Monster4" type="Label" parent="CanvasLayer/Inventory/MonsterList"] +layout_mode = 2 +text = "Monster 4: empty" + +[node name="Monster5" type="Label" parent="CanvasLayer/Inventory/MonsterList"] +layout_mode = 2 +text = "Monster 5: empty" + +[node name="Monster6" type="Label" parent="CanvasLayer/Inventory/MonsterList"] +layout_mode = 2 +text = "Monster 6: empty" [node name="MainMenu" type="Control" parent="CanvasLayer"] +visible = false layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 diff --git a/scenes/monster.tscn b/scenes/monster.tscn index 4db8287..27af6e4 100644 --- a/scenes/monster.tscn +++ b/scenes/monster.tscn @@ -1,8 +1,22 @@ -[gd_scene load_steps=3 format=3 uid="uid://cytaswycabcel"] +[gd_scene load_steps=5 format=3 uid="uid://cytaswycabcel"] [ext_resource type="Script" path="res://scripts/monster.gd" id="1_13xtk"] -[ext_resource type="Resource" uid="uid://ym438vedcdyl" path="res://resources/DebugMonster1.tres" id="2_rjclr"] +[ext_resource type="Material" uid="uid://ctul3e67rcq23" path="res://materials/CollisionDebugMaterial.tres" id="3_k6auu"] -[node name="Monster" type="Node3D"] +[sub_resource type="SphereShape3D" id="SphereShape3D_tjvna"] +radius = 0.4 + +[sub_resource type="SphereMesh" id="SphereMesh_aou7a"] +radius = 0.4 +height = 0.8 + +[node name="Monster" type="CharacterBody3D"] script = ExtResource("1_13xtk") -monster_stats = ExtResource("2_rjclr") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("SphereShape3D_tjvna") + +[node name="CollisionVisualizer" type="MeshInstance3D" parent="."] +mesh = SubResource("SphereMesh_aou7a") +skeleton = NodePath("") +surface_material_override/0 = ExtResource("3_k6auu") diff --git a/scenes/monster_spawnpoint.tscn b/scenes/monster_spawnpoint.tscn index 62100e4..9aac2da 100644 --- a/scenes/monster_spawnpoint.tscn +++ b/scenes/monster_spawnpoint.tscn @@ -1,8 +1,6 @@ -[gd_scene load_steps=6 format=3 uid="uid://dawpmu4vvv3rs"] +[gd_scene load_steps=4 format=3 uid="uid://dawpmu4vvv3rs"] [ext_resource type="Script" path="res://scripts/monster_spawnpoint.gd" id="1_eyon3"] -[ext_resource type="Script" path="res://resources/monster_stats.gd" id="2_u38vv"] -[ext_resource type="Resource" uid="uid://ym438vedcdyl" path="res://resources/DebugMonster1.tres" id="3_4axng"] [sub_resource type="SphereMesh" id="SphereMesh_phb77"] radius = 0.4 @@ -16,10 +14,17 @@ roughness = 0.25 [node name="MonsterSpawnpoint" type="Node3D"] script = ExtResource("1_eyon3") -spawnable_monsters = Array[ExtResource("2_u38vv")]([ExtResource("3_4axng")]) [node name="Diamond" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) mesh = SubResource("SphereMesh_phb77") surface_material_override/0 = SubResource("StandardMaterial3D_kvc2a") [node name="VisibleOnScreenNotifier3D" type="VisibleOnScreenNotifier3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0) + +[node name="Label3D" type="Label3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 0) +billboard = 1 +text = "0 / 5" +font_size = 64 diff --git a/scripts/inventory.gd b/scripts/inventory.gd new file mode 100644 index 0000000..b732637 --- /dev/null +++ b/scripts/inventory.gd @@ -0,0 +1,13 @@ +extends Control + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + Inventory.connect("inventory_changed", update_inventory) + pass # Replace with function body. + +func update_inventory() -> void: + var m = Inventory.monsters[0] + var string = "%s Lvl %s, %s/%s" % [m.name, m.level, m.health, m.max_health] + $MonsterList/Monster1.text = string + print("Updating inventory") diff --git a/scripts/monster.gd b/scripts/monster.gd index d3a45da..737d622 100644 --- a/scripts/monster.gd +++ b/scripts/monster.gd @@ -1,13 +1,53 @@ class_name Monster -extends Node3D +extends CharacterBody3D -@export var monster_stats: MonsterStats +@export var stats: MonsterStats + +var spawn_point: Vector3 = Vector3(0, 0, 0) + +# DEBUG MOVEMENT +@onready var time: float = 16.0 +@onready var frequency: float = 1.0 +@onready var amplitude: float = 0.5 + +var in_battle: bool = false # Called when the node enters the scene tree for the first time. func _ready() -> void: - var model_instance = monster_stats.model.instantiate() + var model_instance = stats.model.instantiate() + frequency = randf_range(1.0, 4.0) + amplitude = randf_range(1.0, 6.0) + spawn_point = position add_child(model_instance) -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: - pass +func _physics_process(delta: float) -> void: + if in_battle: + velocity = Vector3.ZERO + return + + time += delta + var x_movement = sin(time * frequency) * amplitude + var z_movement = cos(time * frequency) * amplitude + velocity = Vector3(x_movement, 0, z_movement) + + # if move_and_slide reports collisions + if move_and_slide(): + var collision = get_slide_collision(0) + var collider = collision.get_collider() + + # if the monster collided with the player... + if collider.name == "Player": + velocity = Vector3.ZERO + in_battle = true + + # calculate players new position + # from the camera 3 units backwards + var camera = collider.find_child("Camera3D") + + # local z axis of the camera + var local_z = camera.global_transform.basis.z + + var new_player_position = camera.global_transform.origin + local_z * 3 + + print(camera.global_transform.origin, new_player_position) + collider.start_battle(new_player_position) diff --git a/scripts/monster_spawnpoint.gd b/scripts/monster_spawnpoint.gd index 168dc2a..f29e2b9 100644 --- a/scripts/monster_spawnpoint.gd +++ b/scripts/monster_spawnpoint.gd @@ -1,32 +1,40 @@ class_name MonsterSpawnpoint extends Node3D -# a spawnpoint that can spawn monsters around the center point -# with a given distance +@onready var monster_tscn = preload("res://scenes/monster.tscn") + +# a spawnpoint that can spawn monsters # monsters are only spawned, if the player is not looking -@onready var spawn_timer: Timer = Timer.new() - # list that holds all spawnable monsters -@export var spawnable_monsters: Array[PackedScene] +@export var spawnable_monsters: Array[MonsterStats] + +# ignore spawning only if visible +@export var ignore_visibility: bool = false # the maximum amount of spawned monsters # no monsters will spawn, when this number is reached @export var max_monsters: int = 5 -# the maximum distance a monster can spawn around the spawnpoint -@export var max_distance_spawn: float = 10.0 - # the maximum lifetime a monster can be in the world # a monster is then deleted if the following conditions are met: # the monster has exceeded its maximum lifetime and it is not on screen # TODO: figure out how to check for the exceeded lifetime and delete @export var max_lifetime: float = 60.0 # seconds +# only spawn a monster every x seconds @export var spawn_cooldown: float = 3.0 # seconds +@onready var spawn_timer: Timer = Timer.new() +@onready var time: float = 16.0 +@onready var frequency: float = 1.0 +@onready var amplitude: float = 0.5 +@onready var spawn_point: Vector3 = Vector3(0, 0, 0) + +@onready var label: Label3D = $Label3D + # a spawnpoint should keep track of spawned entities -#var active_monsters: Array[Monster] = [] +var active_monsters: Array[Monster] = [] # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -35,31 +43,40 @@ func _ready() -> void: spawn_timer.timeout.connect(spawn) add_child(spawn_timer) spawn_timer.start() + + spawn_point = position func spawn() -> void: - if $VisibleOnScreenNotifier3D.is_on_screen(): + if len(active_monsters) >= max_monsters: + print("Spawnpoint reached maximum amount of monsters") + return + + if ignore_visibility == false and $VisibleOnScreenNotifier3D.is_on_screen(): print("Spawnpoint is visible on screen. Not spawning a monster.") return # TODO: Add a check to not spawn enemies X units near the player - - # get a random position near the spawn point - var spawn_point_x = randf_range(-max_distance_spawn, max_distance_spawn) - var spawn_point_z = randf_range(-max_distance_spawn, max_distance_spawn) # instantiate a monster .tscn scene - var monster_to_spawn = spawnable_monsters[0].instantiate() + var monster_to_spawn = monster_tscn.instantiate() + monster_to_spawn.stats = spawnable_monsters[0] + + # keep track of the current monster + active_monsters.append(monster_to_spawn) + label.text = "%s / %s" % [len(active_monsters), max_monsters] # calculate the position of the monster and add the offset of the spawnpoint itself - var monster_position = Vector3(spawn_point_x, 0.2, spawn_point_z) - monster_to_spawn.position = monster_position + position + var monster_position = Vector3(position.x, position.y + 1, position.z) + monster_to_spawn.position = monster_position - var debug_level_node = get_node("/root/Main/CurrentLevel/DebugLevel") + var debug_level_node = get_parent_node_3d() debug_level_node.add_child(monster_to_spawn) - print("spawning mob") + print("Spawning Mob \"%s\"" % monster_to_spawn.stats.name) # Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: - var time = Time.get_ticks_msec() - $Diamond.rotation.y = sin(time / 800.0) * 2 - $Diamond.position.y = 1.5 + sin(time / 800.0) * 0.3 + time += delta + var diamond_rotation: float = sin(time * frequency) * amplitude + var diamond_height: float = sin(time * frequency) * amplitude + $Diamond.rotation.y = diamond_rotation + $Diamond.position.y = 2.0 + diamond_height diff --git a/scripts/player.gd b/scripts/player.gd index 7106c04..2d80947 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -4,13 +4,6 @@ extends CharacterBody3D const SPEED = 5.0 const JUMP_VELOCITY = 4.5 - -func _ready() -> void: - pass - -func _process(delta: float) -> void: - #$CameraRoot.rotation.y += 0.005 - pass func _physics_process(delta: float) -> void: animated_mesh.idle() @@ -62,3 +55,12 @@ func _physics_process(delta: float) -> void: if velocity.length() < 0.01: animated_mesh.idle() + +# what happens when a battle starts? +# the player is positioned (mostly elsewhere than where he currently stands) +# ui changes +# music changes +func start_battle(player_position: Vector3) -> void: + position = Vector3(player_position.x, position.y, player_position.z) + print("düdelüdelüdelüdelü") + print("start battle")