Asset - Extension Fluid Dynamics - GM Studio 2

Dragon47

Member


This thread is for the GM Studio 2 version of Fluid Dynamics.
GM Studio 1 version: https://forum.yoyogames.com/index.php?threads/fluid-dynamics.23643/

The video and screenshots below are taken from the GM Studio 1 version of this asset. The GM Studio 2 version's fluid has a slightly different behavior. You can download and run the demo below to see the fluid behavior of the GM Studio 2 version.

Download demo: https://1drv.ms/u/s!AppH38QcoEBfiKVG-WQg4K02ARzqaA

Marketplace link: https://marketplace.yoyogames.com/assets/5402/fluid-dynamics-gm-studio-2

This asset provides you with realistic fluid simulation and visualization for your games. It includes a guide, a well-commented example, and documentation for each script making it easy to implement it into your game. The physics and visualization are done with shaders, making the fluid simulation very fast. The asset is highly customizable, letting you tweak the fluids extensively. It can be used to simulate fire, smoke, gas, dye, dust, wind, water droplets, cloud formation, and much more. Development and testing has only been done with the windows VM target and the windows YYC target, you might run into problems if you use this asset with other targets.

Features:
  • Can simulate fire, smoke, gas, dye, dust, wind, water droplets, cloud formation, and much more.
  • Using new mathematics from 2014 making fluid simulation faster than ever before.
  • Instances can be pushed around by the velocity field of the simulation.
  • Custom collision masks from sprites and surfaces.
  • Can be tweaked to imitate versions of explosions and tornadoes.
  • 9 different example implementations of fluids.
  • Can be used in small, large and infinite game worlds.
  • Everything is highly customizable, built on top of a fundamental fluid simulation.
  • Custom shaders.
  • A guide for implementation.
  • Commented and organized code.
  • Fast and optimized, made with efficiency in mind.
  • Custom time step.
  • Customizable acceleration equation.
  • Optional dissipation of fluid velocity and material.
  • All in GML and GLSL ES.


Screenshots:











 
Last edited:

Dragon47

Member
Is anything planned to make it work with YYC?
There's no errors in the compile error section or the syntax error section of the IDE.
When I try to compile I get an error window (one of those with a "send report" button) popping up and it won't run. There's no clear description as to what is causing the error, so it would take some time to figure out.
I have reported the bug. Maybe I'll manage to fix it later at some point.
 

Dragon47

Member
Windows YYC is now working perfectly. The issue was related to my GM Studio 2 setup, and not the asset itself.
 
B

Bahcasin

Guest
Hi, I'm loving the asset, well worth the purchase.

What I'm struggling with is the simple side of things, I'm trying to set up a simple fluid dynamics effect and I'm doing something wrong following the instructions or cannibalising the example program.

Would I be able to get some example code? something I can paste to an empty object that works and is visual, just like an effect that is there(like a flame) so I can start to experiment with it. I should be able to work out what I’m doing wrong from that.

Ultimately I'm going for a goo like effect that the player swims through :)
 

Dragon47

Member
Hi, I'm loving the asset, well worth the purchase.

What I'm struggling with is the simple side of things, I'm trying to set up a simple fluid dynamics effect and I'm doing something wrong following the instructions or cannibalising the example program.

Would I be able to get some example code? something I can paste to an empty object that works and is visual, just like an effect that is there(like a flame) so I can start to experiment with it. I should be able to work out what I’m doing wrong from that.

Ultimately I'm going for a goo like effect that the player swims through :)
Each of the examples has their own room. If you look at the room name of the example you want to keep, you can use that when going through the example code to try to get a better understanding. Tell me if you're still having issues after trying this.
 
S

Snayff

Guest
@Dragon47 The asset looks great, especially the pixel fire. However, I am struggling to get it running outside of the example rooms. I have copied out all of the code that relates to the pixel fire from "obj_fd_example_main" but I am getting errors. Any help you can offer would be greatly appreciated!

Code:
___________________________________________
############################################################################################
ERROR in
action number 1
of Draw Event
for object oFire:

Trying to draw non-existing sprite.
 at gml_Script_draw_background_stretched (line 9) - draw_sprite_stretched(argument0, 0, argument1, argument2, argument3, argument4);
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_draw_background_stretched (line 9)
called from - gml_Object_oFire_Draw_0 (line 4) - draw_background_stretched(__background_get( e__BG.Index, 1 ), 0, 0, oViewController.idealWidth, oViewController.idealHeight);

Having looked through the code I found references to the layers as named in the example rooms (in get/set background scripts) but renaming them to my layer names didn't fix the issue. I also tried with both my idealHeight variable and the original world_height.

Am I missing something obvious?
 

Dragon47

Member
@Dragon47 The asset looks great, especially the pixel fire. However, I am struggling to get it running outside of the example rooms. I have copied out all of the code that relates to the pixel fire from "obj_fd_example_main" but I am getting errors. Any help you can offer would be greatly appreciated!

Code:
___________________________________________
############################################################################################
ERROR in
action number 1
of Draw Event
for object oFire:

Trying to draw non-existing sprite.
 at gml_Script_draw_background_stretched (line 9) - draw_sprite_stretched(argument0, 0, argument1, argument2, argument3, argument4);
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_draw_background_stretched (line 9)
called from - gml_Object_oFire_Draw_0 (line 4) - draw_background_stretched(__background_get( e__BG.Index, 1 ), 0, 0, oViewController.idealWidth, oViewController.idealHeight);

