nav collision

This commit is contained in:
veclavtlica
2026-11-01 16:00:46 +03:00
parent 7b74d0606f
commit 6bd30e9ad9
21 changed files with 1915 additions and 19 deletions
+3
View File
@@ -1,3 +1,6 @@
# Godot 4+ specific ignores
.godot/
/android/
**/*.xm
**/*.it
+77 -15
View File
@@ -1,10 +1,20 @@
[gd_scene format=3 uid="uid://crgeyg1m54cg8"]
[ext_resource type="Script" uid="uid://dtqv683r772sd" path="res://player.gd" id="1_3dxm6"]
[ext_resource type="Texture2D" uid="uid://cqisk1m0in4a4" path="res://shield.png" id="1_03owx"]
[ext_resource type="Texture2D" uid="uid://dgkao0lkjfn8x" path="res://gun-handheld-reduced.png" id="1_glv2v"]
[ext_resource type="Texture2D" uid="uid://de7h5yetxbjii" path="res://gui-reduced.png" id="2_uu6xs"]
[ext_resource type="Script" uid="uid://biacb353kq32o" path="res://level_mesh.gd" id="3_cm0pq"]
[ext_resource type="Texture2D" uid="uid://bj63s2jg8oinu" path="res://rock22.jpg" id="4_fos0i"]
[ext_resource type="Texture2D" uid="uid://cbfvjlda1hapx" path="res://metall001-new-tileable2.png" id="5_fos0i"]
[ext_resource type="Script" uid="uid://djgd6mugw2s47" path="res://godot-mod-player-g4-master/addons/modplayer/ModPlayer.gd" id="7_lgr22"]
[ext_resource type="Script" uid="uid://cc2rv3wnwas52" path="res://wall_segment.gd" id="7_trn2v"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_03owx"]
shading_mode = 2
albedo_color = Color(0.1415951, 0.43394297, 0.68819517, 1)
[sub_resource type="PrismMesh" id="PrismMesh_1065d"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_lgr22"]
sky_top_color = Color(0.15010819, 0.09080864, 3.6098065e-08, 1)
@@ -25,7 +35,6 @@ sky = SubResource("Sky_3dxm6")
ambient_light_source = 3
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_cm0pq"]
cull_mode = 1
shading_mode = 2
specular_mode = 2
albedo_texture = ExtResource("4_fos0i")
@@ -34,50 +43,86 @@ fov_override = 33.9
distance_fade_mode = 1
distance_fade_max_distance = 2.0
[sub_resource type="ImmediateMesh" id="ImmediateMesh_fos0i"]
[sub_resource type="ImmediateMesh" id="ImmediateMesh_03owx"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_fos0i"]
shading_mode = 2
specular_mode = 2
albedo_texture = ExtResource("5_fos0i")
texture_filter = 2
texture_filter = 4
fov_override = 33.9
distance_fade_mode = 2
distance_fade_max_distance = 1.0
[sub_resource type="ImmediateMesh" id="ImmediateMesh_3dxm6"]
[sub_resource type="ImmediateMesh" id="ImmediateMesh_wkp8b"]
[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_20pc6"]
data = PackedVector3Array(1.9799999, 0, 0.57, 0.7, 0, 0.89, 1.916, 2.7717, 0.31399998, 0.7, 0, 0.89, 0.188, 1.6502, 1.082, 1.916, 2.7717, 0.31399998, 1.916, 2.7717, 0.31399998, 0.188, 1.6502, 1.082, 1.9799999, 5, 0.57, 0.188, 1.6502, 1.082, 0.7, 5, 0.89, 1.9799999, 5, 0.57, 0.7, 0, 0.89, 1.66, 0, 3.4499998, 0.188, 1.6502, 1.082, 1.66, 0, 3.4499998, 1.3399999, 1.4045, 3.7059999, 0.188, 1.6502, 1.082, 0.188, 1.6502, 1.082, 1.3399999, 1.4045, 3.7059999, 0.7, 5, 0.89, 1.3399999, 1.4045, 3.7059999, 1.66, 5, 3.4499998, 0.7, 5, 0.89, 1.66, 0, 3.4499998, 2.9399998, 0, 5.0499997, 1.3399999, 1.4045, 3.7059999, 2.9399998, 0, 5.0499997, 2.958, 1.2507, 5.694, 1.3399999, 1.4045, 3.7059999, 1.3399999, 1.4045, 3.7059999, 2.958, 1.2507, 5.694, 1.66, 5, 3.4499998, 2.958, 1.2507, 5.694, 2.9399998, 5, 5.0499997, 1.66, 5, 3.4499998, 2.9399998, 0, 5.0499997, 6.16, 0, 4.96, 2.958, 1.2507, 5.694, 6.16, 0, 4.96, 5.118, 1.7171999, 5.148, 2.958, 1.2507, 5.694, 2.958, 1.2507, 5.694, 5.118, 1.7171999, 5.148, 2.9399998, 5, 5.0499997, 5.118, 1.7171999, 5.148, 6.16, 5, 4.96, 2.9399998, 5, 5.0499997, 6.16, 0, 4.96, 7.1, 0, 10.17, 5.118, 1.7171999, 5.148, 7.1, 0, 10.17, 6.5239997, 1.3377, 9.658, 5.118, 1.7171999, 5.148, 5.118, 1.7171999, 5.148, 6.5239997, 1.3377, 9.658, 6.16, 5, 4.96, 6.5239997, 1.3377, 9.658, 7.1, 5, 10.17, 6.16, 5, 4.96, 7.1, 0, 10.17, 4.54, 0, 13.049999, 6.5239997, 1.3377, 9.658, 4.54, 0, 13.049999, 3.964, 2.7186, 13.497999, 6.5239997, 1.3377, 9.658, 6.5239997, 1.3377, 9.658, 3.964, 2.7186, 13.497999, 7.1, 5, 10.17, 3.964, 2.7186, 13.497999, 4.54, 5, 13.049999, 7.1, 5, 10.17, 4.54, 0, 13.049999, 6.7799997, 0, 15.929999, 3.964, 2.7186, 13.497999, 6.7799997, 0, 15.929999, 6.908, 1.9440999, 16.633999, 3.964, 2.7186, 13.497999, 3.964, 2.7186, 13.497999, 6.908, 1.9440999, 16.633999, 4.54, 5, 13.049999, 6.908, 1.9440999, 16.633999, 6.7799997, 5, 15.929999, 4.54, 5, 13.049999, 6.7799997, 0, 15.929999, 10.3, 0, 15.29, 6.908, 1.9440999, 16.633999, 10.3, 0, 15.29, 11.068, 2.4175, 15.481999, 6.908, 1.9440999, 16.633999, 6.908, 1.9440999, 16.633999, 11.068, 2.4175, 15.481999, 6.7799997, 5, 15.929999, 11.068, 2.4175, 15.481999, 10.3, 5, 15.29, 6.7799997, 5, 15.929999, 10.3, 0, 15.29, 11.259999, 0, 11.45, 11.068, 2.4175, 15.481999, 11.259999, 0, 11.45, 12.334, 2.0367, 11.054, 11.068, 2.4175, 15.481999, 11.068, 2.4175, 15.481999, 12.334, 2.0367, 11.054, 10.3, 5, 15.29, 12.334, 2.0367, 11.054, 11.259999, 5, 11.45, 10.3, 5, 15.29, 11.259999, 0, 11.45, 9.28, 0, 6.08, 12.334, 2.0367, 11.054, 9.28, 0, 6.08, 8.846, 1.1595, 7.3719997, 12.334, 2.0367, 11.054, 12.334, 2.0367, 11.054, 8.846, 1.1595, 7.3719997, 11.259999, 5, 11.45, 8.846, 1.1595, 7.3719997, 9.28, 5, 6.08, 11.259999, 5, 11.45, 9.28, 0, 6.08, 15.74, 0, 8.25, 8.846, 1.1595, 7.3719997, 15.74, 0, 8.25, 16.123999, 1.4636999, 8.506, 8.846, 1.1595, 7.3719997, 8.846, 1.1595, 7.3719997, 16.123999, 1.4636999, 8.506, 9.28, 5, 6.08, 16.123999, 1.4636999, 8.506, 15.74, 5, 8.25, 9.28, 5, 6.08, 15.74, 0, 8.25, 17.02, 0, 6.33, 16.123999, 1.4636999, 8.506, 17.02, 0, 6.33, 17.821999, 1.3002, 5.534, 16.123999, 1.4636999, 8.506, 16.123999, 1.4636999, 8.506, 17.821999, 1.3002, 5.534, 15.74, 5, 8.25, 17.821999, 1.3002, 5.534, 17.02, 5, 6.33, 15.74, 5, 8.25, 17.02, 0, 6.33, 13.04, 0, 2.32, 17.821999, 1.3002, 5.534, 13.04, 0, 2.32, 13.134, 2.981, 1.388, 17.821999, 1.3002, 5.534, 17.821999, 1.3002, 5.534, 13.134, 2.981, 1.388, 17.02, 5, 6.33, 13.134, 2.981, 1.388, 13.04, 5, 2.32, 17.02, 5, 6.33, 13.04, 0, 2.32, 8.38, 0, 1.8499999, 13.134, 2.981, 1.388, 8.38, 0, 1.8499999, 8.254, 2.2742, 1.214, 13.134, 2.981, 1.388, 13.134, 2.981, 1.388, 8.254, 2.2742, 1.214, 13.04, 5, 2.32, 8.254, 2.2742, 1.214, 8.38, 5, 1.8499999, 13.04, 5, 2.32, 8.38, 0, 1.8499999, 5.2, 0, 2.48, 8.254, 2.2742, 1.214, 5.2, 0, 2.48, 5.454, 2.3258998, 2.22, 8.254, 2.2742, 1.214, 8.254, 2.2742, 1.214, 5.454, 2.3258998, 2.22, 8.38, 5, 1.8499999, 5.454, 2.3258998, 2.22, 5.2, 5, 2.48, 8.38, 5, 1.8499999, 5.2, 0, 2.48, 3.8999999, 0, 1.2099999, 5.454, 2.3258998, 2.22, 3.8999999, 0, 1.2099999, 4.028, 2.1676, 0.826, 5.454, 2.3258998, 2.22, 5.454, 2.3258998, 2.22, 4.028, 2.1676, 0.826, 5.2, 5, 2.48, 4.028, 2.1676, 0.826, 3.8999999, 5, 1.2099999, 5.2, 5, 2.48, 3.8999999, 0, 1.2099999, 1.9799999, 0, 0.57, 4.028, 2.1676, 0.826, 1.9799999, 0, 0.57, 1.916, 2.2347999, 0.31399998, 4.028, 2.1676, 0.826, 4.028, 2.1676, 0.826, 1.916, 2.2347999, 0.31399998, 3.8999999, 5, 1.2099999, 1.916, 2.2347999, 0.31399998, 1.9799999, 5, 0.57, 3.8999999, 5, 1.2099999)
backface_collision = true
[node name="Node3D" type="Node3D" unique_id=1749101855]
[node name="Camera3D" type="Camera3D" parent="." unique_id=1552004731]
[node name="WallMark" type="Sprite3D" parent="." unique_id=1606442103]
pixel_size = 0.02
texture = ExtResource("1_03owx")
[node name="SidePoint" type="MeshInstance3D" parent="WallMark" unique_id=909669364]
transform = Transform3D(0.2, 0, 0, 0, -3.3225813e-08, -0.19999997, 0, 0.760118, -8.742277e-09, 0, 0, 0.5)
material_override = SubResource("StandardMaterial3D_03owx")
mesh = SubResource("PrismMesh_1065d")
[node name="FloorMark" type="Sprite3D" parent="." unique_id=1733002043]
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, -1, 0, 1, -4.371139e-08, 0, 0, 0)
pixel_size = 0.02
texture = ExtResource("1_03owx")
[node name="SidePoint" type="MeshInstance3D" parent="FloorMark" unique_id=2041287788]
transform = Transform3D(0.2, 0, 0, 0, -3.3225813e-08, -0.19999997, 0, 0.760118, -8.742277e-09, 0, 0, 0.5)
material_override = SubResource("StandardMaterial3D_03owx")
mesh = SubResource("PrismMesh_1065d")
[node name="Player" type="Node3D" parent="." unique_id=1544606435 node_paths=PackedStringArray("_cam", "_ray")]
script = ExtResource("1_3dxm6")
_cam = NodePath("Look")
_ray = NodePath("Look/RayCast3D")
[node name="Look" type="Camera3D" parent="Player" unique_id=1552004731]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1.1841735)
[node name="Sprite3D2" type="Sprite3D" parent="." unique_id=2128191748]
transform = Transform3D(0.75, 0, 0, 0, 0.75, 0, 0, 0, 0.75, 0, 0, 0)
[node name="Sprite3D2" type="Sprite3D" parent="Player/Look" unique_id=2128191748]
transform = Transform3D(0.75, 0, 0, 0, 0.75, 0, 0, 0, 0.75, 0, 0, -1.1841735)
billboard = 1
texture_filter = 0
texture = ExtResource("2_uu6xs")
[node name="Sprite3D" type="Sprite3D" parent="." unique_id=328920978]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.47348556, -0.6719171, 0)
[node name="Sprite3D" type="Sprite3D" parent="Player/Look" unique_id=328920978]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.47348556, -0.6719171, -1.1841735)
billboard = 1
texture_filter = 0
render_priority = 1
texture = ExtResource("1_glv2v")
[node name="RayCast3D" type="RayCast3D" parent="Player/Look" unique_id=987966127]
transform = Transform3D(-100, -1.509958e-05, -6.6002363e-13, 0, -4.371139e-06, 100, -1.509958e-05, 100, 4.371139e-06, 0, 0, 0)
collision_mask = 32774
hit_from_inside = true
collide_with_areas = true
debug_shape_thickness = 1
[node name="WorldEnvironment" type="WorldEnvironment" parent="." unique_id=2112481184]
environment = SubResource("Environment_r0du0")
[node name="AreaLight3D" type="AreaLight3D" parent="." unique_id=1499708949]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.8187913, 0.6215458, 0)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.3378613, -0.5583314, -4.607884)
light_color = Color(0.9137892, 0.027400356, 0.120897986, 1)
light_energy = 16.0
[node name="LevelMesh" type="Polygon2D" parent="." unique_id=1028271676 node_paths=PackedStringArray("_floor_mesh", "_wall_mesh")]
self_modulate = Color(1, 1, 1, 0)
position = Vector2(-38, -25)
color = Color(0.45490196, 0.45490196, 0.45490196, 0.6)
polygon = PackedVector2Array(198, 57, 70, 89, 166, 345, 294, 505, 550, 537, 710, 1017, 454, 1305, 678, 1593, 1030, 1529, 1130.7727, 1130.3756, 902, 505, 1574, 825, 1702, 633, 1192, 256, 838, 185, 518, 249, 390, 121)
polygon = PackedVector2Array(198, 57, 70, 89, 166, 345, 294, 505, 615.9999, 495.99997, 710, 1017, 454, 1305, 678, 1593, 1030, 1529, 1126, 1145, 927.9999, 607.99994, 1574, 825, 1702, 633, 1303.9999, 232, 838, 185, 520, 248, 390, 121)
uv = PackedVector2Array(198, 57, 70, 89, 166, 345, 294, 505, 550, 537, 710, 1017, 454, 1305, 678, 1593, 1030, 1529, 934, 793, 902, 473, 1574, 825, 1702, 633, 1094, 313, 794.0979, 279.67758, 518, 249, 390, 121)
polygons = [PackedInt32Array(0, 1, 2), PackedInt32Array(5, 6, 7), PackedInt32Array(5, 7, 8), PackedInt32Array(5, 8, 9), PackedInt32Array(4, 5, 10), PackedInt32Array(5, 9, 10), PackedInt32Array(10, 11, 13), PackedInt32Array(11, 12, 13), PackedInt32Array(10, 13, 14), PackedInt32Array(4, 10, 14), PackedInt32Array(4, 14, 15), PackedInt32Array(2, 3, 15), PackedInt32Array(3, 4, 15), PackedInt32Array(0, 2, 16), PackedInt32Array(2, 15, 16)]
polygons = [PackedInt32Array(2, 1, 0), PackedInt32Array(7, 6, 5), PackedInt32Array(8, 7, 5), PackedInt32Array(9, 8, 5), PackedInt32Array(10, 5, 4), PackedInt32Array(10, 9, 5), PackedInt32Array(13, 11, 10), PackedInt32Array(13, 12, 11), PackedInt32Array(14, 10, 4), PackedInt32Array(14, 13, 10), PackedInt32Array(15, 14, 4), PackedInt32Array(15, 3, 2), PackedInt32Array(15, 4, 3), PackedInt32Array(16, 2, 0), PackedInt32Array(16, 15, 2)]
script = ExtResource("3_cm0pq")
_floor_mesh = NodePath("FloorMesh")
_wall_mesh = NodePath("WallMesh")
@@ -86,9 +131,26 @@ _scale = 0.01
[node name="FloorMesh" type="MeshInstance3D" parent="LevelMesh" unique_id=961663820]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.325726, -1.0841981, -12.307181)
material_override = SubResource("StandardMaterial3D_cm0pq")
mesh = SubResource("ImmediateMesh_fos0i")
mesh = SubResource("ImmediateMesh_03owx")
[node name="WallMesh" type="MeshInstance3D" parent="LevelMesh" unique_id=653175378]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.325726, -1.0841981, -12.307181)
material_override = SubResource("StandardMaterial3D_fos0i")
mesh = SubResource("ImmediateMesh_3dxm6")
mesh = SubResource("ImmediateMesh_wkp8b")
[node name="WallMesh_col" type="StaticBody3D" parent="LevelMesh/WallMesh" unique_id=141738477]
[node name="CollisionShape3D" type="CollisionShape3D" parent="LevelMesh/WallMesh/WallMesh_col" unique_id=1446575305]
shape = SubResource("ConcavePolygonShape3D_20pc6")
[node name="WallSegments" type="Node2D" parent="LevelMesh" unique_id=1390058976]
[node name="WallSegment" type="Line2D" parent="LevelMesh/WallSegments" unique_id=2053155144]
points = PackedVector2Array(710, 1017, 390, 1369)
script = ExtResource("7_trn2v")
[node name="ModPlayer" type="Node" parent="." unique_id=1374096575]
script = ExtResource("7_lgr22")
file = "res://mod211-headache.xm"
playing = true
metadata/_custom_type_script = "uid://djgd6mugw2s47"
@@ -0,0 +1,12 @@
##
## Godot Mod Player Plugin by arlez80 (Yui Kinomoto)
##
@tool
extends EditorPlugin
# Nothing to do, the main logic to expose this to the user
# is done via `class_name` in `ModPlayer.gd`.
func _get_plugin_name():
return "Godot Mod Player"
@@ -0,0 +1 @@
uid://bfmp165qm0qf
@@ -0,0 +1,271 @@
##
## MOD parser by あるる(きのもと 結衣) @arlez80
##
## MIT License
##
@warning_ignore_start("untyped_declaration")
@warning_ignore_start("unsafe_method_access")
@warning_ignore_start("unused_variable")
class_name Mod
const period_table:Array[int] = [
1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907,
856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113,
107, 101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57,
]
enum ModFlags {
LINEAR_FREQUENCY_TABLE = 1,
}
enum ModWaveFormType {
SINE_WAVEFORM = 0,
SAW_WAVEFORM = 1,
SQUARE_WAVEFORM = 2,
RAMDOM_WAVEFORM = 3,
REV_SAW_WAVEFORM = 4,
}
enum ModLoopType {
NO_LOOP = 0,
FORWARD_LOOP = 1,
PING_PONG_LOOP = 2,
}
class ModData:
var module_name:String
var tracker_name:String
var version:int
var flags:int = 0
var song_length:int
var unknown_number:int
var channel_count:int
var song_positions:PackedByteArray
var magic:String
var patterns:Array # ModPattern[][]
var instruments:Array[ModInstrument]
var init_tick:int = 6
var init_bpm:int = 125
var restart_position:int = 0
class ModPatternNote:
var key_number:int
var note:int
var instrument:int
var volume:int = 0
var effect_command:int
var effect_param:int
class ModInstrument:
var name:String
var samples:Array[ModSample]
var volume_envelope:ModEnvelope
var panning_envelope:ModEnvelope
var vibrato_type:ModWaveFormType = ModWaveFormType.SINE_WAVEFORM
var vibrato_speed:int = -1
var vibrato_depth:int = -1
var vibrato_depth_shift:int = -1
var volume_fadeout:int = -1
class ModSample:
var data:PackedByteArray
var name:String
var length:int
var loop_start:int
var loop_length:int
var volume:int
var finetune:int
var loop_type:int = ModLoopType.FORWARD_LOOP # set(ModLoopType)
var bit:int = 8 # 8 or 16
var panning:int = -1
var relative_note:int = 0
class ModEnvelope:
var points:Array[ModEnvelopePoint]
var point_count:int
var sustain_point:int
var loop_start_point:int
var loop_end_point:int
var enabled:bool
var sustain_enabled:bool
var loop_enabled:bool
func set_flag( f:int ):
self.enabled = ( f & 1 ) != 0
self.sustain_enabled = ( f & 2 ) != 0
self.loop_enabled = ( f & 4 ) != 0
class ModEnvelopePoint:
var frame:int
var value:int
class ModParseResult:
var error:int = OK
var data:ModData = null
func _init():
pass
## ファイルから読み込み
## @param path ファイルパス
## @return 読んだ Modファイルデータ
func read_file( path:String ) -> ModParseResult:
var result: = ModParseResult.new( )
var f: = FileAccess.open( path, FileAccess.READ )
if f.get_error( ) != OK:
result.error = f.get_error( )
return result
var stream:StreamPeerBuffer = StreamPeerBuffer.new( )
stream.set_data_array( f.get_buffer( f.get_length( ) ) )
stream.big_endian = true
result.data = self._read( stream )
return result
## 配列から読み込み
## @param data データ
## @return ModData
func read_data( data:PackedByteArray ) -> ModParseResult:
var stream:StreamPeerBuffer = StreamPeerBuffer.new( )
stream.set_data_array( data )
stream.big_endian = true
var result: = ModParseResult.new( )
result.data = self._read( stream )
return result
## ストリームから読み込み
## @param stream ストリーム
## @return 読んだ Modファイルデータ
func _read( stream:StreamPeerBuffer ) -> ModData:
var mod: = ModData.new( )
mod.module_name = self._read_string( stream, 20 )
mod.tracker_name = ""
mod.instruments = self._read_instruments( stream )
mod.song_length = stream.get_u8( )
mod.unknown_number = stream.get_u8( )
mod.song_positions = stream.get_partial_data( 128 )[1]
var max_song_position:int = 0
for sp in mod.song_positions:
if max_song_position < sp:
max_song_position = sp
mod.magic = self._read_string( stream, 4 )
var channel_count:int = 4
match mod.magic:
"6CHN":
channel_count = 6
"FLT8", "8CHN", "CD81", "OKTA":
channel_count = 8
"16CN":
channel_count = 16
"32CN":
channel_count = 32
_:
if mod.magic.substr( 2 ) == "CH":
channel_count = int( mod.magic )
# print( "Unknown magic" )
# breakpoint
pass
mod.channel_count = channel_count
mod.patterns = self._read_patterns( stream, max_song_position + 1, channel_count )
self._read_sample_data( stream, mod.instruments )
return mod
## 楽器データを読み込む
## @param stream ストリーム
## @return 楽器データ
func _read_instruments( stream:StreamPeerBuffer ) -> Array[ModInstrument]:
var instruments:Array[ModInstrument] = []
for i in range( 31 ):
var sample: = ModSample.new( )
sample.name = self._read_string( stream, 22 )
sample.length = stream.get_u16( ) * 2
var finetune:int = stream.get_u8( ) & 0x0F
if 0x08 < finetune:
finetune = finetune - 0x10
sample.finetune = finetune * 16
sample.volume = stream.get_u8( )
sample.loop_start = stream.get_u16( ) * 2
sample.loop_length = stream.get_u16( ) * 2
if sample.loop_length < 8:
sample.loop_type = ModLoopType.NO_LOOP
else:
sample.loop_type = ModLoopType.FORWARD_LOOP
var instrument: = ModInstrument.new( )
instrument.name = sample.name
instrument.samples = []
for k in range( 96 ):
instrument.samples.append( sample )
instrument.volume_envelope = ModEnvelope.new( )
instrument.volume_envelope.enabled = false
instrument.panning_envelope = ModEnvelope.new( )
instrument.panning_envelope.enabled = false
instruments.append( instrument )
return instruments
## パターンを読み込む
## @param stream ストリームデータ
## @param max_positions 最大パターン数
## @param channels 最大チャンネル数
## @return パターンデータ
func _read_patterns( stream:StreamPeerBuffer, max_position:int, channels:int ) -> Array: # Array of Array of Array of ModPatternNote
var patterns:Array = [] # Array of Array of Array of ModPatternNote
for position in ( max_position ):
var pattern:Array = [] # Array of Array of ModPatternNote
for i in range( 64 ):
var line:Array[ModPatternNote] = []
for ch in ( channels ):
var v1:int = stream.get_u16( )
var v2:int = stream.get_u16( )
var mod_pattern_note: = ModPatternNote.new( )
mod_pattern_note.instrument = ( ( v1 >> 8 ) & 0xF0 ) | ( ( v2 >> 12 ) & 0x0F )
mod_pattern_note.key_number = v1 & 0x0FFF
mod_pattern_note.effect_command = ( v2 >> 8 ) & 0x0F
mod_pattern_note.effect_param = v2 & 0x0FF
# TODO: 遅かったら二分探索にでもしませんか
if 0 < mod_pattern_note.key_number:
mod_pattern_note.note = 23
for k in period_table:
mod_pattern_note.note += 1
if k <= mod_pattern_note.key_number:
break
else:
mod_pattern_note.note = 0
line.append( mod_pattern_note )
pattern.append( line )
patterns.append( pattern )
return patterns
## 楽器のデータに基づき、波形を読み込む
## @param stream ストリーム
## @param instruments 波形を読み込む楽器データリスト
func _read_sample_data( stream:StreamPeerBuffer, instruments:Array[ModInstrument] ) -> void:
for instrument in instruments:
var sample:Mod.ModSample = instrument.samples[0]
if 0 < sample.length:
sample.data = stream.get_partial_data( sample.length )[1]
## 文字列の読み込み
## @param stream ストリーム
## @param size 文字列サイズ
## @return 読み込んだ文字列を返す
func _read_string( stream:StreamPeerBuffer, size:int ) -> String:
return stream.get_partial_data( size )[1].get_string_from_ascii( )
@@ -0,0 +1 @@
uid://ii8p1hyx5nbe
File diff suppressed because it is too large Load Diff
@@ -0,0 +1 @@
uid://djgd6mugw2s47
@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://x5sjwrimtdmi"]
[ext_resource type="Script" path="res://addons/modplayer/ModPlayer.gd" id="1"]
[node name="ModPlayer" type="Node"]
script = ExtResource("1")
@@ -0,0 +1,275 @@
##
## XM parser by あるる(きのもと 結衣) @arlez80
##
## This script required Mod.gd for declaring the data structures.
##
## MIT License
##
@warning_ignore_start("untyped_declaration")
@warning_ignore_start("unsafe_method_access")
@warning_ignore_start("unused_variable")
@warning_ignore_start("int_as_enum_without_cast")
@warning_ignore_start("return_value_discarded")
class_name XM
enum XMNoteFlags {
NOTE = 0x01,
INSTRUMENT = 0x02,
VOLUME = 0x04,
EFFECT_COMMAND = 0x08,
EFFECT_PARAM = 0x10,
FIRST_BYTE_AS_FLAGS = 0x80,
}
## ファイルから読み込む
## @param path ファイルパス
## @return xm
func read_file( path:String ) -> Mod.ModParseResult:
var result: = Mod.ModParseResult.new( )
var f: = FileAccess.open( path, FileAccess.READ )
if f.get_error( ) != OK:
result.error = f.get_error( )
return result
var stream:StreamPeerBuffer = StreamPeerBuffer.new( )
stream.set_data_array( f.get_buffer( f.get_length( ) ) )
result.data = self._read( stream )
if result.data == null:
result.error = ERR_PARSE_ERROR
return result
## 配列から読み込む
## @param data データ
## @return xm
func read_data( data:PackedByteArray ) -> Mod.ModParseResult:
var stream:StreamPeerBuffer = StreamPeerBuffer.new( )
stream.set_data_array( data )
var result: = Mod.ModParseResult.new( )
result.data = self._read( stream )
if result.data == null:
result.error = ERR_PARSE_ERROR
return result
## ストリームから読み込み
## @param stream ストリーム
## @return xm
func _read( stream:StreamPeerBuffer ) -> Mod.ModData:
var xm: = Mod.ModData.new( )
if self._read_string( stream, 17 ) != "Extended Module: ":
return null
xm.module_name = self._read_string( stream, 20 )
if stream.get_u8( ) != 0x1A:
return null
xm.tracker_name = self._read_string( stream, 20 )
xm.version = stream.get_u16( )
var header_size:int = stream.get_u32( )
xm.song_length = stream.get_u16( )
xm.restart_position = stream.get_u16( )
xm.channel_count = stream.get_u16( )
var pattern_count:int = stream.get_u16( )
var instrument_count:int = stream.get_u16( )
xm.flags = stream.get_u16( )
xm.init_tick = stream.get_u16( )
xm.init_bpm = stream.get_u16( )
xm.song_positions = stream.get_partial_data( header_size - 20 )[1]
xm.patterns = self._read_patterns( stream, xm.flags, pattern_count, xm.channel_count )
if len( xm.patterns ) == 0:
return null
xm.instruments = self._read_instruments( stream, instrument_count )
if len( xm.instruments ) == 0:
return null
return xm
## パターン読み込み
## @param stream ストリーム
## @param xm_file_flags XMデータに関するフラグ
## @param pattern_count パターン数
## @param channles 最大チャンネル数
## @return パターンデータ
func _read_patterns( stream:StreamPeerBuffer, xm_file_flags:int, pattern_count:int, channels:int ) -> Array: # Array of Array of Array of ModPatternNote
var patterns:Array = [] # Array of Array of Array of ModPatternNote
for i in ( pattern_count ):
var pattern:Array = [] # Array of Array of ModPatternNote
if stream.get_u32( ) != 9:
return []
if stream.get_u8( ) != 0:
return []
var row_count:int = stream.get_u16( )
var size:int = stream.get_u16( )
for k in ( row_count ):
var line:Array[Mod.ModPatternNote] = []
for ch in ( channels ):
var patr: = Mod.ModPatternNote.new( )
if 0 < size:
var first:int = stream.get_u8( )
size -= 1
if first & XMNoteFlags.FIRST_BYTE_AS_FLAGS != 0:
if first & XMNoteFlags.NOTE != 0:
patr.note = stream.get_u8( )
size -= 1
else:
patr.note = first
first = 0xFF
if 0 < patr.note:
patr.note -= 1
if first & XMNoteFlags.INSTRUMENT != 0:
patr.instrument = stream.get_u8( )
size -= 1
if first & XMNoteFlags.VOLUME != 0:
patr.volume = stream.get_u8( )
size -= 1
if first & XMNoteFlags.EFFECT_COMMAND != 0:
patr.effect_command = stream.get_u8( )
size -= 1
if first & XMNoteFlags.EFFECT_PARAM != 0:
patr.effect_param = stream.get_u8( )
size -= 1
if 0 < patr.note:
if xm_file_flags & Mod.ModFlags.LINEAR_FREQUENCY_TABLE != 0:
patr.key_number = self._conv_linear_freq( patr.note )
else:
patr.key_number = self._conv_amiga_freq( patr.note )
line.append( patr )
pattern.append( line )
patterns.append( pattern )
return patterns
## ノート番号からAMIGA式で周波数計算する
## @param note ノート番号
## @return 周波数
func _conv_amiga_freq( note:int ) -> int:
return int( 6848.0 / pow( 2.0, note / 12.0 ) )
## ノート番号から線形で周波数計算する
## @param note ノート番号
## @return 周波数
func _conv_linear_freq( note:int ) -> int:
return 7680 - note * 64
## 楽器データを読み込む
## @param stream ストリーム
## @param instrument_count 楽器数
## @return 楽器データ
func _read_instruments( stream:StreamPeerBuffer, instrument_count:int ) -> Array[Mod.ModInstrument]:
var instruments:Array[Mod.ModInstrument] = []
for i in ( instrument_count ):
var inst: = Mod.ModInstrument.new( )
var size:int = stream.get_u32( )
var remain_size:int = size
inst.name = self._read_string( stream, 22 )
#print( "%d/%d %s" % [ i, instrument_count, inst.name] )
var instrument_type:int = stream.get_u8( )
if instrument_type != 0:
# 0以外のやつもいるらしいので無視
#return []
pass
var sample_count:int = stream.get_u16( )
var sample_numbers:Array = []
remain_size -= 4 + 22 + 1 + 2
if 0 < sample_count:
var sample_header_size:int = stream.get_u32( )
sample_numbers = stream.get_partial_data( 96 )[1]
inst.volume_envelope = Mod.ModEnvelope.new( )
for k in range( 12 ):
var ve: = Mod.ModEnvelopePoint.new( )
ve.frame = stream.get_u16( )
ve.value = stream.get_u16( )
inst.volume_envelope.points.append( ve )
inst.panning_envelope = Mod.ModEnvelope.new( )
for k in range( 12 ):
var pe: = Mod.ModEnvelopePoint.new( )
pe.frame = stream.get_u16( )
pe.value = stream.get_u16( )
inst.panning_envelope.points.append( pe )
remain_size -= 4 + 96 + 48 + 48
inst.volume_envelope.point_count = stream.get_u8( )
inst.panning_envelope.point_count = stream.get_u8( )
inst.volume_envelope.sustain_point = stream.get_u8( )
inst.volume_envelope.loop_start_point = stream.get_u8( )
inst.volume_envelope.loop_end_point = stream.get_u8( )
inst.panning_envelope.sustain_point = stream.get_u8( )
inst.panning_envelope.loop_start_point = stream.get_u8( )
inst.panning_envelope.loop_end_point = stream.get_u8( )
inst.volume_envelope.set_flag( stream.get_u8( ) )
inst.panning_envelope.set_flag( stream.get_u8( ) )
inst.vibrato_type = stream.get_u8( )
inst.vibrato_speed = stream.get_u8( )
inst.vibrato_depth = stream.get_u8( )
inst.vibrato_depth_shift = stream.get_u8( )
inst.volume_fadeout = stream.get_u16( )
remain_size -= 16
if 0 < remain_size:
stream.get_partial_data( remain_size ) # reserved
if 0 < sample_count:
var sounds:Array[Mod.ModSample] = []
# Sound Header
for k in ( sample_count ):
var xms: = Mod.ModSample.new( )
xms.length = stream.get_u32( )
xms.loop_start = stream.get_u32( )
xms.loop_length = stream.get_u32( )
xms.volume = stream.get_u8( )
xms.finetune = stream.get_8( )
xms.loop_type = stream.get_u8( )
if xms.loop_type & 16 != 0:
xms.bit = 16
xms.loop_type &= 3
xms.panning = stream.get_u8( )
xms.relative_note = stream.get_8( )
stream.get_u8( ) # Reserved
xms.name = self._read_string( stream, 22 )
sounds.append( xms )
# Sound Data
for xms in sounds:
var d:Array[int] = []
var p:int = 0
if xms.bit == 16:
for k in ( xms.length >> 1 ):
p += stream.get_16( )
d.append( p & 0xFF )
d.append( ( p >> 8 ) & 0xFF )
else:
for k in ( xms.length ):
p += stream.get_8( )
d.append( p & 0xFF )
xms.data = PackedByteArray( d )
inst.samples = []
for k in sample_numbers:
if len( sounds ) <= k:
inst.samples.append( sounds[0] )
else:
inst.samples.append( sounds[k] )
instruments.append( inst )
return instruments
## 文字列の読み込み
## @param stream ストリーム
## @param size 文字列サイズ
## @return 読み込んだ文字列を返す
func _read_string( stream:StreamPeerBuffer, size:int ) -> String:
return stream.get_partial_data( size )[1].get_string_from_ascii( )
@@ -0,0 +1 @@
uid://cmuxvykwoxljq
Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

