mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2024-11-18 09:07:18 +01:00
parent
38baf344a8
commit
ca1a7088c5
35
CHANGELOG.md
35
CHANGELOG.md
@ -1,29 +1,32 @@
|
||||
# Changelog #
|
||||
# Changelog
|
||||
|
||||
This document lists new features, improvements, changes, and bug fixes in every release of the add-on.
|
||||
|
||||
## Master ##
|
||||
## Master
|
||||
|
||||
### Changes ###
|
||||
## Godot Steering AI Framework 3.0.0
|
||||
|
||||
### Changes
|
||||
|
||||
- The structure of the project has been overhauled in order to make it possible to import as an add-on in Godot directly.
|
||||
- Acceleration for agents are now multiplied by delta in order to make acceleration be per second instead of instant. The demos' values have been increased significantly to better fit with reality.
|
||||
|
||||
### Fixes
|
||||
|
||||
- KinematicBody2DAgents and KinematicBody3DAgents that moved fast enough no longer reverse velocity suddenly during a frame where no acceleration is applied.
|
||||
- RigidBody2DAgent should no longer crash due to a missing reference.
|
||||
- Specialized Agents like RigidBody2DAgent should no longer crash due to a missing reference.
|
||||
|
||||
## Godot Steering AI Framework 2.1.0 ##
|
||||
## Godot Steering AI Framework 2.1.0
|
||||
|
||||
### Features ###
|
||||
### Features
|
||||
|
||||
- There is now an `Arrive3d` demo to showcase 3D movement.
|
||||
|
||||
### Improvements ###
|
||||
### Improvements
|
||||
|
||||
- All the demos got a bit of attention to improve their feel.
|
||||
|
||||
### Changes ###
|
||||
### Changes
|
||||
|
||||
- `GSAIUtils.vector3_to_angle` now uses the vector's X and Z components to determine angle. Use `GSAIUtils.vector2_to_angle` for 2D use cases.
|
||||
- `GSAIMatchOrientation` and its subclasses like `GSAIFace` and `GSAILookWhereYouGo` now include a `use_z` property. It should be `true` when using 3D so that facing will be done with the X and Z components.
|
||||
@ -31,7 +34,7 @@ This document lists new features, improvements, changes, and bug fixes in every
|
||||
- Exposed `agent_count` inside the `AvoidCollisionsDemo`.
|
||||
- Unused and undocumented variable `_body_type` has been removed from `SpecializedAgent`
|
||||
|
||||
### Bug fixes ###
|
||||
### Bug fixes
|
||||
|
||||
- Fixed `GSAIKinematicBody3DAgent` and `GSAIRigidBody3DAgent` trying to use `global_position` instead of `transform.origin`.
|
||||
- The `SeekFleeDemo`'s boundaries will now match the size of the screen.
|
||||
@ -40,7 +43,7 @@ This document lists new features, improvements, changes, and bug fixes in every
|
||||
- The specialized agents now use WeakRef internally to prevent crashes when their `body` is freed.
|
||||
- `RigidBody2DAgent` now properly connects to physics updates.
|
||||
|
||||
## Godot Steering AI Framework 2.0.0 ##
|
||||
## Godot Steering AI Framework 2.0.0
|
||||
|
||||
This release brings one new feature and bug fix, and breaking changes to the framework as we renamed all the classes.
|
||||
|
||||
@ -50,16 +53,16 @@ If you were using `GSTKinematicBodyAgent` or `GSTRigidBodyAgent`, search and rep
|
||||
|
||||
We decided to make this change as soon as possible, as the framework was released a few days ago.
|
||||
|
||||
### Features ###
|
||||
### Features
|
||||
|
||||
- There is now a main scene with a demo picker, so you can select and play any demo on the fly.
|
||||
- The demo projects now support resizing and toggling fullscreen with <kbd>F11</kbd>.
|
||||
|
||||
### Improvements ###
|
||||
### Improvements
|
||||
|
||||
- We handled all warnings in the framework, so using it won't add warnings to your projects.
|
||||
|
||||
### Changes ###
|
||||
### Changes
|
||||
|
||||
- Renamed all classes from `GST*` (Godot Steering Toolkit) to `GSAI*` (Godot Steering AI).
|
||||
- Removed `GSTNode2DAgent`, `GSTNodeAgent`, and `GSTSpatialAgent` classes.
|
||||
@ -68,11 +71,11 @@ We decided to make this change as soon as possible, as the framework was release
|
||||
- Renamed `GSAIRigidBodyAgent` and `GSAIRigidBodyAgent` to `GSAIRigidBody3DAgent` and `GSAIRigidBody3DAgent` respectively.
|
||||
- 3D nodes like `Sprite`, `KinematicBody`, etc. are being renamed to `Sprite3D`, `KinematicBody3D`, etc. in the upcoming Godot 4.0 release, to be consistent with 2D nodes. We decided to rename them now instead of breaking compatibility in a future release.
|
||||
|
||||
### Bug fixes ###
|
||||
### Bug fixes
|
||||
|
||||
- GSTFollowPath no longer loops back around itself on open paths when `predict_time` is non-zero.
|
||||
|
||||
## Godot Steering AI Framework 1.0.0 ##
|
||||
## Godot Steering AI Framework 1.0.0
|
||||
|
||||
This is the first major release of the framework. It comes with:
|
||||
|
||||
@ -84,7 +87,7 @@ This is the first major release of the framework. It comes with:
|
||||
- For 3D games, `KinematicBody3DAgent` and `RigidBody3DAgent`.
|
||||
- 9 Godot demos to learn straight from the code.
|
||||
|
||||
### Manual ###
|
||||
### Manual
|
||||
|
||||
To get started, check out the framework's [manual](https://www.gdquest.com/docs/godot-steering-toolkit/).
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/icon.png"
|
||||
dest_files=[ "res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
@ -1,151 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:version="1.1-dev (83f2ee46ff, 2020-02-13)"
|
||||
id="svg1340"
|
||||
version="1.1"
|
||||
viewBox="0 0 16.933333 16.933334"
|
||||
height="64"
|
||||
width="64">
|
||||
<defs
|
||||
id="defs1334">
|
||||
<clipPath
|
||||
id="clipPath1560"
|
||||
clipPathUnits="userSpaceOnUse">
|
||||
<rect
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#293252;fill-opacity:1;stroke:none;stroke-width:1.40425;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;stop-color:#000000;stop-opacity:1"
|
||||
id="rect1562"
|
||||
width="16.933332"
|
||||
height="16.933332"
|
||||
x="0"
|
||||
y="9.6346028e-08" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
inkscape:snap-global="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="1043"
|
||||
inkscape:window-width="1920"
|
||||
units="px"
|
||||
showgrid="false"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:cy="31.438019"
|
||||
inkscape:cx="15.072392"
|
||||
inkscape:zoom="8"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base" />
|
||||
<metadata
|
||||
id="metadata1337">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
y="0"
|
||||
x="0"
|
||||
height="16.933332"
|
||||
width="16.933332"
|
||||
id="rect1504"
|
||||
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#293252;fill-opacity:1;stroke:none;stroke-width:1.40425;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0;stop-color:#000000;stop-opacity:1" />
|
||||
<path
|
||||
clip-path="url(#clipPath1560)"
|
||||
id="path2490"
|
||||
d="M 2.8526138,-0.0226856 2.9507848,1.274306 C 2.5771927,1.4791664 2.2289224,1.7185349 1.9075218,1.988743 L 0.29690799,1.3221671 -0.40866643,2.1624613 0.56110833,3.5585158 C 0.33791661,3.9257554 0.15316113,4.3166174 0.00975169,4.7250204 l -0.7432386,0.090259 -0.009472,1.7228785 0.40521717,0.191826 c 0,0.2151562 0.0190602,0.4320655 0.0310875,0.6505844 0.0205584,0.2185642 0.0528327,0.4331209 0.0974454,0.6435666 l -0.54416748,0.401985 -0.008756,1.5907221 1.2930922,-0.090536 C 0.75306491,10.299542 1.0115466,10.64731 1.3029499,10.96517 l -0.672761,1.553839 0.858959,0.689584 1.4456413,-0.959917 c 0.3687832,0.203771 0.7600417,0.372343 1.1673979,0.502553 l 0.2153945,1.714295 1.0964166,0.176342 0.7818497,-1.5822 c 0.2037711,0 0.4094501,-0.01685 0.6159876,-0.03895 H 6.812698 L 9.8042599,12.732617 9.3779282,8.4823903 6.3854715,8.7696026 6.5157868,10.092058 C 4.6330774,10.272636 2.9585336,8.9258916 2.7734622,7.0836627 2.5888891,5.2418454 3.9644158,3.6030022 5.8465387,3.4220125 L 8.8381053,3.1348571 8.5438181,0.20619376 5.5531989,0.49334922 C 5.3459823,0.51050176 5.1420605,0.5378074 4.9415586,0.57229759 L 4.4901554,-0.01349219 Z M 10.360111,2.7244603 9.577372,4.3066562 c -0.2035882,0 -0.4084223,0.016659 -0.6150947,0.038946 L 5.969764,4.633705 6.2641051,7.5605285 9.2556723,7.273373 a 3.4244787,3.3513826 0 0 1 3.7431617,3.007448 3.4244787,3.3513826 0 0 1 -3.0739683,3.662595 l -2.9915662,0.28894 0.2652052,2.646411 2.7965066,0.01566 0.2241417,-0.0215 c 0.206675,-0.01714 0.41087,-0.0444 0.610692,-0.07889 l 0.0814,0.105523 1.973596,0.01109 -0.06151,-0.818622 c 0.373232,-0.204827 0.723028,-0.444409 1.044158,-0.714444 l 1.609666,0.667466 0.705575,-0.840294 -0.968773,-1.396053 c 0.222649,-0.367242 0.407573,-0.758822 0.551301,-1.167399 l 1.699205,-0.205645 0.181684,-1.073405 -1.533445,-0.725078 c 0.01889,-0.214756 -0.01899,-0.432247 -0.03098,-0.6505829 -0.02061,-0.2185654 -0.05301,-0.4339146 -0.09935,-0.6444001 L 17.342103,8.3379231 16.950314,7.3203422 15.242313,7.4418002 C 15.020345,7.0685674 14.760954,6.7200461 14.469323,6.4020456 L 15.142137,4.8490976 14.284072,4.1595128 12.836646,5.1194284 C 12.467685,4.9156577 12.078251,4.7477386 11.671033,4.6177136 L 11.454747,2.9034731 Z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#2f395f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.17682;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
style="stroke-width:1.24672"
|
||||
transform="matrix(0.18285727,0,0,0.14154908,150.31973,-187.36868)"
|
||||
id="g2450">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:1;vector-effect:none;fill:#5e315b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
d="m -822.06042,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
id="path2430" />
|
||||
<path
|
||||
id="path2432"
|
||||
d="m -812.80001,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
style="opacity:1;vector-effect:none;fill:#8c3f5d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:1;vector-effect:none;fill:#ba6156;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
d="m -803.5396,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
id="path2434" />
|
||||
<path
|
||||
id="path2436"
|
||||
d="m -794.27919,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
style="opacity:1;vector-effect:none;fill:#f2a65e;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:1;vector-effect:none;fill:#ffe478;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
d="m -785.01878,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
id="path2438" />
|
||||
<path
|
||||
id="path2440"
|
||||
d="m -775.75837,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
style="opacity:1;vector-effect:none;fill:#cfff70;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:1;vector-effect:none;fill:#8fde5d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
d="m -766.49796,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
id="path2442" />
|
||||
<path
|
||||
id="path2444"
|
||||
d="m -757.23755,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
style="opacity:1;vector-effect:none;fill:#3ca370;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:1;vector-effect:none;fill:#3d6e70;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
d="m -747.97714,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
id="path2446" />
|
||||
<path
|
||||
id="path2448"
|
||||
d="m -738.71673,1434.5708 h 9.26041 v 9.2604 h -9.26041 z"
|
||||
style="opacity:1;vector-effect:none;fill:#323e4f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.989584;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.97917, 1.97917;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
d="M 1.7415414,13.864431 C 2.8091455,12.301646 3.8954985,10.918152 4.8840406,10.004274 M 12.44693,3.6341761 c 0,0 1.658558,-1.2568206 2.909891,-2.065662"
|
||||
style="fill:none;stroke:#a0a9ce;stroke-width:1.087;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:1.6;stroke-dasharray:2.174, 2.174;stroke-dashoffset:1.087;stroke-opacity:1"
|
||||
id="path2283"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2351"
|
||||
d="M 4.6789148,3.8638581 6.5936823,6.200326 4.9999674,7.512026 7.0448877,10.007103 8.6388709,8.6952013 10.553866,11.032019 11.16251,4.529541 Z"
|
||||
style="vector-effect:none;fill:#293252;fill-opacity:1;fill-rule:nonzero;stroke:#7786bb;stroke-width:0.827338;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 11 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/icon.svg"
|
||||
dest_files=[ "res://.import/icon.svg-56083ea2a1f1a4f1e49773bdc6d7826c.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/background.png-dde469fb1f19281f3784b52d4bea96cd.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/sprites/background.png"
|
||||
dest_files=[ "res://.import/background.png-dde469fb1f19281f3784b52d4bea96cd.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,8 +0,0 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/theme/fonts/montserrat/Montserrat-Medium.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
size = 26
|
||||
use_filter = true
|
||||
font_data = ExtResource( 1 )
|
@ -1,8 +0,0 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/theme/fonts/montserrat/Montserrat-Bold.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
size = 26
|
||||
use_filter = true
|
||||
font_data = ExtResource( 1 )
|
@ -1,8 +0,0 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/theme/fonts/source_code_pro/SourceCodePro-Medium.otf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
size = 26
|
||||
use_filter = true
|
||||
font_data = ExtResource( 1 )
|
@ -1,8 +0,0 @@
|
||||
[gd_resource type="DynamicFont" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/theme/fonts/montserrat/Montserrat-Black.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
size = 34
|
||||
use_filter = true
|
||||
font_data = ExtResource( 1 )
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
Before Width: | Height: | Size: 270 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/chevron-right.svg-f77dee7a088177a2ac1d467f4c7cd3e1.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/theme/icons/chevron-right.svg"
|
||||
dest_files=[ "res://.import/chevron-right.svg-f77dee7a088177a2ac1d467f4c7cd3e1.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-up"><polyline points="18 15 12 9 6 15"></polyline></svg>
|
Before Width: | Height: | Size: 268 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/chevron-up.svg-48b5b69265734774d0a7516dcc6f0863.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/theme/icons/chevron-up.svg"
|
||||
dest_files=[ "res://.import/chevron-up.svg-48b5b69265734774d0a7516dcc6f0863.stex" ]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_mode=0
|
||||
compress/bptc_ldr=0
|
||||
compress/normal_map=0
|
||||
flags/repeat=0
|
||||
flags/filter=true
|
||||
flags/mipmaps=false
|
||||
flags/anisotropic=false
|
||||
flags/srgb=2
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/HDR_as_SRGB=false
|
||||
process/invert_color=false
|
||||
stream=false
|
||||
size_limit=0
|
||||
detect_3d=true
|
||||
svg/scale=1.0
|
Binary file not shown.
@ -1,5 +0,0 @@
|
||||
[gd_resource type="StyleBoxLine" format=2]
|
||||
|
||||
[resource]
|
||||
color = Color( 1, 1, 1, 0.196078 )
|
||||
thickness = 2
|
Binary file not shown.
Binary file not shown.
@ -1,7 +0,0 @@
|
||||
[gd_resource type="Environment" load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="ProceduralSky" id=1]
|
||||
|
||||
[resource]
|
||||
background_mode = 2
|
||||
background_sky = SubResource( 1 )
|
@ -1,51 +0,0 @@
|
||||
extends Node
|
||||
|
||||
export (float, 0, 3200, 100) var linear_speed_max := 800.0 setget set_linear_speed_max
|
||||
export (float, 0, 10000, 100) var linear_acceleration_max := 80.0 setget set_linear_acceleration_max
|
||||
export (float, 0, 100, 0.1) var arrival_tolerance := 25.0 setget set_arrival_tolerance
|
||||
export (float, 0, 500, 10) var deceleration_radius := 125.0 setget set_deceleration_radius
|
||||
|
||||
onready var arriver := $Arriver
|
||||
onready var target_drawer := $TargetDrawer
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
arriver.setup(linear_speed_max, linear_acceleration_max, arrival_tolerance, deceleration_radius)
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.is_pressed():
|
||||
arriver.target.position = Vector3(event.position.x, event.position.y, 0)
|
||||
target_drawer.update()
|
||||
|
||||
|
||||
func set_arrival_tolerance(value: float) -> void:
|
||||
arrival_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.arrive.arrival_tolerance = value
|
||||
|
||||
|
||||
func set_deceleration_radius(value: float) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.arrive.deceleration_radius = value
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
linear_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.agent.linear_speed_max = value
|
||||
|
||||
|
||||
func set_linear_acceleration_max(value: float) -> void:
|
||||
linear_acceleration_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.agent.linear_acceleration_max = value
|
@ -1,39 +0,0 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://demos/Arrive/Arriver.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://demos/Arrive/ArriveDemo.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://demos/Arrive/TargetDrawer.gd" type="Script" id=5]
|
||||
[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=6]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 23.2163
|
||||
|
||||
[node name="ArriveDemo" type="Node"]
|
||||
script = ExtResource( 3 )
|
||||
linear_speed_max = 1600.0
|
||||
linear_acceleration_max = 5000.0
|
||||
arrival_tolerance = 35.0
|
||||
deceleration_radius = 180.0
|
||||
|
||||
[node name="BackgroudLayer" parent="." instance=ExtResource( 4 )]
|
||||
|
||||
[node name="TargetDrawer" type="Node2D" parent="."]
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="Arriver" type="KinematicBody2D" parent="."]
|
||||
show_behind_parent = true
|
||||
position = Vector2( 960, 540 )
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Arriver"]
|
||||
shape = SubResource( 1 )
|
||||
script = ExtResource( 6 )
|
||||
inner_color = Color( 0.235294, 0.639216, 0.439216, 1 )
|
||||
outer_color = Color( 0.560784, 0.870588, 0.364706, 1 )
|
||||
stroke = 6.0
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 2 )]
|
||||
text_bbcode = "Arrive Demo
|
||||
Mouse click to make the [color=lime]green \"Player\"[/color] move to the [color=fuchsia]purple target[/color]"
|
@ -1,28 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var agent := GSAIKinematicBody2DAgent.new(self)
|
||||
var target := GSAIAgentLocation.new()
|
||||
var arrive := GSAIArrive.new(agent, target)
|
||||
var _accel := GSAITargetAcceleration.new()
|
||||
|
||||
var _velocity := Vector2()
|
||||
var _drag := 0.1
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
arrive.calculate_steering(_accel)
|
||||
agent._apply_steering(_accel, delta)
|
||||
|
||||
|
||||
func setup(
|
||||
linear_speed_max: float,
|
||||
linear_acceleration_max: float,
|
||||
arrival_tolerance: float,
|
||||
deceleration_radius: float
|
||||
) -> void:
|
||||
agent.linear_speed_max = linear_speed_max
|
||||
agent.linear_acceleration_max = linear_acceleration_max
|
||||
agent.linear_drag_percentage = _drag
|
||||
arrive.deceleration_radius = deceleration_radius
|
||||
arrive.arrival_tolerance = arrival_tolerance
|
||||
target.position = agent.position
|
@ -1,19 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
const COLORS := {
|
||||
deceleration_radius = Color(1.0, 0.419, 0.592, 0.5),
|
||||
arrival_tolerance = Color(0.278, 0.231, 0.47, 0.3)
|
||||
}
|
||||
|
||||
var arriver: Node2D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
yield(owner, "ready")
|
||||
arriver = owner.arriver
|
||||
|
||||
|
||||
func _draw():
|
||||
var target_position := GSAIUtils.to_vector2(arriver.target.position)
|
||||
draw_circle(target_position, owner.deceleration_radius, COLORS.deceleration_radius)
|
||||
draw_circle(target_position, owner.arrival_tolerance, COLORS.arrival_tolerance)
|
@ -1,96 +0,0 @@
|
||||
[gd_scene load_steps=14 format=2]
|
||||
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://demos/Arrive3d/Camera.gd" type="Script" id=2]
|
||||
[ext_resource path="res://demos/Arrive3d/Seek3dDemo.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/Arrive3d/Seeker.gd" type="Script" id=4]
|
||||
[ext_resource path="res://demos/Arrive3d/SeekerMat.tres" type="Material" id=5]
|
||||
|
||||
[sub_resource type="CapsuleShape" id=1]
|
||||
|
||||
[sub_resource type="CapsuleMesh" id=2]
|
||||
|
||||
[sub_resource type="CubeMesh" id=3]
|
||||
material = ExtResource( 5 )
|
||||
size = Vector3( 0.5, 0.5, 1 )
|
||||
|
||||
[sub_resource type="CylinderMesh" id=4]
|
||||
top_radius = 2.0
|
||||
bottom_radius = 2.0
|
||||
height = 0.1
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=5]
|
||||
albedo_color = Color( 0.945098, 0.85098, 0.0745098, 1 )
|
||||
|
||||
[sub_resource type="BoxShape" id=6]
|
||||
extents = Vector3( 1000, 0.1, 1000 )
|
||||
|
||||
[sub_resource type="PlaneMesh" id=7]
|
||||
size = Vector2( 250, 250 )
|
||||
|
||||
[sub_resource type="SpatialMaterial" id=8]
|
||||
albedo_color = Color( 0.0941176, 0.235294, 0.486275, 1 )
|
||||
|
||||
[node name="Arrive3dDemo" type="Node"]
|
||||
script = ExtResource( 3 )
|
||||
linear_speed_max = 50.0
|
||||
linear_acceleration_max = 53.2
|
||||
deceleration_radius = 10.8
|
||||
angular_speed_max = 550
|
||||
angular_accel_max = 910
|
||||
|
||||
[node name="Arriver" type="KinematicBody" parent="."]
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="Arriver"]
|
||||
transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 1.5, 0 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="Capsule" type="MeshInstance" parent="Arriver"]
|
||||
transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 1.5, 0 )
|
||||
mesh = SubResource( 2 )
|
||||
material/0 = ExtResource( 5 )
|
||||
|
||||
[node name="Nose" type="MeshInstance" parent="Arriver"]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 1.25 )
|
||||
mesh = SubResource( 3 )
|
||||
material/0 = null
|
||||
|
||||
[node name="Camera" type="Camera" parent="."]
|
||||
transform = Transform( 0.989952, 0.0720094, -0.121693, 0.0339305, 0.714503, 0.69881, 0.137271, -0.695917, 0.70488, -7.68317, 14.1265, 25.616 )
|
||||
current = true
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="RayCast" type="RayCast" parent="Camera"]
|
||||
enabled = true
|
||||
cast_to = Vector3( -627, 200, -777 )
|
||||
collision_mask = 2
|
||||
|
||||
[node name="MouseTarget" type="Spatial" parent="."]
|
||||
transform = Transform( 1, 0, 7.45058e-09, 0, 1, 0, 7.45058e-09, 0, 1, -4.76837e-07, 9.53674e-07, 1.90735e-06 )
|
||||
|
||||
[node name="MeshInstance" type="MeshInstance" parent="MouseTarget"]
|
||||
mesh = SubResource( 4 )
|
||||
material/0 = SubResource( 5 )
|
||||
|
||||
[node name="StaticBody" type="StaticBody" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.1, 0 )
|
||||
collision_layer = 2
|
||||
collision_mask = 2
|
||||
|
||||
[node name="CollisionShape" type="CollisionShape" parent="StaticBody"]
|
||||
shape = SubResource( 6 )
|
||||
|
||||
[node name="Ground" type="MeshInstance" parent="."]
|
||||
mesh = SubResource( 7 )
|
||||
material/0 = SubResource( 8 )
|
||||
|
||||
[node name="DirectionalLight" type="DirectionalLight" parent="."]
|
||||
transform = Transform( -0.588165, 0.462179, -0.663666, -0.804031, -0.245728, 0.541436, 0.087159, 0.852061, 0.516134, -17.6076, 12.1748, 0 )
|
||||
light_energy = 0.5
|
||||
shadow_enabled = true
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 1 )]
|
||||
mouse_filter = 2
|
||||
text_bbcode = "3D Arrive Demo
|
||||
Move the mouse about the field to have the agent turn towards and smoothly arrive at the target marker."
|
@ -1,24 +0,0 @@
|
||||
extends Camera
|
||||
|
||||
var target: Spatial
|
||||
|
||||
onready var ray := $RayCast
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseMotion:
|
||||
_set_target_position(event.position)
|
||||
|
||||
|
||||
func setup(_target: Spatial) -> void:
|
||||
self.target = _target
|
||||
_set_target_position(get_viewport().get_mouse_position())
|
||||
|
||||
|
||||
func _set_target_position(position: Vector2) -> void:
|
||||
var to = project_local_ray_normal(position) * 10000
|
||||
ray.cast_to = to
|
||||
ray.force_raycast_update()
|
||||
if ray.is_colliding():
|
||||
var point = ray.get_collision_point()
|
||||
target.transform.origin = point
|
@ -1,92 +0,0 @@
|
||||
extends Node
|
||||
|
||||
export (float, 0, 100, 5) var linear_speed_max := 10.0 setget set_linear_speed_max
|
||||
export (float, 0, 100, 0.1) var linear_acceleration_max := 1.0 setget set_linear_acceleration_max
|
||||
export (float, 0, 50, 0.1) var arrival_tolerance := 0.5 setget set_arrival_tolerance
|
||||
export (float, 0, 50, 0.1) var deceleration_radius := 5.0 setget set_deceleration_radius
|
||||
export (int, 0, 1080, 10) var angular_speed_max := 270 setget set_angular_speed_max
|
||||
export (int, 0, 2048, 10) var angular_accel_max := 45 setget set_angular_accel_max
|
||||
export (int, 0, 178, 2) var align_tolerance := 5 setget set_align_tolerance
|
||||
export (int, 0, 180, 2) var angular_deceleration_radius := 45 setget set_angular_deceleration_radius
|
||||
|
||||
onready var target := $MouseTarget
|
||||
onready var arriver := $Arriver
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
arriver.setup(
|
||||
deg2rad(align_tolerance),
|
||||
deg2rad(angular_deceleration_radius),
|
||||
deg2rad(angular_accel_max),
|
||||
deg2rad(angular_speed_max),
|
||||
deceleration_radius,
|
||||
arrival_tolerance,
|
||||
linear_acceleration_max,
|
||||
linear_speed_max,
|
||||
target
|
||||
)
|
||||
$Camera.setup(target)
|
||||
|
||||
|
||||
func set_align_tolerance(value: int) -> void:
|
||||
align_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.face.alignment_tolerance = deg2rad(value)
|
||||
|
||||
|
||||
func set_angular_deceleration_radius(value: int) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.face.deceleration_radius = deg2rad(value)
|
||||
|
||||
|
||||
func set_angular_accel_max(value: int) -> void:
|
||||
angular_accel_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.agent.angular_acceleration_max = deg2rad(value)
|
||||
|
||||
|
||||
func set_angular_speed_max(value: int) -> void:
|
||||
angular_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.agent.angular_speed_max = deg2rad(value)
|
||||
|
||||
|
||||
func set_arrival_tolerance(value: float) -> void:
|
||||
arrival_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.arrive.arrival_tolerance = value
|
||||
|
||||
|
||||
func set_deceleration_radius(value: float) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.arrive.deceleration_radius = value
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
linear_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.agent.linear_speed_max = value
|
||||
|
||||
|
||||
func set_linear_acceleration_max(value: float) -> void:
|
||||
linear_acceleration_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
arriver.agent.linear_acceleration_max = value
|
@ -1,47 +0,0 @@
|
||||
extends KinematicBody
|
||||
|
||||
var target_node: Spatial
|
||||
|
||||
onready var agent := GSAIKinematicBody3DAgent.new(self)
|
||||
onready var target := GSAIAgentLocation.new()
|
||||
onready var accel := GSAITargetAcceleration.new()
|
||||
onready var blend := GSAIBlend.new(agent)
|
||||
onready var face := GSAIFace.new(agent, target, true)
|
||||
onready var arrive := GSAIArrive.new(agent, target)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
target.position = target_node.transform.origin
|
||||
target.position.y = transform.origin.y
|
||||
blend.calculate_steering(accel)
|
||||
agent._apply_steering(accel, delta)
|
||||
|
||||
|
||||
func setup(
|
||||
align_tolerance: float,
|
||||
angular_deceleration_radius: float,
|
||||
angular_accel_max: float,
|
||||
angular_speed_max: float,
|
||||
deceleration_radius: float,
|
||||
arrival_tolerance: float,
|
||||
linear_acceleration_max: float,
|
||||
linear_speed_max: float,
|
||||
_target: Spatial
|
||||
) -> void:
|
||||
agent.linear_speed_max = linear_speed_max
|
||||
agent.linear_acceleration_max = linear_acceleration_max
|
||||
agent.linear_drag_percentage = 0.05
|
||||
agent.angular_acceleration_max = angular_accel_max
|
||||
agent.angular_speed_max = angular_speed_max
|
||||
agent.angular_drag_percentage = 0.1
|
||||
|
||||
arrive.arrival_tolerance = arrival_tolerance
|
||||
arrive.deceleration_radius = deceleration_radius
|
||||
|
||||
face.alignment_tolerance = align_tolerance
|
||||
face.deceleration_radius = angular_deceleration_radius
|
||||
|
||||
target_node = _target
|
||||
self.target.position = target_node.transform.origin
|
||||
blend.add(arrive, 1)
|
||||
blend.add(face, 1)
|
@ -1,4 +0,0 @@
|
||||
[gd_resource type="SpatialMaterial" format=2]
|
||||
|
||||
[resource]
|
||||
albedo_color = Color( 0.152941, 0.764706, 0.247059, 1 )
|
@ -1,40 +0,0 @@
|
||||
extends Node
|
||||
|
||||
export (float, 0, 1000, 40) var linear_speed_max := 350.0 setget set_linear_speed_max
|
||||
export (float, 0, 4000, 2) var linear_acceleration_max := 40.0 setget set_linear_accel_max
|
||||
export (float, 0, 500, 10) var proximity_radius := 140.0 setget set_proximity_radius
|
||||
export var draw_proximity := true setget set_draw_proximity
|
||||
|
||||
onready var spawner := $Spawner
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
linear_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_linear_speed_max(value)
|
||||
|
||||
|
||||
func set_linear_accel_max(value: float) -> void:
|
||||
linear_acceleration_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_linear_accel_max(value)
|
||||
|
||||
|
||||
func set_proximity_radius(value: float) -> void:
|
||||
proximity_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_proximity_radius(value)
|
||||
|
||||
|
||||
func set_draw_proximity(value: bool) -> void:
|
||||
draw_proximity = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_draw_proximity(value)
|
@ -1,26 +0,0 @@
|
||||
[gd_scene load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://demos/AvoidCollisions/Spawner.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/AvoidCollisions/AvoidCollisionsDemo.gd" type="Script" id=2]
|
||||
[ext_resource path="res://demos/AvoidCollisions/Avoider.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5]
|
||||
|
||||
[node name="AvoidCollisionsDemo" type="Node"]
|
||||
script = ExtResource( 2 )
|
||||
linear_speed_max = 520.0
|
||||
linear_acceleration_max = 2250.0
|
||||
proximity_radius = 100.0
|
||||
|
||||
[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )]
|
||||
|
||||
[node name="Spawner" type="Node2D" parent="."]
|
||||
script = ExtResource( 1 )
|
||||
avoider_template = ExtResource( 3 )
|
||||
inner_color = Color( 0.235294, 0.639216, 0.439216, 1 )
|
||||
outer_color = Color( 0.560784, 0.870588, 0.364706, 1 )
|
||||
agent_count = 80
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 4 )]
|
||||
text_bbcode = "Avoid Collisions Demo
|
||||
Watch each agent try to keep traveling in a particular direction, but prioritize avoiding collisions with other agents."
|
@ -1,91 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var draw_proximity: bool
|
||||
|
||||
var _boundary_right: float
|
||||
var _boundary_bottom: float
|
||||
var _radius: float
|
||||
var _accel := GSAITargetAcceleration.new()
|
||||
var _velocity := Vector2.ZERO
|
||||
var _direction := Vector2()
|
||||
var _drag := 0.1
|
||||
var _color := Color(0.4, 1.0, 0.89, 0.3)
|
||||
|
||||
onready var collision := $CollisionShape2D
|
||||
onready var agent := GSAIKinematicBody2DAgent.new(self)
|
||||
onready var proximity := GSAIRadiusProximity.new(agent, [], 140)
|
||||
onready var avoid := GSAIAvoidCollisions.new(agent, proximity)
|
||||
onready var target := GSAIAgentLocation.new()
|
||||
onready var seek := GSAISeek.new(agent, target)
|
||||
onready var priority := GSAIPriority.new(agent, 0.0001)
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
if draw_proximity:
|
||||
draw_circle(Vector2.ZERO, proximity.radius, _color)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
target.position.x = agent.position.x + _direction.x * _radius
|
||||
target.position.y = agent.position.y + _direction.y * _radius
|
||||
|
||||
priority.calculate_steering(_accel)
|
||||
agent._apply_steering(_accel, delta)
|
||||
|
||||
|
||||
func setup(
|
||||
linear_speed_max: float,
|
||||
linear_accel_max: float,
|
||||
proximity_radius: float,
|
||||
boundary_right: float,
|
||||
boundary_bottom: float,
|
||||
_draw_proximity: bool,
|
||||
rng: RandomNumberGenerator
|
||||
) -> void:
|
||||
rng.randomize()
|
||||
_direction = Vector2(rng.randf_range(-1, 1), rng.randf_range(-1, 1)).normalized()
|
||||
|
||||
agent.linear_speed_max = linear_speed_max
|
||||
agent.linear_acceleration_max = linear_accel_max
|
||||
|
||||
proximity.radius = proximity_radius
|
||||
_boundary_bottom = boundary_bottom
|
||||
_boundary_right = boundary_right
|
||||
|
||||
_radius = collision.shape.radius
|
||||
agent.bounding_radius = _radius
|
||||
|
||||
agent.linear_drag_percentage = _drag
|
||||
|
||||
self.draw_proximity = _draw_proximity
|
||||
|
||||
priority.add(avoid)
|
||||
priority.add(seek)
|
||||
|
||||
|
||||
func set_proximity_agents(agents: Array) -> void:
|
||||
proximity.agents = agents
|
||||
|
||||
|
||||
func set_random_nonoverlapping_position(others: Array, distance_from_boundary_min: float) -> void:
|
||||
var rng := RandomNumberGenerator.new()
|
||||
rng.randomize()
|
||||
var tries_max := max(100, others.size() * others.size())
|
||||
while tries_max > 0:
|
||||
tries_max -= 1
|
||||
global_position.x = rng.randf_range(
|
||||
distance_from_boundary_min, _boundary_right - distance_from_boundary_min
|
||||
)
|
||||
global_position.y = rng.randf_range(
|
||||
distance_from_boundary_min, _boundary_bottom - distance_from_boundary_min
|
||||
)
|
||||
var done := true
|
||||
for i in range(others.size()):
|
||||
var other: Node2D = others[i]
|
||||
if (
|
||||
other.global_position.distance_to(position)
|
||||
<= _radius * 2 + distance_from_boundary_min
|
||||
):
|
||||
done = false
|
||||
if done:
|
||||
break
|
@ -1,17 +0,0 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/AvoidCollisions/Avoider.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 21.3503
|
||||
|
||||
[node name="Avoider" type="KinematicBody2D"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
script = ExtResource( 1 )
|
||||
inner_color = Color( 0.890196, 0.411765, 0.337255, 1 )
|
||||
outer_color = Color( 1, 0.709804, 0.439216, 1 )
|
||||
stroke = 5.0
|
@ -1,66 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
export var avoider_template: PackedScene
|
||||
export var inner_color := Color()
|
||||
export var outer_color := Color()
|
||||
export var agent_count := 60
|
||||
|
||||
var boundaries: Vector2
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
boundaries = Vector2(
|
||||
ProjectSettings["display/window/size/width"], ProjectSettings["display/window/size/height"]
|
||||
)
|
||||
var rng := RandomNumberGenerator.new()
|
||||
var avoiders := []
|
||||
var avoider_agents := []
|
||||
for i in range(agent_count):
|
||||
var avoider := avoider_template.instance()
|
||||
add_child(avoider)
|
||||
avoider.setup(
|
||||
owner.linear_speed_max,
|
||||
owner.linear_acceleration_max,
|
||||
owner.proximity_radius,
|
||||
boundaries.x,
|
||||
boundaries.y,
|
||||
true if i == 0 and owner.draw_proximity else false,
|
||||
rng
|
||||
)
|
||||
avoider_agents.append(avoider.agent)
|
||||
avoider.set_random_nonoverlapping_position(avoiders, 16)
|
||||
if i == 0:
|
||||
avoider.collision.inner_color = inner_color
|
||||
avoider.collision.outer_color = outer_color
|
||||
avoiders.append(avoider)
|
||||
if i % 10 == 0:
|
||||
yield(get_tree(), "idle_frame")
|
||||
for child in get_children():
|
||||
child.set_proximity_agents(avoider_agents)
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
for child in get_children():
|
||||
child.global_position = child.global_position.posmodv(boundaries)
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.agent.linear_speed_max = value
|
||||
|
||||
|
||||
func set_linear_accel_max(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.agent.linear_acceleration_max = value
|
||||
|
||||
|
||||
func set_proximity_radius(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.proximity.radius = value
|
||||
get_child(0).update()
|
||||
|
||||
|
||||
func set_draw_proximity(value: bool) -> void:
|
||||
var child := get_child(0)
|
||||
child.draw_proximity = value
|
||||
child.update()
|
@ -1,28 +0,0 @@
|
||||
class_name DemoPickerUI
|
||||
extends Control
|
||||
|
||||
# warning-ignore:unused_signal
|
||||
signal demo_requested
|
||||
|
||||
var demo_path := "" setget set_demo_path
|
||||
|
||||
onready var list: ItemList = $VBoxContainer/ItemList
|
||||
onready var button: Button = $VBoxContainer/Button
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# warning-ignore:return_value_discarded
|
||||
list.connect("demo_selected", self, "set_demo_path")
|
||||
# warning-ignore:return_value_discarded
|
||||
list.connect("item_activated", self, "_on_ItemList_item_activated")
|
||||
# warning-ignore:return_value_discarded
|
||||
button.connect("pressed", self, "emit_signal", ["demo_requested"])
|
||||
demo_path = list.file_paths[0]
|
||||
|
||||
|
||||
func set_demo_path(value: String) -> void:
|
||||
demo_path = value
|
||||
|
||||
|
||||
func _on_ItemList_item_activated(_index: int) -> void:
|
||||
emit_signal("demo_requested")
|
@ -1,16 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
|
||||
func load_demo(scene_path: String) -> void:
|
||||
if not scene_path:
|
||||
return
|
||||
|
||||
var demo = load(scene_path)
|
||||
if demo:
|
||||
add_child(demo.instance())
|
||||
|
||||
|
||||
func unload() -> void:
|
||||
for node in get_children():
|
||||
call_deferred("remove_child", node)
|
||||
node.queue_free()
|
@ -1,84 +0,0 @@
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://demos/PopulateItemList.gd" type="Script" id=1]
|
||||
[ext_resource path="res://assets/theme/gdquest.theme" type="Theme" id=2]
|
||||
[ext_resource path="res://assets/sprites/background.png" type="Texture" id=3]
|
||||
[ext_resource path="res://demos/DemoPickerUI.gd" type="Script" id=4]
|
||||
[ext_resource path="res://demos/DemoPlayer.gd" type="Script" id=5]
|
||||
[ext_resource path="res://demos/Demos.gd" type="Script" id=6]
|
||||
|
||||
[node name="Demos" type="Node"]
|
||||
script = ExtResource( 6 )
|
||||
|
||||
[node name="DemoPlayer" type="Node2D" parent="."]
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="DemoPickerUI" type="Control" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
theme = ExtResource( 2 )
|
||||
script = ExtResource( 4 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="TextureRect" type="TextureRect" parent="DemoPickerUI"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
rect_min_size = Vector2( 1024, 600 )
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
texture = ExtResource( 3 )
|
||||
expand = true
|
||||
stretch_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="DemoPickerUI"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -341.0
|
||||
margin_top = -290.0
|
||||
margin_right = 341.0
|
||||
margin_bottom = 290.0
|
||||
rect_min_size = Vector2( 682, 0 )
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
alignment = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ItemList" type="ItemList" parent="DemoPickerUI/VBoxContainer"]
|
||||
margin_top = 231.0
|
||||
margin_right = 682.0
|
||||
margin_bottom = 240.0
|
||||
auto_height = true
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Button" type="Button" parent="DemoPickerUI/VBoxContainer"]
|
||||
margin_left = 201.0
|
||||
margin_top = 248.0
|
||||
margin_right = 481.0
|
||||
margin_bottom = 348.0
|
||||
rect_min_size = Vector2( 280, 100 )
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 13
|
||||
text = "Load scene"
|
||||
|
||||
[node name="ButtonGoBack" type="Button" parent="."]
|
||||
visible = false
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 48.0
|
||||
margin_top = -156.0
|
||||
margin_right = 328.0
|
||||
margin_bottom = -56.0
|
||||
rect_min_size = Vector2( 280, 100 )
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 13
|
||||
theme = ExtResource( 2 )
|
||||
text = "Go back"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
extends Node
|
||||
|
||||
onready var demo_picker: DemoPickerUI = $DemoPickerUI
|
||||
onready var demo_player := $DemoPlayer
|
||||
onready var button_go_back: Button = $ButtonGoBack
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# warning-ignore:return_value_discarded
|
||||
demo_picker.connect("demo_requested", self, "_on_DemoPickerUI_demo_requested")
|
||||
# warning-ignore:return_value_discarded
|
||||
button_go_back.connect("pressed", self, "_on_ButtonGoBack_pressed")
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("toggle_fullscreen"):
|
||||
OS.window_fullscreen = not OS.window_fullscreen
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
|
||||
func _on_DemoPickerUI_demo_requested() -> void:
|
||||
demo_player.load_demo(demo_picker.demo_path)
|
||||
demo_picker.hide()
|
||||
button_go_back.show()
|
||||
|
||||
|
||||
func _on_ButtonGoBack_pressed() -> void:
|
||||
demo_player.unload()
|
||||
button_go_back.hide()
|
||||
demo_picker.show()
|
@ -1,61 +0,0 @@
|
||||
extends Node
|
||||
|
||||
export (int, 0, 1080, 2) var angular_speed_max := 120 setget set_angular_speed_max
|
||||
export (int, 0, 2048, 2) var angular_accel_max := 10 setget set_angular_accel_max
|
||||
export (int, 0, 180, 2) var align_tolerance := 5 setget set_align_tolerance
|
||||
export (int, 0, 359, 2) var deceleration_radius := 45 setget set_deceleration_radius
|
||||
export (float, 0, 1000, 40) var player_speed := 600.0 setget set_player_speed
|
||||
|
||||
onready var player := $Player
|
||||
onready var turret := $Turret
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
player.speed = player_speed
|
||||
turret.setup(
|
||||
player.agent,
|
||||
deg2rad(align_tolerance),
|
||||
deg2rad(deceleration_radius),
|
||||
deg2rad(angular_accel_max),
|
||||
deg2rad(angular_speed_max)
|
||||
)
|
||||
|
||||
|
||||
func set_align_tolerance(value: int) -> void:
|
||||
align_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
turret.face.alignment_tolerance = deg2rad(value)
|
||||
|
||||
|
||||
func set_deceleration_radius(value: int) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
turret.face.deceleration_radius = deg2rad(value)
|
||||
|
||||
|
||||
func set_angular_accel_max(value: int) -> void:
|
||||
angular_accel_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
turret.agent.angular_acceleration_max = deg2rad(value)
|
||||
|
||||
|
||||
func set_angular_speed_max(value: int) -> void:
|
||||
angular_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
turret.agent.angular_speed_max = deg2rad(value)
|
||||
|
||||
|
||||
func set_player_speed(value: float) -> void:
|
||||
player_speed = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
player.speed = player_speed
|
@ -1,48 +0,0 @@
|
||||
[gd_scene load_steps=9 format=2]
|
||||
|
||||
[ext_resource path="res://demos/Face/Turret.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/Face/FaceDemo.gd" type="Script" id=2]
|
||||
[ext_resource path="res://demos/Face/Player.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5]
|
||||
[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=8]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 20.2633
|
||||
|
||||
[sub_resource type="CircleShape2D" id=2]
|
||||
radius = 37.1052
|
||||
|
||||
[node name="FaceDemo" type="Node"]
|
||||
script = ExtResource( 2 )
|
||||
angular_speed_max = 662
|
||||
angular_accel_max = 924
|
||||
deceleration_radius = 136
|
||||
|
||||
[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )]
|
||||
|
||||
[node name="Player" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 687.363, 351.005 )
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"]
|
||||
shape = SubResource( 1 )
|
||||
script = ExtResource( 8 )
|
||||
inner_color = Color( 0.235294, 0.639216, 0.439216, 1 )
|
||||
outer_color = Color( 0.560784, 0.870588, 0.364706, 1 )
|
||||
stroke = 6.0
|
||||
|
||||
[node name="Turret" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 984.348, 571.959 )
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Turret"]
|
||||
shape = SubResource( 2 )
|
||||
script = ExtResource( 8 )
|
||||
inner_color = Color( 0.890196, 0.411765, 0.337255, 1 )
|
||||
outer_color = Color( 1, 0.709804, 0.439216, 1 )
|
||||
stroke = 8.0
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 4 )]
|
||||
text_bbcode = "Face Demo
|
||||
Move the [color=lime]green player[/color] around with WASD and notice the [color=#ffb570]orange turret[/color] orient itself"
|
@ -1,18 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var speed: float
|
||||
|
||||
onready var agent := GSAIAgentLocation.new()
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
var movement := _get_movement()
|
||||
move_and_slide(movement * speed)
|
||||
agent.position = Vector3(global_position.x, global_position.y, 0)
|
||||
|
||||
|
||||
func _get_movement() -> Vector2:
|
||||
return Vector2(
|
||||
Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"),
|
||||
Input.get_action_strength("sf_down") - Input.get_action_strength("sf_up")
|
||||
)
|
@ -1,43 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var face: GSAIFace
|
||||
var agent := GSAIKinematicBody2DAgent.new(self)
|
||||
|
||||
var _accel := GSAITargetAcceleration.new()
|
||||
var _angular_drag := 0.1
|
||||
var _cannon: Rect2
|
||||
var _color: Color
|
||||
|
||||
onready var collision_shape := $CollisionShape2D
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var radius = collision_shape.shape.radius
|
||||
_cannon = Rect2(Vector2(-5, 0), Vector2(10, -radius * 2))
|
||||
_color = collision_shape.outer_color
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
face.calculate_steering(_accel)
|
||||
agent._apply_steering(_accel, delta)
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
draw_rect(_cannon, _color)
|
||||
|
||||
|
||||
func setup(
|
||||
player_agent: GSAIAgentLocation,
|
||||
align_tolerance: float,
|
||||
deceleration_radius: float,
|
||||
angular_accel_max: float,
|
||||
angular_speed_max: float
|
||||
) -> void:
|
||||
face = GSAIFace.new(agent, player_agent)
|
||||
|
||||
face.alignment_tolerance = align_tolerance
|
||||
face.deceleration_radius = deceleration_radius
|
||||
|
||||
agent.angular_acceleration_max = angular_accel_max
|
||||
agent.angular_speed_max = angular_speed_max
|
||||
agent.angular_drag_percentage = _angular_drag
|
@ -1,53 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
signal path_established(points)
|
||||
|
||||
var active_points := []
|
||||
var is_drawing := false
|
||||
var distance_threshold := 100.0
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseMotion:
|
||||
if is_drawing:
|
||||
active_points.append(event.position)
|
||||
update()
|
||||
elif event is InputEventMouseButton:
|
||||
if event.pressed and event.button_index == BUTTON_LEFT:
|
||||
active_points.clear()
|
||||
active_points.append(event.position)
|
||||
is_drawing = true
|
||||
update()
|
||||
elif not event.pressed:
|
||||
is_drawing = false
|
||||
if active_points.size() >= 2:
|
||||
_simplify()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
if is_drawing:
|
||||
for point in active_points:
|
||||
draw_circle(point, 2, Color.red)
|
||||
else:
|
||||
if active_points.size() > 0:
|
||||
draw_circle(active_points.front(), 2, Color.red)
|
||||
draw_circle(active_points.back(), 2, Color.yellow)
|
||||
draw_polyline(active_points, Color.skyblue, 1.0)
|
||||
|
||||
|
||||
func _simplify() -> void:
|
||||
var first: Vector2 = active_points.front()
|
||||
var last: Vector2 = active_points.back()
|
||||
var key := first
|
||||
var simplified_path := [first]
|
||||
for i in range(1, active_points.size()):
|
||||
var point: Vector2 = active_points[i]
|
||||
var distance := point.distance_to(key)
|
||||
if distance > distance_threshold:
|
||||
key = point
|
||||
simplified_path.append(key)
|
||||
active_points = simplified_path
|
||||
if active_points.back() != last:
|
||||
active_points.append(last)
|
||||
update()
|
||||
emit_signal("path_established", active_points)
|
@ -1,70 +0,0 @@
|
||||
extends Node
|
||||
|
||||
export (float, 0, 2000, 40) var linear_speed_max := 600.0 setget set_linear_speed_max
|
||||
export (float, 0, 9000, 10.0) var linear_acceleration_max := 40.0 setget set_linear_acceleration_max
|
||||
export (float, 0, 100, 0.1) var arrival_tolerance := 10.0 setget set_arrival_tolerance
|
||||
export (float, 0, 500, 10) var deceleration_radius := 100.0 setget set_deceleration_radius
|
||||
export (float, 0, 5, 0.1) var predict_time := 0.3 setget set_predict_time
|
||||
export (float, 0, 200, 10.0) var path_offset := 20.0 setget set_path_offset
|
||||
|
||||
onready var drawer := $Drawer
|
||||
onready var follower := $PathFollower
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
follower.setup(
|
||||
path_offset,
|
||||
predict_time,
|
||||
linear_acceleration_max,
|
||||
linear_speed_max,
|
||||
deceleration_radius,
|
||||
arrival_tolerance
|
||||
)
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
linear_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.agent.linear_speed_max = value
|
||||
|
||||
|
||||
func set_linear_acceleration_max(value: float) -> void:
|
||||
linear_acceleration_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.agent.linear_acceleration_max = value
|
||||
|
||||
|
||||
func set_arrival_tolerance(value: float) -> void:
|
||||
arrival_tolerance = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.arrival_tolerance = value
|
||||
|
||||
|
||||
func set_deceleration_radius(value: float) -> void:
|
||||
deceleration_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.deceleration_radius = value
|
||||
|
||||
|
||||
func set_predict_time(value: float) -> void:
|
||||
predict_time = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.prediction_time = value
|
||||
|
||||
|
||||
func set_path_offset(value: float) -> void:
|
||||
path_offset = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
follower.follow.path_offset = value
|
@ -1,37 +0,0 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://demos/FollowPath/Drawer.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://demos/FollowPath/PathFollower.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/FollowPath/FollowPathDemo.gd" type="Script" id=4]
|
||||
[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5]
|
||||
[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=6]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 24.1954
|
||||
|
||||
[node name="FollowPathDemo" type="Node"]
|
||||
script = ExtResource( 4 )
|
||||
linear_speed_max = 920.0
|
||||
linear_acceleration_max = 3740.0
|
||||
deceleration_radius = 200.0
|
||||
|
||||
[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )]
|
||||
|
||||
[node name="Drawer" type="Node2D" parent="."]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="PathFollower" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 960, 540 )
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="PathFollower"]
|
||||
shape = SubResource( 1 )
|
||||
script = ExtResource( 6 )
|
||||
inner_color = Color( 0.235294, 0.639216, 0.439216, 1 )
|
||||
outer_color = Color( 0.560784, 0.870588, 0.364706, 1 )
|
||||
stroke = 6.0
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 2 )]
|
||||
text_bbcode = "Follow Path Demo
|
||||
Use the mouse to draw a path on screen and watch the [color=lime]green \"Agent\"[/color] follow it to the end."
|
@ -1,49 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var _velocity := Vector2.ZERO
|
||||
var _accel := GSAITargetAcceleration.new()
|
||||
var _valid := false
|
||||
var _drag := 0.1
|
||||
|
||||
onready var agent := GSAIKinematicBody2DAgent.new(self)
|
||||
onready var path := GSAIPath.new(
|
||||
[
|
||||
Vector3(global_position.x, global_position.y, 0),
|
||||
Vector3(global_position.x, global_position.y, 0)
|
||||
],
|
||||
true
|
||||
)
|
||||
onready var follow := GSAIFollowPath.new(agent, path, 0, 0)
|
||||
|
||||
|
||||
func setup(
|
||||
path_offset: float,
|
||||
predict_time: float,
|
||||
accel_max: float,
|
||||
speed_max: float,
|
||||
decel_radius: float,
|
||||
arrival_tolerance: float
|
||||
) -> void:
|
||||
owner.drawer.connect("path_established", self, "_on_Drawer_path_established")
|
||||
follow.path_offset = path_offset
|
||||
follow.prediction_time = predict_time
|
||||
follow.deceleration_radius = decel_radius
|
||||
follow.arrival_tolerance = arrival_tolerance
|
||||
|
||||
agent.linear_acceleration_max = accel_max
|
||||
agent.linear_speed_max = speed_max
|
||||
agent.linear_drag_percentage = _drag
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if _valid:
|
||||
follow.calculate_steering(_accel)
|
||||
agent._apply_steering(_accel, delta)
|
||||
|
||||
|
||||
func _on_Drawer_path_established(points: Array) -> void:
|
||||
var positions := PoolVector3Array()
|
||||
for p in points:
|
||||
positions.append(Vector3(p.x, p.y, 0))
|
||||
path.create_path(positions)
|
||||
_valid = true
|
@ -1,79 +0,0 @@
|
||||
extends Node
|
||||
|
||||
onready var spawner := $Spawner
|
||||
|
||||
export (float, 0, 2000, 40.0) var linear_speed_max := 600.0 setget set_linear_speed_max
|
||||
export (float, 0, 9000, 2.0) var linear_accel_max := 40.0 setget set_linear_accel_max
|
||||
export (float, 0, 300, 2.0) var proximity_radius := 140.0 setget set_proximity_radius
|
||||
export (float, 0, 200000, 250) var separation_decay_coefficient := 2000.0 setget set_separation_decay_coef
|
||||
export (float, 0, 2, 0.1) var cohesion_strength := 0.1 setget set_cohesion_strength
|
||||
export (float, 0, 10, 0.2) var separation_strength := 1.5 setget set_separation_strength
|
||||
export var show_proximity_radius := true setget set_show_proximity_radius
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
spawner.setup(
|
||||
linear_speed_max,
|
||||
linear_accel_max,
|
||||
proximity_radius,
|
||||
separation_decay_coefficient,
|
||||
cohesion_strength,
|
||||
separation_strength,
|
||||
show_proximity_radius
|
||||
)
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
linear_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_linear_speed_max(value)
|
||||
|
||||
|
||||
func set_linear_accel_max(value: float) -> void:
|
||||
linear_accel_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_linear_accel_max(value)
|
||||
|
||||
|
||||
func set_proximity_radius(value: float) -> void:
|
||||
proximity_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_proximity_radius(value)
|
||||
|
||||
|
||||
func set_show_proximity_radius(value: bool) -> void:
|
||||
show_proximity_radius = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_show_proximity_radius(value)
|
||||
|
||||
|
||||
func set_separation_decay_coef(value: float) -> void:
|
||||
separation_decay_coefficient = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_separation_decay_coef(value)
|
||||
|
||||
|
||||
func set_cohesion_strength(value: float) -> void:
|
||||
cohesion_strength = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_cohesion_strength(value)
|
||||
|
||||
|
||||
func set_separation_strength(value: float) -> void:
|
||||
separation_strength = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
spawner.set_separation_strength(value)
|
@ -1,26 +0,0 @@
|
||||
[gd_scene load_steps=6 format=2]
|
||||
|
||||
[ext_resource path="res://demos/GroupBehaviors/Member.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://demos/GroupBehaviors/Spawner.gd" type="Script" id=2]
|
||||
[ext_resource path="res://demos/GroupBehaviors/GroupBehaviorsDemo.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=5]
|
||||
|
||||
[node name="GroupBehaviorsDemo" type="Node"]
|
||||
script = ExtResource( 3 )
|
||||
linear_accel_max = 4234.0
|
||||
proximity_radius = 158.0
|
||||
separation_decay_coefficient = 121500.0
|
||||
cohesion_strength = 0.2
|
||||
separation_strength = 8.8
|
||||
|
||||
[node name="BackgroudLayer" parent="." instance=ExtResource( 5 )]
|
||||
|
||||
[node name="Spawner" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 300 )
|
||||
script = ExtResource( 2 )
|
||||
member = ExtResource( 1 )
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 4 )]
|
||||
text_bbcode = "Group Behavior Demo
|
||||
Each of the \"Agents\" are both attempting to stay separated from each other but within reach of their nearest group's center of mass."
|
@ -1,52 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var separation: GSAISeparation
|
||||
var cohesion: GSAICohesion
|
||||
var proximity: GSAIRadiusProximity
|
||||
var agent := GSAIKinematicBody2DAgent.new(self)
|
||||
var blend := GSAIBlend.new(agent)
|
||||
var acceleration := GSAITargetAcceleration.new()
|
||||
var draw_proximity := false
|
||||
|
||||
var _color := Color.red
|
||||
var _velocity := Vector2()
|
||||
|
||||
onready var collision_shape := $CollisionShape2D
|
||||
|
||||
|
||||
func setup(
|
||||
linear_speed_max: float,
|
||||
linear_accel_max: float,
|
||||
proximity_radius: float,
|
||||
separation_decay_coefficient: float,
|
||||
cohesion_strength: float,
|
||||
separation_strength: float
|
||||
) -> void:
|
||||
_color = Color(rand_range(0.5, 1), rand_range(0.25, 1), rand_range(0, 1))
|
||||
collision_shape.inner_color = _color
|
||||
|
||||
agent.linear_acceleration_max = linear_accel_max
|
||||
agent.linear_speed_max = linear_speed_max
|
||||
agent.linear_drag_percentage = 0.1
|
||||
|
||||
proximity = GSAIRadiusProximity.new(agent, [], proximity_radius)
|
||||
separation = GSAISeparation.new(agent, proximity)
|
||||
separation.decay_coefficient = separation_decay_coefficient
|
||||
cohesion = GSAICohesion.new(agent, proximity)
|
||||
blend.add(separation, separation_strength)
|
||||
blend.add(cohesion, cohesion_strength)
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
if draw_proximity:
|
||||
draw_circle(Vector2.ZERO, proximity.radius, Color(0.4, 1.0, 0.89, 0.3))
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if blend:
|
||||
blend.calculate_steering(acceleration)
|
||||
agent._apply_steering(acceleration, delta)
|
||||
|
||||
|
||||
func set_neighbors(neighbor: Array) -> void:
|
||||
proximity.agents = neighbor
|
@ -1,16 +0,0 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://demos/GroupBehaviors/Member.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=3]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 16.0
|
||||
|
||||
[node name="Member" type="KinematicBody2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
script = ExtResource( 3 )
|
||||
outer_color = Color( 0.301961, 0.65098, 1, 1 )
|
||||
stroke = 4.0
|
@ -1,73 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
export var member: PackedScene
|
||||
|
||||
|
||||
func setup(
|
||||
linear_speed_max: float,
|
||||
linear_accel_max: float,
|
||||
proximity_radius: float,
|
||||
separation_decay_coefficient: float,
|
||||
cohesion_strength: float,
|
||||
separation_strength: float,
|
||||
show_proximity_radius: bool
|
||||
) -> void:
|
||||
var followers := []
|
||||
for i in range(19):
|
||||
var follower := member.instance()
|
||||
add_child(follower)
|
||||
follower.position += Vector2(rand_range(-60, 60), rand_range(-60, 60))
|
||||
followers.append(follower)
|
||||
follower.setup(
|
||||
linear_speed_max,
|
||||
linear_accel_max,
|
||||
proximity_radius,
|
||||
separation_decay_coefficient,
|
||||
cohesion_strength,
|
||||
separation_strength
|
||||
)
|
||||
if i == 0 and show_proximity_radius:
|
||||
follower.draw_proximity = true
|
||||
follower.update()
|
||||
var agents := []
|
||||
for i in followers:
|
||||
agents.append(i.agent)
|
||||
for i in followers:
|
||||
i.proximity.agents = agents
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.agent.linear_speed_max = value
|
||||
|
||||
|
||||
func set_linear_accel_max(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.agent.linear_acceleration_max = value
|
||||
|
||||
|
||||
func set_proximity_radius(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.proximity.radius = value
|
||||
if child == get_child(0):
|
||||
child.update()
|
||||
|
||||
|
||||
func set_show_proximity_radius(value: bool) -> void:
|
||||
get_child(0).draw_proximity = value
|
||||
get_child(0).update()
|
||||
|
||||
|
||||
func set_separation_decay_coef(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.separation.decay_coefficient = value
|
||||
|
||||
|
||||
func set_cohesion_strength(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.blend.get_behavior_at(1).weight = value
|
||||
|
||||
|
||||
func set_separation_strength(value: float) -> void:
|
||||
for child in get_children():
|
||||
child.blend.get_behavior_at(0).weight = value
|
@ -1,68 +0,0 @@
|
||||
extends ItemList
|
||||
|
||||
signal demo_selected(scene_path)
|
||||
|
||||
var file_paths := PoolStringArray()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# warning-ignore:return_value_discarded
|
||||
self.connect("item_selected", self, "_on_item_selected")
|
||||
|
||||
var this_directory: String = get_tree().current_scene.filename.rsplit("/", false, 1)[0]
|
||||
file_paths = _find_files(this_directory, ["*Demo.tscn"], true)
|
||||
populate(file_paths)
|
||||
select(0)
|
||||
|
||||
|
||||
func populate(demos: PoolStringArray) -> void:
|
||||
for path in demos:
|
||||
var demo_name: String = path.rsplit("/", true, 1)[-1]
|
||||
demo_name = demo_name.rsplit("Demo", true, 1)[0]
|
||||
demo_name = sentencify(demo_name)
|
||||
add_item(demo_name)
|
||||
|
||||
|
||||
func sentencify(line: String) -> String:
|
||||
var regex := RegEx.new()
|
||||
# warning-ignore:return_value_discarded
|
||||
regex.compile("[A-Z]")
|
||||
|
||||
line = line.split(".", true, 1)[0]
|
||||
line = regex.sub(line, " $0", true)
|
||||
return line
|
||||
|
||||
|
||||
func _find_files(
|
||||
dirpath := "", patterns := PoolStringArray(), is_recursive := false, do_skip_hidden := true
|
||||
) -> PoolStringArray:
|
||||
var paths := PoolStringArray()
|
||||
var directory := Directory.new()
|
||||
|
||||
if not directory.dir_exists(dirpath):
|
||||
printerr("The directory does not exist: %s" % dirpath)
|
||||
return paths
|
||||
if not directory.open(dirpath) == OK:
|
||||
printerr("Could not open the following dirpath: %s" % dirpath)
|
||||
return paths
|
||||
|
||||
# warning-ignore:return_value_discarded
|
||||
directory.list_dir_begin(true, do_skip_hidden)
|
||||
var file_name := directory.get_next()
|
||||
while file_name != "":
|
||||
if directory.current_is_dir() and is_recursive:
|
||||
var subdirectory := dirpath.plus_file(file_name)
|
||||
paths.append_array(_find_files(subdirectory, patterns, is_recursive))
|
||||
else:
|
||||
for pattern in patterns:
|
||||
if file_name.match(pattern):
|
||||
paths.append(dirpath.plus_file(file_name))
|
||||
file_name = directory.get_next()
|
||||
|
||||
directory.list_dir_end()
|
||||
return paths
|
||||
|
||||
|
||||
func _on_item_selected(index: int) -> void:
|
||||
var demo_path := file_paths[index]
|
||||
emit_signal("demo_selected", demo_path)
|
@ -1,15 +0,0 @@
|
||||
extends Node2D
|
||||
# Wraps the ships' positions around the world border.
|
||||
|
||||
var _world_bounds: Vector2
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_world_bounds = Vector2(
|
||||
ProjectSettings["display/window/size/width"], ProjectSettings["display/window/size/height"]
|
||||
)
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
for ship in get_children():
|
||||
ship.position = ship.position.posmodv(_world_bounds)
|
@ -1,96 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
# Controls the player ship's movements based on player input.
|
||||
|
||||
export var thruster_strength := 175.0
|
||||
export var side_thruster_strength := 10.0
|
||||
export var velocity_max := 300.0
|
||||
export var angular_velocity_max := 2.0
|
||||
export var angular_drag := 0.025
|
||||
export var linear_drag := 0.025
|
||||
|
||||
var _linear_velocity := Vector2()
|
||||
var _angular_velocity := 0.0
|
||||
|
||||
onready var agent := GSAISteeringAgent.new()
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var movement := _get_movement()
|
||||
_angular_velocity = _calculate_angular_velocity(
|
||||
movement.x,
|
||||
_angular_velocity,
|
||||
side_thruster_strength,
|
||||
angular_velocity_max,
|
||||
angular_drag,
|
||||
delta
|
||||
)
|
||||
rotation += _angular_velocity * delta
|
||||
|
||||
_linear_velocity = _calculate_linear_velocity(
|
||||
movement.y,
|
||||
_linear_velocity,
|
||||
Vector2.UP.rotated(rotation),
|
||||
linear_drag,
|
||||
thruster_strength,
|
||||
velocity_max,
|
||||
delta
|
||||
)
|
||||
|
||||
_linear_velocity = move_and_slide(_linear_velocity)
|
||||
_update_agent()
|
||||
|
||||
|
||||
func _calculate_angular_velocity(
|
||||
horizontal_movement: float,
|
||||
current_velocity: float,
|
||||
_thruster_strength: float,
|
||||
_velocity_max: float,
|
||||
ship_drag: float,
|
||||
delta: float
|
||||
) -> float:
|
||||
var velocity := clamp(
|
||||
current_velocity + _thruster_strength * horizontal_movement * delta,
|
||||
-_velocity_max,
|
||||
_velocity_max
|
||||
)
|
||||
|
||||
velocity = lerp(velocity, 0, ship_drag)
|
||||
|
||||
return velocity
|
||||
|
||||
|
||||
func _calculate_linear_velocity(
|
||||
vertical_movement: float,
|
||||
current_velocity: Vector2,
|
||||
facing_direction: Vector2,
|
||||
ship_drag_coefficient: float,
|
||||
strength: float,
|
||||
speed_max: float,
|
||||
delta: float
|
||||
) -> Vector2:
|
||||
var actual_strength := 0.0
|
||||
if vertical_movement > 0:
|
||||
actual_strength = strength
|
||||
elif vertical_movement < 0:
|
||||
actual_strength = -strength / 1.5
|
||||
|
||||
var velocity := current_velocity + facing_direction * actual_strength * delta
|
||||
velocity = velocity.linear_interpolate(Vector2.ZERO, ship_drag_coefficient)
|
||||
|
||||
return velocity.clamped(speed_max)
|
||||
|
||||
|
||||
func _get_movement() -> Vector2:
|
||||
return Vector2(
|
||||
Input.get_action_strength("sf_right") - Input.get_action_strength("sf_left"),
|
||||
Input.get_action_strength("sf_up") - Input.get_action_strength("sf_down")
|
||||
)
|
||||
|
||||
|
||||
func _update_agent() -> void:
|
||||
agent.position.x = global_position.x
|
||||
agent.position.y = global_position.y
|
||||
agent.linear_velocity.x = _linear_velocity.x
|
||||
agent.linear_velocity.y = _linear_velocity.y
|
||||
agent.angular_velocity = _angular_velocity
|
||||
agent.orientation = rotation
|
@ -1,39 +0,0 @@
|
||||
extends Node
|
||||
|
||||
export (float, 0, 2000, 40) var linear_speed_max := 120.0 setget set_linear_speed_max
|
||||
export (float, 0, 2000, 20) var linear_accel_max := 10.0 setget set_linear_accel_max
|
||||
export (float, 0, 5, 0.1) var predict_time := 1.0 setget set_predict_time
|
||||
|
||||
onready var pursuer := $BoundaryManager/Pursuer
|
||||
onready var seeker := $BoundaryManager/Seeker
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
pursuer.setup(predict_time, linear_speed_max, linear_accel_max)
|
||||
seeker.setup(predict_time, linear_speed_max, linear_accel_max)
|
||||
|
||||
|
||||
func set_linear_speed_max(value: float) -> void:
|
||||
linear_speed_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
pursuer.agent.linear_speed_max = value
|
||||
seeker.agent.linear_speed_max = value
|
||||
|
||||
|
||||
func set_linear_accel_max(value: float) -> void:
|
||||
linear_accel_max = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
pursuer.agent.linear_acceleration_max = value
|
||||
seeker.agent.linear_acceleration_max = value
|
||||
|
||||
|
||||
func set_predict_time(value: float) -> void:
|
||||
predict_time = value
|
||||
if not is_inside_tree():
|
||||
return
|
||||
|
||||
pursuer._behavior.predict_time_max = value
|
@ -1,92 +0,0 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://demos/PursueSeek/Pursuer.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/PursueSeek/Player.gd" type="Script" id=2]
|
||||
[ext_resource path="res://demos/PursueSeek/BoundaryManager.gd" type="Script" id=3]
|
||||
[ext_resource path="res://demos/PursueSeek/PursueAndSeekDemo.gd" type="Script" id=4]
|
||||
[ext_resource path="res://demos/Utils/DemoInterface.tscn" type="PackedScene" id=5]
|
||||
[ext_resource path="res://demos/Utils/Line2DDraw.gd" type="Script" id=6]
|
||||
[ext_resource path="res://demos/Utils/BackgroudLayer.tscn" type="PackedScene" id=7]
|
||||
|
||||
[node name="PursueVSSeekDemo" type="Node"]
|
||||
script = ExtResource( 4 )
|
||||
linear_speed_max = 1280.0
|
||||
linear_accel_max = 1040.0
|
||||
predict_time = 1.1
|
||||
|
||||
[node name="BackgroudLayer" parent="." instance=ExtResource( 7 )]
|
||||
|
||||
[node name="BoundaryManager" type="Node2D" parent="."]
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="Player" type="KinematicBody2D" parent="BoundaryManager"]
|
||||
position = Vector2( 307.552, 555.999 )
|
||||
rotation = 1.5708
|
||||
collision_mask = 2
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_group_": true
|
||||
}
|
||||
thruster_strength = 1000.0
|
||||
side_thruster_strength = 40.0
|
||||
velocity_max = 450.0
|
||||
angular_velocity_max = 3.0
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Player"]
|
||||
polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 )
|
||||
|
||||
[node name="Line2D" type="Line2D" parent="BoundaryManager/Player"]
|
||||
points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 )
|
||||
width = 8.0
|
||||
default_color = Color( 0.560784, 0.870588, 0.364706, 1 )
|
||||
joint_mode = 2
|
||||
antialiased = true
|
||||
script = ExtResource( 6 )
|
||||
inner_color = Color( 0.235294, 0.639216, 0.439216, 1 )
|
||||
|
||||
[node name="Pursuer" type="KinematicBody2D" parent="BoundaryManager"]
|
||||
position = Vector2( 1240.22, 866.784 )
|
||||
collision_layer = 2
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_group_": true
|
||||
}
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Pursuer"]
|
||||
polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 )
|
||||
|
||||
[node name="Line2D" type="Line2D" parent="BoundaryManager/Pursuer"]
|
||||
points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 )
|
||||
width = 8.0
|
||||
default_color = Color( 1, 0.709804, 0.439216, 1 )
|
||||
joint_mode = 2
|
||||
antialiased = true
|
||||
script = ExtResource( 6 )
|
||||
inner_color = Color( 0.890196, 0.411765, 0.337255, 1 )
|
||||
|
||||
[node name="Seeker" type="KinematicBody2D" parent="BoundaryManager"]
|
||||
position = Vector2( 1240.22, 280.108 )
|
||||
rotation = 3.14159
|
||||
collision_layer = 2
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_group_": true
|
||||
}
|
||||
use_seek = true
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="BoundaryManager/Seeker"]
|
||||
polygon = PoolVector2Array( 0, -32, -24, 32, 24, 32 )
|
||||
|
||||
[node name="Line2D" type="Line2D" parent="BoundaryManager/Seeker"]
|
||||
points = PoolVector2Array( 0, 32, 24, 32, 0, -32, -24, 32, 0, 32 )
|
||||
width = 8.0
|
||||
default_color = Color( 0.301961, 0.65098, 1, 1 )
|
||||
joint_mode = 2
|
||||
antialiased = true
|
||||
script = ExtResource( 6 )
|
||||
inner_color = Color( 0.294118, 0.356863, 0.670588, 1 )
|
||||
|
||||
[node name="DemoInterface" parent="." instance=ExtResource( 5 )]
|
||||
text_bbcode = "Pursue vs. Seek Demo
|
||||
Move the player around with WASD and notice the [color=#ffb570]orange Pursuer[/color] and the [color=aqua]blue Seeker[/color] follow
|
||||
the [color=lime]green \"Ship\"[/color] around"
|
@ -1,65 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
# Represents a ship that chases after the player.
|
||||
|
||||
export var use_seek: bool = false
|
||||
|
||||
var _blend: GSAIBlend
|
||||
|
||||
var _linear_drag_coefficient := 0.025
|
||||
var _angular_drag := 0.1
|
||||
var _direction_face := GSAIAgentLocation.new()
|
||||
|
||||
onready var agent := GSAIKinematicBody2DAgent.new(self)
|
||||
onready var accel := GSAITargetAcceleration.new()
|
||||
onready var player_agent: GSAISteeringAgent = owner.find_node("Player", true, false).agent
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
agent.calculate_velocities = false
|
||||
set_physics_process(false)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
_direction_face.position = agent.position + accel.linear.normalized()
|
||||
|
||||
_blend.calculate_steering(accel)
|
||||
|
||||
agent.angular_velocity = clamp(
|
||||
agent.angular_velocity + accel.angular * delta, -agent.angular_speed_max, agent.angular_speed_max
|
||||
)
|
||||
agent.angular_velocity = lerp(agent.angular_velocity, 0, _angular_drag)
|
||||
|
||||
rotation += agent.angular_velocity * delta
|
||||
|
||||
var linear_velocity := (
|
||||
GSAIUtils.to_vector2(agent.linear_velocity)
|
||||
+ (GSAIUtils.angle_to_vector2(rotation) * -agent.linear_acceleration_max * delta)
|
||||
)
|
||||
linear_velocity = linear_velocity.clamped(agent.linear_speed_max)
|
||||
linear_velocity = linear_velocity.linear_interpolate(Vector2.ZERO, _linear_drag_coefficient)
|
||||
|
||||
linear_velocity = move_and_slide(linear_velocity)
|
||||
agent.linear_velocity = GSAIUtils.to_vector3(linear_velocity)
|
||||
|
||||
|
||||
func setup(predict_time: float, linear_speed_max: float, linear_accel_max: float) -> void:
|
||||
var behavior: GSAISteeringBehavior
|
||||
if use_seek:
|
||||
behavior = GSAISeek.new(agent, player_agent)
|
||||
else:
|
||||
behavior = GSAIPursue.new(agent, player_agent, predict_time)
|
||||
|
||||
var orient_behavior := GSAIFace.new(agent, _direction_face)
|
||||
orient_behavior.alignment_tolerance = deg2rad(5)
|
||||
orient_behavior.deceleration_radius = deg2rad(30)
|
||||
|
||||
_blend = GSAIBlend.new(agent)
|
||||
_blend.add(behavior, 1)
|
||||
_blend.add(orient_behavior, 1)
|
||||
|
||||
agent.angular_acceleration_max = deg2rad(1080)
|
||||
agent.angular_speed_max = deg2rad(360)
|
||||
agent.linear_acceleration_max = linear_accel_max
|
||||
agent.linear_speed_max = linear_speed_max
|
||||
|
||||
set_physics_process(true)
|
@ -1,167 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
# Maximum possible linear velocity
|
||||
export var speed_max := 450.0
|
||||
# Maximum change in linear velocity
|
||||
export var acceleration_max := 50.0
|
||||
# Maximum rotation velocity represented in degrees
|
||||
export var angular_speed_max := 240
|
||||
# Maximum change in rotation velocity represented in degrees
|
||||
export var angular_acceleration_max := 40
|
||||
|
||||
export var health_max := 100
|
||||
export var flee_health_threshold := 20
|
||||
|
||||
var velocity := Vector2.ZERO
|
||||
var angular_velocity := 0.0
|
||||
var linear_drag := 0.1
|
||||
var angular_drag := 0.1
|
||||
|
||||
# Holds the linear and angular components calculated by our steering behaviors.
|
||||
var acceleration := GSAITargetAcceleration.new()
|
||||
|
||||
onready var current_health := health_max
|
||||
|
||||
# GSAISteeringAgent holds our agent's position, orientation, maximum speed and acceleration.
|
||||
onready var agent := GSAISteeringAgent.new()
|
||||
|
||||
onready var player: Node = get_tree().get_nodes_in_group("Player")[0]
|
||||
# This assumes that our player class will keep its own agent updated.
|
||||
onready var player_agent: GSAISteeringAgent = player.agent
|
||||
|
||||
# Proximities represent an area with which an agent can identify where neighbors in its relevant
|
||||
# group are. In our case, the group will feature the player, which will be used to avoid a
|
||||
# collision with them. We use a radius proximity so the player is only relevant inside 100 pixels.
|
||||
onready var proximity := GSAIRadiusProximity.new(agent, [player_agent], 100)
|
||||
|
||||
# GSAIBlend combines behaviors together, calculating all of their acceleration together and adding
|
||||
# them together, multiplied by a strength. We will have one for fleeing, and one for pursuing,
|
||||
# toggling them depending on the agent's health. Since we want the agent to rotate AND move, then
|
||||
# we aim to blend them together.
|
||||
onready var flee_blend := GSAIBlend.new(agent)
|
||||
onready var pursue_blend := GSAIBlend.new(agent)
|
||||
|
||||
# GSAIPriority will be the main steering behavior we use. It holds sub-behaviors and will pick the
|
||||
# first one that returns non-zero acceleration, ignoring any afterwards.
|
||||
onready var priority := GSAIPriority.new(agent)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# ---------- Configuration for our agent ----------
|
||||
agent.linear_speed_max = speed_max
|
||||
agent.linear_acceleration_max = acceleration_max
|
||||
agent.angular_speed_max = deg2rad(angular_speed_max)
|
||||
agent.angular_acceleration_max = deg2rad(angular_acceleration_max)
|
||||
agent.bounding_radius = calculate_radius($CollisionPolygon2D.polygon)
|
||||
update_agent()
|
||||
|
||||
# ---------- Configuration for our behaviors ----------
|
||||
# Pursue will happen while the agent is in good health. It produces acceleration that takes
|
||||
# the agent on an intercept course with the target, predicting its position in the future.
|
||||
var pursue := GSAIPursue.new(agent, player_agent)
|
||||
pursue.predict_time_max = 1.5
|
||||
|
||||
# Flee will happen while the agent is in bad health, so will start disabled. It produces
|
||||
# acceleration that takes the agent directly away from the target with no prediction.
|
||||
var flee := GSAIFlee.new(agent, player_agent)
|
||||
|
||||
# AvoidCollision tries to keep the agent from running into any of the neighbors found in its
|
||||
# proximity group. In our case, this will be the player, if they are close enough.
|
||||
var avoid := GSAIAvoidCollisions.new(agent, proximity)
|
||||
|
||||
# Face turns the agent to keep looking towards its target. It will be enabled while the agent
|
||||
# is not fleeing due to low health. It tries to arrive 'on alignment' with 0 remaining velocity.
|
||||
var face := GSAIFace.new(agent, player_agent)
|
||||
|
||||
# We use deg2rad because the math in the toolkit assumes radians.
|
||||
# How close for the agent to be 'aligned', if not exact.
|
||||
face.alignment_tolerance = deg2rad(5)
|
||||
# When to start slowing down
|
||||
face.deceleration_radius = deg2rad(60)
|
||||
|
||||
# LookWhereYouGo turns the agent to keep looking towards its direction of travel. It will only
|
||||
# be enabled while the agent is at low health.
|
||||
var look := GSAILookWhereYouGo.new(agent)
|
||||
# How close for the agent to be 'aligned', if not exact
|
||||
look.alignment_tolerance = deg2rad(5)
|
||||
# When to start slowing down.
|
||||
look.deceleration_radius = deg2rad(60)
|
||||
|
||||
# Behaviors that are not enabled produce 0 acceleration.
|
||||
# Adding our fleeing behaviors to a blend. The order does not matter.
|
||||
flee_blend.is_enabled = false
|
||||
flee_blend.add(look, 1)
|
||||
flee_blend.add(flee, 1)
|
||||
|
||||
# Adding our pursuit behaviors to a blend. The order does not matter.
|
||||
pursue_blend.add(face, 1)
|
||||
pursue_blend.add(pursue, 1)
|
||||
|
||||
# Adding our final behaviors to the main priority behavior. The order does matter here.
|
||||
# We want to avoid collision with the player first, flee from the player second when enabled,
|
||||
# and pursue the player last when enabled.
|
||||
priority.add(avoid)
|
||||
priority.add(flee_blend)
|
||||
priority.add(pursue_blend)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
# Make sure any change in position and speed has been recorded.
|
||||
update_agent()
|
||||
|
||||
if current_health <= flee_health_threshold:
|
||||
pursue_blend.is_enabled = false
|
||||
flee_blend.is_enabled = true
|
||||
|
||||
# Calculate the desired acceleration.
|
||||
priority.calculate_steering(acceleration)
|
||||
|
||||
# We add the discovered acceleration to our linear velocity. The toolkit does not limit
|
||||
# velocity, just acceleration, so we clamp the result ourselves here.
|
||||
velocity = (velocity + Vector2(acceleration.linear.x, acceleration.linear.y) * delta).clamped(
|
||||
agent.linear_speed_max
|
||||
)
|
||||
|
||||
# This applies drag on the agent's motion, helping it to slow down naturally.
|
||||
velocity = velocity.linear_interpolate(Vector2.ZERO, linear_drag)
|
||||
|
||||
# And since we're using a KinematicBody2D, we use Godot's excellent move_and_slide to actually
|
||||
# apply the final movement, and record any change in velocity the physics engine discovered.
|
||||
velocity = move_and_slide(velocity)
|
||||
|
||||
# We then do something similar to apply our agent's rotational speed.
|
||||
angular_velocity = clamp(
|
||||
angular_velocity + acceleration.angular * delta, -agent.angular_speed_max, agent.angular_speed_max
|
||||
)
|
||||
# This applies drag on the agent's rotation, helping it slow down naturally.
|
||||
angular_velocity = lerp(angular_velocity, 0, angular_drag)
|
||||
rotation += angular_velocity * delta
|
||||
|
||||
|
||||
# In order to support both 2D and 3D, the toolkit uses Vector3, so the conversion is required
|
||||
# when using 2D nodes. The Z component can be left to 0 safely.
|
||||
func update_agent() -> void:
|
||||
agent.position.x = global_position.x
|
||||
agent.position.y = global_position.y
|
||||
agent.orientation = rotation
|
||||
agent.linear_velocity.x = velocity.x
|
||||
agent.linear_velocity.y = velocity.y
|
||||
agent.angular_velocity = angular_velocity
|
||||
|
||||
|
||||
# We calculate the radius from the collision shape - this will approximate the agent's size in the
|
||||
# game world, to avoid collisions with the player.
|
||||
func calculate_radius(polygon: PoolVector2Array) -> float:
|
||||
var furthest_point := Vector2(-INF, -INF)
|
||||
for p in polygon:
|
||||
if abs(p.x) > furthest_point.x:
|
||||
furthest_point.x = p.x
|
||||
if abs(p.y) > furthest_point.y:
|
||||
furthest_point.y = p.y
|
||||
return furthest_point.length()
|
||||
|
||||
|
||||
func damage(amount: int) -> void:
|
||||
current_health -= amount
|
||||
if current_health <= 0:
|
||||
queue_free()
|
@ -1,33 +0,0 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
export var speed := 1500.0
|
||||
|
||||
var velocity := Vector2.ZERO
|
||||
var player: Node
|
||||
|
||||
onready var timer := $Lifetime
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
timer.connect("timeout", self, "_on_Lifetime_timeout")
|
||||
timer.start()
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
var collision := move_and_collide(velocity * delta)
|
||||
if collision:
|
||||
timer.stop()
|
||||
clear()
|
||||
collision.collider.damage(10)
|
||||
|
||||
|
||||
func start(direction: Vector2) -> void:
|
||||
velocity = direction * speed
|
||||
|
||||
|
||||
func clear() -> void:
|
||||
queue_free()
|
||||
|
||||
|
||||
func _on_Lifetime_timeout() -> void:
|
||||
clear()
|
@ -1,23 +0,0 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://demos/Utils/CircleDraw.gd" type="Script" id=1]
|
||||
[ext_resource path="res://demos/Quickstart/Bullet.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=1]
|
||||
radius = 4.0
|
||||
|
||||
[node name="Bullet" type="KinematicBody2D"]
|
||||
collision_layer = 4
|
||||
collision_mask = 2
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
script = ExtResource( 1 )
|
||||
inner_color = Color( 0.235294, 0.639216, 0.439216, 1 )
|
||||
outer_color = Color( 0.560784, 0.870588, 0.364706, 1 )
|
||||
stroke = 2.0
|
||||
|
||||
[node name="Lifetime" type="Timer" parent="."]
|
||||
process_mode = 0
|
||||
wait_time = 3.0
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user