Having looked through the code I found references to the layers as named in the example rooms (in get/set background scripts) but renaming them to my layer names didn't fix the issue. I also tried with both my idealHeight variable and the original world_height.

Am I missing something obvious?
draw_background_stretched is just a visual thing unrelated to the fluids. It draws the backgrounds and foregrounds in the examples. When I ported the project over from GMS 1, it was automatically created for compatibility. You can just as well use draw_sprite or draw_sprite_stretched in your own implementation.
 
S

Snayff

Guest
Thanks for coming back to me. I tried without the draw_background but it still isnt working; nothing shows on screen at all. I have copied below all of the code I have taken from your examples. Can you spot anything conspicuous by its absence?

Code:
// Clears the rectangle so there's no fluid left in it.
fd_rectangle_clear(fd_rectangle);

// Sets various parameters for the fluid behavior
fd_rectangle_set_visualization_shader(fd_rectangle, FD_VISUALIZATION_SHADER.PIXEL_ART_FIRE);
fd_rectangle_set_collision_mask_sprite(fd_rectangle, spr_fd_example_fluid_collision_mask_normal, 0);
fd_rectangle_set_material_type(fd_rectangle, FD_MATERIAL_TYPE.A_16);
fd_rectangle_set_velocity_time_step(fd_rectangle, 1);
fd_rectangle_set_material_time_step(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_value(fd_rectangle, 0.025);
fd_rectangle_set_velocity_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_velocity_dissipation_value(fd_rectangle, 0);
fd_rectangle_set_velocity_maccormack_weight(fd_rectangle, 1);
fd_rectangle_set_material_maccormack_weight(fd_rectangle, 0);
fd_rectangle_set_pressure_iteration_type(fd_rectangle, -1);
fd_rectangle_set_pressure_size(fd_rectangle, 256, 256);
fd_rectangle_set_velocity_size(fd_rectangle, 256, 256);
fd_rectangle_set_material_size(fd_rectangle, 256, 256);
fd_rectangle_set_initial_value_pressure(fd_rectangle, 0.75);
fd_rectangle_set_acceleration(fd_rectangle, 0, -0.3, 1, -0.2);

Code:
material_interpolation_enabled = false;
show_collision_mask = false;

// Creates a fluid dynamics rectangle.
fd_rectangle = fd_rectangle_create(8, 8);

//set material
material_sprite_index = 0;
material_sprite[0] = spr_fd_example_circle_gradient_small;
material_sprites = array_length_1d(material_sprite);

Code:
fd_rectangle_update(fd_rectangle);

Code:
 // Draws things behind the fluid.
draw_background_stretched(__background_get( e__BG.Index, 1 ), 0, 0, oViewController.idealWidth, oViewController.idealHeight);

var visualization_shader_previous = fd_rectangle_get_visualization_shader(fd_rectangle);

// Draws the fluid.
fd_rectangle_draw_stretched(fd_rectangle, 0, 0, oViewController.idealWidth, oViewController.idealHeight, c_white, 1, material_interpolation_enabled);


// Draws things above the fluid.
draw_background_stretched(__background_get( e__BG.Index, 2 ), 0, 0,oViewController.idealWidth, oViewController.idealHeight);


// Draws the collision mask if visible (for debug).
if (show_collision_mask) draw_surface_stretched(fd_rectangle_get_collision_mask_surface(fd_rectangle), 0, 0, oViewController.idealWidth, oViewController.idealHeight);

// Resets the visualization shader in case a debug visualization shader was used (the velocity, velocity divergence, or pressure visualization shader).
fd_rectangle_set_visualization_shader(fd_rectangle, visualization_shader_previous);
 

Dragon47

Member
Thanks for coming back to me. I tried without the draw_background but it still isnt working; nothing shows on screen at all. I have copied below all of the code I have taken from your examples. Can you spot anything conspicuous by its absence?

Code:
// Clears the rectangle so there's no fluid left in it.
fd_rectangle_clear(fd_rectangle);

// Sets various parameters for the fluid behavior
fd_rectangle_set_visualization_shader(fd_rectangle, FD_VISUALIZATION_SHADER.PIXEL_ART_FIRE);
fd_rectangle_set_collision_mask_sprite(fd_rectangle, spr_fd_example_fluid_collision_mask_normal, 0);
fd_rectangle_set_material_type(fd_rectangle, FD_MATERIAL_TYPE.A_16);
fd_rectangle_set_velocity_time_step(fd_rectangle, 1);
fd_rectangle_set_material_time_step(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_value(fd_rectangle, 0.025);
fd_rectangle_set_velocity_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_velocity_dissipation_value(fd_rectangle, 0);
fd_rectangle_set_velocity_maccormack_weight(fd_rectangle, 1);
fd_rectangle_set_material_maccormack_weight(fd_rectangle, 0);
fd_rectangle_set_pressure_iteration_type(fd_rectangle, -1);
fd_rectangle_set_pressure_size(fd_rectangle, 256, 256);
fd_rectangle_set_velocity_size(fd_rectangle, 256, 256);
fd_rectangle_set_material_size(fd_rectangle, 256, 256);
fd_rectangle_set_initial_value_pressure(fd_rectangle, 0.75);
fd_rectangle_set_acceleration(fd_rectangle, 0, -0.3, 1, -0.2);

Code:
material_interpolation_enabled = false;
show_collision_mask = false;

// Creates a fluid dynamics rectangle.
fd_rectangle = fd_rectangle_create(8, 8);

//set material
material_sprite_index = 0;
material_sprite[0] = spr_fd_example_circle_gradient_small;
material_sprites = array_length_1d(material_sprite);

Code:
fd_rectangle_update(fd_rectangle);

Code:
 // Draws things behind the fluid.
draw_background_stretched(__background_get( e__BG.Index, 1 ), 0, 0, oViewController.idealWidth, oViewController.idealHeight);

var visualization_shader_previous = fd_rectangle_get_visualization_shader(fd_rectangle);

// Draws the fluid.
fd_rectangle_draw_stretched(fd_rectangle, 0, 0, oViewController.idealWidth, oViewController.idealHeight, c_white, 1, material_interpolation_enabled);


// Draws things above the fluid.
draw_background_stretched(__background_get( e__BG.Index, 2 ), 0, 0,oViewController.idealWidth, oViewController.idealHeight);


// Draws the collision mask if visible (for debug).
if (show_collision_mask) draw_surface_stretched(fd_rectangle_get_collision_mask_surface(fd_rectangle), 0, 0, oViewController.idealWidth, oViewController.idealHeight);

// Resets the visualization shader in case a debug visualization shader was used (the velocity, velocity divergence, or pressure visualization shader).
fd_rectangle_set_visualization_shader(fd_rectangle, visualization_shader_previous);
Yes, your fd_rectangle is only 8x8 pixels large (fd_rectangle_create(8, 8)), which is very small, and you don't have any code that adds fluid to the rectangle, hence there's no fluid to show.
 
S

Snayff

Guest
I read through the guide again and added the material but I still haven't got anything showing on screen. I have tried several x/y positions in the material add but nothing shows. Sometimes the screen looks a bit blurry in places, which I assume is the result of something showing, but nothing visible. I also tried different sizes, up to 256 (changing the parameters in the room create to match).

Code:
fd_rectangle_add_material(fd_rectangle, spr_fd_example_circle_gradient_small, 0, fd_rectangle.x, fd_rectangle.y, 1, 1, c_white, 1);

I appreciate your help with this, Dragon47.
 

Dragon47

Member
I read through the guide again and added the material but I still haven't got anything showing on screen. I have tried several x/y positions in the material add but nothing shows. Sometimes the screen looks a bit blurry in places, which I assume is the result of something showing, but nothing visible. I also tried different sizes, up to 256 (changing the parameters in the room create to match).

Code:
fd_rectangle_add_material(fd_rectangle, spr_fd_example_circle_gradient_small, 0, fd_rectangle.x, fd_rectangle.y, 1, 1, c_white, 1);

I appreciate your help with this, Dragon47.
You don't have to access the variables of the FD rectangle directly (I'm looking at fd_rectangle.x and fd_rectangle.y). You only have to use the scripts to manipulate and use FD rectangles. Take a look at the example code provided with the asset. There's a section there using fd_rectangle_add_material which should be helpful.
 
S

Snayff

Guest
I am not sure what I am missing mate. I have used the example as a starting point, I have tried a variety of x and y values for the draw function.

Code:
fd_rectangle_replace_material(fd_rectangle, material_sprite[material_sprite_index], 0, mouse_x_relative, mouse_y_relative, 1, 1, c_white, 1);

I am not using the mouse so I replaced the mouse_x/y with different values (other than the fd_rectangle.x/y) but none of them show. I also took out the reference to the material array and just added the sprite directly. I can't see what else I might have missed.

I have all of the below in a single object (oFire) and it looks to me like I have followed the guide's instructions.

Code:
// Clears the rectangle so there's no fluid left in it.
fd_rectangle_clear(fd_rectangle);

// Sets various parameters for the fluid behavior
fd_rectangle_set_visualization_shader(fd_rectangle, FD_VISUALIZATION_SHADER.PIXEL_ART_FIRE);
fd_rectangle_set_collision_mask_sprite(fd_rectangle, spr_fd_example_fluid_collision_mask_normal, 0);
fd_rectangle_set_material_type(fd_rectangle, FD_MATERIAL_TYPE.A_16);
fd_rectangle_set_velocity_time_step(fd_rectangle, 1);
fd_rectangle_set_material_time_step(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_value(fd_rectangle, 0.025);
fd_rectangle_set_velocity_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_velocity_dissipation_value(fd_rectangle, 0);
fd_rectangle_set_velocity_maccormack_weight(fd_rectangle, 1);
fd_rectangle_set_material_maccormack_weight(fd_rectangle, 0);
fd_rectangle_set_pressure_iteration_type(fd_rectangle, -1);
fd_rectangle_set_pressure_size(fd_rectangle, 256, 256);
fd_rectangle_set_velocity_size(fd_rectangle, 256, 256);
fd_rectangle_set_material_size(fd_rectangle, 256, 256);
fd_rectangle_set_initial_value_pressure(fd_rectangle, 0.75);
fd_rectangle_set_acceleration(fd_rectangle, 0, -0.3, 1, -0.2);

GUIDE: "First off you'll have to create a fluid dynamics rectangle with fd_rectangle_create"
Code:
material_interpolation_enabled = false;

// Creates a fluid dynamics rectangle.
fd_rectangle = fd_rectangle_create(256, 256);


GUIDE: "find a step event that you can call fd_rectangle_update in"
GUIDE: "To add fluid, you can call fd_rectangle_replace_material or fd_rectangle_add_material"
Code:
var _fireX = oFire.x / oViewController.idealWidth * fd_rectangle_get_material_width(fd_rectangle);
var _fireY = oFire.x / oViewController.idealHeight * fd_rectangle_get_material_height(fd_rectangle)

fd_rectangle_add_material(fd_rectangle, spr_fd_example_circle_gradient_small, 0, _fireX, _fireY, 1, 1, c_white, 1);

fd_rectangle_update(fd_rectangle);


GUIDE: "find a draw event to call fd_rectangle_draw in"
Code:
// Draws the fluid.
fd_rectangle_draw_stretched(fd_rectangle, 0, 0, oViewController.idealWidth, oViewController.idealHeight, c_white, 1, material_interpolation_enabled);

Sorry buddy, I am really struggling with this. Any thoughts?
 

Dragon47

Member
I am not sure what I am missing mate. I have used the example as a starting point, I have tried a variety of x and y values for the draw function.

Code:
fd_rectangle_replace_material(fd_rectangle, material_sprite[material_sprite_index], 0, mouse_x_relative, mouse_y_relative, 1, 1, c_white, 1);

I am not using the mouse so I replaced the mouse_x/y with different values (other than the fd_rectangle.x/y) but none of them show. I also took out the reference to the material array and just added the sprite directly. I can't see what else I might have missed.

I have all of the below in a single object (oFire) and it looks to me like I have followed the guide's instructions.

Code:
// Clears the rectangle so there's no fluid left in it.
fd_rectangle_clear(fd_rectangle);

// Sets various parameters for the fluid behavior
fd_rectangle_set_visualization_shader(fd_rectangle, FD_VISUALIZATION_SHADER.PIXEL_ART_FIRE);
fd_rectangle_set_collision_mask_sprite(fd_rectangle, spr_fd_example_fluid_collision_mask_normal, 0);
fd_rectangle_set_material_type(fd_rectangle, FD_MATERIAL_TYPE.A_16);
fd_rectangle_set_velocity_time_step(fd_rectangle, 1);
fd_rectangle_set_material_time_step(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_material_dissipation_value(fd_rectangle, 0.025);
fd_rectangle_set_velocity_dissipation_type(fd_rectangle, 1);
fd_rectangle_set_velocity_dissipation_value(fd_rectangle, 0);
fd_rectangle_set_velocity_maccormack_weight(fd_rectangle, 1);
fd_rectangle_set_material_maccormack_weight(fd_rectangle, 0);
fd_rectangle_set_pressure_iteration_type(fd_rectangle, -1);
fd_rectangle_set_pressure_size(fd_rectangle, 256, 256);
fd_rectangle_set_velocity_size(fd_rectangle, 256, 256);
fd_rectangle_set_material_size(fd_rectangle, 256, 256);
fd_rectangle_set_initial_value_pressure(fd_rectangle, 0.75);
fd_rectangle_set_acceleration(fd_rectangle, 0, -0.3, 1, -0.2);

GUIDE: "First off you'll have to create a fluid dynamics rectangle with fd_rectangle_create"
Code:
material_interpolation_enabled = false;

// Creates a fluid dynamics rectangle.
fd_rectangle = fd_rectangle_create(256, 256);


GUIDE: "find a step event that you can call fd_rectangle_update in"
GUIDE: "To add fluid, you can call fd_rectangle_replace_material or fd_rectangle_add_material"
Code:
var _fireX = oFire.x / oViewController.idealWidth * fd_rectangle_get_material_width(fd_rectangle);
var _fireY = oFire.x / oViewController.idealHeight * fd_rectangle_get_material_height(fd_rectangle)

fd_rectangle_add_material(fd_rectangle, spr_fd_example_circle_gradient_small, 0, _fireX, _fireY, 1, 1, c_white, 1);

fd_rectangle_update(fd_rectangle);


GUIDE: "find a draw event to call fd_rectangle_draw in"
Code:
// Draws the fluid.
fd_rectangle_draw_stretched(fd_rectangle, 0, 0, oViewController.idealWidth, oViewController.idealHeight, c_white, 1, material_interpolation_enabled);

Sorry buddy, I am really struggling with this. Any thoughts?
What is idealWidth and idealHeight? Can you send me the project?
 

Dragon47

Member
idealWidth and idealHeight are for the window and view size. Specifically they are 574.3 and 240.

Here's the fire object: https://we.tl/niDy9ZAlqh

Thanks buddy.
I meant the whole project, but I understand if you want to keep it private.
There's a typo in the step event with "_fireY = oFire.x" which should probably be "_fireY = oFire.y". Probably not the main issue though. Are you sure you have an instance of oFire placed in the room? And where is it placed?
 
S

Snayff

Guest
Good spot on the typo, I have amended that.

oFire is in the room and is created next to the player, at (416, 640) in the room.
_fireX is 185.4 and _fireY is 682.6.
In the debug oFire is set to visible and has a depth of 0.

What other info would be helpful? We have covered all of the obvious things, haven't we?

If the only way to solve this is to share the whole project then I will do so, I don't want to be obtuse when you are trying to help. However, my preference would be to avoid sharing it, yes.
 

Dragon47

Member
Good spot on the typo, I have amended that.

oFire is in the room and is created next to the player, at (416, 640) in the room.
_fireX is 185.4 and _fireY is 682.6.
In the debug oFire is set to visible and has a depth of 0.

What other info would be helpful? We have covered all of the obvious things, haven't we?

If the only way to solve this is to share the whole project then I will do so, I don't want to be obtuse when you are trying to help. However, my preference would be to avoid sharing it, yes.
If those are your values for _fireX and _fireY, then the fluid is placed outside the FD rectangle, which explains why you don't see anything. You have to place fluid inside the FD rectangle, and the FD rectangle is 256x256 large. Your oFire instance's position should be less than the idealWidth and idealHeight for _fireX and _fireY to become less than 256.
 
S

Snayff

Guest
Where is the fd_rectangle actually created? Is it just at 0,0 or is it 0,0 relative to the object creating it? How would I specify it to create on the creating object's location?
 

Dragon47

Member
Where is the fd_rectangle actually created? Is it just at 0,0 or is it 0,0 relative to the object creating it? How would I specify it to create on the creating object's location?
FD rectangles don't have any position, they're just data. They're not part of the room until drawn. You choose the position to draw it at in fd_rectangle_draw_stretched's arguments.
 
S

Snayff

Guest
It is in! I changed both the location of the material being added and the draw location. Thank you for your help mate!

upload_2018-3-4_16-51-29.png


I'll play with it from here. Thank you again for all of your help!
 
Last edited by a moderator:
J

jubjub

Guest
For me the layers behind the flames are being drawn with an outline and with less detail (see the images below). This occurs independent of whether I use PIXEL_ART_FIRE or NO_SHADER. I figure there is probably a simple fix for this but I have been unable to find it.

Without flames:
no blurr.png

With flames:
blurred flames.png

Any help is appreciated. :)
 

Dragon47

Member
For me the layers behind the flames are being drawn with an outline and with less detail (see the images below). This occurs independent of whether I use PIXEL_ART_FIRE or NO_SHADER. I figure there is probably a simple fix for this but I have been unable to find it.

Without flames:
View attachment 17872

With flames:
View attachment 17871

Any help is appreciated. :)
Add "gpu_set_texfilter(false);" after fd_rectangle_update and fd_rectangle_draw have been called. The asset enables interpolation in those scripts (at least in fd_rectangle_update, can't remember with fd_rectangle_draw), and that line of code disables it.
 
J

jubjub

Guest
Add "gpu_set_texfilter(false);" after fd_rectangle_update and fd_rectangle_draw have been called. The asset enables interpolation in those scripts (at least in fd_rectangle_update, can't remember with fd_rectangle_draw), and that line of code disables it.
Excellent! It works like a charm.

Thanks for the help, you have made a really great asset! :)
 

Relic

Member
Hi Dragon,

I'm using fluid dynamics to simulate steam. I have a lot of it working great but a few effects are still missing. I would like to have my character push steam around as it passes through the fluid, similar to the candle in your example project. I'm struggling with the difference between fd_rectangle_add_velocity and fd_rectangle_replace_velocity. I assumed that adding velocity can combine multiple effects - say a wind blowing to the right while a ruptured pipe was spurting steam up - the resultant velocity would be a combination of the two effects plus other things like how you model pressure. While replace velocity would set the velocity to the value passed, removing the effects from any other sources. You do not use replace velocity anywhere in your example project so I can't refer to how it is used in practice.

Two issues I'm facing:
  1. I can't get fd_rectangle_replace_velocity to do anything. When I add a fluid material and set the velocity with this function, the fluid just hangs there as if there is no velocity. Using fd_rectangle_add_velocity works great - why am I not achieving the same effect when replacing the velocity of a fluid rectangle that has an otherwise empty (stationary) fluid field?
  2. fd_rectangle_add_velocity behaves poorly when I try and replicate your candle example
in a step event of my fluid controller:
Code:
with player{
var k = 0.01
fd_rectangle_add_velocity(other.fd_rectangle, spr_player_collision_mask, 0, x, y, anim_dir, 1, k*pm_hspeed/pm_hspeed_max, k*pm_vspeed/pm_vspeed_max);
}
pm_hspeed/pm_hspeedmax gives the fraction of the maximum speed the player moves at and k is a scaling factor. What I intend to happen is the player's movement affects the flow of the fluid. What actually happens is the fluid is blasted away from the player, towards the top left. Adjusting k to be smaller values has no effect - and even more surprisingly, setting k=0 still produces the same bizarre effect. I would hope a stationary player would not effect the flow of the fluid. First image below shows behaviour without this line of code (I have successfully added velocity when I created the steam in the first place). 2nd image shows behaviour with the code added, hoping the player would push the steam around.

Made in GameMaker Studio 2 16_09_2018 11_07_16 AM.png Made in GameMaker Studio 2 16_09_2018 11_07_32 AM.png

EDIT:

A solution to my second problem was to not use the collision mask sprite, but one of a similar size that had a blur effect applied to it so that it had softer edges. In fact the entire system works better when using sprites that have softer edges - I knew the alpha of the pixels in the sprites is used to determine velocity calculations but didn't suspect I had to have transparency to help the system look as good as your demos.
 
Last edited:

Dragon47

Member
Hi Dragon,

I'm using fluid dynamics to simulate steam. I have a lot of it working great but a few effects are still missing. I would like to have my character push steam around as it passes through the fluid, similar to the candle in your example project. I'm struggling with the difference between fd_rectangle_add_velocity and fd_rectangle_replace_velocity. I assumed that adding velocity can combine multiple effects - say a wind blowing to the right while a ruptured pipe was spurting steam up - the resultant velocity would be a combination of the two effects plus other things like how you model pressure. While replace velocity would set the velocity to the value passed, removing the effects from any other sources. You do not use replace velocity anywhere in your example project so I can't refer to how it is used in practice.

Two issues I'm facing:
  1. I can't get fd_rectangle_replace_velocity to do anything. When I add a fluid material and set the velocity with this function, the fluid just hangs there as if there is no velocity. Using fd_rectangle_add_velocity works great - why am I not achieving the same effect when replacing the velocity of a fluid rectangle that has an otherwise empty (stationary) fluid field?
  2. fd_rectangle_add_velocity behaves poorly when I try and replicate your candle example
in a step event of my fluid controller:
Code:
with player{
var k = 0.01
fd_rectangle_add_velocity(other.fd_rectangle, spr_player_collision_mask, 0, x, y, anim_dir, 1, k*pm_hspeed/pm_hspeed_max, k*pm_vspeed/pm_vspeed_max);
}
pm_hspeed/pm_hspeedmax gives the fraction of the maximum speed the player moves at and k is a scaling factor. What I intend to happen is the player's movement affects the flow of the fluid. What actually happens is the fluid is blasted away from the player, towards the top left. Adjusting k to be smaller values has no effect - and even more surprisingly, setting k=0 still produces the same bizarre effect. I would hope a stationary player would not effect the flow of the fluid. First image below shows behaviour without this line of code (I have successfully added velocity when I created the steam in the first place). 2nd image shows behaviour with the code added, hoping the player would push the steam around.

View attachment 20689 View attachment 20690

EDIT:

A solution to my second problem was to not use the collision mask sprite, but one of a similar size that had a blur effect applied to it so that it had softer edges. In fact the entire system works better when using sprites that have softer edges - I knew the alpha of the pixels in the sprites is used to determine velocity calculations but didn't suspect I had to have transparency to help the system look as good as your demos.
Question 1 was actually a result of a bug, causing nothing to happen. I have fixed it now and uploaded new versions to both the GMS 1 and GMS 2 version of this asset.

And I see you found a fix to question 2. The input shapes should be smooth/continuous to give the fluid a better ability to spread its values.

Good luck on your game! :)
 

Relic

Member
Thanks Dragon - this is an amazing asset.

One more thing that had me stumped for a bit was how to add my own shader. I figured it out, but you may like to note for a future update that your instructions for the script that sets the visualisation shader says that I can use my own shader - but deeper in the internal code is a switch statement that only checks for the enum'd shaders. I chose to write my own shader in one of yours so that I could call on it.
 
B

Burzz

Guest
This looks like a great asset and i'm thinking about picking it up, but the description in the marketplace mentions that it was developed and tested in Windows so there's no guarantee that it'll work elsewhere. Does anyone happen to know if it'll work in OSX as well?
 

Dragon47

Member
This looks like a great asset and i'm thinking about picking it up, but the description in the marketplace mentions that it was developed and tested in Windows so there's no guarantee that it'll work elsewhere. Does anyone happen to know if it'll work in OSX as well?
I haven't heard about anyone testing it there. If someone out there has, please tell!
 

Misty

Member
Video absolutely knocked my socks off. But can you provide a list of platforms this is compatible with?
 
B

Burzz

Guest
I decided to take the plunge and buy it at the risk of it not working, and I'm happy to report it works just fine in OSX. :)

Considering there are no external dependencies and everything is being done with GML and shaders, I don't see any reason why at least all of the desktop OSes shouldn't work out of the box. The only tweaking I had to do was to solve a conflict between this asset and TweenGMS, as TweenGMS has scripts defined for "__x", "__y", "__xspeed" and "__yspeed", which are being used as local variables in __background_set_element (which appears to be a compatibility script anyway). Very minor issue.
 
Last edited by a moderator:

Dragon47

Member
Video absolutely knocked my socks off. But can you provide a list of platforms this is compatible with?
Personally I only guarantee Windows and Windows YYC. And as you can see in the post above, OSX seems to be working to the extent of what's been tested by Burzz. The game Nidhogg 2 is using either this asset or the GMS 1 version of it, and they seem to have got it working on Playstation 4, although they might have had to do some tweaks to get it working. I haven't talked to them about it.

Someone tried to get the asset working on Android without success; see the GMS1 version's forum thread for the discussion. Apart from this I can't say much.
 
I

isrzanza

Guest
Hi, I just got Fluid Dynamics but I'm struggling in implementing it in any other way than how it is set up in the example.
1) if I change the fd_rectangle_draw x,y from 0,0 the formula to calculate the relative mouse position stops working (for example, if I change the rectangle draw to 10,10, there will be a 10 pixel offset in the mouse position)