@@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ba4eaiuaq67p"
path="res://.godot/imported/icon.png-1b6fd777bf08247b7c845db8b9125613.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://godot-mod-player-g4-master/addons/modplayer/icon.png"
dest_files=["res://.godot/imported/icon.png-1b6fd777bf08247b7c845db8b9125613.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
@@ -0,0 +1,6 @@
[plugin]
name="Godot Mod Player"
description="A plugin that playing Mod Files for Godot Engine."
author="arlez80"
version="4.3.0"
script="GMP.gd"
+37 -4
View File
@@ -32,25 +32,29 @@ func _prepare_polygons() -> void:
var polys := Geometry2D.triangulate_delaunay(polygon)
var pickled := Array()
for i in polys.size() / 3:
pickled.push_front(PackedInt32Array([polys[i * 3 + 0], polys[i * 3 + 1], polys[i * 3 + 2]]))
pickled.push_back(PackedInt32Array([polys[i * 3 + 0], polys[i * 3 + 1], polys[i * 3 + 2]]))
polygons = pickled
_fix_acute_polygons()
_fix_polygons()
func _fix_acute_polygons() -> void:
func _fix_polygons() -> void:
# Outside triangles are in reversed winding, find and eliminate.
var new := Array()
for poly in polygons as Array[PackedInt32Array]:
var ab := polygon[poly[1]] - polygon[poly[0]]
var ac := polygon[poly[2]] - polygon[poly[0]]
if (ab.x * ac.y - ab.y * ac.x) * 0.5 <= 0:
new.push_front(poly)
# Fix winding as well.
new.push_back(PackedInt32Array([poly[2],poly[1],poly[0]]))
polygons = new
func _prepare_mesh() -> void:
_prepare_floor_mesh()
_prepare_wall_mesh()
_prepare_floor_collision()
_prepare_wall_collision()
func _prepare_floor_mesh() -> void:
@@ -76,6 +80,7 @@ func _prepare_floor_mesh() -> void:
_floor_mesh.mesh = m
# TODO: Make last segment UV stretch to edge, tiling it.
func _prepare_wall_mesh() -> void:
var m := ImmediateMesh.new()
m.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
@@ -121,3 +126,31 @@ func _prepare_wall_mesh() -> void:
ndy = rng.randf_range(-1.0, 1.0)
m.surface_end()
_wall_mesh.mesh = m
func _prepare_floor_collision() -> void:
if _floor_mesh.get_node_or_null("FloorMesh_col"):
_floor_mesh.remove_child(_floor_mesh.get_node("FloorMesh_col"))
_floor_mesh.create_convex_collision()
(_floor_mesh.get_node("FloorMesh_col") as StaticBody3D).set_collision_layer_value(2, 1)
func _prepare_wall_collision() -> void:
if _wall_mesh.get_node_or_null("WallMesh_col"):
_wall_mesh.remove_child(_wall_mesh.get_node("WallMesh_col"))
_wall_mesh.create_trimesh_collision()
_wall_mesh.get_node("WallMesh_col").get_node("CollisionShape3D").shape.backface_collision = true
(_wall_mesh.get_node("WallMesh_col") as StaticBody3D).set_collision_layer_value(3, 1)
#var shape := ConcavePolygonShape3D.new()
#shape.backface_collision = true
#var faces := PackedVector3Array()
#for ld in polygon.size():
#var nd := (ld + 1) % polygon.size()
#faces.push_back(Vector3(polygon[ld].x * _scale, 0, polygon[ld].y * _scale))
#faces.push_back(Vector3(polygon[nd].x * _scale, 0, polygon[nd].y * _scale))
#faces.push_back(Vector3(polygon[ld].x * _scale, 5, polygon[ld].y * _scale))
#faces.push_back(Vector3(polygon[nd].x * _scale, 0, polygon[nd].y * _scale))
#faces.push_back(Vector3(polygon[nd].x * _scale, 5, polygon[nd].y * _scale))
#faces.push_back(Vector3(polygon[ld].x * _scale, 5, polygon[ld].y * _scale))
#shape.set_faces(faces)
#(_wall_mesh.get_node("Area3D").get_node("CollisionShape3D") as CollisionShape3D).shape = shape
+61
View File
@@ -0,0 +1,61 @@
extends Node3D
var _rotation_target_x : Vector3
var _rotation_target_y : Vector3
@export var _cam : Camera3D
@export var _ray : RayCast3D
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
_rotation_target_y = self.rotation
_rotation_target_x = _cam.rotation
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
# TODO: Interpolation.
# TODO: Hiding/Popping animation.
func _physics_process(_delta: float) -> void:
var wmark := get_parent_node_3d().get_node("WallMark") as Sprite3D
var fmark := get_parent_node_3d().get_node("FloorMark") as Sprite3D
# Walls.
if _ray.is_colliding() and (_ray.get_collider() as StaticBody3D).get_collision_layer_value(3):
var normflat := Vector3(_ray.get_collision_normal().x, 0, _ray.get_collision_normal().z)
var posflat := Vector3(_ray.get_collision_point().x, 0, _ray.get_collision_point().z)
wmark.look_at_from_position(posflat, posflat + normflat, Vector3.UP)
wmark.position = posflat + normflat
wmark.show()
else:
wmark.hide()
# Floor.
if _ray.is_colliding() and (_ray.get_collider() as StaticBody3D).get_collision_layer_value(2):
var posflat := Vector3(_ray.get_collision_point().x, 0, _ray.get_collision_point().z)
fmark.position = posflat
fmark.show()
else:
fmark.hide()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
self.rotation.y = lerp_angle(_rotation_target_y.y, _rotation_target_y.y, 1.0 - exp(-30 * delta))
_cam.rotation.x = lerp_angle(_cam.rotation.x, _rotation_target_x.x, 1.0 - exp(-20 * delta))
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
var motion := event as InputEventMouseMotion
var preserve := rotation
rotation = _rotation_target_y
self.rotate_y(deg_to_rad(motion.relative.x) * -0.25)
_rotation_target_y = rotation
rotation = preserve
preserve = _cam.rotation
_cam.rotate_x(deg_to_rad(motion.relative.y) * -0.2)
var camera_rot := _cam.rotation_degrees
camera_rot.x = clamp(camera_rot.x, -30, 30)
_cam.rotation_degrees = camera_rot
_rotation_target_x = _cam.rotation
_cam.rotation = preserve
+1
View File
@@ -0,0 +1 @@
uid://dtqv683r772sd
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+41
View File
@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cqisk1m0in4a4"
path.s3tc="res://.godot/imported/shield.png-bdf8e401b772eb7c90cb1fa4b7e06cd1.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://shield.png"
dest_files=["res://.godot/imported/shield.png-bdf8e401b772eb7c90cb1fa4b7e06cd1.s3tc.ctex"]
[params]
compress/mode=2
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=true
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=0
+15
View File
@@ -0,0 +1,15 @@
@tool
extends Line2D
var _id : int
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
pass
+1
View File
@@ -0,0 +1 @@
uid://cc2rv3wnwas52