mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-05 10:09:47 +03:00
Compare commits
84 Commits
4.2-31d1c0
...
4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52e3004465 | ||
|
|
5557b10cfa | ||
|
|
fdb2f50a20 | ||
|
|
0d46333c4e | ||
|
|
c3b0331d8a | ||
|
|
0e24c8eb2e | ||
|
|
be77353917 | ||
|
|
d3c71ddb20 | ||
|
|
c49e134e13 | ||
|
|
81249b3f4a | ||
|
|
51a7d389af | ||
|
|
5f0e0ce205 | ||
|
|
6f44371df1 | ||
|
|
15bcb941de | ||
|
|
5d9542113a | ||
|
|
0fb1b4e09c | ||
|
|
1e02914267 | ||
|
|
6db1062768 | ||
|
|
adf6d7e08d | ||
|
|
c492e5fd73 | ||
|
|
7ed5b1c116 | ||
|
|
53d3f9cdde | ||
|
|
edccce8563 | ||
|
|
a87fded4cf | ||
|
|
fdae025495 | ||
|
|
fa6061c623 | ||
|
|
8ab921d5b4 | ||
|
|
723331f814 | ||
|
|
71630e80e4 | ||
|
|
5646c6a7a8 | ||
|
|
582229e17c | ||
|
|
7e2a55aa07 | ||
|
|
b05fb07d77 | ||
|
|
7e60538469 | ||
|
|
9f59648c26 | ||
|
|
13b2787173 | ||
|
|
6c635fe75a | ||
|
|
6d5ded3c7d | ||
|
|
cbb68060c6 | ||
|
|
0fba875c72 | ||
|
|
98899881e7 | ||
|
|
8fd41702c6 | ||
|
|
34d174e315 | ||
|
|
3265d3fcd4 | ||
|
|
7d42ae3c9a | ||
|
|
e6fcf24f89 | ||
|
|
16d8ba09fb | ||
|
|
7223aec001 | ||
|
|
0ec2fff5bf | ||
|
|
78bbd99f0d | ||
|
|
b4c73f4888 | ||
|
|
677dc46eeb | ||
|
|
fbb7cb442c | ||
|
|
909331ac51 | ||
|
|
785e3213d5 | ||
|
|
fad6cc2e1b | ||
|
|
9a0c857131 | ||
|
|
bac1e69164 | ||
|
|
8e9c180278 | ||
|
|
3859c66f0e | ||
|
|
9a5176e430 | ||
|
|
95cfb076d1 | ||
|
|
9043224bb2 | ||
|
|
01db4a6f99 | ||
|
|
035e905a3e | ||
|
|
b2ed2d6f6d | ||
|
|
fbef18f58b | ||
|
|
4f866f2a9a | ||
|
|
af93126e05 | ||
|
|
5bda007763 | ||
|
|
f70868ce22 | ||
|
|
6e44341d67 | ||
|
|
3788da41cd | ||
|
|
57c1cb9ffa | ||
|
|
85b8f10778 | ||
|
|
0a35055aa0 | ||
|
|
3ef6a15741 | ||
|
|
d190e73ad3 | ||
|
|
79d30931c3 | ||
|
|
56f103953d | ||
|
|
be7be4c1cc | ||
|
|
5553ecfd88 | ||
|
|
ab9ffb7558 | ||
|
|
c181965682 |
34
.github/dist/export_presets.cfg
vendored
34
.github/dist/export_presets.cfg
vendored
@@ -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)
|
||||||
|
|||||||
46
.github/dist/footer.html
vendored
46
.github/dist/footer.html
vendored
@@ -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>
|
||||||
|
|||||||
22
.github/dist/header.html
vendored
22
.github/dist/header.html
vendored
@@ -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>
|
||||||
|
|||||||
100
.github/workflows/export_html5.yml.disabled
vendored
100
.github/workflows/export_html5.yml.disabled
vendored
@@ -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
|
|
||||||
4
.github/workflows/static_checks.yml
vendored
4
.github/workflows/static_checks.yml
vendored
@@ -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
3
.gitignore
vendored
@@ -21,3 +21,6 @@ mono_crash.*.json
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
*~
|
*~
|
||||||
*.blend1
|
*.blend1
|
||||||
|
|
||||||
|
# Jetbrains IDE files
|
||||||
|
.idea/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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" )
|
|
||||||
@@ -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"
|
||||||
@@ -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
|
||||||
@@ -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"]
|
||||||
@@ -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():
|
||||||
@@ -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"]
|
||||||
@@ -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.
|
||||||
@@ -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"]
|
||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Binary file not shown.
@@ -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" ]
|
|
||||||
|
|
||||||
@@ -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" ]
|
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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?
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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.
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
15
2d/navigation_mesh_chunks/README.md
Normal file
15
2d/navigation_mesh_chunks/README.md
Normal 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
|
||||||
|
|
||||||
|

|
||||||
BIN
2d/navigation_mesh_chunks/icon.webp
Normal file
BIN
2d/navigation_mesh_chunks/icon.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
156
2d/navigation_mesh_chunks/navmesh_chhunks_demo_2d.gd
Normal file
156
2d/navigation_mesh_chunks/navmesh_chhunks_demo_2d.gd
Normal 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()
|
||||||
99
2d/navigation_mesh_chunks/navmesh_chhunks_demo_2d.tscn
Normal file
99
2d/navigation_mesh_chunks/navmesh_chhunks_demo_2d.tscn
Normal 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
|
||||||
29
2d/navigation_mesh_chunks/project.godot
Normal file
29
2d/navigation_mesh_chunks/project.godot
Normal 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"
|
||||||
0
2d/navigation_mesh_chunks/screenshots/.gdignore
Normal file
0
2d/navigation_mesh_chunks/screenshots/.gdignore
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -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
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user