2) even when I use the "view" version of the create, update and draw functions I can't seem to figure out how to calculate the where to add material.

what I'm trying to do is the following:
like you advised in the (very very short) guide is draw a rectangle that follows the view, so only things that are visible will be simulated.
I want to be able to add material to static objects (like torches) or moving objects (like a fireball for example).
I'm struggling to do it because there is no way to actually see the rectangle, so I never know if I position it correctly or not, and also the add_material function is relative to the rectangle so each time the view moves the content follows it.

I would really appreciate some help with it :)
 

Dragon47

Member
Hi, I just got Fluid Dynamics but I'm struggling in implementing it in any other way than how it is set up in the example.
1) if I change the fd_rectangle_draw x,y from 0,0 the formula to calculate the relative mouse position stops working (for example, if I change the rectangle draw to 10,10, there will be a 10 pixel offset in the mouse position)

2) even when I use the "view" version of the create, update and draw functions I can't seem to figure out how to calculate the where to add material.

what I'm trying to do is the following:
like you advised in the (very very short) guide is draw a rectangle that follows the view, so only things that are visible will be simulated.
I want to be able to add material to static objects (like torches) or moving objects (like a fireball for example).
I'm struggling to do it because there is no way to actually see the rectangle, so I never know if I position it correctly or not, and also the add_material function is relative to the rectangle so each time the view moves the content follows it.

