Advertisement
Rolpege

Water, by Chris Thodesen

Jul 15th, 2011
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package com.aberustudios.kodama.objects
  2. {
  3.     import com.aberustudios.kodama.Layer;
  4.    
  5.     import flash.display.Graphics;
  6.     import flash.display.Sprite;
  7.     import flash.geom.Matrix;
  8.    
  9.     import net.flashpunk.Entity;
  10.     import net.flashpunk.FP;
  11.     import net.flashpunk.graphics.Image;
  12.     import net.flashpunk.masks.Grid;
  13.     import net.flashpunk.utils.Draw;
  14.     import net.flashpunk.utils.Input;
  15.    
  16.     public class Water extends Entity
  17.     {
  18.         /* Variables */
  19.         public var cells:Vector.<Vector.<int>> = new Vector.<Vector.<int>>();//contains the data.
  20.         public var mass:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();//to calculate step.
  21.         private var new_mass:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();// / to calculate step.
  22.        
  23.         private var waterMask:Grid;
  24.        
  25.         private var mapWidth:int = 0;
  26.         private var mapHeight:int = 0;
  27.        
  28.         /* Constants */
  29.         private const MAX_MASS:Number = 1.0;
  30.         private const COMPRESSION:Number = 0.02;//how much extra water pressure in can be stored in the cell below.
  31.         private const MIN_MASS:Number = 0.0001;//ignore very dry cells.
  32.  
  33.         private const MIN_FLOW:Number = 0.01;
  34.         private const MAX_MOVEMENT:Number = 1;//Max units of water moved between two cells per turn.
  35.        
  36.         private var s:Sprite;
  37.         private var g:Graphics;
  38.         private var m:Matrix;
  39.        
  40.         public function Water(grid:Grid, width:int, height:int)
  41.         {
  42.             super(0, 0, null, waterMask);
  43.            
  44.             mask = waterMask = new Grid(width, height, 16, 16);
  45.             mapWidth = width >> 4;
  46.             mapHeight = height >> 4;
  47.            
  48.             m = new Matrix;
  49.             s = new Sprite;
  50.             g = s.graphics;
  51.            
  52.             type = "water";
  53.            
  54.             var w:int, h:int;
  55.             for(w = 0; w < mapWidth; w++)
  56.             {
  57.                 cells[w] = new Vector.<int>();
  58.                 mass[w] = new_mass[w] = new Vector.<Number>();
  59.                
  60.                 for(h = 0; h < mapHeight; h++)
  61.                 {
  62.                     cells[w][h] = 0;
  63.                     mass[w][h] = new_mass[w][h] = 0;
  64.                 }
  65.             }
  66.            
  67.             //read grid
  68.             for(w = 0; w < mapWidth; w += 2)
  69.             {
  70.                 for(h = 0; h < mapHeight; h += 2)
  71.                 {
  72.                     if(grid.getTile(w >> 1, h >> 1))
  73.                     {
  74.                         cells[w][h] = 1;
  75.                         cells[w + 1][h] = 1;
  76.                         cells[w][h + 1] = 1;
  77.                         cells[w + 1][h + 1] = 1;
  78.                     }
  79.                 }
  80.             }
  81.            
  82.             layer = Layer.WATER;
  83.         }
  84.        
  85.         override public function update():void
  86.         {
  87.             super.update();
  88.            
  89.             var flow:Number = 0;
  90.             var remaining_mass:Number;
  91.             var w:int, h:int, x:int, y:int;
  92.             var nMass:Number = 0;
  93.            
  94.             for(x = mapWidth - 1; x > 0; x--)
  95.             {
  96.                 for(y = mapHeight - 1; y > 0; y--)
  97.                 {
  98.                     if(solid(x, y)) continue;//Skip ground blocks.
  99.                    
  100.                     flow = 0;
  101.                     remaining_mass = mass[x][y];
  102.                    
  103.                     if(remaining_mass <= 0) continue;
  104.                    
  105.                     //check flow beneath.
  106.                     if(!solid(x, y + 1))
  107.                     {
  108.                         nMass = mass[x][y + 1]
  109.                         flow = distributeWater(remaining_mass + nMass) - nMass;
  110.                         if(flow > MIN_FLOW)
  111.                         {
  112.                             flow *= 0.5;//smoothens water flow.
  113.                         }
  114.                         flow = constrainRange(flow, 0, (MAX_MOVEMENT < remaining_mass) ? MAX_MOVEMENT : remaining_mass);
  115.                        
  116.                         new_mass[x][y] -= flow;
  117.                         new_mass[x][y + 1] += flow;
  118.                         remaining_mass -= flow;
  119.                     }
  120.                    
  121.                     if(remaining_mass <= 0) continue;
  122.                    
  123.                     //Check to the left.
  124.                     if(!solid(x - 1, y))
  125.                     {
  126.                         flow = (mass[x][y] - mass[x - 1][y]) * 0.25;
  127.                         if(flow > MIN_FLOW)
  128.                         {
  129.                             flow *= 0.5;
  130.                         }
  131.                         flow = constrainRange(flow, 0, remaining_mass);
  132.                        
  133.                         new_mass[x][y] -= flow;
  134.                         new_mass[x - 1][y] += flow;
  135.                         remaining_mass -= flow;
  136.                     }
  137.                    
  138.                     if(remaining_mass <= 0) continue;
  139.                    
  140.                     //check to the right.
  141.                     if(!solid(x + 1, y))
  142.                     {
  143.                         flow = (mass[x][y] - mass[x + 1][y]) * 0.25;
  144.                         if(flow > MIN_FLOW)
  145.                         {
  146.                             flow *= 0.5;
  147.                         }
  148.                         flow = constrainRange(flow, 0, remaining_mass);
  149.                        
  150.                         new_mass[x][y] -= flow;
  151.                         new_mass[x + 1][y] += flow;
  152.                         remaining_mass -= flow;
  153.                     }
  154.                    
  155.                     if(remaining_mass <= 0) continue;
  156.                    
  157.                     //Up. Only compressed water should flows upwards.
  158.                     if(!solid(x, y - 1))
  159.                     {
  160.                         flow = remaining_mass - distributeWater(remaining_mass + mass[x][y - 1]);
  161.                         if(flow > MIN_FLOW)
  162.                         {
  163.                             flow *= 0.5;
  164.                         }
  165.                         flow = constrainRange(flow, 0, (MAX_MOVEMENT < remaining_mass) ? MAX_MOVEMENT : remaining_mass);
  166.                        
  167.                         new_mass[x][y] -= flow;
  168.                         new_mass[x][y - 1] += flow;
  169.                         remaining_mass -= flow;
  170.                     }
  171.                 }
  172.             }
  173.            
  174.             //generate water.
  175.             /*if (Input.mouseDown)
  176.             {
  177.                 var xPos:int = world.mouseX >> 4;
  178.                 var yPos:int = world.mouseY >> 4;
  179.                 if(xPos < 0) xPos = 0;
  180.                 if(xPos > mapWidth - 1) xPos = mapWidth - 1;
  181.                 if(yPos < 0) yPos = 0;
  182.                 if(yPos > mapHeight - 1) yPos = mapHeight - 1;
  183.                 if (cells[xPos][yPos] != 1)
  184.                 {
  185.                     cells[xPos][yPos] = 2;
  186.                     mass[xPos][yPos] = 1;
  187.                 }
  188.             }*/
  189.            
  190.             for(w = 0; w < mapWidth; w++)
  191.             {
  192.                 mass[w][0] = 0;
  193.                 mass[w][mapHeight - 1] = 0;
  194.                
  195.                 for(h = 0; h < mapHeight; h++)
  196.                 {
  197.                     nMass = new_mass[w][h];
  198.                     mass[w][h] = nMass;
  199.                    
  200.                     if(cells[w][h] == 1) waterMask.clearTile(w, h);
  201.                     else
  202.                     {
  203.                         cells[w][h] = nMass > MIN_MASS ? 2 : 0;
  204.                         waterMask.setTile(w, h, nMass > 0.5);
  205.                     }
  206.                 }
  207.             }
  208.            
  209.             for (h = 0; h < mapHeight; h++)
  210.             {
  211.                 mass[0][h] = 0;
  212.                 mass[mapWidth - 1][h] = 0;
  213.             }
  214.         }
  215.        
  216.         private function distributeWater(total_mass:Number):Number
  217.         {
  218.             if ( total_mass <= 1 )
  219.             {
  220.                 return 1;
  221.             }
  222.             else if ( total_mass < 2.02) //else if ( total_mass < 2 * MAX_MASS + COMPRESSION)
  223.             {
  224.                 return (1 + total_mass * 0.02) * 0.98;// / 1.02; //return (MAX_MASS + total_mass * COMPRESSION) / (MAX_MASS + COMPRESSION);
  225.             }
  226.             else
  227.             {
  228.                 return (total_mass + COMPRESSION) * 0.5;
  229.             }
  230.         }
  231.        
  232.         private function constrainRange(value:Number, min:Number, max:Number):Number
  233.         {
  234.             if (value > max) return max;
  235.             else if (value < min) return min;
  236.             else return value;
  237.         }
  238.        
  239.         protected function solid(x:int, y:int):Boolean
  240.         {
  241.             var n:int = cells[x][y]
  242.             return n == 1;
  243.         }
  244.        
  245.         protected function water(x:int, y:int):Boolean
  246.         {
  247.             return cells[x][y] == 2;
  248.         }
  249.        
  250.         override public function render():void
  251.         {
  252.             var nMass:Number = 0;
  253.            
  254.             for(var w:int = 1; w < mapWidth - 1; w++)
  255.             {
  256.                 for(var h:int = 1; h < mapHeight - 1; h++)
  257.                 {
  258.                     nMass = mass[w][h];
  259.                     var x:Number = w << 4;
  260.                     var y:Number = h << 4;
  261.                    
  262.                     if(cells[w][h] == 2)
  263.                     {
  264.                         var height:Number = (16 * constrainRange(mass[w][h], 0, 1));
  265.                         g.beginFill(0x5980FF, constrainRange(nMass, 0, 0.6));
  266.                        
  267.                         if((cells[w][h - 1] != 2) && (cells[w + 1][h - 1] != 2))
  268.                         {
  269.                             g.drawRect(x, y + (16 - height), 16, height);
  270.                         }
  271.                         else g.drawRect(x, y, 16, 16);
  272.                     }
  273.                 }
  274.             }
  275.            
  276.             m.tx = -FP.camera.x;
  277.             m.ty = -FP.camera.y;
  278.             FP.buffer.draw(s, m);
  279.             g.clear();
  280.         }
  281.     }
  282.    
  283. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement