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 | } |