I would really appreciate some help with it :)
Hi, thank you for purchasing.

1) If you offset where the fluid rectangle is drawn, you will also have to offset the mouse when inputting material. This is because the fluid rectangle is an object without any position in the world. It's like a surface when it is drawn: you draw it at the desired position, and nothing else is affected. As you can see, the same goes for scaling, which is why the mouse position is scaled when inputting material.

2) The view following can be tricky to get working if you're not used to surfaces in GM. The view extension scripts are not written by me and I haven't tested them in GMS 2. It's possible without the extension, but you need to write more code. In the GMS 1 version, we have an example project linked in the guide that uses the view extension scripts. I can send you a link to this if you PM me the mail you used when purchasing the asset (proof of purchase).
 

Catastrophe

Member
Hey! Just got this for GMS2. Test it out and it looks pretty awesome! Main concerns are performance and platforms:

We've got a pretty large room (3000x1500), and the main useage we'd like to use this for is adding smoke/fire to select parts of a spaceship, with lots of smoke/fire happening potentially at once. What would your recommendations be? Creating small fd_rectangles on the fly and deleting them wherever needed? Creating a rectangle on any spot where an effect can spawn and not deleting them? Making the world 3000x1500 and rectangle 600x300 and just covering the whole room? We can do some performance tetsing of our own, but I figured I'd not waste time and ask first.

