Compare commits

..

84 Commits

Author SHA1 Message Date
Aaron Franke
52e3004465 [4.3] Simplify list of branches in the README (#1255) 2025-10-02 17:10:26 -07:00
utsav132
5557b10cfa Fix mob playback animation being started before the animation is set in Dodge the Creeps (#1175)
The '$AnimatedSprite2D.play()' is called at the beginning in the '_ready' function,
when it should actually be called at the end, after selecting the animation.
2025-03-07 19:43:58 +01:00
Hugo Locurcio
fdb2f50a20 Add a graphics tablet input demo (#1162) 2025-02-10 18:17:34 +01:00
Jason Yundt
0d46333c4e Update Platformer 2D to Godot 4.3 (#1145)
* Update Platformer 2D to Godot v4.3

Before this change, if you tries to import the Platformer 2D project
using Godot v4.3 (the latest stable version of Godot, at the moment),
you would get the following warning:

> Warning: This project was last edited in Godot 4.2.
> Opening will change it to Godot 4.3.
>
> Open anyway? Project will be modified.

This change updates the project to Godot 4.3 so that that warning no
longer appears. When you upgrade to a newer version of Godot, sometimes
certain files will automatically be updated by the Godot Editor after
the upgrade has been completed. Specifically, the files won’t get
updated until after they’re opened in the Godot Editor. When creating
this commit, I tried to open every single file for Platformer 2D in the
Godot Editor to make sure that all of those automatic changes are
included in this commit.

* Replace Platformer2D’s TileMap with a TileMapLayer

Before this change, the Platformer 2D used a TileMap Node. TileMaps are
deprecated. TileMapLayers should be used instead [1].

[1]: <https://docs.godotengine.org/en/4.3/classes/class_tilemap.html#tilemap>
2025-02-06 15:23:15 +01:00
Hugo Locurcio
c3b0331d8a Fix invalid icon reference in C# Android IAP demo (#1159) 2025-01-21 02:39:47 +01:00
Wayne Mwashuma
0e24c8eb2e Update to TileMapLayer in Multiplayer Bomber demo (#1155) 2025-01-10 22:39:38 +01:00
Mohamed Koubaa
be77353917 Move position setting code to be before direction in Dodge the Creeps (#1151) 2025-01-10 19:52:54 +01:00
Fabio Alessandrelli
d3c71ddb20 Fix typo in WebSocketServer class name (#1154) 2025-01-10 19:51:29 +01:00
David Briscoe
c49e134e13 Explain how to setup GUI in 3D (#1149)
Make it more obvious to newcomers how this demo works so they can
replicate it in their projects.

Change the text to point to how this is working.

Add Editor Descriptions to make it clearer how this is setup.

Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
2024-12-23 18:55:20 +01:00
Jorrit Rouwe
81249b3f4a Increase Jolt Physics limit settings so performance tests run without errors (#1146) 2024-12-13 16:39:29 +01:00
Aaron Franke
51a7d389af Merge pull request #1138 from Calinou/truck-town-add-moods
Add moods (times of day) to Truck Town demo
2024-11-25 12:05:53 -08:00
Hugo Locurcio
5f0e0ce205 Improve GUI in 3D demo (#1140)
- Increase physics ticks per second to 120, so that UI interactions feel
  smoother and have lower input lag. This happens since input is governed
  by the physics tick due to the use of physics picking.
- Add a placeholder to the LineEdit and select a default option in the OptionButton.
2024-11-25 12:04:29 -08:00
Markus Sauermann
6f44371df1 Fix physics picking in Gui in 3D Demo (#1139)
Physics picking requires that the SubViewport has a consistent state
of the mouse-enter/exit notifications.

Godot V4.3 was changed in comparison to V4.2, so that it now requires
this additional step.

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
2024-11-25 18:38:26 +01:00
Hugo Locurcio
15bcb941de Add moods (times of day) to Truck Town demo
Four moods are available: sunrise, day, sunset, night. Sunset and night
also feature artificial point lights placed in the town scene.

The mood can be set on the main menu before playing. It can also be cycled
during gameplay by pressing M or D-Pad Down.
2024-11-25 18:35:05 +01:00
Aaron Franke
5d9542113a Improve Truck Town model, fix issues, use OMI glTF Physics (#1110) 2024-11-25 06:56:02 -08:00
smix8
0fb1b4e09c Update 2D navigation demo NavigationPolygon for 4.3+ (#1135)
Updates NavigationPolygon with data that has compatibility with newer 2D navigation mesh baking.
2024-11-17 00:32:38 +01:00
Yaxian
1e02914267 Use TileMapLayer in Dynamic TileMap Layers (#1133)
TileMap is deprecated in 4.3 as TileMapLayer supersedes it.

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2024-11-15 19:04:15 +01:00
Bastiaan Olij
6db1062768 Fix recenter code in OpenXR Character Centric Movement (#1131)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
2024-11-15 19:03:19 +01:00
Hugo Locurcio
adf6d7e08d Disable non-functional XR demos in web exports (#1130)
These demos could work if they are redesigned to account for WebXR's
limitations when running on the web platform.
2024-11-08 11:33:19 +01:00
Danil Alexeev
c492e5fd73 Update some GDScript files for Godot 4.3 (#1129) 2024-11-04 12:00:59 +01:00
Hugo Locurcio
7ed5b1c116 Update web demo exports for Godot 4.3 (#1127)
This comes with other improvements:

- Demos now work on desktop and mobile browsers, as ETC2 import is now
  automatically enabled before exporting each demo.
- Progressive web app is available for each project.
  - Can be added to the home screen on a device for a closer-to-native experience.
  - Cross-origin isolation headers are automatically added, so that the export
    works with threads enabled despite being hosted on GitHub Pages
    (which doesn't send these headers).

Several demos will need further tweaks to look better when using
the Compatibility rendering method. Currently, many 3D demos appear
too bright due to lights with shadows enabled using sRGB blending.

Also, many demos will need to be modified to indicate which parts
of them are not supported when running on the web platform, or
when using the Compatibility rendering method.
2024-10-30 17:13:23 +01:00
Hugo Locurcio
53d3f9cdde Improve Operating System Testing demo (#1124)
- Display more return values of Engine/OS methods such as system fonts,
  memory information and security information.
- Add headless support (the generated report is also printed to stdout).
- Improve theming in the generated report.
- Hide video adapter type if this information can't be queried in the
  current rendering method.
- Update C# script for Godot 4.x platform names.
2024-10-23 23:09:23 +02:00
Hugo Locurcio
edccce8563 Fix normal map direction in 2D Lights and Shadows (#1123)
- Group Light2D nodes for easier dragging in the editor.
2024-10-18 23:30:07 +02:00
Raymond DiDonato
a87fded4cf Fix VRAM leak in compositor effect demo (#1115) 2024-09-17 01:36:20 +02:00
Montandalar
fdae025495 Add full license information for Voxel demo textures (#1113) 2024-09-15 15:04:34 +02:00
Tyler Breisacher
fa6061c623 Add static types in 2D Navigation AStar demo (#1008) 2024-08-31 03:48:17 +02:00
Ryhon
8ab921d5b4 Add FSR 2.2, exclusive fullscreen and ultra SSAO/SSIL to 3D Graphics Settings demo 2024-08-31 03:21:22 +02:00
shahriarlabib000
723331f814 updated README and Screenshots (#1111) 2024-08-28 18:09:22 -07:00
JavierStark
71630e80e4 Fix updated Android IAP project in c# (#1105)
* Update project to 4.3

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2024-08-28 16:58:41 -07:00
Aaron Franke
5646c6a7a8 Open and save 3D demos in Godot 4.3 stable (#1109) 2024-08-27 13:40:06 -07:00
Hugo Locurcio
582229e17c Improve Material Testers demo project (#1068)
- Add reflection probes for each test sphere, which can be toggled using
  a new dropdown with 3 options (no reflection probe, reflection only,
  reflection + ambient). The cull and reflection masks are configured
  on each reflection probe so that spheres don't self-reflect, but other
  spheres still appear in each sphere's reflections. Probe extents are made
  very large to prevent any visible fading, and the test beds don't
  receive the reflection probe's ambient or reflection.
- Improve ice material visuals by giving it some opacity.
- Use lossless compression on all textures, as their relatively low
  resolution and count by today's standards makes them not use much VRAM
  anyway.
2024-08-27 05:32:12 -07:00
Christen Lofland
7e2a55aa07 3D Inverse Kinematics Godot 4 Conversion (Partial) (#1036)
* These changes allow the project to start and run in Godot 4.2

I hit some of the files with my formatter, if whitespace updates are not wanted I can remove those.
The project doesn't entirely work yet, but it runs. I am still working on making it work properly fully, but at least it starts now instead of crashing.

* Center text to match Godot 3 example better.
2024-08-27 05:13:54 -07:00
shahriarlabib000
b05fb07d77 updated meshes to obj instead of res (#1107) 2024-08-27 05:06:22 -07:00
Mikael Hermansson
7e60538469 Change semi-truck in Truck Town demo to use 6DOF joint (#1102) 2024-08-27 04:31:10 -07:00
shahriarlabib000
9f59648c26 Update robot mesh for Godot 4 in 3D in 2D demo (#1106) 2024-08-26 00:07:36 +02:00
JavierStark
13b2787173 Update Android IAP in C# project to Godot 4.3 (#1104)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2024-08-23 04:00:10 +02:00
Rémi Verschelde
6c635fe75a Merge pull request #1080 from BastiaanOlij/openxr_composition_layers
OpenXR composition layer example
2024-08-22 07:35:28 +02:00
Zi Fan
6d5ded3c7d Fix incorrect asset library link in 3D Lights and Shadows README (#1100) 2024-08-11 02:15:38 +02:00
smix8
cbb68060c6 Add navigation mesh chunks demos (#1099)
Adds 2D and 3D demo project for how to bake navigation meshes for large world chunk systems.
2024-08-08 17:22:47 +02:00
esainane
0fba875c72 Fix theme properties in various demos (#1097)
3.x -> 4.x:
`font_color_shadow` -> `font_shadow_color`
`font_color_selected` -> `font_selected_color`
`hseparation` -> `h_separation`
`vseparation` -> `v_separation`
`shadow_as_outline` -> `shadow_outline_size`

`panelf` and `panelnc` were removed in 3.2, as the options were never used.
See: godotengine/godot#28639

`font_color_shadow` is not a property of ProgressBar's theme, and there
doesn't seem to be an equivalent. The term "shadow" does not appear in any of:
{scene/{gui/{progress_bar,range,control},main/{canvas_item,node}},core/object/object}.{cpp,h}
2024-08-02 03:01:04 -07:00
Bastiaan Olij
98899881e7 OpenXR composition layer example 2024-07-31 15:44:50 +10:00
Fabio Alessandrelli
8fd41702c6 Fix typing errors in webrtc_signaling demo (#1096) 2024-07-28 01:35:33 +02:00
Russell Sanborn
34d174e315 Add JetBrains IDE files to .gitignore (#1094)
For reference, this exists in other godotengine repositories. Examples:

* https://github.com/godotengine/godot/blob/master/.gitignore#L157
* https://github.com/godotengine/godot-docs/blob/master/.gitignore#L52
2024-07-26 17:44:57 +02:00
Rémi Verschelde
3265d3fcd4 Merge pull request #1082 from Calinou/add-2d-polygons-lines-demo-4.x
Add a 2D polygons and lines demo
2024-07-25 13:31:10 +02:00
Russell Sanborn
7d42ae3c9a Rename Dodge The Creeps files to snake case (#1084)
This follows the style guide:

- https://docs.godotengine.org/en/stable/tutorials/best_practices/project_organization.html#style-guide

For reference, a documentation PR exists to update references to the
demo.
2024-07-15 00:36:11 +02:00
Matthew
e6fcf24f89 Merge pull request #973 from BastiaanOlij/openxr_hand_tracking_demo
Add OpenXR hand tracking demo
2024-07-13 15:04:58 -04:00
Hugo Locurcio
16d8ba09fb Replace instances of KinematicBody with CharacteBody in READMEs
KinematicBody was replaced by CharacterBody in Godot 4.0.

This also adds the 3D suffix to 3D physics classes.
2024-07-12 23:06:00 +02:00
Hugo Locurcio
7223aec001 Fix incorrect static typing in 2.5D demo 2024-07-03 17:18:29 +02:00
Hugo Locurcio
0ec2fff5bf Fix incorrect typed Array assignment in XR demo scripts (#1081) 2024-06-26 17:20:58 +02:00
Hugo Locurcio
78bbd99f0d Add a 2D polygons and lines demo 2024-06-25 18:09:34 +02:00
ShatteredReality
b4c73f4888 Fix README links to asset library (#1078)
This updates all links to point to the 4.2 demos instead of the 3.5 ones.

Co-authored-by: A Thousand Ships (she/her) <96648715+AThousandShips@users.noreply.github.com>
2024-06-24 19:29:58 +02:00
Bastiaan Olij
677dc46eeb Add OpenXR hand tracking demo 2024-06-15 14:04:49 +10:00
Hugo Locurcio
fbb7cb442c Fix ball speedup logic in Pong demo (#1073) 2024-06-13 12:31:10 +02:00
Bastiaan Olij
909331ac51 Add Compositor Effects (Post-Processing) demo (#1058)
Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2024-06-07 22:19:25 +02:00
Hugo Locurcio
785e3213d5 Use higher shadow filtering quality settings in 3D demos (#1067)
The 3D demos aren't very demanding and Godot has been optimized
a bit since 4.0's release, so we can afford using higher quality
shadow settings for less noisy shadow filtering.

This also tweaks shadow bias to reduce shadow acne in the Voxel demo.

The time slider in the Physical Light and Camera units demo now
allows for more precise adjustments.
2024-06-06 22:11:18 +02:00
Hugo Locurcio
fad6cc2e1b Add turbulence example to 3D Particles demo (#1066)
- Make the attractor in the example dynamic to better showcase its functionality,
  and add a visual representation to it.
- Tweak the appearance of attracted particles.
- Fix force field particle display (it wasn't using Local Coords as intended).
- Lower the sun angle to make the background darker (and particles easier to see).
2024-06-06 22:07:00 +02:00
Hugo Locurcio
9a0c857131 Fix incorrect class_name declarations being swapped with extends
This was caused by an automatic text replacement issue.
2024-06-03 20:13:55 +02:00
Hugo Locurcio
bac1e69164 Use static typing in all demos (#1063)
This leads to code that is easier to understand and runs
faster thanks to GDScript's typed instructions.

The untyped declaration warning is now enabled on all projects
where type hints were added. All projects currently run without
any untyped declration warnings.

Dodge the Creeps and Squash the Creeps demos intentionally don't
use type hints to match the documentation, where type hints haven't
been adopted yet (given its beginner focus).
2024-06-01 12:12:18 +02:00
Sectonidse
8e9c180278 Use match case instead of if else in Audio Mic Record demo (#1053)
* Use match case instead of if else

This is my first pull request.

* Apply suggestions from code review

---------

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
2024-05-13 19:57:04 +02:00
Christen Lofland
3859c66f0e Remove modulate/albedo mix changes from Distance Fade example in Decals (#1054) 2024-05-13 19:50:07 +02:00
Tarik Belabbas
9a5176e430 Fixed minor Godot 3 bit in "gui_in_3d" demo's billboard specific code (#1052) 2024-05-06 23:04:36 -07:00
谢天
95cfb076d1 Add missing tags to several demos (#1048) 2024-04-18 22:24:47 +02:00
Colter
9043224bb2 Fix upward movement key to be W in Multiplayer Bomber (#1049)
It was accidentally set to Z instead.
2024-04-18 22:23:59 +02:00
Lisandro Lorea
01db4a6f99 Fix joypad demo for Godot 4.x (#943) 2024-04-13 14:50:02 -07:00
Bastiaan Olij
035e905a3e XR demos: Add check for VRS/foveation in start vr script, and enable foveation in project settings (#1022)
Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
2024-04-12 14:16:23 -07:00
Christen Lofland
b2ed2d6f6d Remove tiles outside of texture to elliminate these errors on loading the project: (#1035)
```
ERROR: Cannot create tile. The tile is outside the texture or tiles are already present in the space the tile would cover.
   at: (scene\resources\2d\tile_set.cpp:4963)
ERROR: The TileSetAtlasSource atlas has no tile at (1, 0).
   at: (scene\resources\2d\tile_set.cpp:5400)
ERROR: TileSetAtlasSource has no tile at (1, 0).
   at: (scene\resources\2d\tile_set.cpp:5348)
```
2024-04-12 14:16:04 -07:00
captain-redbeard
fbef18f58b Updated Dodge the Creeps C# to Godot mono 4.2 (#1000)
Co-authored-by: Ivan Shakhov <van800@gmail.com>
Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
2024-04-12 00:56:02 -07:00
Hugo Locurcio
4f866f2a9a Add doors as an example of dynamic occluders in the Occlusion culling demo (#807)
The occluders don't actually move, but are toggled when the door starts
opening and finishes closing to avoid unnecessary BVH rebuilds.
2024-04-11 21:07:55 -07:00
Muller-Castro
af93126e05 Fix missing baked_exposure (#1043) 2024-04-11 20:57:52 -07:00
Hugo Locurcio
5bda007763 Update GUI Translation demo for 4.0 (#930)
- Add PO support in addition to CSV.

Co-authored-by: SkyJJ <jjchai01@hotmail.com>
2024-04-11 20:55:49 -07:00
Christen Lofland
f70868ce22 Use @onready to init previous_position to prevent errors (#1042) 2024-04-11 20:36:15 -07:00
Aaron Franke
6e44341d67 Merge pull request #1041 from chrisl8/2.5d-editor-view-update
Update 2.5D GDScript demo to display the editor plugin in Godot 4.
2024-04-11 20:33:37 -07:00
Aaron Franke
3788da41cd Fix 2.5D editor viewport and gizmo for Godot 4.x 2024-04-11 20:30:58 -07:00
Aaron Franke
57c1cb9ffa More tweaks to the 2.5D demo for Godot 4.x 2024-04-11 13:50:34 -07:00
Christen Lofland
85b8f10778 Prefer using guard clauses as suggested by aaronfranke. 2024-04-10 16:33:46 -05:00
Christen Lofland
0a35055aa0 Undue some formatting changes that were in dispute. 2024-04-10 16:31:51 -05:00
Christen Lofland
3ef6a15741 Update 2.5D GDScript demo to display the editor plugin in Godot 4. 2024-04-10 11:52:08 -05:00
Christen Lofland
d190e73ad3 Only print MIDI device list if any are found in MIDI Piano (#1039)
This is a silly "fix", but it prevents an empty `[]` from being printed every time
this demo is run without a MIDI device plugged into the computer.

The MIDI devices list is printed if one is plugged into the computer, which I have tested.
2024-04-10 01:30:09 +02:00
Clay John
79d30931c3 Switch to single safe threaded model in TextureRD demo (#1038)
Multithreaded rendering is not safe in 4.2, so it should not be used
in our official demos for now.
2024-04-09 02:09:27 +02:00
iltenahmet
56f103953d Update dodge-the-creeps asset library link (#1034) 2024-04-03 15:32:10 -07:00
Christen Lofland
be7be4c1cc Disable 2D MSAA in Dynamic TileMap Layers to avoid warning on start (#1030)
The demo uses the Compatibility rendering method, which currently
doesn't support 2D MSAA.
2024-04-02 03:19:56 +02:00
Christen Lofland
5553ecfd88 Fix font code for Godot 4 in Finite State Machine (#1027)
This clears out some errors that happen on every load of this demo in Godot 4 onward.
It also makes the fonts actually work, as they did not before.

We probably don't strictly **need** these font settings for a demo, but they were here before.

I don't think `SourceCodePro-Black.ttf` was ever used, based on looking at history. So I removed it.

Both `.tres` files are gone too, as those are not used in Godot 4.

I have updated everything that used `SourceCodePro-Bold.ttf` to the new setup.
2024-04-02 01:52:04 +02:00
Christen Lofland
ab9ffb7558 Fix font setup in Dodge the Creeps (#1026) 2024-04-02 01:50:12 +02:00
谢天
c181965682 Fix incorrect toggle_mouse_capture key in Global Illumination (#1029) 2024-04-02 01:21:01 +02:00
968 changed files with 20930 additions and 7996 deletions

View File

@@ -1,23 +1,41 @@
[preset.0] [preset.0]
name="HTML5" name="Web"
platform="HTML5" platform="Web"
runnable=true runnable=true
advanced_options=false
dedicated_server=false
custom_features="" custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="*.json" include_filter=""
exclude_filter="" exclude_filter=""
export_path="" export_path=""
script_export_mode=1 encryption_include_filters=""
script_encryption_key="" encryption_exclude_filters=""
encrypt_pck=false
encrypt_directory=false
script_export_mode=2
[preset.0.options] [preset.0.options]
custom_template/debug="" custom_template/debug=""
custom_template/release="" custom_template/release=""
variant/export_type=0 variant/extensions_support=false
variant/thread_support=true
vram_texture_compression/for_desktop=true vram_texture_compression/for_desktop=true
vram_texture_compression/for_mobile=false vram_texture_compression/for_mobile=true
html/export_icon=true
html/custom_html_shell="" html/custom_html_shell=""
html/head_include="" html/head_include=""
html/full_window_size=true html/canvas_resize_policy=2
html/focus_canvas_on_start=true
html/experimental_virtual_keyboard=true
progressive_web_app/enabled=true
progressive_web_app/ensure_cross_origin_isolation_headers=true
progressive_web_app/offline_page=""
progressive_web_app/display=0
progressive_web_app/orientation=1
progressive_web_app/icon_144x144=""
progressive_web_app/icon_180x180=""
progressive_web_app/icon_512x512=""
progressive_web_app/background_color=Color(0, 0, 0, 1)

View File

@@ -1,20 +1,38 @@
<!-- The list of demos will be inserted above by the CI process. --> <!-- The list of demos will be inserted above by the CI process. -->
</ul> </ul>
<h2>Unavailable demos</h2> <h2>Unavailable demos</h2>
<ul> <ul class="unsupported-demos">
<li><code>2d/hdr/</code>: Not supported on HTML5 yet.</li> <li><code>2d/glow</code>: Not supported on the Compatibility rendering method (which the web platform always uses).</li>
<li><code>3d/global_illumination/</code>: Not supported on HTML5 yet (freezes the browser).</li> <li><code>2d/navigation_mesh_chunks</code>: Relies on debug-only drawing functionality which is not available in projects exported in release mode.</li>
<li><code>3d/voxel/</code>: Not supported on HTML5 yet.</li> <li><code>2d/physics_tests</code>: Relies on debug-only drawing functionality which is not available in projects exported in release mode.</li>
<li><code>audio/device_changer/</code>: Not supported on HTML5 due to browser limitations.</li> <li><code>3d/labels_and_texts</code>: Does not export in headless mode due to an engine bug (font importing infinite loop).</li>
<li><code>loading/background_load/</code>: Not supported on HTML5 yet.</li> <li><code>3d/decals</code>: Not supported on the Compatibility rendering method (which the web platform always uses).</li>
<li><code>loading/multiple_threads_loading/</code>: Not supported on HTML5 yet.</li> <li><code>3d/ik</code>: Demo is not fully ported to Godot 4 yet (even though the feature works on the web).</li>
<li><code>loading/threads/</code>: Not supported on HTML5 yet.</li> <li><code>3d/navigation_mesh_chunks</code>: Relies on debug-only drawing functionality which is not available in projects exported in release mode.</li>
<li><code>misc/matrix_transform/</code>: Results are only visible in the editor.</li> <li><code>3d/occlusion_culling_mesh_lod</code>: Occlusion culling is disabled by default in web builds to decrease binary size.</li>
<li><code>mobile/android_iap/</code>: Only relevant on native Android.</li> <li><code>3d/particles</code>: Demo mostly showcases features that are not available in Compatibility (which the web platform always uses).</li>
<li><code>mobile/sensors/</code>: Not supported on HTML5 yet.</li> <li><code>3d/physical_light_camera_units</code>: Demo is not tuned for the Compatibility rendering method (which the web platform always uses).</li>
<li><code>mono/*/</code>: Not available yet (requires Mono-enabled HTML5 build).</li> <li><code>3d/physics_tests</code>: Relies on debug-only drawing functionality which is not available in projects exported in release mode.</li>
<li><code>networking/*/</code>: Doesn't make sense to be hosted on a static host, as the server must be hosted on the same origin due to the browser's same-origin policy.</li> <li><code>3d/variable_rate_shading</code>: Not supported on the Compatibility rendering method (which the web platform always uses)</li>
<li><code>plugins/*/</code>: Only effective within the editor.</li> <li><code>3d/volumetric_fog</code>: Not supported on the Compatibility rendering method (which the web platform always uses)</li>
<li><code>3d/voxel</code>: Freezes after a few seconds of gameplay due to web platform-specific threading issues.</li>
<li><code>audio/bpm_sync</code>: Not functional on the web platform due to differences in the audio playback implementation.</li>
<li><code>audio/device_changer</code>: Not relevant for the web platform, as the web browser always chooses the audio output device.</li>
<li><code>audio/midi_piano</code>: Not functional on the web platform due to differences in the audio playback implementation.</li>
<li><code>audio/spectrum</code>: Not functional on the web platform due to differences in the audio playback implementation.</li>
<li><code>compute/*</code>: Not supported on the Compatibility rendering method (which the web platform always uses).</li>
<li><code>gui/msdf_font</code>: Does not export in headless mode due to an engine bug (font importing crashes).</li>
<li><code>gui/translation</code>: Does not export in headless mode due to an engine bug (font importing crashes).</li>
<li><code>loading/runtime_save_load</code>: Native filesystem access is not available on the web platform.</li>
<li><code>misc/compute_shader_heightmap</code>: Not supported on the Compatibility rendering method (which the web platform always uses).</li>
<li><code>misc/large_world_coordinates</code>: Not supported on the Compatibility rendering method (which the web platform always uses).</li>
<li><code>misc/matrix_transform</code>: Results are only visible in the editor.</li>
<li><code>mobile/android_iap</code>: Only relevant on native Android.</li>
<li><code>mobile/sensors</code>: Not supported on the web platform.</li>
<li><code>mono/*</code>: Not available yet (requires Mono-enabled HTML5 build).</li>
<li><code>networking/*</code>: Doesn't make sense to be hosted on a static host, as the server must be hosted on the same origin due to the browser's same-origin policy.</li>
<li><code>plugins/*</code>: Only effective within the editor.</li>
<li><code>xr/*</code>: Not functional on the web platform, as these demos are not designed for WebXR.</li>
</ul> </ul>
</body> </body>
</html> </html>

View File

@@ -4,13 +4,15 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Godot demos exported to HTML5</title> <title>Official Godot demos exported to Web</title>
<style> <style>
:root { :root {
--background-color: #fff; --background-color: #fff;
--text-color: #222; --text-color: #222;
--link-color: hsl(220, 100%, 45%); --link-color: hsl(220, 100%, 45%);
--link-visited-color: hsl(270, 100%, 55%);
--link-underline-color: hsla(220, 100%, 45%, 0.3); --link-underline-color: hsla(220, 100%, 45%, 0.3);
--link-underline-visited-color: hsla(270, 100%, 45%, 0.3);
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
@@ -18,7 +20,9 @@
--background-color: #222; --background-color: #222;
--text-color: #eee; --text-color: #eee;
--link-color: hsl(200, 100%, 70%); --link-color: hsl(200, 100%, 70%);
--link-visited-color: hsl(250, 100%, 80%);
--link-underline-color: hsla(200, 100%, 70%, 0.3); --link-underline-color: hsla(200, 100%, 70%, 0.3);
--link-underline-visited-color: hsla(250, 100%, 70%, 0.3);
} }
} }
@@ -52,6 +56,11 @@
text-decoration-thickness: 0.125rem; text-decoration-thickness: 0.125rem;
} }
a:visited {
color: var(--link-visited-color);
text-decoration-color: var(--link-visited-color);
}
a:hover { a:hover {
filter: brightness(117.5%); filter: brightness(117.5%);
} }
@@ -88,6 +97,9 @@
margin: 20px 10px; margin: 20px 10px;
} }
.unsupported-demos li {
margin-bottom: 1.5rem;
}
</style> </style>
</head> </head>
@@ -96,12 +108,12 @@
<p> <p>
This page lists This page lists
<a href="https://github.com/godotengine/godot-demo-projects">official Godot demo projects</a> <a href="https://github.com/godotengine/godot-demo-projects">official Godot demo projects</a>
exported to HTML5 for testing purposes. These projects are deployed automatically exported to the web for testing purposes. These projects are deployed automatically
on every commit on the <code>master</code> branch of the repository. on every commit on the <code>master</code> branch of the repository.
</p> </p>
<p> <p>
The HTML5 exports on this page are provided for demonstration purposes only. The web exports on this page are provided for demonstration purposes only.
Some of these demos may not function or render correctly on HTML5, Some of these demos may not function or render correctly on the web platform,
especially on mobile devices. especially on mobile devices.
For best performance, it's recommended to For best performance, it's recommended to
<a href="https://godotengine.org/download">download</a> a native editor <a href="https://godotengine.org/download">download</a> a native editor
@@ -110,7 +122,7 @@
<p> <p>
See the See the
<a href="https://docs.godotengine.org/en/stable/getting_started/workflow/export/exporting_for_web.html">Exporting for the Web</a> <a href="https://docs.godotengine.org/en/stable/getting_started/workflow/export/exporting_for_web.html">Exporting for the Web</a>
documentation for information on exporting your own projects to HTML5. documentation for information on exporting your own projects to the web.
</p> </p>
<h2>List of demos</h2> <h2>List of demos</h2>

View File

@@ -1,100 +0,0 @@
name: Export projects to HTML5 and deploy to GitHub Pages
on:
push:
branches:
- master
env:
GODOT_VERSION: 3.3.3
jobs:
export-html5:
name: Export projects to HTML5 and deploy to GitHub Pages
runs-on: ubuntu-20.04
container:
image: barichello/godot-ci:3.3.3
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup
run: |
mkdir -p ~/.local/share/godot/templates/
mv /root/.local/share/godot/templates/$GODOT_VERSION.stable ~/.local/share/godot/templates/$GODOT_VERSION.stable
- name: Export projects to HTML5
run: |
apt-get update -qq && apt-get install -qqq imagemagick
# Don't export Mono demos (not supported yet), demos that can't be run in HTML5
# since they're platform-specific or demos that are currently broken in HTML5.
# Remember to update `.github/dist/footer.html` when updating the list of excluded demos.
rm -rf \
2d/hdr/ \
3d/global_illumination/ \
3d/voxel/ \
audio/device_changer/ \
loading/background_load/ \
loading/multiple_threads_loading/ \
loading/threads/ \
misc/matrix_transform/ \
mobile/android_iap/ \
mobile/sensors/ \
mono/ \
networking/ \
plugins/
for panorama in 3d/material_testers/backgrounds/*.hdr; do
# Decrease the resolution to get below the 20 MB per-file limit.
# Otherwise, the website can't be deployed as files larger than 20 MB
# can't be pushed to GitHub anymore.
mogrify -resize 75% "$panorama"
done
BASEDIR="$PWD"
# Use absolute paths so that we can `cd` without having to go back to the parent directory manually.
for demo in */*/; do
echo ""
echo "================================"
echo "Exporting demo $demo..."
echo "================================"
mkdir -p "$BASEDIR/.github/dist/$demo"
cd "$BASEDIR/$demo"
# Copy an export template preset file configured for HTML5 exporting.
# This way, we don't have to commit `export_presets.cfg` for each project.
cp "$BASEDIR/.github/dist/export_presets.cfg" .
godot --export "HTML5" "$BASEDIR/.github/dist/$demo/index.html"
# Replace the WASM file with a symbolic link to avoid duplicating files in the pushed branch.
# (WASM files are identical across projects, but not PCK or HTML files.)
mv -f "$BASEDIR/.github/dist/$demo/index.wasm" "$BASEDIR/.github/dist/index.wasm"
# The symlink must be relative as it needs to point to a file within the pushed repository.
ln -s "../../index.wasm" "$BASEDIR/.github/dist/$demo/index.wasm"
# Append the demo to the list of demos for the website.
PROJECT_NAME=$(cat project.godot | grep "config/name" | cut -d '"' -f 2 | tr -d "\n")
echo "<li><a href='$demo'><img width="64" height="64" src="$demo/favicon.png" alt=""><p>$PROJECT_NAME</p></a></li>" >> "$BASEDIR/.github/dist/demos.html"
done
cat "$BASEDIR/.github/dist/header.html" "$BASEDIR/.github/dist/demos.html" "$BASEDIR/.github/dist/footer.html" > "$BASEDIR/.github/dist/index.html"
# Clean up files that don't need to be deployed.
rm -f "$BASEDIR/.github/dist/header.html" "$BASEDIR/.github/dist/demos.html" "$BASEDIR/.github/dist/footer.html" "$BASEDIR/.github/dist/export_presets.cfg"
# Installing rsync is needed in order to deploy to GitHub Pages. Without it, the build will fail.
- name: Install rsync 📚
run: |
apt-get update -qq && apt-get install -qqq rsync
- name: Deploy to GitHub Pages 🚀
uses: JamesIves/github-pages-deploy-action@releases/v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# The branch the action should deploy to.
BRANCH: gh-pages
# The folder the action should deploy.
FOLDER: .github/dist
# Artifacts are large; don't keep the branch's history.
SINGLE_COMMIT: true

View File

@@ -4,10 +4,10 @@ on: [push, pull_request]
jobs: jobs:
format: format:
name: File formatting (file_format.sh) name: File formatting (file_format.sh)
runs-on: ubuntu-20.04 runs-on: ubuntu-24.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v5
- name: Install dependencies - name: Install dependencies
run: | run: |

3
.gitignore vendored
View File

@@ -21,3 +21,6 @@ mono_crash.*.json
.DS_Store .DS_Store
*~ *~
*.blend1 *.blend1
# Jetbrains IDE files
.idea/

View File

@@ -5,4 +5,4 @@ These demos are all 2D, but otherwise do not have a common theme.
Languages: Most have GDScript, some have Languages: Most have GDScript, some have
[Godot shader language](https://docs.godotengine.org/en/latest/tutorials/shaders/shader_reference/shading_language.html) [Godot shader language](https://docs.godotengine.org/en/latest/tutorials/shaders/shader_reference/shading_language.html)
Renderers: 4 of them are GLES 3, but most are GLES 2 Renderers: Glow for 2D and Physics Platformer use Forward+, 2D Particles uses Mobile, and the rest use Compatibility

View File

@@ -11,7 +11,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/887 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2711
## Screenshots ## Screenshots

View File

@@ -8,28 +8,28 @@ const BULLET_COUNT = 500
const SPEED_MIN = 20 const SPEED_MIN = 20
const SPEED_MAX = 80 const SPEED_MAX = 80
const bullet_image = preload("res://bullet.png") const bullet_image := preload("res://bullet.png")
var bullets := [] var bullets := []
var shape var shape := RID()
class Bullet: class Bullet:
var position = Vector2() var position := Vector2()
var speed = 1.0 var speed := 1.0
# The body is stored as a RID, which is an "opaque" way to access resources. # The body is stored as a RID, which is an "opaque" way to access resources.
# With large amounts of objects (thousands or more), it can be significantly # With large amounts of objects (thousands or more), it can be significantly
# faster to use RIDs compared to a high-level approach. # faster to use RIDs compared to a high-level approach.
var body = RID() var body := RID()
func _ready(): func _ready() -> void:
shape = PhysicsServer2D.circle_shape_create() shape = PhysicsServer2D.circle_shape_create()
# Set the collision shape's radius for each bullet in pixels. # Set the collision shape's radius for each bullet in pixels.
PhysicsServer2D.shape_set_data(shape, 8) PhysicsServer2D.shape_set_data(shape, 8)
for _i in BULLET_COUNT: for _i in BULLET_COUNT:
var bullet = Bullet.new() var bullet := Bullet.new()
# Give each bullet its own random speed. # Give each bullet its own random speed.
bullet.speed = randf_range(SPEED_MIN, SPEED_MAX) bullet.speed = randf_range(SPEED_MIN, SPEED_MAX)
bullet.body = PhysicsServer2D.body_create() bullet.body = PhysicsServer2D.body_create()
@@ -45,22 +45,22 @@ func _ready():
randf_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x, randf_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x,
randf_range(0, get_viewport_rect().size.y) randf_range(0, get_viewport_rect().size.y)
) )
var transform2d = Transform2D() var transform2d := Transform2D()
transform2d.origin = bullet.position transform2d.origin = bullet.position
PhysicsServer2D.body_set_state(bullet.body, PhysicsServer2D.BODY_STATE_TRANSFORM, transform2d) PhysicsServer2D.body_set_state(bullet.body, PhysicsServer2D.BODY_STATE_TRANSFORM, transform2d)
bullets.push_back(bullet) bullets.push_back(bullet)
func _process(_delta): func _process(_delta: float) -> void:
# Order the CanvasItem to update every frame. # Order the CanvasItem to update every frame.
queue_redraw() queue_redraw()
func _physics_process(delta): func _physics_process(delta: float) -> void:
var transform2d = Transform2D() var transform2d := Transform2D()
var offset = get_viewport_rect().size.x + 16 var offset := get_viewport_rect().size.x + 16
for bullet in bullets: for bullet: Bullet in bullets:
bullet.position.x -= bullet.speed * delta bullet.position.x -= bullet.speed * delta
if bullet.position.x < -16: if bullet.position.x < -16:
@@ -73,15 +73,15 @@ func _physics_process(delta):
# Instead of drawing each bullet individually in a script attached to each bullet, # Instead of drawing each bullet individually in a script attached to each bullet,
# we are drawing *all* the bullets at once here. # we are drawing *all* the bullets at once here.
func _draw(): func _draw() -> void:
var offset = -bullet_image.get_size() * 0.5 var offset := -bullet_image.get_size() * 0.5
for bullet in bullets: for bullet: Bullet in bullets:
draw_texture(bullet_image, bullet.position + offset) draw_texture(bullet_image, bullet.position + offset)
# Perform cleanup operations (required to exit without error messages in the console). # Perform cleanup operations (required to exit without error messages in the console).
func _exit_tree(): func _exit_tree() -> void:
for bullet in bullets: for bullet: Bullet in bullets:
PhysicsServer2D.free_rid(bullet.body) PhysicsServer2D.free_rid(bullet.body)
PhysicsServer2D.free_rid(shape) PhysicsServer2D.free_rid(shape)

View File

@@ -4,32 +4,32 @@ extends Node2D
# efficient than using instancing and nodes, but requires more programming and # efficient than using instancing and nodes, but requires more programming and
# is less visual. Bullets are managed together in the `bullets.gd` script. # is less visual. Bullets are managed together in the `bullets.gd` script.
# The number of bullets currently touched by the player. ## The number of bullets currently touched by the player.
var touching = 0 var touching := 0
@onready var sprite = $AnimatedSprite2D @onready var sprite: AnimatedSprite2D = $AnimatedSprite2D
func _ready(): func _ready() -> void:
# The player follows the mouse cursor automatically, so there's no point # The player follows the mouse cursor automatically, so there's no point
# in displaying the mouse cursor. # in displaying the mouse cursor.
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
func _input(event): func _input(event: InputEvent) -> void:
# Getting the movement of the mouse so the sprite can follow its position. # Getting the movement of the mouse so the sprite can follow its position.
if event is InputEventMouseMotion: if event is InputEventMouseMotion:
position = event.position - Vector2(0, 16) position = event.position - Vector2(0, 16)
func _on_body_shape_entered(_body_id, _body, _body_shape, _local_shape): func _on_body_shape_entered(_body_id: RID, _body: Node2D, _body_shape_index: int, _local_shape_index: int) -> void:
# Player got touched by a bullet so sprite changes to sad face. # Player got touched by a bullet so sprite changes to sad face.
touching += 1 touching += 1
if touching >= 1: if touching >= 1:
sprite.frame = 1 sprite.frame = 1
func _on_body_shape_exited(_body_id, _body, _body_shape, _local_shape): func _on_body_shape_exited(_body_id: RID, _body: Node2D, _body_shape_index: int, _local_shape_index: int) -> void:
touching -= 1 touching -= 1
# When non of the bullets are touching the player, # When non of the bullets are touching the player,
# sprite changes to happy face. # sprite changes to happy face.

View File

@@ -17,6 +17,10 @@ run/main_scene="res://shower.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"

View File

@@ -14,7 +14,7 @@ Renderer: Compatibility
Note: There is a C# version available [here](https://github.com/godotengine/godot-demo-projects/tree/master/mono/dodge_the_creeps). Note: There is a C# version available [here](https://github.com/godotengine/godot-demo-projects/tree/master/mono/dodge_the_creeps).
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/515 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2712
## Screenshots ## Screenshots

View File

@@ -1,6 +0,0 @@
[gd_resource type="Font" load_steps=2 format=3 uid="uid://dyjc58f6sdms0"]
[ext_resource type="FontData" uid="uid://cit6gwe5px1q8" path="res://fonts/Xolonium-Regular.ttf" id="1_mnk3h"]
[resource]
data/0 = ExtResource( "1_mnk3h" )

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://ccqoreueuxdb7"] [gd_scene load_steps=5 format=3 uid="uid://ccqoreueuxdb7"]
[ext_resource type="Script" path="res://HUD.gd" id="1"] [ext_resource type="Script" path="res://hud.gd" id="1"]
[ext_resource type="FontFile" uid="uid://cit6gwe5px1q8" path="res://fonts/Xolonium-Regular.ttf" id="2_2jm3i"]
[sub_resource type="InputEventAction" id="InputEventAction_fopy7"] [sub_resource type="InputEventAction" id="InputEventAction_fopy7"]
action = &"start_game" action = &"start_game"
@@ -16,6 +17,7 @@ anchors_preset = 10
anchor_right = 1.0 anchor_right = 1.0
offset_bottom = 78.0 offset_bottom = 78.0
grow_horizontal = 2 grow_horizontal = 2
theme_override_fonts/font = ExtResource("2_2jm3i")
theme_override_font_sizes/font_size = 60 theme_override_font_sizes/font_size = 60
text = "0" text = "0"
horizontal_alignment = 1 horizontal_alignment = 1
@@ -29,6 +31,7 @@ offset_top = -79.5
offset_bottom = 79.5 offset_bottom = 79.5
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
theme_override_fonts/font = ExtResource("2_2jm3i")
theme_override_font_sizes/font_size = 60 theme_override_font_sizes/font_size = 60
text = "Dodge the text = "Dodge the
Creeps" Creeps"
@@ -46,6 +49,7 @@ offset_right = 90.0
offset_bottom = -100.0 offset_bottom = -100.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 0 grow_vertical = 0
theme_override_fonts/font = ExtResource("2_2jm3i")
theme_override_font_sizes/font_size = 60 theme_override_font_sizes/font_size = 60
shortcut = SubResource("4") shortcut = SubResource("4")
text = "Start" text = "Start"

View File

@@ -29,12 +29,12 @@ func _on_MobTimer_timeout():
var mob_spawn_location = get_node(^"MobPath/MobSpawnLocation") var mob_spawn_location = get_node(^"MobPath/MobSpawnLocation")
mob_spawn_location.progress = randi() mob_spawn_location.progress = randi()
# Set the mob's direction perpendicular to the path direction.
var direction = mob_spawn_location.rotation + PI / 2
# Set the mob's position to a random location. # Set the mob's position to a random location.
mob.position = mob_spawn_location.position mob.position = mob_spawn_location.position
# Set the mob's direction perpendicular to the path direction.
var direction = mob_spawn_location.rotation + PI / 2
# Add some randomness to the direction. # Add some randomness to the direction.
direction += randf_range(-PI / 4, PI / 4) direction += randf_range(-PI / 4, PI / 4)
mob.rotation = direction mob.rotation = direction

View File

@@ -1,11 +1,11 @@
[gd_scene load_steps=8 format=3 uid="uid://cyfwty2q3rdse"] [gd_scene load_steps=8 format=3 uid="uid://cyfwty2q3rdse"]
[ext_resource type="Script" path="res://Main.gd" id="1"] [ext_resource type="Script" path="res://main.gd" id="1_0r6n5"]
[ext_resource type="PackedScene" uid="uid://rkdnhqgf2hpj" path="res://Mob.tscn" id="2"] [ext_resource type="PackedScene" uid="uid://rkdnhqgf2hpj" path="res://mob.tscn" id="2_50pww"]
[ext_resource type="PackedScene" uid="uid://4vwrqjegqwpj" path="res://Player.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://4vwrqjegqwpj" path="res://player.tscn" id="3_veqnc"]
[ext_resource type="PackedScene" uid="uid://ccqoreueuxdb7" path="res://HUD.tscn" id="4"] [ext_resource type="PackedScene" uid="uid://ccqoreueuxdb7" path="res://hud.tscn" id="4_0qnje"]
[ext_resource type="AudioStream" uid="uid://q2pf4fr8d0ks" path="res://art/House In a Forest Loop.ogg" id="5"] [ext_resource type="AudioStream" uid="uid://q2pf4fr8d0ks" path="res://art/House In a Forest Loop.ogg" id="5_55d8h"]
[ext_resource type="AudioStream" uid="uid://dw26fpygeag8o" path="res://art/gameover.wav" id="6"] [ext_resource type="AudioStream" uid="uid://dw26fpygeag8o" path="res://art/gameover.wav" id="6_hp1r0"]
[sub_resource type="Curve2D" id="1"] [sub_resource type="Curve2D" id="1"]
_data = { _data = {
@@ -14,8 +14,8 @@ _data = {
point_count = 5 point_count = 5
[node name="Main" type="Node"] [node name="Main" type="Node"]
script = ExtResource("1") script = ExtResource("1_0r6n5")
mob_scene = ExtResource("2") mob_scene = ExtResource("2_50pww")
[node name="ColorRect" type="ColorRect" parent="."] [node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 15 anchors_preset = 15
@@ -25,7 +25,7 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
color = Color(0.219608, 0.372549, 0.380392, 1) color = Color(0.219608, 0.372549, 0.380392, 1)
[node name="Player" parent="." instance=ExtResource("3")] [node name="Player" parent="." instance=ExtResource("3_veqnc")]
[node name="MobTimer" type="Timer" parent="."] [node name="MobTimer" type="Timer" parent="."]
wait_time = 0.5 wait_time = 0.5
@@ -44,13 +44,13 @@ curve = SubResource("1")
[node name="MobSpawnLocation" type="PathFollow2D" parent="MobPath"] [node name="MobSpawnLocation" type="PathFollow2D" parent="MobPath"]
[node name="HUD" parent="." instance=ExtResource("4")] [node name="HUD" parent="." instance=ExtResource("4_0qnje")]
[node name="Music" type="AudioStreamPlayer" parent="."] [node name="Music" type="AudioStreamPlayer" parent="."]
stream = ExtResource("5") stream = ExtResource("5_55d8h")
[node name="DeathSound" type="AudioStreamPlayer" parent="."] [node name="DeathSound" type="AudioStreamPlayer" parent="."]
stream = ExtResource("6") stream = ExtResource("6_hp1r0")
[connection signal="hit" from="Player" to="." method="game_over"] [connection signal="hit" from="Player" to="." method="game_over"]
[connection signal="timeout" from="MobTimer" to="." method="_on_MobTimer_timeout"] [connection signal="timeout" from="MobTimer" to="." method="_on_MobTimer_timeout"]

View File

@@ -1,9 +1,9 @@
extends RigidBody2D extends RigidBody2D
func _ready(): func _ready():
$AnimatedSprite2D.play()
var mob_types = Array($AnimatedSprite2D.sprite_frames.get_animation_names()) var mob_types = Array($AnimatedSprite2D.sprite_frames.get_animation_names())
$AnimatedSprite2D.animation = mob_types.pick_random() $AnimatedSprite2D.animation = mob_types.pick_random()
$AnimatedSprite2D.play()
func _on_VisibilityNotifier2D_screen_exited(): func _on_VisibilityNotifier2D_screen_exited():

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=10 format=3 uid="uid://rkdnhqgf2hpj"] [gd_scene load_steps=10 format=3 uid="uid://rkdnhqgf2hpj"]
[ext_resource type="Script" path="res://Mob.gd" id="1"] [ext_resource type="Script" path="res://mob.gd" id="1"]
[ext_resource type="Texture2D" uid="uid://yqglrrsx7j1f" path="res://art/enemyFlyingAlt_1.png" id="2"] [ext_resource type="Texture2D" uid="uid://yqglrrsx7j1f" path="res://art/enemyFlyingAlt_1.png" id="2"]
[ext_resource type="Texture2D" uid="uid://bpot8awhdn6ph" path="res://art/enemyFlyingAlt_2.png" id="3"] [ext_resource type="Texture2D" uid="uid://bpot8awhdn6ph" path="res://art/enemyFlyingAlt_2.png" id="3"]
[ext_resource type="Texture2D" uid="uid://bu4221t7qpa7d" path="res://art/enemyWalking_1.png" id="4"] [ext_resource type="Texture2D" uid="uid://bu4221t7qpa7d" path="res://art/enemyWalking_1.png" id="4"]

View File

@@ -47,7 +47,7 @@ func start(pos):
$CollisionShape2D.disabled = false $CollisionShape2D.disabled = false
func _on_Player_body_entered(_body): func _on_body_entered(_body):
hide() # Player disappears after being hit. hide() # Player disappears after being hit.
hit.emit() hit.emit()
# Must be deferred as we can't change physics properties on a physics callback. # Must be deferred as we can't change physics properties on a physics callback.

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=13 format=3 uid="uid://4vwrqjegqwpj"] [gd_scene load_steps=13 format=3 uid="uid://4vwrqjegqwpj"]
[ext_resource type="Script" path="res://Player.gd" id="1"] [ext_resource type="Script" path="res://player.gd" id="1"]
[ext_resource type="Texture2D" uid="uid://ftkxr8r4qghp" path="res://art/playerGrey_walk1.png" id="2"] [ext_resource type="Texture2D" uid="uid://ftkxr8r4qghp" path="res://art/playerGrey_walk1.png" id="2"]
[ext_resource type="Texture2D" uid="uid://couyhcegeihme" path="res://art/playerGrey_walk2.png" id="3"] [ext_resource type="Texture2D" uid="uid://couyhcegeihme" path="res://art/playerGrey_walk2.png" id="3"]
[ext_resource type="Texture2D" uid="uid://b4yyoafu8bi0q" path="res://art/playerGrey_up1.png" id="4"] [ext_resource type="Texture2D" uid="uid://b4yyoafu8bi0q" path="res://art/playerGrey_up1.png" id="4"]
@@ -72,4 +72,4 @@ process_material = SubResource("7")
texture = ExtResource("2") texture = ExtResource("2")
speed_scale = 2.0 speed_scale = 2.0
[connection signal="body_entered" from="." to="." method="_on_Player_body_entered"] [connection signal="body_entered" from="." to="." method="_on_body_entered"]

View File

@@ -18,7 +18,7 @@ This is a finished version of the game featured in the 'Your first 2D game'
tutorial in the documentation. For more details, consider tutorial in the documentation. For more details, consider
following the tutorial in the documentation." following the tutorial in the documentation."
config/tags=PackedStringArray("2d", "demo", "official") config/tags=PackedStringArray("2d", "demo", "official")
run/main_scene="res://Main.tscn" run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"

View File

@@ -8,6 +8,8 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2713
## Screenshots ## Screenshots
![Screenshot](screenshots/fake_wall.png) ![Screenshot](screenshots/fake_wall.png)

View File

@@ -1,17 +1,10 @@
extends TileMap extends TileMapLayer
# You can have multiple layers if you make this an array.
var secret_layer: int # You can have multiple layers if you make this an array. var player_in_secret := false
var player_in_secret: bool
var layer_alpha := 1.0 var layer_alpha := 1.0
func _init() -> void:
for i in get_layers_count(): # Find the secret layer by name.
if get_layer_name(i) == "Secret":
secret_layer = i
func _ready() -> void: func _ready() -> void:
set_process(false) set_process(false)
@@ -19,30 +12,31 @@ func _ready() -> void:
func _process(delta: float) -> void: func _process(delta: float) -> void:
if player_in_secret: if player_in_secret:
if layer_alpha > 0.3: if layer_alpha > 0.3:
layer_alpha = move_toward(layer_alpha, 0.3, delta) # Animate the layer transparency. # Animate the layer transparency.
set_layer_modulate(secret_layer, Color(1, 1, 1, layer_alpha)) layer_alpha = move_toward(layer_alpha, 0.3, delta)
self_modulate = Color(1, 1, 1, layer_alpha)
else: else:
set_process(false) set_process(false)
else: else:
if layer_alpha < 1.0: if layer_alpha < 1.0:
layer_alpha = move_toward(layer_alpha, 1.0, delta) layer_alpha = move_toward(layer_alpha, 1.0, delta)
set_layer_modulate(secret_layer, Color(1, 1, 1, layer_alpha)) self_modulate = Color(1, 1, 1, layer_alpha)
else: else:
set_process(false) set_process(false)
func _use_tile_data_runtime_update(layer: int, _coords: Vector2i) -> bool: func _use_tile_data_runtime_update(_coords: Vector2i) -> bool:
if layer == secret_layer: return true
return true
return false
func _tile_data_runtime_update(_layer: int, _coords: Vector2i, tile_data: TileData) -> void: func _tile_data_runtime_update(_coords: Vector2i, tile_data: TileData) -> void:
tile_data.set_collision_polygons_count(0, 0) # Remove collision for secret layer. # Remove collision for secret layer.
tile_data.set_collision_polygons_count(0, 0)
func _on_secret_detector_body_entered(body: Node2D) -> void: func _on_secret_detector_body_entered(body: Node2D) -> void:
if not body is CharacterBody2D: # Detect player only. if body is not CharacterBody2D:
# Detect the player only.
return return
player_in_secret = true player_in_secret = true
@@ -50,7 +44,7 @@ func _on_secret_detector_body_entered(body: Node2D) -> void:
func _on_secret_detector_body_exited(body: Node2D) -> void: func _on_secret_detector_body_exited(body: Node2D) -> void:
if not body is CharacterBody2D: if body is not CharacterBody2D:
return return
player_in_secret = false player_in_secret = false

View File

@@ -5,11 +5,11 @@ const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300 const STOP_FORCE = 1300
const JUMP_SPEED = 200 const JUMP_SPEED = 200
@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") @onready var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _physics_process(delta): func _physics_process(delta: float) -> void:
# Horizontal movement code. First, get the player's input. # Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right")) var walk := WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
# Slow down the player if they're not trying to move. # Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2: if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned. # The velocity, slowed down a bit, and then reassigned.

View File

@@ -1,17 +1,17 @@
[gd_scene load_steps=4 format=2] [gd_scene load_steps=4 format=3 uid="uid://1o70ce0fv10w"]
[ext_resource path="res://player/player.gd" type="Script" id=1] [ext_resource type="Script" path="res://player/player.gd" id="1"]
[ext_resource path="res://player/player.png" type="Texture2D" id=2] [ext_resource type="Texture2D" uid="uid://dfb8rr2fakwgp" path="res://player/player.png" id="2"]
[sub_resource type="RectangleShape2D" id=1] [sub_resource type="RectangleShape2D" id="1"]
extents = Vector2(7, 7) size = Vector2(14, 14)
[node name="Player" type="CharacterBody2D"] [node name="Player" type="CharacterBody2D"]
script = ExtResource( 1 ) script = ExtResource("1")
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource( 2 ) texture = ExtResource("2")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(-0.315559, 0.157784) position = Vector2(-0.315559, 0.157784)
shape = SubResource( 1 ) shape = SubResource("1")

View File

@@ -14,10 +14,15 @@ config/name="Dynamic TileMap Layers"
config/description="Example of how to make a kinematic character controller in 2D using config/description="Example of how to make a kinematic character controller in 2D using
CharacterBody2D. The character moves around, is affected by moving CharacterBody2D. The character moves around, is affected by moving
platforms, can jump through one-way collision platforms, etc." platforms, can jump through one-way collision platforms, etc."
config/tags=PackedStringArray("2d", "demo", "official", "tilemap")
run/main_scene="res://world.tscn" run/main_scene="res://world.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.3")
config/icon="res://icon.png" config/icon="res://icon.png"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/size/viewport_width=530 window/size/viewport_width=530
@@ -32,25 +37,25 @@ jump={
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null) "events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":32,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
move_left={ move_left={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) "events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
move_right={ move_right={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null) "events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) , Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
@@ -64,4 +69,3 @@ common/physics_ticks_per_second=120
renderer/rendering_method="gl_compatibility" renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility"
environment/defaults/default_clear_color=Color(0.156863, 0.133333, 0.25098, 1) environment/defaults/default_clear_color=Color(0.156863, 0.133333, 0.25098, 1)
anti_aliasing/quality/msaa_2d=2

View File

@@ -1,20 +1,15 @@
[gd_scene load_steps=8 format=3 uid="uid://de7qapkqfycxl"] [gd_scene load_steps=8 format=4 uid="uid://de7qapkqfycxl"]
[ext_resource type="Texture2D" uid="uid://cs8h2qyuakmko" path="res://level/obstacle.png" id="2"] [ext_resource type="Texture2D" uid="uid://cs8h2qyuakmko" path="res://level/obstacle.png" id="2"]
[ext_resource type="Script" path="res://level/tile_map.gd" id="2_q8fhk"] [ext_resource type="Script" path="res://level/tile_map.gd" id="2_q8fhk"]
[ext_resource type="PackedScene" path="res://player/player.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://1o70ce0fv10w" path="res://player/player.tscn" id="3"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_on5ov"] [sub_resource type="PhysicsMaterial" id="PhysicsMaterial_on5ov"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_vnjib"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_vnjib"]
texture = ExtResource("2") texture = ExtResource("2")
0:0/0 = 0 0:0/0 = 0
0:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
0:0/0/physics_layer_0/angular_velocity = 0.0
0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8) 0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:0/0 = 0
1:0/0/physics_layer_0/linear_velocity = Vector2(0, 0)
1:0/0/physics_layer_0/angular_velocity = 0.0
[sub_resource type="TileSet" id="TileSet_xqlka"] [sub_resource type="TileSet" id="TileSet_xqlka"]
physics_layer_0/collision_layer = 1 physics_layer_0/collision_layer = 1
@@ -26,19 +21,15 @@ size = Vector2(112, 48)
[node name="World" type="Node2D"] [node name="World" type="Node2D"]
[node name="TileMap" type="TileMap" parent="."] [node name="Ground" type="TileMapLayer" parent="."]
z_index = 1 use_parent_material = true
tile_map_data = PackedByteArray("AAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAkAAAAAAAAAAAAAAAoAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAA4AAAAAAAAAAAAAAA8AAAAAAAAAAAAAABAAAAAAAAAAAAAAABEAAAAAAAAAAAAAABIAAAAAAAAAAAAAABMAAAAAAAAAAAAAABQAAAAAAAAAAAAAABUAAAAAAAAAAAAAABYAAAAAAAAAAAAAABcAAAAAAAAAAAAAABgAAAAAAAAAAAAAABkAAAAAAAAAAAAAABoAAAAAAAAAAAAAABsAAAAAAAAAAAAAABwAAAAAAAAAAAAAAB0AAAAAAAAAAAAAAB4AAAAAAAAAAAABAAAAAAAAAAAAAAABAAEAAAAAAAAAAAABAAIAAAAAAAAAAAABAAMAAAAAAAAAAAABAAQAAAAAAAAAAAABAAUAAAAAAAAAAAABAAYAAAAAAAAAAAABAAcAAAAAAAAAAAABAAgAAAAAAAAAAAABAAkAAAAAAAAAAAABAAoAAAAAAAAAAAABAAsAAAAAAAAAAAABAAwAAAAAAAAAAAABAA0AAAAAAAAAAAABAA4AAAAAAAAAAAABAA8AAAAAAAAAAAABABAAAAAAAAAAAAABABEAAAAAAAAAAAABABIAAAAAAAAAAAABABMAAAAAAAAAAAABABQAAAAAAAAAAAABABUAAAAAAAAAAAABABYAAAAAAAAAAAABABcAAAAAAAAAAAABABgAAAAAAAAAAAABABkAAAAAAAAAAAABABoAAAAAAAAAAAABABsAAAAAAAAAAAABABwAAAAAAAAAAAABAB0AAAAAAAAAAAABAB4AAAAAAAAAAAACAAAAAAAAAAAAAAACAAEAAAAAAAAAAAACAB0AAAAAAAAAAAACAB4AAAAAAAAAAAADAAAAAAAAAAAAAAADAAEAAAAAAAAAAAADAB0AAAAAAAAAAAADAB4AAAAAAAAAAAAEAAAAAAAAAAAAAAAEAAEAAAAAAAAAAAAEAB0AAAAAAAAAAAAEAB4AAAAAAAAAAAAFAAAAAAAAAAAAAAAFAAEAAAAAAAAAAAAFAB0AAAAAAAAAAAAFAB4AAAAAAAAAAAAGAAAAAAAAAAAAAAAGAAEAAAAAAAAAAAAGAB0AAAAAAAAAAAAGAB4AAAAAAAAAAAAHAAAAAAAAAAAAAAAHAAEAAAAAAAAAAAAHAB0AAAAAAAAAAAAHAB4AAAAAAAAAAAAIAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAIAB0AAAAAAAAAAAAIAB4AAAAAAAAAAAAJAAAAAAAAAAAAAAAJAAEAAAAAAAAAAAAJAB0AAAAAAAAAAAAJAB4AAAAAAAAAAAAKAAAAAAAAAAAAAAAKAAEAAAAAAAAAAAAKAB0AAAAAAAAAAAAKAB4AAAAAAAAAAAALAAAAAAAAAAAAAAALAAEAAAAAAAAAAAALAB0AAAAAAAAAAAALAB4AAAAAAAAAAAAMAAAAAAAAAAAAAAAMAAEAAAAAAAAAAAAMAB0AAAAAAAAAAAAMAB4AAAAAAAAAAAANAAAAAAAAAAAAAAANAAEAAAAAAAAAAAANAB0AAAAAAAAAAAANAB4AAAAAAAAAAAAOAAAAAAAAAAAAAAAOAAEAAAAAAAAAAAAOAB0AAAAAAAAAAAAOAB4AAAAAAAAAAAAPAAAAAAAAAAAAAAAPAAEAAAAAAAAAAAAPAB0AAAAAAAAAAAAPAB4AAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAEAAAAAAAAAAAAQAB0AAAAAAAAAAAAQAB4AAAAAAAAAAAARAAAAAAAAAAAAAAARAAEAAAAAAAAAAAARAB0AAAAAAAAAAAARAB4AAAAAAAAAAAASAAAAAAAAAAAAAAASAAEAAAAAAAAAAAASAB0AAAAAAAAAAAASAB4AAAAAAAAAAAATAAAAAAAAAAAAAAATAAEAAAAAAAAAAAATAB0AAAAAAAAAAAATAB4AAAAAAAAAAAAUAAAAAAAAAAAAAAAUAAEAAAAAAAAAAAAUAB0AAAAAAAAAAAAUAB4AAAAAAAAAAAAVAAAAAAAAAAAAAAAVAAEAAAAAAAAAAAAVAB0AAAAAAAAAAAAVAB4AAAAAAAAAAAAWAAAAAAAAAAAAAAAWAAEAAAAAAAAAAAAWAB0AAAAAAAAAAAAWAB4AAAAAAAAAAAAXAAAAAAAAAAAAAAAXAAEAAAAAAAAAAAAXAB0AAAAAAAAAAAAXAB4AAAAAAAAAAAAYAAAAAAAAAAAAAAAYAAEAAAAAAAAAAAAYAB0AAAAAAAAAAAAYAB4AAAAAAAAAAAAZAAAAAAAAAAAAAAAZAAEAAAAAAAAAAAAZAB0AAAAAAAAAAAAZAB4AAAAAAAAAAAAaAAAAAAAAAAAAAAAaAAEAAAAAAAAAAAAaAB0AAAAAAAAAAAAaAB4AAAAAAAAAAAAbAAAAAAAAAAAAAAAbAAEAAAAAAAAAAAAbAB0AAAAAAAAAAAAbAB4AAAAAAAAAAAAcAAAAAAAAAAAAAAAcAAEAAAAAAAAAAAAcAB0AAAAAAAAAAAAcAB4AAAAAAAAAAAAdAAAAAAAAAAAAAAAdAAEAAAAAAAAAAAAdAB0AAAAAAAAAAAAdAB4AAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAEAAAAAAAAAAAAeAB0AAAAAAAAAAAAeAB4AAAAAAAAAAAAfAAAAAAAAAAAAAAAfAAEAAAAAAAAAAAAfAAIAAAAAAAAAAAAfAAMAAAAAAAAAAAAfAAQAAAAAAAAAAAAfAAUAAAAAAAAAAAAfAAYAAAAAAAAAAAAfAAcAAAAAAAAAAAAfAAgAAAAAAAAAAAAfAAkAAAAAAAAAAAAfAAoAAAAAAAAAAAAfAAsAAAAAAAAAAAAfAAwAAAAAAAAAAAAfAA0AAAAAAAAAAAAfAA4AAAAAAAAAAAAfAA8AAAAAAAAAAAAfABAAAAAAAAAAAAAfABEAAAAAAAAAAAAfABIAAAAAAAAAAAAfABMAAAAAAAAAAAAfABQAAAAAAAAAAAAfABUAAAAAAAAAAAAfABYAAAAAAAAAAAAfABcAAAAAAAAAAAAfABgAAAAAAAAAAAAfABkAAAAAAAAAAAAfABoAAAAAAAAAAAAfABsAAAAAAAAAAAAfABwAAAAAAAAAAAAfAB0AAAAAAAAAAAAfAB4AAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAEAAAAAAAAAAAAgAAIAAAAAAAAAAAAgAAMAAAAAAAAAAAAgAAQAAAAAAAAAAAAgAAUAAAAAAAAAAAAgAAYAAAAAAAAAAAAgAAcAAAAAAAAAAAAgAAgAAAAAAAAAAAAgAAkAAAAAAAAAAAAgAAoAAAAAAAAAAAAgAAsAAAAAAAAAAAAgAAwAAAAAAAAAAAAgAA0AAAAAAAAAAAAgAA4AAAAAAAAAAAAgAA8AAAAAAAAAAAAgABAAAAAAAAAAAAAgABEAAAAAAAAAAAAgABIAAAAAAAAAAAAgABMAAAAAAAAAAAAgABQAAAAAAAAAAAAgABUAAAAAAAAAAAAgABYAAAAAAAAAAAAgABcAAAAAAAAAAAAgABgAAAAAAAAAAAAgABkAAAAAAAAAAAAgABoAAAAAAAAAAAAgABsAAAAAAAAAAAAgABwAAAAAAAAAAAAgAB0AAAAAAAAAAAAgAB4AAAAAAAAAAAAOABgAAAAAAAAAAAAPABgAAAAAAAAAAAAQABgAAAAAAAAAAAARABgAAAAAAAAAAAASABgAAAAAAAAAAAATABgAAAAAAAAAAAAUABgAAAAAAAAAAAAUABcAAAAAAAAAAAAUABYAAAAAAAAAAAATABYAAAAAAAAAAAASABYAAAAAAAAAAAARABYAAAAAAAAAAAAQABYAAAAAAAAAAAAPABYAAAAAAAAAAAAOABYAAAAAAAAAAAAOABcAAAAAAAAAAAAPABcAAAAAAAAAAAAQABcAAAAAAAAAAAARABcAAAAAAAAAAAASABcAAAAAAAAAAAATABcAAAAAAAAAAAAOABkAAAAAAAAAAAAPABkAAAAAAAAAAAAQABkAAAAAAAAAAAARABkAAAAAAAAAAAASABkAAAAAAAAAAAATABkAAAAAAAAAAAAUABkAAAAAAAAAAAA=")
tile_set = SubResource("TileSet_xqlka")
[node name="Secret" type="TileMapLayer" parent="."]
use_parent_material = true
tile_map_data = PackedByteArray("AAAOABoAAAAAAAAAAAAOABsAAAAAAAAAAAAOABwAAAAAAAAAAAAPABoAAAAAAAAAAAAPABsAAAAAAAAAAAAPABwAAAAAAAAAAAAQABoAAAAAAAAAAAAQABsAAAAAAAAAAAAQABwAAAAAAAAAAAARABoAAAAAAAAAAAARABsAAAAAAAAAAAARABwAAAAAAAAAAAASABoAAAAAAAAAAAASABsAAAAAAAAAAAASABwAAAAAAAAAAAATABoAAAAAAAAAAAATABsAAAAAAAAAAAATABwAAAAAAAAAAAAUABoAAAAAAAAAAAAUABsAAAAAAAAAAAAUABwAAAAAAAAAAAA=")
tile_set = SubResource("TileSet_xqlka") tile_set = SubResource("TileSet_xqlka")
format = 2
layer_0/name = "Ground"
layer_0/tile_data = PackedInt32Array(0, 0, 0, 65536, 0, 0, 131072, 0, 0, 196608, 0, 0, 262144, 0, 0, 327680, 0, 0, 393216, 0, 0, 458752, 0, 0, 524288, 0, 0, 589824, 0, 0, 655360, 0, 0, 720896, 0, 0, 786432, 0, 0, 851968, 0, 0, 917504, 0, 0, 983040, 0, 0, 1048576, 0, 0, 1114112, 0, 0, 1179648, 0, 0, 1245184, 0, 0, 1310720, 0, 0, 1376256, 0, 0, 1441792, 0, 0, 1507328, 0, 0, 1572864, 0, 0, 1638400, 0, 0, 1703936, 0, 0, 1769472, 0, 0, 1835008, 0, 0, 1900544, 0, 0, 1966080, 0, 0, 1, 0, 0, 65537, 0, 0, 131073, 0, 0, 196609, 0, 0, 262145, 0, 0, 327681, 0, 0, 393217, 0, 0, 458753, 0, 0, 524289, 0, 0, 589825, 0, 0, 655361, 0, 0, 720897, 0, 0, 786433, 0, 0, 851969, 0, 0, 917505, 0, 0, 983041, 0, 0, 1048577, 0, 0, 1114113, 0, 0, 1179649, 0, 0, 1245185, 0, 0, 1310721, 0, 0, 1376257, 0, 0, 1441793, 0, 0, 1507329, 0, 0, 1572865, 0, 0, 1638401, 0, 0, 1703937, 0, 0, 1769473, 0, 0, 1835009, 0, 0, 1900545, 0, 0, 1966081, 0, 0, 2, 0, 0, 65538, 0, 0, 1900546, 0, 0, 1966082, 0, 0, 3, 0, 0, 65539, 0, 0, 1900547, 0, 0, 1966083, 0, 0, 4, 0, 0, 65540, 0, 0, 1900548, 0, 0, 1966084, 0, 0, 5, 0, 0, 65541, 0, 0, 1900549, 0, 0, 1966085, 0, 0, 6, 0, 0, 65542, 0, 0, 1900550, 0, 0, 1966086, 0, 0, 7, 0, 0, 65543, 0, 0, 1900551, 0, 0, 1966087, 0, 0, 8, 0, 0, 65544, 0, 0, 1900552, 0, 0, 1966088, 0, 0, 9, 0, 0, 65545, 0, 0, 1900553, 0, 0, 1966089, 0, 0, 10, 0, 0, 65546, 0, 0, 1900554, 0, 0, 1966090, 0, 0, 11, 0, 0, 65547, 0, 0, 1900555, 0, 0, 1966091, 0, 0, 12, 0, 0, 65548, 0, 0, 1900556, 0, 0, 1966092, 0, 0, 13, 0, 0, 65549, 0, 0, 1900557, 0, 0, 1966093, 0, 0, 14, 0, 0, 65550, 0, 0, 1900558, 0, 0, 1966094, 0, 0, 15, 0, 0, 65551, 0, 0, 1900559, 0, 0, 1966095, 0, 0, 16, 0, 0, 65552, 0, 0, 1900560, 0, 0, 1966096, 0, 0, 17, 0, 0, 65553, 0, 0, 1900561, 0, 0, 1966097, 0, 0, 18, 0, 0, 65554, 0, 0, 1900562, 0, 0, 1966098, 0, 0, 19, 0, 0, 65555, 0, 0, 1900563, 0, 0, 1966099, 0, 0, 20, 0, 0, 65556, 0, 0, 1900564, 0, 0, 1966100, 0, 0, 21, 0, 0, 65557, 0, 0, 1900565, 0, 0, 1966101, 0, 0, 22, 0, 0, 65558, 0, 0, 1900566, 0, 0, 1966102, 0, 0, 23, 0, 0, 65559, 0, 0, 1900567, 0, 0, 1966103, 0, 0, 24, 0, 0, 65560, 0, 0, 1900568, 0, 0, 1966104, 0, 0, 25, 0, 0, 65561, 0, 0, 1900569, 0, 0, 1966105, 0, 0, 26, 0, 0, 65562, 0, 0, 1900570, 0, 0, 1966106, 0, 0, 27, 0, 0, 65563, 0, 0, 1900571, 0, 0, 1966107, 0, 0, 28, 0, 0, 65564, 0, 0, 1900572, 0, 0, 1966108, 0, 0, 29, 0, 0, 65565, 0, 0, 1900573, 0, 0, 1966109, 0, 0, 30, 0, 0, 65566, 0, 0, 1900574, 0, 0, 1966110, 0, 0, 31, 0, 0, 65567, 0, 0, 131103, 0, 0, 196639, 0, 0, 262175, 0, 0, 327711, 0, 0, 393247, 0, 0, 458783, 0, 0, 524319, 0, 0, 589855, 0, 0, 655391, 0, 0, 720927, 0, 0, 786463, 0, 0, 851999, 0, 0, 917535, 0, 0, 983071, 0, 0, 1048607, 0, 0, 1114143, 0, 0, 1179679, 0, 0, 1245215, 0, 0, 1310751, 0, 0, 1376287, 0, 0, 1441823, 0, 0, 1507359, 0, 0, 1572895, 0, 0, 1638431, 0, 0, 1703967, 0, 0, 1769503, 0, 0, 1835039, 0, 0, 1900575, 0, 0, 1966111, 0, 0, 32, 0, 0, 65568, 0, 0, 131104, 0, 0, 196640, 0, 0, 262176, 0, 0, 327712, 0, 0, 393248, 0, 0, 458784, 0, 0, 524320, 0, 0, 589856, 0, 0, 655392, 0, 0, 720928, 0, 0, 786464, 0, 0, 852000, 0, 0, 917536, 0, 0, 983072, 0, 0, 1048608, 0, 0, 1114144, 0, 0, 1179680, 0, 0, 1245216, 0, 0, 1310752, 0, 0, 1376288, 0, 0, 1441824, 0, 0, 1507360, 0, 0, 1572896, 0, 0, 1638432, 0, 0, 1703968, 0, 0, 1769504, 0, 0, 1835040, 0, 0, 1900576, 0, 0, 1966112, 0, 0, 1572878, 0, 0, 1572879, 0, 0, 1572880, 0, 0, 1572881, 0, 0, 1572882, 0, 0, 1572883, 0, 0, 1572884, 0, 0, 1507348, 0, 0, 1441812, 0, 0, 1441811, 0, 0, 1441810, 0, 0, 1441809, 0, 0, 1441808, 0, 0, 1441807, 0, 0, 1441806, 0, 0, 1507342, 0, 0, 1507343, 0, 0, 1507344, 0, 0, 1507345, 0, 0, 1507346, 0, 0, 1507347, 0, 0, 1638414, 0, 0, 1638415, 0, 0, 1638416, 0, 0, 1638417, 0, 0, 1638418, 0, 0, 1638419, 0, 0, 1638420, 0, 0)
layer_1/name = "Secret"
layer_1/enabled = true
layer_1/modulate = Color(1, 1, 1, 1)
layer_1/y_sort_enabled = false
layer_1/y_sort_origin = 0
layer_1/z_index = 0
layer_1/tile_data = PackedInt32Array(1703950, 0, 0, 1769486, 0, 0, 1835022, 0, 0, 1703951, 0, 0, 1769487, 0, 0, 1835023, 0, 0, 1703952, 0, 0, 1769488, 0, 0, 1835024, 0, 0, 1703953, 0, 0, 1769489, 0, 0, 1835025, 0, 0, 1703954, 0, 0, 1769490, 0, 0, 1835026, 0, 0, 1703955, 0, 0, 1769491, 0, 0, 1835027, 0, 0, 1703956, 0, 0, 1769492, 0, 0, 1835028, 0, 0)
script = ExtResource("2_q8fhk") script = ExtResource("2_q8fhk")
[node name="Camera2D" type="Camera2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."]
@@ -53,5 +44,5 @@ position = Vector2(280, 440)
[node name="CollisionShape2D" type="CollisionShape2D" parent="SecretDetector"] [node name="CollisionShape2D" type="CollisionShape2D" parent="SecretDetector"]
shape = SubResource("RectangleShape2D_a2gec") shape = SubResource("RectangleShape2D_a2gec")
[connection signal="body_entered" from="SecretDetector" to="TileMap" method="_on_secret_detector_body_entered"] [connection signal="body_entered" from="SecretDetector" to="Secret" method="_on_secret_detector_body_entered"]
[connection signal="body_exited" from="SecretDetector" to="TileMap" method="_on_secret_detector_body_exited"] [connection signal="body_exited" from="SecretDetector" to="Secret" method="_on_secret_detector_body_exited"]

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=8 format=3 uid="uid://dmn8nkpogiwsf"] [gd_scene load_steps=9 format=3 uid="uid://dmn8nkpogiwsf"]
[ext_resource type="PackedScene" uid="uid://bpdyvy2681m3i" path="res://player/Player.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://bpdyvy2681m3i" path="res://player/Player.tscn" id="1"]
[ext_resource type="FontFile" uid="uid://b5bspum6ffekd" path="res://fonts/SourceCodePro-Bold.ttf" id="2_r1c5f"]
[ext_resource type="PackedScene" uid="uid://cvi13chv8g4hj" path="res://debug/StatesStackDiplayer.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://cvi13chv8g4hj" path="res://debug/StatesStackDiplayer.tscn" id="3"]
[ext_resource type="PackedScene" uid="uid://bq6rrfy53rfvo" path="res://debug/ControlsPanel.tscn" id="4"] [ext_resource type="PackedScene" uid="uid://bq6rrfy53rfvo" path="res://debug/ControlsPanel.tscn" id="4"]
@@ -43,6 +44,9 @@ libraries = {
"": SubResource("AnimationLibrary_qbwwp") "": SubResource("AnimationLibrary_qbwwp")
} }
[node name="StateNameDisplayer" parent="Player" index="5"]
theme_override_fonts/font = ExtResource("2_r1c5f")
[node name="Explanations" type="RichTextLabel" parent="."] [node name="Explanations" type="RichTextLabel" parent="."]
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0

View File

@@ -8,7 +8,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/516 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2714
## Why use a state machine ## Why use a state machine

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://cvi13chv8g4hj"] [gd_scene load_steps=3 format=3 uid="uid://cvi13chv8g4hj"]
[ext_resource type="Script" path="res://debug/states_stack_displayer.gd" id="1"] [ext_resource type="Script" path="res://debug/states_stack_displayer.gd" id="1"]
[ext_resource type="FontFile" uid="uid://b5bspum6ffekd" path="res://fonts/SourceCodePro-Bold.ttf" id="2_58if7"]
[node name="StatesStackDiplayer" type="Panel"] [node name="StatesStackDiplayer" type="Panel"]
offset_right = 210.0 offset_right = 210.0
@@ -17,6 +18,7 @@ grow_vertical = 2
[node name="Title" type="Label" parent="VBoxContainer"] [node name="Title" type="Label" parent="VBoxContainer"]
layout_mode = 2 layout_mode = 2
theme_override_fonts/font = ExtResource("2_58if7")
text = "StateStack" text = "StateStack"
uppercase = true uppercase = true
@@ -26,6 +28,7 @@ layout_mode = 2
[node name="Numbers" type="Label" parent="VBoxContainer/HBoxContainer"] [node name="Numbers" type="Label" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
theme_override_fonts/font = ExtResource("2_58if7")
text = "1. text = "1.
2." 2."
horizontal_alignment = 2 horizontal_alignment = 2
@@ -33,5 +36,6 @@ horizontal_alignment = 2
[node name="States" type="Label" parent="VBoxContainer/HBoxContainer"] [node name="States" type="Label" parent="VBoxContainer/HBoxContainer"]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
theme_override_fonts/font = ExtResource("2_58if7")
text = "Jump text = "Jump
Test" Test"

View File

@@ -1,14 +1,16 @@
extends Panel extends Panel
@onready var fsm_node = get_node(^"../../Player/StateMachine") @onready var fsm_node: Node = get_node(^"../../Player/StateMachine")
func _process(_delta): func _process(_delta: float) -> void:
var states_names = "" var states_names := ""
var numbers = "" var numbers := ""
var index = 0 var index := 0
for state in fsm_node.states_stack:
states_names += String(state.get_name()) + "\n" for state: Node in fsm_node.states_stack:
states_names += String(state.name) + "\n"
numbers += str(index) + "\n" numbers += str(index) + "\n"
index += 1 index += 1
%States.text = states_names %States.text = states_names
%Numbers.text = numbers %Numbers.text = numbers

View File

@@ -1,12 +0,0 @@
[gd_resource type="Font" load_steps=2 format=2]
[ext_resource path="res://fonts/SourceCodePro-Bold.ttf" type="FontData" id=1]
[resource]
size = 20
use_mipmaps = false
use_filter = true
font_data = ExtResource( 1 )
_sections_unfolded = [ "Font", "Settings" ]

View File

@@ -1,12 +0,0 @@
[gd_resource type="Font" load_steps=2 format=2]
[ext_resource path="res://fonts/SourceCodePro-Black.ttf" type="FontData" id=1]
[resource]
size = 24
use_mipmaps = false
use_filter = true
font_data = ExtResource( 1 )
_sections_unfolded = [ "Font", "Settings" ]

View File

@@ -1,23 +1,23 @@
extends CharacterBody2D extends CharacterBody2D
var direction = Vector2() var direction := Vector2()
@export var speed: float = 1000.0 @export var speed := 1000.0
@onready var root = get_tree().root @onready var root := get_tree().root
func _ready(): func _ready() -> void:
set_as_top_level(true) set_as_top_level(true)
func _physics_process(delta): func _physics_process(delta: float) -> void:
if not root.get_visible_rect().has_point(position): if not root.get_visible_rect().has_point(position):
queue_free() queue_free()
var motion = direction * speed * delta var motion := direction * speed * delta
var collision_info = move_and_collide(motion) var collision_info := move_and_collide(motion)
if collision_info: if collision_info:
queue_free() queue_free()
func _draw(): func _draw() -> void:
draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color.WHITE) draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color.WHITE)

View File

@@ -1,18 +1,18 @@
extends Node2D extends Node2D
var bullet = preload("Bullet.tscn") var bullet := preload("Bullet.tscn")
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("fire"): if event.is_action_pressed("fire"):
fire() fire()
func fire(): func fire() -> void:
if not $CooldownTimer.is_stopped(): if not $CooldownTimer.is_stopped():
return return
$CooldownTimer.start() $CooldownTimer.start()
var new_bullet = bullet.instantiate() var new_bullet := bullet.instantiate()
add_child(new_bullet) add_child(new_bullet)
new_bullet.position = global_position new_bullet.position = global_position
new_bullet.direction = owner.look_direction new_bullet.direction = owner.look_direction

View File

@@ -3,25 +3,26 @@ extends CharacterBody2D
# It can move, collide with the world, etc... # It can move, collide with the world, etc...
# The player has a state machine, but the body and the state machine are separate. # The player has a state machine, but the body and the state machine are separate.
signal direction_changed(new_direction) signal direction_changed(new_direction: Vector2)
var look_direction = Vector2.RIGHT: var look_direction := Vector2.RIGHT:
set(value): set(value):
look_direction = value look_direction = value
set_look_direction(value) set_look_direction(value)
func take_damage(attacker, amount, effect = null): func take_damage(attacker: Node, amount: float, effect: Node = null) -> void:
if is_ancestor_of(attacker): if is_ancestor_of(attacker):
return return
$States/Stagger.knockback_direction = (attacker.global_position - global_position).normalized() $States/Stagger.knockback_direction = (attacker.global_position - global_position).normalized()
$Health.take_damage(amount, effect) $Health.take_damage(amount, effect)
func set_dead(value): func set_dead(value: bool) -> void:
set_process_input(not value) set_process_input(not value)
set_physics_process(not value) set_physics_process(not value)
$CollisionPolygon2D.disabled = value $CollisionPolygon2D.disabled = value
func set_look_direction(value): func set_look_direction(value: Vector2) -> void:
direction_changed.emit(value) direction_changed.emit(value)

View File

@@ -1,12 +1,12 @@
extends "res://state_machine/state_machine.gd" extends "res://state_machine/state_machine.gd"
@onready var idle = $Idle @onready var idle: Node = $Idle
@onready var move = $Move @onready var move: Node = $Move
@onready var jump = $Jump @onready var jump: Node = $Jump
@onready var stagger = $Stagger @onready var stagger: Node = $Stagger
@onready var attack = $Attack @onready var attack: Node = $Attack
func _ready(): func _ready() -> void:
states_map = { states_map = {
"idle": idle, "idle": idle,
"move": move, "move": move,
@@ -16,7 +16,7 @@ func _ready():
} }
func _change_state(state_name): func _change_state(state_name: String) -> void:
# The base state_machine interface this node extends does most of the work. # The base state_machine interface this node extends does most of the work.
if not _active: if not _active:
return return
@@ -24,10 +24,11 @@ func _change_state(state_name):
states_stack.push_front(states_map[state_name]) states_stack.push_front(states_map[state_name])
if state_name == "jump" and current_state == move: if state_name == "jump" and current_state == move:
jump.initialize(move.speed, move.velocity) jump.initialize(move.speed, move.velocity)
super._change_state(state_name) super._change_state(state_name)
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
# Here we only handle input that can interrupt states, attacking in this case, # Here we only handle input that can interrupt states, attacking in this case,
# otherwise we let the state node handle it. # otherwise we let the state node handle it.
if event.is_action_pressed("attack"): if event.is_action_pressed("attack"):
@@ -35,4 +36,5 @@ func _unhandled_input(event):
return return
_change_state("attack") _change_state("attack")
return return
current_state.handle_input(event) current_state.handle_input(event)

View File

@@ -1,8 +1,8 @@
extends "res://state_machine/state.gd" extends "res://state_machine/state.gd"
func enter(): func enter() -> void:
owner.get_node(^"AnimationPlayer").play("idle") owner.get_node(^"AnimationPlayer").play("idle")
func _on_Sword_attack_finished(): func _on_Sword_attack_finished() -> void:
finished.emit("previous") finished.emit("previous")

View File

@@ -3,10 +3,10 @@ extends "res://state_machine/state.gd"
# The animation only affects the Body Sprite2D's modulate property so it # The animation only affects the Body Sprite2D's modulate property so it
# could stack with other animations if we had two AnimationPlayer nodes. # could stack with other animations if we had two AnimationPlayer nodes.
func enter(): func enter() -> void:
owner.get_node(^"AnimationPlayer").play("stagger") owner.get_node(^"AnimationPlayer").play("stagger")
func _on_animation_finished(anim_name): func _on_animation_finished(anim_name: String) -> void:
assert(anim_name == "stagger") assert(anim_name == "stagger")
finished.emit("previous") finished.emit("previous")

View File

@@ -1,14 +1,14 @@
extends Label extends Label
var start_position = Vector2() var start_position := Vector2()
func _ready(): func _ready() -> void:
start_position = position start_position = position
func _physics_process(_delta): func _physics_process(_delta: float) -> void:
position = $"../BodyPivot".position + start_position position = $"../BodyPivot".position + start_position
func _on_StateMachine_state_changed(current_state): func _on_StateMachine_state_changed(current_state: Node) -> void:
text = String(current_state.get_name()) text = String(current_state.name)

View File

@@ -1,10 +1,10 @@
extends "res://state_machine/state.gd" extends "res://state_machine/state.gd"
# Initialize the state. E.g. change the animation. # Initialize the state. E.g. change the animation.
func enter(): func enter() -> void:
owner.set_dead(true) owner.set_dead(true)
owner.get_node(^"AnimationPlayer").play("die") owner.get_node(^"AnimationPlayer").play("die")
func _on_animation_finished(_anim_name): func _on_animation_finished(_anim_name: String) -> void:
finished.emit("dead") finished.emit("dead")

View File

@@ -1,23 +1,23 @@
extends "../motion.gd" extends "../motion.gd"
@export var base_max_horizontal_speed: float = 400.0 @export var base_max_horizontal_speed := 400.0
@export var air_acceleration: float = 1000.0 @export var air_acceleration := 1000.0
@export var air_deceleration: float = 2000.0 @export var air_deceleration := 2000.0
@export var air_steering_power: float = 50.0 @export var air_steering_power := 50.0
@export var gravity: float = 1600.0 @export var gravity := 1600.0
var enter_velocity = Vector2() var enter_velocity := Vector2()
var max_horizontal_speed = 0.0 var max_horizontal_speed := 0.0
var horizontal_speed = 0.0 var horizontal_speed := 0.0
var horizontal_velocity = Vector2() var horizontal_velocity := Vector2()
var vertical_speed = 0.0 var vertical_speed := 0.0
var height = 0.0 var height := 0.0
func initialize(speed, velocity): func initialize(speed: float, velocity: Vector2) -> void:
horizontal_speed = speed horizontal_speed = speed
if speed > 0.0: if speed > 0.0:
max_horizontal_speed = speed max_horizontal_speed = speed
@@ -26,8 +26,8 @@ func initialize(speed, velocity):
enter_velocity = velocity enter_velocity = velocity
func enter(): func enter() -> void:
var input_direction = get_input_direction() var input_direction := get_input_direction()
update_look_direction(input_direction) update_look_direction(input_direction)
if input_direction: if input_direction:
@@ -39,8 +39,8 @@ func enter():
owner.get_node(^"AnimationPlayer").play("idle") owner.get_node(^"AnimationPlayer").play("idle")
func update(delta): func update(delta: float) -> void:
var input_direction = get_input_direction() var input_direction := get_input_direction()
update_look_direction(input_direction) update_look_direction(input_direction)
move_horizontally(delta, input_direction) move_horizontally(delta, input_direction)
@@ -49,22 +49,22 @@ func update(delta):
finished.emit("previous") finished.emit("previous")
func move_horizontally(delta, direction): func move_horizontally(delta: float, direction: Vector2) -> void:
if direction: if direction:
horizontal_speed += air_acceleration * delta horizontal_speed += air_acceleration * delta
else: else:
horizontal_speed -= air_deceleration * delta horizontal_speed -= air_deceleration * delta
horizontal_speed = clamp(horizontal_speed, 0, max_horizontal_speed) horizontal_speed = clamp(horizontal_speed, 0, max_horizontal_speed)
var target_velocity = horizontal_speed * direction.normalized() var target_velocity := horizontal_speed * direction.normalized()
var steering_velocity = (target_velocity - horizontal_velocity).normalized() * air_steering_power var steering_velocity := (target_velocity - horizontal_velocity).normalized() * air_steering_power
horizontal_velocity += steering_velocity horizontal_velocity += steering_velocity
owner.velocity = horizontal_velocity owner.velocity = horizontal_velocity
owner.move_and_slide() owner.move_and_slide()
func animate_jump_height(delta): func animate_jump_height(delta: float) -> void:
vertical_speed -= gravity * delta vertical_speed -= gravity * delta
height += vertical_speed * delta height += vertical_speed * delta
height = max(0.0, height) height = max(0.0, height)

View File

@@ -1,19 +1,18 @@
extends "res://state_machine/state.gd" extends "res://state_machine/state.gd"
# Collection of important methods to handle direction and animation. # Collection of important methods to handle direction and animation.
func handle_input(event): func handle_input(event: InputEvent) -> void:
if event.is_action_pressed("simulate_damage"): if event.is_action_pressed("simulate_damage"):
finished.emit("stagger") finished.emit("stagger")
func get_input_direction(): func get_input_direction() -> Vector2:
var input_direction = Vector2( return Vector2(
Input.get_axis(&"move_left", &"move_right"), Input.get_axis(&"move_left", &"move_right"),
Input.get_axis(&"move_up", &"move_down") Input.get_axis(&"move_up", &"move_down")
) )
return input_direction
func update_look_direction(direction): func update_look_direction(direction: Vector2) -> void:
if direction and owner.look_direction != direction: if direction and owner.look_direction != direction:
owner.look_direction = direction owner.look_direction = direction

View File

@@ -1,14 +1,14 @@
extends "on_ground.gd" extends "on_ground.gd"
func enter(): func enter() -> void:
owner.get_node(^"AnimationPlayer").play("idle") owner.get_node(^"AnimationPlayer").play("idle")
func handle_input(event): func handle_input(event: InputEvent) -> void:
return super.handle_input(event) return super.handle_input(event)
func update(_delta): func update(_delta: float) -> void:
var input_direction = get_input_direction() var input_direction: Vector2 = get_input_direction()
if input_direction: if input_direction:
finished.emit("move") finished.emit("move")

View File

@@ -1,23 +1,23 @@
extends "on_ground.gd" extends "on_ground.gd"
@export var max_walk_speed: float = 450 @export var max_walk_speed := 450.0
@export var max_run_speed: float = 700 @export var max_run_speed := 700.0
func enter(): func enter() -> void:
speed = 0.0 speed = 0.0
velocity = Vector2() velocity = Vector2()
var input_direction = get_input_direction() var input_direction := get_input_direction()
update_look_direction(input_direction) update_look_direction(input_direction)
owner.get_node(^"AnimationPlayer").play("walk") owner.get_node(^"AnimationPlayer").play("walk")
func handle_input(event): func handle_input(event: InputEvent) -> void:
return super.handle_input(event) return super.handle_input(event)
func update(_delta): func update(_delta: float) -> void:
var input_direction = get_input_direction() var input_direction := get_input_direction()
if input_direction.is_zero_approx(): if input_direction.is_zero_approx():
finished.emit("idle") finished.emit("idle")
update_look_direction(input_direction) update_look_direction(input_direction)
@@ -27,16 +27,17 @@ func update(_delta):
else: else:
speed = max_walk_speed speed = max_walk_speed
var collision_info = move(speed, input_direction) var collision_info := move(speed, input_direction)
if not collision_info: if not collision_info:
return return
if speed == max_run_speed and collision_info.collider.is_in_group("environment"): if speed == max_run_speed and collision_info.collider.is_in_group("environment"):
return null return
func move(speed, direction): func move(p_speed: float, direction: Vector2) -> KinematicCollision2D:
owner.velocity = direction.normalized() * speed owner.velocity = direction.normalized() * p_speed
owner.move_and_slide() owner.move_and_slide()
if owner.get_slide_collision_count() == 0: if owner.get_slide_collision_count() == 0:
return return null
return owner.get_slide_collision(0) return owner.get_slide_collision(0)

View File

@@ -1,10 +1,9 @@
extends "../motion.gd" extends "../motion.gd"
# warning-ignore-all:unused_class_variable var speed := 0.0
var speed = 0.0 var velocity := Vector2()
var velocity = Vector2()
func handle_input(event): func handle_input(event: InputEvent) -> void:
if event.is_action_pressed("jump"): if event.is_action_pressed("jump"):
finished.emit("jump") finished.emit("jump")
return super.handle_input(event) return super.handle_input(event)

View File

@@ -2,41 +2,50 @@ extends Area2D
signal attack_finished signal attack_finished
enum States { IDLE, ATTACK } enum States {
var state = null IDLE,
ATTACK,
}
enum AttackInputStates { IDLE, LISTENING, REGISTERED } enum AttackInputStates {
var attack_input_state = AttackInputStates.IDLE IDLE,
var ready_for_next_attack = false LISTENING,
REGISTERED,
}
var state: States = States.IDLE
var attack_input_state := AttackInputStates.IDLE
var ready_for_next_attack := false
const MAX_COMBO_COUNT = 3 const MAX_COMBO_COUNT = 3
var combo_count = 0 var combo_count := 0
var attack_current = {} var attack_current := {}
var combo = [{ var combo := [{
"damage": 1, "damage": 1,
"animation": "attack_fast", "animation": "attack_fast",
"effect": null "effect": null,
}, },
{ {
"damage": 1, "damage": 1,
"animation": "attack_fast", "animation": "attack_fast",
"effect": null "effect": null,
}, },
{ {
"damage": 3, "damage": 3,
"animation": "attack_medium", "animation": "attack_medium",
"effect": null "effect": null,
}] }
]
var hit_objects = [] var hit_objects := []
func _ready(): func _ready() -> void:
$AnimationPlayer.animation_finished.connect(_on_animation_finished) $AnimationPlayer.animation_finished.connect(_on_animation_finished)
body_entered.connect(_on_body_entered) body_entered.connect(_on_body_entered)
_change_state(States.IDLE) _change_state(States.IDLE)
func _change_state(new_state): func _change_state(new_state: States) -> void:
match state: match state:
States.ATTACK: States.ATTACK:
hit_objects = [] hit_objects = []
@@ -57,7 +66,7 @@ func _change_state(new_state):
state = new_state state = new_state
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
if not state == States.ATTACK: if not state == States.ATTACK:
return return
if attack_input_state != AttackInputStates.LISTENING: if attack_input_state != AttackInputStates.LISTENING:
@@ -66,36 +75,37 @@ func _unhandled_input(event):
attack_input_state = AttackInputStates.REGISTERED attack_input_state = AttackInputStates.REGISTERED
func _physics_process(_delta): func _physics_process(_delta: float) -> void:
if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack: if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack:
attack() attack()
func attack(): func attack() -> void:
combo_count += 1 combo_count += 1
_change_state(States.ATTACK) _change_state(States.ATTACK)
# Use with AnimationPlayer func track. # Use with AnimationPlayer func track.
func set_attack_input_listening(): func set_attack_input_listening() -> void:
attack_input_state = AttackInputStates.LISTENING attack_input_state = AttackInputStates.LISTENING
# Use with AnimationPlayer func track. # Use with AnimationPlayer func track.
func set_ready_for_next_attack(): func set_ready_for_next_attack() -> void:
ready_for_next_attack = true ready_for_next_attack = true
func _on_body_entered(body): func _on_body_entered(body: Node2D) -> void:
if not body.has_node("Health"): if not body.has_node("Health"):
return return
if body.get_rid().get_id() in hit_objects: if body.get_rid().get_id() in hit_objects:
return return
hit_objects.append(body.get_rid().get_id()) hit_objects.append(body.get_rid().get_id())
body.take_damage(self, attack_current["damage"], attack_current["effect"]) body.take_damage(self, attack_current["damage"], attack_current["effect"])
func _on_animation_finished(_name): func _on_animation_finished(_name: String) -> void:
if attack_current.is_empty(): if attack_current.is_empty():
return return
@@ -106,6 +116,6 @@ func _on_animation_finished(_name):
attack_finished.emit() attack_finished.emit()
func _on_StateMachine_state_changed(current_state): func _on_StateMachine_state_changed(current_state: Node) -> void:
if current_state.name == "Attack": if current_state.name == "Attack":
attack() attack()

View File

@@ -1,13 +1,13 @@
extends Marker2D extends Marker2D
var z_index_start = 0 var z_index_start := 0
func _ready(): func _ready() -> void:
owner.direction_changed.connect(_on_Parent_direction_changed) owner.direction_changed.connect(_on_Parent_direction_changed)
z_index_start = z_index z_index_start = z_index
func _on_Parent_direction_changed(direction): func _on_Parent_direction_changed(direction: Vector2) -> void:
rotation = direction.angle() rotation = direction.angle()
match direction: match direction:
Vector2.UP: Vector2.UP:

View File

@@ -19,6 +19,10 @@ run/main_scene="res://Demo.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/size/viewport_width=1280 window/size/viewport_width=1280

View File

@@ -3,26 +3,26 @@ extends Node
# but forces us to pass the right arguments to the methods below # but forces us to pass the right arguments to the methods below
# and makes sure every State object had all of these methods. # and makes sure every State object had all of these methods.
# warning-ignore:unused_signal @warning_ignore("unused_signal")
signal finished(next_state_name) signal finished(next_state_name: String)
# Initialize the state. E.g. change the animation. # Initialize the state. E.g. change the animation.
func enter(): func enter() -> void:
pass pass
# Clean up the state. Reinitialize values like a timer. # Clean up the state. Reinitialize values like a timer.
func exit(): func exit() -> void:
pass pass
func handle_input(_event): func handle_input(_event: InputEvent) -> void:
pass pass
func update(_delta): func update(_delta: float) -> void:
pass pass
func _on_animation_finished(_anim_name): func _on_animation_finished(_anim_name: String) -> void:
pass pass

View File

@@ -5,39 +5,39 @@ extends Node
# and changing the current/active state. # and changing the current/active state.
# See the PlayerV2 scene for an example on how to use it. # See the PlayerV2 scene for an example on how to use it.
signal state_changed(current_state) signal state_changed(current_state: Node)
# You should set a starting node from the inspector or on the node that inherits # You should set a starting node from the inspector or on the node that inherits
# from this state machine interface. If you don't, the game will default to # from this state machine interface. If you don't, the game will default to
# the first state in the state machine's children. # the first state in the state machine's children.
@export var start_state: NodePath @export var start_state: NodePath
var states_map = {} var states_map := {}
var states_stack = [] var states_stack := []
var current_state = null var current_state: Node = null
var _active = false: var _active := false:
set(value): set(value):
_active = value _active = value
set_active(value) set_active(value)
func _enter_tree(): func _enter_tree() -> void:
if start_state.is_empty(): if start_state.is_empty():
start_state = get_child(0).get_path() start_state = get_child(0).get_path()
for child in get_children(): for child in get_children():
var err = child.finished.connect(_change_state) var err: bool = child.finished.connect(_change_state)
if err: if err:
printerr(err) printerr(err)
initialize(start_state) initialize(start_state)
func initialize(initial_state): func initialize(initial_state: NodePath) -> void:
_active = true _active = true
states_stack.push_front(get_node(initial_state)) states_stack.push_front(get_node(initial_state))
current_state = states_stack[0] current_state = states_stack[0]
current_state.enter() current_state.enter()
func set_active(value): func set_active(value: bool) -> void:
set_physics_process(value) set_physics_process(value)
set_process_input(value) set_process_input(value)
if not _active: if not _active:
@@ -45,21 +45,22 @@ func set_active(value):
current_state = null current_state = null
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
current_state.handle_input(event) current_state.handle_input(event)
func _physics_process(delta): func _physics_process(delta: float) -> void:
current_state.update(delta) current_state.update(delta)
func _on_animation_finished(anim_name): func _on_animation_finished(anim_name: String) -> void:
if not _active: if not _active:
return return
current_state._on_animation_finished(anim_name) current_state._on_animation_finished(anim_name)
func _change_state(state_name): func _change_state(state_name: String) -> void:
if not _active: if not _active:
return return
current_state.exit() current_state.exit()

View File

@@ -8,7 +8,7 @@ Language: GDScript
Renderer: Forward+ Renderer: Forward+
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/110 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2715
## Screenshots ## Screenshots

View File

@@ -2,11 +2,11 @@ extends Node2D
const CAVE_LIMIT = 1000 const CAVE_LIMIT = 1000
var glow_map = preload("res://glow_map.webp") var glow_map := preload("res://glow_map.webp")
@onready var cave = $Cave @onready var cave: Node2D = $Cave
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseMotion and event.button_mask > 0: if event is InputEventMouseMotion and event.button_mask > 0:
cave.position.x = clampf(cave.position.x + event.relative.x, -CAVE_LIMIT, 0) cave.position.x = clampf(cave.position.x + event.relative.x, -CAVE_LIMIT, 0)

View File

@@ -37,7 +37,6 @@ environment = SubResource("1")
[node name="Camera2D" type="Camera2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."]
offset = Vector2(540, 360) offset = Vector2(540, 360)
current = true
[node name="Label" type="Label" parent="."] [node name="Label" type="Label" parent="."]
visible = false visible = false

View File

@@ -20,6 +20,10 @@ config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
run/name="" run/name=""
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/size/viewport_width=1080 window/size/viewport_width=1080

View File

@@ -6,7 +6,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/111 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2717
## Screenshots ## Screenshots

View File

@@ -11,4 +11,5 @@ format = 2
layer_0/tile_data = PackedInt32Array(-458747, 0, 0, -458746, 0, 0, -393212, 0, 0, -393211, 0, 0, -393210, 0, 0, -393209, 0, 0, -393208, 0, 0, -393207, 0, 0, -327678, 0, 0, -327677, 0, 0, -327676, 0, 0, -327675, 6, 0, -327674, 6, 0, -327673, 6, 0, -327672, 6, 0, -327671, 0, 0, -327670, 0, 0, -327669, 0, 0, -262142, 0, 0, -262141, 0, 0, -262140, 6, 0, -262139, 6, 0, -262138, 6, 0, -262137, 6, 0, -262136, 6, 0, -262135, 0, 0, -262134, 0, 0, -262133, 0, 0, -262132, 0, 0, -262131, 0, 0, -196606, 0, 0, -196605, 0, 0, -196604, 6, 0, -196603, 6, 0, -196602, 6, 0, -196601, 6, 0, -196600, 1, 0, -196599, 0, 0, -196598, 1, 0, -196597, 1, 0, -196596, 0, 0, -196595, 0, 0, -196594, 0, 0, -131071, 9, 0, -131070, 0, 0, -131069, 0, 0, -131068, 2, 0, -131067, 2, 0, -131066, 0, 0, -131065, 21, 0, -131064, 19, 0, -131063, 0, 0, -131062, 0, 0, -131061, 16, 0, -131060, 0, 0, -131059, 0, 0, -131058, 0, 0, -131057, 0, 0, -131056, 0, 0, -65534, 0, 0, -65533, 1, 0, -65532, 0, 0, -65531, 0, 0, -65530, 20, 0, -65529, 19, 0, -65528, 2, 0, -65527, 0, 0, -65526, 14, 0, -65525, 0, 0, -65524, 0, 0, -65523, 0, 0, -65522, 23, 0, -65521, 0, 0, -65520, 0, 0, -65519, 0, 0, 3, 1, 0, 4, 2, 0, 5, 0, 0, 6, 1, 0, 7, 1, 0, 8, 0, 0, 9, 10, 0, 10, 12, 0, 11, 0, 0, 12, 0, 0, 13, 8, 0, 14, 0, 0, 15, 0, 0, 16, 0, 0, 17, 0, 0, 65538, 0, 0, 65539, 0, 0, 65540, 2, 0, 65541, 0, 0, 65542, 1, 0, 65543, 15, 0, 65544, 0, 0, 65545, 0, 0, 65546, 0, 0, 65547, 0, 0, 65548, 0, 0, 65549, 25, 0, 65550, 8, 0, 65551, 0, 0, 65552, 21, 0, 65553, 0, 0, 131074, 0, 0, 131075, 1, 0, 131076, 0, 0, 131077, 1, 0, 131078, 0, 0, 131079, 0, 0, 131080, 0, 0, 131081, 5, 0, 131082, 0, 0, 131083, 0, 0, 131084, 0, 0, 131085, 0, 0, 131086, 0, 0, 131087, 0, 0, 131088, 0, 0, 131089, 0, 0, 196610, 0, 0, 196611, 0, 0, 196612, 0, 0, 196613, 23, 0, 196614, 0, 0, 196615, 0, 0, 196616, 0, 0, 196617, 5, 0, 196618, 5, 0, 196619, 0, 0, 196620, 0, 0, 196621, 0, 0, 196622, 0, 0, 196623, 23, 0, 196624, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 8, 0, 262153, 5, 0, 262154, 5, 0, 262155, 0, 0, 262156, 0, 0, 262157, 21, 0, 262158, 0, 0, 262159, 0, 0, 262160, 0, 0, 327686, 0, 0, 327687, 0, 0, 327688, 0, 0, 327689, 0, 0, 327690, 0, 0, 327691, 0, 0, 327692, 0, 0, 327693, 0, 0, 327694, 0, 0) layer_0/tile_data = PackedInt32Array(-458747, 0, 0, -458746, 0, 0, -393212, 0, 0, -393211, 0, 0, -393210, 0, 0, -393209, 0, 0, -393208, 0, 0, -393207, 0, 0, -327678, 0, 0, -327677, 0, 0, -327676, 0, 0, -327675, 6, 0, -327674, 6, 0, -327673, 6, 0, -327672, 6, 0, -327671, 0, 0, -327670, 0, 0, -327669, 0, 0, -262142, 0, 0, -262141, 0, 0, -262140, 6, 0, -262139, 6, 0, -262138, 6, 0, -262137, 6, 0, -262136, 6, 0, -262135, 0, 0, -262134, 0, 0, -262133, 0, 0, -262132, 0, 0, -262131, 0, 0, -196606, 0, 0, -196605, 0, 0, -196604, 6, 0, -196603, 6, 0, -196602, 6, 0, -196601, 6, 0, -196600, 1, 0, -196599, 0, 0, -196598, 1, 0, -196597, 1, 0, -196596, 0, 0, -196595, 0, 0, -196594, 0, 0, -131071, 9, 0, -131070, 0, 0, -131069, 0, 0, -131068, 2, 0, -131067, 2, 0, -131066, 0, 0, -131065, 21, 0, -131064, 19, 0, -131063, 0, 0, -131062, 0, 0, -131061, 16, 0, -131060, 0, 0, -131059, 0, 0, -131058, 0, 0, -131057, 0, 0, -131056, 0, 0, -65534, 0, 0, -65533, 1, 0, -65532, 0, 0, -65531, 0, 0, -65530, 20, 0, -65529, 19, 0, -65528, 2, 0, -65527, 0, 0, -65526, 14, 0, -65525, 0, 0, -65524, 0, 0, -65523, 0, 0, -65522, 23, 0, -65521, 0, 0, -65520, 0, 0, -65519, 0, 0, 3, 1, 0, 4, 2, 0, 5, 0, 0, 6, 1, 0, 7, 1, 0, 8, 0, 0, 9, 10, 0, 10, 12, 0, 11, 0, 0, 12, 0, 0, 13, 8, 0, 14, 0, 0, 15, 0, 0, 16, 0, 0, 17, 0, 0, 65538, 0, 0, 65539, 0, 0, 65540, 2, 0, 65541, 0, 0, 65542, 1, 0, 65543, 15, 0, 65544, 0, 0, 65545, 0, 0, 65546, 0, 0, 65547, 0, 0, 65548, 0, 0, 65549, 25, 0, 65550, 8, 0, 65551, 0, 0, 65552, 21, 0, 65553, 0, 0, 131074, 0, 0, 131075, 1, 0, 131076, 0, 0, 131077, 1, 0, 131078, 0, 0, 131079, 0, 0, 131080, 0, 0, 131081, 5, 0, 131082, 0, 0, 131083, 0, 0, 131084, 0, 0, 131085, 0, 0, 131086, 0, 0, 131087, 0, 0, 131088, 0, 0, 131089, 0, 0, 196610, 0, 0, 196611, 0, 0, 196612, 0, 0, 196613, 23, 0, 196614, 0, 0, 196615, 0, 0, 196616, 0, 0, 196617, 5, 0, 196618, 5, 0, 196619, 0, 0, 196620, 0, 0, 196621, 0, 0, 196622, 0, 0, 196623, 23, 0, 196624, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 8, 0, 262153, 5, 0, 262154, 5, 0, 262155, 0, 0, 262156, 0, 0, 262157, 21, 0, 262158, 0, 0, 262159, 0, 0, 262160, 0, 0, 327686, 0, 0, 327687, 0, 0, 327688, 0, 0, 327689, 0, 0, 327690, 0, 0, 327691, 0, 0, 327692, 0, 0, 327693, 0, 0, 327694, 0, 0)
[node name="Troll" parent="." instance=ExtResource("2")] [node name="Troll" parent="." instance=ExtResource("2")]
modulate = Color(1.5, 1.5, 1.5, 1)
position = Vector2(602.819, -39.2876) position = Vector2(602.819, -39.2876)

View File

@@ -17,6 +17,10 @@ run/main_scene="res://map.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"

View File

@@ -4,8 +4,8 @@ const MOTION_SPEED = 30
const FRICTION_FACTOR = 0.89 const FRICTION_FACTOR = 0.89
const TAN30DEG = tan(deg_to_rad(30)) const TAN30DEG = tan(deg_to_rad(30))
func _physics_process(_delta): func _physics_process(_delta: float) -> void:
var motion = Vector2() var motion := Vector2()
motion.x = Input.get_axis(&"move_left", &"move_right") motion.x = Input.get_axis(&"move_left", &"move_right")
motion.y = Input.get_axis(&"move_up", &"move_down") motion.y = Input.get_axis(&"move_up", &"move_down")
# Make diagonal movement fit for hexagonal tiles. # Make diagonal movement fit for hexagonal tiles.

View File

@@ -15,7 +15,9 @@ texture = ExtResource("2")
[node name="Shadow" type="Sprite2D" parent="."] [node name="Shadow" type="Sprite2D" parent="."]
modulate = Color(0, 0, 0, 0.501961) modulate = Color(0, 0, 0, 0.501961)
show_behind_parent = true show_behind_parent = true
position = Vector2(3, 3) position = Vector2(16.4422, 4.89438)
scale = Vector2(0.794259, 1.04505)
skew = 0.523599
texture = ExtResource("2") texture = ExtResource("2")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."] [node name="CollisionShape2D" type="CollisionShape2D" parent="."]
@@ -23,4 +25,3 @@ position = Vector2(3.24216, 19.453)
shape = SubResource("1") shape = SubResource("1")
[node name="Camera2D" type="Camera2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."]
current = true

View File

@@ -7,7 +7,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/148 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2716
## Screenshots ## Screenshots

View File

@@ -1,18 +1,18 @@
[gd_scene load_steps=4 format=2] [gd_scene load_steps=4 format=3 uid="uid://cgx884jv27maj"]
[ext_resource path="res://bowling_ball.png" type="Texture2D" id=1] [ext_resource type="Texture2D" uid="uid://cyqshsjd3qwo0" path="res://bowling_ball.png" id="1"]
[sub_resource type="PhysicsMaterial" id=1] [sub_resource type="PhysicsMaterial" id="1"]
bounce = 0.4 bounce = 0.4
[sub_resource type="CircleShape2D" id=2] [sub_resource type="CircleShape2D" id="2"]
radius = 30.0 radius = 30.0
[node name="Ball" type="RigidDynamicBody2D"] [node name="Ball" type="RigidBody2D"]
physics_material_override = SubResource( 1 ) physics_material_override = SubResource("1")
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource( 1 ) texture = ExtResource("1")
[node name="Collision" type="CollisionShape2D" parent="."] [node name="Collision" type="CollisionShape2D" parent="."]
shape = SubResource( 2 ) shape = SubResource("2")

View File

@@ -2,15 +2,16 @@ extends Node2D
@export var ball_scene: PackedScene = preload("res://ball.tscn") @export var ball_scene: PackedScene = preload("res://ball.tscn")
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
if event.is_echo(): if event.is_echo():
return return
if event is InputEventMouseButton and event.is_pressed(): if event is InputEventMouseButton and event.is_pressed():
if event.button_index == MOUSE_BUTTON_LEFT: if event.button_index == MOUSE_BUTTON_LEFT:
spawn(get_global_mouse_position()) spawn(get_global_mouse_position())
func spawn(spawn_global_position): func spawn(spawn_global_position: Vector2) -> void:
var instance = ball_scene.instantiate() var instance: Node2D = ball_scene.instantiate()
instance.global_position = spawn_global_position instance.global_position = spawn_global_position
add_child(instance) add_child(instance)

View File

@@ -18,6 +18,10 @@ run/main_scene="res://scene_instancing.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"
@@ -25,6 +29,7 @@ window/stretch/aspect="expand"
[physics] [physics]
common/physics_ticks_per_second=120
2d/default_gravity=300 2d/default_gravity=300
[rendering] [rendering]

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=13 format=3 uid="uid://rcsr8t4nw526"] [gd_scene load_steps=13 format=3 uid="uid://rcsr8t4nw526"]
[ext_resource type="Script" path="res://ball_factory.gd" id="1"] [ext_resource type="Script" path="res://ball_factory.gd" id="1"]
[ext_resource type="PackedScene" path="res://ball.tscn" id="2"] [ext_resource type="PackedScene" uid="uid://cgx884jv27maj" path="res://ball.tscn" id="2"]
[sub_resource type="PhysicsMaterial" id="1"] [sub_resource type="PhysicsMaterial" id="1"]
bounce = 0.4 bounce = 0.4
@@ -35,7 +35,9 @@ bounce = 0.4
[node name="SceneInstancing" type="Node2D"] [node name="SceneInstancing" type="Node2D"]
[node name="InfoLabel" type="Label" parent="."] [node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="InfoLabel" type="Label" parent="CanvasLayer"]
offset_left = 16.0 offset_left = 16.0
offset_top = 16.0 offset_top = 16.0
offset_right = 370.0 offset_right = 370.0

View File

@@ -9,7 +9,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/112 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2718
## How does it work? ## How does it work?

View File

@@ -35,7 +35,6 @@ func _physics_process(_delta):
motion.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up") motion.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
motion.y /= 2 motion.y /= 2
motion = motion.normalized() * MOTION_SPEED motion = motion.normalized() * MOTION_SPEED
#warning-ignore:return_value_discarded
set_velocity(motion) set_velocity(motion)
move_and_slide() move_and_slide()
var dir = velocity var dir = velocity
@@ -48,7 +47,6 @@ func _physics_process(_delta):
func update_animation(anim_set): func update_animation(anim_set):
var angle = rad_to_deg(last_direction.angle()) + 22.5 var angle = rad_to_deg(last_direction.angle()) + 22.5
var slice_dir = floor(angle / 45) var slice_dir = floor(angle / 45)

View File

@@ -1,7 +1,7 @@
# Kinematic Character 2D # Kinematic Character 2D
Example of how to make a kinematic character controller in 2D using Example of how to make a kinematic character controller in 2D using
[`KinematicBody2D`](https://docs.godotengine.org/en/latest/classes/class_kinematicbody2d.html). [`CharacterBody2D`](https://docs.godotengine.org/en/latest/classes/class_characterbody2d.html).
The character moves around, is affected by moving platforms, The character moves around, is affected by moving platforms,
can jump through one-way collision platforms, etc. can jump through one-way collision platforms, etc.
@@ -9,7 +9,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/113 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2719
## Screenshots ## Screenshots

View File

@@ -1,5 +1,5 @@
extends Node extends Node
func _on_body_entered(body): func _on_body_entered(body: Node2D) -> void:
if body.name == "Player": if body.name == "Player":
$"../WinText".show() $"../WinText".show()

View File

@@ -5,11 +5,11 @@ const WALK_MAX_SPEED = 200
const STOP_FORCE = 1300 const STOP_FORCE = 1300
const JUMP_SPEED = 200 const JUMP_SPEED = 200
@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") @onready var gravity := float(ProjectSettings.get_setting("physics/2d/default_gravity"))
func _physics_process(delta): func _physics_process(delta: float) -> void:
# Horizontal movement code. First, get the player's input. # Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right")) var walk := WALK_FORCE * (Input.get_axis(&"move_left", &"move_right"))
# Slow down the player if they're not trying to move. # Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2: if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned. # The velocity, slowed down a bit, and then reassigned.

View File

@@ -19,6 +19,10 @@ run/main_scene="res://world.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/size/viewport_width=530 window/size/viewport_width=530

View File

@@ -6,7 +6,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/115 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2720
## Screenshots ## Screenshots

View File

@@ -17,6 +17,10 @@ run/main_scene="res://lightmask.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"

View File

@@ -8,7 +8,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/116 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2721
## Screenshots ## Screenshots

View File

@@ -27,7 +27,7 @@ roughness/mode=0
roughness/src_normal="" roughness/src_normal=""
process/fix_alpha_border=true process/fix_alpha_border=true
process/premult_alpha=false process/premult_alpha=false
process/normal_map_invert_y=false process/normal_map_invert_y=true
process/hdr_as_srgb=false process/hdr_as_srgb=false
process/hdr_clamp_exposure=false process/hdr_clamp_exposure=false
process/size_limit=0 process/size_limit=0

View File

@@ -1,7 +1,7 @@
extends Node2D extends Node2D
func _input(event): func _input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_directional_light"): if event.is_action_pressed("toggle_directional_light"):
$DirectionalLight2D.visible = not $DirectionalLight2D.visible $DirectionalLight2D.visible = not $DirectionalLight2D.visible

View File

@@ -320,6 +320,7 @@ shadow_enabled = true
shadow_filter = 1 shadow_filter = 1
shadow_filter_smooth = 1.2 shadow_filter_smooth = 1.2
texture = ExtResource("3") texture = ExtResource("3")
metadata/_edit_group_ = true
[node name="Blob" type="Sprite2D" parent="RedLight"] [node name="Blob" type="Sprite2D" parent="RedLight"]
material = SubResource("2") material = SubResource("2")
@@ -338,8 +339,9 @@ shadow_enabled = true
shadow_filter = 1 shadow_filter = 1
shadow_filter_smooth = 1.2 shadow_filter_smooth = 1.2
texture = ExtResource("3") texture = ExtResource("3")
metadata/_edit_group_ = true
[node name="blob" type="Sprite2D" parent="GreenLight"] [node name="Blob" type="Sprite2D" parent="GreenLight"]
material = SubResource("5") material = SubResource("5")
texture = ExtResource("4") texture = ExtResource("4")
@@ -356,8 +358,9 @@ shadow_enabled = true
shadow_filter = 1 shadow_filter = 1
shadow_filter_smooth = 1.2 shadow_filter_smooth = 1.2
texture = ExtResource("3") texture = ExtResource("3")
metadata/_edit_group_ = true
[node name="blob" type="Sprite2D" parent="BlueLight"] [node name="Blob" type="Sprite2D" parent="BlueLight"]
material = SubResource("6") material = SubResource("6")
texture = ExtResource("4") texture = ExtResource("4")

View File

@@ -15,9 +15,13 @@ config/description="Simple demo of 2D lights and shadows,
using PointLight2D and LightOccluder2D." using PointLight2D and LightOccluder2D."
config/tags=PackedStringArray("2d", "demo", "official", "rendering") config/tags=PackedStringArray("2d", "demo", "official", "rendering")
run/main_scene="res://light_shadows.tscn" run/main_scene="res://light_shadows.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.3")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/size/viewport_width=800 window/size/viewport_width=800
@@ -28,22 +32,22 @@ window/stretch/aspect="expand"
toggle_directional_light={ toggle_directional_light={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
toggle_point_lights={ toggle_point_lights={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":80,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":80,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
cycle_directional_light_shadows_quality={ cycle_directional_light_shadows_quality={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
cycle_point_light_shadows_quality={ cycle_point_light_shadows_quality={
"deadzone": 0.2, "deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":72,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":72,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }

View File

@@ -9,7 +9,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/117 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2722
## Screenshots ## Screenshots

View File

@@ -1,11 +1,10 @@
extends CharacterBody2D extends CharacterBody2D
var movement_speed := 200.0
var movement_speed: float = 200.0
@onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D @onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D
func _ready() -> void:
func _ready():
# These values need to be adjusted for the actor's speed # These values need to be adjusted for the actor's speed
# and the navigation layout. # and the navigation layout.
navigation_agent.path_desired_distance = 2.0 navigation_agent.path_desired_distance = 2.0
@@ -15,17 +14,18 @@ func _ready():
# The "click" event is a custom input action defined in # The "click" event is a custom input action defined in
# Project > Project Settings > Input Map tab. # Project > Project Settings > Input Map tab.
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
if not event.is_action_pressed("click"): if not event.is_action_pressed("click"):
return return
set_movement_target(get_global_mouse_position()) set_movement_target(get_global_mouse_position())
func set_movement_target(movement_target: Vector2): func set_movement_target(movement_target: Vector2) -> void:
navigation_agent.target_position = movement_target navigation_agent.target_position = movement_target
func _physics_process(_delta): func _physics_process(_delta: float) -> void:
if navigation_agent.is_navigation_finished(): if navigation_agent.is_navigation_finished():
return return

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://bjgad00c2xiuc"] [gd_scene load_steps=4 format=3 uid="uid://bjgad00c2xiuc"]
[ext_resource type="NavigationPolygon" uid="uid://prlt4stfk6uh" path="res://navigation_polygon.res" id="2_lph0a"]
[ext_resource type="Texture2D" uid="uid://bk26gi6qsuh18" path="res://map.png" id="2_nxfkp"] [ext_resource type="Texture2D" uid="uid://bk26gi6qsuh18" path="res://map.png" id="2_nxfkp"]
[ext_resource type="NavigationPolygon" uid="uid://bk5r48dcijlqt" path="res://navigation_polygon.res" id="3_6c0vu"]
[ext_resource type="PackedScene" uid="uid://ct7veakwiei3h" path="res://character.tscn" id="4_n6iop"] [ext_resource type="PackedScene" uid="uid://ct7veakwiei3h" path="res://character.tscn" id="4_n6iop"]
[node name="Navigation" type="Node2D"] [node name="Navigation" type="Node2D"]
@@ -12,7 +12,7 @@ position = Vector2(400, 302)
texture = ExtResource("2_nxfkp") texture = ExtResource("2_nxfkp")
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."] [node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
navigation_polygon = ExtResource("3_6c0vu") navigation_polygon = ExtResource("2_lph0a")
[node name="Character" parent="." instance=ExtResource("4_n6iop")] [node name="Character" parent="." instance=ExtResource("4_n6iop")]
position = Vector2(211, 141) position = Vector2(211, 141)

Binary file not shown.

View File

@@ -19,6 +19,10 @@ run/main_scene="res://navigation.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/size/viewport_width=800 window/size/viewport_width=800
@@ -33,6 +37,10 @@ click={
] ]
} }
[physics]
common/physics_ticks_per_second=120
[rendering] [rendering]
renderer/rendering_method="gl_compatibility" renderer/rendering_method="gl_compatibility"

View File

@@ -7,7 +7,7 @@ Language: GDScript
Renderer: Compatibility Renderer: Compatibility
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/519 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2723
## Screenshots ## Screenshots

View File

@@ -1,29 +1,35 @@
extends Node2D extends Node2D
enum State { IDLE, FOLLOW } const PathFindAStar = preload("./pathfind_astar.gd")
const MASS = 10.0 enum State {
const ARRIVE_DISTANCE = 10.0 IDLE,
FOLLOW,
}
@export var speed: float = 200.0 const MASS: float = 10.0
const ARRIVE_DISTANCE: float = 10.0
var _state = State.IDLE @export_range(10, 500, 0.1, "or_greater") var speed: float = 200.0
var _velocity = Vector2()
@onready var _tile_map = $"../TileMap" var _state := State.IDLE
var _velocity := Vector2()
var _click_position = Vector2() var _click_position := Vector2()
var _path = PackedVector2Array() var _path := PackedVector2Array()
var _next_point = Vector2() var _next_point := Vector2()
func _ready(): @onready var _tile_map: PathFindAStar = $"../TileMap"
func _ready() -> void:
_change_state(State.IDLE) _change_state(State.IDLE)
func _process(_delta): func _process(_delta: float) -> void:
if _state != State.FOLLOW: if _state != State.FOLLOW:
return return
var arrived_to_next_point = _move_to(_next_point)
var arrived_to_next_point: bool = _move_to(_next_point)
if arrived_to_next_point: if arrived_to_next_point:
_path.remove_at(0) _path.remove_at(0)
if _path.is_empty(): if _path.is_empty():
@@ -32,7 +38,7 @@ func _process(_delta):
_next_point = _path[0] _next_point = _path[0]
func _unhandled_input(event): func _unhandled_input(event: InputEvent) -> void:
_click_position = get_global_mouse_position() _click_position = get_global_mouse_position()
if _tile_map.is_point_walkable(_click_position): if _tile_map.is_point_walkable(_click_position):
if event.is_action_pressed(&"teleport_to", false, true): if event.is_action_pressed(&"teleport_to", false, true):
@@ -42,16 +48,16 @@ func _unhandled_input(event):
_change_state(State.FOLLOW) _change_state(State.FOLLOW)
func _move_to(local_position): func _move_to(local_position: Vector2) -> bool:
var desired_velocity = (local_position - position).normalized() * speed var desired_velocity: Vector2 = (local_position - position).normalized() * speed
var steering = desired_velocity - _velocity var steering: Vector2 = desired_velocity - _velocity
_velocity += steering / MASS _velocity += steering / MASS
position += _velocity * get_process_delta_time() position += _velocity * get_process_delta_time()
rotation = _velocity.angle() rotation = _velocity.angle()
return position.distance_to(local_position) < ARRIVE_DISTANCE return position.distance_to(local_position) < ARRIVE_DISTANCE
func _change_state(new_state): func _change_state(new_state: State) -> void:
if new_state == State.IDLE: if new_state == State.IDLE:
_tile_map.clear_path() _tile_map.clear_path()
elif new_state == State.FOLLOW: elif new_state == State.FOLLOW:

View File

@@ -1,19 +1,23 @@
extends TileMap extends TileMap
enum Tile { OBSTACLE, START_POINT, END_POINT } enum Tile {
OBSTACLE,
START_POINT,
END_POINT,
}
const CELL_SIZE = Vector2i(64, 64) const CELL_SIZE = Vector2i(64, 64)
const BASE_LINE_WIDTH = 3.0 const BASE_LINE_WIDTH: float = 3.0
const DRAW_COLOR = Color.WHITE * Color(1, 1, 1, 0.5) const DRAW_COLOR = Color.WHITE * Color(1, 1, 1, 0.5)
# The object for pathfinding on 2D grids. # The object for pathfinding on 2D grids.
var _astar = AStarGrid2D.new() var _astar := AStarGrid2D.new()
var _start_point = Vector2i() var _start_point := Vector2i()
var _end_point = Vector2i() var _end_point := Vector2i()
var _path = PackedVector2Array() var _path := PackedVector2Array()
func _ready(): func _ready() -> void:
# Region should match the size of the playable area plus one (in tiles). # Region should match the size of the playable area plus one (in tiles).
# In this demo, the playable area is 17×9 tiles, so the rect size is 18×10. # In this demo, the playable area is 17×9 tiles, so the rect size is 18×10.
_astar.region = Rect2i(0, 0, 18, 10) _astar.region = Rect2i(0, 0, 18, 10)
@@ -26,35 +30,35 @@ func _ready():
for i in range(_astar.region.position.x, _astar.region.end.x): for i in range(_astar.region.position.x, _astar.region.end.x):
for j in range(_astar.region.position.y, _astar.region.end.y): for j in range(_astar.region.position.y, _astar.region.end.y):
var pos = Vector2i(i, j) var pos := Vector2i(i, j)
if get_cell_source_id(0, pos) == Tile.OBSTACLE: if get_cell_source_id(0, pos) == Tile.OBSTACLE:
_astar.set_point_solid(pos) _astar.set_point_solid(pos)
func _draw(): func _draw() -> void:
if _path.is_empty(): if _path.is_empty():
return return
var last_point = _path[0] var last_point: Vector2 = _path[0]
for index in range(1, len(_path)): for index in range(1, len(_path)):
var current_point = _path[index] var current_point: Vector2 = _path[index]
draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true) draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true)
draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR) draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR)
last_point = current_point last_point = current_point
func round_local_position(local_position): func round_local_position(local_position: Vector2i) -> Vector2i:
return map_to_local(local_to_map(local_position)) return map_to_local(local_to_map(local_position))
func is_point_walkable(local_position): func is_point_walkable(local_position: Vector2) -> bool:
var map_position = local_to_map(local_position) var map_position: Vector2i = local_to_map(local_position)
if _astar.is_in_boundsv(map_position): if _astar.is_in_boundsv(map_position):
return not _astar.is_point_solid(map_position) return not _astar.is_point_solid(map_position)
return false return false
func clear_path(): func clear_path() -> void:
if not _path.is_empty(): if not _path.is_empty():
_path.clear() _path.clear()
erase_cell(0, _start_point) erase_cell(0, _start_point)
@@ -63,7 +67,7 @@ func clear_path():
queue_redraw() queue_redraw()
func find_path(local_start_point, local_end_point): func find_path(local_start_point: Vector2i, local_end_point: Vector2i) -> PackedVector2Array:
clear_path() clear_path()
_start_point = local_to_map(local_start_point) _start_point = local_to_map(local_start_point)

View File

@@ -18,6 +18,10 @@ run/main_scene="res://game.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"

View File

@@ -0,0 +1,15 @@
# Navigation Mesh Chunks 2D
Demo that shows how to bake navigation meshes for large world chunk systems.
A mouse cursor left click changes the start position for the debug paths.
Language: GDScript
Renderer: Compatibility
> Note: this demo requires Godot 4.3 or later
## Screenshots
![Screenshot](screenshots/navigation_mesh_chunks.webp)

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,156 @@
extends Node2D
static var map_cell_size: float = 1.0
static var chunk_size: int = 256
static var cell_size: float = 1.0
static var agent_radius: float = 10.0
static var chunk_id_to_region: Dictionary = {}
var path_start_position: Vector2
func _ready() -> void:
NavigationServer2D.set_debug_enabled(true)
path_start_position = %DebugPaths.global_position
var map: RID = get_world_2d().navigation_map
NavigationServer2D.map_set_cell_size(map, map_cell_size)
# Disable performance costly edge connection margin feature.
# This feature is not needed to merge navigation mesh edges.
# If edges are well aligned they will merge just fine by edge key.
NavigationServer2D.map_set_use_edge_connections(map, false)
# Parse the collision shapes below our parse root node.
var source_geometry: NavigationMeshSourceGeometryData2D = NavigationMeshSourceGeometryData2D.new()
var parse_settings: NavigationPolygon = NavigationPolygon.new()
parse_settings.parsed_geometry_type = NavigationPolygon.PARSED_GEOMETRY_STATIC_COLLIDERS
NavigationServer2D.parse_source_geometry_data(parse_settings, source_geometry, %ParseRootNode)
# Add an outline to define the traversable surface that the parsed collision shapes can "cut" into.
var traversable_outline: PackedVector2Array = PackedVector2Array([
Vector2(0.0, 0.0),
Vector2(1920.0, 0.0),
Vector2(1920.0, 1080.0),
Vector2(0.0, 1080.0),
])
source_geometry.add_traversable_outline(traversable_outline)
create_region_chunks(%ChunksContainer, source_geometry, chunk_size * cell_size, agent_radius)
static func create_region_chunks(chunks_root_node: Node, p_source_geometry: NavigationMeshSourceGeometryData2D, p_chunk_size: float, p_agent_radius: float) -> void:
# We need to know how many chunks are required for the input geometry.
# So first get an axis aligned bounding box that covers all vertices.
var input_geometry_bounds: Rect2 = calculate_source_geometry_bounds(p_source_geometry)
# Rasterize bounding box into chunk grid to know range of required chunks.
var start_chunk: Vector2 = floor(
input_geometry_bounds.position / p_chunk_size
)
var end_chunk: Vector2 = floor(
(input_geometry_bounds.position + input_geometry_bounds.size)
/ p_chunk_size
)
for chunk_y in range(start_chunk.y, end_chunk.y + 1):
for chunk_x in range(start_chunk.x, end_chunk.x + 1):
var chunk_id: Vector2i = Vector2i(chunk_x, chunk_y)
var chunk_bounding_box: Rect2 = Rect2(
Vector2(chunk_x, chunk_y) * p_chunk_size,
Vector2(p_chunk_size, p_chunk_size),
)
# We grow the chunk bounding box to include geometry
# from all the neighbor chunks so edges can align.
# The border size is the same value as our grow amount so
# the final navigation mesh ends up with the intended chunk size.
var baking_bounds: Rect2 = chunk_bounding_box.grow(p_chunk_size)
var chunk_navmesh: NavigationPolygon = NavigationPolygon.new()
chunk_navmesh.parsed_geometry_type = NavigationPolygon.PARSED_GEOMETRY_STATIC_COLLIDERS
chunk_navmesh.baking_rect = baking_bounds
chunk_navmesh.border_size = p_chunk_size
chunk_navmesh.agent_radius = p_agent_radius
NavigationServer2D.bake_from_source_geometry_data(chunk_navmesh, p_source_geometry)
# The only reason we reset the baking bounds here is to not render its debug.
chunk_navmesh.baking_rect = Rect2()
# Snap vertex positions to avoid most rasterization issues with float precision.
var navmesh_vertices: PackedVector2Array = chunk_navmesh.vertices
for i in navmesh_vertices.size():
var vertex: Vector2 = navmesh_vertices[i]
navmesh_vertices[i] = vertex.snappedf(map_cell_size * 0.1)
chunk_navmesh.vertices = navmesh_vertices
var chunk_region: NavigationRegion2D = NavigationRegion2D.new()
chunk_region.navigation_polygon = chunk_navmesh
chunks_root_node.add_child(chunk_region)
chunk_id_to_region[chunk_id] = chunk_region
static func calculate_source_geometry_bounds(p_source_geometry: NavigationMeshSourceGeometryData2D) -> Rect2:
if p_source_geometry.has_method("get_bounds"):
# Godot 4.3 Patch added get_bounds() function that does the same but faster.
return p_source_geometry.call("get_bounds")
var bounds: Rect2 = Rect2()
var first_vertex: bool = true
for traversable_outline: PackedVector2Array in p_source_geometry.get_traversable_outlines():
for traversable_point: Vector2 in traversable_outline:
if first_vertex:
first_vertex = false
bounds.position = traversable_point
else:
bounds = bounds.expand(traversable_point)
for obstruction_outline: PackedVector2Array in p_source_geometry.get_obstruction_outlines():
for obstruction_point: Vector2 in obstruction_outline:
if first_vertex:
first_vertex = false
bounds.position = obstruction_point
else:
bounds = bounds.expand(obstruction_point)
for projected_obstruction: Dictionary in p_source_geometry.get_projected_obstructions():
var projected_obstruction_vertices: PackedFloat32Array = projected_obstruction["vertices"]
for i in projected_obstruction_vertices.size() / 2:
var vertex: Vector2 = Vector2(projected_obstruction_vertices[i * 2], projected_obstruction_vertices[i * 2 + 1])
if first_vertex:
first_vertex = false
bounds.position = vertex
else:
bounds = bounds.expand(vertex)
return bounds
func _process(_delta: float) -> void:
var mouse_cursor_position: Vector2 = get_global_mouse_position()
var map: RID = get_world_2d().navigation_map
# Do not query when the map has never synchronized and is empty.
if NavigationServer2D.map_get_iteration_id(map) == 0:
return
var closest_point_on_navmesh: Vector2 = NavigationServer2D.map_get_closest_point(
map,
mouse_cursor_position
)
if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
path_start_position = closest_point_on_navmesh
%DebugPaths.global_position = path_start_position
%PathDebugCorridorFunnel.target_position = closest_point_on_navmesh
%PathDebugEdgeCentered.target_position = closest_point_on_navmesh
%PathDebugCorridorFunnel.get_next_path_position()
%PathDebugEdgeCentered.get_next_path_position()

View File

@@ -0,0 +1,99 @@
[gd_scene load_steps=2 format=3 uid="uid://svfku2i5n033"]
[ext_resource type="Script" path="res://navmesh_chhunks_demo_2d.gd" id="1_d68tl"]
[node name="NavMeshChunksDemo2D" type="Node2D"]
script = ExtResource("1_d68tl")
[node name="Camera2D" type="Camera2D" parent="."]
position = Vector2(960, 540)
zoom = Vector2(0.8, 0.8)
[node name="ParseRootNode" type="Node2D" parent="."]
unique_name_in_owner = true
[node name="StaticBody2D" type="StaticBody2D" parent="ParseRootNode"]
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="ParseRootNode/StaticBody2D"]
polygon = PackedVector2Array(244, 147, 636, 155, 376, 391, 460, 655, 804, 795, 756, 971, 484, 839, 308, 963, 132, 811, 128, 559)
[node name="CollisionPolygon2D2" type="CollisionPolygon2D" parent="ParseRootNode/StaticBody2D"]
polygon = PackedVector2Array(1312, 207, 1596, 91, 1832, 175, 1739, 926, 1562, 796, 1508, 935, 1184, 811, 1324, 533, 1499, 599, 1684, 511, 1596, 322)
[node name="CollisionPolygon2D3" type="CollisionPolygon2D" parent="ParseRootNode/StaticBody2D"]
polygon = PackedVector2Array(661, 339, 943, 397, 1112, 178, 1172, 443, 960, 639, 700, 579)
[node name="DebugPaths" type="Node2D" parent="."]
unique_name_in_owner = true
[node name="PathDebugCorridorFunnel" type="NavigationAgent2D" parent="DebugPaths"]
unique_name_in_owner = true
debug_enabled = true
debug_use_custom = true
debug_path_custom_color = Color(1, 0, 1, 1)
debug_path_custom_point_size = 10.0
debug_path_custom_line_width = 4.0
[node name="PathDebugEdgeCentered" type="NavigationAgent2D" parent="DebugPaths"]
unique_name_in_owner = true
path_postprocessing = 1
debug_enabled = true
debug_use_custom = true
debug_path_custom_color = Color(1, 1, 0, 1)
debug_path_custom_point_size = 10.0
debug_path_custom_line_width = 4.0
[node name="ChunksContainer" type="Node2D" parent="."]
unique_name_in_owner = true
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="PanelContainer" type="PanelContainer" parent="CanvasLayer"]
offset_right = 40.0
offset_bottom = 40.0
[node name="MarginContainer" type="MarginContainer" parent="CanvasLayer/PanelContainer"]
layout_mode = 2
theme_override_constants/margin_left = 15
theme_override_constants/margin_top = 15
theme_override_constants/margin_right = 15
theme_override_constants/margin_bottom = 15
[node name="VBoxContainer" type="VBoxContainer" parent="CanvasLayer/PanelContainer/MarginContainer"]
layout_mode = 2
[node name="Label" type="Label" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Use cursor button to set path start position"
[node name="HBoxContainer" type="HBoxContainer" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="ColorRect" type="ColorRect" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
custom_minimum_size = Vector2(128, 8)
layout_mode = 2
size_flags_vertical = 4
color = Color(1, 0, 1, 1)
[node name="Label" type="Label" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer"]
layout_mode = 2
text = "Path corridor-funnel"
horizontal_alignment = 1
vertical_alignment = 1
[node name="HBoxContainer2" type="HBoxContainer" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="ColorRect" type="ColorRect" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
custom_minimum_size = Vector2(128, 8)
layout_mode = 2
size_flags_vertical = 4
color = Color(1, 1, 0, 1)
[node name="Label" type="Label" parent="CanvasLayer/PanelContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
layout_mode = 2
text = "Path edge-centered"
horizontal_alignment = 1
vertical_alignment = 1

View File

@@ -0,0 +1,29 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Navigation Mesh Chunks 2D"
config/tags=PackedStringArray("2d", "ai", "demo", "official")
run/main_scene="res://navmesh_chhunks_demo_2d.tscn"
config/features=PackedStringArray("4.3", "GL Compatibility")
config/icon="res://icon.webp"
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
[rendering]
renderer/rendering_method="gl_compatibility"
renderer/rendering_method.mobile="gl_compatibility"

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -6,7 +6,7 @@ Language: GDScript
Renderer: Mobile Renderer: Mobile
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/118 Check out this demo on the asset library: https://godotengine.org/asset-library/asset/2724
## How does it work? ## How does it work?

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
extends Label extends Label
func _input(event): func _input(event: InputEvent) -> void:
if event.is_action_pressed("toggle_pause"): if event.is_action_pressed("toggle_pause"):
get_tree().paused = not get_tree().paused get_tree().paused = not get_tree().paused

View File

@@ -17,6 +17,10 @@ run/main_scene="res://particles.tscn"
config/features=PackedStringArray("4.2") config/features=PackedStringArray("4.2")
config/icon="res://icon.webp" config/icon="res://icon.webp"
[debug]
gdscript/warnings/untyped_declaration=1
[display] [display]
window/stretch/mode="canvas_items" window/stretch/mode="canvas_items"

Some files were not shown because too many files have changed in this diff Show More