• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GML [SOLVED] grid-based water (Terraria etc)

N

noino

Guest
I'm struggling a little bit with implementing water into my game. I understand vaguely how it should work, but I fail to execute it at any decent level.

It works for the most part, but in large volumes it just floods the whole area without deflating from the source. this video should explain it a bit:


Any help with perfecting the water mechanics is greatly appreciated and dont hesitate to ask more questions if my post is too unclear. :)

Code:
for(var xx = (view_xview-175) div 35; xx < (view_xview+view_wview+175) div 35; xx++;){
    for(var yy = (view_yview) div 35; yy < (view_yview+(view_hview)) div 35; yy++;){
        if(xx*35 > 35 and yy*35 > 35 and xx*35 < room_width-35 and yy*35 < room_height-35){
            if(watergrid[# xx,yy] > 0){
          
                var rand = choose(-1,1);
                if(watergrid[# xx,yy] > 7) watergrid[# xx,yy] = 7;
                if(obj_grid.collidegrid[# xx,yy+1] = 0 and watergrid[# xx,yy+1] < 7){
                    if(watergrid[# xx,yy+1] <= 0){
                        watergrid[# xx,yy+1] = watergrid[# xx,yy];
                        watergrid[# xx,yy] = 0;
                    }else{
                        while(watergrid[# xx,yy+1] < 7 and watergrid[# xx,yy] > 0){
                            watergrid[# xx,yy+1] += 1;
                            watergrid[# xx,yy] -= 1;
                        }
                    }
                }else if(obj_grid.collidegrid[# xx-(1*rand),yy] = 0 and watergrid[# xx-(1*rand),yy] < 7 and watergrid[# xx,yy] != watergrid[# xx-(1*rand),yy] and watergrid[# xx,yy] > 0){
                    if(watergrid[# xx-(1*rand),yy] <= 0){
                        watergrid[# xx-(1*rand),yy] = watergrid[# xx,yy]/2;
                        watergrid[# xx,yy] = watergrid[# xx-(1*rand),yy];
                    }else{
                        while(watergrid[# xx-(1*rand),yy] < watergrid[# xx,yy]){
                            watergrid[# xx-(1*rand),yy] += 1;
                            watergrid[# xx,yy] -= 1;
                        }
                    }
                }else if(obj_grid.collidegrid[# xx+(1*rand),yy] = 0 and watergrid[# xx+(1*rand),yy] < 7 and watergrid[# xx,yy] != watergrid[# xx+(1*rand),yy] and watergrid[# xx,yy] > 0){
                    if(watergrid[# xx+(1*rand),yy] <= 0){
                        watergrid[# xx+(1*rand),yy] = watergrid[# xx,yy]/2;
                        watergrid[# xx,yy] = watergrid[# xx-(1*rand),yy];
                    }else if(watergrid[# xx+(1*rand),yy] < watergrid[# xx,yy]){
                        while(watergrid[# xx+(1*rand),yy] < watergrid[# xx,yy]){
                            watergrid[# xx+(1*rand),yy] += 1;
                            watergrid[# xx,yy] -= 1;
                        }
                    }else{
                        if(watergrid[# xx,yy] >= 7){
                            watergrid[# xx,yy] -= 1;
                        }
                    }
                }
                if(watergrid[# xx,yy] < 7 and watergrid[# xx,yy] >= 6 and watergrid[# xx,yy-1] > 0){
                    watergrid[# xx,yy] = 7;
                }
            }
        }
    }
}
 
Last edited by a moderator:

Simon Gust

Member
A thing that could be a problem is dividing water by 2, I'm not sure though.
Try putting a div wherever there is a /.
(line 20, pos 74 and line 30, pos 74)
 
N

noino

Guest
A thing that could be a problem is dividing water by 2, I'm not sure though.
Try putting a div wherever there is a /.
(line 20, pos 74 and line 30, pos 74)
oh wow that worked. Thank you!
EDIT: something that is much harder to change is how it produces the same effects anyway because it doesn't update while offscreen. Is there any way I can update the entire room's water (~150,000x25,000) with minimal frame loss?
 
Last edited by a moderator:

Yal

šŸ§ *penguin noises*
GMC Elder
EDIT: something that is much harder to change is how it produces the same effects anyway because it doesn't update while offscreen. Is there any way I can update the entire room's water (~150,000x25,000) with minimal frame loss?
Probably, but you need to cut corners for speed reasons.
  • Update chunks of 2x2 / 4x4 grid cells at once when possible and you cut the processing time down to 25% and 1.5%, respectively, albeit at a loss of precision.
  • Update water less often but several steps at a time.
  • Process different parts/regions of the water every step to spread the load thinner. You could combine it with the 'several steps at a time' approach or just hope that the player being far away means you'll be able to get the correct results before they're back, even if you update it much slower than usual.
  • Ignore water that is far enough away from the player altogether, they probably won't see changes until much later. If there's no fast-travel or teleportation, players are unlikely to get this far away before enough changes has propagated. If there is, you could make a note that "water in region XYZ started doing major stuff" and keep processing that until it settles, then make it not update until next time the player gets close enough.
 
Top