We're also releasing the game commercially, so eventually we'd like to port it to as many platforms as we can. It sounds like Windows and OSX are the only ones it's been tested on.
 

Dragon47

Member
Hey! Just got this for GMS2. Test it out and it looks pretty awesome! Main concerns are performance and platforms:

We've got a pretty large room (3000x1500), and the main useage we'd like to use this for is adding smoke/fire to select parts of a spaceship, with lots of smoke/fire happening potentially at once. What would your recommendations be? Creating small fd_rectangles on the fly and deleting them wherever needed? Creating a rectangle on any spot where an effect can spawn and not deleting them? Making the world 3000x1500 and rectangle 600x300 and just covering the whole room? We can do some performance testing of our own, but I figured I'd not waste time and ask first.

We're also releasing the game commercially, so eventually we'd like to port it to as many platforms as we can. It sounds like Windows and OSX are the only ones it's been tested on.
It has only been tested on Windows, but other people might have got it to work on OSX. I haven't tested anything else myself. As for the large rooms, I suggest creating a fd rectangle that is slightly bigger than the view and that follows it. As you move your view around, you shift the content of the simulation surfaces. This is what I have done myself, and what I think the Nidhogg 2 and Unworthy games did. If you see the "SimenGames view extension" folder in the code, there are functions for doing this created by user SimenGames. I also have a GMS 1 project that does it, that I can mail you privately in case some problems arise in the implementation.

