hedgewars/uLand.pas
changeset 2948 3f21a9dc93d0
parent 2905 f3c79f7193a9
child 2981 d0471586a616
equal deleted inserted replaced
2947:803b277e4894 2948:3f21a9dc93d0
    20 
    20 
    21 unit uLand;
    21 unit uLand;
    22 interface
    22 interface
    23 uses SDLh, uLandTemplates, uFloat, uConsts,
    23 uses SDLh, uLandTemplates, uFloat, uConsts,
    24 {$IFDEF GLES11}
    24 {$IFDEF GLES11}
    25 	gles11;
    25     gles11;
    26 {$ELSE}
    26 {$ELSE}
    27 	GL;
    27     GL;
    28 {$ENDIF}
    28 {$ENDIF}
    29 
    29 
    30 type TLandArray = packed array[0 .. LAND_HEIGHT - 1, 0 .. LAND_WIDTH - 1] of LongWord;
    30 type TLandArray = packed array[0 .. LAND_HEIGHT - 1, 0 .. LAND_WIDTH - 1] of LongWord;
    31 	TCollisionArray = packed array[0 .. LAND_HEIGHT - 1, 0 .. LAND_WIDTH - 1] of Word;
    31     TCollisionArray = packed array[0 .. LAND_HEIGHT - 1, 0 .. LAND_WIDTH - 1] of Word;
    32 	TPreview  = packed array[0..127, 0..31] of byte;
    32     TPreview  = packed array[0..127, 0..31] of byte;
    33 	TDirtyTag = packed array[0 .. LAND_HEIGHT div 32 - 1, 0 .. LAND_WIDTH div 32 - 1] of byte;
    33     TDirtyTag = packed array[0 .. LAND_HEIGHT div 32 - 1, 0 .. LAND_WIDTH div 32 - 1] of byte;
    34 
    34 
    35 var Land: TCollisionArray;
    35 var Land: TCollisionArray;
    36     LandPixels: TLandArray;
    36     LandPixels: TLandArray;
    37     LandDirty: TDirtyTag;
    37     LandDirty: TDirtyTag;
    38     hasBorder: boolean; 
    38     hasBorder: boolean; 
   312 end;
   312 end;
   313 
   313 
   314 function LandBackPixel(x, y: LongInt): LongWord;
   314 function LandBackPixel(x, y: LongInt): LongWord;
   315 var p: PLongWordArray;
   315 var p: PLongWordArray;
   316 begin
   316 begin
   317 	if LandBackSurface = nil then LandBackPixel:= 0
   317     if LandBackSurface = nil then LandBackPixel:= 0
   318 	else
   318     else
   319 	begin
   319     begin
   320 		p:= LandBackSurface^.pixels;
   320         p:= LandBackSurface^.pixels;
   321 		LandBackPixel:= p^[LandBackSurface^.w * (y mod LandBackSurface^.h) + (x mod LandBackSurface^.w)];// or $FF000000;
   321         LandBackPixel:= p^[LandBackSurface^.w * (y mod LandBackSurface^.h) + (x mod LandBackSurface^.w)];// or $FF000000;
   322 	end
   322     end
   323 end;
   323 end;
   324 
   324 
   325 procedure ColorizeLand(Surface: PSDL_Surface);
   325 procedure ColorizeLand(Surface: PSDL_Surface);
   326 var tmpsurf: PSDL_Surface;
   326 var tmpsurf: PSDL_Surface;
   327     r, rr: TSDL_Rect;
   327     r, rr: TSDL_Rect;
   328     x, yd, yu: LongInt;
   328     x, yd, yu: LongInt;
   329 begin
   329 begin
   330 	tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', ifCritical or ifIgnoreCaps);
   330     tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/LandTex', ifCritical or ifIgnoreCaps);
   331 	r.y:= 0;
   331     r.y:= 0;
   332 	while r.y < LAND_HEIGHT do
   332     while r.y < LAND_HEIGHT do
   333 	begin
   333     begin
   334 		r.x:= 0;
   334         r.x:= 0;
   335 		while r.x < LAND_WIDTH do
   335         while r.x < LAND_WIDTH do
   336 		begin
   336         begin
   337 			SDL_UpperBlit(tmpsurf, nil, Surface, @r);
   337             SDL_UpperBlit(tmpsurf, nil, Surface, @r);
   338 			inc(r.x, tmpsurf^.w)
   338             inc(r.x, tmpsurf^.w)
   339 		end;
   339         end;
   340 		inc(r.y, tmpsurf^.h)
   340         inc(r.y, tmpsurf^.h)
   341 	end;
   341     end;
   342 	SDL_FreeSurface(tmpsurf);
   342     SDL_FreeSurface(tmpsurf);
   343 
   343 
   344 	// freed in free_uLand() below
   344     // freed in free_uLand() below
   345 	LandBackSurface:= LoadImage(Pathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent);
   345     LandBackSurface:= LoadImage(Pathz[ptCurrTheme] + '/LandBackTex', ifIgnoreCaps or ifTransparent);
   346 
   346 
   347 	tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', ifCritical or ifIgnoreCaps or ifTransparent);
   347     tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Border', ifCritical or ifIgnoreCaps or ifTransparent);
   348 	for x:= 0 to LAND_WIDTH - 1 do
   348     for x:= 0 to LAND_WIDTH - 1 do
   349 	begin
   349     begin
   350 		yd:= LAND_HEIGHT - 1;
   350         yd:= LAND_HEIGHT - 1;
   351 		repeat
   351         repeat
   352 			while (yd > 0) and (Land[yd, x] =  0) do dec(yd);
   352             while (yd > 0) and (Land[yd, x] =  0) do dec(yd);
   353 
   353 
   354 			if (yd < 0) then yd:= 0;
   354             if (yd < 0) then yd:= 0;
   355 
   355 
   356 			while (yd < LAND_HEIGHT) and (Land[yd, x] <> 0) do inc(yd);
   356             while (yd < LAND_HEIGHT) and (Land[yd, x] <> 0) do inc(yd);
   357 			dec(yd);
   357             dec(yd);
   358 			yu:= yd;
   358             yu:= yd;
   359 
   359 
   360 			while (yu > 0  ) and (Land[yu, x] <> 0) do dec(yu);
   360             while (yu > 0  ) and (Land[yu, x] <> 0) do dec(yu);
   361 			while (yu < yd ) and (Land[yu, x] =  0) do inc(yu);
   361             while (yu < yd ) and (Land[yu, x] =  0) do inc(yu);
   362 
   362 
   363 			if (yd < LAND_HEIGHT - 1) and ((yd - yu) >= 16) then
   363             if (yd < LAND_HEIGHT - 1) and ((yd - yu) >= 16) then
   364 			begin
   364             begin
   365 				rr.x:= x;
   365                 rr.x:= x;
   366 				rr.y:= yd - 15;
   366                 rr.y:= yd - 15;
   367 				r.x:= x mod tmpsurf^.w;
   367                 r.x:= x mod tmpsurf^.w;
   368 				r.y:= 16;
   368                 r.y:= 16;
   369 				r.w:= 1;
   369                 r.w:= 1;
   370 				r.h:= 16;
   370                 r.h:= 16;
   371 				SDL_UpperBlit(tmpsurf, @r, Surface, @rr);
   371                 SDL_UpperBlit(tmpsurf, @r, Surface, @rr);
   372 			end;
   372             end;
   373 			if (yu > 0) then
   373             if (yu > 0) then
   374 			begin
   374             begin
   375 				rr.x:= x;
   375                 rr.x:= x;
   376 				rr.y:= yu;
   376                 rr.y:= yu;
   377 				r.x:= x mod tmpsurf^.w;
   377                 r.x:= x mod tmpsurf^.w;
   378 				r.y:= 0;
   378                 r.y:= 0;
   379 				r.w:= 1;
   379                 r.w:= 1;
   380 				r.h:= min(16, yd - yu + 1);
   380                 r.h:= min(16, yd - yu + 1);
   381 				SDL_UpperBlit(tmpsurf, @r, Surface, @rr);
   381                 SDL_UpperBlit(tmpsurf, @r, Surface, @rr);
   382 			end;
   382             end;
   383 			yd:= yu - 1;
   383             yd:= yu - 1;
   384 		until yd < 0;
   384         until yd < 0;
   385 	end;
   385     end;
   386 	SDL_FreeSurface(tmpsurf);
   386     SDL_FreeSurface(tmpsurf);
   387 end;
   387 end;
   388 
   388 
   389 procedure SetPoints(var Template: TEdgeTemplate; var pa: TPixAr);
   389 procedure SetPoints(var Template: TEdgeTemplate; var pa: TPixAr);
   390 var i: LongInt;
   390 var i: LongInt;
   391 begin
   391 begin
   614 WriteLnToConsole('Selected template #'+inttostr(SelectTemplate)+' using filter #'+inttostr(cTemplateFilter));
   614 WriteLnToConsole('Selected template #'+inttostr(SelectTemplate)+' using filter #'+inttostr(cTemplateFilter));
   615 end;
   615 end;
   616 
   616 
   617 procedure LandSurface2LandPixels(Surface: PSDL_Surface);
   617 procedure LandSurface2LandPixels(Surface: PSDL_Surface);
   618 var x, y: LongInt;
   618 var x, y: LongInt;
   619 	p: PLongwordArray;
   619     p: PLongwordArray;
   620 begin
   620 begin
   621 TryDo(Surface <> nil, 'Assert (LandSurface <> nil) failed', true);
   621 TryDo(Surface <> nil, 'Assert (LandSurface <> nil) failed', true);
   622 
   622 
   623 if SDL_MustLock(Surface) then
   623 if SDL_MustLock(Surface) then
   624 	SDLTry(SDL_LockSurface(Surface) >= 0, true);
   624     SDLTry(SDL_LockSurface(Surface) >= 0, true);
   625 
   625 
   626 p:= Surface^.pixels;
   626 p:= Surface^.pixels;
   627 for y:= 0 to LAND_HEIGHT - 1 do
   627 for y:= 0 to LAND_HEIGHT - 1 do
   628 	begin
   628     begin
   629 	for x:= 0 to LAND_WIDTH - 1 do
   629     for x:= 0 to LAND_WIDTH - 1 do
   630 		if Land[y, x] <> 0 then LandPixels[y, x]:= p^[x] or AMask;
   630         if Land[y, x] <> 0 then LandPixels[y, x]:= p^[x] or AMask;
   631 
   631 
   632 	p:= @(p^[Surface^.pitch div 4]);
   632     p:= @(p^[Surface^.pitch div 4]);
   633 	end;
   633     end;
   634 
   634 
   635 if SDL_MustLock(Surface) then
   635 if SDL_MustLock(Surface) then
   636 	SDL_UnlockSurface(Surface);
   636     SDL_UnlockSurface(Surface);
   637 end;
   637 end;
   638 
   638 
   639 procedure GenLandSurface;
   639 procedure GenLandSurface;
   640 var tmpsurf: PSDL_Surface;
   640 var tmpsurf: PSDL_Surface;
   641 begin
   641 begin
   642 	WriteLnToConsole('Generating land...');
   642     WriteLnToConsole('Generating land...');
   643 	GenBlank(EdgeTemplates[SelectTemplate]);
   643     GenBlank(EdgeTemplates[SelectTemplate]);
   644 	AddProgress();
   644     AddProgress();
   645 
   645 
   646 	tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, 0);
   646     tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, 0);
   647 
   647 
   648 	TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true);
   648     TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true);
   649 	ColorizeLand(tmpsurf);
   649     ColorizeLand(tmpsurf);
   650 	AddOnLandObjects(tmpsurf);
   650     AddOnLandObjects(tmpsurf);
   651 
   651 
   652 	LandSurface2LandPixels(tmpsurf);
   652     LandSurface2LandPixels(tmpsurf);
   653 	SDL_FreeSurface(tmpsurf);
   653     SDL_FreeSurface(tmpsurf);
   654 	AddProgress();
   654     AddProgress();
   655 end;
   655 end;
   656 
   656 
   657 procedure MakeFortsMap;
   657 procedure MakeFortsMap;
   658 var tmpsurf: PSDL_Surface;
   658 var tmpsurf: PSDL_Surface;
   659 begin
   659 begin
   685 procedure LoadMask;
   685 procedure LoadMask;
   686 var tmpsurf: PSDL_Surface;
   686 var tmpsurf: PSDL_Surface;
   687     p: PLongwordArray;
   687     p: PLongwordArray;
   688     x, y, cpX, cpY: Longword;
   688     x, y, cpX, cpY: Longword;
   689 begin
   689 begin
   690 	tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/mask', ifAlpha or ifTransparent or ifIgnoreCaps);
   690     tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/mask', ifAlpha or ifTransparent or ifIgnoreCaps);
   691 	if (tmpsurf <> nil) and (tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT) and (tmpsurf^.format^.BytesPerPixel = 4) then
   691     if (tmpsurf <> nil) and (tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT) and (tmpsurf^.format^.BytesPerPixel = 4) then
   692 	begin
   692     begin
   693 		cpX:= (LAND_WIDTH - tmpsurf^.w) div 2;
   693         cpX:= (LAND_WIDTH - tmpsurf^.w) div 2;
   694 		cpY:= LAND_HEIGHT - tmpsurf^.h;
   694         cpY:= LAND_HEIGHT - tmpsurf^.h;
   695 		if SDL_MustLock(tmpsurf) then
   695         if SDL_MustLock(tmpsurf) then
   696 			SDLTry(SDL_LockSurface(tmpsurf) >= 0, true);
   696             SDLTry(SDL_LockSurface(tmpsurf) >= 0, true);
   697 
   697 
   698 			p:= tmpsurf^.pixels;
   698             p:= tmpsurf^.pixels;
   699 			for y:= 0 to Pred(tmpsurf^.h) do
   699             for y:= 0 to Pred(tmpsurf^.h) do
   700 			begin
   700             begin
   701 				for x:= 0 to Pred(tmpsurf^.w) do
   701                 for x:= 0 to Pred(tmpsurf^.w) do
   702 				begin
   702                 begin
   703 					if ((AMask and p^[x]) = 0) then  // Tiy was having trouble generating transparent black
   703                     if ((AMask and p^[x]) = 0) then  // Tiy was having trouble generating transparent black
   704 						Land[cpY + y, cpX + x]:= 0
   704                         Land[cpY + y, cpX + x]:= 0
   705 					else if p^[x] = (AMask or RMask) then
   705                     else if p^[x] = (AMask or RMask) then
   706 						Land[cpY + y, cpX + x]:= COLOR_INDESTRUCTIBLE
   706                         Land[cpY + y, cpX + x]:= COLOR_INDESTRUCTIBLE
   707 					else if p^[x] = $FFFFFFFF then
   707                     else if p^[x] = $FFFFFFFF then
   708 						Land[cpY + y, cpX + x]:= COLOR_LAND;
   708                         Land[cpY + y, cpX + x]:= COLOR_LAND;
   709 				end;
   709                 end;
   710 				p:= @(p^[tmpsurf^.pitch div 4]);
   710                 p:= @(p^[tmpsurf^.pitch div 4]);
   711 			end;
   711             end;
   712 
   712 
   713 		if SDL_MustLock(tmpsurf) then
   713         if SDL_MustLock(tmpsurf) then
   714 			SDL_UnlockSurface(tmpsurf);
   714             SDL_UnlockSurface(tmpsurf);
   715 	end;
   715     end;
   716 	if (tmpsurf <> nil) then 
   716     if (tmpsurf <> nil) then 
   717 		SDL_FreeSurface(tmpsurf);
   717         SDL_FreeSurface(tmpsurf);
   718 end;
   718 end;
   719 
   719 
   720 procedure LoadMap;
   720 procedure LoadMap;
   721 var tmpsurf: PSDL_Surface;
   721 var tmpsurf: PSDL_Surface;
   722 	s: shortstring;
   722     s: shortstring;
   723 	f: textfile;
   723     f: textfile;
   724 begin
   724 begin
   725 WriteLnToConsole('Loading land from file...');
   725 WriteLnToConsole('Loading land from file...');
   726 AddProgress;
   726 AddProgress;
   727 tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
   727 tmpsurf:= LoadImage(Pathz[ptMapCurrent] + '/map', ifAlpha or ifCritical or ifTransparent or ifIgnoreCaps);
   728 TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true);
   728 TryDo((tmpsurf^.w <= LAND_WIDTH) and (tmpsurf^.h <= LAND_HEIGHT), 'Map dimensions too big!', true);
   745 topY:= LAND_HEIGHT - playHeight;
   745 topY:= LAND_HEIGHT - playHeight;
   746 
   746 
   747 TryDo(tmpsurf^.format^.BytesPerPixel = 4, 'Map should be 32bit', true);
   747 TryDo(tmpsurf^.format^.BytesPerPixel = 4, 'Map should be 32bit', true);
   748 
   748 
   749 BlitImageAndGenerateCollisionInfo(
   749 BlitImageAndGenerateCollisionInfo(
   750 	(LAND_WIDTH - tmpsurf^.w) div 2,
   750     (LAND_WIDTH - tmpsurf^.w) div 2,
   751 	LAND_HEIGHT - tmpsurf^.h,
   751     LAND_HEIGHT - tmpsurf^.h,
   752 	tmpsurf^.w,
   752     tmpsurf^.w,
   753 	tmpsurf);
   753     tmpsurf);
   754 SDL_FreeSurface(tmpsurf);
   754 SDL_FreeSurface(tmpsurf);
   755 
   755 
   756 LoadMask;
   756 LoadMask;
   757 end;
   757 end;
   758 
   758 
   787                     break;
   787                     break;
   788                     end;
   788                     end;
   789                 end;
   789                 end;
   790 
   790 
   791 if hasBorder then
   791 if hasBorder then
   792 	begin
   792     begin
   793 	for y:= 0 to LAND_HEIGHT - 1 do
   793     for y:= 0 to LAND_HEIGHT - 1 do
   794 		for x:= 0 to LAND_WIDTH - 1 do
   794         for x:= 0 to LAND_WIDTH - 1 do
   795 			if (y < topY) or (x < leftX) or (x > rightX) then
   795             if (y < topY) or (x < leftX) or (x > rightX) then
   796 				Land[y, x]:= COLOR_INDESTRUCTIBLE;
   796                 Land[y, x]:= COLOR_INDESTRUCTIBLE;
   797 	// experiment hardcoding cave
   797     // experiment hardcoding cave
   798 	// also try basing cave dimensions on map/template dimensions, if they exist
   798     // also try basing cave dimensions on map/template dimensions, if they exist
   799 	for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade
   799     for w:= 0 to 5 do // width of 3 allowed hogs to be knocked through with grenade
   800 		begin
   800         begin
   801 		for y:= topY to LAND_HEIGHT - 1 do
   801         for y:= topY to LAND_HEIGHT - 1 do
   802 			begin
   802             begin
   803 			Land[y, leftX + w]:= COLOR_INDESTRUCTIBLE;
   803             Land[y, leftX + w]:= COLOR_INDESTRUCTIBLE;
   804 			Land[y, rightX - w]:= COLOR_INDESTRUCTIBLE;
   804             Land[y, rightX - w]:= COLOR_INDESTRUCTIBLE;
   805 			if (y + w) mod 32 < 16 then
   805             if (y + w) mod 32 < 16 then
   806 				c:= AMask
   806                 c:= AMask
   807 			else
   807             else
   808 				c:= AMask or RMask or GMask; // FF00FFFF
   808                 c:= AMask or RMask or GMask; // FF00FFFF
   809 			LandPixels[y, leftX + w]:= c;
   809             LandPixels[y, leftX + w]:= c;
   810 			LandPixels[y, rightX - w]:= c;
   810             LandPixels[y, rightX - w]:= c;
   811 			end;
   811             end;
   812 
   812 
   813 		for x:= leftX to rightX do
   813         for x:= leftX to rightX do
   814 			begin
   814             begin
   815 			Land[topY + w, x]:= COLOR_INDESTRUCTIBLE;
   815             Land[topY + w, x]:= COLOR_INDESTRUCTIBLE;
   816 			if (x + w) mod 32 < 16 then
   816             if (x + w) mod 32 < 16 then
   817 				c:= AMask
   817                 c:= AMask
   818 			else
   818             else
   819 				c:= AMask or RMask or GMask; // FF00FFFF
   819                 c:= AMask or RMask or GMask; // FF00FFFF
   820 			LandPixels[topY + w, x]:= c;
   820             LandPixels[topY + w, x]:= c;
   821 			end;
   821             end;
   822 		end;
   822         end;
   823 	end;
   823     end;
   824 
   824 
   825 if (GameFlags and gfDisableGirders) <> 0 then hasGirders:= false;
   825 if (GameFlags and gfDisableGirders) <> 0 then hasGirders:= false;
   826 
   826 
   827 if ((GameFlags and gfForts) = 0) and (Pathz[ptMapCurrent] = '') then AddObjects;
   827 if ((GameFlags and gfForts) = 0) and (Pathz[ptMapCurrent] = '') then AddObjects;
   828 
   828 
   852 GenPreview:= Preview
   852 GenPreview:= Preview
   853 end;
   853 end;
   854 
   854 
   855 procedure init_uLand;
   855 procedure init_uLand;
   856 begin
   856 begin
   857 	LandBackSurface:= nil;
   857     LandBackSurface:= nil;
   858 end;
   858 end;
   859 
   859 
   860 procedure free_uLand;
   860 procedure free_uLand;
   861 begin
   861 begin
   862 	if LandBackSurface <> nil then
   862     if LandBackSurface <> nil then
   863 		SDL_FreeSurface(LandBackSurface);
   863         SDL_FreeSurface(LandBackSurface);
   864 end;
   864 end;
   865 
   865 
   866 end.
   866 end.