18 |
18 |
19 unit uLand; |
19 unit uLand; |
20 interface |
20 interface |
21 uses SDLh, uLandTemplates, uFloat, GL, uConsts; |
21 uses SDLh, uLandTemplates, uFloat, GL, uConsts; |
22 {$include options.inc} |
22 {$include options.inc} |
23 type TLandArray = packed array[0..1023, 0..2047] of LongWord; |
23 type TLandArray = packed array[0..LAND_HEIGHT, 0..LAND_WIDTH] of LongWord; |
24 TPreview = packed array[0..127, 0..31] of byte; |
24 TPreview = packed array[0..127, 0..31] of byte; |
25 TDirtyTag = packed array[0..31, 0..63] of byte; |
25 TDirtyTag = packed array[0..63, 0..127] of byte; |
26 |
26 |
27 var Land: TLandArray; |
27 var Land: TLandArray; |
28 LandPixels: TLandArray; |
28 LandPixels: TLandArray; |
29 LandTexture: PTexture = nil; |
29 LandTexture: PTexture = nil; |
30 LandDirty: TDirtyTag; |
30 LandDirty: TDirtyTag; |
243 |
243 |
244 procedure Push(_xl, _xr, _y, _dir: LongInt); |
244 procedure Push(_xl, _xr, _y, _dir: LongInt); |
245 begin |
245 begin |
246 TryDo(Stack.Count <= 8192, 'FillLand: stack overflow', true); |
246 TryDo(Stack.Count <= 8192, 'FillLand: stack overflow', true); |
247 _y:= _y + _dir; |
247 _y:= _y + _dir; |
248 if (_y < 0) or (_y > 1023) then exit; |
248 if (_y < 0) or (_y > LAND_HEIGHT) then exit; |
249 with Stack.points[Stack.Count] do |
249 with Stack.points[Stack.Count] do |
250 begin |
250 begin |
251 xl:= _xl; |
251 xl:= _xl; |
252 xr:= _xr; |
252 xr:= _xr; |
253 y:= _y; |
253 y:= _y; |
277 Push(xl, xr, y, 1); |
277 Push(xl, xr, y, 1); |
278 while Stack.Count > 0 do |
278 while Stack.Count > 0 do |
279 begin |
279 begin |
280 Pop(xl, xr, y, dir); |
280 Pop(xl, xr, y, dir); |
281 while (xl > 0) and (Land[y, xl] <> 0) do dec(xl); |
281 while (xl > 0) and (Land[y, xl] <> 0) do dec(xl); |
282 while (xr < 2047) and (Land[y, xr] <> 0) do inc(xr); |
282 while (xr < LAND_WIDTH) and (Land[y, xr] <> 0) do inc(xr); |
283 while (xl < xr) do |
283 while (xl < xr) do |
284 begin |
284 begin |
285 while (xl <= xr) and (Land[y, xl] = 0) do inc(xl); |
285 while (xl <= xr) and (Land[y, xl] = 0) do inc(xl); |
286 x:= xl; |
286 x:= xl; |
287 while (xl <= xr) and (Land[y, xl] <> 0) do |
287 while (xl <= xr) and (Land[y, xl] <> 0) do |
303 r, rr: TSDL_Rect; |
303 r, rr: TSDL_Rect; |
304 x, yd, yu: LongInt; |
304 x, yd, yu: LongInt; |
305 begin |
305 begin |
306 tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', false, true, false); |
306 tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', false, true, false); |
307 r.y:= 0; |
307 r.y:= 0; |
308 while r.y < 1024 do |
308 while r.y < 2048 do |
309 begin |
309 begin |
310 r.x:= 0; |
310 r.x:= 0; |
311 while r.x < 2048 do |
311 while r.x <= LAND_WIDTH do |
312 begin |
312 begin |
313 SDL_UpperBlit(tmpsurf, nil, Surface, @r); |
313 SDL_UpperBlit(tmpsurf, nil, Surface, @r); |
314 inc(r.x, tmpsurf^.w) |
314 inc(r.x, tmpsurf^.w) |
315 end; |
315 end; |
316 inc(r.y, tmpsurf^.h) |
316 inc(r.y, tmpsurf^.h) |
317 end; |
317 end; |
318 SDL_FreeSurface(tmpsurf); |
318 SDL_FreeSurface(tmpsurf); |
319 |
319 |
320 tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', false, true, true); |
320 tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', false, true, true); |
321 for x:= 0 to 2047 do |
321 for x:= 0 to 4095 do |
322 begin |
322 begin |
323 yd:= 1023; |
323 yd:= LAND_HEIGHT; |
324 repeat |
324 repeat |
325 while (yd > 0 ) and (Land[yd, x] = 0) do dec(yd); |
325 while (yd > 0 ) and (Land[yd, x] = 0) do dec(yd); |
326 |
326 |
327 if (yd < 0) then yd:= 0; |
327 if (yd < 0) then yd:= 0; |
328 |
328 |
329 while (yd < 1024) and (Land[yd, x] <> 0) do inc(yd); |
329 while (yd <= LAND_HEIGHT) and (Land[yd, x] <> 0) do inc(yd); |
330 dec(yd); |
330 dec(yd); |
331 yu:= yd; |
331 yu:= yd; |
332 |
332 |
333 while (yu > 0 ) and (Land[yu, x] <> 0) do dec(yu); |
333 while (yu > 0 ) and (Land[yu, x] <> 0) do dec(yu); |
334 while (yu < yd ) and (Land[yu, x] = 0) do inc(yu); |
334 while (yu < yd ) and (Land[yu, x] = 0) do inc(yu); |
335 |
335 |
336 if (yd < 1023) and ((yd - yu) >= 16) then |
336 if (yd < LAND_HEIGHT) and ((yd - yu) >= 16) then |
337 begin |
337 begin |
338 rr.x:= x; |
338 rr.x:= x; |
339 rr.y:= yd - 15; |
339 rr.y:= yd - 15; |
340 r.x:= x mod tmpsurf^.w; |
340 r.x:= x mod tmpsurf^.w; |
341 r.y:= 16; |
341 r.y:= 16; |
373 if canMirror then |
373 if canMirror then |
374 if getrandom(2) = 0 then |
374 if getrandom(2) = 0 then |
375 begin |
375 begin |
376 for i:= 0 to pred(BasePointsCount) do |
376 for i:= 0 to pred(BasePointsCount) do |
377 if pa.ar[i].x <> NTPX then |
377 if pa.ar[i].x <> NTPX then |
378 pa.ar[i].x:= 2047 - pa.ar[i].x; |
378 pa.ar[i].x:= LAND_WIDTH - pa.ar[i].x; |
379 for i:= 0 to pred(FillPointsCount) do |
379 for i:= 0 to pred(FillPointsCount) do |
380 FillPoints^[i].x:= 2047 - FillPoints^[i].x; |
380 FillPoints^[i].x:= LAND_WIDTH - FillPoints^[i].x; |
381 end; |
381 end; |
382 |
382 |
383 if canFlip then |
383 if canFlip then |
384 if getrandom(2) = 0 then |
384 if getrandom(2) = 0 then |
385 begin |
385 begin |
386 for i:= 0 to pred(BasePointsCount) do |
386 for i:= 0 to pred(BasePointsCount) do |
387 pa.ar[i].y:= 1023 - pa.ar[i].y; |
387 pa.ar[i].y:= LAND_HEIGHT - pa.ar[i].y; |
388 for i:= 0 to pred(FillPointsCount) do |
388 for i:= 0 to pred(FillPointsCount) do |
389 FillPoints^[i].y:= 1023 - FillPoints^[i].y; |
389 FillPoints^[i].y:= LAND_HEIGHT - FillPoints^[i].y; |
390 end; |
390 end; |
391 end |
391 end |
392 end; |
392 end; |
393 |
393 |
394 function CheckIntersect(V1, V2, V3, V4: TPoint): boolean; |
394 function CheckIntersect(V1, V2, V3, V4: TPoint): boolean; |
438 radz[0]:= 0; |
438 radz[0]:= 0; |
439 for i:= 0 to Pred(pa.Count) do |
439 for i:= 0 to Pred(pa.Count) do |
440 with pa.ar[i] do |
440 with pa.ar[i] do |
441 if x <> NTPX then |
441 if x <> NTPX then |
442 begin |
442 begin |
443 radz[i]:= Min(Max(x - cEdge, 0), Max(2048 - cEdge - x, 0)); |
443 radz[i]:= Min(Max(x - cEdge, 0), Max(LAND_WIDTH + 1 - cEdge - x, 0)); |
444 radz[i]:= Min(radz[i], Min(Max(y - cEdge, 0), Max(1024 - cEdge - y, 0))); |
444 radz[i]:= Min(radz[i], Min(Max(y - cEdge, 0), Max(LAND_HEIGHT + 1 - cEdge - y, 0))); |
445 if radz[i] > 0 then |
445 if radz[i] > 0 then |
446 for k:= 0 to Pred(i) do |
446 for k:= 0 to Pred(i) do |
447 begin |
447 begin |
448 dist:= Max(abs(x - pa.ar[k].x), abs(y - pa.ar[k].y)); |
448 dist:= Max(abs(x - pa.ar[k].x), abs(y - pa.ar[k].y)); |
449 radz[k]:= Max(0, Min((dist - cMinDist) div 2, radz[k])); |
449 radz[k]:= Max(0, Min((dist - cMinDist) div 2, radz[k])); |
502 SelectTemplate:= getrandom(Succ(High(EdgeTemplates))) |
502 SelectTemplate:= getrandom(Succ(High(EdgeTemplates))) |
503 end; |
503 end; |
504 |
504 |
505 procedure LandSurface2LandPixels(Surface: PSDL_Surface); |
505 procedure LandSurface2LandPixels(Surface: PSDL_Surface); |
506 var x, y: LongInt; |
506 var x, y: LongInt; |
|
507 c: LongWord; |
507 p: PLongwordArray; |
508 p: PLongwordArray; |
508 begin |
509 begin |
509 TryDo(Surface <> nil, 'Assert (LandSurface <> nil) failed', true); |
510 TryDo(Surface <> nil, 'Assert (LandSurface <> nil) failed', true); |
510 |
511 |
511 if SDL_MustLock(Surface) then |
512 if SDL_MustLock(Surface) then |
512 SDLTry(SDL_LockSurface(Surface) >= 0, true); |
513 SDLTry(SDL_LockSurface(Surface) >= 0, true); |
513 |
514 |
514 p:= Surface^.pixels; |
515 p:= Surface^.pixels; |
515 for y:= 0 to 1023 do |
516 for y:= 0 to LAND_HEIGHT do |
516 begin |
517 begin |
517 for x:= 0 to 2047 do |
518 for x:= 0 to LAND_WIDTH do |
518 if Land[y, x] <> 0 then LandPixels[y, x]:= p^[x] or $FF000000; |
519 if Land[y, x] <> 0 then LandPixels[y, x]:= p^[x] or $FF000000; |
519 p:= @(p^[Surface^.pitch div 4]); |
520 p:= @(p^[Surface^.pitch div 4]); |
520 end; |
521 end; |
521 |
522 |
522 if SDL_MustLock(Surface) then |
523 if SDL_MustLock(Surface) then |
523 SDL_UnlockSurface(Surface) |
524 SDL_UnlockSurface(Surface); |
|
525 |
|
526 for y:= 0 to 63 do |
|
527 for x:= 0 to 127 do |
|
528 LandDirty[y, x]:= 0; // TODO - ask unC0Rr why he took this out of merge - doesn't it need initialising? seems random values could result in some unintended smoothing of initial map edges. also be slower. |
|
529 |
|
530 // experiment hardcoding cave |
|
531 for y:= 0 to LAND_HEIGHT do |
|
532 begin |
|
533 Land[y, 0]:= COLOR_INDESTRUCTIBLE; |
|
534 Land[y, 1]:= COLOR_INDESTRUCTIBLE; |
|
535 Land[y, 2]:= COLOR_INDESTRUCTIBLE; |
|
536 Land[y, LAND_WIDTH-2]:= COLOR_INDESTRUCTIBLE; |
|
537 Land[y, LAND_WIDTH-1]:= COLOR_INDESTRUCTIBLE; |
|
538 Land[y, LAND_WIDTH]:= COLOR_INDESTRUCTIBLE; |
|
539 if y mod 32 < 16 then c:= $FF000000 |
|
540 else c:= $FF00FFFF; |
|
541 LandPixels[y, 0]:= c; |
|
542 LandPixels[y, 1]:= c; |
|
543 LandPixels[y, 2]:= c; |
|
544 LandPixels[y, LAND_WIDTH-2]:= c; |
|
545 LandPixels[y, LAND_WIDTH-1]:= c; |
|
546 LandPixels[y, LAND_WIDTH]:= c; |
|
547 end; |
|
548 |
|
549 for x:= 0 to LAND_WIDTH do |
|
550 begin |
|
551 Land[0, x]:= COLOR_INDESTRUCTIBLE; |
|
552 Land[1, x]:= COLOR_INDESTRUCTIBLE; |
|
553 Land[2, x]:= COLOR_INDESTRUCTIBLE; |
|
554 if x mod 32 < 16 then c:= $FF000000 |
|
555 else c:= $FF00FFFF; |
|
556 LandPixels[0, x]:= c; |
|
557 LandPixels[1, x]:= c; |
|
558 LandPixels[2, x]:= c; |
|
559 end; |
524 end; |
560 end; |
525 |
561 |
526 procedure GenLandSurface; |
562 procedure GenLandSurface; |
527 var tmpsurf: PSDL_Surface; |
563 var tmpsurf: PSDL_Surface; |
528 begin |
564 begin |
530 |
566 |
531 GenBlank(EdgeTemplates[SelectTemplate]); |
567 GenBlank(EdgeTemplates[SelectTemplate]); |
532 |
568 |
533 AddProgress; |
569 AddProgress; |
534 |
570 |
535 tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, 2048, 1024, 32, RMask, GMask, BMask, 0); |
571 tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH+1, LAND_HEIGHT+1, 32, RMask, GMask, BMask, 0); |
536 |
572 |
537 TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true); |
573 TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true); |
538 ColorizeLand(tmpsurf); |
574 ColorizeLand(tmpsurf); |
539 AddOnLandObjects(tmpsurf); |
575 AddOnLandObjects(tmpsurf); |
540 |
576 |
543 |
579 |
544 AddProgress; |
580 AddProgress; |
545 |
581 |
546 AddObjects; |
582 AddObjects; |
547 |
583 |
548 UpdateLandTexture(0, 1023); |
584 UpdateLandTexture(0, LAND_WIDTH); |
549 AddProgress |
585 AddProgress |
550 end; |
586 end; |
551 |
587 |
552 procedure MakeFortsMap; |
588 procedure MakeFortsMap; |
553 var tmpsurf: PSDL_Surface; |
589 var tmpsurf: PSDL_Surface; |
554 begin |
590 begin |
555 WriteLnToConsole('Generating forts land...'); |
591 WriteLnToConsole('Generating forts land...'); |
556 |
592 |
557 tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[0]^.Teams[0]^.FortName + 'L', true, true, true); |
593 tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[0]^.Teams[0]^.FortName + 'L', true, true, true); |
558 BlitImageAndGenerateCollisionInfo(0, 0, 1024, tmpsurf); |
594 BlitImageAndGenerateCollisionInfo(0, 0, LAND_WIDTH+1, tmpsurf); |
559 SDL_FreeSurface(tmpsurf); |
595 SDL_FreeSurface(tmpsurf); |
560 |
596 |
561 tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[1]^.Teams[0]^.FortName + 'R', true, true, true); |
597 tmpsurf:= LoadImage(Pathz[ptForts] + '/' + ClansArray[1]^.Teams[0]^.FortName + 'R', true, true, true); |
562 BlitImageAndGenerateCollisionInfo(1024, 0, 1024, tmpsurf); |
598 BlitImageAndGenerateCollisionInfo(2048, 0, LAND_WIDTH+1, tmpsurf); |
563 SDL_FreeSurface(tmpsurf); |
599 SDL_FreeSurface(tmpsurf); |
564 |
600 |
565 UpdateLandTexture(0, 1023) |
601 UpdateLandTexture(0, LAND_HEIGHT) |
566 end; |
602 end; |
567 |
603 |
568 procedure LoadMap; |
604 procedure LoadMap; |
569 var tmpsurf: PSDL_Surface; |
605 var tmpsurf: PSDL_Surface; |
570 begin |
606 begin |
571 WriteLnToConsole('Loading land from file...'); |
607 WriteLnToConsole('Loading land from file...'); |
572 AddProgress; |
608 AddProgress; |
573 tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', true, true, true); |
609 tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', true, true, true); |
574 TryDo((tmpsurf^.w = 2048) and (tmpsurf^.h = 1024), 'Map dimensions should be 2048x1024!', true); |
610 TryDo((tmpsurf^.w = LAND_WIDTH+1) and (tmpsurf^.h = LAND_HEIGHT+1), 'Map dimensions should be 4096x2048!', true); |
575 |
611 |
576 TryDo(tmpsurf^.format^.BytesPerPixel = 4, 'Map should be 32bit', true); |
612 TryDo(tmpsurf^.format^.BytesPerPixel = 4, 'Map should be 32bit', true); |
577 |
613 |
578 BlitImageAndGenerateCollisionInfo(0, 0, 2048, tmpsurf); |
614 BlitImageAndGenerateCollisionInfo(0, 0, LAND_WIDTH+1, tmpsurf); |
579 SDL_FreeSurface(tmpsurf); |
615 SDL_FreeSurface(tmpsurf); |
580 |
616 |
581 UpdateLandTexture(0, 1023) |
617 UpdateLandTexture(0, LAND_HEIGHT) |
582 end; |
618 end; |
583 |
619 |
584 procedure GenMap; |
620 procedure GenMap; |
585 begin |
621 begin |
586 LoadThemeConfig; |
622 LoadThemeConfig; |
605 begin |
641 begin |
606 Preview[y, x]:= 0; |
642 Preview[y, x]:= 0; |
607 for bit:= 0 to 7 do |
643 for bit:= 0 to 7 do |
608 begin |
644 begin |
609 t:= 0; |
645 t:= 0; |
610 for yy:= y * 8 to y * 8 + 7 do |
646 for yy:= y * 16 to y * 16 + 7 do |
611 for xx:= x * 64 + bit * 8 to x * 64 + bit * 8 + 7 do |
647 for xx:= x * 128 + bit * 8 to x * 128 + bit * 8 + 7 do |
612 if Land[yy, xx] <> 0 then inc(t); |
648 if Land[yy, xx] <> 0 then inc(t); |
613 if t > 8 then Preview[y, x]:= Preview[y, x] or ($80 shr bit) |
649 if t > 8 then Preview[y, x]:= Preview[y, x] or ($80 shr bit) |
614 end |
650 end |
615 end; |
651 end; |
616 GenPreview:= Preview |
652 GenPreview:= Preview |
617 end; |
653 end; |
618 |
654 |
619 procedure UpdateLandTexture(Y, Height: LongInt); |
655 procedure UpdateLandTexture(Y, Height: LongInt); |
620 begin |
656 begin |
621 if (Height <= 0) then exit; |
657 if (Height <= 0) then exit; |
622 TryDo((Y >= 0) and (Y < 1024), 'UpdateLandTexture: wrong Y parameter', true); |
658 TryDo((Y >= 0) and (Y <= LAND_HEIGHT), 'UpdateLandTexture: wrong Y parameter', true); |
623 TryDo(Y + Height < 1024, 'UpdateLandTexture: wrong Height parameter', true); |
659 TryDo(Y + Height <= LAND_WIDTH, 'UpdateLandTexture: wrong Height parameter', true); |
624 |
660 |
625 if LandTexture = nil then |
661 if LandTexture = nil then |
626 LandTexture:= NewTexture(2048, 1024, @LandPixels) |
662 LandTexture:= NewTexture(LAND_WIDTH+1, LAND_HEIGHT+1, @LandPixels) |
627 else |
663 else |
628 begin |
664 begin |
629 glBindTexture(GL_TEXTURE_2D, LandTexture^.id); |
665 glBindTexture(GL_TEXTURE_2D, LandTexture^.id); |
630 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, Y, 2048, Height, GL_RGBA, GL_UNSIGNED_BYTE, @LandPixels[Y, 0]); |
666 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, Y, LAND_WIDTH+1, Height, GL_RGBA, GL_UNSIGNED_BYTE, @LandPixels[Y, 0]); |
631 end |
667 end |
632 end; |
668 end; |
633 |
669 |
634 initialization |
670 initialization |
635 |
671 |