I put some notes in the asset guide for making it more performant iirc. Or they are on another post in this thread or the GMS1 version's thread. On PC it's pretty fast. It might have a hard time on mobile, but I'm not even sure if it works there at all.
 

Catastrophe

Member
Got the view moving after a while, that was pretty helpful. Took me a while to figure out what to change these to:


//var mouse_x_relative = mouse_x / world_width * fd_rectangle_get_material_width(fd_rectangle);
//var mouse_y_relative = mouse_y / world_height * fd_rectangle_get_material_height(fd_rectangle);

var mouse_x_relative = (mouse_x - camX) / view_wport[0] * fd_rectangle_get_material_width(fd_rectangle);
var mouse_y_relative = (mouse_y - camY) / view_hport[0] * fd_rectangle_get_material_height(fd_rectangle);

But now that I get the logic behind that I can work with this :D

Btw, has anyone made like a layman's guide? I've got most things working but it is taking a while how to learn how to make it do everything I want. For instance, for making things smaller without increasing resolution (for performance sake), it sounds like the best way is to use a smaller material size, or make an even smaller one myself, right?

And from what I gather, the only way to have very different effects, like the fire + dust, in the same room, is to create two rectangles
 
Last edited:

Dragon47

Member
Got the view moving after a while, that was pretty helpful. Took me a while to figure out what to change these to:


