Implemented humanoid

This commit is contained in:
Juicy 2021-05-19 16:22:05 +02:00
commit 203e91cdab
47 changed files with 2063 additions and 0 deletions

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
MIT License Copyright (c) 2021 Leon Rauschenberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# RPGH_Engine
A basic Godot framework to build my own little rpg horror games. \o/

BIN
assets/fonts/brass_mono.otf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/template_body_sheet.png-c516a7a78afb421474e2f96badc864d7.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/assets/graphics/template_body_sheet.png"
dest_files=[ "res://.import/template_body_sheet.png-c516a7a78afb421474e2f96badc864d7.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/template_head_sheet.png-ccffc3ebe8cf379534d68b508e65b991.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/assets/graphics/template_head_sheet.png"
dest_files=[ "res://.import/template_head_sheet.png-ccffc3ebe8cf379534d68b508e65b991.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/template_humanoid.png-efa89c12906092cd739cf9f69dbb6647.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/assets/graphics/template_humanoid.png"
dest_files=[ "res://.import/template_humanoid.png-efa89c12906092cd739cf9f69dbb6647.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

View File

@ -0,0 +1,60 @@
class_name RPGH_DataManager
extends Node
var current_map = null
var game_version: String
var _game_data = "user://save.json"
var default_data = {
"options": {
"music_volume": 0.5
}
}
var global_data = {}
func _ready():
game_version = ProjectSettings.get_setting("application/config/version")
load_from_file()
print(game_version)
func write_in_dictionary(key, value):
global_data[key] = value
func save_to_file():
var f = File.new()
f.open(_game_data, File.WRITE)
f.store_line(to_json(global_data))
f.close()
func load_from_file():
var f = File.new()
if !f.file_exists(_game_data):
default_data()
return
if f.open(_game_data, File.READ) != OK:
f.close()
return
var text := JSON.parse(f.get_as_text())
if text.result == null:
default_data()
push_error("Can't parse JSON, Save File is corrupted")
return
else:
return
f.close()
global_data = text.result
func default_data():
global_data = default_data
func _on_Button_button_down():
save_to_file()

View File

@ -0,0 +1,44 @@
extends RPGH_DataManager
# Just keeps a value that is stored over multiple
# maps and sessions.
var value setget _set_value, _get_value
var _key = ""
var _value = null
var map_key = ""
var event_key = ""
var _initial_value = null
var data
func _init(key: String, initial_value = null, map = null, event = null):
data = RPGH.get_node("DataManager").global_data
_initial_value = initial_value
if map != null:
yield(map, "ready")
map_key = map.name + "_"
if event != null:
event_key = event.name + "_"
_key = map_key + event_key + key
_value = initial_value
if !data.has(_key):
RPGH.get_node("DataManager").write_in_dictionary(_key, initial_value)
return
else:
return
func _set_value(new_value):
_value = new_value
if new_value == _initial_value:
data.erase(_key)
else:
RPGH.get_node("DataManager").write_in_dictionary(_key, _value)
func _get_value():
return _value

200
ingame/camera/camera.gd Normal file
View File

@ -0,0 +1,200 @@
extends Camera2D
var _previous_observee_position: Vector2
var _previous_camera_setup := CameraSetup.new()
var _target_camera_setup := CameraSetup.new() # This one is used if only one ist set.
var _fade_over_start_timestamp = 0.0
var _fade_over_duration = 0.0
var _fade_over_smooth = false
onready var IngameDisplay = get_node("../../../Display")
func _process(_delta):
# if not _previous_observee_position == RPGH.Camera._get_definite_position():
# _previous_observee_position = RPGH.Camera._get_definite_position()
# _update_camera_position()
# elif RPGH.Camera._is_zoom_invalid:
# _update_camera_position()
# RPGH.Camera._is_zoom_invalid = false
_update_camera_position()
func set_camera_setup(camera_setup):
_target_camera_setup = camera_setup
_fade_over_duration = 0.0
func fade_over_camera_setup(camera_setup, duration, smooth = false):
_previous_camera_setup = _target_camera_setup
_target_camera_setup = camera_setup
_fade_over_start_timestamp = OS.get_ticks_msec() * 0.001
_fade_over_duration = duration
_fade_over_smooth = smooth
func _get_definite_position():
var previous_position = _previous_camera_setup.position
var target_position = _target_camera_setup.position
var ratio = _get_ratio_over_time()
return previous_position.linear_interpolate(target_position, ratio)
func _get_definite_zoom():
var previous_zoom = _previous_camera_setup.zoom
var target_zoom = _target_camera_setup.zoom
var ratio = _get_ratio_over_time()
return lerp(previous_zoom, target_zoom, ratio)
func _get_ratio_over_time():
var current_timestamp = OS.get_ticks_msec() * 0.001
var passed_time = current_timestamp - _fade_over_start_timestamp
var ratio
if _fade_over_duration > 0.0:
ratio = clamp(passed_time / _fade_over_duration, 0.0, 1.0)
else:
ratio = 1.0
if _fade_over_smooth:
if ratio <= 0.5:
ratio = pow(ratio * 2.0, 3.0) * 0.5
else:
ratio = 1.0 - ratio
ratio = pow(ratio * 2.0, 3.0) * 0.5
ratio = 1.0 - ratio
return ratio
func _update_camera_position():
var definite_position = _get_definite_position()
var definite_zoom = _get_definite_zoom()
var whole_definite_position = Vector2(floor(definite_position.x), floor(definite_position.y))
var decimal_part = definite_position - whole_definite_position
var zoomed_decimal_part = decimal_part * -1.6 * definite_zoom
position = whole_definite_position
IngameDisplay.get_material().set_shader_param("offset", zoomed_decimal_part)
IngameDisplay.get_material().set_shader_param("zoom", definite_zoom)
force_update_scroll()
class CameraSetup:
var observee: Node2D = null setget ,_get_observee
var pixel_perfect = false setget ,_get_pixel_perfect # Forced if observee is player.
var position = Vector2() setget ,_get_position
var zoom := 1.0 setget _set_zoom, _get_zoom
var limit_left := -INF
var limit_right := INF
var limit_top := -INF
var limit_bottom := INF
var _previous_observee_position
var _is_zoom_invalid = false
var _cached_position = Vector2()
var _cached_zoom
# warning-ignore:shadowed_variable
# warning-ignore:shadowed_variable
func _calculate_and_cache_position_and_zoom(position, zoom):
var zoomed_screen_size = RPGH.DEFAULT_SCREEN_SIZE * zoom
var half_zoomed_screen_size = zoomed_screen_size * 0.5
var horizontal_border_alignment = _align_and_squish_borders(
position.x, half_zoomed_screen_size.x, limit_left, limit_right
)
_cached_position.x = horizontal_border_alignment[0]
var left_border = horizontal_border_alignment[1]
var right_border = horizontal_border_alignment[2]
var horizontal_size = right_border - left_border
var horizontal_zoom = RPGH.DEFAULT_SCREEN_SIZE.x / horizontal_size
var vertical_border_alignment = _align_and_squish_borders(
position.y, half_zoomed_screen_size.y, limit_top, limit_bottom
)
_cached_position.y = vertical_border_alignment[0]
var top_border = vertical_border_alignment[1]
var bottom_border = vertical_border_alignment[2]
var vertical_size = bottom_border - top_border
var vertical_zoom = RPGH.DEFAULT_SCREEN_SIZE.y / vertical_size
if _get_pixel_perfect():
_cached_position = Vector2(floor(_cached_position.x), floor(_cached_position.y))
_cached_zoom = min(horizontal_zoom, vertical_zoom)
func _align_and_squish_borders(current_position, expansion, limit_negative, limit_positive):
#var current_position = position
var left_border = current_position - expansion
var right_border = current_position + expansion
if limit_negative > left_border:
current_position += limit_negative - left_border
left_border = limit_negative
right_border = current_position + expansion
if limit_positive < right_border:
right_border = limit_positive
current_position = (left_border + right_border) * 0.5
elif limit_positive < right_border:
current_position += limit_positive - right_border
right_border = limit_positive
left_border = current_position - expansion
if limit_negative > left_border:
left_border = limit_negative
current_position = (left_border + right_border) * 0.5
return [current_position, left_border, right_border]
func _get_observee():
if not is_instance_valid(observee):
observee = null
if observee == null:
if RPGH.Player._player_exists:
return RPGH.Player.CameraFocus
else:
return RPGH.Player.CameraFocus # CHANGE THIS PLEASE. #later# CHANGE TO WHAT?!
else:
return observee
func _get_pixel_perfect():
if observee == null:
return true
else:
return pixel_perfect
func _get_position():
var observee_position = _get_observee().global_position
var is_position_invalid = not observee_position == _previous_observee_position
if is_position_invalid or _is_zoom_invalid:
_previous_observee_position = observee_position
_is_zoom_invalid = false
_calculate_and_cache_position_and_zoom(observee_position, zoom)
return _cached_position
func _set_zoom(value):
zoom = value
_is_zoom_invalid = true
RPGH.Camera.IngameDisplay.get_material().set_shader_param("zoom", zoom)
func _get_zoom():
var observee_position = _get_observee().global_position
var is_position_invalid = not observee_position == _previous_observee_position
if is_position_invalid or _is_zoom_invalid:
_previous_observee_position = observee_position
_is_zoom_invalid = false
_calculate_and_cache_position_and_zoom(observee_position, zoom)
return _cached_zoom

Binary file not shown.

View File

@ -0,0 +1,125 @@
extends Node
enum ViewDirection {
UP = 0,
UP_RIGHT = 1,
RIGHT = 2,
DOWN_RIGHT = 3,
DOWN = 4,
DOWN_LEFT = 5,
LEFT = 6,
UP_LEFT = 7
}
signal texture_position_updated(new_position)
signal tile_reached()
signal frame_pushed(frame_coord)
const SPEED = 100.0
const STEP = 8.0
const FRAMES_PER_SECOND = 8.0
var view_direction = ViewDirection.DOWN
var body_direction = Vector2.DOWN
var speed_multiplier = 1.0
# For movement.
var _previous_position
var _target_position
var _in_walk_animation = false
var _walk_interpolation_ratio = 0.0
# For sheet animation.
var _in_idle_frame = true
var _frame_timer = 0.0
var _previous_frame_timer = 0.0
var _next_initial_frame_timer = 0.0
var _frame_coords
var _previous_frame_coords
func _process(delta):
_handle_walk_animation(delta)
_handle_sprite_sheet_animation(delta)
func start_walk_animation(destination: Vector2):
_previous_position = _target_position
_target_position = destination
_in_walk_animation = true
_in_idle_frame = false
func stop_walk_animation():
_walk_interpolation_ratio = 0.0
_in_walk_animation = false
emit_signal("texture_position_updated", _target_position)
func set_position(new_position):
_previous_position = new_position
_target_position = new_position
emit_signal("texture_position_updated", _target_position)
func is_in_walk_animation():
return _in_walk_animation
func _handle_walk_animation(delta):
if _in_walk_animation:
_walk_interpolation_ratio += SPEED * speed_multiplier / STEP * delta
if _walk_interpolation_ratio >= 1.0:
_walk_interpolation_ratio -= 1.0
emit_signal("tile_reached")
else:
var next_position = _previous_position.linear_interpolate(
_target_position, _walk_interpolation_ratio)
emit_signal("texture_position_updated", next_position)
func _handle_sprite_sheet_animation(delta):
_frame_coords = Vector2.ZERO
if _in_walk_animation:
if _in_idle_frame:
_in_idle_frame = false
_frame_timer = _next_initial_frame_timer
_frame_coords.x = floor(_get_wraped_frame_timer(delta) + 1.0)
else:
if _in_idle_frame:
_frame_coords.x = 0.0
else:
_handle_after_walk_animation(delta)
_frame_coords.y = view_direction
if _frame_coords != _previous_frame_coords:
emit_signal("frame_pushed", _frame_coords)
# The humanoid is supposed to finish its walking animation,
# even if it already reached a whole tile.
func _handle_after_walk_animation(delta):
var wraped_previous_frame_timer = wrapf(_previous_frame_timer, 0.0, 4.0)
var wraped_frame_timer = _get_wraped_frame_timer(delta)
_next_initial_frame_timer = floor(wraped_frame_timer * 0.5) * 2.0
var walk_animation_frame = floor(wraped_frame_timer) + 1.0
var wraped_2 = wrapf(wraped_frame_timer, 1.0, 3.0) - 1.0
var previous_wraped_2 = wrapf(wraped_previous_frame_timer, 1.0, 3.0) - 1.0
if previous_wraped_2 > wraped_2:
_in_idle_frame = true
_frame_coords.x = 0.0
else:
_frame_coords.x = walk_animation_frame
func _get_wraped_frame_timer(delta):
_previous_frame_timer = _frame_timer
_frame_timer += delta * FRAMES_PER_SECOND
return wrapf(_frame_timer, 0.0, 4.0)

View File

@ -0,0 +1,73 @@
class_name RPGH_Humanoid
extends YSort
const DIAGONAL_SPEED_MULTIPLIER = 0.8
const STEP = 8.0
onready var Texture = get_node("Texture")
onready var AnimationHandler = get_node("Texture/AnimationHandler")
onready var CameraFocus = get_node("Texture/CameraFocus")
onready var Body = get_node("Body")
onready var view_direction_map = {
Vector2(0.0, -1.0) : AnimationHandler.ViewDirection.UP,
Vector2(1.0, -1.0) : AnimationHandler.ViewDirection.UP_RIGHT,
Vector2(1.0, 0.0) : AnimationHandler.ViewDirection.RIGHT,
Vector2(1.0, 1.0) : AnimationHandler.ViewDirection.DOWN_RIGHT,
Vector2(0.0, 1.0) : AnimationHandler.ViewDirection.DOWN,
Vector2(-1.0, 1.0) : AnimationHandler.ViewDirection.DOWN_LEFT,
Vector2(-1.0, 0.0) : AnimationHandler.ViewDirection.LEFT,
Vector2(-1.0, -1.0) : AnimationHandler.ViewDirection.UP_LEFT
}
# Called when the node enters the scene tree for the first time.
func _ready():
_check_if_on_tile()
AnimationHandler.set_position(Body.position)
# Returns true if the humanoid is moved.
func move(direction: Vector2) -> bool:
var direction_test_list = [ Vector2(direction.x, direction.y),
# Default direction, rotated 45 degrees to the left.
Vector2(
clamp(direction.x + direction.y, -1.0, 1.0),
clamp(direction.y - direction.x, -1.0, 1.0)),
# Default direction, rotated 45 degrees to the right.
Vector2(
clamp(direction.x - direction.y, -1.0, 1.0),
clamp(direction.y + direction.x, -1.0, 1.0)) ]
# Already setting a few variables in case no test is successful.
AnimationHandler.speed_multiplier = DIAGONAL_SPEED_MULTIPLIER
if direction.x == 0 or direction.y == 0:
AnimationHandler.speed_multiplier = 1.0
var was_humanoid_moved = false
for direction_test in direction_test_list:
var step_to_destination = direction_test * STEP
if !Body.test_move(Body.global_transform, step_to_destination):
AnimationHandler.view_direction = view_direction_map[direction_test]
AnimationHandler.speed_multiplier = DIAGONAL_SPEED_MULTIPLIER
if direction_test.x == 0 or direction_test.y == 0:
AnimationHandler.speed_multiplier = 1.0
# Finally actually moving the body.
Body.position += step_to_destination
AnimationHandler.start_walk_animation(Body.position)
was_humanoid_moved = true
break
return was_humanoid_moved
# Checking if humanoid is positioned on a tile.
func _check_if_on_tile():
var on_tile = true
if not wrapf(position.x, 0.0, 8.0) == 0.0:
position.x = round(position.x / 8.0) * 8.0
on_tile = false
if not wrapf(position.y, 0.0, 8.0) == 0.0:
position.y = round(position.y / 8.0) * 8.0
on_tile = false
if not on_tile:
push_warning("The humanoid was not exactly position on a tile! Please fix this.")

View File

@ -0,0 +1,32 @@
[gd_scene load_steps=5 format=2]
[ext_resource path="res://addons/rpgh_engine/ingame/humanoid/humanoid.gd" type="Script" id=1]
[ext_resource path="res://addons/rpgh_engine/assets/graphics/template_humanoid.png" type="Texture" id=2]
[ext_resource path="res://addons/rpgh_engine/ingame/humanoid/animation_handler.gd" type="Script" id=3]
[sub_resource type="RectangleShape2D" id=1]
[node name="Humanoid" type="YSort"]
script = ExtResource( 1 )
[node name="Texture" type="Sprite" parent="."]
texture = ExtResource( 2 )
centered = false
offset = Vector2( 0, -14 )
hframes = 15
vframes = 8
frame = 60
[node name="AnimationHandler" type="Node" parent="Texture"]
script = ExtResource( 3 )
[node name="CameraFocus" type="Position2D" parent="Texture"]
position = Vector2( 12, 8 )
[node name="Body" type="KinematicBody2D" parent="."]
collision_layer = 0
collision_mask = 2
[node name="Collision" type="CollisionShape2D" parent="Body"]
position = Vector2( 12, 12 )
shape = SubResource( 1 )

112
ingame/player/player.gd Normal file
View File

@ -0,0 +1,112 @@
extends RPGH_Humanoid
enum Direction {
UP = -1,
LEFT = -1
NONE = 0,
RIGHT = 1,
DOWN = 1
}
# Input variables.
var input_x_axis = Direction.NONE
var input_y_axis = Direction.NONE
var input_interact = false
var _player_exists = false
var _player_movement_disabled := false
var _player_interact_disabled := false
var _await_interaction = false
onready var InteractableAntenna = get_node("Body/InteractableAntenna")
func spawn(position: Vector2):
Body.position = position
AnimationHandler.set_position(Body.position)
self.Texture.position = position
self.Texture.visible = true
_player_exists = true
func despawn():
self.Texture.visible = false
_player_exists = false
# Called when the node enters the scene tree for the first time.
func _ready():
AnimationHandler.connect(
"texture_position_updated", self, "_on_texture_position_updated")
AnimationHandler.connect(
"tile_reached", self, "_on_tile_reached")
AnimationHandler.connect(
"frame_pushed", self, "_on_frame_pushed")
func _physics_process(_delta):
_check_input()
if !AnimationHandler.is_in_walk_animation():
if not _get_axis_input_vector() == Vector2.ZERO:
InteractableAntenna.position = _get_axis_input_vector() * STEP * 2.0
_move_player()
if input_interact:
if AnimationHandler.is_in_walk_animation():
yield(AnimationHandler, "tile_reached")
for i in InteractableAntenna.get_overlapping_areas():
i.trigger()
for i in InteractableAntenna.get_overlapping_bodies():
i.trigger()
_await_interaction = false
# Sets local axis input variables.
func _check_input():
if not RPGH.Player._player_movement_disabled:
# Handle input_x_axis
if (Input.is_action_pressed("ingame_left") || Input.is_action_pressed("ingame_right")):
if (Input.is_action_just_pressed("ingame_left")): input_x_axis = Direction.LEFT
if (Input.is_action_just_pressed("ingame_right")): input_x_axis = Direction.RIGHT
else: input_x_axis = Direction.NONE
if (Input.is_action_just_released("ingame_left") && Input.is_action_pressed("ingame_right")): input_x_axis = Direction.RIGHT
if (Input.is_action_just_released("ingame_right") && Input.is_action_pressed("ingame_left")): input_x_axis = Direction.LEFT
# Handle input_y_axis
if (Input.is_action_pressed("ingame_up") || Input.is_action_pressed("ingame_down")):
if (Input.is_action_just_pressed("ingame_up")): input_y_axis = Direction.UP
if (Input.is_action_just_pressed("ingame_down")): input_y_axis = Direction.DOWN
else: input_y_axis = Direction.NONE
if (Input.is_action_just_released("ingame_up") && Input.is_action_pressed("ingame_down")): input_y_axis = Direction.DOWN
if (Input.is_action_just_released("ingame_down") && Input.is_action_pressed("ingame_up")): input_y_axis = Direction.UP
else:
input_x_axis = Direction.NONE
input_y_axis = Direction.NONE
if not RPGH.Player._player_interact_disabled:
input_interact = Input.is_action_just_pressed("ingame_interact")
else:
input_interact = false
func _move_player() -> bool:
var was_player_moved = not (input_x_axis == 0.0 and input_y_axis == 0.0)
if was_player_moved:
was_player_moved = move(_get_axis_input_vector())
return was_player_moved
func _get_axis_input_vector() -> Vector2:
return Vector2(input_x_axis, input_y_axis)
func _on_texture_position_updated(new_position):
self.Texture.position = new_position
func _on_tile_reached():
if !_move_player():
AnimationHandler.stop_walk_animation()
func _on_frame_pushed(frame_coords):
self.Texture.frame_coords = frame_coords

18
ingame/player/player.tscn Normal file
View File

@ -0,0 +1,18 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/rpgh_engine/ingame/humanoid/humanoid.tscn" type="PackedScene" id=1]
[ext_resource path="res://addons/rpgh_engine/ingame/player/player.gd" type="Script" id=2]
[sub_resource type="RectangleShape2D" id=1]
[node name="Player" instance=ExtResource( 1 )]
script = ExtResource( 2 )
[node name="InteractableAntenna" type="Area2D" parent="Body" index="1"]
monitorable = false
collision_layer = 0
collision_mask = 4
[node name="Collision" type="CollisionShape2D" parent="Body/InteractableAntenna" index="0"]
position = Vector2( 12, 12 )
shape = SubResource( 1 )

113
nodes/event/event.gd Normal file
View File

@ -0,0 +1,113 @@
class_name RPGH_Event, "res://addons/rpgh_engine/nodes/event/icon_event.svg"
extends Node
# This is the main class for interacting with the RPGH Engine's
# core system. Adds behaviour to the game.
signal triggered
export(bool) var auto_start = false
export(bool) var block_player = true
var map: RPGH_Map = RPGH.get_node("DataManager").current_map
var state setget _set_state, _get_state
var _state := Storable("State")
var _is_first_run := Storable("IsFirstRun", true)
func _ready():
if auto_start:
_run()
func is_first_run() -> bool:
return _is_first_run.value
# This function currently simply plays the event without further
# preparations or clean up. So that the event can be called
# within another one.
#
# TODO: automate this somehow please :pray:
func append():
var filtered_state_value = "default" if _state.value == null else _state.value
var func_state = call(filtered_state_value)
if func_state is GDScriptFunctionState:
yield(func_state, "completed")
_is_first_run.value = false
# --- INGAME_CAMERA -----------------------------------------------------------
func set_camera_setup(camera_setup):
RPGH.Camera.set_camera_setup(camera_setup)
func fade_over_camera_setup(camera_setup, duration, smooth = false):
RPGH.Camera.fade_over_camera_setup(camera_setup, duration, smooth)
func CameraSetup():
return RPGH.Camera.CameraSetup.new()
# --- UI_DIALOG ---------------------------------------------------------------
func textbox(id: String, left_bust: Texture = null, right_bust: Texture = null):
RPGH.Dialog.textbox(id, left_bust, right_bust)
func screen_text(id: String):
RPGH.Dialog.screen_text(id)
func close_textbox():
var func_state = RPGH.Dialog.close_textbox()
if func_state is GDScriptFunctionState:
yield(func_state, "completed")
if !block_player:
_enable_character_movement()
# -----------------------------------------------------------------------------
func _run():
emit_signal("triggered")
if block_player:
RPGH.Player._player_movement_disabled = true
RPGH.Player._player_interact_disabled = true
var filtered_state_value = "default" if _state.value == null else _state.value
var func_state = call(filtered_state_value)
if func_state is GDScriptFunctionState:
yield(func_state, "completed")
close_textbox()
_is_first_run.value = false
_enable_character_movement()
func _enable_character_movement():
RPGH.Player._player_movement_disabled = false
yield(RPGH.get_tree(), "physics_frame")
yield(RPGH.get_tree(), "physics_frame")
RPGH.Player._player_interact_disabled = false
func _set_state(new_state):
if !new_state is String:
push_error("State can only be set to string.")
return
_state.value = new_state
func _get_state():
return _state.value
# Just a fast wrapper for "storable.gd".
class RPGH_Storable:
extends "res://addons/rpgh_engine/data_management/storable.gd"
func _init(key: String, value = null, map = null, event = null).(key, value, map, event): pass
func Storable(key: String, value = null) -> RPGH_Storable:
return RPGH_Storable.new(name + key, value, map, self)

View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6-6 6 6 0 0 0 -6-6zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4z" fill="#cf7a9c"/></svg>

After

Width:  |  Height:  |  Size: 243 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_event.svg-5b91700846557ab2e64806fd3a2f8e31.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/nodes/event/icon_event.svg"
dest_files=[ "res://.import/icon_event.svg-5b91700846557ab2e64806fd3a2f8e31.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

1
nodes/map/icon_map.svg Normal file
View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm-12 3v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2zm3 0v2h2v-2z" fill="#cf7a9c"/></svg>

After

Width:  |  Height:  |  Size: 425 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_map.svg-43ff95cf50e4e38847d7dade7944c61f.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/nodes/map/icon_map.svg"
dest_files=[ "res://.import/icon_map.svg-43ff95cf50e4e38847d7dade7944c61f.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

52
nodes/map/map.gd Normal file
View File

@ -0,0 +1,52 @@
tool
class_name RPGH_Map, "res://addons/rpgh_engine/nodes/map/icon_map.svg"
extends YSort
export(Texture) var top_layer: Texture setget _set_top_layer
export(Texture) var bottom_layer: Texture setget _set_bottom_layer
func _init():
if !Engine.editor_hint:
RPGH.get_node("DataManager").current_map = self
func _ready():
if !Engine.editor_hint:
var top_layer_sprite = Sprite.new()
top_layer_sprite.name = "\\TopLayer"
top_layer_sprite.texture = top_layer
top_layer_sprite.centered = false
top_layer_sprite.z_index = 1
add_child(top_layer_sprite)
var bottom_layer_sprite = Sprite.new()
bottom_layer_sprite.name = "\\BottomLayer"
bottom_layer_sprite.texture = bottom_layer
bottom_layer_sprite.centered = false
bottom_layer_sprite.z_index = -1
add_child(bottom_layer_sprite)
func _draw():
if Engine.editor_hint:
draw_texture(bottom_layer, Vector2())
draw_texture(top_layer, Vector2())
func _set_top_layer(new_top_layer):
top_layer = new_top_layer
update()
func _set_bottom_layer(new_bottom_layer):
bottom_layer = new_bottom_layer
update()
# Just a fast wrapper for "storable.gd".
class RPGH_Storable:
extends "res://addons/rpgh_engine/data_management/storable.gd"
func _init(key: String, value = null, map = null, event = null).(key, value, map, event): pass
func Storable(key: String, value = null) -> RPGH_Storable:
return RPGH_Storable.new(key, value, self)

6
nodes/map/map.tscn Normal file
View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/rpgh_engine/nodes/map/map.gd" type="Script" id=1]
[node name="Map" type="YSort"]
script = ExtResource( 1 )

View File

@ -0,0 +1,19 @@
tool
extends Node2D
var _TEXTURE
func _init():
if Engine.editor_hint:
_TEXTURE = load("res://addons/rpgh_engine/nodes/spawn_marker/spawn_marker.png")
func _ready():
if !Engine.editor_hint:
RPGH.Player.spawn(position)
func _draw():
if Engine.editor_hint:
draw_texture(_TEXTURE, Vector2(0.0, -12.0))

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/spawn_marker.png-d45b8788eb0da07408f13bd5984ebbe4.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/nodes/spawn_marker/spawn_marker.png"
dest_files=[ "res://.import/spawn_marker.png-d45b8788eb0da07408f13bd5984ebbe4.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/rpgh_engine/nodes/spawn_marker/spawn_marker.gd" type="Script" id=1]
[node name="SpawnMarker" type="Node2D"]
script = ExtResource( 1 )

View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m3 1c-1.1046 0-2 .89543-2 2v10c0 1.1046.89543 2 2 2h10c1.1046 0 2-.89543 2-2v-10c0-1.1046-.89543-2-2-2zm4 2h2v6h-2zm0 8h2v2h-2z" fill="#cf7a9c"/></svg>

After

Width:  |  Height:  |  Size: 244 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/icon_trigger.svg-f9c620bf9d15462f19689f0412c9b2e4.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/nodes/trigger/icon_trigger.svg"
dest_files=[ "res://.import/icon_trigger.svg-f9c620bf9d15462f19689f0412c9b2e4.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/rpgh_engine/nodes/trigger/trigger_collision_object.gd" type="Script" id=1]
[node name="PassableTrigger" type="Area2D"]
collision_layer = 4
collision_mask = 0
script = ExtResource( 1 )

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/rpgh_engine/Nodes/Trigger/trigger_collision_object.gd" type="Script" id=1]
[node name="SolidTrigger" type="KinematicBody2D"]
collision_layer = 4
collision_mask = 0
script = ExtResource( 1 )

31
nodes/trigger/trigger.gd Normal file
View File

@ -0,0 +1,31 @@
class_name RPGH_Trigger, "res://addons/rpgh_engine/nodes/trigger/icon_trigger.svg"
extends Node
enum TriggerType {
ON_INTERACT,
ON_TOUCH,
}
export(NodePath) var event = @".."
# Both not functioning yet!
export(TriggerType) var trigger_type = TriggerType.ON_INTERACT
export(bool) var is_passable = false
onready var passable_trigger = preload("res://addons/rpgh_engine/nodes/trigger/passable_trigger.tscn")
onready var solid_trigger = preload("res://addons/rpgh_engine/nodes/trigger/solid_trigger.tscn")
func _ready():
var collision_object: CollisionObject2D
if is_passable:
collision_object = passable_trigger.instance()
else:
collision_object = solid_trigger.instance()
collision_object.set_collision_layer_bit(1, true)
collision_object.name = name
collision_object.event = get_node(event)
call_deferred("replace_by", collision_object, true)

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/rpgh_engine/nodes/trigger/trigger.gd" type="Script" id=1]
[node name="Trigger" type="Node2D"]
script = ExtResource( 1 )

View File

@ -0,0 +1,7 @@
extends Node2D
var event
func trigger():
event._run()

7
plugin.cfg Normal file
View File

@ -0,0 +1,7 @@
[plugin]
name = "RPGH Engine"
description = "A framework for rpg horror like games."
author = "Leon Rauschenberg"
version = "0.0.1"
script = "plugin.gd"

505
rpgh_engine.tscn Normal file
View File

@ -0,0 +1,505 @@
[gd_scene load_steps=22 format=2]
[ext_resource path="res://addons/rpgh_engine/data_management/data_manager.gd" type="Script" id=1]
[ext_resource path="res://addons/rpgh_engine/system/rpgh_engine.gd" type="Script" id=2]
[ext_resource path="res://addons/rpgh_engine/ingame/camera/ingame_display.material" type="Material" id=3]
[ext_resource path="res://addons/rpgh_engine/ingame/player/player.tscn" type="PackedScene" id=4]
[ext_resource path="res://addons/rpgh_engine/ui/textbox.gd" type="Script" id=5]
[ext_resource path="res://addons/rpgh_engine/ingame/camera/camera.gd" type="Script" id=6]
[ext_resource path="res://game/maps/hobby_room_corrupted/ako_shocked.png" type="Texture" id=7]
[ext_resource path="res://addons/rpgh_engine/ui/dialog.gd" type="Script" id=8]
[ext_resource path="res://addons/rpgh_engine/ui/pause.gd" type="Script" id=9]
[sub_resource type="ViewportTexture" id=1]
flags = 4
viewport_path = NodePath("Ingame/Viewport")
[sub_resource type="Animation" id=2]
resource_name = "DespawnBust"
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath(".:rect_position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( -50, 0 ), Vector2( -511.111, 0 ) ]
}
[sub_resource type="Animation" id=3]
resource_name = "SpawnBust"
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath(".:rect_position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( -511.111, 0 ), Vector2( -50, 0 ) ]
}
[sub_resource type="Animation" id=4]
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath(".:rect_position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 472, 0 ), Vector2( 936, 0 ) ]
}
[sub_resource type="Animation" id=5]
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath(".:rect_position")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Vector2( 936, 0 ), Vector2( 472, 0 ) ]
}
[sub_resource type="DynamicFontData" id=6]
font_path = "res://addons/rpgh_engine/assets/fonts/brass_mono.otf"
[sub_resource type="DynamicFont" id=7]
size = 36
font_data = SubResource( 6 )
[sub_resource type="Animation" id=8]
tracks/0/type = "value"
tracks/0/path = NodePath("../../Ingame/Viewport/CanvasModulate:color")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 0.254902, 0.254902, 0.254902, 1 ), Color( 1, 1, 1, 1 ) ]
}
[sub_resource type="Animation" id=9]
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("TextboxBackground:polygon")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ PoolVector2Array( 0, 440, 0, 600, 1024, 600, 1024, 408 ), PoolVector2Array( 0, 712, 0, 600, 1024, 936, 1024, 1200 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Textbox:percent_visible")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ 0.0 ]
}
[sub_resource type="Animation" id=10]
tracks/0/type = "value"
tracks/0/path = NodePath("Textbox:grow_vertical")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ 2 ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Textbox:fit_content_height")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ true ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("Textbox:margin_top")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ 0.0 ]
}
tracks/3/type = "value"
tracks/3/path = NodePath("Textbox:margin_bottom")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ 0.0 ]
}
tracks/4/type = "value"
tracks/4/path = NodePath("Textbox:anchor_top")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ 0.5 ]
}
tracks/5/type = "value"
tracks/5/path = NodePath("Textbox:anchor_bottom")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ 0.5 ]
}
tracks/6/type = "value"
tracks/6/path = NodePath("../../Ingame/Viewport/CanvasModulate:color")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 1, 1, 1, 1 ), Color( 0.254902, 0.254902, 0.254902, 1 ) ]
}
[sub_resource type="Animation" id=11]
length = 0.2
tracks/0/type = "value"
tracks/0/path = NodePath("TextboxBackground:polygon")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.2 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ PoolVector2Array( 0, 712, 0, 600, 1024, 936, 1024, 1200 ), PoolVector2Array( 0, 440, 0, 600, 1024, 600, 1024, 408 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("Textbox:anchor_top")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ 1.0 ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("Textbox:anchor_bottom")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 0,
"values": [ 1.0 ]
}
tracks/3/type = "value"
tracks/3/path = NodePath("Textbox:margin_top")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ -144.0 ]
}
tracks/4/type = "value"
tracks/4/path = NodePath("Textbox:margin_bottom")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = {
"times": PoolRealArray( 0 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ -16.0 ]
}
[sub_resource type="Animation" id=12]
length = 0.64
step = 0.01
tracks/0/type = "value"
tracks/0/path = NodePath("TextureRect:anchor_top")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 0.1, 0.55, 0.64 ),
"transitions": PoolRealArray( 1, 1, 1, 1 ),
"update": 0,
"values": [ 0.5, 0.0, 0.0, 0.5 ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("TextureRect:anchor_bottom")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 0.1, 0.55, 0.64 ),
"transitions": PoolRealArray( 1, 1, 1, 1 ),
"update": 0,
"values": [ 0.5, 1.0, 1.0, 0.5 ]
}
tracks/2/type = "value"
tracks/2/path = NodePath("TextureRect:rect_position")
tracks/2/interp = 2
tracks/2/loop_wrap = true
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/keys = {
"times": PoolRealArray( 0.1, 0.15, 0.21, 0.26, 0.31, 0.36, 0.41, 0.46, 0.5, 0.52 ),
"transitions": PoolRealArray( 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ),
"update": 0,
"values": [ Vector2( 0, 0 ), Vector2( -24, 8 ), Vector2( 8, -16 ), Vector2( 32, 16 ), Vector2( -16, -8 ), Vector2( -8, 16 ), Vector2( 16, -24 ), Vector2( -8, 8 ), Vector2( 8, 0 ), Vector2( 0, 0 ) ]
}
tracks/3/type = "value"
tracks/3/path = NodePath("TextureRect:margin_top")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/keys = {
"times": PoolRealArray( 0.54 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ 0.0 ]
}
tracks/4/type = "value"
tracks/4/path = NodePath("TextureRect:margin_bottom")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/keys = {
"times": PoolRealArray( 0.54 ),
"transitions": PoolRealArray( 1 ),
"update": 1,
"values": [ 6.10352e-05 ]
}
[node name="RPGH Engine" type="Node"]
script = ExtResource( 2 )
[node name="DataManager" type="Node" parent="."]
script = ExtResource( 1 )
[node name="Ingame" type="Node" parent="."]
[node name="Viewport" type="Viewport" parent="Ingame"]
size = Vector2( 640, 360 )
render_target_v_flip = true
[node name="CanvasModulate" type="CanvasModulate" parent="Ingame/Viewport"]
position = Vector2( 16, 456 )
z_index = -1
[node name="MapContainer" type="YSort" parent="Ingame/Viewport"]
__meta__ = {
"_editor_description_": "Test"
}
[node name="Player" parent="Ingame/Viewport/MapContainer" instance=ExtResource( 4 )]
[node name="Camera" type="Camera2D" parent="Ingame/Viewport/MapContainer"]
current = true
script = ExtResource( 6 )
[node name="Display" type="TextureRect" parent="Ingame"]
material = ExtResource( 3 )
anchor_right = 1.0
anchor_bottom = 1.0
margin_right = -0.00012207
rect_pivot_offset = Vector2( 512, 300 )
texture = SubResource( 1 )
expand = true
__meta__ = {
"_edit_use_anchors_": false,
"_editor_description_": ""
}
[node name="UI" type="Node" parent="."]
[node name="Dialog" type="Control" parent="UI"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 8 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LeftBust" type="TextureRect" parent="UI/Dialog"]
margin_left = 286.0
margin_right = 886.0
margin_bottom = 600.0
expand = true
stretch_mode = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/Dialog/LeftBust"]
anims/DespawnBust = SubResource( 2 )
anims/SpawnBust = SubResource( 3 )
[node name="RightBust" type="TextureRect" parent="UI/Dialog"]
margin_left = 472.0
margin_right = 1072.0
margin_bottom = 600.0
expand = true
stretch_mode = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/Dialog/RightBust"]
anims/DespawnBust = SubResource( 4 )
anims/SpawnBust = SubResource( 5 )
[node name="TextboxBackground" type="Polygon2D" parent="UI/Dialog"]
color = Color( 0.0627451, 0.0588235, 0.0627451, 0.721569 )
antialiased = true
polygon = PoolVector2Array( 0, 712, 0, 600, 1024, 936, 1024, 1200 )
[node name="Textbox" type="RichTextLabel" parent="UI/Dialog"]
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
margin_left = 16.0
margin_right = -16.0
grow_vertical = 2
custom_fonts/normal_font = SubResource( 7 )
bbcode_enabled = true
visible_characters = 0
percent_visible = 0.0
fit_content_height = true
scroll_active = false
script = ExtResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/Dialog"]
pause_mode = 2
anims/DespawnScreenText = SubResource( 8 )
anims/DespawnTextbox = SubResource( 9 )
anims/SpawnScreenText = SubResource( 10 )
anims/SpawnTextbox = SubResource( 11 )
[node name="Insertion" type="Control" parent="UI"]
anchor_right = 1.0
anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": false
}
[node name="TextureRect" type="TextureRect" parent="UI/Insertion"]
anchor_top = 0.5
anchor_right = 1.0
anchor_bottom = 0.5
margin_right = -0.000732422
margin_bottom = 6.10352e-05
texture = ExtResource( 7 )
expand = true
stretch_mode = 1
__meta__ = {
"_edit_use_anchors_": false
}
[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/Insertion"]
anims/FadeInInsertion = SubResource( 12 )
[node name="Button" type="Button" parent="UI"]
margin_left = 10.3942
margin_top = 11.3813
margin_right = 144.394
margin_bottom = 31.3813
text = "Save"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Pause" type="Popup" parent="UI"]
pause_mode = 2
margin_right = 40.0
margin_bottom = 40.0
script = ExtResource( 9 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Label" type="Label" parent="UI/Pause"]
margin_right = 40.0
margin_bottom = 14.0
[node name="Unpause" type="Button" parent="UI/Pause"]
margin_left = 111.702
margin_top = 218.0
margin_right = 327.702
margin_bottom = 238.0
text = "Resume"
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="button_down" from="UI/Button" to="DataManager" method="_on_Button_button_down"]
[connection signal="button_down" from="UI/Pause/Unpause" to="UI/Pause" method="_pause_manager"]

6
system/init.gd Normal file
View File

@ -0,0 +1,6 @@
extends Node
export(String, FILE, "*.tscn") var initial_map
func _ready():
RPGH.map = initial_map

8
system/init.tscn Normal file
View File

@ -0,0 +1,8 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://addons/rpgh_engine/system/init.gd" type="Script" id=1]
[node name="Init" type="Node"]
script = ExtResource( 1 )

40
system/rpgh_engine.gd Normal file
View File

@ -0,0 +1,40 @@
extends Node
const DEFAULT_SCREEN_SIZE = Vector2(640, 360)
var map = null setget set_map
var global_data := {}
onready var DataManager = get_node("DataManager")
onready var MapContainer = get_node("Ingame/Viewport/MapContainer")
onready var Player = get_node("Ingame/Viewport/MapContainer/Player")
onready var Camera = get_node("Ingame/Viewport/MapContainer/Camera")
onready var Dialog = get_node("UI/Dialog")
func set_map(value):
if !value == null:
if !map == null:
map.queue_free()
yield(map, "tree_exited")
var instanced_map = _map_to_node(value)
if instanced_map != null:
MapContainer.add_child(instanced_map)
map = instanced_map
print("Map set!")
else:
if !map == null:
map.queue_free()
# Pass either a String, a PackedScene or a Node
# directly to certainly get a Node
func _map_to_node(node_information) -> Node:
if node_information is String:
return load(node_information).instance()
elif node_information is PackedScene:
return node_information.instance()
elif node_information is Node:
return node_information
else:
push_error("No supported format was passed for the map!")
return null

BIN
ui/bust.material Normal file

Binary file not shown.

BIN
ui/bust_transition.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bust_transition.png-4f62a5e234bc14ba3bbb18d047ce1a4f.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/rpgh_engine/ui/bust_transition.png"
dest_files=[ "res://.import/bust_transition.png-4f62a5e234bc14ba3bbb18d047ce1a4f.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

221
ui/dialog.gd Normal file
View File

@ -0,0 +1,221 @@
extends Control
signal finished_textbox_queue
var _is_left_bust_visible = false
var _is_right_bust_visible = false
var _are_textboxes_cached = false
var _textbox_queue := []
var _current_textbox: RPGH_Textbox = null
var text_data = _json_parser()
var json_directory = _json_directory()
onready var Textbox = get_node("Textbox")
onready var DialogAnimationPlayer = get_node("AnimationPlayer")
onready var LeftBust = get_node("LeftBust")
onready var LeftBustAnimationPlayer = get_node("LeftBust/AnimationPlayer")
onready var RightBust = get_node("RightBust")
onready var RightBustAnimationPlayer = get_node("RightBust/AnimationPlayer")
func _json_directory(): # On Work
var directory = Directory.new()
if !directory.dir_exists("res://game/lang"):
directory.make_dir("res://game/lang")
return directory
func _json_parser():
var text_data_file = File.new()
text_data_file.open("res://game/lang/lang.json", File.READ)
var text_data_json = JSON.parse(text_data_file.get_as_text())
text_data_file.close()
return text_data_json.result
func textbox(id: String, left_bust: Texture = null, right_bust: Texture = null):
var textbox = RPGH_DefaultTextbox.new()
var text = text_data["tb"][id].eng
textbox.text = text
if !left_bust == null:
textbox.left_artwork = left_bust
if !right_bust == null:
textbox.right_artwork = right_bust
var is_no_textbox_opened = _current_textbox == null
_textbox_queue.append(textbox)
if is_no_textbox_opened:
_show_textbox_queue()
func screen_text(id: String):
var screen_text = RPGH_ScreenText.new()
var text = text_data["tb"][id].eng
screen_text.text = text
var is_no_textbox_opened = _current_textbox == null
_textbox_queue.append(screen_text)
if is_no_textbox_opened:
_show_textbox_queue()
func close_textbox():
if !_current_textbox == null:
_current_textbox._close()
func _show_textbox_queue():
var is_queue_active = true
while is_queue_active:
var previous_textbox = _current_textbox
_current_textbox = _textbox_queue.pop_front()
var different_textbox_type
if previous_textbox == null or _current_textbox == null:
different_textbox_type = true
else:
different_textbox_type = !previous_textbox.type == _current_textbox.type
if different_textbox_type and !previous_textbox == null:
previous_textbox._close()
yield(previous_textbox, "closed_textbox")
if !_current_textbox == null:
_current_textbox._prepare()
if different_textbox_type:
_current_textbox._open()
yield(_current_textbox, "opened_textbox")
_current_textbox._show()
yield(_current_textbox, "showed_textbox")
is_queue_active = !_current_textbox == null
emit_signal("finished_textbox_queue")
# Just a base class for different types of textboxes.
class RPGH_Textbox:
# The signals are used in the subclasses.
# warning-ignore:unused_signal
signal opened_textbox
# warning-ignore:unused_signal
signal showed_textbox
# warning-ignore:unused_signal
signal closed_textbox
enum Type {
DEFAULT_TEXTBOX,
SCREEN_TEXT
}
var text = ""
var type
func _prepare():
pass
func _open():
pass
func _show():
pass
func _close():
pass
class RPGH_DefaultTextbox:
extends RPGH_Textbox
var left_artwork = null
var right_artwork = null
func _init():
type = Type.DEFAULT_TEXTBOX
func _prepare():
RPGH.Dialog.Textbox.text = text
if !left_artwork == null:
if !RPGH.Dialog._is_left_bust_visible:
RPGH.Dialog.LeftBust.texture = left_artwork
RPGH.Dialog.LeftBustAnimationPlayer.play("SpawnBust")
RPGH.Dialog._is_left_bust_visible = true
else:
RPGH.Dialog.LeftBust.texture = left_artwork
if !right_artwork == null:
if !RPGH.Dialog._is_right_bust_visible:
RPGH.Dialog.RightBust.texture = right_artwork
RPGH.Dialog.RightBustAnimationPlayer.play("SpawnBust")
RPGH.Dialog._is_right_bust_visible = true
else:
RPGH.Dialog.RightBust.texture = right_artwork
func _open():
RPGH.Player._player_movement_disabled = true
RPGH.Player._player_interact_disabled = true
RPGH.Dialog.DialogAnimationPlayer.play("SpawnTextbox")
yield(RPGH.Dialog.DialogAnimationPlayer, "animation_finished")
emit_signal("opened_textbox")
func _show():
RPGH.Dialog.Textbox.start_show_characters_animation()
yield(RPGH.Dialog.Textbox, "accepted")
emit_signal("showed_textbox")
func _close():
if RPGH.Dialog._is_left_bust_visible:
RPGH.Dialog.LeftBustAnimationPlayer.play("DespawnBust")
RPGH.Dialog._is_left_bust_visible = false
if RPGH.Dialog._is_right_bust_visible:
RPGH.Dialog.RightBustAnimationPlayer.play("DespawnBust")
RPGH.Dialog._is_right_bust_visible = false
RPGH.Dialog.Textbox.visible_characters = 0
RPGH.Dialog.DialogAnimationPlayer.play("DespawnTextbox")
yield(RPGH.Dialog.DialogAnimationPlayer, "animation_finished")
emit_signal("closed_textbox")
class RPGH_ScreenText:
extends RPGH_Textbox
func _init():
type = Type.SCREEN_TEXT
func _prepare():
RPGH.Dialog.Textbox.text = text
func _open():
RPGH.Player._player_movement_disabled = true
RPGH.Player._player_interact_disabled = true
RPGH.Dialog.DialogAnimationPlayer.play("SpawnScreenText")
yield(RPGH.Dialog.DialogAnimationPlayer, "animation_finished")
emit_signal("opened_textbox")
func _show():
RPGH.Dialog.Textbox.start_show_characters_animation()
yield(RPGH.Dialog.Textbox, "accepted")
emit_signal("showed_textbox")
func _close():
RPGH.Dialog.Textbox.visible_characters = 0
RPGH.Dialog.DialogAnimationPlayer.play("DespawnScreenText")
yield(RPGH.Dialog.DialogAnimationPlayer, "animation_finished")
emit_signal("closed_textbox")

20
ui/pause.gd Normal file
View File

@ -0,0 +1,20 @@
extends Popup
export var pause = false
# Doesn't prevent zooming at the start of the Game
func _process(delta):
if Input.is_action_just_pressed("game_pause"):
_pause_manager()
func _pause_manager():
if !pause:
get_tree().paused = true
show()
pause = true
else:
hide()
get_tree().paused = false
pause = false

39
ui/textbox.gd Normal file
View File

@ -0,0 +1,39 @@
extends RichTextLabel
signal accepted
const CHARACTERS_PER_SECOND = 25.0
const ACCELERATED_CHARACTERS_PER_SECOND = 260.0
var _in_show_characters_animation = false
var _add_character_timer = 0.0
var _seconds_per_character
func _process(delta):
if _in_show_characters_animation:
_add_character_timer += delta
var characters_to_add = _add_character_timer / _seconds_per_character
var floored_characters_to_add = floor(characters_to_add)
_add_character_timer -= floored_characters_to_add * _seconds_per_character
visible_characters += floored_characters_to_add
var total_character_count = get_total_character_count()
if visible_characters >= total_character_count:
visible_characters = -1
_in_show_characters_animation = false
func _input(event):
if event.is_action_pressed("ui_accept"):
if _in_show_characters_animation: # accelerate show characters animation.
_seconds_per_character = 1.0 / ACCELERATED_CHARACTERS_PER_SECOND
else:
emit_signal("accepted")
func start_show_characters_animation():
_in_show_characters_animation = true
_seconds_per_character = 1.0 / CHARACTERS_PER_SECOND
_add_character_timer = 0.0
visible_characters = 0