base level for enemies testing

This commit is contained in:
2026-01-15 10:31:13 +01:00
parent f33257ca3b
commit 24a781f36a
14 changed files with 631 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Skaruts
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 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.

View File

@@ -0,0 +1,11 @@
# Fly Camera Addon for Godot 4
A camera addon for flying around scenes at runtime, which can be handy during the prototyping phase of a project, for example.
The camera is easy to use. You can just drop it in a scene, and run the game.
Optionally you can also tweek the camera node settings in the inspector (speed, mouse sensitivity, etc).
By default the camera uses `WASD` keys for movement, `Shift` to move faster, `Ctrl` to move slower,
and `Right Mouse Button` to activate/deactivate the camera's mouse controls.
Please refer to the documentation for more information.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b42t3486jwfud"
path="res://.godot/imported/fly_camera.png-f981b86d63a5d3aa84ae2448e297f41a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/sk_fly_camera/icons/fly_camera.png"
dest_files=["res://.godot/imported/fly_camera.png-f981b86d63a5d3aa84ae2448e297f41a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="16"
height="16"
version="1.1"
id="svg134"
sodipodi:docname="fly_camera.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs138" />
<sodipodi:namedview
id="namedview136"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="true"
inkscape:zoom="32"
inkscape:cx="2.625"
inkscape:cy="7.671875"
inkscape:window-width="1920"
inkscape:window-height="1019"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="layer2">
<inkscape:grid
type="xygrid"
id="grid308" />
</sodipodi:namedview>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2">
<path
style="fill:#fc7f7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 3,10 -2,2 c -0.003906,0.519531 0.4687424,0.996094 1,1 L 4,11 C 4,10.46875 3.5117188,10.003906 3,10 Z"
id="path14405"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#fc7f7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 7,11 -3,3 c 0,0.558594 0.4648437,1 1,1 L 8,12 C 7.9921875,11.449219 7.5195312,11 7,11 Z"
id="path14407"
sodipodi:nodetypes="ccccc" />
<path
style="fill:#fc7f7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 11,12 -2,2 c 0,0.527344 0.5195313,1.003906 1,1 l 2,-2 c 0,-0.515625 -0.476562,-1 -1,-1 z"
id="path14411"
sodipodi:nodetypes="ccccc" />
<path
fill="#fc7f7f"
d="M 11.138701,0.75495528 C 9.6199087,0.34348987 8.0412937,1.175426 7.5221826,2.6608742 6.5016104,1.0517042 4.2589492,0.78937193 2.8945438,2.1195486 1.5301383,3.4497251 1.7354189,5.6983262 3.3181454,6.7594447 L 3.0137742,7.8953734 C 2.8708323,8.4288398 3.1874149,8.9771765 3.720881,9.1201183 l 5.7955549,1.5529137 c 0.5334661,0.142942 1.0818031,-0.17364 1.2247451,-0.7071062 L 11,9 13.380139,11.708309 14.933053,5.9127538 11.517638,7.0681483 11.716929,6.3243854 C 14.164193,5.0783219 13.789747,1.4717031 11.138701,0.75495528 Z"
id="path14413"
sodipodi:nodetypes="ccscsssscccccc"
style="display:inline" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dma1meqanq6lr"
path="res://.godot/imported/fly_camera.svg-197f6cff73611fb9b2753ae8bc3c4adb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/sk_fly_camera/icons/fly_camera.svg"
dest_files=["res://.godot/imported/fly_camera.svg-197f6cff73611fb9b2753ae8bc3c4adb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@@ -0,0 +1,7 @@
[plugin]
name="Fly Camera"
description="A camera for when you need to quickly fly around while prototyping games."
author="Skaruts"
version="0.1"
script="plugin.gd"

View File

@@ -0,0 +1,5 @@
@tool
extends EditorPlugin
# nothing to see here

View File

@@ -0,0 +1 @@
uid://ctjbk1djxsko6

View File

@@ -0,0 +1,314 @@
@icon("../icons/fly_camera.svg")
class_name FlyCamera
extends CharacterBody3D
##
## A free flying camera, handy for prototyping.
## [br][br]
##
##
## This camera allows to quickly be able to fly around at runtime.
## Just put it in a scene and it should be good to go. You can optionally
## tweak its settings in the inspector.
## [br][br]
##
## The camera node itself is not an actual camera, but a [CharacterBody3D], so
## it has no visual preview in the inspector. You can still align it to the
## camera in the 3D View, by clicking [param Perspective > Align Transform With View].
## [br][br]
##
## You will also see a warning in the [param Scene] tree about the [CharacterBody3D]
## not having a shape. Normally a flying camera doesn't need any collisions,
## and you can ignore the warning. The camera still supports collisions, though,
## either by turning on [param Use Collisions] in the inspector, or by
## manually adding a [CollisionShape3D] node with a shape of your choice.
## [br][br]
##[color=white][b]Note:[/b][/color] the collisions are added at runtime, so
## turning on [param Use Collisions] will not suppress the warning.
## [br][br]
##
## The camera controls can be changed. By default it uses the [param WASD]
## keys for movement, [param Shift] to move faster, [param Ctrl] to move slower, and
## the [param Right Mouse Button] to activate/deactivate the mouse controls
## (capturing/uncapturing the mouse pointer).
## [br][br]
##
## This camera was intended for quick use, so the default controls are easy to
## change in the camera script by hand (in the [param _actions_to_key] dictionary).
## However, if you prefer, you can also set the following input actions in
## your project settings, and the camera will automatically use them instead:
## [codeblock]
##cam_forward
##cam_backward
##cam_left
##cam_right
##cam_faster
##cam_slower
##cam_activate
## [/codeblock]
## [color=white][b]Note:[/b][/color] the mouse button used to activate the
## camera can easily be changed in the inspector, so for that end you don't
## need to use [param cam_activate] input action.
## This action is provided in case you'd like to use a keyboard key instead.
##
##
## How to activate mouse controls.
enum ActivationMode {
ON_CLICK, ## Click to activate, click again to deactivate.
ON_HOLD, ## Hold mouse button to activate, release to deactivate.
}
## Where to revert the mouse pointer when releasing mouse controls.
enum RevertMouseOption {
CLICK_POSITION, ## The position where the mouse was initially clicked.
VIEWPORT_CENTER, ## The center of the viewport.
}
enum MouseButton {
LEFT = 1,
RIGHT,
MIDDLE,
}
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
# User Properties / Settings
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
#region user_settings
@export_group("Mouse Settings")
## How to activate the mouse controls.
@export var activation_mode := ActivationMode.ON_CLICK
## Where the mouse pointer should be at when releasing mouse controls.
@export var revert_mouse_to := RevertMouseOption.CLICK_POSITION
## Which mouse button activates mouse control.
@export var mouse_button := MouseButton.RIGHT
## The mouse sensitivity in each axis.
@export var mouse_sensitivity := Vector2(2.2, 2.2)
## If true the mouse's vertical axis will be inverted.
@export var invert_y := false
## If true, the key controls will still work when the mouse controls
## are inactive.
@export var keep_key_controls := true
@export_group("Camera Settings")
## The camera's movement speed.
@export var fly_speed := 20.0
## The camera's acceleration.
## [br][br]
## For simplicity, this also doubles as friction.
@export var acceleration : int = 10
## The factor by which to multiply or divide the camera speed in order to
## move faster or slower.
@export var speed_factor : int = 3
## Adds a sphere collision shape to the camera. You can setup
## the collision layers as you please.
@export var use_collision := false:
set(enable):
use_collision = enable
_set_collisions(enable)
## If true, the camera will use the default controls and ignore any
## input actions defined in the project settings.
@export var use_default_controls := false
#endregion
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
# Internals
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
#region internal_Stuff
const _ACTION_FORWARD := "cam_forward"
const _ACTION_BACKWARD := "cam_backward"
const _ACTION_LEFT := "cam_left"
const _ACTION_RIGHT := "cam_right"
const _ACTION_FASTER := "cam_faster"
const _ACTION_SLOWER := "cam_slower"
const _ACTION_ACTIVATE := "cam_activate"
var _actions_to_key := {
_ACTION_FORWARD : KEY_W,
_ACTION_BACKWARD : KEY_S,
_ACTION_LEFT : KEY_A,
_ACTION_RIGHT : KEY_D,
_ACTION_FASTER : KEY_SHIFT,
_ACTION_SLOWER : KEY_CTRL,
_ACTION_ACTIVATE : mouse_button,
}
const _PITCH_LIMIT : int = 90
var _mouse_click_pos : Vector2
var _mouse_hidden : bool
var _coll : CollisionShape3D
var _camera : Camera3D # The actual, internal camera node.
var _cam_pivot: Node3D # The Y rotation pivot node
var _yaw : float = 0
var _pitch : float = 0
func _ready() -> void:
_cam_pivot = Node3D.new()
add_child(_cam_pivot)
_camera = Camera3D.new()
_cam_pivot.add_child(_camera)
_camera.current = true
# if this node was rotated in the editor, use that as default rotation
var rot := rotation_degrees
rotation = Vector3.ZERO
set_rot(rot)
func _unhandled_input(event: InputEvent) -> void:
_check_mouse_capture(event)
if not _mouse_hidden:
return
## Camera motion
if event is InputEventMouseMotion:
_yaw = fmod(_yaw - event.relative.x * mouse_sensitivity.x/10, 360)
if not invert_y: _pitch = max(min(_pitch - event.relative.y * mouse_sensitivity.y/10.0, _PITCH_LIMIT), -_PITCH_LIMIT)
else: _pitch = max(min(_pitch + event.relative.y * mouse_sensitivity.y/10.0, _PITCH_LIMIT), -_PITCH_LIMIT)
_cam_pivot.rotation.y = deg_to_rad(_yaw)
_camera.rotation.x = deg_to_rad(_pitch)
func _physics_process(delta: float) -> void:
var aim : Basis = _camera.get_camera_transform().basis
var dir := Vector3()
var spd := fly_speed
if _mouse_hidden or keep_key_controls:
if _is_cam_action_pressed(_ACTION_FORWARD): dir -= aim[2]
if _is_cam_action_pressed(_ACTION_BACKWARD): dir += aim[2]
if _is_cam_action_pressed(_ACTION_LEFT): dir -= aim[0]
if _is_cam_action_pressed(_ACTION_RIGHT): dir += aim[0]
if _is_cam_action_pressed(_ACTION_FASTER): spd *= speed_factor
if _is_cam_action_pressed(_ACTION_SLOWER): spd /= speed_factor
dir = dir.normalized()
var target := dir * spd
velocity = velocity.lerp( target, acceleration*delta )
move_and_slide()
if is_zero_approx(velocity.length()):
velocity = Vector3.ZERO
func _is_cam_action_pressed(action:String) -> bool:
if not use_default_controls and InputMap.has_action(action):
return Input.is_action_pressed(action)
return Input.is_key_pressed(_actions_to_key[action])
func _set_collisions(enable:bool) -> void:
if enable:
_coll = CollisionShape3D.new()
_coll.shape = SphereShape3D.new()
add_child(_coll)
else:
_coll.queue_free()
_coll = null
func _check_mouse_capture(event:InputEvent) -> void:
var button_state := 0 # 0- unchaged, 1- pressed, 2- released
if not use_default_controls and InputMap.has_action(_ACTION_ACTIVATE):
if event.is_action_pressed(_ACTION_ACTIVATE): button_state = 1
elif event.is_action_released(_ACTION_ACTIVATE): button_state = 2
elif event is InputEventMouseButton and event.button_index == mouse_button:
button_state = 1 if event.pressed else 2
if button_state == 0: return
match activation_mode:
ActivationMode.ON_HOLD:
set_active(button_state == 1)
ActivationMode.ON_CLICK:
if button_state == 1:
set_active(not _mouse_hidden)
func _revert_mouse_pos() -> void:
var vp := get_viewport()
match revert_mouse_to:
RevertMouseOption.CLICK_POSITION:
vp.warp_mouse( _mouse_click_pos )
RevertMouseOption.VIEWPORT_CENTER:
vp.warp_mouse(vp.get_visible_rect().size/2)
#endregion
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
# Public API
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=
## Returns the actual camera that is used internally.
func get_camera() -> Camera3D:
return _camera
## Sets the FlyCamera's rotation to [param rot].
## [br][br]
## [color=white][b]Note:[/b][/color] don't set the rotation directly, as the
## rotation of the root node doesn't represent the rotation of the actual camera.
func set_rot(rot:Vector3) -> void:
_yaw = rot.y
_pitch = rot.x
_cam_pivot.rotation_degrees.y = _yaw
_camera.rotation_degrees.x = _pitch
## Returns the rotation of the camera.
## [br][br]
## [color=white][b]Note:[/b][/color] don't get the rotation directly, as the
## rotation of the root node doesn't represent the rotation of the actual camera.
func get_rot() -> Vector3:
return Vector3(_camera.rotation.x, _cam_pivot.rotation.y, 0)
## Activate or deactivate the mouse controls
func set_active(enable:bool) -> void:
if enable:
_mouse_click_pos = get_viewport().get_mouse_position()
_mouse_hidden = true
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
_mouse_hidden = false
_revert_mouse_pos()

View File

@@ -0,0 +1 @@
uid://cte4jalives85