//var mouse_x_relative = mouse_x / world_width * fd_rectangle_get_material_width(fd_rectangle);
//var mouse_y_relative = mouse_y / world_height * fd_rectangle_get_material_height(fd_rectangle);

var mouse_x_relative = (mouse_x - camX) / view_wport[0] * fd_rectangle_get_material_width(fd_rectangle);
var mouse_y_relative = (mouse_y - camY) / view_hport[0] * fd_rectangle_get_material_height(fd_rectangle);

But now that I get the logic behind that I can work with this :D

Btw, has anyone made like a layman's guide? I've got most things working but it is taking a while how to learn how to make it do everything I want. For instance, for making things smaller without increasing resolution (for performance sake), it sounds like the best way is to use a smaller material size, or make an even smaller one myself, right?

And from what I gather, the only way to have very different effects, like the fire + dust, in the same room, is to create two rectangles
For multiple effects, you can use the inherit_velocity script to avoid having to do the underlying velocity field update twice. This is much faster. Alternatively make a shader and use each color channel for separate effects.
As for the guide, I PM-ed you the project I talked about earlier. I don't really have much more than that in terms of tutorial stuff. It's for GMS1, so you'll have to download that if you don't already have it. Or try the GMS2 import, but not sure if that will work.
 

Catastrophe

