├── godot ├── .gitignore ├── assets │ ├── cpp.png │ ├── zig.png │ ├── csharp.png │ ├── fish1.png │ ├── fish2.png │ ├── ground.png │ ├── rust.png │ ├── swift.png │ ├── wavy2.png │ ├── wavy3.png │ ├── water.gdshader │ ├── cpp.png.import │ ├── zig.png.import │ ├── rust.png.import │ ├── fish1.png.import │ ├── fish2.png.import │ ├── swift.png.import │ ├── wavy2.png.import │ ├── wavy3.png.import │ ├── csharp.png.import │ ├── ground.png.import │ └── ground.tres ├── bin │ ├── zig.gdextension │ ├── rust.gdextension │ ├── swift.gdextension │ └── cpp.gdextension ├── score.gd ├── CSharpShipper.csproj ├── project.godot ├── CSharpShipper.sln ├── export_presets.cfg ├── player.gd ├── CSharpShip.cs ├── scenery.gd ├── main.gd └── main.tscn ├── assets ├── csharp-image-from-ms.png └── rusty-rust-logo-512x512.png ├── .gitignore ├── swift ├── .gitignore ├── Tests │ └── GdSwiftTests │ │ └── GdSwiftTests.swift ├── Package.resolved ├── Package.swift └── Sources │ └── SwiftShipper │ └── SwiftShipper.swift ├── .config └── dotnet-tools.json ├── .gitmodules ├── .clang-format ├── cpp ├── src │ ├── lib.rs │ ├── register_types.h │ ├── gdexample.h │ ├── register_types.cpp │ └── gdexample.cpp └── SConstruct ├── rust ├── Cargo.toml ├── src │ └── lib.rs └── Cargo.lock ├── README.md └── zig ├── src ├── root.zig └── ZigShip.zig ├── build.zig.zon └── build.zig /godot/.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | -------------------------------------------------------------------------------- /godot/assets/cpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/cpp.png -------------------------------------------------------------------------------- /godot/assets/zig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/zig.png -------------------------------------------------------------------------------- /godot/assets/csharp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/csharp.png -------------------------------------------------------------------------------- /godot/assets/fish1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/fish1.png -------------------------------------------------------------------------------- /godot/assets/fish2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/fish2.png -------------------------------------------------------------------------------- /godot/assets/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/ground.png -------------------------------------------------------------------------------- /godot/assets/rust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/rust.png -------------------------------------------------------------------------------- /godot/assets/swift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/swift.png -------------------------------------------------------------------------------- /godot/assets/wavy2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/wavy2.png -------------------------------------------------------------------------------- /godot/assets/wavy3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/godot/assets/wavy3.png -------------------------------------------------------------------------------- /assets/csharp-image-from-ms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/assets/csharp-image-from-ms.png -------------------------------------------------------------------------------- /assets/rusty-rust-logo-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/contextfreecode/gdext/HEAD/assets/rusty-rust-logo-512x512.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | exports/ 2 | extension_api.json 3 | godot-cpp/ 4 | *.os 5 | .sconsign.dblite 6 | *.so 7 | target/ 8 | zig-cache/ 9 | zig-out/ 10 | 11 | 12 | # Added by cargo 13 | 14 | /target 15 | -------------------------------------------------------------------------------- /swift/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "csharpier": { 6 | "version": "0.27.3", 7 | "commands": [ 8 | "dotnet-csharpier" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "zig/godot-zig"] 2 | path = zig/godot-zig 3 | url = git@github.com:godot-zig/godot-zig.git 4 | [submodule "cpp/godot-cpp"] 5 | path = cpp/godot-cpp 6 | url = https://github.com/godotengine/godot-cpp 7 | branch = 4.2 8 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | AlignAfterOpenBracket: BlockIndent 4 | AlignOperands: DontAlign 5 | BreakBeforeTernaryOperators: false 6 | IndentCaseLabels: true 7 | IndentWidth: 4 8 | LambdaBodyIndentation: OuterScope 9 | PointerAlignment: Left 10 | -------------------------------------------------------------------------------- /cpp/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub fn add(left: usize, right: usize) -> usize { 2 | left + right 3 | } 4 | 5 | #[cfg(test)] 6 | mod tests { 7 | use super::*; 8 | 9 | #[test] 10 | fn it_works() { 11 | let result = add(2, 2); 12 | assert_eq!(result, 4); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /godot/bin/zig.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | compatibility_minimum = "4.2.0" 4 | entry_symbol = "my_extension_init" 5 | 6 | [libraries] 7 | 8 | linux.debug.x86_64 = "res://../zig/zig-out/lib/libzigshipper.so" 9 | linux.release.x86_64 = "res://../zig/zig-out/lib/libzigshipper.so" 10 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustshipper" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib"] # Compile this crate to a dynamic C library. 8 | 9 | [dependencies] 10 | godot = { git = "https://github.com/godot-rust/gdext", branch = "master" } 11 | -------------------------------------------------------------------------------- /godot/bin/rust.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "gdext_rust_init" 4 | compatibility_minimum = "4.2" 5 | 6 | [libraries] 7 | 8 | linux.debug.x86_64 = "res://../rust/target/debug/librustshipper.so" 9 | linux.release.x86_64 = "res://../rust/target/release/librustshipper.so" 10 | -------------------------------------------------------------------------------- /godot/bin/swift.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "swift_entry_point" 4 | compatibility_minimum = "4.2" 5 | 6 | [libraries] 7 | 8 | linux.debug.x86_64 = "res://../swift/.build/debug/libSwiftShipper.so" 9 | linux.release.x86_64 = "res://../swift/.build/release/libSwiftShipper.so" 10 | -------------------------------------------------------------------------------- /cpp/src/register_types.h: -------------------------------------------------------------------------------- 1 | #ifndef GDEXAMPLE_REGISTER_TYPES_H 2 | #define GDEXAMPLE_REGISTER_TYPES_H 3 | 4 | #include 5 | 6 | void initialize_example_module(godot::ModuleInitializationLevel p_level); 7 | void uninitialize_example_module(godot::ModuleInitializationLevel p_level); 8 | 9 | #endif // GDEXAMPLE_REGISTER_TYPES_H 10 | -------------------------------------------------------------------------------- /godot/score.gd: -------------------------------------------------------------------------------- 1 | extends Label 2 | 3 | 4 | # Called when the node enters the scene tree for the first time. 5 | func _ready(): 6 | text = "" 7 | 8 | 9 | # Called every frame. 'delta' is the elapsed time since the previous frame. 10 | func _process(delta): 11 | pass 12 | 13 | 14 | func _on_main_ship_attacked(): 15 | score += 1 16 | text = " Score %s " % score 17 | 18 | 19 | var score := 0 20 | -------------------------------------------------------------------------------- /swift/Tests/GdSwiftTests/GdSwiftTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import GdSwift 3 | 4 | final class GdSwiftTests: XCTestCase { 5 | func testExample() throws { 6 | // XCTest Documentation 7 | // https://developer.apple.com/documentation/xctest 8 | 9 | // Defining Test Cases and Test Methods 10 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /godot/CSharpShipper.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net6.0 4 | net7.0 5 | net8.0 6 | true 7 | CSharpShipper 8 | 9 | -------------------------------------------------------------------------------- /godot/assets/water.gdshader: -------------------------------------------------------------------------------- 1 | shader_type canvas_item; 2 | 3 | uniform vec4 bottom_color : source_color; 4 | uniform vec4 top_color : source_color; 5 | 6 | void vertex() { 7 | } 8 | 9 | void fragment() { 10 | float depth = UV.y; 11 | COLOR = (1.0 - depth) * top_color + depth * bottom_color; 12 | } 13 | 14 | //void light() { 15 | // Called for every pixel for every light affecting the CanvasItem. 16 | // Uncomment to replace the default light processing function with this one. 17 | //} 18 | -------------------------------------------------------------------------------- /swift/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "originHash" : "cd7839f50a3f5590b93c4296a9153236a666ad5c3718927b684eea679ec7b270", 3 | "pins" : [ 4 | { 5 | "identity" : "swift-syntax", 6 | "kind" : "remoteSourceControl", 7 | "location" : "https://github.com/apple/swift-syntax", 8 | "state" : { 9 | "revision" : "fa8f95c2d536d6620cc2f504ebe8a6167c9fc2dd", 10 | "version" : "510.0.1" 11 | } 12 | }, 13 | { 14 | "identity" : "swiftgodot", 15 | "kind" : "remoteSourceControl", 16 | "location" : "https://github.com/migueldeicaza/SwiftGodot", 17 | "state" : { 18 | "branch" : "main", 19 | "revision" : "7c34297bc676b37dbb7b0a53c2d334aa2a1bfcdf" 20 | } 21 | } 22 | ], 23 | "version" : 3 24 | } 25 | -------------------------------------------------------------------------------- /godot/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Shipper" 14 | run/main_scene="res://main.tscn" 15 | config/features=PackedStringArray("4.2", "C#", "GL Compatibility") 16 | 17 | [display] 18 | 19 | window/size/viewport_width=1280 20 | window/size/viewport_height=720 21 | window/stretch/mode="canvas_items" 22 | 23 | [dotnet] 24 | 25 | project/assembly_name="CSharpShipper" 26 | 27 | [rendering] 28 | 29 | renderer/rendering_method="gl_compatibility" 30 | renderer/rendering_method.mobile="gl_compatibility" 31 | -------------------------------------------------------------------------------- /godot/assets/cpp.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cf3ihs80fach" 6 | path="res://.godot/imported/cpp.png-e074533e814f9363698e971e704fb787.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/cpp.png" 14 | dest_files=["res://.godot/imported/cpp.png-e074533e814f9363698e971e704fb787.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/zig.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cjyu6rjcjglum" 6 | path="res://.godot/imported/zig.png-6a37e53e3405112d6834977c66e87cc8.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/zig.png" 14 | dest_files=["res://.godot/imported/zig.png-6a37e53e3405112d6834977c66e87cc8.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/rust.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bc746y2bkxphn" 6 | path="res://.godot/imported/rust.png-46f6faf2a7c01f2d56cba481fe3449f1.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/rust.png" 14 | dest_files=["res://.godot/imported/rust.png-46f6faf2a7c01f2d56cba481fe3449f1.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/fish1.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://da60o1w7cedfc" 6 | path="res://.godot/imported/fish1.png-1377768c2b10dbaec29e2bbeb375ccf6.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/fish1.png" 14 | dest_files=["res://.godot/imported/fish1.png-1377768c2b10dbaec29e2bbeb375ccf6.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/fish2.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://divpm8ilegavo" 6 | path="res://.godot/imported/fish2.png-792a68da13ace066e8dc17eec0f86d42.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/fish2.png" 14 | dest_files=["res://.godot/imported/fish2.png-792a68da13ace066e8dc17eec0f86d42.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/swift.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://d4fr8e0ijooen" 6 | path="res://.godot/imported/swift.png-c4e3cf49a89d6981572a224b9f128f4d.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/swift.png" 14 | dest_files=["res://.godot/imported/swift.png-c4e3cf49a89d6981572a224b9f128f4d.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/wavy2.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://7sfe1m4rrd57" 6 | path="res://.godot/imported/wavy2.png-a176304db4f3f44cb06644c12f1d980a.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/wavy2.png" 14 | dest_files=["res://.godot/imported/wavy2.png-a176304db4f3f44cb06644c12f1d980a.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/wavy3.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://wbuw2i11u4sg" 6 | path="res://.godot/imported/wavy3.png-38b6aa4f7709806c8ee8e168fe50507a.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/wavy3.png" 14 | dest_files=["res://.godot/imported/wavy3.png-38b6aa4f7709806c8ee8e168fe50507a.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /cpp/src/gdexample.h: -------------------------------------------------------------------------------- 1 | #ifndef GDEXAMPLE_H 2 | #define GDEXAMPLE_H 3 | 4 | #include 5 | 6 | namespace shipper { 7 | 8 | enum class State { 9 | Wait, 10 | Enter, 11 | Turn, 12 | Exit, 13 | }; 14 | 15 | class CppShip : public godot::Node2D { 16 | GDCLASS(CppShip, godot::Node2D) 17 | 18 | private: 19 | double speed = 500.0; 20 | 21 | godot::Node2D* sprite; 22 | godot::Vector2 start; 23 | State state = State::Wait; 24 | godot::Node2D* target; 25 | 26 | protected: 27 | static void _bind_methods(); 28 | 29 | public: 30 | CppShip(); 31 | ~CppShip(); 32 | 33 | void attack(double ship_y, double target_x, double target_y); 34 | double get_speed() const; 35 | void set_speed(const double p_speed); 36 | 37 | void _process(double delta) override; 38 | void _ready() override; 39 | }; 40 | 41 | } // namespace shipper 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /godot/assets/csharp.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dop8x0tb7s627" 6 | path="res://.godot/imported/csharp.png-546455a244ceb51077723638ad082115.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/csharp.png" 14 | dest_files=["res://.godot/imported/csharp.png-546455a244ceb51077723638ad082115.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /godot/assets/ground.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://duk10thql43ef" 6 | path="res://.godot/imported/ground.png-328d82a69941a655cdd4638d3455ed11.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://assets/ground.png" 14 | dest_files=["res://.godot/imported/ground.png-328d82a69941a655cdd4638d3455ed11.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Some things I did, or at least similar to things I did. I don't have all steps 2 | here, though. 3 | 4 | ``` 5 | pip install scons 6 | mkdir gdext 7 | cd gdext/ 8 | git init 9 | git clone -b 4.2 https://github.com/godotengine/godot-cpp 10 | godot --headless --dump-extension-api 11 | echo godot-cpp/ >> .gitignore 12 | echo extension_api.json >> .gitignore 13 | cd godot-cpp/ 14 | time scons platform=linux custom_api_file=../extension_api.json 15 | # Add cpp source files and gdextension file. 16 | cd .. 17 | time scons platform=linux 18 | clang-format -i src/*.cpp src/*.h 19 | ``` 20 | 21 | ``` 22 | mkdir swift 23 | cd swifth 24 | swift package init --type library --name GdSwift 25 | swift build --configuration release 26 | # cp .build/release/lib*.so ../demo/bin/ 27 | # Manually copied libSwiftGodot.so to export dir. 28 | # TODO Put it in bin after all? 29 | ``` 30 | 31 | ``` 32 | cargo init --lib 33 | # modify file per instructions 34 | cargo build --release 35 | ``` 36 | -------------------------------------------------------------------------------- /cpp/SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | env = SConscript("godot-cpp/SConstruct") 6 | 7 | # For reference: 8 | # - CCFLAGS are compilation flags shared between C and C++ 9 | # - CFLAGS are for C-specific compilation flags 10 | # - CXXFLAGS are for C++-specific compilation flags 11 | # - CPPFLAGS are for pre-processor flags 12 | # - CPPDEFINES are for pre-processor defines 13 | # - LINKFLAGS are for linking flags 14 | 15 | # tweak this if you want to use different folders, or more folders, to store your source code in. 16 | env.Append(CPPPATH=["src/"]) 17 | sources = Glob("src/*.cpp") 18 | 19 | if env["platform"] == "macos": 20 | library = env.SharedLibrary( 21 | "demo/bin/libcppshipper.{}.{}.framework/libcppshipper.{}.{}".format( 22 | env["platform"], env["target"], env["platform"], env["target"] 23 | ), 24 | source=sources, 25 | ) 26 | else: 27 | library = env.SharedLibrary( 28 | "bin/libcppshipper{}{}".format(env["suffix"], env["SHLIBSUFFIX"]), 29 | source=sources, 30 | ) 31 | 32 | Default(library) 33 | -------------------------------------------------------------------------------- /swift/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.10 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "SwiftShipper", 8 | products: [ 9 | // Products define the executables and libraries a package produces, making them visible to other packages. 10 | .library( 11 | name: "SwiftShipper", 12 | type: .dynamic, 13 | targets: ["SwiftShipper"]), 14 | ], 15 | dependencies: [ 16 | .package(url: "https://github.com/migueldeicaza/SwiftGodot", branch: "main") 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package, defining a module or a test suite. 20 | // Targets can depend on other targets in this package and products from dependencies. 21 | .target( 22 | name: "SwiftShipper", 23 | dependencies: ["SwiftGodot"]), 24 | .testTarget( 25 | name: "SwiftShipperTests", 26 | dependencies: ["SwiftShipper"]), 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /godot/CSharpShipper.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 2012 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpShipper", "CSharpShipper.csproj", "{349D21C6-18CD-460B-A086-B7831BAC5A7B}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Any CPU = Debug|Any CPU 8 | ExportDebug|Any CPU = ExportDebug|Any CPU 9 | ExportRelease|Any CPU = ExportRelease|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {349D21C6-18CD-460B-A086-B7831BAC5A7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {349D21C6-18CD-460B-A086-B7831BAC5A7B}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {349D21C6-18CD-460B-A086-B7831BAC5A7B}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU 15 | {349D21C6-18CD-460B-A086-B7831BAC5A7B}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU 16 | {349D21C6-18CD-460B-A086-B7831BAC5A7B}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU 17 | {349D21C6-18CD-460B-A086-B7831BAC5A7B}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /godot/export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Linux/X11" 4 | platform="Linux/X11" 5 | runnable=true 6 | dedicated_server=false 7 | custom_features="" 8 | export_filter="all_resources" 9 | include_filter="" 10 | exclude_filter="" 11 | export_path="exports/Shipper.x86_64" 12 | encryption_include_filters="" 13 | encryption_exclude_filters="" 14 | encrypt_pck=false 15 | encrypt_directory=false 16 | 17 | [preset.0.options] 18 | 19 | custom_template/debug="" 20 | custom_template/release="" 21 | debug/export_console_wrapper=1 22 | binary_format/embed_pck=true 23 | texture_format/bptc=true 24 | texture_format/s3tc=true 25 | texture_format/etc=false 26 | texture_format/etc2=false 27 | binary_format/architecture="x86_64" 28 | ssh_remote_deploy/enabled=false 29 | ssh_remote_deploy/host="user@host_ip" 30 | ssh_remote_deploy/port="22" 31 | ssh_remote_deploy/extra_args_ssh="" 32 | ssh_remote_deploy/extra_args_scp="" 33 | ssh_remote_deploy/run_script="#!/usr/bin/env bash 34 | export DISPLAY=:0 35 | unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" 36 | \"{temp_dir}/{exe_name}\" {cmd_args}" 37 | ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash 38 | kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") 39 | rm -rf \"{temp_dir}\"" 40 | dotnet/include_scripts_content=false 41 | dotnet/include_debug_symbols=true 42 | dotnet/embed_build_outputs=false 43 | -------------------------------------------------------------------------------- /cpp/src/register_types.cpp: -------------------------------------------------------------------------------- 1 | #include "register_types.h" 2 | 3 | #include "gdexample.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace g = godot; 10 | 11 | void initialize_example_module(g::ModuleInitializationLevel p_level) { 12 | if (p_level != g::MODULE_INITIALIZATION_LEVEL_SCENE) { 13 | return; 14 | } 15 | 16 | g::ClassDB::register_class(); 17 | } 18 | 19 | void uninitialize_example_module(g::ModuleInitializationLevel p_level) { 20 | if (p_level != g::MODULE_INITIALIZATION_LEVEL_SCENE) { 21 | return; 22 | } 23 | } 24 | 25 | extern "C" { 26 | // Initialization. 27 | GDExtensionBool GDE_EXPORT example_library_init( 28 | GDExtensionInterfaceGetProcAddress p_get_proc_address, 29 | const GDExtensionClassLibraryPtr p_library, 30 | GDExtensionInitialization* r_initialization 31 | ) { 32 | g::GDExtensionBinding::InitObject init_obj( 33 | p_get_proc_address, p_library, r_initialization 34 | ); 35 | 36 | init_obj.register_initializer(initialize_example_module); 37 | init_obj.register_terminator(uninitialize_example_module); 38 | init_obj.set_minimum_library_initialization_level( 39 | g::MODULE_INITIALIZATION_LEVEL_SCENE 40 | ); 41 | 42 | return init_obj.init(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /godot/bin/cpp.gdextension: -------------------------------------------------------------------------------- 1 | [configuration] 2 | 3 | entry_symbol = "example_library_init" 4 | compatibility_minimum = "4.2" 5 | 6 | [libraries] 7 | 8 | linux.debug.x86_64 = "res://../cpp/bin/libcppshipper.linux.template_debug.x86_64.so" 9 | linux.release.x86_64 = "res://../cpp/bin/libcppshipper.linux.template_release.x86_64.so" 10 | 11 | macos.debug = "res://bin/libcppshipper.macos.template_debug.framework" 12 | macos.release = "res://bin/libcppshipper.macos.template_release.framework" 13 | windows.debug.x86_32 = "res://bin/libcppshipper.windows.template_debug.x86_32.dll" 14 | windows.release.x86_32 = "res://bin/libcppshipper.windows.template_release.x86_32.dll" 15 | windows.debug.x86_64 = "res://bin/libcppshipper.windows.template_debug.x86_64.dll" 16 | windows.release.x86_64 = "res://bin/libcppshipper.windows.template_release.x86_64.dll" 17 | linux.debug.arm64 = "res://bin/libcppshipper.linux.template_debug.arm64.so" 18 | linux.release.arm64 = "res://bin/libcppshipper.linux.template_release.arm64.so" 19 | linux.debug.rv64 = "res://bin/libcppshipper.linux.template_debug.rv64.so" 20 | linux.release.rv64 = "res://bin/libcppshipper.linux.template_release.rv64.so" 21 | android.debug.x86_64 = "res://bin/libcppshipper.android.template_debug.x86_64.so" 22 | android.release.x86_64 = "res://bin/libcppshipper.android.template_release.x86_64.so" 23 | android.debug.arm64 = "res://bin/libcppshipper.android.template_debug.arm64.so" 24 | android.release.arm64 = "res://bin/libcppshipper.android.template_release.arm64.so" 25 | -------------------------------------------------------------------------------- /godot/player.gd: -------------------------------------------------------------------------------- 1 | class_name Player 2 | extends Area2D 3 | 4 | @export var speed := 550.0 5 | 6 | 7 | func _ready(): 8 | var ref := get_tree().root.get_node("Main/Bounds") as ReferenceRect 9 | bounds_min = ref.get_rect().position 10 | bounds_max = ref.get_rect().size + bounds_min 11 | var extent := read_sprite_frames() 12 | bounds_max -= extent 13 | bounds_min += extent 14 | #print("bounds: ", bounds) 15 | 16 | 17 | func _process(delta: float): 18 | var animation_speed = 1.0 19 | var velocity := Vector2.ZERO 20 | if Input.is_action_pressed("ui_up"): 21 | velocity = Vector2.UP 22 | elif Input.is_action_pressed("ui_down"): 23 | velocity = Vector2.DOWN 24 | elif Input.is_action_pressed("ui_left"): 25 | velocity = Vector2.LEFT 26 | elif Input.is_action_pressed("ui_right"): 27 | animation_speed = 2.0 28 | velocity = Vector2.RIGHT 29 | sprite.play("swim", animation_speed) 30 | if velocity.length() > 0: 31 | position += velocity * speed * delta 32 | # Bound things. 33 | position.x = max(position.x, bounds_min.x) 34 | position.y = max(position.y, bounds_min.y) 35 | position.x = min(position.x, bounds_max.x) 36 | position.y = min(position.y, bounds_max.y) 37 | 38 | 39 | func read_sprite_frames() -> Vector2: 40 | var frames := sprite.sprite_frames as SpriteFrames 41 | var anim := sprite.animation as StringName 42 | var size_x := 0.0 43 | var size_y := 0.0 44 | for index in range(0, frames.get_frame_count(anim)): 45 | var frame := frames.get_frame_texture(anim, index) 46 | size_x = max(size_x, frame.get_width()) 47 | size_y = max(size_y, frame.get_height()) 48 | return Vector2(size_x / 2, size_y / 2) 49 | 50 | 51 | var bounds_max: Vector2 52 | var bounds_min: Vector2 53 | @onready var sprite := $Sprite 54 | -------------------------------------------------------------------------------- /zig/src/root.zig: -------------------------------------------------------------------------------- 1 | const Godot = @import("Godot"); 2 | const builtin = @import("builtin"); 3 | const std = @import("std"); 4 | const testing = std.testing; 5 | 6 | const GDE = Godot.GDE; 7 | const GPA = std.heap.GeneralPurposeAllocator(.{}); 8 | 9 | pub export fn my_extension_init( 10 | p_get_proc_address: GDE.GDExtensionInterfaceGetProcAddress, 11 | p_library: GDE.GDExtensionClassLibraryPtr, 12 | r_initialization: [*c]GDE.GDExtensionInitialization, 13 | ) callconv(.C) GDE.GDExtensionBool { 14 | r_initialization.*.initialize = initializeLevel; 15 | r_initialization.*.deinitialize = deinitializeLevel; 16 | r_initialization.*.minimum_initialization_level = GDE.GDEXTENSION_INITIALIZATION_SCENE; 17 | // Allocator 18 | var allocator: std.mem.Allocator = undefined; 19 | if (builtin.mode == .Debug) { 20 | var gpa = std.heap.c_allocator.create(GPA) catch unreachable; 21 | gpa.* = GPA{}; 22 | r_initialization.*.userdata = @ptrCast(@alignCast(gpa)); 23 | allocator = gpa.allocator(); 24 | } else { 25 | allocator = std.heap.c_allocator; 26 | } 27 | // Init and done 28 | Godot.init(p_get_proc_address.?, p_library, allocator) catch unreachable; 29 | return 1; 30 | } 31 | 32 | fn initializeLevel(_: ?*anyopaque, p_level: GDE.GDExtensionInitializationLevel) callconv(.C) void { 33 | if (p_level != GDE.GDEXTENSION_INITIALIZATION_SCENE) { 34 | return; 35 | } 36 | const ZigShip = @import("ZigShip.zig"); 37 | ZigShip.register(); 38 | } 39 | 40 | fn deinitializeLevel(userdata: ?*anyopaque, p_level: GDE.GDExtensionInitializationLevel) callconv(.C) void { 41 | if (p_level != GDE.GDEXTENSION_INITIALIZATION_CORE) { 42 | return; 43 | } 44 | Godot.deinit(); 45 | if (builtin.mode == .Debug) { 46 | var gpa = @as(*GPA, @ptrCast(@alignCast(userdata.?))); 47 | _ = gpa.deinit(); 48 | std.heap.c_allocator.destroy(gpa); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /swift/Sources/SwiftShipper/SwiftShipper.swift: -------------------------------------------------------------------------------- 1 | import SwiftGodot 2 | 3 | #initSwiftExtension(cdecl: "swift_entry_point", types: [SwiftShip.self]) 4 | 5 | @Godot 6 | class SwiftShip: Node2D { 7 | @Export(.range, "0,2000,100") 8 | var speed: Double = 500.0 9 | 10 | #signal("attack_finished", arguments: ["node": Node.self]) 11 | 12 | @Callable 13 | public func attack(ship_x: Double, target_x: Double, target_y: Double) { 14 | if state != .wait { return } 15 | state = .enter; 16 | // TODO Interpret args. 17 | } 18 | 19 | public override func _ready () { 20 | sprite = (getNode(path: "Sprite") as! Node2D) 21 | target = (getNode(path: "Target") as! Node2D) 22 | } 23 | 24 | public override func _process(delta: Double) { 25 | var position = sprite!.position 26 | if state == .wait { 27 | start = position 28 | } 29 | let targetPos = target!.position 30 | let oldState = state; 31 | state = switch state { 32 | case .wait: state 33 | case .enter: position.y > targetPos.y ? .exit : state 34 | case .exit: position.y < start.y ? .wait : state 35 | } 36 | let direction = (targetPos - start).normalized() 37 | let move = switch state { 38 | case .wait: Vector2.zero 39 | case .enter: direction 40 | case .exit: Vector2(x: direction.x, y: -direction.y) 41 | } 42 | position += move * delta * speed 43 | if state == .wait { 44 | if state != oldState { 45 | emit(signal: SwiftShip.attackFinished, self) 46 | } 47 | position = start 48 | } 49 | sprite!.position = position 50 | } 51 | 52 | var sprite = nil as Node2D? 53 | var start = Vector2() 54 | var state = State.wait 55 | var target = nil as Node2D? 56 | } 57 | 58 | enum State { 59 | case wait 60 | case enter 61 | case exit 62 | } 63 | -------------------------------------------------------------------------------- /godot/CSharpShip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Godot; 3 | 4 | public partial class CSharpShip : Node2D 5 | { 6 | [Export(PropertyHint.Range, "0,2000,100")] 7 | public float Speed = 500; 8 | 9 | [Signal] 10 | public delegate void attack_finishedEventHandler(Node node); 11 | 12 | public void attack(double ship_y, double target_x, double target_y) 13 | { 14 | if (state != State.Wait) return; 15 | state = State.Top; 16 | // TODO Interpret args. 17 | } 18 | 19 | public override void _Ready() 20 | { 21 | sprite = GetNode("Sprite"); 22 | target = GetNode("Target"); 23 | } 24 | 25 | public override void _Process(double delta) 26 | { 27 | var move = Speed * (float)delta; 28 | if (state == State.Wait) 29 | { 30 | start = sprite.Position; 31 | } 32 | var oldState = state; 33 | state = state switch 34 | { 35 | State.Top when sprite.Position.X > target.Position.X => State.Right, 36 | State.Right when sprite.Position.Y > target.Position.Y => State.Bottom, 37 | State.Bottom when sprite.Position.X < target.Position.X / 2 => State.Left, 38 | State.Left when sprite.Position.Y < -200 => State.Wait, 39 | _ => state, 40 | }; 41 | sprite.Position += 42 | move 43 | * state switch 44 | { 45 | State.Wait => Vector2.Zero, 46 | State.Top => Vector2.Right, 47 | State.Right => Vector2.Down, 48 | State.Bottom => Vector2.Left, 49 | State.Left => Vector2.Up, 50 | }; 51 | if (state == State.Wait) 52 | { 53 | if (oldState != state) 54 | { 55 | EmitSignal(SignalName.attack_finished, this); 56 | } 57 | sprite.Position = start; 58 | } 59 | } 60 | 61 | private Node2D sprite; 62 | private Vector2 start; 63 | private State state = State.Wait; 64 | private Node2D target; 65 | 66 | private enum State 67 | { 68 | Wait, 69 | Top, 70 | Right, 71 | Bottom, 72 | Left, 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /zig/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = "zig", 3 | // This is a [Semantic Version](https://semver.org/). 4 | // In a future version of Zig it will be used for package deduplication. 5 | .version = "0.0.0", 6 | 7 | // This field is optional. 8 | // This is currently advisory only; Zig does not yet do anything 9 | // with this value. 10 | //.minimum_zig_version = "0.11.0", 11 | 12 | // This field is optional. 13 | // Each dependency must either provide a `url` and `hash`, or a `path`. 14 | // `zig build --fetch` can be used to fetch all dependencies of a package, recursively. 15 | // Once all dependencies are fetched, `zig build` no longer requires 16 | // internet connectivity. 17 | .dependencies = .{ 18 | // See `zig fetch --save ` for a command-line interface for adding dependencies. 19 | //.example = .{ 20 | // // When updating this field to a new URL, be sure to delete the corresponding 21 | // // `hash`, otherwise you are communicating that you expect to find the old hash at 22 | // // the new URL. 23 | // .url = "https://example.com/foo.tar.gz", 24 | // 25 | // // This is computed from the file contents of the directory of files that is 26 | // // obtained after fetching `url` and applying the inclusion rules given by 27 | // // `paths`. 28 | // // 29 | // // This field is the source of truth; packages do not come from a `url`; they 30 | // // come from a `hash`. `url` is just one of many possible mirrors for how to 31 | // // obtain a package matching this `hash`. 32 | // // 33 | // // Uses the [multihash](https://multiformats.io/multihash/) format. 34 | // .hash = "...", 35 | // 36 | // // When this is provided, the package is found in a directory relative to the 37 | // // build root. In this case the package's hash is irrelevant and therefore not 38 | // // computed. This field and `url` are mutually exclusive. 39 | // .path = "foo", 40 | //}, 41 | }, 42 | 43 | // Specifies the set of files and directories that are included in this package. 44 | // Only files and directories listed here are included in the `hash` that 45 | // is computed for this package. 46 | // Paths are relative to the build root. Use the empty string (`""`) to refer to 47 | // the build root itself. 48 | // A directory listed here means that all files within, recursively, are included. 49 | .paths = .{ 50 | // This makes *all* files, recursively, included in this package. It is generally 51 | // better to explicitly list the files and directories instead, to insure that 52 | // fetching from tarballs, file system paths, and version control all result 53 | // in the same contents hash. 54 | "", 55 | // For example... 56 | //"build.zig", 57 | //"build.zig.zon", 58 | //"src", 59 | //"LICENSE", 60 | //"README.md", 61 | }, 62 | } 63 | -------------------------------------------------------------------------------- /cpp/src/gdexample.cpp: -------------------------------------------------------------------------------- 1 | #include "gdexample.h" 2 | #include 3 | #include 4 | 5 | namespace g = godot; 6 | 7 | namespace shipper { 8 | 9 | void CppShip::_bind_methods() { 10 | // Attack 11 | g::ClassDB::bind_method( 12 | g::D_METHOD("attack", "ship_y", "target_x", "target_y"), 13 | &CppShip::attack 14 | ); 15 | // Position changed 16 | ADD_SIGNAL(g::MethodInfo( 17 | "attack_finished", g::PropertyInfo(g::Variant::OBJECT, "node") 18 | )); 19 | // Speed 20 | g::ClassDB::bind_method(g::D_METHOD("get_speed"), &CppShip::get_speed); 21 | g::ClassDB::bind_method( 22 | g::D_METHOD("set_speed", "p_speed"), &CppShip::set_speed 23 | ); 24 | g::ClassDB::add_property( 25 | "CppShip", 26 | g::PropertyInfo( 27 | g::Variant::FLOAT, "speed", g::PROPERTY_HINT_RANGE, "0,2000,100" 28 | ), 29 | "set_speed", "get_speed" 30 | ); 31 | } 32 | 33 | CppShip::CppShip() {} 34 | 35 | CppShip::~CppShip() { 36 | // Add your cleanup here. 37 | } 38 | 39 | void CppShip::attack(double ship_y, double target_x, double target_y) { 40 | if (state != State::Wait) return; 41 | state = State::Enter; 42 | // TODO Interpret args. 43 | } 44 | 45 | double CppShip::get_speed() const { return speed; } 46 | 47 | void CppShip::set_speed(const double p_speed) { speed = p_speed; } 48 | 49 | void CppShip::_process(double delta) { 50 | if (g::Engine::get_singleton()->is_editor_hint()) { 51 | return; 52 | } 53 | auto position = sprite->get_position(); 54 | auto target = this->target->get_position(); 55 | if (state == State::Wait) { 56 | start = position; 57 | } 58 | auto old_state = state; 59 | state = ([this, position, target]() { 60 | switch (state) { 61 | case State::Enter: 62 | return position.x < target.x ? State::Turn : state; 63 | case State::Turn: 64 | return position.x > target.x ? State::Exit : state; 65 | case State::Exit: 66 | return position.x > start.x ? State::Wait : state; 67 | default: 68 | return state; 69 | } 70 | })(); 71 | position += speed * delta * ([this, position, target]() { 72 | switch (state) { 73 | case State::Enter: 74 | return g::Vector2(-1, 0); 75 | case State::Turn: { 76 | auto center = g::Vector2(target.x, 0.5 * (start.y + target.y)); 77 | auto offset = position - center; 78 | auto angle = std::atan2(offset.y, offset.x); 79 | return g::Vector2(std::sin(angle), -std::cos(angle)); 80 | } 81 | case State::Exit: 82 | return g::Vector2(1, 0); 83 | default: 84 | return g::Vector2(0, 0); 85 | } 86 | })(); 87 | if (state == State::Wait) { 88 | if (old_state != state) { 89 | emit_signal("attack_finished", this); 90 | } 91 | position = start; 92 | } 93 | sprite->set_position(position); 94 | } 95 | 96 | void CppShip::_ready() { 97 | if (g::Engine::get_singleton()->is_editor_hint()) { 98 | return; 99 | } 100 | sprite = get_node(g::NodePath("Sprite")); 101 | start = sprite->get_position(); 102 | target = get_node(g::NodePath("Target")); 103 | } 104 | 105 | } // namespace shipper 106 | -------------------------------------------------------------------------------- /rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | use godot::prelude::*; 2 | 3 | struct MyExtension; 4 | 5 | #[gdextension] 6 | unsafe impl ExtensionLibrary for MyExtension {} 7 | 8 | #[derive(GodotClass)] 9 | #[class(base=Node2D)] 10 | struct RustShip { 11 | #[export(range=(0.0, 2000.0, 100.0))] 12 | speed: f32, 13 | base: Base, 14 | sprite: Option>, 15 | start: Vector2, 16 | state: State, 17 | target: Option>, 18 | } 19 | 20 | #[godot_api] 21 | impl RustShip { 22 | #[func] 23 | fn attack(&mut self, ship_y: f64, target_x: f64, target_y: f64) { 24 | if self.state != State::Wait { 25 | return; 26 | } 27 | self.state = State::Enter; 28 | // TODO Interpret args. 29 | } 30 | 31 | #[signal] 32 | fn attack_finished(node: Gd); 33 | } 34 | 35 | #[godot_api] 36 | impl INode2D for RustShip { 37 | fn init(base: Base) -> Self { 38 | // godot_print!("rust init"); 39 | Self { 40 | speed: 500f32, 41 | base, 42 | sprite: None, 43 | start: Vector2::ZERO, 44 | state: State::Wait, 45 | target: None, 46 | } 47 | } 48 | 49 | fn physics_process(&mut self, delta: f64) { 50 | let view_rect = self.base().get_viewport().unwrap().get_visible_rect(); 51 | let sprite = self.sprite.as_mut().unwrap(); 52 | let target = self.target.as_mut().unwrap().get_position(); 53 | let position = sprite.get_position(); 54 | let old_state = self.state; 55 | if self.state == State::Wait { 56 | self.start = position; 57 | } 58 | self.state = match self.state { 59 | State::Enter if position.x > target.x => State::Up, 60 | State::Up if position.x < target.x => State::Down, 61 | State::Down if position.x > target.x => State::Exit, 62 | State::Exit if position.x > view_rect.size.x + 200f32 => State::Wait, 63 | _ => self.state, 64 | }; 65 | let distance = self.speed * delta as f32; 66 | let position = position 67 | + distance 68 | * match self.state { 69 | State::Wait => Vector2::ZERO, 70 | State::Enter => Vector2::RIGHT, 71 | State::Up | State::Down => { 72 | let mid_y = (self.start.y + target.y) / 2f32; 73 | let center = Vector2::new(target.x, mid_y); 74 | let angle = (position - center).angle(); 75 | Vector2::new(angle.sin(), -angle.cos()) 76 | } 77 | State::Exit => Vector2::RIGHT, 78 | }; 79 | let position = match () { 80 | _ if self.state == State::Wait => self.start, 81 | _ => position, 82 | }; 83 | sprite.set_position(position); 84 | if self.state == State::Wait && self.state != old_state { 85 | let other_self = self.base().clone(); 86 | self.base_mut() 87 | .emit_signal("attack_finished".into(), &[Variant::from(other_self)]); 88 | } 89 | } 90 | 91 | fn ready(&mut self) { 92 | // godot_print!("rust ready"); 93 | self.sprite = Some( 94 | self.base() 95 | .get_node("Sprite".into()) 96 | .unwrap() 97 | .cast::(), 98 | ); 99 | self.target = Some( 100 | self.base() 101 | .get_node("Target".into()) 102 | .unwrap() 103 | .cast::(), 104 | ); 105 | } 106 | } 107 | 108 | #[derive(Clone, Copy, PartialEq)] 109 | enum State { 110 | Wait, 111 | Enter, 112 | Up, 113 | Down, 114 | Exit, 115 | } 116 | -------------------------------------------------------------------------------- /godot/scenery.gd: -------------------------------------------------------------------------------- 1 | class_name Scenery 2 | extends Node2D 3 | 4 | 5 | @export_range(100, 1000, 50) var speed := 400.0 6 | 7 | 8 | func prep_info(info_: Info): 9 | info = info_ 10 | print("prep_info: ", name, ", ", info_) 11 | 12 | 13 | # Called when the node enters the scene tree for the first time. 14 | func _ready(): 15 | var coords_array := tile_map.get_used_cells(0) 16 | last_tile_coords = coords_array.max() 17 | viewport_size = get_viewport_rect().size 18 | print(last_tile_coords, ": ", tile_map.map_to_local(last_tile_coords)) 19 | for kid in get_children(): 20 | if kid is Sprite2D: 21 | last_sprite_x = max(last_sprite_x, kid.position.x) 22 | 23 | 24 | # Called every frame. 'delta' is the elapsed time since the previous frame. 25 | func _process(delta): 26 | position.x -= delta * speed 27 | var viewport_right := viewport_size.x - position.x 28 | if last_sprite_x < viewport_right + gen_x: 29 | print("ha: ", last_sprite_x, " vs ", viewport_right + gen_x) 30 | place_sprite(max(viewport_right, last_sprite_x) + 300) 31 | var last_tile_x := tile_map.map_to_local(last_tile_coords).x 32 | if last_tile_x < viewport_right + gen_x: 33 | print("hi: ", last_tile_x, " vs ", viewport_right) 34 | place_tile() 35 | # TODO Extend scenery. Clean up old. 36 | #tile_map.get_cell_tile_data() 37 | if position.x < -reset_x: 38 | reset_scenery() 39 | 40 | 41 | func place_sprite(min_x: float): 42 | var refs := info.sprite_info.refs 43 | var ref := refs[info.rng.randi_range(0, refs.size() - 1)] 44 | var sprite := ref.duplicate() as Sprite2D 45 | var x = info.rng.randf_range(min_x, min_x + 1200) 46 | var scale := info.rng.randf_range( 47 | info.sprite_info.min_scale, info.sprite_info.max_scale 48 | ) 49 | sprite.scale = Vector2(scale, scale) 50 | var y := info.sprite_info.bottom - sprite.get_rect().end.y * scale 51 | sprite.position = Vector2(x, y) 52 | print("bottom: ", info.sprite_info.bottom, ", ", sprite.get_rect(), ", ", sprite.position) 53 | last_sprite_x = x 54 | add_child(sprite) 55 | move_child(sprite, 0) 56 | 57 | 58 | func place_tile(): 59 | var current := tile_map.get_cell_atlas_coords(0, last_tile_coords) 60 | var nexts: Array[Vector2i] = info.tile_info.nexts[current] 61 | var next_index := info.rng.randi_range(0, nexts.size() - 1) 62 | var next_tile = nexts[next_index] 63 | last_tile_coords = Vector2i(last_tile_coords.x + 1, last_tile_coords.y) 64 | tile_map.set_cell(0, last_tile_coords, 0, next_tile) 65 | 66 | 67 | func reset_scenery(): 68 | reset_sprites() 69 | # Changes position.x!!! 70 | reset_tiles() 71 | 72 | 73 | func reset_sprites(): 74 | for kid in get_children(): 75 | if kid is Sprite2D: 76 | kid.position.x -= reset_x 77 | if kid.position.x < -gen_x: 78 | kid.queue_free() 79 | print("free: ", kid, ", ", kid.position.x) 80 | last_sprite_x -= reset_x 81 | 82 | 83 | func reset_tiles(): 84 | var from := start_tile() 85 | position.x += reset_x 86 | var to := start_tile() 87 | var tile_width := tile_map.tile_set.tile_size.x 88 | # The +1 and many other things in the script are slop on my part. 89 | # I haven't worked out perfect logic. 90 | var needed := ceili(viewport_size.x / float(tile_width)) + 1 91 | for i in range(0, needed): 92 | last_tile_coords = Vector2i(to.x + i, to.y) 93 | tile_map.set_cell( 94 | 0, last_tile_coords, 95 | 0, tile_map.get_cell_atlas_coords(0, Vector2i(from.x + i, to.y)), 96 | ) 97 | 98 | 99 | func start_tile() -> Vector2i: 100 | return tile_map.local_to_map(Vector2(-position.x, viewport_size.y)) 101 | 102 | 103 | var gen_x := 200.0 104 | var info: Info 105 | var last_sprite_x := -INF 106 | var last_tile_coords: Vector2i 107 | var reset_x := 2000.0 108 | @onready var tile_map: TileMap = $TileMap 109 | var viewport_size: Vector2i 110 | 111 | 112 | class Info: 113 | var rng: RandomNumberGenerator 114 | var sprite_info: SpriteInfo 115 | var tile_info: TileInfo 116 | 117 | 118 | class SpriteInfo: 119 | var bottom := -INF 120 | var max_scale := -INF 121 | var min_scale := INF 122 | var refs: Array[Sprite2D] 123 | 124 | 125 | class TileInfo: 126 | var nexts: Dictionary # Vector2i, Array[Vector2i] 127 | -------------------------------------------------------------------------------- /godot/main.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal ship_attacked 4 | 5 | 6 | func _ready(): 7 | var scenery_info = Scenery.Info.new() 8 | var rng := RandomNumberGenerator.new() 9 | rng.seed = 1337 10 | scenery_info.rng = rng 11 | scenery_info.sprite_info = read_sprites() 12 | scenery_info.tile_info = read_tiles() 13 | get_tree().call_group("scenery", "prep_info", scenery_info) 14 | for node in get_tree().get_nodes_in_group("ship"): 15 | node.connect("attack_finished", _on_ship_attack_finished) 16 | waiting_ships.append(node) 17 | schedule_attacks(rng) 18 | 19 | 20 | func _process(delta: float): 21 | if zig_sprite.position.x > zig_sprite_old_x: 22 | zig_ship.emit_signal(&"attack_finished", zig_ship) 23 | zig_sprite_old_x = zig_sprite.position.x 24 | 25 | 26 | func read_sprites() -> Scenery.SpriteInfo: 27 | var info := Scenery.SpriteInfo.new() 28 | var nodes := get_tree().get_nodes_in_group("scenery") 29 | var refs := {} # String, Sprite 30 | for node in nodes: 31 | for kid in node.get_children(): 32 | if kid is Sprite2D: 33 | var path := kid.texture.resource_path as String 34 | var scale := kid.scale.x as float 35 | var end: Vector2 = kid.get_rect().end * kid.scale + kid.position 36 | info.bottom = max(info.bottom, end.y) 37 | info.min_scale = min(info.min_scale, scale) 38 | info.max_scale = max(info.max_scale, scale) 39 | print(kid.name, ": ", scale, ", ", path, ", ", kid.position, ", ", kid.get_rect(), ", ", end) 40 | if path not in info.refs: 41 | refs[path] = kid.duplicate() 42 | info.refs.assign(refs.values()) 43 | print(info.refs) 44 | print(info.min_scale, ", ", info.max_scale) 45 | return info 46 | 47 | 48 | func read_tiles() -> Scenery.TileInfo: 49 | var info := Scenery.TileInfo.new() 50 | var tile_map := $Ground/TileMap as TileMap 51 | var tile_set := tile_map.tile_set 52 | var source := tile_set.get_source(0) as TileSetAtlasSource 53 | for i in range(0, source.get_tiles_count()): 54 | var tile_id := source.get_tile_id(i) 55 | #var alt := source.get_alternative_tile_id(i) 56 | var region := source.get_tile_texture_region(tile_id, 0) 57 | print(tile_id, ": ", region) 58 | var coords_array := tile_map.get_used_cells(0) 59 | coords_array.sort() 60 | var last := Vector2i.ZERO 61 | for coords in coords_array: 62 | var data := tile_map.get_cell_tile_data(0, coords) 63 | var atlas_coords := tile_map.get_cell_atlas_coords(0, coords) 64 | var current_nexts := \ 65 | info.nexts.get(last, [] as Array[Vector2i]) as Array[Vector2i] 66 | if last != Vector2i.ZERO and atlas_coords not in current_nexts: 67 | current_nexts.append(atlas_coords) 68 | info.nexts[last] = current_nexts 69 | #data.set_custom_data() 70 | #print(coords, ": ", atlas_coords, ", ", last, ", ", current_nexts) 71 | #tile_map.set_cell(0, coords) 72 | last = atlas_coords 73 | print(info.nexts) 74 | return info 75 | 76 | 77 | func _on_player_area_entered(area: Area2D): 78 | var parent := area.get_parent() 79 | if &"ship" in parent.get_groups(): 80 | animation_player.play("fade") 81 | get_tree().paused = true 82 | 83 | 84 | # The "null" default is for testing emit without args. 85 | func _on_ship_attack_finished(node: Node = null): 86 | print("Ship finished: ", node) 87 | 88 | 89 | func schedule_attacks(rng: RandomNumberGenerator): 90 | while true: 91 | await get_tree().create_timer(rng.randf_range(0.0, 1.0)).timeout 92 | if waiting_ships.is_empty(): 93 | if finished_ships.is_empty(): 94 | continue 95 | waiting_ships.append_array(finished_ships) 96 | finished_ships.clear() 97 | var index := rng.randi_range(0, waiting_ships.size() - 1) 98 | var ship := waiting_ships.pop_at(index) as Node 99 | ship.attack(0.0, 0.0, 0.0) 100 | ship_attacked.emit() 101 | await wait_for_ship(ship) 102 | 103 | 104 | func wait_for_ship(ship: Node): 105 | await ship.attack_finished 106 | finished_ships.append(ship) 107 | 108 | 109 | var finished_ships: Array[Node] 110 | var waiting_ships: Array[Node] 111 | var zig_sprite_old_x := INF 112 | 113 | @onready var animation_player := $AnimationPlayer as AnimationPlayer 114 | 115 | # Work around trouble sending signals from Zig. 116 | @onready var zig_ship = $Actors/Ships/ZigShip 117 | @onready var zig_sprite = $Actors/Ships/ZigShip/Sprite 118 | -------------------------------------------------------------------------------- /zig/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | // Although this function looks imperative, note that its job is to 4 | // declaratively construct a build graph that will be executed by an external 5 | // runner. 6 | pub fn build(b: *std.Build) void { 7 | // Standard target options allows the person running `zig build` to choose 8 | // what target to build for. Here we do not override the defaults, which 9 | // means any target is allowed, and the default is native. Other options 10 | // for restricting supported target set are available. 11 | const target = b.standardTargetOptions(.{}); 12 | 13 | // Standard optimization options allow the person running `zig build` to select 14 | // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not 15 | // set a preferred release mode, allowing the user to decide how to optimize. 16 | const optimize = b.standardOptimizeOption(.{}); 17 | 18 | const lib = b.addSharedLibrary(.{ 19 | .name = "zigshipper", 20 | // In this case the main source file is merely a path, however, in more 21 | // complicated build scripts, this could be a generated file. 22 | .root_source_file = .{ .path = "src/root.zig" }, 23 | .target = target, 24 | .optimize = optimize, 25 | }); 26 | lib.linkLibC(); 27 | 28 | const godot = b.addModule("Godot", .{ 29 | .root_source_file = .{ .path = "godot-zig/src/api/Godot.zig" }, 30 | }); 31 | godot.addIncludePath(.{ .path = "godot-zig/src/api" }); 32 | lib.root_module.addImport("Godot", godot); 33 | 34 | // This declares intent for the library to be installed into the standard 35 | // location when the user invokes the "install" step (the default step when 36 | // running `zig build`). 37 | b.installArtifact(lib); 38 | 39 | // const exe = b.addExecutable(.{ 40 | // .name = "zig", 41 | // .root_source_file = .{ .path = "src/main.zig" }, 42 | // .target = target, 43 | // .optimize = optimize, 44 | // }); 45 | 46 | // // This declares intent for the executable to be installed into the 47 | // // standard location when the user invokes the "install" step (the default 48 | // // step when running `zig build`). 49 | // b.installArtifact(exe); 50 | 51 | // // This *creates* a Run step in the build graph, to be executed when another 52 | // // step is evaluated that depends on it. The next line below will establish 53 | // // such a dependency. 54 | // const run_cmd = b.addRunArtifact(exe); 55 | 56 | // // By making the run step depend on the install step, it will be run from the 57 | // // installation directory rather than directly from within the cache directory. 58 | // // This is not necessary, however, if the application depends on other installed 59 | // // files, this ensures they will be present and in the expected location. 60 | // run_cmd.step.dependOn(b.getInstallStep()); 61 | 62 | // // This allows the user to pass arguments to the application in the build 63 | // // command itself, like this: `zig build run -- arg1 arg2 etc` 64 | // if (b.args) |args| { 65 | // run_cmd.addArgs(args); 66 | // } 67 | 68 | // // This creates a build step. It will be visible in the `zig build --help` menu, 69 | // // and can be selected like this: `zig build run` 70 | // // This will evaluate the `run` step rather than the default, which is "install". 71 | // const run_step = b.step("run", "Run the app"); 72 | // run_step.dependOn(&run_cmd.step); 73 | 74 | // // Creates a step for unit testing. This only builds the test executable 75 | // // but does not run it. 76 | // const lib_unit_tests = b.addTest(.{ 77 | // .root_source_file = .{ .path = "src/root.zig" }, 78 | // .target = target, 79 | // .optimize = optimize, 80 | // }); 81 | 82 | // const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); 83 | 84 | // const exe_unit_tests = b.addTest(.{ 85 | // .root_source_file = .{ .path = "src/main.zig" }, 86 | // .target = target, 87 | // .optimize = optimize, 88 | // }); 89 | 90 | // const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); 91 | 92 | // // Similar to creating the run step earlier, this exposes a `test` step to 93 | // // the `zig build --help` menu, providing a way for the user to request 94 | // // running the unit tests. 95 | // const test_step = b.step("test", "Run unit tests"); 96 | // test_step.dependOn(&run_lib_unit_tests.step); 97 | // test_step.dependOn(&run_exe_unit_tests.step); 98 | } 99 | -------------------------------------------------------------------------------- /zig/src/ZigShip.zig: -------------------------------------------------------------------------------- 1 | const Godot = @import("Godot"); 2 | const Vector2 = Godot.Vector2; 3 | 4 | const Self = @This(); 5 | 6 | pub usingnamespace Godot.Node2D; 7 | godot_object: *Godot.Node2D, 8 | 9 | speed: f32 = 500, 10 | 11 | sprite: *Godot.Node2D = undefined, 12 | state: State = .wait, 13 | start: Vector2 = @splat(0), 14 | target: *Godot.Node2D = undefined, 15 | 16 | pub fn attack(self: *Self, ship_y: f64, target_x: f64, target_y: f64) void { 17 | if (self.state != State.wait) return; 18 | self.state = State.enter; 19 | // TODO Interpret args. 20 | _ = ship_y; 21 | _ = target_x; 22 | _ = target_y; 23 | } 24 | 25 | pub fn _physics_process(self: *Self, delta: f64) void { 26 | if (Godot.Engine.getSingleton().is_editor_hint()) return; 27 | var position = self.sprite.get_position(); 28 | if (self.state == .wait) self.start = position; 29 | const target = self.target.get_position(); 30 | const exit = target[0] / 2; 31 | const end = -200; 32 | const old_state = self.state; 33 | self.state = switch (self.state) { 34 | .wait => self.state, 35 | .enter => if (position[0] < target[0]) .zag else self.state, 36 | .zag => if (position[0] < exit) .exit else self.state, 37 | .exit => if (position[0] < end) .wait else self.state, 38 | }; 39 | const distance: Vector2 = @splat(@as(f32, @floatCast(delta)) * self.speed); 40 | position += distance * switch (self.state) { 41 | .wait => Vector2{ 0, 0 }, 42 | .enter => Godot.normalized(target - self.start), 43 | .zag => Godot.normalized(Vector2{ 44 | exit - target[0], 45 | self.start[1] - target[1], 46 | }), 47 | .exit => Godot.normalized(Vector2{ 48 | end - exit, 49 | target[1] - self.start[1], 50 | }), 51 | }; 52 | if (self.state == .wait) { 53 | // _ = old_state; 54 | if (self.state != old_state) { 55 | _ = self.emit_signal_self(attack_finished_signal); 56 | } 57 | position = self.start; 58 | } 59 | self.sprite.set_position(position); 60 | } 61 | 62 | pub fn _ready(self: *Self) void { 63 | if (Godot.Engine.getSingleton().is_editor_hint()) return; 64 | // Sprite 65 | var sprite_path = Godot.NodePath.initFromString("Sprite"); 66 | defer sprite_path.deinit(); 67 | self.sprite = @ptrCast(self.get_node(sprite_path)); 68 | // Target 69 | var target_path = Godot.NodePath.initFromString("Target"); 70 | defer target_path.deinit(); 71 | self.target = @ptrCast(self.get_node(target_path)); 72 | _ = self.emit_signal_self(attack_finished_signal); 73 | } 74 | 75 | const State = enum { 76 | wait, 77 | enter, 78 | zag, 79 | exit, 80 | }; 81 | 82 | var attack_finished_signal: Godot.StringName = undefined; 83 | 84 | pub fn register() void { 85 | Godot.registerClass(Self); 86 | Godot.registerMethod(Self, "attack"); 87 | attack_finished_signal = Godot.StringName.initFromString( 88 | Godot.String.initFromUtf8Chars("attack_finished"), 89 | ); 90 | const node_name = Godot.StringName.initFromString( 91 | Godot.String.initFromUtf8Chars("node"), 92 | ); 93 | const attack_finished_property = GDE.GDExtensionPropertyInfo{ 94 | .type = @intCast(GDE.GDEXTENSION_VARIANT_TYPE_OBJECT), 95 | .name = @ptrCast(@constCast(&node_name)), 96 | .class_name = Godot.getClassName(Godot.Node), 97 | .hint = Godot.GlobalEnums.PROPERTY_HINT_NONE, 98 | .hint_string = @ptrCast(@constCast(&String.init())), 99 | .usage = Godot.GlobalEnums.PROPERTY_USAGE_NONE, 100 | }; 101 | Godot.classdbRegisterExtensionClassSignal( 102 | Godot.p_library, 103 | Godot.getClassName(Self), 104 | &attack_finished_signal, 105 | &attack_finished_property, 106 | 1, 107 | ); 108 | // TODO Deinit which things where? 109 | // object_str = Godot.String.initFromUtf8Chars("Object"); 110 | const emit_signal_str = Godot.StringName.initFromString( 111 | Godot.String.initFromUtf8Chars("emit_signal"), 112 | ); 113 | emit_signal_method = Godot.classdbGetMethodBind( 114 | Godot.getClassName(Object), 115 | &emit_signal_str, 116 | // Hash copied from object.cpp Object::emit_signal_internal 117 | 4047867050, 118 | ); 119 | } 120 | 121 | const GDE = Godot.GDE; 122 | // var object_str: Godot.String = undefined; 123 | // var emit_signal_str: Godot.StringName = undefined; 124 | var emit_signal_method: GDE.GDExtensionMethodBindPtr = undefined; 125 | 126 | const GlobalEnums = Godot.GlobalEnums; 127 | const Object = Godot.Object; 128 | const String = Godot.String; 129 | const StringName = Godot.StringName; 130 | 131 | // Modified from: Object.zig: pub fn emit_signal(self: anytype, signal_: anytype) GlobalEnums.Error 132 | pub fn emit_signal_self(self: *Self, signal_: anytype) GlobalEnums.Error { 133 | var result: GlobalEnums.Error = @import("std").mem.zeroes(GlobalEnums.Error); 134 | var ret: Godot.Variant = undefined; 135 | var signal_name: StringName = undefined; 136 | // TODO Probably can recombine String and StringName cases. 137 | if (@TypeOf(signal_) == StringName) { 138 | signal_name = signal_; 139 | } else if (@TypeOf(signal_) == String) { 140 | signal_name = StringName.initFromString(signal_); 141 | } else { 142 | signal_name = StringName.initFromLatin1Chars(@as([*c]const u8, &signal_[0])); 143 | } 144 | // TODO Maybe `Variant.init` is wrong for objects? 145 | // TODO See constructor `Variant::Variant(const Object *v)` 146 | const name_arg = Godot.Variant.init(*Godot.StringName, &signal_name); 147 | const self_arg = Godot.Variant.init(*Godot.Node2D, self.godot_object); 148 | const args = [_]GDE.GDExtensionConstVariantPtr{ &name_arg, &self_arg }; 149 | Godot.objectMethodBindCall( 150 | emit_signal_method, 151 | @ptrCast(self.godot_object), 152 | &args, 153 | args.len, 154 | &ret, 155 | @ptrCast(&result), 156 | ); 157 | return result; 158 | } 159 | -------------------------------------------------------------------------------- /rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aho-corasick" 7 | version = "1.1.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "cfg-if" 16 | version = "1.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 19 | 20 | [[package]] 21 | name = "gensym" 22 | version = "0.1.1" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82" 25 | dependencies = [ 26 | "proc-macro2", 27 | "quote", 28 | "syn", 29 | "uuid", 30 | ] 31 | 32 | [[package]] 33 | name = "getrandom" 34 | version = "0.2.12" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 37 | dependencies = [ 38 | "cfg-if", 39 | "libc", 40 | "wasi", 41 | ] 42 | 43 | [[package]] 44 | name = "glam" 45 | version = "0.23.0" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "8e4afd9ad95555081e109fe1d21f2a30c691b5f0919c67dfa690a2e1eb6bd51c" 48 | 49 | [[package]] 50 | name = "godot" 51 | version = "0.1.0" 52 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 53 | dependencies = [ 54 | "godot-core", 55 | "godot-macros", 56 | ] 57 | 58 | [[package]] 59 | name = "godot-bindings" 60 | version = "0.1.0" 61 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 62 | dependencies = [ 63 | "godot4-prebuilt", 64 | ] 65 | 66 | [[package]] 67 | name = "godot-cell" 68 | version = "0.1.0" 69 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 70 | 71 | [[package]] 72 | name = "godot-codegen" 73 | version = "0.1.0" 74 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 75 | dependencies = [ 76 | "godot-bindings", 77 | "godot-fmt", 78 | "heck", 79 | "nanoserde", 80 | "proc-macro2", 81 | "quote", 82 | "regex", 83 | ] 84 | 85 | [[package]] 86 | name = "godot-core" 87 | version = "0.1.0" 88 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 89 | dependencies = [ 90 | "glam", 91 | "godot-bindings", 92 | "godot-cell", 93 | "godot-codegen", 94 | "godot-ffi", 95 | ] 96 | 97 | [[package]] 98 | name = "godot-ffi" 99 | version = "0.1.0" 100 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 101 | dependencies = [ 102 | "gensym", 103 | "godot-bindings", 104 | "godot-codegen", 105 | "paste", 106 | ] 107 | 108 | [[package]] 109 | name = "godot-fmt" 110 | version = "0.1.0" 111 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 112 | dependencies = [ 113 | "proc-macro2", 114 | ] 115 | 116 | [[package]] 117 | name = "godot-macros" 118 | version = "0.1.0" 119 | source = "git+https://github.com/godot-rust/gdext?branch=master#fe5b02ba6abec0ba2d8fff612368a9c896872810" 120 | dependencies = [ 121 | "godot-bindings", 122 | "proc-macro2", 123 | "quote", 124 | "venial", 125 | ] 126 | 127 | [[package]] 128 | name = "godot4-prebuilt" 129 | version = "0.0.0" 130 | source = "git+https://github.com/godot-rust/godot4-prebuilt?branch=4.2#3328a4cded2da9c9a3e2c4f7e42f649f677648ce" 131 | 132 | [[package]] 133 | name = "heck" 134 | version = "0.4.1" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 137 | 138 | [[package]] 139 | name = "libc" 140 | version = "0.2.153" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 143 | 144 | [[package]] 145 | name = "memchr" 146 | version = "2.7.1" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 149 | 150 | [[package]] 151 | name = "nanoserde" 152 | version = "0.1.37" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "5de9cf844ab1e25a0353525bd74cb889843a6215fa4a0d156fd446f4857a1b99" 155 | dependencies = [ 156 | "nanoserde-derive", 157 | ] 158 | 159 | [[package]] 160 | name = "nanoserde-derive" 161 | version = "0.1.22" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "e943b2c21337b7e3ec6678500687cdc741b7639ad457f234693352075c082204" 164 | 165 | [[package]] 166 | name = "paste" 167 | version = "1.0.14" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 170 | 171 | [[package]] 172 | name = "proc-macro2" 173 | version = "1.0.79" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" 176 | dependencies = [ 177 | "unicode-ident", 178 | ] 179 | 180 | [[package]] 181 | name = "quote" 182 | version = "1.0.35" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 185 | dependencies = [ 186 | "proc-macro2", 187 | ] 188 | 189 | [[package]] 190 | name = "regex" 191 | version = "1.10.4" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" 194 | dependencies = [ 195 | "aho-corasick", 196 | "memchr", 197 | "regex-automata", 198 | "regex-syntax", 199 | ] 200 | 201 | [[package]] 202 | name = "regex-automata" 203 | version = "0.4.6" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" 206 | dependencies = [ 207 | "aho-corasick", 208 | "memchr", 209 | "regex-syntax", 210 | ] 211 | 212 | [[package]] 213 | name = "regex-syntax" 214 | version = "0.8.2" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 217 | 218 | [[package]] 219 | name = "rustshipper" 220 | version = "0.1.0" 221 | dependencies = [ 222 | "godot", 223 | ] 224 | 225 | [[package]] 226 | name = "syn" 227 | version = "2.0.55" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" 230 | dependencies = [ 231 | "proc-macro2", 232 | "quote", 233 | "unicode-ident", 234 | ] 235 | 236 | [[package]] 237 | name = "unicode-ident" 238 | version = "1.0.12" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 241 | 242 | [[package]] 243 | name = "uuid" 244 | version = "1.8.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" 247 | dependencies = [ 248 | "getrandom", 249 | ] 250 | 251 | [[package]] 252 | name = "venial" 253 | version = "0.5.0" 254 | source = "git+https://github.com/PoignardAzur/venial?rev=32ade31408eb0ffba4ce7b02d3cdb2e78b496644#32ade31408eb0ffba4ce7b02d3cdb2e78b496644" 255 | dependencies = [ 256 | "proc-macro2", 257 | "quote", 258 | ] 259 | 260 | [[package]] 261 | name = "wasi" 262 | version = "0.11.0+wasi-snapshot-preview1" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 265 | -------------------------------------------------------------------------------- /godot/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=24 format=3 uid="uid://bsd55whmkxkxb"] 2 | 3 | [ext_resource type="Script" path="res://main.gd" id="1_llsrq"] 4 | [ext_resource type="Texture2D" uid="uid://cf3ihs80fach" path="res://assets/cpp.png" id="2_5a4du"] 5 | [ext_resource type="Shader" path="res://assets/water.gdshader" id="2_bx3yb"] 6 | [ext_resource type="Script" path="res://scenery.gd" id="3_fdh0l"] 7 | [ext_resource type="Texture2D" uid="uid://dop8x0tb7s627" path="res://assets/csharp.png" id="3_ievdu"] 8 | [ext_resource type="Script" path="res://CSharpShip.cs" id="3_kchdg"] 9 | [ext_resource type="Texture2D" uid="uid://7sfe1m4rrd57" path="res://assets/wavy2.png" id="4_dot2n"] 10 | [ext_resource type="Script" path="res://player.gd" id="4_ppds8"] 11 | [ext_resource type="Texture2D" uid="uid://d4fr8e0ijooen" path="res://assets/swift.png" id="5_0susi"] 12 | [ext_resource type="Texture2D" uid="uid://bc746y2bkxphn" path="res://assets/rust.png" id="8_tqcs3"] 13 | [ext_resource type="Texture2D" uid="uid://cjyu6rjcjglum" path="res://assets/zig.png" id="9_ufsnv"] 14 | [ext_resource type="Texture2D" uid="uid://da60o1w7cedfc" path="res://assets/fish1.png" id="10_4h157"] 15 | [ext_resource type="Texture2D" uid="uid://divpm8ilegavo" path="res://assets/fish2.png" id="11_smcpe"] 16 | [ext_resource type="Texture2D" uid="uid://wbuw2i11u4sg" path="res://assets/wavy3.png" id="12_co80w"] 17 | [ext_resource type="TileSet" uid="uid://cgtd1p0jfj1e3" path="res://assets/ground.tres" id="12_wmx52"] 18 | [ext_resource type="Script" path="res://score.gd" id="16_u8gjv"] 19 | 20 | [sub_resource type="ShaderMaterial" id="ShaderMaterial_vm7du"] 21 | shader = ExtResource("2_bx3yb") 22 | shader_parameter/bottom_color = Color(0.2904, 0.44, 0.42504, 1) 23 | shader_parameter/top_color = Color(0.607843, 0.921569, 0.894118, 1) 24 | 25 | [sub_resource type="SpriteFrames" id="SpriteFrames_qmws7"] 26 | animations = [{ 27 | "frames": [{ 28 | "duration": 1.0, 29 | "texture": ExtResource("10_4h157") 30 | }, { 31 | "duration": 1.0, 32 | "texture": ExtResource("11_smcpe") 33 | }], 34 | "loop": true, 35 | "name": &"swim", 36 | "speed": 5.0 37 | }] 38 | 39 | [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_yfivn"] 40 | radius = 31.0 41 | height = 88.0 42 | 43 | [sub_resource type="CapsuleShape2D" id="CapsuleShape2D_wovkj"] 44 | radius = 47.0 45 | height = 132.0 46 | 47 | [sub_resource type="Animation" id="Animation_r5fve"] 48 | length = 0.001 49 | tracks/0/type = "value" 50 | tracks/0/imported = false 51 | tracks/0/enabled = true 52 | tracks/0/path = NodePath("Actors:modulate") 53 | tracks/0/interp = 1 54 | tracks/0/loop_wrap = true 55 | tracks/0/keys = { 56 | "times": PackedFloat32Array(0), 57 | "transitions": PackedFloat32Array(1), 58 | "update": 0, 59 | "values": [Color(1, 1, 1, 1)] 60 | } 61 | 62 | [sub_resource type="Animation" id="Animation_bic8i"] 63 | resource_name = "fade" 64 | length = 0.3 65 | tracks/0/type = "value" 66 | tracks/0/imported = false 67 | tracks/0/enabled = true 68 | tracks/0/path = NodePath("Actors:modulate") 69 | tracks/0/interp = 1 70 | tracks/0/loop_wrap = true 71 | tracks/0/keys = { 72 | "times": PackedFloat32Array(0, 0.3), 73 | "transitions": PackedFloat32Array(1, 1), 74 | "update": 0, 75 | "values": [Color(1, 1, 1, 1), Color(1, 1, 1, 0)] 76 | } 77 | 78 | [sub_resource type="AnimationLibrary" id="AnimationLibrary_fjcx4"] 79 | _data = { 80 | "RESET": SubResource("Animation_r5fve"), 81 | "fade": SubResource("Animation_bic8i") 82 | } 83 | 84 | [node name="Main" type="Node"] 85 | script = ExtResource("1_llsrq") 86 | 87 | [node name="Water" type="ColorRect" parent="."] 88 | material = SubResource("ShaderMaterial_vm7du") 89 | offset_right = 1280.0 90 | offset_bottom = 720.0 91 | 92 | [node name="Background" type="Node2D" parent="." groups=["scenery"]] 93 | process_mode = 3 94 | modulate = Color(0.52549, 0.729412, 0.713726, 1) 95 | script = ExtResource("3_fdh0l") 96 | speed = 350.0 97 | 98 | [node name="Wavy2" type="Sprite2D" parent="Background"] 99 | position = Vector2(738.932, 587.677) 100 | scale = Vector2(0.574409, 0.574409) 101 | texture = ExtResource("4_dot2n") 102 | 103 | [node name="Wavy2b" type="Sprite2D" parent="Background"] 104 | position = Vector2(882, 558) 105 | scale = Vector2(0.882141, 0.882141) 106 | texture = ExtResource("4_dot2n") 107 | 108 | [node name="Wavy2c" type="Sprite2D" parent="Background"] 109 | position = Vector2(1361, 531) 110 | scale = Vector2(0.778173, 0.778173) 111 | texture = ExtResource("4_dot2n") 112 | 113 | [node name="Wavy3" type="Sprite2D" parent="Background"] 114 | position = Vector2(273.5, 432.408) 115 | scale = Vector2(1.0675, 1.0675) 116 | texture = ExtResource("12_co80w") 117 | 118 | [node name="Wavy3b" type="Sprite2D" parent="Background"] 119 | position = Vector2(1713.04, 455.218) 120 | scale = Vector2(0.914778, 0.914778) 121 | texture = ExtResource("12_co80w") 122 | 123 | [node name="TileMap" type="TileMap" parent="Background"] 124 | position = Vector2(100, 0) 125 | tile_set = ExtResource("12_wmx52") 126 | format = 2 127 | layer_0/tile_data = PackedInt32Array(196608, 65536, 0, 196609, 131072, 0, 196610, 196608, 0, 196611, 262144, 0, 196612, 327680, 0, 196613, 393216, 0, 196614, 65536, 0, 262143, 262144, 0, 262142, 131072, 0, 196615, 393216, 0, 262141, 196608, 0, 262140, 65536, 0, 196616, 327680, 0, 196617, 196608, 0, 196618, 393216, 0) 128 | 129 | [node name="Actors" type="Node2D" parent="."] 130 | process_mode = 3 131 | 132 | [node name="Player" type="Area2D" parent="Actors"] 133 | process_mode = 1 134 | position = Vector2(640, 300) 135 | script = ExtResource("4_ppds8") 136 | 137 | [node name="Sprite" type="AnimatedSprite2D" parent="Actors/Player"] 138 | sprite_frames = SubResource("SpriteFrames_qmws7") 139 | animation = &"swim" 140 | 141 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Actors/Player"] 142 | position = Vector2(18, 3) 143 | rotation = 1.5708 144 | shape = SubResource("CapsuleShape2D_yfivn") 145 | 146 | [node name="Ships" type="Node2D" parent="Actors"] 147 | process_mode = 1 148 | 149 | [node name="CppShip" type="CppShip" parent="Actors/Ships" groups=["ship"]] 150 | 151 | [node name="Sprite" type="Area2D" parent="Actors/Ships/CppShip"] 152 | position = Vector2(1380, 203) 153 | 154 | [node name="Sprite" type="Sprite2D" parent="Actors/Ships/CppShip/Sprite"] 155 | position = Vector2(0, 15) 156 | texture = ExtResource("2_5a4du") 157 | 158 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Actors/Ships/CppShip/Sprite"] 159 | position = Vector2(0, -8) 160 | shape = SubResource("CapsuleShape2D_wovkj") 161 | 162 | [node name="Target" type="Node2D" parent="Actors/Ships/CppShip"] 163 | position = Vector2(343, 414) 164 | 165 | [node name="CSharpShip" type="Node2D" parent="Actors/Ships" groups=["ship"]] 166 | script = ExtResource("3_kchdg") 167 | 168 | [node name="Sprite" type="Area2D" parent="Actors/Ships/CSharpShip"] 169 | position = Vector2(-100, 106) 170 | 171 | [node name="Sprite" type="Sprite2D" parent="Actors/Ships/CSharpShip/Sprite"] 172 | texture = ExtResource("3_ievdu") 173 | 174 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Actors/Ships/CSharpShip/Sprite"] 175 | position = Vector2(0, -10) 176 | shape = SubResource("CapsuleShape2D_wovkj") 177 | 178 | [node name="Target" type="Node2D" parent="Actors/Ships/CSharpShip"] 179 | position = Vector2(941, 500) 180 | 181 | [node name="RustShip" type="RustShip" parent="Actors/Ships" groups=["ship"]] 182 | 183 | [node name="Sprite" type="Area2D" parent="Actors/Ships/RustShip"] 184 | position = Vector2(-100, 454) 185 | 186 | [node name="Sprite" type="Sprite2D" parent="Actors/Ships/RustShip/Sprite"] 187 | texture = ExtResource("8_tqcs3") 188 | 189 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Actors/Ships/RustShip/Sprite"] 190 | position = Vector2(-1, -9) 191 | shape = SubResource("CapsuleShape2D_wovkj") 192 | 193 | [node name="Target" type="Node2D" parent="Actors/Ships/RustShip"] 194 | position = Vector2(644, 106) 195 | 196 | [node name="SwiftShip" type="SwiftShip" parent="Actors/Ships" groups=["ship"]] 197 | 198 | [node name="Sprite" type="Area2D" parent="Actors/Ships/SwiftShip"] 199 | position = Vector2(171, -99) 200 | 201 | [node name="Sprite" type="Sprite2D" parent="Actors/Ships/SwiftShip/Sprite"] 202 | texture = ExtResource("5_0susi") 203 | 204 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Actors/Ships/SwiftShip/Sprite"] 205 | position = Vector2(0, -12) 206 | shape = SubResource("CapsuleShape2D_wovkj") 207 | 208 | [node name="Target" type="Node2D" parent="Actors/Ships/SwiftShip"] 209 | position = Vector2(525, 414) 210 | 211 | [node name="ZigShip" type="ZigShip" parent="Actors/Ships" groups=["ship"]] 212 | 213 | [node name="Sprite" type="Area2D" parent="Actors/Ships/ZigShip"] 214 | position = Vector2(1380, 451) 215 | 216 | [node name="Sprite" type="Sprite2D" parent="Actors/Ships/ZigShip/Sprite"] 217 | texture = ExtResource("9_ufsnv") 218 | 219 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Actors/Ships/ZigShip/Sprite"] 220 | position = Vector2(-1, -7) 221 | shape = SubResource("CapsuleShape2D_wovkj") 222 | 223 | [node name="Target" type="Node2D" parent="Actors/Ships/ZigShip"] 224 | position = Vector2(846, 106) 225 | 226 | [node name="Ground" type="Node2D" parent="." groups=["scenery"]] 227 | process_mode = 3 228 | position = Vector2(0, 10) 229 | script = ExtResource("3_fdh0l") 230 | 231 | [node name="Wavy3" type="Sprite2D" parent="Ground"] 232 | position = Vector2(1029, 453) 233 | scale = Vector2(0.905, 0.905) 234 | texture = ExtResource("12_co80w") 235 | 236 | [node name="Wavy3b" type="Sprite2D" parent="Ground"] 237 | position = Vector2(1612, 473) 238 | scale = Vector2(0.819025, 0.819025) 239 | texture = ExtResource("12_co80w") 240 | 241 | [node name="Wavy2" type="Sprite2D" parent="Ground"] 242 | position = Vector2(243, 500) 243 | scale = Vector2(1.07652, 1.07652) 244 | texture = ExtResource("4_dot2n") 245 | 246 | [node name="TileMap" type="TileMap" parent="Ground"] 247 | tile_set = ExtResource("12_wmx52") 248 | format = 2 249 | layer_0/tile_data = PackedInt32Array(196608, 65536, 0, 196609, 131072, 0, 196610, 196608, 0, 196611, 262144, 0, 196612, 327680, 0, 196613, 393216, 0, 196614, 65536, 0, 262143, 262144, 0, 262142, 131072, 0, 196615, 393216, 0, 262141, 196608, 0, 262140, 65536, 0, 196616, 327680, 0, 196617, 196608, 0, 196618, 393216, 0) 250 | 251 | [node name="Bounds" type="ReferenceRect" parent="."] 252 | offset_right = 1280.0 253 | offset_bottom = 655.0 254 | border_color = Color(1, 1, 1, 1) 255 | 256 | [node name="Score" type="Label" parent="."] 257 | anchors_preset = 7 258 | anchor_left = 0.5 259 | anchor_top = 1.0 260 | anchor_right = 0.5 261 | anchor_bottom = 1.0 262 | offset_left = -77.0 263 | offset_top = -63.0 264 | offset_right = 77.0 265 | grow_horizontal = 2 266 | grow_vertical = 0 267 | theme_override_colors/font_color = Color(1, 1, 1, 1) 268 | theme_override_colors/font_outline_color = Color(0, 0, 0, 1) 269 | theme_override_constants/outline_size = 15 270 | theme_override_font_sizes/font_size = 45 271 | text = " Score 123 " 272 | script = ExtResource("16_u8gjv") 273 | 274 | [node name="AnimationPlayer" type="AnimationPlayer" parent="."] 275 | process_mode = 3 276 | libraries = { 277 | "": SubResource("AnimationLibrary_fjcx4") 278 | } 279 | 280 | [connection signal="ship_attacked" from="." to="Score" method="_on_main_ship_attacked"] 281 | [connection signal="area_entered" from="Actors/Player" to="." method="_on_player_area_entered"] 282 | -------------------------------------------------------------------------------- /godot/assets/ground.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="TileSet" load_steps=3 format=3 uid="uid://cgtd1p0jfj1e3"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://duk10thql43ef" path="res://assets/ground.png" id="1_52ohr"] 4 | 5 | [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_46vqo"] 6 | resource_name = "ground" 7 | texture = ExtResource("1_52ohr") 8 | texture_region_size = Vector2i(200, 200) 9 | 1:0/0 = 0 10 | 2:0/0 = 0 11 | 3:0/0 = 0 12 | 4:0/0 = 0 13 | 5:0/0 = 0 14 | 6:0/0 = 0 15 | 8:0/0 = 0 16 | 9:0/0 = 0 17 | 10:0/0 = 0 18 | 11:0/0 = 0 19 | 12:0/0 = 0 20 | 18:0/0 = 0 21 | 19:0/0 = 0 22 | 20:0/0 = 0 23 | 21:0/0 = 0 24 | 22:0/0 = 0 25 | 23:0/0 = 0 26 | 24:0/0 = 0 27 | 25:0/0 = 0 28 | 26:0/0 = 0 29 | 27:0/0 = 0 30 | 28:0/0 = 0 31 | 29:0/0 = 0 32 | 30:0/0 = 0 33 | 31:0/0 = 0 34 | 32:0/0 = 0 35 | 33:0/0 = 0 36 | 34:0/0 = 0 37 | 35:0/0 = 0 38 | 36:0/0 = 0 39 | 37:0/0 = 0 40 | 38:0/0 = 0 41 | 39:0/0 = 0 42 | 40:0/0 = 0 43 | 41:0/0 = 0 44 | 42:0/0 = 0 45 | 43:0/0 = 0 46 | 44:0/0 = 0 47 | 45:0/0 = 0 48 | 46:0/0 = 0 49 | 47:0/0 = 0 50 | 48:0/0 = 0 51 | 49:0/0 = 0 52 | 50:0/0 = 0 53 | 51:0/0 = 0 54 | 52:0/0 = 0 55 | 53:0/0 = 0 56 | 54:0/0 = 0 57 | 55:0/0 = 0 58 | 56:0/0 = 0 59 | 57:0/0 = 0 60 | 58:0/0 = 0 61 | 59:0/0 = 0 62 | 60:0/0 = 0 63 | 61:0/0 = 0 64 | 62:0/0 = 0 65 | 63:0/0 = 0 66 | 74:0/0 = 0 67 | 75:0/0 = 0 68 | 76:0/0 = 0 69 | 77:0/0 = 0 70 | 78:0/0 = 0 71 | 79:0/0 = 0 72 | 80:0/0 = 0 73 | 81:0/0 = 0 74 | 82:0/0 = 0 75 | 83:0/0 = 0 76 | 84:0/0 = 0 77 | 85:0/0 = 0 78 | 86:0/0 = 0 79 | 0:1/0 = 0 80 | 1:1/0 = 0 81 | 2:1/0 = 0 82 | 3:1/0 = 0 83 | 4:1/0 = 0 84 | 5:1/0 = 0 85 | 6:1/0 = 0 86 | 7:1/0 = 0 87 | 8:1/0 = 0 88 | 9:1/0 = 0 89 | 10:1/0 = 0 90 | 11:1/0 = 0 91 | 12:1/0 = 0 92 | 13:1/0 = 0 93 | 14:1/0 = 0 94 | 15:1/0 = 0 95 | 16:1/0 = 0 96 | 17:1/0 = 0 97 | 18:1/0 = 0 98 | 19:1/0 = 0 99 | 20:1/0 = 0 100 | 21:1/0 = 0 101 | 22:1/0 = 0 102 | 23:1/0 = 0 103 | 24:1/0 = 0 104 | 25:1/0 = 0 105 | 26:1/0 = 0 106 | 27:1/0 = 0 107 | 28:1/0 = 0 108 | 29:1/0 = 0 109 | 30:1/0 = 0 110 | 31:1/0 = 0 111 | 32:1/0 = 0 112 | 33:1/0 = 0 113 | 34:1/0 = 0 114 | 35:1/0 = 0 115 | 36:1/0 = 0 116 | 37:1/0 = 0 117 | 38:1/0 = 0 118 | 39:1/0 = 0 119 | 40:1/0 = 0 120 | 41:1/0 = 0 121 | 42:1/0 = 0 122 | 43:1/0 = 0 123 | 44:1/0 = 0 124 | 45:1/0 = 0 125 | 46:1/0 = 0 126 | 47:1/0 = 0 127 | 48:1/0 = 0 128 | 49:1/0 = 0 129 | 50:1/0 = 0 130 | 51:1/0 = 0 131 | 52:1/0 = 0 132 | 53:1/0 = 0 133 | 54:1/0 = 0 134 | 55:1/0 = 0 135 | 56:1/0 = 0 136 | 57:1/0 = 0 137 | 58:1/0 = 0 138 | 59:1/0 = 0 139 | 60:1/0 = 0 140 | 61:1/0 = 0 141 | 62:1/0 = 0 142 | 63:1/0 = 0 143 | 64:1/0 = 0 144 | 65:1/0 = 0 145 | 66:1/0 = 0 146 | 67:1/0 = 0 147 | 68:1/0 = 0 148 | 69:1/0 = 0 149 | 70:1/0 = 0 150 | 71:1/0 = 0 151 | 72:1/0 = 0 152 | 73:1/0 = 0 153 | 74:1/0 = 0 154 | 75:1/0 = 0 155 | 76:1/0 = 0 156 | 77:1/0 = 0 157 | 78:1/0 = 0 158 | 79:1/0 = 0 159 | 80:1/0 = 0 160 | 81:1/0 = 0 161 | 82:1/0 = 0 162 | 83:1/0 = 0 163 | 84:1/0 = 0 164 | 85:1/0 = 0 165 | 86:1/0 = 0 166 | 0:2/0 = 0 167 | 1:2/0 = 0 168 | 2:2/0 = 0 169 | 3:2/0 = 0 170 | 4:2/0 = 0 171 | 5:2/0 = 0 172 | 6:2/0 = 0 173 | 7:2/0 = 0 174 | 8:2/0 = 0 175 | 9:2/0 = 0 176 | 10:2/0 = 0 177 | 11:2/0 = 0 178 | 12:2/0 = 0 179 | 13:2/0 = 0 180 | 14:2/0 = 0 181 | 15:2/0 = 0 182 | 16:2/0 = 0 183 | 17:2/0 = 0 184 | 18:2/0 = 0 185 | 19:2/0 = 0 186 | 20:2/0 = 0 187 | 21:2/0 = 0 188 | 22:2/0 = 0 189 | 23:2/0 = 0 190 | 24:2/0 = 0 191 | 25:2/0 = 0 192 | 26:2/0 = 0 193 | 27:2/0 = 0 194 | 28:2/0 = 0 195 | 29:2/0 = 0 196 | 30:2/0 = 0 197 | 31:2/0 = 0 198 | 32:2/0 = 0 199 | 33:2/0 = 0 200 | 34:2/0 = 0 201 | 35:2/0 = 0 202 | 36:2/0 = 0 203 | 37:2/0 = 0 204 | 38:2/0 = 0 205 | 39:2/0 = 0 206 | 40:2/0 = 0 207 | 41:2/0 = 0 208 | 42:2/0 = 0 209 | 43:2/0 = 0 210 | 44:2/0 = 0 211 | 45:2/0 = 0 212 | 46:2/0 = 0 213 | 47:2/0 = 0 214 | 48:2/0 = 0 215 | 49:2/0 = 0 216 | 50:2/0 = 0 217 | 51:2/0 = 0 218 | 52:2/0 = 0 219 | 53:2/0 = 0 220 | 54:2/0 = 0 221 | 55:2/0 = 0 222 | 56:2/0 = 0 223 | 57:2/0 = 0 224 | 58:2/0 = 0 225 | 59:2/0 = 0 226 | 60:2/0 = 0 227 | 61:2/0 = 0 228 | 62:2/0 = 0 229 | 63:2/0 = 0 230 | 64:2/0 = 0 231 | 65:2/0 = 0 232 | 66:2/0 = 0 233 | 67:2/0 = 0 234 | 68:2/0 = 0 235 | 69:2/0 = 0 236 | 70:2/0 = 0 237 | 71:2/0 = 0 238 | 72:2/0 = 0 239 | 73:2/0 = 0 240 | 74:2/0 = 0 241 | 75:2/0 = 0 242 | 76:2/0 = 0 243 | 77:2/0 = 0 244 | 78:2/0 = 0 245 | 79:2/0 = 0 246 | 80:2/0 = 0 247 | 81:2/0 = 0 248 | 82:2/0 = 0 249 | 83:2/0 = 0 250 | 84:2/0 = 0 251 | 85:2/0 = 0 252 | 86:2/0 = 0 253 | 0:3/0 = 0 254 | 1:3/0 = 0 255 | 2:3/0 = 0 256 | 3:3/0 = 0 257 | 4:3/0 = 0 258 | 5:3/0 = 0 259 | 6:3/0 = 0 260 | 7:3/0 = 0 261 | 8:3/0 = 0 262 | 9:3/0 = 0 263 | 10:3/0 = 0 264 | 11:3/0 = 0 265 | 12:3/0 = 0 266 | 13:3/0 = 0 267 | 14:3/0 = 0 268 | 15:3/0 = 0 269 | 16:3/0 = 0 270 | 17:3/0 = 0 271 | 18:3/0 = 0 272 | 19:3/0 = 0 273 | 20:3/0 = 0 274 | 21:3/0 = 0 275 | 22:3/0 = 0 276 | 23:3/0 = 0 277 | 24:3/0 = 0 278 | 25:3/0 = 0 279 | 26:3/0 = 0 280 | 27:3/0 = 0 281 | 28:3/0 = 0 282 | 29:3/0 = 0 283 | 30:3/0 = 0 284 | 31:3/0 = 0 285 | 32:3/0 = 0 286 | 33:3/0 = 0 287 | 34:3/0 = 0 288 | 35:3/0 = 0 289 | 36:3/0 = 0 290 | 37:3/0 = 0 291 | 38:3/0 = 0 292 | 39:3/0 = 0 293 | 40:3/0 = 0 294 | 41:3/0 = 0 295 | 42:3/0 = 0 296 | 43:3/0 = 0 297 | 44:3/0 = 0 298 | 45:3/0 = 0 299 | 46:3/0 = 0 300 | 47:3/0 = 0 301 | 48:3/0 = 0 302 | 49:3/0 = 0 303 | 50:3/0 = 0 304 | 51:3/0 = 0 305 | 52:3/0 = 0 306 | 53:3/0 = 0 307 | 54:3/0 = 0 308 | 55:3/0 = 0 309 | 56:3/0 = 0 310 | 57:3/0 = 0 311 | 58:3/0 = 0 312 | 59:3/0 = 0 313 | 60:3/0 = 0 314 | 61:3/0 = 0 315 | 62:3/0 = 0 316 | 63:3/0 = 0 317 | 64:3/0 = 0 318 | 65:3/0 = 0 319 | 66:3/0 = 0 320 | 67:3/0 = 0 321 | 68:3/0 = 0 322 | 69:3/0 = 0 323 | 70:3/0 = 0 324 | 71:3/0 = 0 325 | 72:3/0 = 0 326 | 73:3/0 = 0 327 | 74:3/0 = 0 328 | 75:3/0 = 0 329 | 76:3/0 = 0 330 | 77:3/0 = 0 331 | 78:3/0 = 0 332 | 79:3/0 = 0 333 | 80:3/0 = 0 334 | 81:3/0 = 0 335 | 82:3/0 = 0 336 | 83:3/0 = 0 337 | 84:3/0 = 0 338 | 85:3/0 = 0 339 | 86:3/0 = 0 340 | 0:4/0 = 0 341 | 1:4/0 = 0 342 | 2:4/0 = 0 343 | 3:4/0 = 0 344 | 4:4/0 = 0 345 | 5:4/0 = 0 346 | 6:4/0 = 0 347 | 7:4/0 = 0 348 | 8:4/0 = 0 349 | 9:4/0 = 0 350 | 10:4/0 = 0 351 | 11:4/0 = 0 352 | 12:4/0 = 0 353 | 13:4/0 = 0 354 | 14:4/0 = 0 355 | 15:4/0 = 0 356 | 16:4/0 = 0 357 | 17:4/0 = 0 358 | 18:4/0 = 0 359 | 19:4/0 = 0 360 | 20:4/0 = 0 361 | 21:4/0 = 0 362 | 22:4/0 = 0 363 | 23:4/0 = 0 364 | 24:4/0 = 0 365 | 25:4/0 = 0 366 | 26:4/0 = 0 367 | 27:4/0 = 0 368 | 28:4/0 = 0 369 | 29:4/0 = 0 370 | 30:4/0 = 0 371 | 31:4/0 = 0 372 | 32:4/0 = 0 373 | 33:4/0 = 0 374 | 34:4/0 = 0 375 | 35:4/0 = 0 376 | 36:4/0 = 0 377 | 37:4/0 = 0 378 | 38:4/0 = 0 379 | 39:4/0 = 0 380 | 40:4/0 = 0 381 | 41:4/0 = 0 382 | 42:4/0 = 0 383 | 43:4/0 = 0 384 | 44:4/0 = 0 385 | 45:4/0 = 0 386 | 46:4/0 = 0 387 | 47:4/0 = 0 388 | 48:4/0 = 0 389 | 49:4/0 = 0 390 | 50:4/0 = 0 391 | 51:4/0 = 0 392 | 52:4/0 = 0 393 | 53:4/0 = 0 394 | 54:4/0 = 0 395 | 55:4/0 = 0 396 | 56:4/0 = 0 397 | 57:4/0 = 0 398 | 58:4/0 = 0 399 | 59:4/0 = 0 400 | 60:4/0 = 0 401 | 61:4/0 = 0 402 | 62:4/0 = 0 403 | 63:4/0 = 0 404 | 64:4/0 = 0 405 | 65:4/0 = 0 406 | 66:4/0 = 0 407 | 67:4/0 = 0 408 | 68:4/0 = 0 409 | 69:4/0 = 0 410 | 70:4/0 = 0 411 | 71:4/0 = 0 412 | 72:4/0 = 0 413 | 73:4/0 = 0 414 | 74:4/0 = 0 415 | 75:4/0 = 0 416 | 76:4/0 = 0 417 | 77:4/0 = 0 418 | 78:4/0 = 0 419 | 79:4/0 = 0 420 | 80:4/0 = 0 421 | 81:4/0 = 0 422 | 82:4/0 = 0 423 | 83:4/0 = 0 424 | 84:4/0 = 0 425 | 85:4/0 = 0 426 | 86:4/0 = 0 427 | 0:5/0 = 0 428 | 1:5/0 = 0 429 | 2:5/0 = 0 430 | 3:5/0 = 0 431 | 4:5/0 = 0 432 | 5:5/0 = 0 433 | 6:5/0 = 0 434 | 7:5/0 = 0 435 | 8:5/0 = 0 436 | 9:5/0 = 0 437 | 10:5/0 = 0 438 | 11:5/0 = 0 439 | 12:5/0 = 0 440 | 13:5/0 = 0 441 | 14:5/0 = 0 442 | 15:5/0 = 0 443 | 16:5/0 = 0 444 | 17:5/0 = 0 445 | 18:5/0 = 0 446 | 19:5/0 = 0 447 | 20:5/0 = 0 448 | 21:5/0 = 0 449 | 22:5/0 = 0 450 | 23:5/0 = 0 451 | 24:5/0 = 0 452 | 25:5/0 = 0 453 | 26:5/0 = 0 454 | 27:5/0 = 0 455 | 28:5/0 = 0 456 | 29:5/0 = 0 457 | 30:5/0 = 0 458 | 31:5/0 = 0 459 | 32:5/0 = 0 460 | 33:5/0 = 0 461 | 34:5/0 = 0 462 | 35:5/0 = 0 463 | 36:5/0 = 0 464 | 37:5/0 = 0 465 | 38:5/0 = 0 466 | 39:5/0 = 0 467 | 40:5/0 = 0 468 | 41:5/0 = 0 469 | 42:5/0 = 0 470 | 43:5/0 = 0 471 | 44:5/0 = 0 472 | 45:5/0 = 0 473 | 46:5/0 = 0 474 | 47:5/0 = 0 475 | 48:5/0 = 0 476 | 49:5/0 = 0 477 | 50:5/0 = 0 478 | 51:5/0 = 0 479 | 52:5/0 = 0 480 | 53:5/0 = 0 481 | 54:5/0 = 0 482 | 55:5/0 = 0 483 | 56:5/0 = 0 484 | 57:5/0 = 0 485 | 58:5/0 = 0 486 | 59:5/0 = 0 487 | 60:5/0 = 0 488 | 61:5/0 = 0 489 | 62:5/0 = 0 490 | 63:5/0 = 0 491 | 64:5/0 = 0 492 | 65:5/0 = 0 493 | 66:5/0 = 0 494 | 67:5/0 = 0 495 | 68:5/0 = 0 496 | 69:5/0 = 0 497 | 70:5/0 = 0 498 | 71:5/0 = 0 499 | 72:5/0 = 0 500 | 73:5/0 = 0 501 | 74:5/0 = 0 502 | 75:5/0 = 0 503 | 76:5/0 = 0 504 | 77:5/0 = 0 505 | 78:5/0 = 0 506 | 79:5/0 = 0 507 | 80:5/0 = 0 508 | 81:5/0 = 0 509 | 82:5/0 = 0 510 | 83:5/0 = 0 511 | 84:5/0 = 0 512 | 85:5/0 = 0 513 | 86:5/0 = 0 514 | 0:6/0 = 0 515 | 1:6/0 = 0 516 | 2:6/0 = 0 517 | 3:6/0 = 0 518 | 4:6/0 = 0 519 | 5:6/0 = 0 520 | 6:6/0 = 0 521 | 7:6/0 = 0 522 | 8:6/0 = 0 523 | 9:6/0 = 0 524 | 10:6/0 = 0 525 | 11:6/0 = 0 526 | 12:6/0 = 0 527 | 13:6/0 = 0 528 | 14:6/0 = 0 529 | 15:6/0 = 0 530 | 16:6/0 = 0 531 | 17:6/0 = 0 532 | 18:6/0 = 0 533 | 19:6/0 = 0 534 | 20:6/0 = 0 535 | 21:6/0 = 0 536 | 22:6/0 = 0 537 | 23:6/0 = 0 538 | 24:6/0 = 0 539 | 25:6/0 = 0 540 | 26:6/0 = 0 541 | 27:6/0 = 0 542 | 28:6/0 = 0 543 | 29:6/0 = 0 544 | 30:6/0 = 0 545 | 31:6/0 = 0 546 | 32:6/0 = 0 547 | 33:6/0 = 0 548 | 34:6/0 = 0 549 | 35:6/0 = 0 550 | 36:6/0 = 0 551 | 37:6/0 = 0 552 | 38:6/0 = 0 553 | 39:6/0 = 0 554 | 40:6/0 = 0 555 | 41:6/0 = 0 556 | 42:6/0 = 0 557 | 43:6/0 = 0 558 | 44:6/0 = 0 559 | 45:6/0 = 0 560 | 46:6/0 = 0 561 | 47:6/0 = 0 562 | 48:6/0 = 0 563 | 49:6/0 = 0 564 | 50:6/0 = 0 565 | 51:6/0 = 0 566 | 52:6/0 = 0 567 | 53:6/0 = 0 568 | 54:6/0 = 0 569 | 55:6/0 = 0 570 | 56:6/0 = 0 571 | 57:6/0 = 0 572 | 58:6/0 = 0 573 | 59:6/0 = 0 574 | 60:6/0 = 0 575 | 61:6/0 = 0 576 | 62:6/0 = 0 577 | 63:6/0 = 0 578 | 64:6/0 = 0 579 | 65:6/0 = 0 580 | 66:6/0 = 0 581 | 67:6/0 = 0 582 | 68:6/0 = 0 583 | 69:6/0 = 0 584 | 70:6/0 = 0 585 | 71:6/0 = 0 586 | 72:6/0 = 0 587 | 73:6/0 = 0 588 | 74:6/0 = 0 589 | 75:6/0 = 0 590 | 76:6/0 = 0 591 | 77:6/0 = 0 592 | 78:6/0 = 0 593 | 79:6/0 = 0 594 | 80:6/0 = 0 595 | 81:6/0 = 0 596 | 82:6/0 = 0 597 | 83:6/0 = 0 598 | 84:6/0 = 0 599 | 85:6/0 = 0 600 | 86:6/0 = 0 601 | 0:7/0 = 0 602 | 1:7/0 = 0 603 | 2:7/0 = 0 604 | 3:7/0 = 0 605 | 4:7/0 = 0 606 | 5:7/0 = 0 607 | 6:7/0 = 0 608 | 7:7/0 = 0 609 | 8:7/0 = 0 610 | 9:7/0 = 0 611 | 10:7/0 = 0 612 | 11:7/0 = 0 613 | 12:7/0 = 0 614 | 13:7/0 = 0 615 | 14:7/0 = 0 616 | 15:7/0 = 0 617 | 16:7/0 = 0 618 | 17:7/0 = 0 619 | 18:7/0 = 0 620 | 19:7/0 = 0 621 | 20:7/0 = 0 622 | 21:7/0 = 0 623 | 22:7/0 = 0 624 | 23:7/0 = 0 625 | 24:7/0 = 0 626 | 25:7/0 = 0 627 | 26:7/0 = 0 628 | 27:7/0 = 0 629 | 28:7/0 = 0 630 | 29:7/0 = 0 631 | 30:7/0 = 0 632 | 31:7/0 = 0 633 | 32:7/0 = 0 634 | 33:7/0 = 0 635 | 34:7/0 = 0 636 | 35:7/0 = 0 637 | 36:7/0 = 0 638 | 37:7/0 = 0 639 | 38:7/0 = 0 640 | 39:7/0 = 0 641 | 40:7/0 = 0 642 | 41:7/0 = 0 643 | 42:7/0 = 0 644 | 43:7/0 = 0 645 | 44:7/0 = 0 646 | 45:7/0 = 0 647 | 46:7/0 = 0 648 | 47:7/0 = 0 649 | 48:7/0 = 0 650 | 49:7/0 = 0 651 | 50:7/0 = 0 652 | 51:7/0 = 0 653 | 52:7/0 = 0 654 | 53:7/0 = 0 655 | 54:7/0 = 0 656 | 55:7/0 = 0 657 | 56:7/0 = 0 658 | 57:7/0 = 0 659 | 58:7/0 = 0 660 | 59:7/0 = 0 661 | 60:7/0 = 0 662 | 61:7/0 = 0 663 | 62:7/0 = 0 664 | 63:7/0 = 0 665 | 64:7/0 = 0 666 | 65:7/0 = 0 667 | 66:7/0 = 0 668 | 67:7/0 = 0 669 | 68:7/0 = 0 670 | 69:7/0 = 0 671 | 70:7/0 = 0 672 | 71:7/0 = 0 673 | 72:7/0 = 0 674 | 73:7/0 = 0 675 | 74:7/0 = 0 676 | 75:7/0 = 0 677 | 76:7/0 = 0 678 | 77:7/0 = 0 679 | 78:7/0 = 0 680 | 79:7/0 = 0 681 | 80:7/0 = 0 682 | 81:7/0 = 0 683 | 82:7/0 = 0 684 | 83:7/0 = 0 685 | 84:7/0 = 0 686 | 85:7/0 = 0 687 | 86:7/0 = 0 688 | 0:8/0 = 0 689 | 1:8/0 = 0 690 | 2:8/0 = 0 691 | 3:8/0 = 0 692 | 4:8/0 = 0 693 | 5:8/0 = 0 694 | 6:8/0 = 0 695 | 7:8/0 = 0 696 | 8:8/0 = 0 697 | 9:8/0 = 0 698 | 10:8/0 = 0 699 | 11:8/0 = 0 700 | 12:8/0 = 0 701 | 13:8/0 = 0 702 | 14:8/0 = 0 703 | 15:8/0 = 0 704 | 16:8/0 = 0 705 | 17:8/0 = 0 706 | 18:8/0 = 0 707 | 19:8/0 = 0 708 | 20:8/0 = 0 709 | 21:8/0 = 0 710 | 22:8/0 = 0 711 | 23:8/0 = 0 712 | 24:8/0 = 0 713 | 25:8/0 = 0 714 | 26:8/0 = 0 715 | 27:8/0 = 0 716 | 28:8/0 = 0 717 | 29:8/0 = 0 718 | 30:8/0 = 0 719 | 31:8/0 = 0 720 | 32:8/0 = 0 721 | 33:8/0 = 0 722 | 34:8/0 = 0 723 | 35:8/0 = 0 724 | 36:8/0 = 0 725 | 37:8/0 = 0 726 | 38:8/0 = 0 727 | 39:8/0 = 0 728 | 40:8/0 = 0 729 | 41:8/0 = 0 730 | 42:8/0 = 0 731 | 43:8/0 = 0 732 | 44:8/0 = 0 733 | 45:8/0 = 0 734 | 46:8/0 = 0 735 | 47:8/0 = 0 736 | 48:8/0 = 0 737 | 49:8/0 = 0 738 | 50:8/0 = 0 739 | 51:8/0 = 0 740 | 52:8/0 = 0 741 | 53:8/0 = 0 742 | 54:8/0 = 0 743 | 55:8/0 = 0 744 | 56:8/0 = 0 745 | 57:8/0 = 0 746 | 58:8/0 = 0 747 | 59:8/0 = 0 748 | 60:8/0 = 0 749 | 61:8/0 = 0 750 | 62:8/0 = 0 751 | 63:8/0 = 0 752 | 64:8/0 = 0 753 | 65:8/0 = 0 754 | 66:8/0 = 0 755 | 67:8/0 = 0 756 | 68:8/0 = 0 757 | 69:8/0 = 0 758 | 70:8/0 = 0 759 | 71:8/0 = 0 760 | 72:8/0 = 0 761 | 73:8/0 = 0 762 | 74:8/0 = 0 763 | 75:8/0 = 0 764 | 76:8/0 = 0 765 | 77:8/0 = 0 766 | 78:8/0 = 0 767 | 79:8/0 = 0 768 | 80:8/0 = 0 769 | 81:8/0 = 0 770 | 82:8/0 = 0 771 | 83:8/0 = 0 772 | 84:8/0 = 0 773 | 85:8/0 = 0 774 | 86:8/0 = 0 775 | 0:9/0 = 0 776 | 1:9/0 = 0 777 | 2:9/0 = 0 778 | 3:9/0 = 0 779 | 4:9/0 = 0 780 | 5:9/0 = 0 781 | 6:9/0 = 0 782 | 7:9/0 = 0 783 | 8:9/0 = 0 784 | 9:9/0 = 0 785 | 10:9/0 = 0 786 | 11:9/0 = 0 787 | 12:9/0 = 0 788 | 13:9/0 = 0 789 | 14:9/0 = 0 790 | 15:9/0 = 0 791 | 16:9/0 = 0 792 | 17:9/0 = 0 793 | 18:9/0 = 0 794 | 19:9/0 = 0 795 | 20:9/0 = 0 796 | 21:9/0 = 0 797 | 22:9/0 = 0 798 | 23:9/0 = 0 799 | 24:9/0 = 0 800 | 25:9/0 = 0 801 | 26:9/0 = 0 802 | 27:9/0 = 0 803 | 28:9/0 = 0 804 | 29:9/0 = 0 805 | 30:9/0 = 0 806 | 31:9/0 = 0 807 | 32:9/0 = 0 808 | 33:9/0 = 0 809 | 34:9/0 = 0 810 | 35:9/0 = 0 811 | 36:9/0 = 0 812 | 37:9/0 = 0 813 | 38:9/0 = 0 814 | 39:9/0 = 0 815 | 40:9/0 = 0 816 | 41:9/0 = 0 817 | 42:9/0 = 0 818 | 43:9/0 = 0 819 | 44:9/0 = 0 820 | 45:9/0 = 0 821 | 46:9/0 = 0 822 | 47:9/0 = 0 823 | 48:9/0 = 0 824 | 49:9/0 = 0 825 | 50:9/0 = 0 826 | 51:9/0 = 0 827 | 52:9/0 = 0 828 | 53:9/0 = 0 829 | 54:9/0 = 0 830 | 55:9/0 = 0 831 | 56:9/0 = 0 832 | 57:9/0 = 0 833 | 58:9/0 = 0 834 | 59:9/0 = 0 835 | 60:9/0 = 0 836 | 61:9/0 = 0 837 | 62:9/0 = 0 838 | 63:9/0 = 0 839 | 64:9/0 = 0 840 | 65:9/0 = 0 841 | 66:9/0 = 0 842 | 67:9/0 = 0 843 | 68:9/0 = 0 844 | 69:9/0 = 0 845 | 70:9/0 = 0 846 | 71:9/0 = 0 847 | 72:9/0 = 0 848 | 73:9/0 = 0 849 | 74:9/0 = 0 850 | 75:9/0 = 0 851 | 76:9/0 = 0 852 | 77:9/0 = 0 853 | 78:9/0 = 0 854 | 79:9/0 = 0 855 | 80:9/0 = 0 856 | 81:9/0 = 0 857 | 82:9/0 = 0 858 | 83:9/0 = 0 859 | 84:9/0 = 0 860 | 85:9/0 = 0 861 | 86:9/0 = 0 862 | 0:10/0 = 0 863 | 1:10/0 = 0 864 | 2:10/0 = 0 865 | 3:10/0 = 0 866 | 4:10/0 = 0 867 | 5:10/0 = 0 868 | 6:10/0 = 0 869 | 7:10/0 = 0 870 | 8:10/0 = 0 871 | 9:10/0 = 0 872 | 10:10/0 = 0 873 | 11:10/0 = 0 874 | 12:10/0 = 0 875 | 13:10/0 = 0 876 | 14:10/0 = 0 877 | 15:10/0 = 0 878 | 16:10/0 = 0 879 | 17:10/0 = 0 880 | 18:10/0 = 0 881 | 19:10/0 = 0 882 | 20:10/0 = 0 883 | 21:10/0 = 0 884 | 22:10/0 = 0 885 | 23:10/0 = 0 886 | 24:10/0 = 0 887 | 25:10/0 = 0 888 | 26:10/0 = 0 889 | 27:10/0 = 0 890 | 28:10/0 = 0 891 | 29:10/0 = 0 892 | 30:10/0 = 0 893 | 31:10/0 = 0 894 | 32:10/0 = 0 895 | 33:10/0 = 0 896 | 34:10/0 = 0 897 | 35:10/0 = 0 898 | 36:10/0 = 0 899 | 37:10/0 = 0 900 | 38:10/0 = 0 901 | 39:10/0 = 0 902 | 40:10/0 = 0 903 | 41:10/0 = 0 904 | 42:10/0 = 0 905 | 43:10/0 = 0 906 | 44:10/0 = 0 907 | 45:10/0 = 0 908 | 46:10/0 = 0 909 | 47:10/0 = 0 910 | 48:10/0 = 0 911 | 49:10/0 = 0 912 | 50:10/0 = 0 913 | 51:10/0 = 0 914 | 52:10/0 = 0 915 | 53:10/0 = 0 916 | 54:10/0 = 0 917 | 55:10/0 = 0 918 | 56:10/0 = 0 919 | 57:10/0 = 0 920 | 58:10/0 = 0 921 | 59:10/0 = 0 922 | 60:10/0 = 0 923 | 61:10/0 = 0 924 | 62:10/0 = 0 925 | 63:10/0 = 0 926 | 64:10/0 = 0 927 | 65:10/0 = 0 928 | 66:10/0 = 0 929 | 67:10/0 = 0 930 | 68:10/0 = 0 931 | 69:10/0 = 0 932 | 70:10/0 = 0 933 | 71:10/0 = 0 934 | 72:10/0 = 0 935 | 73:10/0 = 0 936 | 74:10/0 = 0 937 | 75:10/0 = 0 938 | 76:10/0 = 0 939 | 77:10/0 = 0 940 | 78:10/0 = 0 941 | 79:10/0 = 0 942 | 80:10/0 = 0 943 | 81:10/0 = 0 944 | 82:10/0 = 0 945 | 83:10/0 = 0 946 | 84:10/0 = 0 947 | 85:10/0 = 0 948 | 86:10/0 = 0 949 | 0:11/0 = 0 950 | 1:11/0 = 0 951 | 2:11/0 = 0 952 | 3:11/0 = 0 953 | 4:11/0 = 0 954 | 5:11/0 = 0 955 | 6:11/0 = 0 956 | 7:11/0 = 0 957 | 8:11/0 = 0 958 | 9:11/0 = 0 959 | 10:11/0 = 0 960 | 11:11/0 = 0 961 | 12:11/0 = 0 962 | 13:11/0 = 0 963 | 14:11/0 = 0 964 | 15:11/0 = 0 965 | 16:11/0 = 0 966 | 17:11/0 = 0 967 | 18:11/0 = 0 968 | 19:11/0 = 0 969 | 20:11/0 = 0 970 | 21:11/0 = 0 971 | 22:11/0 = 0 972 | 23:11/0 = 0 973 | 24:11/0 = 0 974 | 25:11/0 = 0 975 | 26:11/0 = 0 976 | 27:11/0 = 0 977 | 28:11/0 = 0 978 | 29:11/0 = 0 979 | 30:11/0 = 0 980 | 31:11/0 = 0 981 | 32:11/0 = 0 982 | 33:11/0 = 0 983 | 34:11/0 = 0 984 | 35:11/0 = 0 985 | 36:11/0 = 0 986 | 37:11/0 = 0 987 | 38:11/0 = 0 988 | 39:11/0 = 0 989 | 40:11/0 = 0 990 | 41:11/0 = 0 991 | 42:11/0 = 0 992 | 43:11/0 = 0 993 | 44:11/0 = 0 994 | 45:11/0 = 0 995 | 46:11/0 = 0 996 | 47:11/0 = 0 997 | 48:11/0 = 0 998 | 49:11/0 = 0 999 | 50:11/0 = 0 1000 | 51:11/0 = 0 1001 | 52:11/0 = 0 1002 | 53:11/0 = 0 1003 | 54:11/0 = 0 1004 | 55:11/0 = 0 1005 | 56:11/0 = 0 1006 | 57:11/0 = 0 1007 | 58:11/0 = 0 1008 | 59:11/0 = 0 1009 | 60:11/0 = 0 1010 | 61:11/0 = 0 1011 | 62:11/0 = 0 1012 | 63:11/0 = 0 1013 | 64:11/0 = 0 1014 | 65:11/0 = 0 1015 | 66:11/0 = 0 1016 | 67:11/0 = 0 1017 | 68:11/0 = 0 1018 | 69:11/0 = 0 1019 | 70:11/0 = 0 1020 | 71:11/0 = 0 1021 | 72:11/0 = 0 1022 | 73:11/0 = 0 1023 | 74:11/0 = 0 1024 | 75:11/0 = 0 1025 | 76:11/0 = 0 1026 | 77:11/0 = 0 1027 | 78:11/0 = 0 1028 | 79:11/0 = 0 1029 | 80:11/0 = 0 1030 | 81:11/0 = 0 1031 | 82:11/0 = 0 1032 | 83:11/0 = 0 1033 | 84:11/0 = 0 1034 | 85:11/0 = 0 1035 | 86:11/0 = 0 1036 | 1037 | [resource] 1038 | tile_size = Vector2i(200, 200) 1039 | sources/0 = SubResource("TileSetAtlasSource_46vqo") 1040 | --------------------------------------------------------------------------------