From 4a88c2d0f6d2d7e3ad5635bc59c64d2f1d5cd598 Mon Sep 17 00:00:00 2001 From: Nathan Lovato Date: Tue, 12 May 2020 12:48:04 -0600 Subject: [PATCH] Add Godot project, update README Co-authored by: Henrique Campos --- README.md | 32 ++- godot/Explosion/Explosion.tscn | 314 ++++++++++++++++++++++ godot/Explosion/ExplosionDemo.tscn | 192 +++++++++++++ godot/Explosion/explosion_gradient.tres | 8 + godot/Explosion/explosion_gradient_2.tres | 8 + godot/Explosion/scraps_gradient.tres | 8 + godot/GhostTrail/GhostTrail.tscn | 31 +++ godot/GhostTrail/GhostTrailDemo.tscn | 173 ++++++++++++ godot/LaserBeam/LaserBeam.gd | 73 +++++ godot/LaserBeam/LaserBeam.tscn | 111 ++++++++ godot/LaserBeam/LaserBeamDemo.tscn | 81 ++++++ godot/StarField/StarField.tscn | 30 +++ godot/StarField/StarFieldBackground.tscn | 25 ++ godot/StarField/StarFieldDemo.tscn | 264 ++++++++++++++++++ godot/StarField/star.svg | 73 +++++ godot/StarField/star.svg.import | 34 +++ godot/Trail/ShipWithTrail.tscn | 52 ++++ godot/Trail/Trail2D.gd | 101 +++++++ godot/Trail/Trail2D.tscn | 17 ++ godot/Trail/Trail2DDemo.tscn | 253 +++++++++++++++++ godot/assets/2d_environment.tres | 9 + godot/assets/asteroid.svg | 153 +++++++++++ godot/assets/asteroid.svg.import | 34 +++ godot/assets/glowing_circle.png | Bin 0 -> 4138 bytes godot/assets/glowing_circle.png.import | 34 +++ godot/assets/planets.svg | 282 +++++++++++++++++++ godot/assets/planets.svg.import | 34 +++ godot/assets/puff.png | Bin 0 -> 1684 bytes godot/assets/puff.png.import | 34 +++ godot/assets/puff_smooth.png | Bin 0 -> 7188 bytes godot/assets/puff_smooth.png.import | 34 +++ godot/assets/sparkle.png | Bin 0 -> 3699 bytes godot/assets/sparkle.png.import | 34 +++ godot/assets/topdown-player.svg | 66 +++++ godot/assets/topdown-player.svg.import | 34 +++ godot/default_env.tres | 7 + godot/icon.png | Bin 0 -> 3446 bytes godot/icon.png.import | 34 +++ godot/project.godot | 42 +++ img/explosion_1.png | Bin 0 -> 33447 bytes img/ghost_trail.png | Bin 0 -> 57674 bytes img/laser.png | Bin 0 -> 32302 bytes img/trail.png | Bin 0 -> 14367 bytes 43 files changed, 2708 insertions(+), 3 deletions(-) create mode 100644 godot/Explosion/Explosion.tscn create mode 100644 godot/Explosion/ExplosionDemo.tscn create mode 100644 godot/Explosion/explosion_gradient.tres create mode 100644 godot/Explosion/explosion_gradient_2.tres create mode 100644 godot/Explosion/scraps_gradient.tres create mode 100644 godot/GhostTrail/GhostTrail.tscn create mode 100644 godot/GhostTrail/GhostTrailDemo.tscn create mode 100644 godot/LaserBeam/LaserBeam.gd create mode 100644 godot/LaserBeam/LaserBeam.tscn create mode 100644 godot/LaserBeam/LaserBeamDemo.tscn create mode 100644 godot/StarField/StarField.tscn create mode 100644 godot/StarField/StarFieldBackground.tscn create mode 100644 godot/StarField/StarFieldDemo.tscn create mode 100644 godot/StarField/star.svg create mode 100644 godot/StarField/star.svg.import create mode 100644 godot/Trail/ShipWithTrail.tscn create mode 100644 godot/Trail/Trail2D.gd create mode 100644 godot/Trail/Trail2D.tscn create mode 100644 godot/Trail/Trail2DDemo.tscn create mode 100644 godot/assets/2d_environment.tres create mode 100644 godot/assets/asteroid.svg create mode 100644 godot/assets/asteroid.svg.import create mode 100644 godot/assets/glowing_circle.png create mode 100644 godot/assets/glowing_circle.png.import create mode 100644 godot/assets/planets.svg create mode 100644 godot/assets/planets.svg.import create mode 100644 godot/assets/puff.png create mode 100644 godot/assets/puff.png.import create mode 100644 godot/assets/puff_smooth.png create mode 100644 godot/assets/puff_smooth.png.import create mode 100644 godot/assets/sparkle.png create mode 100644 godot/assets/sparkle.png.import create mode 100644 godot/assets/topdown-player.svg create mode 100644 godot/assets/topdown-player.svg.import create mode 100644 godot/default_env.tres create mode 100644 godot/icon.png create mode 100644 godot/icon.png.import create mode 100644 godot/project.godot create mode 100644 img/explosion_1.png create mode 100644 img/ghost_trail.png create mode 100644 img/laser.png create mode 100644 img/trail.png diff --git a/README.md b/README.md index b4b2b56..e602b07 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # Godot Visual Effects -⚠ This repository is a work-in-progress. To know when its content is available, [follow us on Twitter](https://twitter.com/NathanGDQuest) - ![project banner](./img/banner-vfx-secrets.png) -This project is a Free and Open-Source set of polished visual effects from our course [Godot VFX Secrets](). They are available under the permissive MIT license +Godot Visual Effects is a Free and Open-Source set of polished visual effects from our course **Godot VFX Secrets**. + +ℹ Follow us on [Twitter](https://twitter.com/NathanGDQuest) and [YouTube](https://www.youtube.com/c/gdquest/) for free game creation tutorials, tips, and news. You can support our work on Free Software by [getting one of our courses](https://gdquest.mavenseed.com/). + +![Laser effect](./img/laser.png) + +ℹ The course isn't out yet. To know when it's available, you can [subscribe via email](https://gdquest.mavenseed.com/p/follow). This hands-on tutorial series will teach you essential techniques to design effects such as explosions, ghost trails behind the player as in Castlevania games, lasers, background animation, and more. @@ -16,3 +20,25 @@ All available effects are currently 2D-only. - Laser beam - Ghost trail or after image - Star field +- Trail that follows the character + +![Trail effect](./img/trail.png) + +## How to use + +Download the Godot project. Each effect is in a self-contained directory with all its dependencies. + +To add an effect to your own project, copy its directory to the root of your project, and move it from Godot's _FileSystem_ tab. That's it! + +![Explosion effect](./img/explosion_1.png) + +## Contributing + +Contributors are welcome! + +If you encounter a bug, please [open an issue](https://github.com/GDQuest/godot-game-harvester/issues/new). + +If you want to contribute to the project, for instance by fixing a bug or adding a feature, check out our: + +1. [Contributor guidelines](https://www.gdquest.com/docs/guidelines/contributing-to/gdquest-projects/). +1. [GDScript style guide](https://www.gdquest.com/docs/guidelines/best-practices/godot-gdscript/) diff --git a/godot/Explosion/Explosion.tscn b/godot/Explosion/Explosion.tscn new file mode 100644 index 0000000..f4478e3 --- /dev/null +++ b/godot/Explosion/Explosion.tscn @@ -0,0 +1,314 @@ +[gd_scene load_steps=23 format=2] + +[ext_resource path="res://assets/sparkle.png" type="Texture" id=1] +[ext_resource path="res://Explosion/explosion_gradient.tres" type="Texture" id=2] +[ext_resource path="res://assets/puff.png" type="Texture" id=3] +[ext_resource path="res://assets/puff_smooth.png" type="Texture" id=5] +[ext_resource path="res://Explosion/scraps_gradient.tres" type="Texture" id=6] + +[sub_resource type="Gradient" id=1] +offsets = PoolRealArray( 0.0494297, 0.913043, 1 ) +colors = PoolColorArray( 0.226562, 0.217086, 0.217086, 1, 0.133333, 0.12549, 0.12549, 1, 0.133333, 0.12549, 0.12549, 0 ) + +[sub_resource type="GradientTexture" id=2] +gradient = SubResource( 1 ) + +[sub_resource type="Curve" id=3] +_data = [ Vector2( 0, 0.290223 ), 0.0, 3.6562, 0, 0, Vector2( 0.682482, 1 ), -0.0677277, -0.0677277, 0, 0, Vector2( 1, 0.554545 ), -0.29932, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=4] +curve = SubResource( 3 ) + +[sub_resource type="ParticlesMaterial" id=5] +emission_shape = 1 +emission_sphere_radius = 40.0 +flag_disable_z = true +spread = 180.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 80.0 +initial_velocity_random = 0.6 +angular_velocity = 40.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +damping = 40.0 +damping_random = 0.5 +angle = 360.0 +angle_random = 1.0 +scale = 2.6 +scale_random = 0.5 +scale_curve = SubResource( 4 ) +color_ramp = SubResource( 2 ) + +[sub_resource type="Curve" id=6] +_data = [ Vector2( 0, 0.377273 ), 0.0, 2.60769, 0, 0, Vector2( 0.761062, 0.986364 ), 0.0, 0.0, 0, 0, Vector2( 1, 0.322727 ), -0.564845, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=7] +curve = SubResource( 6 ) + +[sub_resource type="ParticlesMaterial" id=8] +trail_divisor = 50 +emission_shape = 1 +emission_sphere_radius = 15.0 +flag_disable_z = true +spread = 180.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 1000.0 +initial_velocity_random = 0.4 +orbit_velocity = 0.3 +orbit_velocity_random = 1.0 +tangential_accel = 1000.0 +tangential_accel_random = 1.0 +damping = 1500.0 +scale = 0.2 +scale_random = 0.2 +scale_curve = SubResource( 7 ) +color_ramp = ExtResource( 6 ) + +[sub_resource type="Curve" id=9] +_data = [ Vector2( 0, 0.0409091 ), 0.0, 8.35303, 0, 0, Vector2( 0.251678, 1 ), 0.0, 0.0, 0, 0, Vector2( 0.993289, 0.0136364 ), 0.0, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=10] +curve = SubResource( 9 ) + +[sub_resource type="ParticlesMaterial" id=11] +flag_disable_z = true +spread = 180.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 350.0 +initial_velocity_random = 0.5 +angular_velocity = 80.0 +angular_velocity_random = 0.8 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +damping = 100.0 +damping_random = 0.85 +angle = 220.0 +angle_random = 1.0 +scale = 2.0 +scale_random = 0.2 +scale_curve = SubResource( 10 ) +color_ramp = ExtResource( 2 ) + +[sub_resource type="Gradient" id=12] +offsets = PoolRealArray( 0, 0.130909, 0.345455, 0.607273, 1 ) +colors = PoolColorArray( 1, 1, 1, 1, 1, 0.648972, 0.164062, 1, 1, 0.475624, 0.136719, 1, 0.888672, 0.17704, 0.17704, 1, 0.203922, 0.203922, 0.203922, 1 ) + +[sub_resource type="GradientTexture" id=13] +gradient = SubResource( 12 ) + +[sub_resource type="Curve" id=14] +_data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 0.483222, 1 ), 0.0, 0.0, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=15] +curve = SubResource( 14 ) + +[sub_resource type="ParticlesMaterial" id=16] +lifetime_randomness = 0.6 +emission_shape = 1 +emission_sphere_radius = 50.0 +flag_disable_z = true +spread = 180.0 +gravity = Vector3( 0, 0, 0 ) +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +radial_accel = 200.0 +radial_accel_random = 0.3 +tangential_accel = 100.0 +scale = 0.1 +scale_random = 0.3 +scale_curve = SubResource( 15 ) +color_ramp = SubResource( 13 ) + +[sub_resource type="Animation" id=17] +length = 3.0 +step = 0.05 +tracks/0/type = "value" +tracks/0/path = NodePath("FireBurstParticles2D:emitting") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 0.5 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/1/type = "value" +tracks/1/path = NodePath("SparkleParticles2D:emitting") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0, 0.5 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/2/type = "value" +tracks/2/path = NodePath("SmokeParticles2D:emitting") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/keys = { +"times": PoolRealArray( 0, 0.5 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/3/type = "value" +tracks/3/path = NodePath("FireTrails/FireTrailParticles2D5:emitting") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/keys = { +"times": PoolRealArray( 0, 0.5 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/4/type = "value" +tracks/4/path = NodePath("FireTrails/FireTrailParticles2D4:emitting") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/keys = { +"times": PoolRealArray( 0.05, 0.55 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/5/type = "value" +tracks/5/path = NodePath("FireTrails/FireTrailParticles2D3:emitting") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/keys = { +"times": PoolRealArray( 0.1, 0.6 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/6/type = "value" +tracks/6/path = NodePath("FireTrails/FireTrailParticles2D2:emitting") +tracks/6/interp = 1 +tracks/6/loop_wrap = true +tracks/6/imported = false +tracks/6/enabled = true +tracks/6/keys = { +"times": PoolRealArray( 0.15, 0.65 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} +tracks/7/type = "value" +tracks/7/path = NodePath("FireTrails/FireTrailParticles2D:emitting") +tracks/7/interp = 1 +tracks/7/loop_wrap = true +tracks/7/imported = false +tracks/7/enabled = true +tracks/7/keys = { +"times": PoolRealArray( 0, 0.5 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} + +[node name="Explosion" type="Node2D"] +z_index = 1 +z_as_relative = false + +[node name="SmokeParticles2D" type="Particles2D" parent="."] +emitting = false +amount = 16 +lifetime = 3.0 +preprocess = 0.6 +explosiveness = 0.6 +local_coords = false +process_material = SubResource( 5 ) +texture = ExtResource( 3 ) + +[node name="FireTrails" type="Node2D" parent="."] + +[node name="FireTrailParticles2D" type="Particles2D" parent="FireTrails"] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 50 +lifetime = 0.5 +randomness = 0.5 +local_coords = false +process_material = SubResource( 8 ) +texture = ExtResource( 5 ) + +[node name="FireTrailParticles2D2" type="Particles2D" parent="FireTrails"] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 50 +lifetime = 0.5 +randomness = 0.5 +local_coords = false +draw_order = 1 +process_material = SubResource( 8 ) +texture = ExtResource( 5 ) + +[node name="FireTrailParticles2D3" type="Particles2D" parent="FireTrails"] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 50 +lifetime = 0.5 +randomness = 0.5 +local_coords = false +draw_order = 1 +process_material = SubResource( 8 ) +texture = ExtResource( 5 ) + +[node name="FireTrailParticles2D4" type="Particles2D" parent="FireTrails"] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 50 +lifetime = 0.5 +randomness = 0.5 +local_coords = false +draw_order = 1 +process_material = SubResource( 8 ) +texture = ExtResource( 5 ) + +[node name="FireTrailParticles2D5" type="Particles2D" parent="FireTrails"] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 50 +lifetime = 0.5 +randomness = 0.5 +local_coords = false +draw_order = 1 +process_material = SubResource( 8 ) +texture = ExtResource( 5 ) + +[node name="FireBurstParticles2D" type="Particles2D" parent="."] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 64 +lifetime = 0.5 +explosiveness = 0.3 +randomness = 1.0 +local_coords = false +draw_order = 1 +process_material = SubResource( 11 ) +texture = ExtResource( 3 ) + +[node name="SparkleParticles2D" type="Particles2D" parent="."] +modulate = Color( 1.2, 1.2, 1.2, 1 ) +emitting = false +amount = 32 +explosiveness = 0.2 +randomness = 1.0 +process_material = SubResource( 16 ) +texture = ExtResource( 1 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +anims/Explode = SubResource( 17 ) diff --git a/godot/Explosion/ExplosionDemo.tscn b/godot/Explosion/ExplosionDemo.tscn new file mode 100644 index 0000000..2256b3a --- /dev/null +++ b/godot/Explosion/ExplosionDemo.tscn @@ -0,0 +1,192 @@ +[gd_scene load_steps=15 format=2] + +[ext_resource path="res://assets/2d_environment.tres" type="Environment" id=1] +[ext_resource path="res://Explosion/Explosion.tscn" type="PackedScene" id=2] +[ext_resource path="res://assets/topdown-player.svg" type="Texture" id=3] +[ext_resource path="res://StarField/StarField.tscn" type="PackedScene" id=4] +[ext_resource path="res://assets/asteroid.svg" type="Texture" id=5] + +[sub_resource type="Curve" id=1] +_data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 0.241936, 1 ), 0.0, 0.0, 0, 0, Vector2( 0.5, 0.0482635 ), 0.0, 0.0, 0, 0, Vector2( 0.745161, 0.990571 ), 0.0, 0.0, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=2] +curve = SubResource( 1 ) + +[sub_resource type="ParticlesMaterial" id=3] +emission_shape = 2 +emission_box_extents = Vector3( 512, 300, 0 ) +flag_disable_z = true +gravity = Vector3( 0, 0, 0 ) +angular_velocity = 50.0 +angular_velocity_random = 1.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale_random = 1.0 +scale_curve = SubResource( 2 ) + +[sub_resource type="Animation" id=4] +resource_name = "Collide" +step = 0.05 +tracks/0/type = "value" +tracks/0/path = NodePath(".:position") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 0.95 ), +"transitions": PoolRealArray( 3.605, 0.5 ), +"update": 0, +"values": [ Vector2( -40.6533, 721.027 ), Vector2( 770.137, 222.812 ) ] +} +tracks/1/type = "value" +tracks/1/path = NodePath(".:self_modulate") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0, 0.8 ), +"transitions": PoolRealArray( 0, 1 ), +"update": 0, +"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ] +} +tracks/2/type = "value" +tracks/2/path = NodePath(".:rotation_degrees") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/keys = { +"times": PoolRealArray( 0 ), +"transitions": PoolRealArray( 0.5 ), +"update": 0, +"values": [ 53.1619 ] +} +tracks/3/type = "value" +tracks/3/path = NodePath("GhostTrail:emitting") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/keys = { +"times": PoolRealArray( 0, 0.95 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 1, +"values": [ true, false ] +} + +[sub_resource type="Gradient" id=5] +colors = PoolColorArray( 1, 1, 1, 0.435294, 1, 1, 1, 0 ) + +[sub_resource type="GradientTexture" id=6] +gradient = SubResource( 5 ) + +[sub_resource type="ParticlesMaterial" id=7] +flag_align_y = true +flag_rotate_y = true +flag_disable_z = true +direction = Vector3( 0, -1, 0 ) +spread = 0.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 1.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale = 0.7 +color_ramp = SubResource( 6 ) + +[sub_resource type="Animation" id=8] +length = 8.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 8 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=9] +resource_name = "Explosion" +length = 5.0 +loop = true +step = 0.05 +tracks/0/type = "animation" +tracks/0/path = NodePath("Player/AnimationPlayer") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"clips": PoolStringArray( "Collide" ), +"times": PoolRealArray( 0.3 ) +} +tracks/1/type = "animation" +tracks/1/path = NodePath("Explosion/AnimationPlayer") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"clips": PoolStringArray( "Explode" ), +"times": PoolRealArray( 1.15 ) +} + +[node name="ExplosionSampleScene" type="Node2D"] + +[node name="StarField" parent="." instance=ExtResource( 4 )] +modulate = Color( 1.05, 1.05, 1.05, 1 ) +process_material = SubResource( 3 ) + +[node name="StarField2" parent="." instance=ExtResource( 4 )] +modulate = Color( 1.05, 1.05, 1.05, 1 ) +process_material = SubResource( 3 ) + +[node name="Player" type="Sprite" parent="."] +self_modulate = Color( 1, 1, 1, 0 ) +position = Vector2( 770.137, 222.812 ) +rotation = 0.92785 +scale = Vector2( 0.7, 0.7 ) +z_index = 1 +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Player"] +anims/Collide = SubResource( 4 ) + +[node name="GhostTrail" type="Particles2D" parent="Player"] +show_behind_parent = true +rotation = 3.14159 +emitting = false +amount = 16 +lifetime = 0.5 +local_coords = false +draw_order = 1 +process_material = SubResource( 7 ) +texture = ExtResource( 3 ) + +[node name="Asteroid" type="Sprite" parent="."] +position = Vector2( 842, 146 ) +rotation = 0.785398 +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Asteroid"] +autoplay = "Spin" +anims/Spin = SubResource( 8 ) + +[node name="Explosion" parent="." instance=ExtResource( 2 )] +position = Vector2( 770.137, 222.812 ) +z_index = 3 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +autoplay = "Explosion" +anims/Explosion = SubResource( 9 ) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = ExtResource( 1 ) + +[editable path="Explosion"] diff --git a/godot/Explosion/explosion_gradient.tres b/godot/Explosion/explosion_gradient.tres new file mode 100644 index 0000000..1bed0d3 --- /dev/null +++ b/godot/Explosion/explosion_gradient.tres @@ -0,0 +1,8 @@ +[gd_resource type="GradientTexture" load_steps=2 format=2] + +[sub_resource type="Gradient" id=1] +offsets = PoolRealArray( 0, 0.1, 0.389091, 0.570909, 0.865455 ) +colors = PoolColorArray( 1, 1, 1, 1, 1, 0.788235, 0.309804, 1, 0.980392, 0.419608, 0.211765, 1, 0.831373, 0.219608, 0.219608, 1, 0.258824, 0.25098, 0.25098, 1 ) + +[resource] +gradient = SubResource( 1 ) diff --git a/godot/Explosion/explosion_gradient_2.tres b/godot/Explosion/explosion_gradient_2.tres new file mode 100644 index 0000000..5ba0ff1 --- /dev/null +++ b/godot/Explosion/explosion_gradient_2.tres @@ -0,0 +1,8 @@ +[gd_resource type="GradientTexture" load_steps=2 format=2] + +[sub_resource type="Gradient" id=1] +offsets = PoolRealArray( 0, 0.0945455, 0.181818, 0.389091, 0.570909, 0.865455 ) +colors = PoolColorArray( 0.976471, 0.878431, 0.705882, 0, 0.97568, 0.84943, 0.605487, 1, 0.972656, 0.754792, 0.26258, 1, 1, 0.45265, 0.155894, 1, 0.831373, 0.219608, 0.219608, 1, 0.258824, 0.25098, 0.25098, 1 ) + +[resource] +gradient = SubResource( 1 ) diff --git a/godot/Explosion/scraps_gradient.tres b/godot/Explosion/scraps_gradient.tres new file mode 100644 index 0000000..02b89fd --- /dev/null +++ b/godot/Explosion/scraps_gradient.tres @@ -0,0 +1,8 @@ +[gd_resource type="GradientTexture" load_steps=2 format=2] + +[sub_resource type="Gradient" id=1] +offsets = PoolRealArray( 0, 0.155894, 0.505017, 0.8327, 1 ) +colors = PoolColorArray( 0.258824, 0.25098, 0.25098, 1, 0.722656, 0.118153, 0.118153, 1, 0.855469, 0.323879, 0.126857, 1, 1, 0.788235, 0.309804, 0.717647, 1, 1, 1, 0 ) + +[resource] +gradient = SubResource( 1 ) diff --git a/godot/GhostTrail/GhostTrail.tscn b/godot/GhostTrail/GhostTrail.tscn new file mode 100644 index 0000000..dcc0441 --- /dev/null +++ b/godot/GhostTrail/GhostTrail.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://assets/topdown-player.svg" type="Texture" id=2] + +[sub_resource type="Gradient" id=7] +colors = PoolColorArray( 1, 1, 1, 0.435294, 1, 1, 1, 0 ) + +[sub_resource type="GradientTexture" id=8] +gradient = SubResource( 7 ) + +[sub_resource type="ParticlesMaterial" id=3] +flag_align_y = true +flag_rotate_y = true +flag_disable_z = true +direction = Vector3( 0, -1, 0 ) +spread = 0.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 1.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale = 0.7 +color_ramp = SubResource( 8 ) + +[node name="GhostTrail" type="Particles2D"] +show_behind_parent = true +rotation = 3.14159 +lifetime = 0.5 +local_coords = false +draw_order = 1 +process_material = SubResource( 3 ) +texture = ExtResource( 2 ) diff --git a/godot/GhostTrail/GhostTrailDemo.tscn b/godot/GhostTrail/GhostTrailDemo.tscn new file mode 100644 index 0000000..b3988c9 --- /dev/null +++ b/godot/GhostTrail/GhostTrailDemo.tscn @@ -0,0 +1,173 @@ +[gd_scene load_steps=12 format=2] + +[ext_resource path="res://assets/topdown-player.svg" type="Texture" id=1] +[ext_resource path="res://StarField/StarFieldDemo.tscn" type="PackedScene" id=2] +[ext_resource path="res://GhostTrail/GhostTrail.tscn" type="PackedScene" id=3] + +[sub_resource type="GDScript" id=1] +script/source = "extends Camera2D + +export(float) var speed = 0 + +func _process(delta): + translate((Vector2.RIGHT * speed) * delta) +" + +[sub_resource type="Shader" id=2] +code = "shader_type canvas_item; + +const float SAMPLES = 71.0; +const float WIDTH = 0.04734573810584494679397346954847; //1.0 / sqrt(PI * 2 * SAMPLES) + +uniform vec2 blur_scale = vec2(1, 0); + +float gaussian(float x) { + float x_squared = x*x; + + return WIDTH * exp((x_squared / (2.0 * SAMPLES)) * -1.0); +} + +void fragment() { + vec2 scale = TEXTURE_PIXEL_SIZE * blur_scale; + + float weight = 0.0; + float total_weight = 0.0; + vec4 color = vec4(0.0); + + for(int i=-int(SAMPLES)/2; i < int(SAMPLES)/2; ++i) { + weight = gaussian(float(i)); + color.rgb += texture(TEXTURE, UV + scale * vec2(float(i))).rgb * weight; + total_weight += weight; + } + + COLOR.rgb = color.rgb / total_weight; +}" + +[sub_resource type="ShaderMaterial" id=3] +shader = SubResource( 2 ) +shader_param/blur_scale = Vector2( 0, 0 ) + +[sub_resource type="ViewportTexture" id=4] +viewport_path = NodePath("Viewport") + +[sub_resource type="Gradient" id=5] +colors = PoolColorArray( 1, 1, 1, 0.435294, 1, 1, 1, 0 ) + +[sub_resource type="GradientTexture" id=6] +gradient = SubResource( 5 ) + +[sub_resource type="ParticlesMaterial" id=7] +flag_align_y = true +flag_rotate_y = true +flag_disable_z = true +direction = Vector3( 0, -1, 0 ) +spread = 0.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 1.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale = 0.7 +color_ramp = SubResource( 6 ) + +[sub_resource type="Animation" id=8] +length = 6.0 +loop = true +step = 0.05 +tracks/0/type = "value" +tracks/0/path = NodePath("Viewport/Camera2D:speed") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 1.6, 2.25, 4 ), +"transitions": PoolRealArray( 1, 2, 1, 2 ), +"update": 0, +"values": [ 200.0, 200.0, 2000.0, 4000.0 ] +} +tracks/1/type = "value" +tracks/1/path = NodePath("BlurHorizontal:material:shader_param/blur_scale") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/keys = { +"times": PoolRealArray( 0, 1.6, 2.25, 4 ), +"transitions": PoolRealArray( 1, 2, 1, 2 ), +"update": 0, +"values": [ Vector2( 0, 0 ), Vector2( 0, 0 ), Vector2( 4, 0 ), Vector2( 6, 0 ) ] +} +tracks/2/type = "value" +tracks/2/path = NodePath("Sprite/GhostTrail:emitting") +tracks/2/interp = 1 +tracks/2/loop_wrap = true +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/keys = { +"times": PoolRealArray( 0, 1.6, 5.5 ), +"transitions": PoolRealArray( 1, 1, 1 ), +"update": 1, +"values": [ false, true, false ] +} +tracks/3/type = "value" +tracks/3/path = NodePath("Sprite/GhostTrail:speed_scale") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/keys = { +"times": PoolRealArray( 0, 1.6, 2.25, 4 ), +"transitions": PoolRealArray( 2, 2, 1, 2 ), +"update": 0, +"values": [ 0.2, 0.2, 1.0, 4.0 ] +} +tracks/4/type = "value" +tracks/4/path = NodePath("Sprite/GhostTrail:process_material:initial_velocity") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/keys = { +"times": PoolRealArray( 0, 1.6, 2.25 ), +"transitions": PoolRealArray( 1, 1, 1 ), +"update": 0, +"values": [ 1.0, 1.0, 500.0 ] +} + +[node name="BlurTest" type="Node"] + +[node name="Viewport" type="Viewport" parent="."] +size = Vector2( 1024, 600 ) +render_target_v_flip = true + +[node name="StarFieldTest" parent="Viewport" instance=ExtResource( 2 )] + +[node name="Camera2D" type="Camera2D" parent="Viewport"] +anchor_mode = 0 +current = true +script = SubResource( 1 ) +speed = 200.0 + +[node name="BlurHorizontal" type="TextureRect" parent="."] +material = SubResource( 3 ) +anchor_right = 1.0 +anchor_bottom = 1.0 +texture = SubResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Sprite" type="Sprite" parent="."] +position = Vector2( 473.5, 312.5 ) +rotation = 1.5708 +scale = Vector2( 0.7, 0.7 ) +texture = ExtResource( 1 ) + +[node name="GhostTrail" parent="Sprite" instance=ExtResource( 3 )] +emitting = false +speed_scale = 0.2 +process_material = SubResource( 7 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="."] +autoplay = "Accelerate" +anims/Accelerate = SubResource( 8 ) diff --git a/godot/LaserBeam/LaserBeam.gd b/godot/LaserBeam/LaserBeam.gd new file mode 100644 index 0000000..bb3aa57 --- /dev/null +++ b/godot/LaserBeam/LaserBeam.gd @@ -0,0 +1,73 @@ +extends RayCast2D + +export var cast_speed := 7000.0 +export var max_length := 1400 +export var growth_time := 0.1 + +var is_casting := false setget set_is_casting + +onready var fill := $FillLine2D +onready var tween := $Tween +onready var casting_particles := $CastingParticles2D +onready var collision_particles := $CollisionParticles2D +onready var beam_particles := $BeamParticles2D + +onready var line_width: float = fill.width + + +func _ready() -> void: + set_physics_process(false) + fill.points[1] = Vector2.ZERO + + +func _physics_process(delta: float) -> void: + cast_to = (cast_to + Vector2.RIGHT * cast_speed * delta).clamped(max_length) + cast_beam() + + +func set_is_casting(cast: bool) -> void: + is_casting = cast + + if is_casting: + cast_to = Vector2.ZERO + fill.points[1] = cast_to + appear() + else: + collision_particles.emitting = false + disappear() + + set_physics_process(is_casting) + beam_particles.emitting = is_casting + casting_particles.emitting = is_casting + + +func cast_beam() -> void: + var cast_point := cast_to + + force_raycast_update() + collision_particles.emitting = is_colliding() + + if is_colliding(): + cast_point = to_local(get_collision_point()) + collision_particles.process_material.direction = Vector3( + get_collision_normal().x, get_collision_normal().y, 0 + ) + collision_particles.position = cast_point + + fill.points[1] = cast_point + beam_particles.position = cast_point * 0.5 + beam_particles.process_material.emission_box_extents.x = cast_point.length() * 0.5 + + +func appear() -> void: + if tween.is_active(): + tween.stop_all() + tween.interpolate_property(fill, "width", 0, line_width, growth_time * 2) + tween.start() + + +func disappear() -> void: + if tween.is_active(): + tween.stop_all() + tween.interpolate_property(fill, "width", fill.width, 0, growth_time) + tween.start() diff --git a/godot/LaserBeam/LaserBeam.tscn b/godot/LaserBeam/LaserBeam.tscn new file mode 100644 index 0000000..aa37aec --- /dev/null +++ b/godot/LaserBeam/LaserBeam.tscn @@ -0,0 +1,111 @@ +[gd_scene load_steps=12 format=2] + +[ext_resource path="res://LaserBeam/LaserBeam.gd" type="Script" id=1] +[ext_resource path="res://assets/glowing_circle.png" type="Texture" id=2] + +[sub_resource type="Gradient" id=1] +offsets = PoolRealArray( 0.582915, 1 ) +colors = PoolColorArray( 1, 1, 1, 1, 1, 1, 1, 0 ) + +[sub_resource type="GradientTexture" id=2] +gradient = SubResource( 1 ) + +[sub_resource type="Curve" id=3] +_data = [ Vector2( 0.518072, 1 ), 0.0, -3.53434, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=4] +curve = SubResource( 3 ) + +[sub_resource type="ParticlesMaterial" id=5] +flag_disable_z = true +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 100.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale = 0.5 +scale_curve = SubResource( 4 ) +color_ramp = SubResource( 2 ) + +[sub_resource type="Curve" id=6] +_data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 0.503614, 0.957505 ), 0.0, 0.0, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=7] +curve = SubResource( 6 ) + +[sub_resource type="ParticlesMaterial" id=8] +emission_shape = 2 +emission_box_extents = Vector3( 60, 20, 1 ) +flag_align_y = true +flag_disable_z = true +direction = Vector3( -1, 0, 0 ) +spread = 0.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 30.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +tangential_accel = 100.0 +tangential_accel_random = 1.0 +scale = 0.3 +scale_curve = SubResource( 7 ) + +[sub_resource type="ParticlesMaterial" id=9] +flag_disable_z = true +spread = 50.0 +gravity = Vector3( 0, 0, 0 ) +initial_velocity = 300.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale = 0.5 +scale_curve = SubResource( 4 ) +color_ramp = SubResource( 2 ) + +[node name="LaserBeam2D" type="RayCast2D"] +enabled = true +cast_to = Vector2( 0, 0 ) +script = ExtResource( 1 ) + +[node name="FillLine2D" type="Line2D" parent="."] +modulate = Color( 1.5, 1.5, 1.5, 1 ) +points = PoolVector2Array( 0, 0, 100, 0 ) +default_color = Color( 0.301961, 0.65098, 1, 1 ) +texture_mode = 2 +joint_mode = 2 +begin_cap_mode = 2 +end_cap_mode = 2 +sharp_limit = 8.0 +antialiased = true + +[node name="CastingParticles2D" type="Particles2D" parent="."] +modulate = Color( 1.5, 1.5, 1.5, 1 ) +show_behind_parent = true +emitting = false +lifetime = 0.3 +visibility_rect = Rect2( 0, -18.722, 29.6756, 38.4841 ) +local_coords = false +process_material = SubResource( 5 ) +texture = ExtResource( 2 ) + +[node name="BeamParticles2D" type="Particles2D" parent="."] +modulate = Color( 1.5, 1.5, 1.5, 1 ) +emitting = false +amount = 50 +preprocess = 1.0 +randomness = 1.0 +visibility_rect = Rect2( -2500, -2500, 5000, 5000 ) +local_coords = false +draw_order = 1 +process_material = SubResource( 8 ) +texture = ExtResource( 2 ) + +[node name="CollisionParticles2D" type="Particles2D" parent="."] +modulate = Color( 1.5, 1.5, 1.5, 1 ) +show_behind_parent = true +emitting = false +amount = 16 +lifetime = 0.3 +visibility_rect = Rect2( -2500, -2500, 5000, 5000 ) +local_coords = false +process_material = SubResource( 9 ) +texture = ExtResource( 2 ) + +[node name="Tween" type="Tween" parent="."] diff --git a/godot/LaserBeam/LaserBeamDemo.tscn b/godot/LaserBeam/LaserBeamDemo.tscn new file mode 100644 index 0000000..d22d560 --- /dev/null +++ b/godot/LaserBeam/LaserBeamDemo.tscn @@ -0,0 +1,81 @@ +[gd_scene load_steps=10 format=2] + +[ext_resource path="res://assets/asteroid.svg" type="Texture" id=1] +[ext_resource path="res://assets/topdown-player.svg" type="Texture" id=2] +[ext_resource path="res://StarField/StarFieldBackground.tscn" type="PackedScene" id=3] +[ext_resource path="res://LaserBeam/LaserBeam.tscn" type="PackedScene" id=4] +[ext_resource path="res://assets/2d_environment.tres" type="Environment" id=5] + +[sub_resource type="CircleShape2D" id=1] +radius = 52.7564 + +[sub_resource type="CircleShape2D" id=2] +radius = 69.1353 + +[sub_resource type="CircleShape2D" id=3] +radius = 106.584 + +[sub_resource type="GDScript" id=4] +script/source = "extends Node2D + +onready var laser := $LaserBeam2D + + +func _process(_delta: float) -> void: + look_at(get_global_mouse_position()) + + +func _unhandled_input(event: InputEvent) -> void: + if not event.is_action(\"fire_weapon\"): + return + laser.is_casting = event.is_action_pressed(\"fire_weapon\") +" + +[node name="LaserBeamScene" type="Node2D"] + +[node name="StarFieldBackground" parent="." instance=ExtResource( 3 )] + +[node name="Asteroid" type="StaticBody2D" parent="."] +position = Vector2( 933.744, 126.894 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Asteroid"] +shape = SubResource( 1 ) + +[node name="Sprite" type="Sprite" parent="Asteroid"] +scale = Vector2( 0.486244, 0.486244 ) +texture = ExtResource( 1 ) + +[node name="Asteroid2" type="StaticBody2D" parent="."] +position = Vector2( 641.708, 118.409 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Asteroid2"] +shape = SubResource( 2 ) + +[node name="Sprite" type="Sprite" parent="Asteroid2"] +scale = Vector2( 0.635398, 0.635398 ) +texture = ExtResource( 1 ) + +[node name="Asteroid3" type="StaticBody2D" parent="."] +position = Vector2( 810, 426 ) + +[node name="CollisionShape2D" type="CollisionShape2D" parent="Asteroid3"] +shape = SubResource( 3 ) + +[node name="Sprite" type="Sprite" parent="Asteroid3"] +texture = ExtResource( 1 ) + +[node name="PlayerShip" type="Node2D" parent="."] +position = Vector2( 188.09, 295.571 ) +script = SubResource( 4 ) + +[node name="LaserBeam2D" parent="PlayerShip" instance=ExtResource( 4 )] +position = Vector2( 24, 0 ) +cast_to = Vector2( 100, 0 ) + +[node name="Sprite" type="Sprite" parent="PlayerShip"] +rotation = 1.5708 +scale = Vector2( 0.7, 0.7 ) +texture = ExtResource( 2 ) + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = ExtResource( 5 ) diff --git a/godot/StarField/StarField.tscn b/godot/StarField/StarField.tscn new file mode 100644 index 0000000..2c79f50 --- /dev/null +++ b/godot/StarField/StarField.tscn @@ -0,0 +1,30 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://StarField/star.svg" type="Texture" id=1] + + +[sub_resource type="Curve" id=1] +_data = [ Vector2( 0, 0 ), 0.0, 0.0, 0, 0, Vector2( 0.241936, 1 ), 0.0, 0.0, 0, 0, Vector2( 0.5, 0.0482635 ), 0.0, 0.0, 0, 0, Vector2( 0.745161, 0.990571 ), 0.0, 0.0, 0, 0, Vector2( 1, 0 ), 0.0, 0.0, 0, 0 ] + +[sub_resource type="CurveTexture" id=2] +curve = SubResource( 1 ) + +[sub_resource type="ParticlesMaterial" id=3] +emission_shape = 2 +emission_box_extents = Vector3( 512, 300, 0 ) +flag_disable_z = true +gravity = Vector3( 0, 0, 0 ) +angular_velocity = 50.0 +angular_velocity_random = 1.0 +orbit_velocity = 0.0 +orbit_velocity_random = 0.0 +scale_random = 1.0 +scale_curve = SubResource( 2 ) + +[node name="StarField" type="Particles2D"] +position = Vector2( 512, 300 ) +lifetime = 6.0 +preprocess = 6.0 +visibility_rect = Rect2( -512, -300, 1024, 600 ) +process_material = SubResource( 3 ) +texture = ExtResource( 1 ) diff --git a/godot/StarField/StarFieldBackground.tscn b/godot/StarField/StarFieldBackground.tscn new file mode 100644 index 0000000..05d89a5 --- /dev/null +++ b/godot/StarField/StarFieldBackground.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://StarField/StarField.tscn" type="PackedScene" id=1] + + +[node name="StarFieldBackground" type="ParallaxBackground"] +scroll_ignore_camera_zoom = true + +[node name="ParallaxLayer" type="ParallaxLayer" parent="."] +motion_scale = Vector2( 0.1, 0.1 ) +motion_mirroring = Vector2( 1024, 600 ) + +[node name="StarField" parent="ParallaxLayer" instance=ExtResource( 1 )] + +[node name="ParallaxLayer2" type="ParallaxLayer" parent="."] +motion_scale = Vector2( 0.05, 0.05 ) +motion_mirroring = Vector2( 1024, 600 ) + +[node name="StarField" parent="ParallaxLayer2" instance=ExtResource( 1 )] + +[node name="ParallaxLayer3" type="ParallaxLayer" parent="."] +motion_scale = Vector2( 0.01, 0.01 ) +motion_mirroring = Vector2( 1024, 600 ) + +[node name="StarField" parent="ParallaxLayer3" instance=ExtResource( 1 )] diff --git a/godot/StarField/StarFieldDemo.tscn b/godot/StarField/StarFieldDemo.tscn new file mode 100644 index 0000000..c4bce9f --- /dev/null +++ b/godot/StarField/StarFieldDemo.tscn @@ -0,0 +1,264 @@ +[gd_scene load_steps=13 format=2] + +[ext_resource path="res://StarField/StarFieldBackground.tscn" type="PackedScene" id=1] +[ext_resource path="res://assets/planets.svg" type="Texture" id=2] +[ext_resource path="res://assets/asteroid.svg" type="Texture" id=3] + +[sub_resource type="GDScript" id=1] +script/source = "extends Camera2D + + +func _process(delta: float) -> void: + translate(Vector2(100, 0) * delta) +" + +[sub_resource type="Animation" id=2] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=3] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=4] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=5] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=6] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=7] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=8] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=9] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[node name="StarFieldTest" type="Node"] +__meta__ = { +"_edit_vertical_guides_": [ 3320.0 ] +} + +[node name="StarFieldBackground" parent="." instance=ExtResource( 1 )] + +[node name="Camera2D" type="Camera2D" parent="."] +anchor_mode = 0 +current = true +script = SubResource( 1 ) + +[node name="RepeatingBackground" type="ParallaxBackground" parent="."] +layer = -99 + +[node name="ParallaxLayer" type="ParallaxLayer" parent="RepeatingBackground"] +motion_scale = Vector2( 0.2, 0.2 ) +motion_mirroring = Vector2( 3328, 0 ) + +[node name="Sprite" type="Sprite" parent="RepeatingBackground/ParallaxLayer"] +position = Vector2( 432, 264 ) +texture = ExtResource( 2 ) +region_enabled = true +region_rect = Rect2( 30, 10, 370, 380 ) + +[node name="Sprite2" type="Sprite" parent="RepeatingBackground/ParallaxLayer"] +position = Vector2( 1608, 440 ) +texture = ExtResource( 2 ) +region_enabled = true +region_rect = Rect2( 610, 30, 380, 330 ) + +[node name="Sprite3" type="Sprite" parent="RepeatingBackground/ParallaxLayer"] +position = Vector2( 2768, 224 ) +texture = ExtResource( 2 ) +region_enabled = true +region_rect = Rect2( 130, 470, 760, 380 ) + +[node name="ParallaxLayer2" type="ParallaxLayer" parent="RepeatingBackground"] +motion_scale = Vector2( 0.5, 0.5 ) +motion_mirroring = Vector2( 3328, 0 ) + +[node name="Sprite4" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 1868, 99.9999 ) +scale = Vector2( 0.40625, 0.40625 ) +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite4"] +anims/spin = SubResource( 2 ) + +[node name="Sprite5" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 1130, 434 ) +scale = Vector2( 0.546875, 0.546875 ) +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite5"] +playback_speed = 0.8 +anims/spin = SubResource( 3 ) + +[node name="Sprite6" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 749, 117 ) +scale = Vector2( 0.398437, 0.398437 ) +z_index = -1 +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite6"] +playback_speed = 1.2 +anims/spin = SubResource( 4 ) + +[node name="Sprite7" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 7.62939e-06, 512 ) +scale = Vector2( 0.480469, 0.480469 ) +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite7"] +playback_speed = 1.2 +anims/spin = SubResource( 5 ) + +[node name="Sprite8" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 2276.62, 124.625 ) +scale = Vector2( 0.401367, 0.401367 ) +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite8"] +playback_speed = 1.2 +anims/spin = SubResource( 6 ) + +[node name="Sprite9" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 2048, 528 ) +scale = Vector2( 0.302733, 0.302733 ) +z_index = -1 +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite9"] +playback_speed = 1.2 +anims/spin = SubResource( 7 ) + +[node name="Sprite10" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 3288, 96 ) +scale = Vector2( 0.401367, 0.401367 ) +z_index = -1 +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite10"] +playback_speed = 1.2 +anims/spin = SubResource( 8 ) + +[node name="Sprite11" type="Sprite" parent="RepeatingBackground/ParallaxLayer2"] +position = Vector2( 2656.62, 528.625 ) +scale = Vector2( 0.245116, 0.245116 ) +texture = ExtResource( 3 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="RepeatingBackground/ParallaxLayer2/Sprite11"] +playback_speed = 1.2 +anims/spin = SubResource( 9 ) diff --git a/godot/StarField/star.svg b/godot/StarField/star.svg new file mode 100644 index 0000000..1801600 --- /dev/null +++ b/godot/StarField/star.svg @@ -0,0 +1,73 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/godot/StarField/star.svg.import b/godot/StarField/star.svg.import new file mode 100644 index 0000000..a5b25ae --- /dev/null +++ b/godot/StarField/star.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/star.svg-edd6f0acbe425332a660644689131489.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://StarField/star.svg" +dest_files=[ "res://.import/star.svg-edd6f0acbe425332a660644689131489.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 diff --git a/godot/Trail/ShipWithTrail.tscn b/godot/Trail/ShipWithTrail.tscn new file mode 100644 index 0000000..b461247 --- /dev/null +++ b/godot/Trail/ShipWithTrail.tscn @@ -0,0 +1,52 @@ +[gd_scene load_steps=6 format=2] + +[ext_resource path="res://assets/topdown-player.svg" type="Texture" id=2] +[ext_resource path="res://Trail/Trail2D.tscn" type="PackedScene" id=3] + +[sub_resource type="GDScript" id=1] +script/source = "extends Node2D + + +export var speed := 300.0 + +var _direction := Vector2.RIGHT + +func _process(delta: float) -> void: + _direction = global_position.direction_to(get_global_mouse_position()) + rotation = _direction.angle() + translate((_direction * speed) * delta) + +" + +[sub_resource type="Curve" id=2] +_data = [ Vector2( 0, 0 ), 0.0, 1.0, 0, 1, Vector2( 1, 1 ), 1.0, 0.0, 1, 0 ] + +[sub_resource type="Gradient" id=3] +colors = PoolColorArray( 0.294118, 0.356863, 0.670588, 0, 0.294118, 0.356863, 0.670588, 1 ) + +[node name="ShipWithTrail" type="Node2D"] +position = Vector2( 511.602, 297.63 ) +script = SubResource( 1 ) +speed = 600.0 + +[node name="Sprite" type="Sprite" parent="."] +rotation = 1.5708 +scale = Vector2( 0.7, 0.7 ) +texture = ExtResource( 2 ) + +[node name="Camera2D" type="Camera2D" parent="."] +rotation = -1.5708 +current = true + +[node name="Trail2D" parent="." instance=ExtResource( 3 )] +position = Vector2( -15.8954, -0.198364 ) +rotation = 1.57079 +z_index = -1 +points = PoolVector2Array( -0.589685, 44.7556, -0.0901849, 0.300196 ) +width = 45.0 +width_curve = SubResource( 2 ) +gradient = SubResource( 3 ) +begin_cap_mode = 2 +end_cap_mode = 2 +is_emitting = true +target_path = NodePath("../../ShipWithTrail") diff --git a/godot/Trail/Trail2D.gd b/godot/Trail/Trail2D.gd new file mode 100644 index 0000000..b6b1ecf --- /dev/null +++ b/godot/Trail/Trail2D.gd @@ -0,0 +1,101 @@ +# Draws a 2D trail using Godot's `Line2D`. +# +# Instantiate `Trail2D` as a child of a moving node to use it. To control the color, width curve, +# texture, or trail width, use parameters from the `Line2D` class. +class_name Trail2D +extends Line2D + +export var is_emitting := false setget set_emitting + +# Distance in pixels between vertices. A higher point_distance_threshold leads to more details. +export var point_distance_threshold := 5.0 +# Life of each point in seconds before it is deleted. +export var lifetime := 0.5 +# Maximum number of points allowed on the curve. +export var max_points := 100 + +# Optional path to the target node to follow. If not set, the instance follows its parent. +export var target_path: NodePath + +var _points_creation_time := [] +var _last_point := Vector2.ZERO +var _clock: float = 0.0 +var _offset := 0.0 + +onready var _target: Node2D = get_node(target_path) + + +func _ready() -> void: + if not _target: + _target = get_parent() as Node2D + + # Avoid making the node toplevel in the editor so it rotates and moves with its parent. + if Engine.editor_hint: + set_process(false) + return + + _offset = position.length() + set_as_toplevel(true) + clear_points() + position = Vector2.ZERO + _last_point = to_local(_target.global_position) + calculate_offset() + + +func _get_configuration_warning() -> String: + return ( + "Missing Target node: assign a node to Target Path or give this node a parent that extends Node2D." + if not _target + else "" + ) + + +func _process(delta: float) -> void: + # Remove points older than `lifetime`. + _clock += delta + for creation_time in _points_creation_time: + var time_diff = _clock - creation_time + if time_diff > lifetime: + remove_first_point() + # Points in `_points_creation_time` are ordered from oldest to newest so as soon as a point + # isn't older than `lifetime`, we know all remaining points should stay as well. + else: + break + + if not is_emitting: + return + + # Adding new points if necessary. + var distance: float = _last_point.distance_to(_target.position) + if distance > point_distance_threshold: + add_timed_point(to_local(_target.global_position), _clock) + + +# Creates a new point and stores its creation time. +func add_timed_point(point_position: Vector2, time: float) -> void: + add_point(point_position + calculate_offset()) + _points_creation_time.append(time) + _last_point = point_position + if get_point_count() > max_points: + remove_first_point() + + +# Removes the first point in the line and the corresponding time. +func remove_first_point() -> void: + if get_point_count() > 1: + remove_point(0) + _points_creation_time.pop_front() + + +# Calculates the offset of the trail from its target. +func calculate_offset() -> Vector2: + return -polar2cartesian(1.0, _target.rotation - PI / 2) * _offset + + +func set_emitting(emitting: bool) -> void: + is_emitting = emitting + if not is_inside_tree(): + yield(self, "ready") + if is_emitting: + clear_points() + _points_creation_time.clear() + _last_point = position diff --git a/godot/Trail/Trail2D.tscn b/godot/Trail/Trail2D.tscn new file mode 100644 index 0000000..8ee3d4b --- /dev/null +++ b/godot/Trail/Trail2D.tscn @@ -0,0 +1,17 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://Trail/Trail2D.gd" type="Script" id=1] + +[sub_resource type="Curve" id=1] +_data = [ Vector2( 0, 0 ), 0.0, 1.0, 0, 1, Vector2( 1, 1 ), 1.0, 0.0, 1, 0 ] + +[sub_resource type="Gradient" id=2] +colors = PoolColorArray( 0.294118, 0.356863, 0.670588, 0, 0.294118, 0.356863, 0.670588, 1 ) + +[node name="Trail2D" type="Line2D"] +points = PoolVector2Array( 0, 0, 32, 0 ) +width_curve = SubResource( 1 ) +default_color = Color( 1, 1, 1, 1 ) +gradient = SubResource( 2 ) +joint_mode = 2 +script = ExtResource( 1 ) diff --git a/godot/Trail/Trail2DDemo.tscn b/godot/Trail/Trail2DDemo.tscn new file mode 100644 index 0000000..0f77d0e --- /dev/null +++ b/godot/Trail/Trail2DDemo.tscn @@ -0,0 +1,253 @@ +[gd_scene load_steps=13 format=2] + +[ext_resource path="res://Trail/ShipWithTrail.tscn" type="PackedScene" id=1] +[ext_resource path="res://StarField/StarFieldBackground.tscn" type="PackedScene" id=3] +[ext_resource path="res://assets/planets.svg" type="Texture" id=4] +[ext_resource path="res://assets/asteroid.svg" type="Texture" id=5] + +[sub_resource type="Animation" id=1] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=2] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=3] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=4] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=5] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=6] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=7] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[sub_resource type="Animation" id=8] +resource_name = "spin" +length = 3.0 +loop = true +tracks/0/type = "value" +tracks/0/path = NodePath(".:rotation_degrees") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 3 ), +"transitions": PoolRealArray( 1, 1 ), +"update": 0, +"values": [ 0.0, 360.0 ] +} + +[node name="Trail2DDemo" type="Node"] + +[node name="ShipWithTrail" parent="." instance=ExtResource( 1 )] + +[node name="Background" type="CanvasLayer" parent="."] + +[node name="RepeatingBackground" type="ParallaxBackground" parent="Background"] +layer = -99 + +[node name="ParallaxLayer" type="ParallaxLayer" parent="Background/RepeatingBackground"] +motion_scale = Vector2( 0.2, 0.2 ) +motion_mirroring = Vector2( 3328, 0 ) + +[node name="Sprite" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer"] +position = Vector2( 432, 264 ) +texture = ExtResource( 4 ) +region_enabled = true +region_rect = Rect2( 30, 10, 370, 380 ) + +[node name="Sprite2" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer"] +position = Vector2( 1608, 440 ) +texture = ExtResource( 4 ) +region_enabled = true +region_rect = Rect2( 610, 30, 380, 330 ) + +[node name="Sprite3" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer"] +position = Vector2( 2768, 224 ) +texture = ExtResource( 4 ) +region_enabled = true +region_rect = Rect2( 130, 470, 760, 380 ) + +[node name="ParallaxLayer2" type="ParallaxLayer" parent="Background/RepeatingBackground"] +motion_scale = Vector2( 0.5, 0.5 ) +motion_mirroring = Vector2( 3328, 0 ) + +[node name="Sprite4" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 1868, 99.9999 ) +scale = Vector2( 0.40625, 0.40625 ) +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite4"] +anims/spin = SubResource( 1 ) + +[node name="Sprite5" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 1130, 434 ) +scale = Vector2( 0.546875, 0.546875 ) +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite5"] +playback_speed = 0.8 +anims/spin = SubResource( 2 ) + +[node name="Sprite6" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 749, 117 ) +scale = Vector2( 0.398437, 0.398437 ) +z_index = -1 +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite6"] +playback_speed = 1.2 +anims/spin = SubResource( 3 ) + +[node name="Sprite7" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 7.62939e-06, 512 ) +scale = Vector2( 0.480469, 0.480469 ) +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite7"] +playback_speed = 1.2 +anims/spin = SubResource( 4 ) + +[node name="Sprite8" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 2276.62, 124.625 ) +scale = Vector2( 0.401367, 0.401367 ) +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite8"] +playback_speed = 1.2 +anims/spin = SubResource( 5 ) + +[node name="Sprite9" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 2048, 528 ) +scale = Vector2( 0.302733, 0.302733 ) +z_index = -1 +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite9"] +playback_speed = 1.2 +anims/spin = SubResource( 6 ) + +[node name="Sprite10" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 3288, 96 ) +scale = Vector2( 0.401367, 0.401367 ) +z_index = -1 +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite10"] +playback_speed = 1.2 +anims/spin = SubResource( 7 ) + +[node name="Sprite11" type="Sprite" parent="Background/RepeatingBackground/ParallaxLayer2"] +position = Vector2( 2656.62, 528.625 ) +scale = Vector2( 0.245116, 0.245116 ) +texture = ExtResource( 5 ) + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Background/RepeatingBackground/ParallaxLayer2/Sprite11"] +playback_speed = 1.2 +anims/spin = SubResource( 8 ) + +[node name="StarFieldBackground" parent="Background" instance=ExtResource( 3 )] diff --git a/godot/assets/2d_environment.tres b/godot/assets/2d_environment.tres new file mode 100644 index 0000000..23421c2 --- /dev/null +++ b/godot/assets/2d_environment.tres @@ -0,0 +1,9 @@ +[gd_resource type="Environment" format=2] + +[resource] +background_mode = 4 +glow_enabled = true +glow_levels/4 = true +glow_intensity = 0.5 +glow_blend_mode = 0 +glow_bicubic_upscale = true diff --git a/godot/assets/asteroid.svg b/godot/assets/asteroid.svg new file mode 100644 index 0000000..76b7b6e --- /dev/null +++ b/godot/assets/asteroid.svg @@ -0,0 +1,153 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/godot/assets/asteroid.svg.import b/godot/assets/asteroid.svg.import new file mode 100644 index 0000000..ac9c009 --- /dev/null +++ b/godot/assets/asteroid.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/asteroid.svg-eca243ae5a2d26805376206206297e5c.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/asteroid.svg" +dest_files=[ "res://.import/asteroid.svg-eca243ae5a2d26805376206206297e5c.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 diff --git a/godot/assets/glowing_circle.png b/godot/assets/glowing_circle.png new file mode 100644 index 0000000000000000000000000000000000000000..6e51f4f816a1a0c0e1493fd75c0b04f049009cb8 GIT binary patch literal 4138 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 literal 0 HcmV?d00001 diff --git a/godot/assets/glowing_circle.png.import b/godot/assets/glowing_circle.png.import new file mode 100644 index 0000000..da190ed --- /dev/null +++ b/godot/assets/glowing_circle.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/glowing_circle.png-49ab3290464f5a6dcf55fd0e057ae670.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/glowing_circle.png" +dest_files=[ "res://.import/glowing_circle.png-49ab3290464f5a6dcf55fd0e057ae670.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 diff --git a/godot/assets/planets.svg b/godot/assets/planets.svg new file mode 100644 index 0000000..2efaa2f --- /dev/null +++ b/godot/assets/planets.svg @@ -0,0 +1,282 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/godot/assets/planets.svg.import b/godot/assets/planets.svg.import new file mode 100644 index 0000000..a9c2fe2 --- /dev/null +++ b/godot/assets/planets.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/planets.svg-d841eda3ef3fecf8c8336304152de084.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/planets.svg" +dest_files=[ "res://.import/planets.svg-d841eda3ef3fecf8c8336304152de084.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 diff --git a/godot/assets/puff.png b/godot/assets/puff.png new file mode 100644 index 0000000000000000000000000000000000000000..e45babd8e74ddc9a120497c77206a6e6effa6fee GIT binary patch literal 1684 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 + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/godot/assets/topdown-player.svg.import b/godot/assets/topdown-player.svg.import new file mode 100644 index 0000000..4802e59 --- /dev/null +++ b/godot/assets/topdown-player.svg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/topdown-player.svg-15d45af2a50bc01de23d871062968452.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/topdown-player.svg" +dest_files=[ "res://.import/topdown-player.svg-15d45af2a50bc01de23d871062968452.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 diff --git a/godot/default_env.tres b/godot/default_env.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/godot/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/godot/icon.png b/godot/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2e42096c9664f3c8f496ec964d9989c551bda910 GIT binary patch literal 3446 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 Y0Sb~ou*ArFkN^Mx07*qoM6N<$f_ntYg8%>k literal 0 HcmV?d00001 diff --git a/godot/icon.png.import b/godot/icon.png.import new file mode 100644 index 0000000..96cbf46 --- /dev/null +++ b/godot/icon.png.import @@ -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 diff --git a/godot/project.godot b/godot/project.godot new file mode 100644 index 0000000..55983b2 --- /dev/null +++ b/godot/project.godot @@ -0,0 +1,42 @@ +; 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": "Line2D", +"class": "Trail2D", +"language": "GDScript", +"path": "res://Trail/Trail2D.gd" +} ] +_global_script_class_icons={ +"Trail2D": "" +} + +[application] + +config/name="VFX Secrets: Design 2D Visual Effects" +config/icon="res://icon.png" + +[input] + +fire_weapon={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) + ] +} +slash={ +"deadzone": 0.5, +"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null) + ] +} + +[rendering] + +environment/default_clear_color=Color( 0.196078, 0.160784, 0.278431, 1 ) +environment/default_environment="res://default_env.tres" diff --git a/img/explosion_1.png b/img/explosion_1.png new file mode 100644 index 0000000000000000000000000000000000000000..88d67d8f4075e6eb4e1e1aa5409e273c9a076be6 GIT binary patch literal 33447 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