Compare commits
90 Commits
3.2-5bd2bb
...
3.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f43c0fb3a1 | ||
|
|
834c62fb88 | ||
|
|
098e13cca2 | ||
|
|
ee1252eafe | ||
|
|
aa5aa936cb | ||
|
|
94ec2ea5d9 | ||
|
|
40aec7c068 | ||
|
|
ead2777f48 | ||
|
|
0a0d44d4f1 | ||
|
|
4911866f3d | ||
|
|
d7e1052205 | ||
|
|
8e2dbf3f55 | ||
|
|
2ee9b47f6c | ||
|
|
d8dc94c1ff | ||
|
|
d989bf6209 | ||
|
|
021070215c | ||
|
|
ac61cba05b | ||
|
|
21e829416f | ||
|
|
cf7e4b31f4 | ||
|
|
dc5c1016ce | ||
|
|
8a0824a948 | ||
|
|
5c154dac25 | ||
|
|
7f095a6092 | ||
|
|
35687c3ead | ||
|
|
f91fe01f3e | ||
|
|
43d29bfbbb | ||
|
|
7dff4e748d | ||
|
|
4913cd868a | ||
|
|
973c12264c | ||
|
|
fecbed5fb2 | ||
|
|
82e68e378b | ||
|
|
bbf4cff5f7 | ||
|
|
3d6ba65cfc | ||
|
|
ca0f74ee44 | ||
|
|
aa65867e43 | ||
|
|
c2e7a30e42 | ||
|
|
4dbfd92e6f | ||
|
|
c0d9e483c2 | ||
|
|
36db05c3b9 | ||
|
|
fc032119ca | ||
|
|
98ed996780 | ||
|
|
fa83ee0277 | ||
|
|
7c137510e7 | ||
|
|
10a7e3d301 | ||
|
|
feaf406fee | ||
|
|
d90e401d2a | ||
|
|
99ad90bd0d | ||
|
|
4adaaa2eb2 | ||
|
|
b946d20762 | ||
|
|
2a13307276 | ||
|
|
0b3e046953 | ||
|
|
68e095c4d6 | ||
|
|
fe54ebbb3a | ||
|
|
cdf0ed3be9 | ||
|
|
da9e24dfa7 | ||
|
|
1c1ad17b43 | ||
|
|
5618c2b45a | ||
|
|
3878948300 | ||
|
|
ca4cde1c26 | ||
|
|
6a738c1ede | ||
|
|
04e9afb4cf | ||
|
|
e73af12f49 | ||
|
|
6bdbeafca2 | ||
|
|
21cbaafb2f | ||
|
|
35426410d5 | ||
|
|
54a8d37e6c | ||
|
|
d5dae1cbb7 | ||
|
|
06dc40ba65 | ||
|
|
7c604f336d | ||
|
|
e3a31afe40 | ||
|
|
289d658baa | ||
|
|
7a437d1d23 | ||
|
|
08e3f1efd0 | ||
|
|
0d9c0d15c6 | ||
|
|
96baaa09e3 | ||
|
|
e004d2564e | ||
|
|
651ef54920 | ||
|
|
4a60286512 | ||
|
|
1148a6bda0 | ||
|
|
9ad473c633 | ||
|
|
e38be6dec0 | ||
|
|
8241be5817 | ||
|
|
1c836ecde9 | ||
|
|
6dd09308fa | ||
|
|
555e43c896 | ||
|
|
2bd5b1c8ee | ||
|
|
14f2f1a713 | ||
|
|
3d9bcc6d97 | ||
|
|
3147c6c5bd | ||
|
|
20a515153f |
@@ -2,10 +2,15 @@
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file.
|
||||
[*.cs]
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.cs]
|
||||
csharp_space_after_cast = false
|
||||
indent_size = 4
|
||||
|
||||
[*.csproj]
|
||||
insert_final_newline = false
|
||||
indent_size = 2
|
||||
|
||||
11
.github/CODEOWNERS
vendored
@@ -2,5 +2,12 @@
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
# Owners can be @users, @org/teams or emails
|
||||
|
||||
/misc/2.5d @aaronfranke
|
||||
/mono/2.5d @aaronfranke
|
||||
/.github/dist/ @Calinou
|
||||
|
||||
/3d/voxel/ @aaronfranke
|
||||
/misc/matrix_transform/ @aaronfranke
|
||||
/misc/2.5d/ @aaronfranke
|
||||
/mono/2.5d/ @aaronfranke
|
||||
|
||||
/2d/physics_tests/ @pouleyKetchoupp
|
||||
/3d/physics_tests/ @pouleyKetchoupp
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Report a bug with one of the demo projects.
|
||||
title: ''
|
||||
title: ""
|
||||
labels: bug
|
||||
assignees: ''
|
||||
assignees: ""
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
---
|
||||
name: Feature / Enhancement Request
|
||||
about: Adding new features or improving existing ones.
|
||||
title: ''
|
||||
title: ""
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
assignees: ""
|
||||
|
||||
---
|
||||
|
||||
|
||||
0
.github/dist/.nojekyll
vendored
Normal file
23
.github/dist/export_presets.cfg
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
[preset.0]
|
||||
|
||||
name="HTML5"
|
||||
platform="HTML5"
|
||||
runnable=true
|
||||
custom_features=""
|
||||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
exclude_filter=""
|
||||
export_path=""
|
||||
script_export_mode=1
|
||||
script_encryption_key=""
|
||||
|
||||
[preset.0.options]
|
||||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
variant/export_type=0
|
||||
vram_texture_compression/for_desktop=true
|
||||
vram_texture_compression/for_mobile=false
|
||||
html/custom_html_shell=""
|
||||
html/head_include=""
|
||||
html/full_window_size=true
|
||||
19
.github/dist/footer.html
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- The list of demos will be inserted above by the CI process. -->
|
||||
</ul>
|
||||
<h2>Unavailable demos</h2>
|
||||
<ul>
|
||||
<li><code>2d/hdr/</code>: Not supported on HTML5 yet.
|
||||
<li><code>3d/voxel/</code>: Not supported on HTML5 yet.
|
||||
<li><code>audio/device_changer/</code>: Not supported on HTML5 due to browser limitations.
|
||||
<li><code>loading/background_load/</code>: Not supported on HTML5 yet.
|
||||
<li><code>loading/multiple_threads_loading/</code>: Not supported on HTML5 yet.
|
||||
<li><code>loading/threads/</code>: Not supported on HTML5 yet.
|
||||
<li><code>misc/matrix_transform/</code>: Results are only visible in the editor.
|
||||
<li><code>mobile/android_iap/</code>: Only relevant on native Android.
|
||||
<li><code>mobile/sensors/</code>: Not supported on HTML5 yet.
|
||||
<li><code>mono/*/</code>: Not available yet (requires Mono-enabled HTML5 build).</li>
|
||||
<li><code>networking/*/</code>: Doesn't make sense to be hosted on a static host, as the server must be hosted on the same origin due to the browser's same-origin policy.</li>
|
||||
<li><code>plugins/*/</code>: Only effective within the editor.</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
118
.github/dist/header.html
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Godot demos exported to HTML5</title>
|
||||
<style>
|
||||
:root {
|
||||
--background-color: #fff;
|
||||
--text-color: #222;
|
||||
--link-color: hsl(220, 100%, 45%);
|
||||
--link-underline-color: hsla(220, 100%, 45%, 0.3);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background-color: #222;
|
||||
--text-color: #eee;
|
||||
--link-color: hsl(200, 100%, 70%);
|
||||
--link-underline-color: hsla(200, 100%, 70%, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
*:focus {
|
||||
/* More visible outline for better keyboard navigation. */
|
||||
outline: 0.125rem solid hsl(220, 100%, 62.5%);
|
||||
/* Make the outline always appear above other elements. */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: var(--background-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
max-width: 50rem;
|
||||
margin: 0 auto;
|
||||
padding: 0.75rem;
|
||||
line-height: 1.618rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link-color);
|
||||
text-decoration-color: var(--link-underline-color);
|
||||
text-decoration-thickness: 0.125rem;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
filter: brightness(117.5%);
|
||||
}
|
||||
|
||||
a:active {
|
||||
filter: brightness(82.5%);
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: block;
|
||||
}
|
||||
|
||||
li a {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 4rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
li a:hover {
|
||||
background-color: hsla(0, 0%, 50%, 0.1);
|
||||
}
|
||||
|
||||
li a * {
|
||||
float: left;
|
||||
}
|
||||
|
||||
li a p {
|
||||
height: 24px;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Godot demo projects</h1>
|
||||
<p>
|
||||
This page lists
|
||||
<a href="https://github.com/godotengine/godot-demo-projects">official Godot demo projects</a>
|
||||
exported to HTML5 for testing purposes. These projects are deployed automatically
|
||||
on every commit on the <code>master</code> branch of the repository.
|
||||
</p>
|
||||
<p>
|
||||
The HTML5 exports on this page are provided for demonstration purposes only.
|
||||
Some of these demos may not function or render correctly on HTML5,
|
||||
especially on mobile devices.
|
||||
For best performance, it's recommended to
|
||||
<a href="https://godotengine.org/download">download</a> a native editor
|
||||
and run the demo project by importing its files in the project manager.
|
||||
</p>
|
||||
<p>
|
||||
See the
|
||||
<a href="https://docs.godotengine.org/en/stable/getting_started/workflow/export/exporting_for_web.html">Exporting for the Web</a>
|
||||
documentation for information on exporting your own projects to HTML5.
|
||||
</p>
|
||||
|
||||
<h2>List of demos</h2>
|
||||
<ul>
|
||||
<!-- The list of demos will be inserted below by the CI process. -->
|
||||
4
.github/workflows/static_checks.yml
vendored
@@ -4,10 +4,10 @@ on: [push, pull_request]
|
||||
jobs:
|
||||
format:
|
||||
name: File formatting (file_format.sh)
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
3
.gitignore
vendored
@@ -5,6 +5,8 @@
|
||||
.import/
|
||||
export.cfg
|
||||
export_presets.cfg
|
||||
# Dummy HTML5 export presets file for continuous integration
|
||||
!.github/dist/export_presets.cfg
|
||||
|
||||
# Imported translations (automatically generated from CSV files)
|
||||
*.translation
|
||||
@@ -16,4 +18,5 @@ mono_crash.*.json
|
||||
|
||||
# System/tool-specific ignores
|
||||
.directory
|
||||
.DS_Store
|
||||
*~
|
||||
|
||||
20
2d/bullet_shower/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Bullet Shower
|
||||
|
||||
This demonstrates how to manage large amounts of objects efficiently using
|
||||
low-level Servers.
|
||||
|
||||
See
|
||||
[Optimization using Servers](https://docs.godotengine.org/en/latest/tutorials/performance/using_servers.html)
|
||||
in the documentation for more information.
|
||||
|
||||
Language: GDScript
|
||||
|
||||
Renderer: GLES 2
|
||||
|
||||
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/887
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
BIN
2d/bullet_shower/bullet.png
Normal file
|
After Width: | Height: | Size: 312 B |
34
2d/bullet_shower/bullet.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/bullet.png-ff1424653e10246c11e3724e402c519e.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://bullet.png"
|
||||
dest_files=[ "res://.import/bullet.png-ff1424653e10246c11e3724e402c519e.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
|
||||
89
2d/bullet_shower/bullets.gd
Normal file
@@ -0,0 +1,89 @@
|
||||
extends Node2D
|
||||
# This demo is an example of controling a high number of 2D objects with logic
|
||||
# and collision without using nodes in the scene. This technique is a lot more
|
||||
# efficient than using instancing and nodes, but requires more programming and
|
||||
# is less visual. Bullets are managed together in the `bullets.gd` script.
|
||||
|
||||
const BULLET_COUNT = 500
|
||||
const SPEED_MIN = 20
|
||||
const SPEED_MAX = 80
|
||||
|
||||
const bullet_image = preload("res://bullet.png")
|
||||
|
||||
var bullets = []
|
||||
var shape
|
||||
|
||||
|
||||
class Bullet:
|
||||
var position = Vector2()
|
||||
var speed = 1.0
|
||||
# The body is stored as a RID, which is an "opaque" way to access resources.
|
||||
# With large amounts of objects (thousands or more), it can be significantly
|
||||
# faster to use RIDs compared to a high-level approach.
|
||||
var body = RID()
|
||||
|
||||
|
||||
func _ready():
|
||||
randomize()
|
||||
|
||||
shape = Physics2DServer.circle_shape_create()
|
||||
# Set the collision shape's radius for each bullet in pixels.
|
||||
Physics2DServer.shape_set_data(shape, 8)
|
||||
|
||||
for _i in BULLET_COUNT:
|
||||
var bullet = Bullet.new()
|
||||
# Give each bullet its own speed.
|
||||
bullet.speed = rand_range(SPEED_MIN, SPEED_MAX)
|
||||
bullet.body = Physics2DServer.body_create()
|
||||
|
||||
Physics2DServer.body_set_space(bullet.body, get_world_2d().get_space())
|
||||
Physics2DServer.body_add_shape(bullet.body, shape)
|
||||
|
||||
# Place bullets randomly on the viewport and move bullets outside the
|
||||
# play area so that they fade in nicely.
|
||||
bullet.position = Vector2(
|
||||
rand_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x,
|
||||
rand_range(0, get_viewport_rect().size.y)
|
||||
)
|
||||
var transform2d = Transform2D()
|
||||
transform2d.origin = bullet.position
|
||||
Physics2DServer.body_set_state(bullet.body, Physics2DServer.BODY_STATE_TRANSFORM, transform2d)
|
||||
|
||||
bullets.push_back(bullet)
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
# Order the CanvasItem to update every frame.
|
||||
update()
|
||||
|
||||
|
||||
func _physics_process(delta):
|
||||
var transform2d = Transform2D()
|
||||
var offset = get_viewport_rect().size.x + 16
|
||||
for bullet in bullets:
|
||||
bullet.position.x -= bullet.speed * delta
|
||||
|
||||
if bullet.position.x < -16:
|
||||
# The bullet has left the screen; move it back to the right.
|
||||
bullet.position.x = offset
|
||||
|
||||
transform2d.origin = bullet.position
|
||||
|
||||
Physics2DServer.body_set_state(bullet.body, Physics2DServer.BODY_STATE_TRANSFORM, transform2d)
|
||||
|
||||
|
||||
# Instead of drawing each bullet individually in a script attached to each bullet,
|
||||
# we are drawing *all* the bullets at once here.
|
||||
func _draw():
|
||||
var offset = -bullet_image.get_size() * 0.5
|
||||
for bullet in bullets:
|
||||
draw_texture(bullet_image, bullet.position + offset)
|
||||
|
||||
|
||||
# Perform cleanup operations (required to exit without error messages in the console).
|
||||
func _exit_tree():
|
||||
for bullet in bullets:
|
||||
Physics2DServer.free_rid(bullet.body)
|
||||
|
||||
Physics2DServer.free_rid(shape)
|
||||
bullets.clear()
|
||||
BIN
2d/bullet_shower/face_happy.png
Normal file
|
After Width: | Height: | Size: 907 B |
34
2d/bullet_shower/face_happy.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/face_happy.png-38d387d31ec13459f749c93ce3d75d80.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://face_happy.png"
|
||||
dest_files=[ "res://.import/face_happy.png-38d387d31ec13459f749c93ce3d75d80.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
|
||||
BIN
2d/bullet_shower/face_sad.png
Normal file
|
After Width: | Height: | Size: 846 B |
34
2d/bullet_shower/face_sad.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/face_sad.png-0ac7165eab24f595aba17a746a66c550.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://face_sad.png"
|
||||
dest_files=[ "res://.import/face_sad.png-0ac7165eab24f595aba17a746a66c550.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
|
||||
BIN
2d/bullet_shower/icon.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
34
2d/bullet_shower/icon.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.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
|
||||
33
2d/bullet_shower/player.gd
Normal file
@@ -0,0 +1,33 @@
|
||||
extends Node2D
|
||||
# This demo is an example of controling a high number of 2D objects with logic
|
||||
# and collision without using nodes in the scene. This technique is a lot more
|
||||
# efficient than using instancing and nodes, but requires more programming and
|
||||
# is less visual. Bullets are managed together in the `bullets.gd` script.
|
||||
|
||||
# The number of bullets currently touched by the player.
|
||||
var touching = 0
|
||||
|
||||
onready var sprite = $AnimatedSprite
|
||||
|
||||
|
||||
func _ready():
|
||||
# The player follows the mouse cursor automatically, so there's no point
|
||||
# in displaying the mouse cursor.
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN)
|
||||
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventMouseMotion:
|
||||
position = event.position - Vector2(0, 16)
|
||||
|
||||
|
||||
func _on_body_shape_entered(_body_id, _body, _body_shape, _local_shape):
|
||||
touching += 1
|
||||
if touching >= 1:
|
||||
sprite.frame = 1
|
||||
|
||||
|
||||
func _on_body_shape_exited(_body_id, _body, _body_shape, _local_shape):
|
||||
touching -= 1
|
||||
if touching == 0:
|
||||
sprite.frame = 0
|
||||
41
2d/bullet_shower/project.godot
Normal file
@@ -0,0 +1,41 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=4
|
||||
|
||||
_global_script_classes=[ ]
|
||||
_global_script_class_icons={
|
||||
|
||||
}
|
||||
|
||||
[application]
|
||||
|
||||
config/name="Bullet Shower"
|
||||
config/description="Demonstrates how to manage large amounts of objects efficiently using low-level Servers."
|
||||
run/main_scene="res://shower.tscn"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[display]
|
||||
|
||||
window/dpi/allow_hidpi=true
|
||||
window/stretch/mode="2d"
|
||||
window/stretch/aspect="expand"
|
||||
|
||||
[physics]
|
||||
|
||||
2d/cell_size=64
|
||||
common/enable_pause_aware_picking=true
|
||||
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
quality/intended_usage/framebuffer_allocation=0
|
||||
quality/intended_usage/framebuffer_allocation.mobile=0
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.133333, 0.133333, 0.2, 1 )
|
||||
0
2d/bullet_shower/screenshots/.gdignore
Normal file
BIN
2d/bullet_shower/screenshots/collision.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
2d/bullet_shower/screenshots/no_collision.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
33
2d/bullet_shower/shower.tscn
Normal file
@@ -0,0 +1,33 @@
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://bullets.gd" type="Script" id=2]
|
||||
[ext_resource path="res://face_happy.png" type="Texture" id=3]
|
||||
[ext_resource path="res://face_sad.png" type="Texture" id=4]
|
||||
[ext_resource path="res://player.gd" type="Script" id=5]
|
||||
|
||||
[sub_resource type="SpriteFrames" id=1]
|
||||
animations = [ {
|
||||
"frames": [ ExtResource( 3 ), ExtResource( 4 ) ],
|
||||
"loop": true,
|
||||
"name": "default",
|
||||
"speed": 5.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="CircleShape2D" id=2]
|
||||
radius = 27.0
|
||||
|
||||
[node name="Shower" type="Node2D"]
|
||||
|
||||
[node name="Bullets" type="Node2D" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="Player" type="Area2D" parent="."]
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="AnimatedSprite" type="AnimatedSprite" parent="Player"]
|
||||
frames = SubResource( 1 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Player"]
|
||||
shape = SubResource( 2 )
|
||||
[connection signal="body_shape_entered" from="Player" to="Player" method="_on_body_shape_entered"]
|
||||
[connection signal="body_shape_exited" from="Player" to="Player" method="_on_body_shape_exited"]
|
||||
@@ -10,20 +10,20 @@
|
||||
|
||||
[sub_resource type="SpriteFrames" id=1]
|
||||
animations = [ {
|
||||
"frames": [ ExtResource( 4 ), ExtResource( 5 ) ],
|
||||
"frames": [ ExtResource( 2 ), ExtResource( 3 ) ],
|
||||
"loop": true,
|
||||
"name": "walk",
|
||||
"speed": 4.0
|
||||
"name": "fly",
|
||||
"speed": 3.0
|
||||
}, {
|
||||
"frames": [ ExtResource( 6 ), ExtResource( 7 ) ],
|
||||
"loop": true,
|
||||
"name": "swim",
|
||||
"speed": 4.0
|
||||
}, {
|
||||
"frames": [ ExtResource( 2 ), ExtResource( 3 ) ],
|
||||
"frames": [ ExtResource( 4 ), ExtResource( 5 ) ],
|
||||
"loop": true,
|
||||
"name": "fly",
|
||||
"speed": 3.0
|
||||
"name": "walk",
|
||||
"speed": 4.0
|
||||
} ]
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=2]
|
||||
|
||||
@@ -115,7 +115,7 @@ align = 1
|
||||
valign = 1
|
||||
uppercase = true
|
||||
script = ExtResource( 15 )
|
||||
[connection signal="state_changed" from="StateMachine" to="StateNameDisplayer" method="_on_StateMachine_state_changed"]
|
||||
[connection signal="state_changed" from="StateMachine" to="BodyPivot/WeaponPivot/Offset/Sword" method="_on_StateMachine_state_changed"]
|
||||
[connection signal="state_changed" from="StateMachine" to="StateNameDisplayer" method="_on_StateMachine_state_changed"]
|
||||
[connection signal="animation_finished" from="AnimationPlayer" to="StateMachine" method="_on_animation_finished"]
|
||||
[connection signal="attack_finished" from="BodyPivot/WeaponPivot/Offset/Sword" to="StateMachine/Attack" method="_on_Sword_attack_finished"]
|
||||
|
||||
@@ -19,7 +19,10 @@ var height = 0.0
|
||||
|
||||
func initialize(speed, velocity):
|
||||
horizontal_speed = speed
|
||||
max_horizontal_speed = speed if speed > 0.0 else base_max_horizontal_speed
|
||||
if speed > 0.0:
|
||||
max_horizontal_speed = speed
|
||||
else:
|
||||
max_horizontal_speed = base_max_horizontal_speed
|
||||
enter_velocity = velocity
|
||||
|
||||
|
||||
@@ -27,7 +30,10 @@ func enter():
|
||||
var input_direction = get_input_direction()
|
||||
update_look_direction(input_direction)
|
||||
|
||||
horizontal_velocity = enter_velocity if input_direction else Vector2()
|
||||
if input_direction:
|
||||
horizontal_velocity = enter_velocity
|
||||
else:
|
||||
horizontal_velocity = Vector2()
|
||||
vertical_speed = 600.0
|
||||
|
||||
owner.get_node("AnimationPlayer").play("idle")
|
||||
|
||||
@@ -22,7 +22,11 @@ func update(_delta):
|
||||
emit_signal("finished", "idle")
|
||||
update_look_direction(input_direction)
|
||||
|
||||
speed = max_run_speed if Input.is_action_pressed("run") else max_walk_speed
|
||||
if Input.is_action_pressed("run"):
|
||||
speed = max_run_speed
|
||||
else:
|
||||
speed = max_walk_speed
|
||||
|
||||
var collision_info = move(speed, input_direction)
|
||||
if not collision_info:
|
||||
return
|
||||
|
||||
@@ -102,3 +102,5 @@ attack={
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
|
||||
@@ -37,3 +37,5 @@ singletons=[ ]
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
|
||||
@@ -68,4 +68,6 @@ move_up={
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.172549, 0.219608, 0.129412, 1 )
|
||||
|
||||
@@ -39,4 +39,6 @@ singletons=[ ]
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.301961, 0.301961, 0.301961, 1 )
|
||||
|
||||
@@ -80,4 +80,6 @@ use_pixel_snap=true
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.0784314, 0.105882, 0.145098, 1 )
|
||||
|
||||
@@ -76,4 +76,6 @@ multithread/thread_rid_pool_prealloc=60
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.156, 0.1325, 0.25, 1 )
|
||||
|
||||
@@ -37,3 +37,5 @@ shadow_filter=3
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
|
||||
@@ -41,3 +41,5 @@ shadow_filter=2
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
|
||||
@@ -46,4 +46,6 @@ click={
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.160784, 0.172549, 0.278431, 1 )
|
||||
|
||||
@@ -38,3 +38,5 @@ click={
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
|
||||
@@ -19,11 +19,11 @@ _data = [ Vector2( 0, 1 ), 0.0, 0.0, 0, 0, Vector2( 1, 85.0781 ), 0.0, 0.0, 0, 0
|
||||
[sub_resource type="CurveTexture" id=3]
|
||||
curve = SubResource( 2 )
|
||||
|
||||
[sub_resource type="Curve" id=31]
|
||||
[sub_resource type="Curve" id=4]
|
||||
_data = [ Vector2( 0, 1 ), 0.0, 0.0, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ]
|
||||
|
||||
[sub_resource type="CurveTexture" id=5]
|
||||
curve = SubResource( 31 )
|
||||
curve = SubResource( 4 )
|
||||
|
||||
[sub_resource type="ParticlesMaterial" id=6]
|
||||
emission_shape = 1
|
||||
|
||||
21
2d/physics_tests/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 2D Physics Tests
|
||||
|
||||
This demo contains a series of tests for the 2D
|
||||
physics engine.
|
||||
|
||||
They can be used for different purpose:
|
||||
|
||||
- Functional tests to check for regressions and
|
||||
behavior of the 2D physics engine
|
||||
- Performance tests to evaluate performance
|
||||
of the 2D physics engine
|
||||
|
||||
Language: GDScript
|
||||
|
||||
Renderer: GLES 2
|
||||
|
||||
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/888
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
BIN
2d/physics_tests/assets/texture/godot-head.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
34
2d/physics_tests/assets/texture/godot-head.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/godot-head.png-6a90da7ab6a8c80b4170f240c8e33e70.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/texture/godot-head.png"
|
||||
dest_files=[ "res://.import/godot-head.png-6a90da7ab6a8c80b4170f240c8e33e70.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
|
||||
BIN
2d/physics_tests/assets/tileset/tiles_demo.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
34
2d/physics_tests/assets/tileset/tiles_demo.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/tiles_demo.png-4d398d5cc02bc85a2809dc13fbc9a3c2.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/tileset/tiles_demo.png"
|
||||
dest_files=[ "res://.import/tiles_demo.png-4d398d5cc02bc85a2809dc13fbc9a3c2.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
|
||||
335
2d/physics_tests/assets/tileset/tileset.tres
Normal file
@@ -0,0 +1,335 @@
|
||||
[gd_resource type="TileSet" load_steps=14 format=2]
|
||||
|
||||
[ext_resource path="res://assets/tileset/tiles_demo.png" type="Texture" id=1]
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=1]
|
||||
points = PoolVector2Array( 0, 6, 32, 6, 32, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=2]
|
||||
points = PoolVector2Array( 0, 6, 28, 6, 28, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=3]
|
||||
points = PoolVector2Array( 0, 0, 32, 0, 32, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=4]
|
||||
points = PoolVector2Array( 0, 6, 32, 6, 32, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=5]
|
||||
points = PoolVector2Array( 32, 38, 32, 64, 0, 64, 0, 6 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=6]
|
||||
points = PoolVector2Array( 0, 0, 28, 0, 28, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=7]
|
||||
points = PoolVector2Array( 28, 6, 32, 6, 32, 32, 0, 32, 0, 0, 28, 0 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=8]
|
||||
points = PoolVector2Array( 0, 6, 32, 6, 32, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=9]
|
||||
points = PoolVector2Array( 0, 6, 28, 6, 28, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=10]
|
||||
points = PoolVector2Array( 0, 0, 32, 0, 32, 32, 0, 32 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=11]
|
||||
points = PoolVector2Array( 0, 0, 32, 0, 32, 24, 0, 24 )
|
||||
|
||||
[sub_resource type="ConvexPolygonShape2D" id=12]
|
||||
points = PoolVector2Array( 0, 0, 28, 0, 28, 24, 0, 24 )
|
||||
|
||||
[resource]
|
||||
0/name = "ground"
|
||||
0/texture = ExtResource( 1 )
|
||||
0/tex_offset = Vector2( 0, 0 )
|
||||
0/modulate = Color( 0, 0, 1, 1 )
|
||||
0/region = Rect2( 0, 0, 32, 32 )
|
||||
0/tile_mode = 0
|
||||
0/occluder_offset = Vector2( 0, 0 )
|
||||
0/navigation_offset = Vector2( 0, 0 )
|
||||
0/shape_offset = Vector2( 0, 0 )
|
||||
0/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
0/shape = SubResource( 1 )
|
||||
0/shape_one_way = false
|
||||
0/shape_one_way_margin = 1.0
|
||||
0/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 1 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
0/z_index = 0
|
||||
1/name = "ground_end"
|
||||
1/texture = ExtResource( 1 )
|
||||
1/tex_offset = Vector2( 0, 0 )
|
||||
1/modulate = Color( 1, 1, 1, 1 )
|
||||
1/region = Rect2( 32, 0, 32, 32 )
|
||||
1/tile_mode = 0
|
||||
1/occluder_offset = Vector2( 0, 0 )
|
||||
1/navigation_offset = Vector2( 0, 0 )
|
||||
1/shape_offset = Vector2( 0, 0 )
|
||||
1/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
1/shape = SubResource( 2 )
|
||||
1/shape_one_way = false
|
||||
1/shape_one_way_margin = 1.0
|
||||
1/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 2 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
1/z_index = 0
|
||||
2/name = "slope"
|
||||
2/texture = ExtResource( 1 )
|
||||
2/tex_offset = Vector2( 0, 0 )
|
||||
2/modulate = Color( 1, 1, 1, 1 )
|
||||
2/region = Rect2( 64, 64, 32, 64 )
|
||||
2/tile_mode = 0
|
||||
2/occluder_offset = Vector2( 0, 0 )
|
||||
2/navigation_offset = Vector2( 0, 0 )
|
||||
2/shape_offset = Vector2( 0, 0 )
|
||||
2/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
2/shape = SubResource( 5 )
|
||||
2/shape_one_way = false
|
||||
2/shape_one_way_margin = 1.0
|
||||
2/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 5 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
2/z_index = 0
|
||||
3/name = "wall"
|
||||
3/texture = ExtResource( 1 )
|
||||
3/tex_offset = Vector2( 0, 0 )
|
||||
3/modulate = Color( 1, 1, 1, 1 )
|
||||
3/region = Rect2( 32, 32, 32, 32 )
|
||||
3/tile_mode = 0
|
||||
3/occluder_offset = Vector2( 0, 0 )
|
||||
3/navigation_offset = Vector2( 0, 0 )
|
||||
3/shape_offset = Vector2( 0, 0 )
|
||||
3/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
3/shape = SubResource( 6 )
|
||||
3/shape_one_way = false
|
||||
3/shape_one_way_margin = 1.0
|
||||
3/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 6 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
3/z_index = 0
|
||||
4/name = "slope_top"
|
||||
4/texture = ExtResource( 1 )
|
||||
4/tex_offset = Vector2( 0, 0 )
|
||||
4/modulate = Color( 1, 1, 1, 1 )
|
||||
4/region = Rect2( 32, 64, 32, 32 )
|
||||
4/tile_mode = 0
|
||||
4/occluder_offset = Vector2( 0, 0 )
|
||||
4/navigation_offset = Vector2( 0, 0 )
|
||||
4/shape_offset = Vector2( 0, 0 )
|
||||
4/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
4/shape = SubResource( 7 )
|
||||
4/shape_one_way = false
|
||||
4/shape_one_way_margin = 1.0
|
||||
4/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 7 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
4/z_index = 0
|
||||
5/name = "one_way"
|
||||
5/texture = ExtResource( 1 )
|
||||
5/tex_offset = Vector2( 0, 0 )
|
||||
5/modulate = Color( 1, 1, 1, 1 )
|
||||
5/region = Rect2( 64, 0, 32, 32 )
|
||||
5/tile_mode = 0
|
||||
5/occluder_offset = Vector2( 0, 0 )
|
||||
5/navigation_offset = Vector2( 0, 0 )
|
||||
5/shape_offset = Vector2( 0, 0 )
|
||||
5/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
5/shape = SubResource( 8 )
|
||||
5/shape_one_way = true
|
||||
5/shape_one_way_margin = 1.0
|
||||
5/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": true,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 8 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
5/z_index = 0
|
||||
6/name = "one_way_end"
|
||||
6/texture = ExtResource( 1 )
|
||||
6/tex_offset = Vector2( 0, 0 )
|
||||
6/modulate = Color( 1, 1, 1, 1 )
|
||||
6/region = Rect2( 96, 0, 32, 32 )
|
||||
6/tile_mode = 0
|
||||
6/occluder_offset = Vector2( 0, 0 )
|
||||
6/navigation_offset = Vector2( 0, 0 )
|
||||
6/shape_offset = Vector2( 0, 0 )
|
||||
6/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
6/shape = SubResource( 9 )
|
||||
6/shape_one_way = true
|
||||
6/shape_one_way_margin = 1.0
|
||||
6/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": true,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 9 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
6/z_index = 0
|
||||
7/name = "rock"
|
||||
7/texture = ExtResource( 1 )
|
||||
7/tex_offset = Vector2( 0, 0 )
|
||||
7/modulate = Color( 1, 1, 1, 1 )
|
||||
7/region = Rect2( 0, 32, 32, 32 )
|
||||
7/tile_mode = 0
|
||||
7/occluder_offset = Vector2( 0, 0 )
|
||||
7/navigation_offset = Vector2( 0, 0 )
|
||||
7/shape_offset = Vector2( 0, 0 )
|
||||
7/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
7/shape = SubResource( 10 )
|
||||
7/shape_one_way = false
|
||||
7/shape_one_way_margin = 1.0
|
||||
7/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 10 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
7/z_index = 0
|
||||
8/name = "bottom"
|
||||
8/texture = ExtResource( 1 )
|
||||
8/tex_offset = Vector2( 0, 0 )
|
||||
8/modulate = Color( 1, 1, 1, 1 )
|
||||
8/region = Rect2( 192, 32, 32, 32 )
|
||||
8/tile_mode = 0
|
||||
8/occluder_offset = Vector2( 0, 0 )
|
||||
8/navigation_offset = Vector2( 0, 0 )
|
||||
8/shape_offset = Vector2( 0, 0 )
|
||||
8/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
8/shape = SubResource( 11 )
|
||||
8/shape_one_way = false
|
||||
8/shape_one_way_margin = 1.0
|
||||
8/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 11 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
8/z_index = 0
|
||||
9/name = "bottom_end"
|
||||
9/texture = ExtResource( 1 )
|
||||
9/tex_offset = Vector2( 0, 0 )
|
||||
9/modulate = Color( 1, 1, 1, 1 )
|
||||
9/region = Rect2( 224, 32, 32, 32 )
|
||||
9/tile_mode = 0
|
||||
9/occluder_offset = Vector2( 0, 0 )
|
||||
9/navigation_offset = Vector2( 0, 0 )
|
||||
9/shape_offset = Vector2( 0, 0 )
|
||||
9/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
9/shape = SubResource( 12 )
|
||||
9/shape_one_way = false
|
||||
9/shape_one_way_margin = 1.0
|
||||
9/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 12 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
9/z_index = 0
|
||||
10/name = "bottom_corner"
|
||||
10/texture = ExtResource( 1 )
|
||||
10/tex_offset = Vector2( 0, 0 )
|
||||
10/modulate = Color( 1, 1, 1, 1 )
|
||||
10/region = Rect2( 160, 32, 32, 32 )
|
||||
10/tile_mode = 0
|
||||
10/occluder_offset = Vector2( 0, 0 )
|
||||
10/navigation_offset = Vector2( 0, 0 )
|
||||
10/shape_offset = Vector2( 0, 0 )
|
||||
10/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
10/shape = SubResource( 3 )
|
||||
10/shape_one_way = false
|
||||
10/shape_one_way_margin = 1.0
|
||||
10/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 3 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
10/z_index = 0
|
||||
11/name = "tree_trunk_0"
|
||||
11/texture = ExtResource( 1 )
|
||||
11/tex_offset = Vector2( 0, 0 )
|
||||
11/modulate = Color( 1, 1, 1, 1 )
|
||||
11/region = Rect2( 128, 64, 32, 32 )
|
||||
11/tile_mode = 0
|
||||
11/occluder_offset = Vector2( 0, 0 )
|
||||
11/navigation_offset = Vector2( 0, 0 )
|
||||
11/shape_offset = Vector2( 0, 0 )
|
||||
11/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
11/shape_one_way = false
|
||||
11/shape_one_way_margin = 0.0
|
||||
11/shapes = [ ]
|
||||
11/z_index = 0
|
||||
12/name = "tree_trunk_1"
|
||||
12/texture = ExtResource( 1 )
|
||||
12/tex_offset = Vector2( 0, 0 )
|
||||
12/modulate = Color( 1, 1, 1, 1 )
|
||||
12/region = Rect2( 128, 32, 32, 32 )
|
||||
12/tile_mode = 0
|
||||
12/occluder_offset = Vector2( 0, 0 )
|
||||
12/navigation_offset = Vector2( 0, 0 )
|
||||
12/shape_offset = Vector2( 0, 0 )
|
||||
12/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
12/shape_one_way = false
|
||||
12/shape_one_way_margin = 0.0
|
||||
12/shapes = [ ]
|
||||
12/z_index = 0
|
||||
13/name = "tree_base"
|
||||
13/texture = ExtResource( 1 )
|
||||
13/tex_offset = Vector2( 0, 0 )
|
||||
13/modulate = Color( 1, 1, 1, 1 )
|
||||
13/region = Rect2( 128, 96, 32, 32 )
|
||||
13/tile_mode = 0
|
||||
13/occluder_offset = Vector2( 0, 0 )
|
||||
13/navigation_offset = Vector2( 0, 0 )
|
||||
13/shape_offset = Vector2( 0, 0 )
|
||||
13/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
13/shape = SubResource( 4 )
|
||||
13/shape_one_way = false
|
||||
13/shape_one_way_margin = 1.0
|
||||
13/shapes = [ {
|
||||
"autotile_coord": Vector2( 0, 0 ),
|
||||
"one_way": false,
|
||||
"one_way_margin": 1.0,
|
||||
"shape": SubResource( 4 ),
|
||||
"shape_transform": Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
} ]
|
||||
13/z_index = 0
|
||||
14/name = "tree_top"
|
||||
14/texture = ExtResource( 1 )
|
||||
14/tex_offset = Vector2( 0, 0 )
|
||||
14/modulate = Color( 1, 1, 1, 1 )
|
||||
14/region = Rect2( 128, 0, 32, 32 )
|
||||
14/tile_mode = 0
|
||||
14/occluder_offset = Vector2( 0, 0 )
|
||||
14/navigation_offset = Vector2( 0, 0 )
|
||||
14/shape_offset = Vector2( 0, 0 )
|
||||
14/shape_transform = Transform2D( 1, 0, 0, 1, 0, 0 )
|
||||
14/shape_one_way = false
|
||||
14/shape_one_way_margin = 0.0
|
||||
14/shapes = [ ]
|
||||
14/z_index = 0
|
||||
BIN
2d/physics_tests/icon.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
34
2d/physics_tests/icon.png.import
Normal file
@@ -0,0 +1,34 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="StreamTexture"
|
||||
path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.png"
|
||||
dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.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
|
||||
197
2d/physics_tests/main.tscn
Normal file
@@ -0,0 +1,197 @@
|
||||
[gd_scene load_steps=11 format=2]
|
||||
|
||||
[ext_resource path="res://utils/label_fps.gd" type="Script" id=1]
|
||||
[ext_resource path="res://utils/label_version.gd" type="Script" id=2]
|
||||
[ext_resource path="res://utils/label_engine.gd" type="Script" id=3]
|
||||
[ext_resource path="res://tests_menu.gd" type="Script" id=4]
|
||||
[ext_resource path="res://utils/label_test.gd" type="Script" id=5]
|
||||
[ext_resource path="res://utils/label_pause.gd" type="Script" id=6]
|
||||
[ext_resource path="res://utils/container_log.gd" type="Script" id=10]
|
||||
[ext_resource path="res://utils/scroll_log.gd" type="Script" id=11]
|
||||
[ext_resource path="res://tests.gd" type="Script" id=12]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=1]
|
||||
bg_color = Color( 0, 0, 0, 0.176471 )
|
||||
|
||||
[node name="Main" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 2
|
||||
script = ExtResource( 12 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="TestsMenu" type="MenuButton" parent="."]
|
||||
pause_mode = 2
|
||||
margin_left = 10.0
|
||||
margin_top = 10.0
|
||||
margin_right = 125.0
|
||||
margin_bottom = 30.0
|
||||
text = "TESTS"
|
||||
flat = false
|
||||
script = ExtResource( 4 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelControls" type="Label" parent="."]
|
||||
pause_mode = 2
|
||||
margin_left = 157.0
|
||||
margin_top = 13.0
|
||||
margin_right = 646.0
|
||||
margin_bottom = 27.0
|
||||
text = "P - TOGGLE PAUSE / R - RESTART / C - TOGGLE COLLISION / F - TOGGLE FULL SCREEN / ESC - QUIT"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelFPS" type="Label" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 10.0
|
||||
margin_top = -19.0
|
||||
margin_right = 50.0
|
||||
margin_bottom = -5.0
|
||||
text = "FPS: 0"
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelEngine" type="Label" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 10.0
|
||||
margin_top = -39.0
|
||||
margin_right = 50.0
|
||||
margin_bottom = -25.0
|
||||
text = "Physics engine:"
|
||||
script = ExtResource( 3 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelVersion" type="Label" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 10.0
|
||||
margin_top = -59.0
|
||||
margin_right = 50.0
|
||||
margin_bottom = -45.0
|
||||
text = "Godot Version:"
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelTest" type="Label" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 10.0
|
||||
margin_top = -79.0
|
||||
margin_right = 50.0
|
||||
margin_bottom = -65.0
|
||||
text = "Test:"
|
||||
script = ExtResource( 5 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelPause" type="Label" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
margin_left = -20.0
|
||||
margin_top = -40.9695
|
||||
margin_right = 31.0
|
||||
margin_bottom = -26.9695
|
||||
text = "PAUSED"
|
||||
script = ExtResource( 6 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PanelLog" type="Panel" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = -428.0
|
||||
margin_top = -125.0
|
||||
custom_styles/panel = SubResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ButtonClear" type="Button" parent="PanelLog"]
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = -48.0
|
||||
margin_top = -25.0
|
||||
margin_right = -5.0
|
||||
margin_bottom = -5.0
|
||||
focus_mode = 0
|
||||
text = "clear"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="CheckBoxScroll" type="CheckBox" parent="PanelLog"]
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = -150.0
|
||||
margin_top = -27.0
|
||||
margin_right = -54.0
|
||||
margin_bottom = -3.0
|
||||
focus_mode = 0
|
||||
pressed = true
|
||||
text = "auto-scroll"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ScrollLog" type="ScrollContainer" parent="PanelLog"]
|
||||
margin_left = 10.0
|
||||
margin_top = 5.0
|
||||
margin_right = 418.0
|
||||
margin_bottom = 94.0
|
||||
scroll_horizontal_enabled = false
|
||||
script = ExtResource( 11 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
auto_scroll = true
|
||||
|
||||
[node name="VBoxLog" type="VBoxContainer" parent="PanelLog/ScrollLog"]
|
||||
margin_right = 408.0
|
||||
margin_bottom = 89.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
alignment = 2
|
||||
script = ExtResource( 10 )
|
||||
|
||||
[node name="LabelLog" type="Label" parent="PanelLog/ScrollLog/VBoxLog"]
|
||||
margin_top = 75.0
|
||||
margin_right = 408.0
|
||||
margin_bottom = 89.0
|
||||
text = "Log start"
|
||||
valign = 2
|
||||
autowrap = true
|
||||
max_lines_visible = 5
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
[connection signal="pressed" from="PanelLog/ButtonClear" to="PanelLog/ScrollLog/VBoxLog" method="clear"]
|
||||
[connection signal="toggled" from="PanelLog/CheckBoxScroll" to="PanelLog/ScrollLog" method="set_auto_scroll"]
|
||||
126
2d/physics_tests/project.godot
Normal file
@@ -0,0 +1,126 @@
|
||||
; Engine configuration file.
|
||||
; It's best edited using the editor UI and not directly,
|
||||
; since the parameters that go here are not all obvious.
|
||||
;
|
||||
; Format:
|
||||
; [section] ; section goes between []
|
||||
; param=value ; assign values to parameters
|
||||
|
||||
config_version=4
|
||||
|
||||
_global_script_classes=[ {
|
||||
"base": "MenuButton",
|
||||
"class": "OptionMenu",
|
||||
"language": "GDScript",
|
||||
"path": "res://utils/option_menu.gd"
|
||||
}, {
|
||||
"base": "Node2D",
|
||||
"class": "Test",
|
||||
"language": "GDScript",
|
||||
"path": "res://test.gd"
|
||||
}, {
|
||||
"base": "Test",
|
||||
"class": "TestCharacter",
|
||||
"language": "GDScript",
|
||||
"path": "res://tests/functional/test_character.gd"
|
||||
} ]
|
||||
_global_script_class_icons={
|
||||
"OptionMenu": "",
|
||||
"Test": "",
|
||||
"TestCharacter": ""
|
||||
}
|
||||
|
||||
[application]
|
||||
|
||||
config/name="2D Physics Tests"
|
||||
run/main_scene="res://main.tscn"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[autoload]
|
||||
|
||||
Log="*res://utils/system_log.gd"
|
||||
System="*res://utils/system.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
gdscript/warnings/return_value_discarded=false
|
||||
|
||||
[display]
|
||||
|
||||
window/dpi/allow_hidpi=true
|
||||
window/stretch/mode="2d"
|
||||
window/stretch/aspect="expand"
|
||||
|
||||
[input]
|
||||
|
||||
ui_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [ ]
|
||||
}
|
||||
ui_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [ ]
|
||||
}
|
||||
ui_up={
|
||||
"deadzone": 0.5,
|
||||
"events": [ ]
|
||||
}
|
||||
ui_down={
|
||||
"deadzone": 0.5,
|
||||
"events": [ ]
|
||||
}
|
||||
toggle_full_screen={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":70,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
exit={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
toggle_debug_collision={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":67,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
restart_test={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":82,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
toggle_pause={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":80,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
character_left={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
character_right={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
character_jump={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null)
|
||||
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[memory]
|
||||
|
||||
limits/message_queue/max_size_kb=10240
|
||||
|
||||
[rendering]
|
||||
|
||||
quality/driver/driver_name="GLES2"
|
||||
vram_compression/import_etc=true
|
||||
vram_compression/import_etc2=false
|
||||
environment/default_clear_color=Color( 0.184314, 0.184314, 0.184314, 1 )
|
||||
quality/filters/msaa=2
|
||||
0
2d/physics_tests/screenshots/.gdignore
Normal file
BIN
2d/physics_tests/screenshots/screenshot.png
Normal file
|
After Width: | Height: | Size: 162 KiB |
151
2d/physics_tests/test.gd
Normal file
@@ -0,0 +1,151 @@
|
||||
class_name Test
|
||||
extends Node2D
|
||||
|
||||
|
||||
signal wait_done()
|
||||
|
||||
export var _enable_debug_collision = true
|
||||
|
||||
var _timer
|
||||
var _timer_started = false
|
||||
|
||||
var _wait_physics_ticks_counter = 0
|
||||
|
||||
class Circle2D:
|
||||
extends Node2D
|
||||
var center
|
||||
var radius
|
||||
var color
|
||||
|
||||
func _draw():
|
||||
draw_circle(center, radius, color)
|
||||
|
||||
var _drawn_nodes = []
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
if not _enable_debug_collision:
|
||||
get_tree().debug_collisions_hint = false
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if _wait_physics_ticks_counter > 0:
|
||||
_wait_physics_ticks_counter -= 1
|
||||
if _wait_physics_ticks_counter == 0:
|
||||
emit_signal("wait_done")
|
||||
|
||||
|
||||
func add_line(pos_start, pos_end, color):
|
||||
var line = Line2D.new()
|
||||
line.points = [pos_start, pos_end]
|
||||
line.width = 1.5
|
||||
line.default_color = color
|
||||
_drawn_nodes.push_back(line)
|
||||
add_child(line)
|
||||
|
||||
|
||||
func add_circle(pos, radius, color):
|
||||
var circle = Circle2D.new()
|
||||
circle.center = pos
|
||||
circle.radius = radius
|
||||
circle.color = color
|
||||
_drawn_nodes.push_back(circle)
|
||||
add_child(circle)
|
||||
|
||||
|
||||
func add_shape(shape, transform, color):
|
||||
var collision = CollisionShape2D.new()
|
||||
collision.shape = shape
|
||||
collision.transform = transform
|
||||
collision.modulate = color
|
||||
_drawn_nodes.push_back(collision)
|
||||
add_child(collision)
|
||||
|
||||
|
||||
func clear_drawn_nodes():
|
||||
for node in _drawn_nodes:
|
||||
node.queue_free()
|
||||
_drawn_nodes.clear()
|
||||
|
||||
|
||||
func create_rigidbody(shape, pickable = false, transform = Transform.IDENTITY):
|
||||
var collision = CollisionShape2D.new()
|
||||
collision.shape = shape
|
||||
collision.transform = transform
|
||||
|
||||
var body = RigidBody2D.new()
|
||||
body.add_child(collision)
|
||||
|
||||
if pickable:
|
||||
var script = load("res://utils/rigidbody_pick.gd")
|
||||
body.set_script(script)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
func create_rigidbody_collision(collision, pickable = false, transform = Transform.IDENTITY):
|
||||
var collision_copy = collision.duplicate()
|
||||
collision_copy.transform = transform
|
||||
|
||||
if collision is CollisionShape2D:
|
||||
collision_copy.shape = collision.shape.duplicate()
|
||||
|
||||
var body = RigidBody2D.new()
|
||||
body.add_child(collision_copy)
|
||||
|
||||
if pickable:
|
||||
var script = load("res://utils/rigidbody_pick.gd")
|
||||
body.set_script(script)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
func create_rigidbody_box(size, pickable = false, use_icon = false, transform = Transform.IDENTITY):
|
||||
var shape = RectangleShape2D.new()
|
||||
shape.extents = 0.5 * size
|
||||
|
||||
var body = create_rigidbody(shape, pickable, transform)
|
||||
|
||||
if use_icon:
|
||||
var texture = load("res://icon.png")
|
||||
var icon = Sprite.new()
|
||||
icon.texture = texture
|
||||
icon.scale = size / texture.get_size()
|
||||
body.add_child(icon)
|
||||
|
||||
return body
|
||||
|
||||
|
||||
func start_timer(timeout):
|
||||
if _timer == null:
|
||||
_timer = Timer.new()
|
||||
_timer.one_shot = true
|
||||
add_child(_timer)
|
||||
_timer.connect("timeout", self, "_on_timer_done")
|
||||
else:
|
||||
cancel_timer()
|
||||
|
||||
_timer.start(timeout)
|
||||
_timer_started = true
|
||||
|
||||
return _timer
|
||||
|
||||
|
||||
func cancel_timer():
|
||||
if _timer_started:
|
||||
_timer.paused = true
|
||||
_timer.emit_signal("timeout")
|
||||
_timer.paused = false
|
||||
|
||||
|
||||
func is_timer_canceled():
|
||||
return _timer and _timer.paused
|
||||
|
||||
|
||||
func wait_for_physics_ticks(tick_count):
|
||||
_wait_physics_ticks_counter = tick_count
|
||||
return self
|
||||
|
||||
|
||||
func _on_timer_done():
|
||||
_timer_started = false
|
||||
59
2d/physics_tests/tests.gd
Normal file
@@ -0,0 +1,59 @@
|
||||
extends Node
|
||||
|
||||
|
||||
var _tests = [
|
||||
{
|
||||
"id": "Functional Tests/Shapes",
|
||||
"path": "res://tests/functional/test_shapes.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Box Stack",
|
||||
"path": "res://tests/functional/test_stack.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Box Pyramid",
|
||||
"path": "res://tests/functional/test_pyramid.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Collision Pairs",
|
||||
"path": "res://tests/functional/test_collision_pairs.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Character - Slopes",
|
||||
"path": "res://tests/functional/test_character_slopes.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Character - Tilemap",
|
||||
"path": "res://tests/functional/test_character_tilemap.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Character - Pixels",
|
||||
"path": "res://tests/functional/test_character_pixels.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/One Way Collision",
|
||||
"path": "res://tests/functional/test_one_way_collision.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Joints",
|
||||
"path": "res://tests/functional/test_joints.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Functional Tests/Raycasting",
|
||||
"path": "res://tests/functional/test_raycasting.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Performance Tests/Broadphase",
|
||||
"path": "res://tests/performance/test_perf_broadphase.tscn",
|
||||
},
|
||||
{
|
||||
"id": "Performance Tests/Contacts",
|
||||
"path": "res://tests/performance/test_perf_contacts.tscn",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
func _ready():
|
||||
var test_menu = $TestsMenu
|
||||
for test in _tests:
|
||||
test_menu.add_test(test.id, test.path)
|
||||
10
2d/physics_tests/tests/dynamic_box.tscn
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 20, 20 )
|
||||
|
||||
[node name="StackBox" type="RigidBody2D"]
|
||||
position = Vector2( -180, -20 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
|
||||
shape = SubResource( 1 )
|
||||
165
2d/physics_tests/tests/functional/test_character.gd
Normal file
@@ -0,0 +1,165 @@
|
||||
extends Test
|
||||
class_name TestCharacter
|
||||
|
||||
|
||||
enum E_BodyType {
|
||||
RIGID_BODY,
|
||||
KINEMATIC_BODY,
|
||||
KINEMATIC_BODY_RAY_SHAPE,
|
||||
}
|
||||
|
||||
const OPTION_OBJECT_TYPE_RIGIDBODY = "Object type/Rigid body (1)"
|
||||
const OPTION_OBJECT_TYPE_KINEMATIC = "Object type/Kinematic body (2)"
|
||||
const OPTION_OBJECT_TYPE_KINEMATIC_RAYSHAPE = "Object type/Kinematic body with ray shape (3)"
|
||||
|
||||
const OPTION_MOVE_KINEMATIC_SNAP = "Move Options/Use snap (Kinematic only)"
|
||||
const OPTION_MOVE_KINEMATIC_STOP_ON_SLOPE = "Move Options/Use stop on slope (Kinematic only)"
|
||||
|
||||
export(Vector2) var _initial_velocity = Vector2.ZERO
|
||||
export(Vector2) var _constant_velocity = Vector2.ZERO
|
||||
export(float) var _motion_speed = 400.0
|
||||
export(float) var _gravity_force = 50.0
|
||||
export(float) var _jump_force = 1000.0
|
||||
export(float) var _snap_distance = 0.0
|
||||
export(float) var _floor_max_angle = 45.0
|
||||
export(E_BodyType) var _body_type = 0
|
||||
|
||||
onready var options = $Options
|
||||
|
||||
var _use_snap = true
|
||||
var _use_stop_on_slope = true
|
||||
|
||||
var _body_parent = null
|
||||
var _rigid_body_template = null
|
||||
var _kinematic_body_template = null
|
||||
var _kinematic_body_ray_template = null
|
||||
var _moving_body = null
|
||||
|
||||
|
||||
func _ready():
|
||||
options.connect("option_selected", self, "_on_option_selected")
|
||||
options.connect("option_changed", self, "_on_option_changed")
|
||||
|
||||
_rigid_body_template = find_node("RigidBody2D")
|
||||
if _rigid_body_template:
|
||||
_body_parent = _rigid_body_template.get_parent()
|
||||
_body_parent.remove_child(_rigid_body_template)
|
||||
var enabled = _body_type == E_BodyType.RIGID_BODY
|
||||
options.add_menu_item(OPTION_OBJECT_TYPE_RIGIDBODY, true, enabled, true)
|
||||
|
||||
_kinematic_body_template = find_node("KinematicBody2D")
|
||||
if _kinematic_body_template:
|
||||
_body_parent = _kinematic_body_template.get_parent()
|
||||
_body_parent.remove_child(_kinematic_body_template)
|
||||
var enabled = _body_type == E_BodyType.KINEMATIC_BODY
|
||||
options.add_menu_item(OPTION_OBJECT_TYPE_KINEMATIC, true, enabled, true)
|
||||
|
||||
_kinematic_body_ray_template = find_node("KinematicBodyRay2D")
|
||||
if _kinematic_body_ray_template:
|
||||
_body_parent = _kinematic_body_ray_template.get_parent()
|
||||
_body_parent.remove_child(_kinematic_body_ray_template)
|
||||
var enabled = _body_type == E_BodyType.KINEMATIC_BODY_RAY_SHAPE
|
||||
options.add_menu_item(OPTION_OBJECT_TYPE_KINEMATIC_RAYSHAPE, true, enabled, true)
|
||||
|
||||
options.add_menu_item(OPTION_MOVE_KINEMATIC_SNAP, true, _use_snap)
|
||||
options.add_menu_item(OPTION_MOVE_KINEMATIC_STOP_ON_SLOPE, true, _use_stop_on_slope)
|
||||
|
||||
_start_test()
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
var label_floor = $LabelFloor
|
||||
if _moving_body:
|
||||
if _moving_body.is_on_floor():
|
||||
label_floor.text = "ON FLOOR"
|
||||
label_floor.self_modulate = Color.green
|
||||
else:
|
||||
label_floor.text = "OFF FLOOR"
|
||||
label_floor.self_modulate = Color.red
|
||||
else:
|
||||
label_floor.visible = false
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
if key_event.scancode == KEY_1:
|
||||
if _rigid_body_template:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_RIGIDBODY)
|
||||
elif key_event.scancode == KEY_2:
|
||||
if _kinematic_body_template:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_KINEMATIC)
|
||||
elif key_event.scancode == KEY_3:
|
||||
if _kinematic_body_ray_template:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_KINEMATIC_RAYSHAPE)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
if _rigid_body_template:
|
||||
_rigid_body_template.free()
|
||||
if _kinematic_body_template:
|
||||
_kinematic_body_template.free()
|
||||
if _kinematic_body_ray_template:
|
||||
_kinematic_body_ray_template.free()
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_OBJECT_TYPE_RIGIDBODY:
|
||||
_body_type = E_BodyType.RIGID_BODY
|
||||
_start_test()
|
||||
OPTION_OBJECT_TYPE_KINEMATIC:
|
||||
_body_type = E_BodyType.KINEMATIC_BODY
|
||||
_start_test()
|
||||
OPTION_OBJECT_TYPE_KINEMATIC_RAYSHAPE:
|
||||
_body_type = E_BodyType.KINEMATIC_BODY_RAY_SHAPE
|
||||
_start_test()
|
||||
|
||||
|
||||
func _on_option_changed(option, checked):
|
||||
match option:
|
||||
OPTION_MOVE_KINEMATIC_SNAP:
|
||||
_use_snap = checked
|
||||
_start_test()
|
||||
OPTION_MOVE_KINEMATIC_STOP_ON_SLOPE:
|
||||
_use_stop_on_slope = checked
|
||||
_start_test()
|
||||
|
||||
|
||||
func _start_test():
|
||||
cancel_timer()
|
||||
|
||||
if _moving_body:
|
||||
_body_parent.remove_child(_moving_body)
|
||||
_moving_body.queue_free()
|
||||
_moving_body = null
|
||||
|
||||
var test_label = "Testing: "
|
||||
|
||||
var template = null
|
||||
match _body_type:
|
||||
E_BodyType.RIGID_BODY:
|
||||
template = _rigid_body_template
|
||||
E_BodyType.KINEMATIC_BODY:
|
||||
template = _kinematic_body_template
|
||||
E_BodyType.KINEMATIC_BODY_RAY_SHAPE:
|
||||
template = _kinematic_body_ray_template
|
||||
|
||||
test_label += template.name
|
||||
_moving_body = template.duplicate()
|
||||
_body_parent.add_child(_moving_body)
|
||||
|
||||
_moving_body._initial_velocity = _initial_velocity
|
||||
_moving_body._constant_velocity = _constant_velocity
|
||||
|
||||
_moving_body._motion_speed = _motion_speed
|
||||
_moving_body._gravity_force = _gravity_force
|
||||
_moving_body._jump_force = _jump_force
|
||||
|
||||
if _moving_body is KinematicBody2D:
|
||||
if _use_snap:
|
||||
_moving_body._snap = Vector2(0, _snap_distance)
|
||||
_moving_body._stop_on_slope = _use_stop_on_slope
|
||||
_moving_body._floor_max_angle = _floor_max_angle
|
||||
|
||||
$LabelTestType.text = test_label
|
||||
151
2d/physics_tests/tests/functional/test_character_pixels.gd
Normal file
@@ -0,0 +1,151 @@
|
||||
extends TestCharacter
|
||||
|
||||
|
||||
const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)"
|
||||
const OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP = "Test Cases/Floor detection (Kinematic Body)"
|
||||
const OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES = "Test Cases/Floor detection with motion changes (Kinematic Body)"
|
||||
|
||||
const MOTION_CHANGES_DIR = Vector2(1.0, 1.0)
|
||||
const MOTION_CHANGES_SPEEDS = [0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0]
|
||||
|
||||
var _test_floor_detection = false
|
||||
var _test_motion_changes = false
|
||||
var _floor_detected = false
|
||||
var _floor_lost = false
|
||||
|
||||
var _failed_reason = ""
|
||||
|
||||
|
||||
func _ready():
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL)
|
||||
options.add_menu_item(OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP)
|
||||
options.add_menu_item(OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES)
|
||||
|
||||
func _physics_process(_delta):
|
||||
if _moving_body:
|
||||
if _moving_body.is_on_floor():
|
||||
_floor_detected = true
|
||||
elif _floor_detected:
|
||||
_floor_lost = true
|
||||
if _test_motion_changes:
|
||||
Log.print_log("Floor lost.")
|
||||
|
||||
if _test_motion_changes:
|
||||
var speed_count = MOTION_CHANGES_SPEEDS.size()
|
||||
var speed_index = randi() % speed_count
|
||||
var speed = MOTION_CHANGES_SPEEDS[speed_index]
|
||||
var velocity = speed * MOTION_CHANGES_DIR
|
||||
_moving_body._constant_velocity = velocity
|
||||
#Log.print_log("Velocity: %s" % velocity)
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
if key_event.scancode == KEY_0:
|
||||
_on_option_selected(OPTION_TEST_CASE_ALL)
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_TEST_CASE_ALL:
|
||||
_test_all()
|
||||
OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP:
|
||||
_start_test_case(option)
|
||||
return
|
||||
OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES:
|
||||
_start_test_case(option)
|
||||
return
|
||||
|
||||
._on_option_selected(option)
|
||||
|
||||
|
||||
func _start_test_case(option):
|
||||
Log.print_log("* Starting " + option)
|
||||
|
||||
match option:
|
||||
OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP:
|
||||
_test_floor_detection = true
|
||||
_test_motion_changes = false
|
||||
_use_snap = false
|
||||
_body_type = E_BodyType.KINEMATIC_BODY
|
||||
_start_test()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_set_result(not _floor_lost)
|
||||
OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES:
|
||||
_test_floor_detection = true
|
||||
_test_motion_changes = true
|
||||
_use_snap = false
|
||||
_body_type = E_BodyType.KINEMATIC_BODY
|
||||
_start_test()
|
||||
|
||||
yield(start_timer(4.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
_test_motion_changes = false
|
||||
return
|
||||
|
||||
_test_motion_changes = false
|
||||
_moving_body._constant_velocity = Vector2.ZERO
|
||||
|
||||
_set_result(not _floor_lost)
|
||||
_:
|
||||
Log.print_error("Invalid test case.")
|
||||
|
||||
|
||||
func _test_all():
|
||||
Log.print_log("* TESTING ALL...")
|
||||
|
||||
# Test floor detection with no snapping.
|
||||
yield(_start_test_case(OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
# Test floor detection with no snapping.
|
||||
# In this test case, motion alternates different speeds.
|
||||
yield(_start_test_case(OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _set_result(test_passed):
|
||||
var result = ""
|
||||
if test_passed:
|
||||
result = "PASSED"
|
||||
else:
|
||||
result = "FAILED"
|
||||
|
||||
if not test_passed and not _failed_reason.empty():
|
||||
result += _failed_reason
|
||||
else:
|
||||
result += "."
|
||||
|
||||
Log.print_log("Test %s" % result)
|
||||
|
||||
|
||||
func _start_test():
|
||||
._start_test()
|
||||
|
||||
_failed_reason = ""
|
||||
|
||||
_floor_detected = false
|
||||
_floor_lost = false
|
||||
|
||||
if _test_floor_detection:
|
||||
_failed_reason = ": floor was not detected consistently."
|
||||
if _test_motion_changes:
|
||||
# Always use the same seed for reproducible results.
|
||||
rand_seed(123456789)
|
||||
_moving_body._gravity_force = 0.0
|
||||
_moving_body._motion_speed = 0.0
|
||||
_moving_body._jump_force = 0.0
|
||||
else:
|
||||
_moving_body._initial_velocity = Vector2(30, 0)
|
||||
_test_floor_detection = false
|
||||
else:
|
||||
_test_motion_changes = false
|
||||
151
2d/physics_tests/tests/functional/test_character_pixels.tscn
Normal file
@@ -0,0 +1,151 @@
|
||||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_character_pixels.gd" type="Script" id=1]
|
||||
[ext_resource path="res://utils/rigidbody_controller.gd" type="Script" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://tests/static_scene_flat.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://utils/kinematicbody_controller.gd" type="Script" id=7]
|
||||
|
||||
[sub_resource type="PhysicsMaterial" id=1]
|
||||
friction = 0.0
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=2]
|
||||
extents = Vector2( 3, 5 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=3]
|
||||
extents = Vector2( 3, 4.9 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=4]
|
||||
extents = Vector2( 3, 3 )
|
||||
|
||||
[sub_resource type="RayShape2D" id=5]
|
||||
length = 3.0
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=6]
|
||||
extents = Vector2( 10, 2 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
_motion_speed = 30.0
|
||||
_gravity_force = 2.0
|
||||
_jump_force = 50.0
|
||||
_snap_distance = 1.0
|
||||
|
||||
[node name="ViewportContainer" type="ViewportContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
stretch = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Viewport" type="Viewport" parent="ViewportContainer"]
|
||||
size = Vector2( 128, 75 )
|
||||
handle_input_locally = false
|
||||
render_target_update_mode = 3
|
||||
|
||||
[node name="StaticSceneFlat" parent="ViewportContainer/Viewport" instance=ExtResource( 4 )]
|
||||
position = Vector2( 0, -450 )
|
||||
|
||||
[node name="RigidBody2D" type="RigidBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 30, 40 )
|
||||
collision_mask = 2147483649
|
||||
mode = 2
|
||||
physics_material_override = SubResource( 1 )
|
||||
contacts_reported = 4
|
||||
contact_monitor = true
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/RigidBody2D"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="KinematicBody2D" type="KinematicBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 30, 40 )
|
||||
collision_mask = 2147483649
|
||||
script = ExtResource( 7 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/KinematicBody2D"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="KinematicBodyRay2D" type="KinematicBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 30, 40 )
|
||||
collision_mask = 2147483649
|
||||
script = ExtResource( 7 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/KinematicBodyRay2D"]
|
||||
position = Vector2( 0, -2 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="CollisionShapeRay2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/KinematicBodyRay2D"]
|
||||
position = Vector2( 0, -1 )
|
||||
shape = SubResource( 5 )
|
||||
|
||||
[node name="Wall1" type="StaticBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 20, 40 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/Wall1"]
|
||||
rotation = 1.5708
|
||||
shape = SubResource( 6 )
|
||||
|
||||
[node name="Wall2" type="StaticBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 122, 40 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/Wall2"]
|
||||
rotation = 1.5708
|
||||
shape = SubResource( 6 )
|
||||
|
||||
[node name="Platform1" type="StaticBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 50, 44 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/Platform1"]
|
||||
shape = SubResource( 6 )
|
||||
one_way_collision = true
|
||||
|
||||
[node name="Platform2" type="StaticBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 80, 38 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="ViewportContainer/Viewport/Platform2"]
|
||||
shape = SubResource( 6 )
|
||||
|
||||
[node name="Slope" type="StaticBody2D" parent="ViewportContainer/Viewport"]
|
||||
position = Vector2( 84, 36 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionPolygon2D" parent="ViewportContainer/Viewport/Slope"]
|
||||
polygon = PoolVector2Array( 0, 0, 6, 0, 22, 16, 16, 16 )
|
||||
|
||||
[node name="LabelTestType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 79.0
|
||||
margin_right = 145.0
|
||||
margin_bottom = 93.0
|
||||
text = "Testing: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="LabelFloor" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 237.929
|
||||
margin_right = 145.0
|
||||
margin_bottom = 251.929
|
||||
text = "ON FLOOR"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelControls" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 263.291
|
||||
margin_right = 145.0
|
||||
margin_bottom = 294.291
|
||||
text = "LEFT/RIGHT - MOVE
|
||||
UP - JUMP"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
102
2d/physics_tests/tests/functional/test_character_slopes.tscn
Normal file
@@ -0,0 +1,102 @@
|
||||
[gd_scene load_steps=11 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_character.gd" type="Script" id=1]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://tests/static_scene_flat.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://utils/rigidbody_controller.gd" type="Script" id=6]
|
||||
[ext_resource path="res://utils/kinematicbody_controller.gd" type="Script" id=7]
|
||||
|
||||
[sub_resource type="PhysicsMaterial" id=1]
|
||||
friction = 0.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=2]
|
||||
radius = 32.0
|
||||
height = 32.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=3]
|
||||
radius = 32.0
|
||||
height = 32.0
|
||||
|
||||
[sub_resource type="CircleShape2D" id=4]
|
||||
radius = 32.0
|
||||
|
||||
[sub_resource type="RayShape2D" id=5]
|
||||
length = 64.0
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
_snap_distance = 32.0
|
||||
|
||||
[node name="LabelTestType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 79.0
|
||||
margin_right = 145.0
|
||||
margin_bottom = 93.0
|
||||
text = "Testing: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="LabelFloor" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 237.929
|
||||
margin_right = 145.0
|
||||
margin_bottom = 251.929
|
||||
text = "ON FLOOR"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelControls" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 263.291
|
||||
margin_right = 145.0
|
||||
margin_bottom = 294.291
|
||||
text = "LEFT/RIGHT - MOVE
|
||||
UP - JUMP"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="RigidBody2D" type="RigidBody2D" parent="."]
|
||||
position = Vector2( 100, 450 )
|
||||
collision_mask = 2147483649
|
||||
mode = 2
|
||||
physics_material_override = SubResource( 1 )
|
||||
contacts_reported = 4
|
||||
contact_monitor = true
|
||||
script = ExtResource( 6 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="KinematicBody2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 100, 450 )
|
||||
collision_mask = 2147483649
|
||||
script = ExtResource( 7 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="KinematicBody2D"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="KinematicBodyRay2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 100, 450 )
|
||||
collision_mask = 2147483649
|
||||
script = ExtResource( 7 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="KinematicBodyRay2D"]
|
||||
position = Vector2( 0, -16 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="CollisionShapeRay2D" type="CollisionShape2D" parent="KinematicBodyRay2D"]
|
||||
position = Vector2( 0, -16 )
|
||||
shape = SubResource( 5 )
|
||||
|
||||
[node name="StaticSceneFlat" parent="." instance=ExtResource( 4 )]
|
||||
position = Vector2( 0, 12 )
|
||||
|
||||
[node name="StaticBody2D" type="StaticBody2D" parent="."]
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="StaticBody2D"]
|
||||
polygon = PoolVector2Array( 171.04, 529.248, 379.275, 294.316, 506.084, 429.135, 648.26, 322.058, 868.746, 322.058, 985.282, 36.6919, 1242.91, 531.917 )
|
||||
209
2d/physics_tests/tests/functional/test_character_tilemap.gd
Normal file
@@ -0,0 +1,209 @@
|
||||
extends TestCharacter
|
||||
|
||||
|
||||
const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)"
|
||||
const OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID = "Test Cases/Jump through one-way tiles (Rigid Body)"
|
||||
const OPTION_TEST_CASE_JUMP_ONE_WAY_KINEMATIC = "Test Cases/Jump through one-way tiles (Kinematic Body)"
|
||||
const OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID = "Test Cases/Jump through one-way corner (Rigid Body)"
|
||||
const OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_KINEMATIC = "Test Cases/Jump through one-way corner (Kinematic Body)"
|
||||
const OPTION_TEST_CASE_FALL_ONE_WAY_KINEMATIC = "Test Cases/Fall and pushed on one-way tiles (Kinematic Body)"
|
||||
|
||||
var _test_jump_one_way = false
|
||||
var _test_jump_one_way_corner = false
|
||||
var _test_fall_one_way = false
|
||||
|
||||
var _extra_body = null
|
||||
|
||||
var _failed_reason = ""
|
||||
|
||||
|
||||
func _ready():
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL)
|
||||
options.add_menu_item(OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID)
|
||||
options.add_menu_item(OPTION_TEST_CASE_JUMP_ONE_WAY_KINEMATIC)
|
||||
options.add_menu_item(OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID)
|
||||
options.add_menu_item(OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_KINEMATIC)
|
||||
options.add_menu_item(OPTION_TEST_CASE_FALL_ONE_WAY_KINEMATIC)
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
if key_event.scancode == KEY_0:
|
||||
_on_option_selected(OPTION_TEST_CASE_ALL)
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_TEST_CASE_ALL:
|
||||
_test_all()
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID:
|
||||
_start_test_case(option)
|
||||
return
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_KINEMATIC:
|
||||
_start_test_case(option)
|
||||
return
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID:
|
||||
_start_test_case(option)
|
||||
return
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_KINEMATIC:
|
||||
_start_test_case(option)
|
||||
return
|
||||
OPTION_TEST_CASE_FALL_ONE_WAY_KINEMATIC:
|
||||
_start_test_case(option)
|
||||
return
|
||||
|
||||
._on_option_selected(option)
|
||||
|
||||
|
||||
func _start_test_case(option):
|
||||
Log.print_log("* Starting " + option)
|
||||
|
||||
match option:
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID:
|
||||
_body_type = E_BodyType.RIGID_BODY
|
||||
_test_jump_one_way_corner = false
|
||||
yield(_start_jump_one_way(), "completed")
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_KINEMATIC:
|
||||
_body_type = E_BodyType.KINEMATIC_BODY
|
||||
_test_jump_one_way_corner = false
|
||||
yield(_start_jump_one_way(), "completed")
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID:
|
||||
_body_type = E_BodyType.RIGID_BODY
|
||||
_test_jump_one_way_corner = true
|
||||
yield(_start_jump_one_way(), "completed")
|
||||
OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_KINEMATIC:
|
||||
_body_type = E_BodyType.KINEMATIC_BODY
|
||||
_test_jump_one_way_corner = true
|
||||
yield(_start_jump_one_way(), "completed")
|
||||
OPTION_TEST_CASE_FALL_ONE_WAY_KINEMATIC:
|
||||
_body_type = E_BodyType.KINEMATIC_BODY
|
||||
yield(_start_fall_one_way(), "completed")
|
||||
_:
|
||||
Log.print_error("Invalid test case.")
|
||||
|
||||
|
||||
func _test_all():
|
||||
Log.print_log("* TESTING ALL...")
|
||||
|
||||
# RigidBody tests.
|
||||
yield(_start_test_case(OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
yield(_start_test_case(OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
# KinematicBody tests.
|
||||
yield(_start_test_case(OPTION_TEST_CASE_JUMP_ONE_WAY_KINEMATIC), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
yield(_start_test_case(OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_KINEMATIC), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
yield(_start_test_case(OPTION_TEST_CASE_FALL_ONE_WAY_KINEMATIC), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _set_result(test_passed):
|
||||
var result = ""
|
||||
if test_passed:
|
||||
result = "PASSED"
|
||||
else:
|
||||
result = "FAILED"
|
||||
|
||||
if not test_passed and not _failed_reason.empty():
|
||||
result += _failed_reason
|
||||
else:
|
||||
result += "."
|
||||
|
||||
Log.print_log("Test %s" % result)
|
||||
|
||||
|
||||
func _start_test():
|
||||
if _extra_body:
|
||||
_body_parent.remove_child(_extra_body)
|
||||
_extra_body.queue_free()
|
||||
_extra_body = null
|
||||
|
||||
._start_test()
|
||||
|
||||
if _test_jump_one_way:
|
||||
_test_jump_one_way = false
|
||||
_moving_body._initial_velocity = Vector2(600, -1000)
|
||||
|
||||
if _test_jump_one_way_corner:
|
||||
_moving_body.position.x = 147.0
|
||||
|
||||
$JumpTargetArea2D.visible = true
|
||||
$JumpTargetArea2D/CollisionShape2D.disabled = false
|
||||
|
||||
if _test_fall_one_way:
|
||||
_test_fall_one_way = false
|
||||
|
||||
_moving_body.position.y = 350.0
|
||||
_moving_body._gravity_force = 100.0
|
||||
_moving_body._motion_speed = 0.0
|
||||
_moving_body._jump_force = 0.0
|
||||
|
||||
_extra_body = _moving_body.duplicate()
|
||||
_extra_body._gravity_force = 100.0
|
||||
_extra_body._motion_speed = 0.0
|
||||
_extra_body._jump_force = 0.0
|
||||
_extra_body.position -= Vector2(0.0, 200.0)
|
||||
_body_parent.add_child(_extra_body)
|
||||
|
||||
$FallTargetArea2D.visible = true
|
||||
$FallTargetArea2D/CollisionShape2D.disabled = false
|
||||
|
||||
|
||||
func _start_jump_one_way():
|
||||
_test_jump_one_way = true
|
||||
_start_test()
|
||||
|
||||
yield(start_timer(1.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_finalize_jump_one_way()
|
||||
|
||||
|
||||
func _start_fall_one_way():
|
||||
_test_fall_one_way = true
|
||||
_start_test()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_finalize_fall_one_way()
|
||||
|
||||
|
||||
func _finalize_jump_one_way():
|
||||
var passed = true
|
||||
if not $JumpTargetArea2D.overlaps_body(_moving_body):
|
||||
passed = false
|
||||
_failed_reason = ": the body wasn't able to jump all the way through."
|
||||
|
||||
_set_result(passed)
|
||||
|
||||
$JumpTargetArea2D.visible = false
|
||||
$JumpTargetArea2D/CollisionShape2D.disabled = true
|
||||
|
||||
|
||||
func _finalize_fall_one_way():
|
||||
var passed = true
|
||||
if $FallTargetArea2D.overlaps_body(_moving_body):
|
||||
passed = false
|
||||
_failed_reason = ": the body was pushed through the one-way collision."
|
||||
|
||||
_set_result(passed)
|
||||
|
||||
$FallTargetArea2D.visible = false
|
||||
$FallTargetArea2D/CollisionShape2D.disabled = true
|
||||
125
2d/physics_tests/tests/functional/test_character_tilemap.tscn
Normal file
@@ -0,0 +1,125 @@
|
||||
[gd_scene load_steps=12 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_character_tilemap.gd" type="Script" id=1]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://tests/static_scene_flat.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://assets/tileset/tileset.tres" type="TileSet" id=5]
|
||||
[ext_resource path="res://utils/rigidbody_controller.gd" type="Script" id=6]
|
||||
[ext_resource path="res://utils/kinematicbody_controller.gd" type="Script" id=7]
|
||||
|
||||
[sub_resource type="PhysicsMaterial" id=1]
|
||||
friction = 0.0
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=2]
|
||||
extents = Vector2( 16, 31.9 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=3]
|
||||
extents = Vector2( 16, 24 )
|
||||
|
||||
[sub_resource type="RayShape2D" id=4]
|
||||
length = 24.0
|
||||
|
||||
[sub_resource type="CircleShape2D" id=5]
|
||||
radius = 16.0
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="LabelTestType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 79.0
|
||||
margin_right = 145.0
|
||||
margin_bottom = 93.0
|
||||
text = "Testing: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="LabelFloor" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 237.929
|
||||
margin_right = 145.0
|
||||
margin_bottom = 251.929
|
||||
text = "ON FLOOR"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelControls" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 263.291
|
||||
margin_right = 145.0
|
||||
margin_bottom = 277.291
|
||||
text = "LEFT/RIGHT - MOVE
|
||||
UP - JUMP"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="RigidBody2D" type="RigidBody2D" parent="."]
|
||||
position = Vector2( 250, 460 )
|
||||
collision_mask = 2147483649
|
||||
mode = 2
|
||||
physics_material_override = SubResource( 1 )
|
||||
contacts_reported = 4
|
||||
contact_monitor = true
|
||||
script = ExtResource( 6 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="KinematicBody2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 250, 460 )
|
||||
collision_mask = 2147483649
|
||||
script = ExtResource( 7 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="KinematicBody2D"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="KinematicBodyRay2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 250, 460 )
|
||||
collision_mask = 2147483649
|
||||
script = ExtResource( 7 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="KinematicBodyRay2D"]
|
||||
position = Vector2( 0, -8 )
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="CollisionShapeRay2D" type="CollisionShape2D" parent="KinematicBodyRay2D"]
|
||||
position = Vector2( 0, 8 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="CollisionShapeRay2DLeft" type="CollisionShape2D" parent="KinematicBodyRay2D"]
|
||||
position = Vector2( -16, 8 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="CollisionShapeRay2DRight" type="CollisionShape2D" parent="KinematicBodyRay2D"]
|
||||
position = Vector2( 16, 8 )
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="JumpTargetArea2D" type="Area2D" parent="."]
|
||||
visible = false
|
||||
position = Vector2( 810, 390 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="JumpTargetArea2D"]
|
||||
shape = SubResource( 5 )
|
||||
disabled = true
|
||||
|
||||
[node name="FallTargetArea2D" type="Area2D" parent="."]
|
||||
visible = false
|
||||
position = Vector2( 250, 480 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="FallTargetArea2D"]
|
||||
shape = SubResource( 5 )
|
||||
disabled = true
|
||||
|
||||
[node name="StaticSceneFlat" parent="." instance=ExtResource( 4 )]
|
||||
position = Vector2( 0, 12 )
|
||||
|
||||
[node name="TileMap" type="TileMap" parent="."]
|
||||
tile_set = ExtResource( 5 )
|
||||
cell_size = Vector2( 32, 32 )
|
||||
format = 1
|
||||
tile_data = PoolIntArray( 458764, 5, 0, 458765, 5, 0, 458766, 5, 0, 458767, 5, 0, 458768, 5, 0, 458769, 5, 0, 458770, 5, 0, 458771, 5, 0, 524300, 5, 0, 524301, 5, 0, 524302, 5, 0, 524303, 5, 0, 524304, 5, 0, 524305, 5, 0, 524306, 5, 0, 524307, 5, 0, 589836, 5, 0, 589837, 5, 0, 589838, 5, 0, 589839, 5, 0, 589840, 5, 0, 589841, 5, 0, 589842, 5, 0, 589843, 5, 0, 655372, 5, 0, 655373, 5, 0, 655374, 5, 0, 655375, 5, 0, 655376, 5, 0, 655377, 5, 0, 655378, 5, 0, 655379, 5, 0, 720908, 5, 0, 720909, 5, 0, 720910, 5, 0, 720911, 5, 0, 720912, 5, 0, 720913, 5, 0, 720914, 5, 0, 720915, 5, 0, 720922, 0, 0, 720923, 0, 0, 720924, 0, 0, 720925, 0, 0, 786438, 5, 0, 786439, 5, 0, 786440, 5, 0, 786441, 5, 0, 786444, 5, 0, 786445, 5, 0, 786446, 5, 0, 786447, 5, 0, 786448, 5, 0, 786449, 5, 0, 786450, 5, 0, 786451, 5, 0, 851980, 5, 0, 851981, 5, 0, 851982, 5, 0, 851983, 5, 0, 851984, 5, 0, 851985, 5, 0, 851986, 5, 0, 851987, 5, 0, 851992, 0, 0, 851993, 0, 0, 851994, 0, 0, 851995, 0, 0, 917516, 5, 0, 917517, 5, 0, 917518, 5, 0, 917519, 5, 0, 917520, 5, 0, 917521, 5, 0, 917522, 5, 0, 917523, 5, 0, 983052, 5, 0, 983053, 5, 0, 983054, 5, 0, 983055, 5, 0, 983056, 5, 0, 983057, 5, 0, 983058, 5, 0, 983059, 5, 0 )
|
||||
208
2d/physics_tests/tests/functional/test_collision_pairs.gd
Normal file
@@ -0,0 +1,208 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const OPTION_TYPE_RECTANGLE = "Collision type/Rectangle (1)"
|
||||
const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)"
|
||||
const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)"
|
||||
const OPTION_TYPE_CONVEX_POLYGON = "Collision type/Convex Polygon (4)"
|
||||
const OPTION_TYPE_CONCAVE_SEGMENTS = "Collision type/Concave Segments (5)"
|
||||
|
||||
const OPTION_SHAPE_RECTANGLE = "Shape type/Rectangle"
|
||||
const OPTION_SHAPE_SPHERE = "Shape type/Sphere"
|
||||
const OPTION_SHAPE_CAPSULE = "Shape type/Capsule"
|
||||
const OPTION_SHAPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
|
||||
const OPTION_SHAPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
|
||||
const OPTION_SHAPE_CONCAVE_SEGMENTS = "Shape type/Concave Segments"
|
||||
|
||||
const OFFSET_RANGE = 120.0
|
||||
|
||||
export(Vector2) var offset = Vector2.ZERO
|
||||
|
||||
onready var options = $Options
|
||||
|
||||
var _update_collision = false
|
||||
var _collision_test_index = 0
|
||||
var _current_offset = Vector2.ZERO
|
||||
var _collision_shapes = []
|
||||
|
||||
|
||||
func _ready():
|
||||
_initialize_collision_shapes()
|
||||
|
||||
options.add_menu_item(OPTION_TYPE_RECTANGLE)
|
||||
options.add_menu_item(OPTION_TYPE_SPHERE)
|
||||
options.add_menu_item(OPTION_TYPE_CAPSULE)
|
||||
options.add_menu_item(OPTION_TYPE_CONVEX_POLYGON)
|
||||
options.add_menu_item(OPTION_TYPE_CONCAVE_SEGMENTS)
|
||||
|
||||
options.add_menu_item(OPTION_SHAPE_RECTANGLE, true, true)
|
||||
options.add_menu_item(OPTION_SHAPE_SPHERE, true, true)
|
||||
options.add_menu_item(OPTION_SHAPE_CAPSULE, true, true)
|
||||
options.add_menu_item(OPTION_SHAPE_CONVEX_POLYGON, true, true)
|
||||
options.add_menu_item(OPTION_SHAPE_CONCAVE_POLYGON, true, true)
|
||||
options.add_menu_item(OPTION_SHAPE_CONCAVE_SEGMENTS, true, true)
|
||||
|
||||
options.connect("option_selected", self, "_on_option_selected")
|
||||
options.connect("option_changed", self, "_on_option_changed")
|
||||
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
if key_event.scancode == KEY_1:
|
||||
_on_option_selected(OPTION_TYPE_RECTANGLE)
|
||||
elif key_event.scancode == KEY_2:
|
||||
_on_option_selected(OPTION_TYPE_SPHERE)
|
||||
elif key_event.scancode == KEY_3:
|
||||
_on_option_selected(OPTION_TYPE_CAPSULE)
|
||||
elif key_event.scancode == KEY_4:
|
||||
_on_option_selected(OPTION_TYPE_CONVEX_POLYGON)
|
||||
elif key_event.scancode == KEY_5:
|
||||
_on_option_selected(OPTION_TYPE_CONCAVE_SEGMENTS)
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not _update_collision:
|
||||
return
|
||||
|
||||
_update_collision = false
|
||||
|
||||
_do_collision_test()
|
||||
|
||||
|
||||
func set_h_offset(value):
|
||||
offset.x = value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func set_v_offset(value):
|
||||
offset.y = -value * OFFSET_RANGE
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _initialize_collision_shapes():
|
||||
_collision_shapes.clear()
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
var body = node as PhysicsBody2D
|
||||
var shape = body.shape_owner_get_shape(0, 0)
|
||||
shape.resource_name = node.name.substr("RigidBody".length())
|
||||
|
||||
_collision_shapes.push_back(shape)
|
||||
|
||||
|
||||
func _do_collision_test():
|
||||
clear_drawn_nodes()
|
||||
|
||||
var shape = _collision_shapes[_collision_test_index]
|
||||
|
||||
Log.print_log("* Start %s collision tests..." % shape.resource_name)
|
||||
|
||||
var shape_query = Physics2DShapeQueryParameters.new()
|
||||
shape_query.set_shape(shape)
|
||||
var shape_scale = Vector2(0.5, 0.5)
|
||||
shape_query.transform = Transform2D.IDENTITY.scaled(shape_scale)
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
if not node.visible:
|
||||
continue
|
||||
|
||||
var body = node as PhysicsBody2D
|
||||
var space_state = body.get_world_2d().direct_space_state
|
||||
|
||||
Log.print_log("* Testing: %s" % body.name)
|
||||
|
||||
var center = body.position
|
||||
|
||||
# Collision at the center inside.
|
||||
var res = _add_collision(space_state, center, shape, shape_query)
|
||||
Log.print_log("Collision center inside: %s" % ("NO HIT" if res.empty() else "HIT"))
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _add_collision(space_state, pos, shape, shape_query):
|
||||
shape_query.transform.origin = pos + offset
|
||||
var results = space_state.collide_shape(shape_query)
|
||||
|
||||
var color
|
||||
if results.empty():
|
||||
color = Color.white.darkened(0.5)
|
||||
else:
|
||||
color = Color.green
|
||||
|
||||
# Draw collision query shape.
|
||||
add_shape(shape, shape_query.transform, color)
|
||||
|
||||
# Draw contact positions.
|
||||
for contact_pos in results:
|
||||
add_circle(contact_pos, 1.0, Color.red)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_TYPE_RECTANGLE:
|
||||
_collision_test_index = _find_type_index("Rectangle")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_SPHERE:
|
||||
_collision_test_index = _find_type_index("Sphere")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CAPSULE:
|
||||
_collision_test_index = _find_type_index("Capsule")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CONVEX_POLYGON:
|
||||
_collision_test_index = _find_type_index("ConvexPolygon")
|
||||
_update_collision = true
|
||||
OPTION_TYPE_CONCAVE_SEGMENTS:
|
||||
_collision_test_index = _find_type_index("ConcaveSegments")
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _find_type_index(type_name):
|
||||
for type_index in range(_collision_shapes.size()):
|
||||
var type_shape = _collision_shapes[type_index]
|
||||
if type_shape.resource_name.find(type_name) > -1:
|
||||
return type_index
|
||||
|
||||
Log.print_error("Invalid collision type: " + type_name)
|
||||
return -1
|
||||
|
||||
|
||||
func _on_option_changed(option, checked):
|
||||
var node
|
||||
|
||||
match option:
|
||||
OPTION_SHAPE_RECTANGLE:
|
||||
node = _find_shape_node("Rectangle")
|
||||
OPTION_SHAPE_SPHERE:
|
||||
node = _find_shape_node("Sphere")
|
||||
OPTION_SHAPE_CAPSULE:
|
||||
node = _find_shape_node("Capsule")
|
||||
OPTION_SHAPE_CONVEX_POLYGON:
|
||||
node = _find_shape_node("ConvexPolygon")
|
||||
OPTION_SHAPE_CONCAVE_POLYGON:
|
||||
node = _find_shape_node("ConcavePolygon")
|
||||
OPTION_SHAPE_CONCAVE_SEGMENTS:
|
||||
node = _find_shape_node("ConcaveSegments")
|
||||
|
||||
if node:
|
||||
node.visible = checked
|
||||
node.get_child(0).disabled = not checked
|
||||
_update_collision = true
|
||||
|
||||
|
||||
func _find_shape_node(type_name):
|
||||
var node = $Shapes.find_node("RigidBody%s" % type_name)
|
||||
|
||||
if not node:
|
||||
Log.print_error("Invalid shape type: " + type_name)
|
||||
|
||||
return node
|
||||
150
2d/physics_tests/tests/functional/test_collision_pairs.tscn
Normal file
@@ -0,0 +1,150 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_collision_pairs.gd" type="Script" id=1]
|
||||
[ext_resource path="res://assets/texture/godot-head.png" type="Texture" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 40, 60 )
|
||||
|
||||
[sub_resource type="CircleShape2D" id=2]
|
||||
radius = 60.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=3]
|
||||
radius = 30.0
|
||||
height = 50.0
|
||||
|
||||
[sub_resource type="ConcavePolygonShape2D" id=4]
|
||||
segments = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 6.44476, -42.9695, 11.127, -54.3941, 11.127, -54.3941, 26.9528, -49.4309, 26.9528, -49.4309, 26.2037, -36.508, 26.2037, -36.508, 37.5346, -28.1737, 37.5346, -28.1737, 47.6282, -34.3806, 47.6282, -34.3806, 58.0427, -20.9631, 58.0427, -20.9631, 51.113, -10.2876, 51.113, -10.2876, 50.9869, 35.2694, 50.9869, 35.2694, 38.8, 47.5, 38.8, 47.5, 15.9852, 54.3613, 15.9852, 54.3613, -14.9507, 54.1845, -14.9507, 54.1845, -36.5, 48.1, -36.5, 48.1, -50.4828, 36.33, -50.4828, 36.33, -51.3668, -9.98545, -51.3668, -9.98545, -57.8889, -20.5885, -57.8889, -20.5885, -46.9473, -34.7342, -46.9473, -34.7342, -37.4014, -28.547, -37.4014, -28.547, -26.0876, -37.0323, -26.0876, -37.0323, -26.9862, -49.15, -26.9862, -49.15, -11.4152, -54.5332, -11.4152, -54.5332, -5.93512, -43.2195 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="Shapes" type="Node2D" parent="."]
|
||||
z_index = -1
|
||||
z_as_relative = false
|
||||
|
||||
[node name="RigidBodyRectangle" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 114.877, 248.76 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyRectangle"]
|
||||
rotation = -1.19206
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 314.894, 257.658 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodySphere"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 465.629, 261.204 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyCapsule"]
|
||||
rotation = -0.202458
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 613.385, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 771.159, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="RigidBodyConcaveSegments" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 930.097, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="Controls" type="VBoxContainer" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 25.3619
|
||||
margin_top = 416.765
|
||||
margin_right = 218.362
|
||||
margin_bottom = 458.765
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="OffsetH" type="HBoxContainer" parent="Controls"]
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetH"]
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset H"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetH"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
|
||||
[node name="OffsetV" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 26.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 42.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/OffsetV"]
|
||||
margin_left = 2.0
|
||||
margin_top = 1.0
|
||||
margin_right = 53.0
|
||||
margin_bottom = 15.0
|
||||
text = "Offset V"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/OffsetV"]
|
||||
margin_left = 73.0
|
||||
margin_right = 193.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 120, 0 )
|
||||
min_value = -1.0
|
||||
max_value = 1.0
|
||||
step = 0.01
|
||||
[connection signal="value_changed" from="Controls/OffsetH/HSlider" to="." method="set_h_offset"]
|
||||
[connection signal="value_changed" from="Controls/OffsetV/HSlider" to="." method="set_v_offset"]
|
||||
143
2d/physics_tests/tests/functional/test_joints.gd
Normal file
@@ -0,0 +1,143 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const OPTION_JOINT_TYPE = "Joint Type/%s Joint (%d)"
|
||||
|
||||
const OPTION_TEST_CASE_BODIES_COLLIDE = "Test case/Attached bodies collide"
|
||||
const OPTION_TEST_CASE_WORLD_ATTACHMENT = "Test case/No parent body"
|
||||
const OPTION_TEST_CASE_DYNAMIC_ATTACHMENT = "Test case/Parent body is dynamic (no gravity)"
|
||||
const OPTION_TEST_CASE_DESTROY_BODY = "Test case/Destroy attached body"
|
||||
const OPTION_TEST_CASE_CHANGE_POSITIONS = "Test case/Set body positions after added to scene"
|
||||
|
||||
const BOX_SIZE = Vector2(64, 64)
|
||||
|
||||
var _update_joint = false
|
||||
var _selected_joint = null
|
||||
|
||||
var _joint_type = PinJoint2D
|
||||
var _bodies_collide = false
|
||||
var _world_attachement = false
|
||||
var _dynamic_attachement = false
|
||||
var _destroy_body = false
|
||||
var _change_positions = false
|
||||
|
||||
var _joint_types = {}
|
||||
|
||||
|
||||
func _ready():
|
||||
var options = $Options
|
||||
|
||||
var joints = $Joints
|
||||
for joint_index in range(joints.get_child_count()):
|
||||
var joint_node = joints.get_child(joint_index)
|
||||
joint_node.visible = false
|
||||
var joint_name = joint_node.name
|
||||
var joint_short = joint_name.substr(0, joint_name.length() - 7)
|
||||
var option_name = OPTION_JOINT_TYPE % [joint_short, joint_index + 1]
|
||||
options.add_menu_item(option_name)
|
||||
_joint_types[option_name] = joint_node
|
||||
|
||||
options.add_menu_item(OPTION_TEST_CASE_BODIES_COLLIDE, true, false)
|
||||
options.add_menu_item(OPTION_TEST_CASE_WORLD_ATTACHMENT, true, false)
|
||||
options.add_menu_item(OPTION_TEST_CASE_DYNAMIC_ATTACHMENT, true, false)
|
||||
options.add_menu_item(OPTION_TEST_CASE_DESTROY_BODY, true, false)
|
||||
options.add_menu_item(OPTION_TEST_CASE_CHANGE_POSITIONS, true, false)
|
||||
|
||||
options.connect("option_selected", self, "_on_option_selected")
|
||||
options.connect("option_changed", self, "_on_option_changed")
|
||||
|
||||
_selected_joint = _joint_types.values()[0]
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if _update_joint:
|
||||
_update_joint = false
|
||||
_create_joint()
|
||||
$LabelJointType.text = "Joint Type: " + _selected_joint.name
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
var joint_index = key_event.scancode - KEY_1
|
||||
if joint_index >= 0 and joint_index < _joint_types.size():
|
||||
_selected_joint = _joint_types.values()[joint_index]
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
if _joint_types.has(option):
|
||||
_selected_joint = _joint_types[option]
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _on_option_changed(option, checked):
|
||||
match option:
|
||||
OPTION_TEST_CASE_BODIES_COLLIDE:
|
||||
_bodies_collide = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_WORLD_ATTACHMENT:
|
||||
_world_attachement = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_DYNAMIC_ATTACHMENT:
|
||||
_dynamic_attachement = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_DESTROY_BODY:
|
||||
_destroy_body = checked
|
||||
_update_joint = true
|
||||
OPTION_TEST_CASE_CHANGE_POSITIONS:
|
||||
_change_positions = checked
|
||||
_update_joint = true
|
||||
|
||||
|
||||
func _create_joint():
|
||||
cancel_timer()
|
||||
|
||||
var root = $Objects
|
||||
|
||||
while root.get_child_count():
|
||||
var last_child_index = root.get_child_count() - 1
|
||||
var last_child = root.get_child(last_child_index)
|
||||
root.remove_child(last_child)
|
||||
last_child.queue_free()
|
||||
|
||||
var child_body = create_rigidbody_box(BOX_SIZE, true, true)
|
||||
child_body.mode = RigidBody2D.MODE_RIGID
|
||||
if _change_positions:
|
||||
root.add_child(child_body)
|
||||
child_body.position = Vector2(0.0, 40)
|
||||
else:
|
||||
child_body.position = Vector2(0.0, 40)
|
||||
root.add_child(child_body)
|
||||
|
||||
var parent_body = null
|
||||
if not _world_attachement:
|
||||
parent_body = create_rigidbody_box(BOX_SIZE, true, true)
|
||||
if _dynamic_attachement:
|
||||
parent_body.mode = RigidBody2D.MODE_RIGID
|
||||
parent_body.gravity_scale = 0.0
|
||||
child_body.gravity_scale = 0.0
|
||||
else:
|
||||
parent_body.mode = RigidBody2D.MODE_STATIC
|
||||
if _change_positions:
|
||||
root.add_child(parent_body)
|
||||
parent_body.position = Vector2(0.0, -40)
|
||||
else:
|
||||
parent_body.position = Vector2(0.0, -40)
|
||||
root.add_child(parent_body)
|
||||
|
||||
var joint = _selected_joint.duplicate()
|
||||
joint.visible = true
|
||||
joint.disable_collision = not _bodies_collide
|
||||
if parent_body:
|
||||
joint.node_a = parent_body.get_path()
|
||||
joint.node_b = child_body.get_path()
|
||||
root.add_child(joint)
|
||||
|
||||
if _destroy_body:
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
child_body.queue_free()
|
||||
31
2d/physics_tests/tests/functional/test_joints.tscn
Normal file
@@ -0,0 +1,31 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_joints.gd" type="Script" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=4]
|
||||
|
||||
[node name="JointTest2D" type="Node2D"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="LabelJointType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 79.0
|
||||
margin_right = 145.0
|
||||
margin_bottom = 93.0
|
||||
text = "Joint Type: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 4 )]
|
||||
|
||||
[node name="Joints" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 200 )
|
||||
|
||||
[node name="PinJoint2D" type="PinJoint2D" parent="Joints"]
|
||||
|
||||
[node name="DampedSpringJoint2D" type="DampedSpringJoint2D" parent="Joints"]
|
||||
|
||||
[node name="GrooveJoint2D" type="GrooveJoint2D" parent="Joints"]
|
||||
|
||||
[node name="Objects" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 200 )
|
||||
497
2d/physics_tests/tests/functional/test_one_way_collision.gd
Normal file
@@ -0,0 +1,497 @@
|
||||
extends Test
|
||||
tool
|
||||
|
||||
|
||||
signal all_tests_done()
|
||||
signal test_done()
|
||||
|
||||
const OPTION_OBJECT_TYPE_RIGIDBODY = "Object type/Rigid body (1)"
|
||||
const OPTION_OBJECT_TYPE_KINEMATIC = "Object type/Kinematic body (2)"
|
||||
|
||||
const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)"
|
||||
const OPTION_TEST_CASE_ALL_RIGID = "Test Cases/All Rigid Body tests"
|
||||
const OPTION_TEST_CASE_ALL_KINEMATIC = "Test Cases/All Kinematic Body tests"
|
||||
const OPTION_TEST_CASE_ALL_ANGLES_RIGID = "Test Cases/Around the clock (Rigid Body)"
|
||||
const OPTION_TEST_CASE_ALL_ANGLES_KINEMATIC = "Test Cases/Around the clock (Kinematic Body)"
|
||||
const OPTION_TEST_CASE_MOVING_PLATFORM_RIGID = "Test Cases/Moving Platform (Rigid Body)"
|
||||
const OPTION_TEST_CASE_MOVING_PLATFORM_KINEMATIC = "Test Cases/Moving Platform (Kinematic Body)"
|
||||
|
||||
const TEST_ALL_ANGLES_STEP = 15.0
|
||||
const TEST_ALL_ANGLES_MAX = 344.0
|
||||
|
||||
export(float, 32, 128, 0.1) var _platform_size = 64.0 setget _set_platform_size
|
||||
export(float, 0, 360, 0.1) var _platform_angle = 0.0 setget _set_platform_angle
|
||||
export(float) var _platform_speed = 0.0
|
||||
export(float, 0, 360, 0.1) var _body_angle = 0.0 setget _set_rigidbody_angle
|
||||
export(Vector2) var _body_velocity = Vector2(400.0, 0.0)
|
||||
export(bool) var _use_kinematic_body = false
|
||||
|
||||
onready var options = $Options
|
||||
|
||||
var _rigid_body_template = null
|
||||
var _kinematic_body_template = null
|
||||
var _moving_body = null
|
||||
|
||||
var _platform_template = null
|
||||
var _platform_body = null
|
||||
var _platform_velocity = Vector2.ZERO
|
||||
|
||||
var _contact_detected = false
|
||||
var _target_entered = false
|
||||
var _test_passed = false
|
||||
var _test_step = 0
|
||||
|
||||
var _test_all_angles = false
|
||||
var _lock_controls = false
|
||||
|
||||
var _test_canceled = false
|
||||
|
||||
|
||||
func _ready():
|
||||
if not Engine.editor_hint:
|
||||
options.add_menu_item(OPTION_OBJECT_TYPE_RIGIDBODY, true, not _use_kinematic_body, true)
|
||||
options.add_menu_item(OPTION_OBJECT_TYPE_KINEMATIC, true, _use_kinematic_body, true)
|
||||
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL)
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL_RIGID)
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL_KINEMATIC)
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL_ANGLES_RIGID)
|
||||
options.add_menu_item(OPTION_TEST_CASE_ALL_ANGLES_KINEMATIC)
|
||||
options.add_menu_item(OPTION_TEST_CASE_MOVING_PLATFORM_RIGID)
|
||||
options.add_menu_item(OPTION_TEST_CASE_MOVING_PLATFORM_KINEMATIC)
|
||||
|
||||
options.connect("option_selected", self, "_on_option_selected")
|
||||
|
||||
$Controls/PlatformSize/HSlider.value = _platform_size
|
||||
$Controls/PlatformAngle/HSlider.value = _platform_angle
|
||||
$Controls/BodyAngle/HSlider.value = _body_angle
|
||||
|
||||
$TargetArea2D.connect("body_entered", self, "_on_target_entered")
|
||||
$Timer.connect("timeout", self, "_on_timeout")
|
||||
|
||||
_rigid_body_template = $RigidBody2D
|
||||
remove_child(_rigid_body_template)
|
||||
|
||||
_kinematic_body_template = $KinematicBody2D
|
||||
remove_child(_kinematic_body_template)
|
||||
|
||||
_platform_template = $OneWayKinematicBody2D
|
||||
remove_child(_platform_template)
|
||||
|
||||
_start_test()
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if not Engine.editor_hint:
|
||||
if Input.is_action_just_pressed("ui_accept"):
|
||||
_reset_test(false)
|
||||
|
||||
|
||||
func _physics_process(delta):
|
||||
if not Engine.editor_hint:
|
||||
if _moving_body and not _contact_detected:
|
||||
if _use_kinematic_body:
|
||||
var collision = _moving_body.move_and_collide(_body_velocity * delta, false)
|
||||
if collision:
|
||||
var colliding_body = collision.collider
|
||||
_on_contact_detected(colliding_body)
|
||||
|
||||
if _platform_body and _platform_velocity != Vector2.ZERO:
|
||||
var motion = _platform_velocity * delta
|
||||
_platform_body.global_position += motion
|
||||
|
||||
|
||||
func _input(event):
|
||||
var key_event = event as InputEventKey
|
||||
if key_event and not key_event.pressed:
|
||||
if key_event.scancode == KEY_0:
|
||||
_on_option_selected(OPTION_TEST_CASE_ALL)
|
||||
if key_event.scancode == KEY_1:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_RIGIDBODY)
|
||||
elif key_event.scancode == KEY_2:
|
||||
_on_option_selected(OPTION_OBJECT_TYPE_KINEMATIC)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
if not Engine.editor_hint:
|
||||
_rigid_body_template.free()
|
||||
_kinematic_body_template.free()
|
||||
_platform_template.free()
|
||||
|
||||
|
||||
func _set_platform_size(value, reset = true):
|
||||
if _lock_controls:
|
||||
return
|
||||
if value == _platform_size:
|
||||
return
|
||||
_platform_size = value
|
||||
if is_inside_tree():
|
||||
if Engine.editor_hint:
|
||||
$OneWayKinematicBody2D/CollisionShape2D.shape.extents.x = value
|
||||
else:
|
||||
var platform_collision = _platform_template.get_child(0)
|
||||
platform_collision.shape.extents.x = value
|
||||
if _platform_body:
|
||||
# Bug: need to re-add when changing shape.
|
||||
var child_index = _platform_body.get_index()
|
||||
remove_child(_platform_body)
|
||||
add_child(_platform_body)
|
||||
move_child(_platform_body, child_index)
|
||||
if reset:
|
||||
_reset_test()
|
||||
|
||||
|
||||
func _set_platform_angle(value, reset = true):
|
||||
if _lock_controls:
|
||||
return
|
||||
if value == _platform_angle:
|
||||
return
|
||||
_platform_angle = value
|
||||
if is_inside_tree():
|
||||
if Engine.editor_hint:
|
||||
$OneWayKinematicBody2D.rotation = deg2rad(value)
|
||||
else:
|
||||
if _platform_body:
|
||||
_platform_body.rotation = deg2rad(value)
|
||||
_platform_template.rotation = deg2rad(value)
|
||||
if reset:
|
||||
_reset_test()
|
||||
|
||||
|
||||
func _set_rigidbody_angle(value, reset = true):
|
||||
if _lock_controls:
|
||||
return
|
||||
if value == _body_angle:
|
||||
return
|
||||
_body_angle = value
|
||||
if is_inside_tree():
|
||||
if Engine.editor_hint:
|
||||
$RigidBody2D.rotation = deg2rad(value)
|
||||
$KinematicBody2D.rotation = deg2rad(value)
|
||||
else:
|
||||
if _moving_body:
|
||||
_moving_body.rotation = deg2rad(value)
|
||||
_rigid_body_template.rotation = deg2rad(value)
|
||||
_kinematic_body_template.rotation = deg2rad(value)
|
||||
if reset:
|
||||
_reset_test()
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
match option:
|
||||
OPTION_OBJECT_TYPE_KINEMATIC:
|
||||
_use_kinematic_body = true
|
||||
_reset_test()
|
||||
OPTION_OBJECT_TYPE_RIGIDBODY:
|
||||
_use_kinematic_body = false
|
||||
_reset_test()
|
||||
OPTION_TEST_CASE_ALL:
|
||||
_test_all()
|
||||
OPTION_TEST_CASE_ALL_RIGID:
|
||||
_test_all_rigid_body()
|
||||
OPTION_TEST_CASE_ALL_KINEMATIC:
|
||||
_test_all_kinematic_body()
|
||||
OPTION_TEST_CASE_ALL_ANGLES_RIGID:
|
||||
_use_kinematic_body = false
|
||||
_test_all_angles = true
|
||||
_reset_test(false)
|
||||
OPTION_TEST_CASE_ALL_ANGLES_KINEMATIC:
|
||||
_use_kinematic_body = true
|
||||
_test_all_angles = true
|
||||
_reset_test(false)
|
||||
OPTION_TEST_CASE_MOVING_PLATFORM_RIGID:
|
||||
_use_kinematic_body = false
|
||||
_test_moving_platform()
|
||||
OPTION_TEST_CASE_MOVING_PLATFORM_KINEMATIC:
|
||||
_use_kinematic_body = true
|
||||
_test_moving_platform()
|
||||
|
||||
|
||||
func _start_test_case(option):
|
||||
Log.print_log("* Starting " + option)
|
||||
|
||||
_on_option_selected(option)
|
||||
|
||||
yield(self, "all_tests_done")
|
||||
|
||||
|
||||
func _wait_for_test():
|
||||
_reset_test()
|
||||
|
||||
yield(self, "test_done")
|
||||
|
||||
|
||||
func _test_all_rigid_body():
|
||||
Log.print_log("* All RigidBody test cases...")
|
||||
|
||||
_set_platform_size(64.0, false)
|
||||
_set_rigidbody_angle(0.0, false)
|
||||
yield(_start_test_case(OPTION_TEST_CASE_ALL_ANGLES_RIGID), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_set_platform_size(64.0, false)
|
||||
_set_rigidbody_angle(45.0, false)
|
||||
yield(_start_test_case(OPTION_TEST_CASE_ALL_ANGLES_RIGID), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_set_platform_size(32.0, false)
|
||||
_set_rigidbody_angle(45.0, false)
|
||||
yield(_start_test_case(OPTION_TEST_CASE_ALL_ANGLES_RIGID), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
yield(_start_test_case(OPTION_TEST_CASE_MOVING_PLATFORM_RIGID), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
|
||||
func _test_all_kinematic_body():
|
||||
Log.print_log("* All KinematicBody test cases...")
|
||||
|
||||
_set_platform_size(64.0, false)
|
||||
_set_rigidbody_angle(0.0, false)
|
||||
yield(_start_test_case(OPTION_TEST_CASE_ALL_ANGLES_KINEMATIC), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_set_platform_size(64.0, false)
|
||||
_set_rigidbody_angle(45.0, false)
|
||||
yield(_start_test_case(OPTION_TEST_CASE_ALL_ANGLES_KINEMATIC), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_set_platform_size(32.0, false)
|
||||
_set_rigidbody_angle(45.0, false)
|
||||
yield(_start_test_case(OPTION_TEST_CASE_ALL_ANGLES_KINEMATIC), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
yield(_start_test_case(OPTION_TEST_CASE_MOVING_PLATFORM_KINEMATIC), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
|
||||
func _test_moving_platform():
|
||||
Log.print_log("* Start moving platform tests")
|
||||
|
||||
Log.print_log("* Platform moving away from body...")
|
||||
_set_platform_size(64.0, false)
|
||||
_set_rigidbody_angle(0.0, false)
|
||||
_platform_speed = 50.0
|
||||
|
||||
_set_platform_angle(90.0, false)
|
||||
yield(_wait_for_test(), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_set_platform_angle(-90.0, false)
|
||||
yield(_wait_for_test(), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
Log.print_log("* Platform moving towards body...")
|
||||
_set_platform_size(64.0, false)
|
||||
_set_rigidbody_angle(0.0, false)
|
||||
_platform_speed = -50.0
|
||||
|
||||
_set_platform_angle(90.0, false)
|
||||
yield(_wait_for_test(), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_set_platform_angle(-90.0, false)
|
||||
yield(_wait_for_test(), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
_platform_speed = 0.0
|
||||
emit_signal("all_tests_done")
|
||||
|
||||
|
||||
func _test_all():
|
||||
Log.print_log("* TESTING ALL...")
|
||||
|
||||
yield(_test_all_rigid_body(), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
yield(_test_all_kinematic_body(), "completed")
|
||||
if _test_canceled:
|
||||
return
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _start_test():
|
||||
var test_label = "Testing: "
|
||||
|
||||
var platform_angle = _platform_template.rotation
|
||||
if _platform_body:
|
||||
platform_angle = _platform_body.rotation
|
||||
remove_child(_platform_body)
|
||||
_platform_body.queue_free()
|
||||
_platform_body = null
|
||||
|
||||
_platform_body = _platform_template.duplicate()
|
||||
_platform_body.rotation = platform_angle
|
||||
add_child(_platform_body)
|
||||
|
||||
if _use_kinematic_body:
|
||||
test_label += _kinematic_body_template.name
|
||||
_moving_body = _kinematic_body_template.duplicate()
|
||||
else:
|
||||
test_label += _rigid_body_template.name
|
||||
_moving_body = _rigid_body_template.duplicate()
|
||||
_moving_body.linear_velocity = _body_velocity
|
||||
_moving_body.connect("body_entered", self, "_on_contact_detected")
|
||||
add_child(_moving_body)
|
||||
|
||||
if _platform_speed != 0.0:
|
||||
var platform_pos = _platform_body.global_position
|
||||
var body_pos = _moving_body.global_position
|
||||
var dir = (platform_pos - body_pos).normalized()
|
||||
_platform_velocity = dir * _platform_speed
|
||||
else:
|
||||
_platform_velocity = Vector2.ZERO
|
||||
|
||||
if _test_all_angles:
|
||||
test_label += " - All angles"
|
||||
|
||||
$LabelTestType.text = test_label
|
||||
|
||||
_contact_detected = false
|
||||
_target_entered = false
|
||||
_test_passed = false
|
||||
_test_step += 1
|
||||
|
||||
$Timer.start()
|
||||
|
||||
$LabelResult.text = "..."
|
||||
$LabelResult.self_modulate = Color.white
|
||||
|
||||
|
||||
func _reset_test(cancel_test = true):
|
||||
_test_canceled = true
|
||||
_on_timeout()
|
||||
_test_canceled = false
|
||||
|
||||
_test_step = 0
|
||||
|
||||
if _test_all_angles:
|
||||
if cancel_test:
|
||||
Log.print_log("*** Stop around the clock tests")
|
||||
_test_all_angles = false
|
||||
emit_signal("all_tests_done")
|
||||
else:
|
||||
Log.print_log("*** Start around the clock tests")
|
||||
_platform_body.rotation = deg2rad(_platform_angle)
|
||||
_lock_controls = true
|
||||
$Controls/PlatformAngle/HSlider.value = _platform_angle
|
||||
_lock_controls = false
|
||||
|
||||
_next_test(true)
|
||||
|
||||
|
||||
func _next_test(force_start = false):
|
||||
if _moving_body:
|
||||
remove_child(_moving_body)
|
||||
_moving_body.queue_free()
|
||||
_moving_body = null
|
||||
|
||||
if _test_all_angles:
|
||||
var angle = rad2deg(_platform_body.rotation)
|
||||
if angle >= _platform_angle + TEST_ALL_ANGLES_MAX:
|
||||
_platform_body.rotation = deg2rad(_platform_angle)
|
||||
_lock_controls = true
|
||||
$Controls/PlatformAngle/HSlider.value = _platform_angle
|
||||
_lock_controls = false
|
||||
_test_all_angles = false
|
||||
Log.print_log("*** Done all angles")
|
||||
else:
|
||||
angle = _platform_angle + _test_step * TEST_ALL_ANGLES_STEP
|
||||
_platform_body.rotation = deg2rad(angle)
|
||||
_lock_controls = true
|
||||
$Controls/PlatformAngle/HSlider.value = angle
|
||||
_lock_controls = false
|
||||
_start_test()
|
||||
elif force_start:
|
||||
_start_test()
|
||||
|
||||
|
||||
func _on_contact_detected(_body):
|
||||
if _contact_detected or _target_entered:
|
||||
return
|
||||
|
||||
_contact_detected = true
|
||||
_test_passed = _should_collide()
|
||||
_set_result()
|
||||
_on_timeout()
|
||||
|
||||
|
||||
func _on_target_entered(_body):
|
||||
if _contact_detected or _target_entered:
|
||||
return
|
||||
|
||||
_target_entered = true
|
||||
_test_passed = not _should_collide()
|
||||
_set_result()
|
||||
_on_timeout()
|
||||
|
||||
|
||||
func _should_collide():
|
||||
var platform_rotation = round(rad2deg(_platform_body.rotation))
|
||||
|
||||
var angle = fposmod(platform_rotation, 360)
|
||||
return angle > 180
|
||||
|
||||
|
||||
func _on_timeout():
|
||||
cancel_timer()
|
||||
|
||||
if $Timer.is_stopped():
|
||||
return
|
||||
|
||||
$Timer.stop()
|
||||
|
||||
if _test_canceled:
|
||||
emit_signal("test_done")
|
||||
emit_signal("all_tests_done")
|
||||
return
|
||||
|
||||
if not _contact_detected and not _target_entered:
|
||||
Log.print_log("Test TIMEOUT")
|
||||
_set_result()
|
||||
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if _test_canceled:
|
||||
emit_signal("test_done")
|
||||
emit_signal("all_tests_done")
|
||||
return
|
||||
|
||||
var was_all_angles = _test_all_angles
|
||||
|
||||
_next_test()
|
||||
|
||||
emit_signal("test_done")
|
||||
|
||||
if was_all_angles and not _test_all_angles:
|
||||
emit_signal("all_tests_done")
|
||||
|
||||
|
||||
func _set_result():
|
||||
var result = ""
|
||||
if _test_passed:
|
||||
result = "PASSED"
|
||||
$LabelResult.self_modulate = Color.green
|
||||
else:
|
||||
result = "FAILED"
|
||||
$LabelResult.self_modulate = Color.red
|
||||
|
||||
$LabelResult.text = result
|
||||
|
||||
var platform_angle = rad2deg(_platform_body.rotation)
|
||||
|
||||
result += ": size=%.1f, angle=%.1f, body angle=%.1f" % [_platform_size, platform_angle, _body_angle]
|
||||
Log.print_log("Test %s" % result)
|
||||
250
2d/physics_tests/tests/functional/test_one_way_collision.tscn
Normal file
@@ -0,0 +1,250 @@
|
||||
[gd_scene load_steps=9 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_one_way_collision.gd" type="Script" id=1]
|
||||
[ext_resource path="res://icon.png" type="Texture" id=2]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://utils/label_slider_value.gd" type="Script" id=4]
|
||||
[ext_resource path="res://utils/slider.gd" type="Script" id=5]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 32, 32 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=2]
|
||||
extents = Vector2( 64, 32 )
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=3]
|
||||
extents = Vector2( 32, 32 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
_enable_debug_collision = true
|
||||
_platform_size = 64.0
|
||||
_platform_angle = 0.0
|
||||
_platform_speed = 0.0
|
||||
_body_angle = 0.0
|
||||
_body_velocity = Vector2( 400, 0 )
|
||||
_use_kinematic_body = false
|
||||
|
||||
[node name="LabelTestType" type="Label" parent="."]
|
||||
margin_left = 14.0
|
||||
margin_top = 79.0
|
||||
margin_right = 145.0
|
||||
margin_bottom = 93.0
|
||||
text = "Testing: "
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 3 )]
|
||||
|
||||
[node name="Controls" type="VBoxContainer" parent="."]
|
||||
pause_mode = 2
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 25.3619
|
||||
margin_top = 416.765
|
||||
margin_right = 265.362
|
||||
margin_bottom = 484.765
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="PlatformSize" type="HBoxContainer" parent="Controls"]
|
||||
margin_right = 432.0
|
||||
margin_bottom = 16.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/PlatformSize"]
|
||||
margin_left = 8.0
|
||||
margin_top = 1.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 15.0
|
||||
text = "Platform size"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/PlatformSize"]
|
||||
margin_left = 112.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 200, 0 )
|
||||
min_value = 32.0
|
||||
max_value = 128.0
|
||||
value = 64.0
|
||||
script = ExtResource( 5 )
|
||||
|
||||
[node name="LabelValue" type="Label" parent="Controls/PlatformSize"]
|
||||
margin_left = 332.0
|
||||
margin_top = 1.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
text = "64.0"
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="PlatformAngle" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 26.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 42.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/PlatformAngle"]
|
||||
margin_top = 1.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 15.0
|
||||
text = "Platform angle"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/PlatformAngle"]
|
||||
margin_left = 112.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 200, 0 )
|
||||
max_value = 360.0
|
||||
script = ExtResource( 5 )
|
||||
snap_step = 5.0
|
||||
|
||||
[node name="LabelValue" type="Label" parent="Controls/PlatformAngle"]
|
||||
margin_left = 332.0
|
||||
margin_top = 1.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
text = "0.0"
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="BodyAngle" type="HBoxContainer" parent="Controls"]
|
||||
margin_top = 52.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 68.0
|
||||
custom_constants/separation = 20
|
||||
alignment = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Controls/BodyAngle"]
|
||||
margin_left = 22.0
|
||||
margin_top = 1.0
|
||||
margin_right = 92.0
|
||||
margin_bottom = 15.0
|
||||
text = "Body angle"
|
||||
|
||||
[node name="HSlider" type="HSlider" parent="Controls/BodyAngle"]
|
||||
margin_left = 112.0
|
||||
margin_right = 312.0
|
||||
margin_bottom = 16.0
|
||||
rect_min_size = Vector2( 200, 0 )
|
||||
max_value = 360.0
|
||||
script = ExtResource( 5 )
|
||||
snap_step = 5.0
|
||||
|
||||
[node name="LabelValue" type="Label" parent="Controls/BodyAngle"]
|
||||
margin_left = 332.0
|
||||
margin_top = 1.0
|
||||
margin_right = 432.0
|
||||
margin_bottom = 15.0
|
||||
rect_min_size = Vector2( 100, 0 )
|
||||
text = "0.0"
|
||||
script = ExtResource( 4 )
|
||||
|
||||
[node name="LabelResultTitle" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 34.1273
|
||||
margin_top = 251.131
|
||||
margin_right = 88.1273
|
||||
margin_bottom = 265.131
|
||||
text = "RESULT: "
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelResult" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 34.1273
|
||||
margin_top = 266.131
|
||||
margin_right = 88.1273
|
||||
margin_bottom = 280.131
|
||||
text = "..."
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LabelRestart" type="Label" parent="."]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 34.1273
|
||||
margin_top = 304.841
|
||||
margin_right = 139.127
|
||||
margin_bottom = 318.841
|
||||
text = "SPACE - RESTART"
|
||||
align = 1
|
||||
valign = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Timer" type="Timer" parent="."]
|
||||
wait_time = 5.0
|
||||
one_shot = true
|
||||
|
||||
[node name="TargetArea2D" type="Area2D" parent="."]
|
||||
position = Vector2( 724, 300 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="TargetArea2D"]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="OneWayKinematicBody2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 512, 300 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="OneWayKinematicBody2D"]
|
||||
shape = SubResource( 2 )
|
||||
one_way_collision = true
|
||||
|
||||
[node name="RigidBody2D" type="RigidBody2D" parent="."]
|
||||
position = Vector2( 300, 300 )
|
||||
collision_mask = 2147483649
|
||||
gravity_scale = 0.0
|
||||
contacts_reported = 1
|
||||
contact_monitor = true
|
||||
|
||||
[node name="Sprite" type="Sprite" parent="RigidBody2D"]
|
||||
self_modulate = Color( 1, 1, 1, 0.501961 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBody2D"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="KinematicBody2D" type="KinematicBody2D" parent="."]
|
||||
position = Vector2( 300, 300 )
|
||||
collision_mask = 2147483649
|
||||
|
||||
[node name="Sprite" type="Sprite" parent="KinematicBody2D"]
|
||||
self_modulate = Color( 1, 1, 1, 0.501961 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 2 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="KinematicBody2D"]
|
||||
shape = SubResource( 3 )
|
||||
[connection signal="value_changed" from="Controls/PlatformSize/HSlider" to="." method="_set_platform_size"]
|
||||
[connection signal="value_changed" from="Controls/PlatformAngle/HSlider" to="." method="_set_platform_angle"]
|
||||
[connection signal="value_changed" from="Controls/BodyAngle/HSlider" to="." method="_set_rigidbody_angle"]
|
||||
41
2d/physics_tests/tests/functional/test_pyramid.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends Test
|
||||
|
||||
|
||||
export(int, 1, 100) var height = 10
|
||||
export(Vector2) var box_size = Vector2(40.0, 40.0)
|
||||
export(Vector2) var box_spacing = Vector2(0.0, 0.0)
|
||||
|
||||
|
||||
func _ready():
|
||||
_create_pyramid()
|
||||
|
||||
|
||||
func _create_pyramid():
|
||||
var root_node = $Pyramid
|
||||
|
||||
var template_body = create_rigidbody_box(box_size, true)
|
||||
|
||||
var pos_y = -0.5 * box_size.y - box_spacing.y
|
||||
|
||||
for level in height:
|
||||
var level_index = height - level - 1
|
||||
var num_boxes = 2 * level_index + 1
|
||||
|
||||
var row_node = Node2D.new()
|
||||
row_node.position = Vector2(0.0, pos_y)
|
||||
row_node.name = "Row%02d" % (level + 1)
|
||||
root_node.add_child(row_node)
|
||||
|
||||
var pos_x = -0.5 * (num_boxes - 1) * (box_size.x + box_spacing.x)
|
||||
|
||||
for box_index in range(num_boxes):
|
||||
var box = template_body.duplicate()
|
||||
box.position = Vector2(pos_x, 0.0)
|
||||
box.name = "Box%02d" % (box_index + 1)
|
||||
row_node.add_child(box)
|
||||
|
||||
pos_x += box_size.x + box_spacing.x
|
||||
|
||||
pos_y -= box_size.y + box_spacing.y
|
||||
|
||||
template_body.queue_free()
|
||||
12
2d/physics_tests/tests/functional/test_pyramid.tscn
Normal file
@@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_pyramid.gd" type="Script" id=1]
|
||||
[ext_resource path="res://tests/static_scene_flat.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Pyramid" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 500 )
|
||||
|
||||
[node name="StaticSceneFlat" parent="." instance=ExtResource( 2 )]
|
||||
70
2d/physics_tests/tests/functional/test_raycasting.gd
Normal file
@@ -0,0 +1,70 @@
|
||||
extends Test
|
||||
|
||||
|
||||
var _do_raycasts = false
|
||||
|
||||
|
||||
func _ready():
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_do_raycasts = true
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not _do_raycasts:
|
||||
return
|
||||
|
||||
_do_raycasts = false
|
||||
|
||||
Log.print_log("* Start Raycasting...")
|
||||
|
||||
clear_drawn_nodes()
|
||||
|
||||
for node in $Shapes.get_children():
|
||||
var body = node as PhysicsBody2D
|
||||
var space_state = body.get_world_2d().direct_space_state
|
||||
var body_name = body.name.substr("RigidBody".length())
|
||||
|
||||
Log.print_log("* Testing: %s" % body_name)
|
||||
|
||||
var center = body.position
|
||||
|
||||
# Raycast entering from the top.
|
||||
var res = _add_raycast(space_state, center - Vector2(0, 100), center)
|
||||
Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT"))
|
||||
|
||||
# Raycast exiting from inside.
|
||||
center.x -= 20
|
||||
res = _add_raycast(space_state, center, center + Vector2(0, 200))
|
||||
Log.print_log("Raycast out: %s" % ("HIT" if res else "NO HIT"))
|
||||
|
||||
# Raycast all inside.
|
||||
center.x += 40
|
||||
res = _add_raycast(space_state, center, center + Vector2(0, 40))
|
||||
Log.print_log("Raycast inside: %s" % ("HIT" if res else "NO HIT"))
|
||||
|
||||
if body.name.ends_with("ConcavePolygon"):
|
||||
# Raycast inside an internal face.
|
||||
center.x += 20
|
||||
res = _add_raycast(space_state, center, center + Vector2(0, 40))
|
||||
Log.print_log("Raycast inside face: %s" % ("HIT" if res else "NO HIT"))
|
||||
|
||||
|
||||
func _add_raycast(space_state, pos_start, pos_end):
|
||||
var result = space_state.intersect_ray(pos_start, pos_end)
|
||||
var color
|
||||
if result:
|
||||
color = Color.green
|
||||
else:
|
||||
color = Color.red.darkened(0.5)
|
||||
|
||||
# Draw raycast line.
|
||||
add_line(pos_start, pos_end, color)
|
||||
|
||||
# Draw raycast arrow.
|
||||
add_line(pos_end, pos_end + Vector2(-5, -10), color)
|
||||
add_line(pos_end, pos_end + Vector2(5, -10), color)
|
||||
|
||||
return result
|
||||
82
2d/physics_tests/tests/functional/test_raycasting.tscn
Normal file
@@ -0,0 +1,82 @@
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://assets/texture/godot-head.png" type="Texture" id=1]
|
||||
[ext_resource path="res://tests/functional/test_raycasting.gd" type="Script" id=2]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 40, 60 )
|
||||
|
||||
[sub_resource type="CircleShape2D" id=2]
|
||||
radius = 60.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=3]
|
||||
radius = 30.0
|
||||
height = 50.0
|
||||
|
||||
[sub_resource type="ConcavePolygonShape2D" id=4]
|
||||
segments = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 6.44476, -42.9695, 11.127, -54.3941, 11.127, -54.3941, 26.9528, -49.4309, 26.9528, -49.4309, 26.2037, -36.508, 26.2037, -36.508, 37.5346, -28.1737, 37.5346, -28.1737, 47.6282, -34.3806, 47.6282, -34.3806, 58.0427, -20.9631, 58.0427, -20.9631, 51.113, -10.2876, 51.113, -10.2876, 50.9869, 35.2694, 50.9869, 35.2694, 38.8, 47.5, 38.8, 47.5, 15.9852, 54.3613, 15.9852, 54.3613, -14.9507, 54.1845, -14.9507, 54.1845, -36.5, 48.1, -36.5, 48.1, -50.4828, 36.33, -50.4828, 36.33, -51.3668, -9.98545, -51.3668, -9.98545, -57.8889, -20.5885, -57.8889, -20.5885, -46.9473, -34.7342, -46.9473, -34.7342, -37.4014, -28.547, -37.4014, -28.547, -26.0876, -37.0323, -26.0876, -37.0323, -26.9862, -49.15, -26.9862, -49.15, -11.4152, -54.5332, -11.4152, -54.5332, -5.93512, -43.2195 )
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="Shapes" type="Node2D" parent="."]
|
||||
z_index = -1
|
||||
z_as_relative = false
|
||||
|
||||
[node name="RigidBodyRectangle" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 114.877, 248.76 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyRectangle"]
|
||||
rotation = -1.19206
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 314.894, 257.658 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodySphere"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 465.629, 261.204 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyCapsule"]
|
||||
rotation = -0.202458
|
||||
scale = Vector2( 1.2, 1.2 )
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 613.385, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConvexPolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 771.159, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcavePolygon"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodyConcaveSegments" type="RigidBody2D" parent="Shapes"]
|
||||
position = Vector2( 930.097, 252.771 )
|
||||
mode = 1
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
shape = SubResource( 4 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="Shapes/RigidBodyConcaveSegments"]
|
||||
modulate = Color( 1, 1, 1, 0.392157 )
|
||||
texture = ExtResource( 1 )
|
||||
66
2d/physics_tests/tests/functional/test_shapes.tscn
Normal file
@@ -0,0 +1,66 @@
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://assets/texture/godot-head.png" type="Texture" id=1]
|
||||
[ext_resource path="res://test.gd" type="Script" id=2]
|
||||
[ext_resource path="res://tests/static_scene.tscn" type="PackedScene" id=6]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 20, 30 )
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=2]
|
||||
radius = 20.0
|
||||
height = 30.0
|
||||
|
||||
[sub_resource type="CircleShape2D" id=3]
|
||||
radius = 30.0
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="DynamicShapes" type="Node2D" parent="."]
|
||||
|
||||
[node name="RigidBodyRectangle" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 96, 127 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyRectangle"]
|
||||
rotation = 0.675442
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 270.165, 139.444 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyCapsule"]
|
||||
rotation = -0.202458
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 683.614, 132.749 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 473.536, 134.336 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 919.968, 115.129 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodySphere"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="StaticScene" parent="." instance=ExtResource( 6 )]
|
||||
39
2d/physics_tests/tests/functional/test_stack.gd
Normal file
@@ -0,0 +1,39 @@
|
||||
extends Test
|
||||
|
||||
|
||||
export(int) var height = 10
|
||||
export(int) var width = 1
|
||||
export(Vector2) var box_size = Vector2(40.0, 40.0)
|
||||
export(Vector2) var box_spacing = Vector2(0.0, 0.0)
|
||||
|
||||
|
||||
func _ready():
|
||||
_create_stack()
|
||||
|
||||
|
||||
func _create_stack():
|
||||
var root_node = $Stack
|
||||
|
||||
var template_body = create_rigidbody_box(box_size, true)
|
||||
|
||||
var pos_y = -0.5 * box_size.y - box_spacing.y
|
||||
|
||||
for level in height:
|
||||
var row_node = Node2D.new()
|
||||
row_node.position = Vector2(0.0, pos_y)
|
||||
row_node.name = "Row%02d" % (level + 1)
|
||||
root_node.add_child(row_node)
|
||||
|
||||
var pos_x = -0.5 * (width - 1) * (box_size.x + box_spacing.x)
|
||||
|
||||
for box_index in range(width):
|
||||
var box = template_body.duplicate()
|
||||
box.position = Vector2(pos_x, 0.0)
|
||||
box.name = "Box%02d" % (box_index + 1)
|
||||
row_node.add_child(box)
|
||||
|
||||
pos_x += box_size.x + box_spacing.x
|
||||
|
||||
pos_y -= box_size.y + box_spacing.y
|
||||
|
||||
template_body.queue_free()
|
||||
12
2d/physics_tests/tests/functional/test_stack.tscn
Normal file
@@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://tests/functional/test_stack.gd" type="Script" id=1]
|
||||
[ext_resource path="res://tests/static_scene_flat.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Stack" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 500 )
|
||||
|
||||
[node name="StaticSceneFlat" parent="." instance=ExtResource( 2 )]
|
||||
155
2d/physics_tests/tests/performance/test_perf_broadphase.gd
Normal file
@@ -0,0 +1,155 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const BOX_SIZE = Vector2(40, 40)
|
||||
const BOX_SPACE = Vector2(50, 50)
|
||||
|
||||
export(int, 1, 1000) var row_size = 100
|
||||
export(int, 1, 1000) var column_size = 100
|
||||
|
||||
var _objects = []
|
||||
|
||||
var _log_physics = false
|
||||
var _log_physics_time = 0
|
||||
var _log_physics_time_start = 0
|
||||
|
||||
|
||||
func _ready():
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_create_objects()
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_add_objects()
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_move_objects()
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_remove_objects()
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
Log.print_log("* Done.")
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
for object in _objects:
|
||||
object.free()
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if _log_physics:
|
||||
var time = OS.get_ticks_usec()
|
||||
var time_delta = time - _log_physics_time
|
||||
var time_total = time - _log_physics_time_start
|
||||
_log_physics_time = time
|
||||
Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total])
|
||||
|
||||
|
||||
func _log_physics_start():
|
||||
_log_physics = true
|
||||
_log_physics_time_start = OS.get_ticks_usec()
|
||||
_log_physics_time = _log_physics_time_start
|
||||
|
||||
|
||||
func _log_physics_stop():
|
||||
_log_physics = false
|
||||
|
||||
|
||||
func _create_objects():
|
||||
_objects.clear()
|
||||
|
||||
Log.print_log("* Creating objects...")
|
||||
var timer = OS.get_ticks_usec()
|
||||
|
||||
var pos_x = -0.5 * (row_size - 1) * BOX_SPACE.x
|
||||
|
||||
for row in row_size:
|
||||
var pos_y = -0.5 * (column_size - 1) * BOX_SPACE.y
|
||||
|
||||
for column in column_size:
|
||||
# Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape.
|
||||
var box = create_rigidbody_box(BOX_SIZE)
|
||||
box.gravity_scale = 0.0
|
||||
box.position = Vector2(pos_x, pos_y)
|
||||
_objects.push_back(box)
|
||||
|
||||
pos_y += BOX_SPACE.y
|
||||
|
||||
pos_x += BOX_SPACE.x
|
||||
|
||||
timer = OS.get_ticks_usec() - timer
|
||||
Log.print_log(" Create Time: %.3f ms" % (0.001 * timer))
|
||||
|
||||
|
||||
func _add_objects():
|
||||
var root_node = $Objects
|
||||
|
||||
Log.print_log("* Adding objects...")
|
||||
var timer = OS.get_ticks_usec()
|
||||
|
||||
for object in _objects:
|
||||
root_node.add_child(object)
|
||||
|
||||
timer = OS.get_ticks_usec() - timer
|
||||
Log.print_log(" Add Time: %.3f ms" % (0.001 * timer))
|
||||
|
||||
|
||||
func _move_objects():
|
||||
Log.print_log("* Moving objects...")
|
||||
var timer = OS.get_ticks_usec()
|
||||
|
||||
for object in _objects:
|
||||
object.position += BOX_SPACE
|
||||
|
||||
timer = OS.get_ticks_usec() - timer
|
||||
Log.print_log(" Move Time: %.3f ms" % (0.001 * timer))
|
||||
|
||||
|
||||
func _remove_objects():
|
||||
var root_node = $Objects
|
||||
|
||||
Log.print_log("* Removing objects...")
|
||||
var timer = OS.get_ticks_usec()
|
||||
|
||||
# Remove objects in reversed order to avoid the overhead of changing children index in parent.
|
||||
var object_count = _objects.size()
|
||||
for object_index in range(object_count):
|
||||
root_node.remove_child(_objects[object_count - object_index - 1])
|
||||
|
||||
timer = OS.get_ticks_usec() - timer
|
||||
Log.print_log(" Remove Time: %.3f ms" % (0.001 * timer))
|
||||
12
2d/physics_tests/tests/performance/test_perf_broadphase.tscn
Normal file
@@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://tests/performance/test_perf_broadphase.gd" type="Script" id=1]
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
_enable_debug_collision = false
|
||||
row_size = 300
|
||||
column_size = 300
|
||||
|
||||
[node name="Objects" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 300 )
|
||||
193
2d/physics_tests/tests/performance/test_perf_contacts.gd
Normal file
@@ -0,0 +1,193 @@
|
||||
extends Test
|
||||
|
||||
|
||||
const OPTION_TYPE_ALL = "Shape type/All"
|
||||
const OPTION_TYPE_RECTANGLE = "Shape type/Rectangle"
|
||||
const OPTION_TYPE_SPHERE = "Shape type/Sphere"
|
||||
const OPTION_TYPE_CAPSULE = "Shape type/Capsule"
|
||||
const OPTION_TYPE_CONVEX_POLYGON = "Shape type/Convex Polygon"
|
||||
const OPTION_TYPE_CONCAVE_POLYGON = "Shape type/Concave Polygon"
|
||||
|
||||
export(Array) var spawns = Array()
|
||||
export(int) var spawn_count = 100
|
||||
|
||||
onready var options = $Options
|
||||
|
||||
var _object_templates = []
|
||||
|
||||
var _log_physics = false
|
||||
var _log_physics_time = 0
|
||||
var _log_physics_time_start = 0
|
||||
|
||||
|
||||
func _ready():
|
||||
yield(start_timer(0.5), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
var dynamic_shapes = $DynamicShapes
|
||||
while dynamic_shapes.get_child_count():
|
||||
var type_node = dynamic_shapes.get_child(0)
|
||||
type_node.position = Vector2.ZERO
|
||||
_object_templates.push_back(type_node)
|
||||
dynamic_shapes.remove_child(type_node)
|
||||
|
||||
options.add_menu_item(OPTION_TYPE_ALL)
|
||||
options.add_menu_item(OPTION_TYPE_RECTANGLE)
|
||||
options.add_menu_item(OPTION_TYPE_SPHERE)
|
||||
options.add_menu_item(OPTION_TYPE_CAPSULE)
|
||||
options.add_menu_item(OPTION_TYPE_CONVEX_POLYGON)
|
||||
options.add_menu_item(OPTION_TYPE_CONCAVE_POLYGON)
|
||||
options.connect("option_selected", self, "_on_option_selected")
|
||||
|
||||
_start_all_types()
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if _log_physics:
|
||||
var time = OS.get_ticks_usec()
|
||||
var time_delta = time - _log_physics_time
|
||||
var time_total = time - _log_physics_time_start
|
||||
_log_physics_time = time
|
||||
Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total])
|
||||
|
||||
|
||||
func _log_physics_start():
|
||||
_log_physics = true
|
||||
_log_physics_time_start = OS.get_ticks_usec()
|
||||
_log_physics_time = _log_physics_time_start
|
||||
|
||||
|
||||
func _log_physics_stop():
|
||||
_log_physics = false
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
for object_template in _object_templates:
|
||||
object_template.free()
|
||||
|
||||
|
||||
func _on_option_selected(option):
|
||||
cancel_timer()
|
||||
|
||||
_despawn_objects()
|
||||
|
||||
match option:
|
||||
OPTION_TYPE_ALL:
|
||||
_start_all_types()
|
||||
OPTION_TYPE_RECTANGLE:
|
||||
_start_type(_find_type_index("Rectangle"))
|
||||
OPTION_TYPE_SPHERE:
|
||||
_start_type(_find_type_index("Sphere"))
|
||||
OPTION_TYPE_CAPSULE:
|
||||
_start_type(_find_type_index("Capsule"))
|
||||
OPTION_TYPE_CONVEX_POLYGON:
|
||||
_start_type(_find_type_index("ConvexPolygon"))
|
||||
OPTION_TYPE_CONCAVE_POLYGON:
|
||||
_start_type(_find_type_index("ConcavePolygon"))
|
||||
|
||||
|
||||
func _find_type_index(type_name):
|
||||
for type_index in range(_object_templates.size()):
|
||||
var type_node = _object_templates[type_index]
|
||||
if type_node.name.find(type_name) > -1:
|
||||
return type_index
|
||||
|
||||
Log.print_error("Invalid shape type: " + type_name)
|
||||
return -1
|
||||
|
||||
|
||||
func _start_type(type_index):
|
||||
if type_index < 0:
|
||||
return
|
||||
if type_index >= _object_templates.size():
|
||||
return
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_spawn_objects(type_index)
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_activate_objects()
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(5.0), "timeout")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
_log_physics_start()
|
||||
|
||||
_despawn_objects()
|
||||
|
||||
yield(wait_for_physics_ticks(5), "wait_done")
|
||||
_log_physics_stop()
|
||||
|
||||
yield(start_timer(1.0), "timeout")
|
||||
|
||||
|
||||
func _start_all_types():
|
||||
Log.print_log("* Start all types.")
|
||||
|
||||
for type_index in range(_object_templates.size()):
|
||||
yield(_start_type(type_index), "completed")
|
||||
if is_timer_canceled():
|
||||
return
|
||||
|
||||
Log.print_log("* Done all types.")
|
||||
|
||||
|
||||
func _spawn_objects(type_index):
|
||||
var template_node = _object_templates[type_index]
|
||||
for spawn in spawns:
|
||||
var spawn_parent = get_node(spawn)
|
||||
|
||||
Log.print_log("* Spawning: " + template_node.name)
|
||||
|
||||
for _node_index in range(spawn_count):
|
||||
# Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape.
|
||||
var collision = template_node.get_child(0)
|
||||
var body = create_rigidbody_collision(collision, false, collision.transform)
|
||||
body.set_sleeping(true)
|
||||
spawn_parent.add_child(body)
|
||||
|
||||
|
||||
func _activate_objects():
|
||||
for spawn in spawns:
|
||||
var spawn_parent = get_node(spawn)
|
||||
|
||||
Log.print_log("* Activating")
|
||||
|
||||
for node_index in range(spawn_parent.get_child_count()):
|
||||
var node = spawn_parent.get_child(node_index) as RigidBody2D
|
||||
node.set_sleeping(false)
|
||||
|
||||
|
||||
func _despawn_objects():
|
||||
for spawn in spawns:
|
||||
var spawn_parent = get_node(spawn)
|
||||
|
||||
var object_count = spawn_parent.get_child_count()
|
||||
if object_count == 0:
|
||||
continue
|
||||
|
||||
Log.print_log("* Despawning")
|
||||
|
||||
# Remove objects in reversed order to avoid the overhead of changing children index in parent.
|
||||
for object_index in range(object_count):
|
||||
var node = spawn_parent.get_child(object_count - object_index - 1)
|
||||
spawn_parent.remove_child(node)
|
||||
node.queue_free()
|
||||
74
2d/physics_tests/tests/performance/test_perf_contacts.tscn
Normal file
@@ -0,0 +1,74 @@
|
||||
[gd_scene load_steps=8 format=2]
|
||||
|
||||
[ext_resource path="res://tests/static_scene.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://tests/performance/test_perf_contacts.gd" type="Script" id=2]
|
||||
[ext_resource path="res://assets/texture/godot-head.png" type="Texture" id=3]
|
||||
[ext_resource path="res://tests/test_options.tscn" type="PackedScene" id=4]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 20, 30 )
|
||||
|
||||
[sub_resource type="CircleShape2D" id=2]
|
||||
radius = 30.0
|
||||
|
||||
[sub_resource type="CapsuleShape2D" id=3]
|
||||
radius = 20.0
|
||||
height = 30.0
|
||||
|
||||
[node name="Test" type="Node2D"]
|
||||
script = ExtResource( 2 )
|
||||
_enable_debug_collision = false
|
||||
spawns = [ NodePath("SpawnTarget1") ]
|
||||
spawn_count = 200
|
||||
|
||||
[node name="Options" parent="." instance=ExtResource( 4 )]
|
||||
|
||||
[node name="SpawnTarget1" type="Node2D" parent="."]
|
||||
position = Vector2( 512, 400 )
|
||||
|
||||
[node name="StaticScene" parent="." instance=ExtResource( 1 )]
|
||||
position = Vector2( 0, 125.017 )
|
||||
|
||||
[node name="DynamicShapes" type="Node2D" parent="."]
|
||||
|
||||
[node name="RigidBodyRectangle" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 0, 1024 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyRectangle"]
|
||||
shape = SubResource( 1 )
|
||||
|
||||
[node name="RigidBodySphere" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 100, 1024 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodySphere"]
|
||||
shape = SubResource( 2 )
|
||||
|
||||
[node name="RigidBodyCapsule" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 200, 1024 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyCapsule"]
|
||||
shape = SubResource( 3 )
|
||||
|
||||
[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 300, 1024 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( 10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, 57.9717, -20.9447, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -58.0115, -20.515, -46.9473, -34.7342, -26.0876, -50.1138, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConvexPolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 3 )
|
||||
|
||||
[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"]
|
||||
position = Vector2( 400, 1024 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
polygon = PoolVector2Array( -5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54.3941, 26.9528, -49.4309, 26.2037, -36.508, 37.5346, -28.1737, 47.6282, -34.3806, 58.0427, -20.9631, 51.113, -10.2876, 50.9869, 35.2694, 38.8, 47.5, 15.9852, 54.3613, -14.9507, 54.1845, -36.5, 48.1, -50.4828, 36.33, -51.3668, -9.98545, -57.8889, -20.5885, -46.9473, -34.7342, -37.4014, -28.547, -26.0876, -37.0323, -26.9862, -49.15, -11.4152, -54.5332 )
|
||||
|
||||
[node name="GodotIcon" type="Sprite" parent="DynamicShapes/RigidBodyConcavePolygon"]
|
||||
self_modulate = Color( 1, 1, 1, 0.392157 )
|
||||
scale = Vector2( 0.5, 0.5 )
|
||||
texture = ExtResource( 3 )
|
||||
10
2d/physics_tests/tests/static_scene.tscn
Normal file
@@ -0,0 +1,10 @@
|
||||
[gd_scene format=2]
|
||||
|
||||
[node name="StaticScene" type="Node2D"]
|
||||
|
||||
[node name="StaticBodyPolygon" type="StaticBody2D" parent="."]
|
||||
position = Vector2( -7.85718, 399.596 )
|
||||
|
||||
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="StaticBodyPolygon"]
|
||||
build_mode = 1
|
||||
polygon = PoolVector2Array( 16.3331, -129.432, 154.006, -20.0078, 292.354, 30.3943, 447.054, 33.9161, 584.899, -14.7955, 751.156, -15.5179, 894.098, -65.4518, 1000.73, -209.127, 1037.77, -398.823, 1029.92, 253.327, 6.2309, 261.185, 7.35339, -398.823 )
|
||||
12
2d/physics_tests/tests/static_scene_flat.tscn
Normal file
@@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id=1]
|
||||
extents = Vector2( 800, 50 )
|
||||
|
||||
[node name="StaticSceneFlat" type="Node2D"]
|
||||
|
||||
[node name="StaticBodyPolygon" type="StaticBody2D" parent="."]
|
||||
position = Vector2( 512, 550 )
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBodyPolygon"]
|
||||
shape = SubResource( 1 )
|
||||
17
2d/physics_tests/tests/test_options.tscn
Normal file
@@ -0,0 +1,17 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://utils/option_menu.gd" type="Script" id=1]
|
||||
|
||||
[node name="Options" type="MenuButton"]
|
||||
pause_mode = 2
|
||||
margin_left = 10.0
|
||||
margin_top = 106.719
|
||||
margin_right = 125.0
|
||||
margin_bottom = 126.719
|
||||
text = "TEST OPTIONS"
|
||||
flat = false
|
||||
align = 0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
54
2d/physics_tests/tests_menu.gd
Normal file
@@ -0,0 +1,54 @@
|
||||
extends OptionMenu
|
||||
|
||||
|
||||
class TestData:
|
||||
var id
|
||||
var scene_path
|
||||
|
||||
|
||||
var _test_list = []
|
||||
|
||||
var _current_test = null
|
||||
var _current_test_scene = null
|
||||
|
||||
|
||||
func _ready():
|
||||
connect("option_selected", self, "_on_option_selected")
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if Input.is_action_just_pressed("restart_test"):
|
||||
if _current_test:
|
||||
_start_test(_current_test)
|
||||
|
||||
|
||||
func add_test(id, scene_path):
|
||||
var test_data = TestData.new()
|
||||
test_data.id = id
|
||||
test_data.scene_path = scene_path
|
||||
_test_list.append(test_data)
|
||||
|
||||
add_menu_item(id)
|
||||
|
||||
|
||||
func _on_option_selected(item_path):
|
||||
for test in _test_list:
|
||||
if test.id == item_path:
|
||||
_start_test(test)
|
||||
|
||||
|
||||
func _start_test(test):
|
||||
_current_test = test
|
||||
|
||||
if _current_test_scene:
|
||||
_current_test_scene.queue_free()
|
||||
_current_test_scene = null
|
||||
|
||||
Log.print_log("*** STARTING TEST: " + test.id)
|
||||
var scene = load(test.scene_path)
|
||||
_current_test_scene = scene.instance()
|
||||
get_tree().root.add_child(_current_test_scene)
|
||||
get_tree().root.move_child(_current_test_scene, 0)
|
||||
|
||||
var label_test = get_node("../LabelTest")
|
||||
label_test.test_name = test.id
|
||||
41
2d/physics_tests/utils/container_log.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends Control
|
||||
|
||||
|
||||
const MAX_ENTRIES = 100
|
||||
|
||||
var _entry_template
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
Log.connect("entry_logged", self, "_on_log_entry")
|
||||
|
||||
_entry_template = get_child(0) as Label
|
||||
remove_child(_entry_template)
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
_entry_template.free()
|
||||
|
||||
|
||||
func clear():
|
||||
while get_child_count():
|
||||
var entry = get_child(get_child_count() - 1)
|
||||
remove_child(entry)
|
||||
entry.queue_free()
|
||||
|
||||
|
||||
func _on_log_entry(message, type):
|
||||
var new_entry = _entry_template.duplicate() as Label
|
||||
|
||||
new_entry.set_text(message)
|
||||
if type == Log.LogType.ERROR:
|
||||
new_entry.modulate = Color.red
|
||||
else:
|
||||
new_entry.modulate = Color.white
|
||||
|
||||
if get_child_count() >= MAX_ENTRIES:
|
||||
var first_entry = get_child(0) as Label
|
||||
remove_child(first_entry)
|
||||
first_entry.queue_free()
|
||||
|
||||
add_child(new_entry)
|
||||
55
2d/physics_tests/utils/kinematicbody_controller.gd
Normal file
@@ -0,0 +1,55 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
|
||||
var _initial_velocity = Vector2.ZERO
|
||||
var _constant_velocity = Vector2.ZERO
|
||||
var _motion_speed = 400.0
|
||||
var _gravity_force = 50.0
|
||||
var _jump_force = 1000.0
|
||||
var _velocity = Vector2.ZERO
|
||||
var _snap = Vector2.ZERO
|
||||
var _floor_max_angle = 45.0
|
||||
var _stop_on_slope = false
|
||||
var _jumping = false
|
||||
var _keep_velocity = false
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if _initial_velocity != Vector2.ZERO:
|
||||
_velocity = _initial_velocity
|
||||
_initial_velocity = Vector2.ZERO
|
||||
_keep_velocity = true
|
||||
elif _constant_velocity != Vector2.ZERO:
|
||||
_velocity = _constant_velocity
|
||||
elif not _keep_velocity:
|
||||
_velocity.x = 0.0
|
||||
|
||||
# Handle horizontal controls.
|
||||
if Input.is_action_pressed("character_left"):
|
||||
if position.x > 0.0:
|
||||
_velocity.x = -_motion_speed
|
||||
_keep_velocity = false
|
||||
_constant_velocity = Vector2.ZERO
|
||||
elif Input.is_action_pressed("character_right"):
|
||||
if position.x < 1024.0:
|
||||
_velocity.x = _motion_speed
|
||||
_keep_velocity = false
|
||||
_constant_velocity = Vector2.ZERO
|
||||
|
||||
# Handle jump controls and gravity.
|
||||
if is_on_floor():
|
||||
if not _jumping and Input.is_action_just_pressed("character_jump"):
|
||||
# Start jumping.
|
||||
_jumping = true
|
||||
_velocity.y = -_jump_force
|
||||
|
||||
# Always apply gravity for floor detection.
|
||||
_velocity.y += _gravity_force
|
||||
|
||||
var snap = _snap if not _jumping else Vector2.ZERO
|
||||
var max_angle = deg2rad(_floor_max_angle)
|
||||
_velocity = move_and_slide_with_snap(_velocity, snap, Vector2.UP, _stop_on_slope, 4, max_angle)
|
||||
|
||||
# Get next jump ready.
|
||||
if _jumping:
|
||||
_jumping = false
|
||||
12
2d/physics_tests/utils/label_engine.gd
Normal file
@@ -0,0 +1,12 @@
|
||||
extends Label
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
var engine_name = ""
|
||||
match System.get_physics_engine():
|
||||
System.PhysicsEngine.GODOT_PHYSICS:
|
||||
engine_name = "Godot Physics"
|
||||
System.PhysicsEngine.OTHER:
|
||||
var engine_setting = ProjectSettings.get_setting("physics/2d/physics_engine")
|
||||
engine_name = "Other (%s)" % engine_setting
|
||||
set_text("Physics engine: %s" % engine_name)
|
||||
5
2d/physics_tests/utils/label_fps.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
extends Label
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
set_text("FPS: %d" % Engine.get_frames_per_second())
|
||||
5
2d/physics_tests/utils/label_pause.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
extends Label
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
visible = get_tree().paused
|
||||
7
2d/physics_tests/utils/label_slider_value.gd
Normal file
@@ -0,0 +1,7 @@
|
||||
extends Label
|
||||
tool
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
var slider = get_node("../HSlider")
|
||||
text = "%.1f" % slider.value
|
||||
13
2d/physics_tests/utils/label_test.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
extends Label
|
||||
|
||||
|
||||
var test_name setget _set_test_name
|
||||
|
||||
|
||||
func _ready():
|
||||
set_text("Select a test from the menu to start it")
|
||||
|
||||
|
||||
func _set_test_name(value):
|
||||
test_name = value
|
||||
set_text("Test: %s" % test_name)
|
||||
5
2d/physics_tests/utils/label_version.gd
Normal file
@@ -0,0 +1,5 @@
|
||||
extends Label
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
set_text("Godot Version: %s" % Engine.get_version_info().string)
|
||||
71
2d/physics_tests/utils/option_menu.gd
Normal file
@@ -0,0 +1,71 @@
|
||||
class_name OptionMenu
|
||||
extends MenuButton
|
||||
|
||||
|
||||
signal option_selected(item_path)
|
||||
signal option_changed(item_path, checked)
|
||||
|
||||
|
||||
func add_menu_item(item_path, checkbox = false, checked = false, radio = false):
|
||||
var path_elements = item_path.split("/", false)
|
||||
var path_element_count = path_elements.size()
|
||||
assert(path_element_count > 0)
|
||||
|
||||
var path = ""
|
||||
var popup = get_popup()
|
||||
for element_index in range(path_element_count - 1):
|
||||
var popup_label = path_elements[element_index]
|
||||
path += popup_label + "/"
|
||||
popup = _add_popup(popup, path, popup_label)
|
||||
|
||||
var label = path_elements[path_element_count - 1]
|
||||
if radio:
|
||||
popup.add_radio_check_item(label)
|
||||
popup.set_item_checked(popup.get_item_count() - 1, checked)
|
||||
elif checkbox:
|
||||
popup.add_check_item(label)
|
||||
popup.set_item_checked(popup.get_item_count() - 1, checked)
|
||||
else:
|
||||
popup.add_item(label)
|
||||
|
||||
|
||||
func _add_item(parent_popup, label):
|
||||
parent_popup.add_item(label)
|
||||
|
||||
|
||||
func _add_popup(parent_popup, path, label):
|
||||
if parent_popup.has_node(label):
|
||||
var popup_node = parent_popup.get_node(label)
|
||||
var popup_menu = popup_node as PopupMenu
|
||||
assert(popup_menu)
|
||||
return popup_menu
|
||||
|
||||
var popup_menu = PopupMenu.new()
|
||||
popup_menu.name = label
|
||||
popup_menu.hide_on_checkable_item_selection = false
|
||||
|
||||
parent_popup.add_child(popup_menu)
|
||||
parent_popup.add_submenu_item(label, label)
|
||||
|
||||
popup_menu.connect("index_pressed", self, "_on_item_pressed", [popup_menu, path])
|
||||
|
||||
return popup_menu
|
||||
|
||||
|
||||
func _on_item_pressed(item_index, popup_menu, path):
|
||||
var item_path = path + popup_menu.get_item_text(item_index)
|
||||
|
||||
if popup_menu.is_item_radio_checkable(item_index):
|
||||
var checked = popup_menu.is_item_checked(item_index)
|
||||
if not checked:
|
||||
popup_menu.set_item_checked(item_index, true)
|
||||
for other_index in range(popup_menu.get_item_count()):
|
||||
if other_index != item_index:
|
||||
popup_menu.set_item_checked(other_index, false)
|
||||
emit_signal("option_selected", item_path)
|
||||
elif popup_menu.is_item_checkable(item_index):
|
||||
var checked = not popup_menu.is_item_checked(item_index)
|
||||
popup_menu.set_item_checked(item_index, checked)
|
||||
emit_signal("option_changed", item_path, checked)
|
||||
else:
|
||||
emit_signal("option_selected", item_path)
|
||||
65
2d/physics_tests/utils/rigidbody_controller.gd
Normal file
@@ -0,0 +1,65 @@
|
||||
extends RigidBody2D
|
||||
|
||||
|
||||
var _initial_velocity = Vector2.ZERO
|
||||
var _constant_velocity = Vector2.ZERO
|
||||
var _motion_speed = 400.0
|
||||
var _gravity_force = 50.0
|
||||
var _jump_force = 1000.0
|
||||
var _velocity = Vector2.ZERO
|
||||
var _on_floor = false
|
||||
var _jumping = false
|
||||
var _keep_velocity = false
|
||||
|
||||
|
||||
func _physics_process(_delta):
|
||||
if _initial_velocity != Vector2.ZERO:
|
||||
_velocity = _initial_velocity
|
||||
_initial_velocity = Vector2.ZERO
|
||||
_keep_velocity = true
|
||||
elif _constant_velocity != Vector2.ZERO:
|
||||
_velocity = _constant_velocity
|
||||
elif not _keep_velocity:
|
||||
_velocity.x = 0.0
|
||||
|
||||
# Handle horizontal controls.
|
||||
if Input.is_action_pressed("character_left"):
|
||||
if position.x > 0.0:
|
||||
_velocity.x = -_motion_speed
|
||||
_keep_velocity = false
|
||||
_constant_velocity = Vector2.ZERO
|
||||
elif Input.is_action_pressed("character_right"):
|
||||
if position.x < 1024.0:
|
||||
_velocity.x = _motion_speed
|
||||
_keep_velocity = false
|
||||
_constant_velocity = Vector2.ZERO
|
||||
|
||||
# Handle jump controls and gravity.
|
||||
if is_on_floor():
|
||||
if not _jumping and Input.is_action_just_pressed("character_jump"):
|
||||
# Start jumping.
|
||||
_jumping = true
|
||||
_velocity.y = -_jump_force
|
||||
elif not _jumping:
|
||||
# Reset gravity.
|
||||
_velocity.y = 0.0
|
||||
else:
|
||||
# Apply gravity and get jump ready.
|
||||
_velocity.y += _gravity_force
|
||||
_jumping = false
|
||||
|
||||
linear_velocity = _velocity
|
||||
|
||||
|
||||
func _integrate_forces(state):
|
||||
_on_floor = false
|
||||
|
||||
var contacts = state.get_contact_count()
|
||||
for i in contacts:
|
||||
var pos = state.get_contact_collider_position(i)
|
||||
if pos.y > position.y:
|
||||
_on_floor = true
|
||||
|
||||
|
||||
func is_on_floor():
|
||||
return _on_floor
|
||||
32
2d/physics_tests/utils/rigidbody_pick.gd
Normal file
@@ -0,0 +1,32 @@
|
||||
extends RigidBody2D
|
||||
|
||||
|
||||
var _picked = false
|
||||
var _last_mouse_pos = Vector2.ZERO
|
||||
|
||||
|
||||
func _ready():
|
||||
input_pickable = true
|
||||
|
||||
|
||||
func _input(event):
|
||||
var mouse_event = event as InputEventMouseButton
|
||||
if mouse_event and not mouse_event.pressed:
|
||||
_picked = false
|
||||
|
||||
|
||||
func _input_event(_viewport, event, _shape_idx):
|
||||
var mouse_event = event as InputEventMouseButton
|
||||
if mouse_event and mouse_event.pressed:
|
||||
_picked = true
|
||||
_last_mouse_pos = get_global_mouse_position()
|
||||
|
||||
|
||||
func _physics_process(delta):
|
||||
if _picked:
|
||||
var mouse_pos = get_global_mouse_position()
|
||||
if mode == MODE_STATIC:
|
||||
global_position = mouse_pos
|
||||
else:
|
||||
linear_velocity = (mouse_pos - _last_mouse_pos) / delta
|
||||
_last_mouse_pos = mouse_pos
|
||||
24
2d/physics_tests/utils/scroll_log.gd
Normal file
@@ -0,0 +1,24 @@
|
||||
extends ScrollContainer
|
||||
|
||||
|
||||
export(bool) var auto_scroll = false setget set_auto_scroll
|
||||
|
||||
|
||||
func _ready():
|
||||
var scrollbar = get_v_scrollbar()
|
||||
scrollbar.connect("scrolling", self, "_on_scrolling")
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if auto_scroll:
|
||||
var scrollbar = get_v_scrollbar()
|
||||
scrollbar.value = scrollbar.max_value
|
||||
|
||||
|
||||
func set_auto_scroll(value):
|
||||
auto_scroll = value
|
||||
|
||||
|
||||
func _on_scrolling():
|
||||
auto_scroll = false
|
||||
$"../CheckBoxScroll".pressed = false
|
||||
11
2d/physics_tests/utils/slider.gd
Normal file
@@ -0,0 +1,11 @@
|
||||
extends Slider
|
||||
|
||||
|
||||
export(float) var snap_step = 1.0
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if Input.is_key_pressed(KEY_SHIFT):
|
||||
step = 0.1
|
||||
else:
|
||||
step = snap_step
|
||||
55
2d/physics_tests/utils/system.gd
Normal file
@@ -0,0 +1,55 @@
|
||||
extends Node
|
||||
|
||||
|
||||
enum PhysicsEngine {
|
||||
GODOT_PHYSICS,
|
||||
OTHER,
|
||||
}
|
||||
|
||||
var _engine = PhysicsEngine.OTHER
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
pause_mode = Node.PAUSE_MODE_PROCESS
|
||||
|
||||
get_tree().debug_collisions_hint = true
|
||||
|
||||
var engine_string = ProjectSettings.get_setting("physics/2d/physics_engine")
|
||||
match engine_string:
|
||||
"DEFAULT":
|
||||
_engine = PhysicsEngine.GODOT_PHYSICS
|
||||
"GodotPhysics":
|
||||
_engine = PhysicsEngine.GODOT_PHYSICS
|
||||
_:
|
||||
_engine = PhysicsEngine.OTHER
|
||||
|
||||
|
||||
func _process(_delta):
|
||||
if Input.is_action_just_pressed("toggle_full_screen"):
|
||||
OS.window_fullscreen = not OS.window_fullscreen
|
||||
|
||||
if Input.is_action_just_pressed("toggle_debug_collision"):
|
||||
var debug_collision_enabled = not _is_debug_collision_enabled()
|
||||
_set_debug_collision_enabled(debug_collision_enabled)
|
||||
if debug_collision_enabled:
|
||||
Log.print_log("Debug Collision ON")
|
||||
else:
|
||||
Log.print_log("Debug Collision OFF")
|
||||
|
||||
if Input.is_action_just_pressed("toggle_pause"):
|
||||
get_tree().paused = not get_tree().paused
|
||||
|
||||
if Input.is_action_just_pressed("exit"):
|
||||
get_tree().quit()
|
||||
|
||||
|
||||
func get_physics_engine():
|
||||
return _engine
|
||||
|
||||
|
||||
func _set_debug_collision_enabled(enabled):
|
||||
get_tree().debug_collisions_hint = enabled
|
||||
|
||||
|
||||
func _is_debug_collision_enabled():
|
||||
return get_tree().debug_collisions_hint
|
||||
20
2d/physics_tests/utils/system_log.gd
Normal file
@@ -0,0 +1,20 @@
|
||||
extends Node
|
||||
|
||||
|
||||
enum LogType {
|
||||
LOG,
|
||||
ERROR,
|
||||
}
|
||||
|
||||
signal entry_logged(message, type)
|
||||
|
||||
|
||||
func print_log(message):
|
||||
print(message)
|
||||
emit_signal("entry_logged", message, LogType.LOG)
|
||||
|
||||
|
||||
func print_error(message):
|
||||
push_error(message)
|
||||
printerr(message)
|
||||
emit_signal("entry_logged", message, LogType.ERROR)
|
||||
@@ -63,6 +63,7 @@ border_width_bottom = 1
|
||||
border_color = Color( 0.41, 0.61, 0.91, 1 )
|
||||
|
||||
[sub_resource type="DynamicFont" id=6]
|
||||
size = 30
|
||||
font_data = ExtResource( 1 )
|
||||
|
||||
[resource]
|
||||
@@ -70,7 +71,7 @@ default_font = SubResource( 6 )
|
||||
Button/colors/font_color = Color( 0.8, 0.8075, 0.8275, 1 )
|
||||
Button/colors/font_color_disabled = Color( 1, 1, 1, 0.3 )
|
||||
Button/colors/font_color_hover = Color( 0.88, 0.8845, 0.8965, 1 )
|
||||
Button/colors/font_color_pressed = Color( 0.41, 0.61, 0.91, 1 )
|
||||
Button/colors/font_color_pressed = Color( 0.411765, 0.611765, 0.909804, 1 )
|
||||
Button/colors/icon_color_hover = Color( 1.15, 1.15, 1.15, 1 )
|
||||
Button/colors/icon_color_pressed = Color( 0.4715, 0.7015, 1.0465, 1 )
|
||||
Button/constants/hseparation = 2
|
||||
|
||||
@@ -49,7 +49,10 @@ func _physics_process(_delta):
|
||||
_velocity.y = move_and_slide(_velocity, FLOOR_NORMAL).y
|
||||
|
||||
# We flip the Sprite depending on which way the enemy is moving.
|
||||
sprite.scale.x = 1 if _velocity.x > 0 else -1
|
||||
if _velocity.x > 0:
|
||||
sprite.scale.x = 1
|
||||
else:
|
||||
sprite.scale.x = -1
|
||||
|
||||
var animation = get_new_animation()
|
||||
if animation != animation_player.current_animation:
|
||||
@@ -64,7 +67,10 @@ func destroy():
|
||||
func get_new_animation():
|
||||
var animation_new = ""
|
||||
if _state == State.WALKING:
|
||||
animation_new = "walk" if abs(_velocity.x) > 0 else "idle"
|
||||
if _velocity.x == 0:
|
||||
animation_new = "idle"
|
||||
else:
|
||||
animation_new = "walk"
|
||||
else:
|
||||
animation_new = "destroy"
|
||||
return animation_new
|
||||
|
||||