View difference between Paste ID: zFJLYjpK and
SHOW: | | - or go back to the newest paste.
1-
1+
package  {
2
	import flash.display.BitmapData;
3
	import flash.display.Graphics;
4
	import flash.display.Sprite;
5
	import flash.geom.Matrix;
6
	import flash.geom.Point;
7
	import flash.geom.Rectangle;
8
	import net.flashpunk.Entity;
9
	import net.flashpunk.FP;
10
	import net.flashpunk.graphics.Stamp;
11
	import net.flashpunk.masks.Grid;
12
	import net.flashpunk.utils.Draw;
13
	import net.flashpunk.utils.Input;
14
	/**
15
	 * ...
16
	 * @author grigri
17
	 */
18
	public class Water extends Entity
19
	{
20
		/* Variables */
21
		public var cells:Vector.<Vector.<int>> = new Vector.<Vector.<int>>();//contains the data.
22
		public var mass:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();//to calculate step.
23
		private var new_mass:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();// / to calculate step.
24
		
25
		private var waterMask:Grid;
26
		
27
		private var mapWidth:int = 0;
28
		private var mapHeight:int = 0;
29
		
30
		/* Constants */
31
		private const MAX_MASS:Number = 1.0;
32
		private const COMPRESSION:Number = 0.02;//how much extra water pressure in can be stored in the cell below.
33
		private const MIN_MASS:Number = 0.0001;//ignore very dry cells.
34
35
		private const MIN_FLOW:Number = 0.01;
36
		private const MAX_MOVEMENT:Number = 1;//Max units of water moved between two cells per turn.
37
		
38
		private var tilesBmp:BitmapData;
39
		private var srcRect:Rectangle = new Rectangle(0, 0, 16, 16);
40
		private var dstPoint:Point = new Point;
41
		/*
42
		private var s:Sprite;
43
		private var g:Graphics;
44
		private var m:Matrix;
45
		*/
46
		
47
		public function Water(grid:Grid, width:int, height:int) 
48
		{
49
			super(0, 0, null, waterMask);
50
			
51
			mask = waterMask = new Grid(width, height, 16, 16);
52
			mapWidth = width >> 4;
53
			mapHeight = height >> 4;
54
			
55
			//m = new Matrix;
56
			//s = new Sprite;
57
			//g = s.graphics;
58
			
59
			type = "water";
60
			
61
			var w:int, h:int;
62
			for(w = 0; w < mapWidth; w++) 
63
			{
64
				cells[w] = new Vector.<int>();
65
				mass[w] = new Vector.<Number>();
66
				new_mass[w] = new Vector.<Number>();
67
				
68
				for(h = 0; h < mapHeight; h++)
69
				{
70
					cells[w][h] = 0;
71
					mass[w][h] = 0;
72
					new_mass[w][h] = 0;
73
				}
74
			}
75
			
76
			//read grid
77
			for(w = 0; w < mapWidth; w += 2)
78
			{
79
				for(h = 0; h < mapHeight; h += 2)
80
				{
81
					if(grid.getTile(w >> 1, h >> 1))
82
					{
83
						cells[w][h] = 1;
84
						cells[w + 1][h] = 1;
85
						cells[w][h + 1] = 1;
86
						cells[w + 1][h + 1] = 1;
87
					}
88
				}
89
			}
90
			
91
			//layer = Layer.WATER;
92
			
93
			tilesBmp = new BitmapData(16 * 16, 16 * 2, true, 0);
94
			Draw.setTarget(tilesBmp);
95
			var alpha:Number;
96
			for (w = 0; w < 16; w++) {
97
				alpha = w / 15.0;
98
				if (alpha > 0.6) alpha = 0.6;
99
				Draw.rect(w * 16, 16 - w - 1, 16, w + 1, 0x5980FF, alpha, true);
100
				Draw.rect(w * 16, 16, 16, 16, 0x5980FF, alpha, true);
101
			}
102
			Draw.resetTarget();
103
		}
104
		
105
		/*
106
		override public function added():void {
107
			super.added();
108
			world.addGraphic(new Stamp(tilesBmp), 0, 0, 100);
109
		}
110
		*/
111
		
112
		override public function update():void
113
		{
114
			super.update();
115
			
116
			var flow:Number = 0;
117
			var remaining_mass:Number;
118
			var w:int, h:int, x:int, y:int;
119
			var nMass:Number = 0;
120
			
121
			for(x = mapWidth - 1; x > 0; x--)
122
			{
123
				for(y = mapHeight - 1; y > 0; y--)
124
				{
125
					if(cells[x][y] == 1) continue;//Skip ground blocks.
126
					
127
					flow = 0;
128
					remaining_mass = mass[x][y];
129
					
130
					if(remaining_mass <= 0) continue;
131
					
132
					//check flow beneath.
133
					if(y < mapHeight - 1 && cells[x][y+1] != 1)
134
					{
135
						nMass = mass[x][y + 1]
136
						//if (nMass < mass[x][y]) {
137
							flow = distributeWater(remaining_mass + nMass) - nMass;
138
							if(flow > MIN_FLOW)
139
							{
140
								flow *= 0.5;//smoothens water flow.
141
							}
142
							if (flow < 0) flow = 0;
143
							if (flow > MAX_MOVEMENT) flow = MAX_MOVEMENT;
144
							if (flow > remaining_mass) flow = remaining_mass;
145
							//flow = constrainRange(flow, 0, remaining_mass);
146
							
147
							new_mass[x][y] -= flow;
148
							new_mass[x][y + 1] += flow;
149
							remaining_mass -= flow;
150
						//}
151
					}
152
					
153
					if(remaining_mass <= 0) continue;
154
					
155
					//Check to the left.
156
					if(x > 0 && cells[x-1][y] != 1)
157
					{
158
						//if (mass[x - 1][y] < mass[x][y]) {
159
							flow = (mass[x][y] - mass[x - 1][y]) * 0.25;
160
							if(flow > MIN_FLOW)
161
							{
162
								flow *= 0.5;
163
							}
164
							if (flow < 0) flow = 0;
165
							//if (flow > MAX_MOVEMENT) flow = MAX_MOVEMENT;
166
							if (flow > remaining_mass) flow = remaining_mass;
167
							//flow = constrainRange(flow, 0, remaining_mass);
168
							
169
							new_mass[x][y] -= flow;
170
							new_mass[x - 1][y] += flow;
171
							remaining_mass -= flow;
172
						//}
173
					}
174
					
175
					if(remaining_mass <= 0) continue;
176
					
177
					//check to the right.
178
					if(x < mapWidth - 1 && cells[x+1][y] != 1)
179
					{
180
						//if (mass[x + 1][y] < mass[x][y]) {
181
							flow = (mass[x][y] - mass[x + 1][y]) * 0.25;
182
							if(flow > MIN_FLOW)
183
							{
184
								flow *= 0.5;
185
							}
186
							if (flow < 0) flow = 0;
187
							//if (flow > MAX_MOVEMENT) flow = MAX_MOVEMENT;
188
							if (flow > remaining_mass) flow = remaining_mass;
189
							//flow = constrainRange(flow, 0, remaining_mass);
190
							
191
							new_mass[x][y] -= flow;
192
							new_mass[x + 1][y] += flow;
193
							remaining_mass -= flow;
194
						//}
195
					}
196
					
197
					if(remaining_mass <= 0) continue;
198
					
199
					//Up. Only compressed water should flows upwards.
200
					if(y > 0 && cells[x][y-1] != 1)
201
					{
202
						//if (mass[x][y-1] < remaining_mass) {
203
							flow = remaining_mass - distributeWater(remaining_mass + mass[x][y - 1]);
204
							if(flow > MIN_FLOW)
205
							{
206
								flow *= 0.5;
207
							}
208
							if (flow < 0) flow = 0;
209
							if (flow > MAX_MOVEMENT) flow = MAX_MOVEMENT;
210
							if (flow > remaining_mass) flow = remaining_mass;
211
							//flow = constrainRange(flow, 0, (MAX_MOVEMENT < remaining_mass) ? MAX_MOVEMENT : remaining_mass);
212
							
213
							new_mass[x][y] -= flow;
214
							new_mass[x][y - 1] += flow;
215
							remaining_mass -= flow;
216
						//}
217
					}
218
				}
219
			}
220
			
221
			//generate water.
222
			if (Input.mouseDown)
223
			{
224
				var xPos:int = world.mouseX >> 4;
225
				var yPos:int = world.mouseY >> 4;
226
				if(xPos < 0) xPos = 0;
227
				if(xPos > mapWidth - 1) xPos = mapWidth - 1; 
228
				if(yPos < 0) yPos = 0;
229
				if(yPos > mapHeight - 1) yPos = mapHeight - 1; 
230
				if (cells[xPos][yPos] != 1)
231
				{
232
					cells[xPos][yPos] = 2;
233
					//mass[xPos][yPos] = 1;
234
					new_mass[xPos][yPos] = 1;
235
				}
236
			}
237
			
238
			for(w = 0; w < mapWidth; w++)
239
			{
240
				mass[w][0] = 0;
241
				mass[w][mapHeight - 1] = 0;
242
				
243
				for(h = 0; h < mapHeight; h++)
244
				{
245
					nMass = new_mass[w][h];
246
					//mass[w][h] = nMass;
247
					
248
249
					if (cells[w][h] == 1) {
250
						//waterMask.clearTile(w, h);
251
					}
252
					else
253
					{
254
						if (mass[w][h] != nMass) {
255
256
						cells[w][h] = nMass > MIN_MASS ? 2 : 0;
257
						waterMask.setTile(w, h, nMass > 0.5);
258
259
						mass[w][h] = nMass;
260
						}
261
262
					}
263
				}
264
			}
265
			
266
			for (h = 0; h < mapHeight; h++)
267
			{
268
				mass[0][h] = 0;
269
				mass[mapWidth - 1][h] = 0;
270
			}
271
		}
272
		
273
		private function distributeWater(total_mass:Number):Number
274
		{
275
			if ( total_mass <= 1 ) 
276
			{
277
				return 1;
278
			}
279
			else if ( total_mass < 2.02) //else if ( total_mass < 2 * MAX_MASS + COMPRESSION) 
280
			{
281
				return (1 + total_mass * 0.02) * 0.98;// / 1.02; //return (MAX_MASS + total_mass * COMPRESSION) / (MAX_MASS + COMPRESSION);
282
			}
283
			else
284
			{
285
				return (total_mass + COMPRESSION) * 0.5;
286
			}
287
		}
288
		
289
		private function constrainRange(value:Number, min:Number, max:Number):Number
290
		{
291
			if (value > max) return max;
292
			else if (value < min) return min;
293
			else return value;
294
		}
295
		
296
		protected function solid(x:int, y:int):Boolean
297
		{
298
			var n:int = cells[x][y]
299
			return n == 1;
300
		}
301
		
302
		protected function water(x:int, y:int):Boolean
303
		{
304
			return cells[x][y] == 2;
305
		}
306
		
307
		override public function render():void
308
		{
309
			var nMass:Number = 0;
310
			//var x:Number = 16, y:Number = 16;
311
			var height:Number, alpha:Number;
312
			
313
			dstPoint.x = 16;// - FP.camera.x;
314
			dstPoint.y = 16;// - FP.camera.y;
315
			
316
			//Draw.resetTarget();
317
			
318
			for(var w:int = 1; w < mapWidth - 1; w++)
319
			{
320
				for(var h:int = 1; h < mapHeight - 1; h++)
321
				{
322
					nMass = mass[w][h];
323
					//var x:Number = w << 4;
324
					//var y:Number = h << 4;
325
					
326
					if(cells[w][h] == 2)
327
					{
328
						height = mass[w][h];
329
						if (height < 0) continue;// height = 0;
330
						if (height > 1) height = 1;
331
						
332
						srcRect.x = Math.ceil(height * 15) * 16;
333
						//alpha = height;
334
						//height *= 16;
335
						//if (alpha > 0.6) alpha = 0.6;
336
						/*
337
						var height:Number = (16 * constrainRange(mass[w][h], 0, 1));
338
						va
339
						g.beginFill(0x5980FF, constrainRange(nMass, 0, 0.6));
340
						*/
341
						if((cells[w][h - 1] != 2) && (cells[w + 1][h - 1] != 2))
342
						{
343
							srcRect.y = 0;
344
							//Draw.rect(x, y + (16 - height), 16, height, 0x5980FF, alpha, true);
345
							//g.drawRect(x, y + (16 - height), 16, height);
346
						}
347
						else {
348
							srcRect.y = 16;
349
							//Draw.rect(x, y, 16, 16, 0x5980FF, alpha, true);
350
							//g.drawRect(x, y, 16, 16);
351
						}
352
						FP.buffer.copyPixels(tilesBmp, srcRect, dstPoint);
353
					}
354
					dstPoint.y += 16;
355
				}
356
				dstPoint.y = 16;
357
				dstPoint.x += 16;
358
			}
359
			
360
			//m.tx = -FP.camera.x;
361
			//m.ty = -FP.camera.y;
362
			//FP.buffer.draw(s, m);
363
			//g.clear();
364
		}
365
	}
366
367
368
}