hedgewars/uLand.pas
changeset 1753 2ccba26f1aa4
parent 1738 00e8dadce69a
child 1754 a37392548124
equal deleted inserted replaced
1752:769986d39202 1753:2ccba26f1aa4
    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;
   116        begin
   116        begin
   117        dec(eY, d);
   117        dec(eY, d);
   118        inc(y, sY);
   118        inc(y, sY);
   119        end;
   119        end;
   120 
   120 
   121     if ((x and $FFFFF800) = 0) and ((y and $FFFFFC00) = 0) then
   121     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   122        Land[y, x]:= Color;
   122        Land[y, x]:= Color;
   123     end
   123     end
   124 end;
   124 end;
   125 
   125 
   126 procedure DrawEdge(var pa: TPixAr; Color: Longword);
   126 procedure DrawEdge(var pa: TPixAr; Color: Longword);
   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]));
   451         end
   451         end
   452       end;
   452       end;
   453 
   453 
   454 for i:= 0 to Pred(pa.Count) do
   454 for i:= 0 to Pred(pa.Count) do
   455   with pa.ar[i] do
   455   with pa.ar[i] do
   456     if ((x and $FFFFF800) = 0) and ((y and $FFFFFC00) = 0) then
   456     if ((x and LAND_WIDTH_MASK) = 0) and ((y and LAND_HEIGHT_MASK) = 0) then
   457       begin
   457       begin
   458       px:= x;
   458       px:= x;
   459       py:= y;
   459       py:= y;
   460       x:= x + LongInt(GetRandom(7) - 3) * (radz[i] * 5 div 7) div 3;
   460       x:= x + LongInt(GetRandom(7) - 3) * (radz[i] * 5 div 7) div 3;
   461       y:= y + LongInt(GetRandom(7) - 3) * (radz[i] * 5 div 7) div 3;
   461       y:= y + LongInt(GetRandom(7) - 3) * (radz[i] * 5 div 7) div 3;
   471 procedure GenBlank(var Template: TEdgeTemplate);
   471 procedure GenBlank(var Template: TEdgeTemplate);
   472 var pa: TPixAr;
   472 var pa: TPixAr;
   473     i: Longword;
   473     i: Longword;
   474     y, x: Longword;
   474     y, x: Longword;
   475 begin
   475 begin
   476 for y:= 0 to 1023 do
   476 for y:= 0 to LAND_HEIGHT do
   477     for x:= 0 to 2047 do
   477     for x:= 0 to LAND_WIDTH do
   478         Land[y, x]:= COLOR_LAND;
   478         Land[y, x]:= COLOR_LAND;
   479 
   479 
   480 SetPoints(Template, pa);
   480 SetPoints(Template, pa);
   481 for i:= 1 to Template.BezierizeCount do
   481 for i:= 1 to Template.BezierizeCount do
   482     begin
   482     begin
   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