Member
Nice, I'll take a look at the example.

But yeah, reducing the material size with a small rectangle + using view shifting makes this super performant. I didn't start getting lag until I made over 10 fluid dynamic rectangles. So I think I'll be able to handle two rectangles for the two kinds I want and try the inherit velocity.

Anyways, thanks for the awesome asset :D
 

Catastrophe

Member
Ooof. So we basically used your example and extended it after duplicating it.

Your fd example object has random_set_seed(123) in one of the cases and we missed it xD. That gave us a fun evening. If you're ever updating the extension you might want to remove that haha.
 
Hi all. would anyone that knows this project well have any pointers on perhaps rigging this to work well with a game that uses delta time? I'm not really sure where to start
 

Dragon47

Member
Hi all. would anyone that knows this project well have any pointers on perhaps rigging this to work well with a game that uses delta time? I'm not really sure where to start
This asset would have to be calculated at a fixed timestep. This is very common with physics engines though. I think even the included physics in GameMaker works this way. To make it work with delta time, you can for example have a timer variable you check every step to see if a fixed amount of time has passed (e.g. via get_timer() if that's still what it's called), then perform the physics update and reset the timer.
 

Lakshaya

Member
Hi,

Great asset. I have question however....

If I draw my fd_rectangle to be the size of my view, the resulting fluids that have been created look rather pixelated.

In your example, setting the pressure/velocity/material sizes to 512 makes the fire look decent, but not in my game.

How can I fix this?


Thanks,
Lakshaya
 

Dragon47

Member
Hi,

Great asset. I have question however....

If I draw my fd_rectangle to be the size of my view, the resulting fluids that have been created look rather pixelated.

In your example, setting the pressure/velocity/material sizes to 512 makes the fire look decent, but not in my game.

How can I fix this?


Thanks,
Lakshaya
Sounds like you don't have linear interpolation enabled. I think you do so with gpu_set_texfilter(true). (Back in the day it was texture_set_interpolation(true)). Then the rectangle will be stretched more smoothly
 

Lakshaya

Member
Sounds like you don't have linear interpolation enabled. I think you do so with gpu_set_texfilter(true). (Back in the day it was texture_set_interpolation(true)). Then the rectangle will be stretched more smoothly
1620849588247.png

This is what it looks like with linear interpolation enabled. Enabling it had no effect. The size of the fd rectangle is 1300 by 1300. This looks a lot better if I make it half that.
 

Lakshaya

Member
Here is my code for reference:

Rectangle set up:

fd_rectangle_set_visualization_shader(world_rectangle, FD_VISUALIZATION_SHADER.PIXEL_ART_FIRE);
fd_rectangle_set_collision_mask_sprite(world_rectangle, spr_fd_example_fluid_collision_mask_normal, 0,);
fd_rectangle_set_material_type(world_rectangle, FD_MATERIAL_TYPE.A_16);
fd_rectangle_set_velocity_time_step(world_rectangle, 3);
fd_rectangle_set_material_time_step(world_rectangle, 3);
fd_rectangle_set_material_dissipation_type(world_rectangle, 1);
fd_rectangle_set_material_dissipation_value(world_rectangle, 0.010);
fd_rectangle_set_velocity_dissipation_type(world_rectangle, 1);
fd_rectangle_set_velocity_dissipation_value(world_rectangle, 0);
fd_rectangle_set_velocity_maccormack_weight(world_rectangle, 1);
fd_rectangle_set_material_maccormack_weight(world_rectangle, 1);
fd_rectangle_set_pressure_iteration_type(world_rectangle, -2);
fd_rectangle_set_pressure_size(world_rectangle, 512, 512);
fd_rectangle_set_velocity_size(world_rectangle, 512, 512);
fd_rectangle_set_material_size(world_rectangle, 512, 512);
fd_rectangle_set_initial_value_pressure(world_rectangle, 2);
fd_rectangle_set_acceleration(world_rectangle, 0, -0.3, 1, -0.2);

fd_rectangle_draw_stretched(world_rectangle, x, y, worldWidth, worldHeight, c_white, 1, true);

world_rectangle = fd_rectangle_create(512, 512);
worldWidth = 1300;
worldHeight = 1300;
 

Dragon47

Member
Sorry for the wait, been busy.

Does that screenshot hold a full 1300x1300 fd rectangle? Or is it just a small view of the world? The flame looks like it's very small compared to the fd rectangle size. How does it look with linear interpolation turned off, and without the pixelation shader?

Might be a good idea to just mess around more with copying over code from my examples or something, since it's working over there.
 
Top