hedgewars/uLandObjects.pas
changeset 2948 3f21a9dc93d0
parent 2905 f3c79f7193a9
child 3053 55a7e3a896ef
equal deleted inserted replaced
2947:803b277e4894 2948:3f21a9dc93d0
    28 procedure AddOnLandObjects(Surface: PSDL_Surface);
    28 procedure AddOnLandObjects(Surface: PSDL_Surface);
    29 
    29 
    30 implementation
    30 implementation
    31 uses uLand, uStore, uConsts, uMisc, uConsole, uRandom, uVisualGears, uFloat, uSound, uWorld,
    31 uses uLand, uStore, uConsts, uMisc, uConsole, uRandom, uVisualGears, uFloat, uSound, uWorld,
    32 {$IFDEF GLES11}
    32 {$IFDEF GLES11}
    33 	gles11;
    33     gles11;
    34 {$ELSE}
    34 {$ELSE}
    35 	GL;
    35     GL;
    36 {$ENDIF}
    36 {$ENDIF}
    37 
    37 
    38 const MaxRects = 512;
    38 const MaxRects = 512;
    39       MAXOBJECTRECTS = 16;
    39       MAXOBJECTRECTS = 16;
    40       MAXTHEMEOBJECTS = 32;
    40       MAXTHEMEOBJECTS = 32;
    84 
    84 
    85 if Width = 0 then Width:= Image^.w;
    85 if Width = 0 then Width:= Image^.w;
    86 
    86 
    87 p:= Image^.pixels;
    87 p:= Image^.pixels;
    88 for y:= 0 to Pred(Image^.h) do
    88 for y:= 0 to Pred(Image^.h) do
    89 	begin
    89     begin
    90 	for x:= 0 to Pred(Width) do
    90     for x:= 0 to Pred(Width) do
    91 		if LandPixels[cpY + y, cpX + x] = 0 then
    91         if LandPixels[cpY + y, cpX + x] = 0 then
    92 			begin
    92             begin
    93 			LandPixels[cpY + y, cpX + x]:= p^[x];
    93             LandPixels[cpY + y, cpX + x]:= p^[x];
    94 			if (p^[x] and AMask) <> 0 then Land[cpY + y, cpX + x]:= COLOR_OBJECT;
    94             if (p^[x] and AMask) <> 0 then Land[cpY + y, cpX + x]:= COLOR_OBJECT;
    95 			end;
    95             end;
    96 	p:= @(p^[Image^.pitch shr 2]);
    96     p:= @(p^[Image^.pitch shr 2]);
    97 	end;
    97     end;
    98 
    98 
    99 if SDL_MustLock(Image) then
    99 if SDL_MustLock(Image) then
   100    SDL_UnlockSurface(Image);
   100    SDL_UnlockSurface(Image);
   101 WriteLnToConsole(msgOK)
   101 WriteLnToConsole(msgOK)
   102 end;
   102 end;
   120 New(Rects)
   120 New(Rects)
   121 end;
   121 end;
   122 
   122 
   123 procedure FreeRects;
   123 procedure FreeRects;
   124 begin
   124 begin
   125 	Dispose(rects)
   125     Dispose(rects)
   126 end;
   126 end;
   127 
   127 
   128 function CheckIntersect(x1, y1, w1, h1: LongInt): boolean;
   128 function CheckIntersect(x1, y1, w1, h1: LongInt): boolean;
   129 var i: Longword;
   129 var i: Longword;
   130     res: boolean = false;
   130     res: boolean = false;
   145 var tmpsurf: PSDL_Surface;
   145 var tmpsurf: PSDL_Surface;
   146     x1, x2, y, k, i: LongInt;
   146     x1, x2, y, k, i: LongInt;
   147     rr: TSDL_Rect;
   147     rr: TSDL_Rect;
   148     bRes: boolean;
   148     bRes: boolean;
   149 
   149 
   150 	function CountNonZeroz(x, y: LongInt): Longword;
   150     function CountNonZeroz(x, y: LongInt): Longword;
   151 	var i: LongInt;
   151     var i: LongInt;
   152 		lRes: Longword;
   152         lRes: Longword;
   153 	begin
   153     begin
   154 	lRes:= 0;
   154     lRes:= 0;
   155 	for i:= y to y + 15 do
   155     for i:= y to y + 15 do
   156 		if Land[i, x] <> 0 then inc(lRes);
   156         if Land[i, x] <> 0 then inc(lRes);
   157 	CountNonZeroz:= lRes;
   157     CountNonZeroz:= lRes;
   158 	end;
   158     end;
   159 
   159 
   160 begin
   160 begin
   161 y:= topY+150;
   161 y:= topY+150;
   162 repeat
   162 repeat
   163 	inc(y, 24);
   163     inc(y, 24);
   164 	x1:= gX;
   164     x1:= gX;
   165 	x2:= gX;
   165     x2:= gX;
   166 
   166 
   167 	while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y) = 0) do dec(x1, 2);
   167     while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y) = 0) do dec(x1, 2);
   168 
   168 
   169 	i:= x1 - 12;
   169     i:= x1 - 12;
   170 	repeat
   170     repeat
   171 		dec(x1, 2);
   171         dec(x1, 2);
   172 		k:= CountNonZeroz(x1, y)
   172         k:= CountNonZeroz(x1, y)
   173 	until (x1 < Longint(leftX)+150) or (k = 0) or (k = 16) or (x1 < i);
   173     until (x1 < Longint(leftX)+150) or (k = 0) or (k = 16) or (x1 < i);
   174 
   174 
   175 	inc(x1, 2);
   175     inc(x1, 2);
   176 	if k = 16 then
   176     if k = 16 then
   177 		begin
   177         begin
   178 		while (x2 < (rightX-150)) and (CountNonZeroz(x2, y) = 0) do inc(x2, 2);
   178         while (x2 < (rightX-150)) and (CountNonZeroz(x2, y) = 0) do inc(x2, 2);
   179 		i:= x2 + 12;
   179         i:= x2 + 12;
   180 		repeat
   180         repeat
   181 		inc(x2, 2);
   181         inc(x2, 2);
   182 		k:= CountNonZeroz(x2, y)
   182         k:= CountNonZeroz(x2, y)
   183 		until (x2 >= (rightX-150)) or (k = 0) or (k = 16) or (x2 > i) or (x2 - x1 >= 768);
   183         until (x2 >= (rightX-150)) or (k = 0) or (k = 16) or (x2 > i) or (x2 - x1 >= 768);
   184 		if (x2 < (rightX - 150)) and (k = 16) and (x2 - x1 > 250) and (x2 - x1 < 768)
   184         if (x2 < (rightX - 150)) and (k = 16) and (x2 - x1 > 250) and (x2 - x1 < 768)
   185 			and not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144) then break;
   185             and not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144) then break;
   186 		end;
   186         end;
   187 x1:= 0;
   187 x1:= 0;
   188 until y > (LAND_HEIGHT-125);
   188 until y > (LAND_HEIGHT-125);
   189 
   189 
   190 if x1 > 0 then
   190 if x1 > 0 then
   191 begin
   191 begin
   192 	bRes:= true;
   192     bRes:= true;
   193 	tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Girder', ifTransparent or ifIgnoreCaps);
   193     tmpsurf:= LoadImage(Pathz[ptCurrTheme] + '/Girder', ifTransparent or ifIgnoreCaps);
   194 	if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptGraphics] + '/Girder', ifCritical or ifTransparent or ifIgnoreCaps);
   194     if tmpsurf = nil then tmpsurf:= LoadImage(Pathz[ptGraphics] + '/Girder', ifCritical or ifTransparent or ifIgnoreCaps);
   195 
   195 
   196 	rr.x:= x1;
   196     rr.x:= x1;
   197 	while rr.x < x2 do
   197     while rr.x < x2 do
   198 		begin
   198         begin
   199 		BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf);
   199         BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf);
   200 		inc(rr.x, tmpsurf^.w);
   200         inc(rr.x, tmpsurf^.w);
   201 		end;
   201         end;
   202 	SDL_FreeSurface(tmpsurf);
   202     SDL_FreeSurface(tmpsurf);
   203 
   203 
   204 	AddRect(x1 - 8, y - 32, x2 - x1 + 16, 80);
   204     AddRect(x1 - 8, y - 32, x2 - x1 + 16, 80);
   205 end
   205 end
   206 else bRes:= false;
   206 else bRes:= false;
   207 
   207 
   208 AddGirder:= bRes;
   208 AddGirder:= bRes;
   209 end;
   209 end;
   303     r: TSDL_Rect;
   303     r: TSDL_Rect;
   304     bRes: boolean;
   304     bRes: boolean;
   305 begin
   305 begin
   306 cnt:= 0;
   306 cnt:= 0;
   307 with Obj do
   307 with Obj do
   308 	begin
   308     begin
   309 	if Maxcnt = 0 then
   309     if Maxcnt = 0 then
   310 		exit(false);
   310         exit(false);
   311 	x:= 0;
   311     x:= 0;
   312 	r.x:= 0;
   312     r.x:= 0;
   313 	r.y:= 0;
   313     r.y:= 0;
   314 	r.w:= Width;
   314     r.w:= Width;
   315 	r.h:= Height + 16;
   315     r.h:= Height + 16;
   316 	repeat
   316     repeat
   317 		y:= 8;
   317         y:= 8;
   318 		repeat
   318         repeat
   319 			if CheckLand(r, x, y - 8, COLOR_LAND)
   319             if CheckLand(r, x, y - 8, COLOR_LAND)
   320 			and not CheckIntersect(x, y, Width, Height) then
   320             and not CheckIntersect(x, y, Width, Height) then
   321 			begin
   321             begin
   322 			ar[cnt].x:= x;
   322             ar[cnt].x:= x;
   323 			ar[cnt].y:= y;
   323             ar[cnt].y:= y;
   324 			inc(cnt);
   324             inc(cnt);
   325 			if cnt > MaxPointsIndex then // buffer is full, do not check the rest land
   325             if cnt > MaxPointsIndex then // buffer is full, do not check the rest land
   326 				begin
   326                 begin
   327 				y:= 5000;
   327                 y:= 5000;
   328 				x:= 5000;
   328                 x:= 5000;
   329 				end
   329                 end
   330 			end;
   330             end;
   331 			inc(y, 12);
   331             inc(y, 12);
   332         until y > LAND_HEIGHT - 1 - Height - 8;
   332         until y > LAND_HEIGHT - 1 - Height - 8;
   333 		inc(x, getrandom(12) + 12)
   333         inc(x, getrandom(12) + 12)
   334     until x > LAND_WIDTH - 1 - Width;
   334     until x > LAND_WIDTH - 1 - Width;
   335 	bRes:= cnt <> 0;
   335     bRes:= cnt <> 0;
   336 	if bRes then
   336     if bRes then
   337 		begin
   337         begin
   338 		i:= getrandom(cnt);
   338         i:= getrandom(cnt);
   339 		r.x:= ar[i].X;
   339         r.x:= ar[i].X;
   340 		r.y:= ar[i].Y;
   340         r.y:= ar[i].Y;
   341 		r.w:= Width;
   341         r.w:= Width;
   342 		r.h:= Height;
   342         r.h:= Height;
   343 		SDL_UpperBlit(Obj.Surf, nil, Surface, @r);
   343         SDL_UpperBlit(Obj.Surf, nil, Surface, @r);
   344 		AddRect(ar[i].x - 32, ar[i].y - 32, Width + 64, Height + 64);
   344         AddRect(ar[i].x - 32, ar[i].y - 32, Width + 64, Height + 64);
   345 		dec(Maxcnt)
   345         dec(Maxcnt)
   346 		end else Maxcnt:= 0
   346         end else Maxcnt:= 0
   347 	end;
   347     end;
   348 TryPut:= bRes;
   348 TryPut:= bRes;
   349 end;
   349 end;
   350 
   350 
   351 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
   351 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
   352 var s: shortstring;
   352 var s: shortstring;
   353     f: textfile;
   353     f: textfile;
   354     i, ii: LongInt;
   354     i, ii: LongInt;
   355     vobcount: Longword;
   355     vobcount: Longword;
   356     c1, c2: TSDL_Color;
   356     c1, c2: TSDL_Color;
   357 
   357 
   358 	procedure CheckRect(Width, Height, x, y, w, h: LongWord);
   358     procedure CheckRect(Width, Height, x, y, w, h: LongWord);
   359 	begin
   359     begin
   360 	if (x + w > Width) then OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
   360     if (x + w > Width) then OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
   361 	if (y + h > Height) then OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
   361     if (y + h > Height) then OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
   362 	end;
   362     end;
   363 
   363 
   364 begin
   364 begin
   365 
   365 
   366 AddProgress;
   366 AddProgress;
   367 
   367 
   394 // TODO - adjust all the theme cloud numbers. This should not be a permanent fix
   394 // TODO - adjust all the theme cloud numbers. This should not be a permanent fix
   395 cCloudsNumber:= cCloudsNumber * (LAND_WIDTH div 2048);
   395 cCloudsNumber:= cCloudsNumber * (LAND_WIDTH div 2048);
   396 
   396 
   397 Readln(f, ThemeObjects.Count);
   397 Readln(f, ThemeObjects.Count);
   398 for i:= 0 to Pred(ThemeObjects.Count) do
   398 for i:= 0 to Pred(ThemeObjects.Count) do
   399 	begin
   399     begin
   400 	Readln(f, s); // filename
   400     Readln(f, s); // filename
   401 	with ThemeObjects.objs[i] do
   401     with ThemeObjects.objs[i] do
   402 			begin
   402             begin
   403 			Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + s, ifCritical or ifTransparent or ifIgnoreCaps);
   403             Surf:= LoadImage(Pathz[ptCurrTheme] + '/' + s, ifCritical or ifTransparent or ifIgnoreCaps);
   404 			Width:= Surf^.w;
   404             Width:= Surf^.w;
   405 			Height:= Surf^.h;
   405             Height:= Surf^.h;
   406 			Read(f, Maxcnt);
   406             Read(f, Maxcnt);
   407 			if (Maxcnt < 1) or (Maxcnt > MAXTHEMEOBJECTS) then OutError('Object''s max count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true);
   407             if (Maxcnt < 1) or (Maxcnt > MAXTHEMEOBJECTS) then OutError('Object''s max count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true);
   408 			with inland do
   408             with inland do
   409 				begin
   409                 begin
   410 				Read(f, x, y, w, h);
   410                 Read(f, x, y, w, h);
   411 				CheckRect(Width, Height, x, y, w, h)
   411                 CheckRect(Width, Height, x, y, w, h)
   412 				end;
   412                 end;
   413 			Read(f, rectcnt);
   413             Read(f, rectcnt);
   414 			for ii:= 1 to rectcnt do
   414             for ii:= 1 to rectcnt do
   415 				with outland[ii] do
   415                 with outland[ii] do
   416 					begin
   416                     begin
   417 					Read(f, x, y, w, h);
   417                     Read(f, x, y, w, h);
   418 					CheckRect(Width, Height, x, y, w, h)
   418                     CheckRect(Width, Height, x, y, w, h)
   419 					end;
   419                     end;
   420 			ReadLn(f)
   420             ReadLn(f)
   421 			end;
   421             end;
   422 	end;
   422     end;
   423 
   423 
   424 // sprays
   424 // sprays
   425 Readln(f, SprayObjects.Count);
   425 Readln(f, SprayObjects.Count);
   426 for i:= 0 to Pred(SprayObjects.Count) do
   426 for i:= 0 to Pred(SprayObjects.Count) do
   427     begin
   427     begin
   451 
   451 
   452 procedure AddThemeObjects(var ThemeObjects: TThemeObjects);
   452 procedure AddThemeObjects(var ThemeObjects: TThemeObjects);
   453 var i, ii, t: LongInt;
   453 var i, ii, t: LongInt;
   454     b: boolean;
   454     b: boolean;
   455 begin
   455 begin
   456 	if ThemeObjects.Count = 0 then exit;
   456     if ThemeObjects.Count = 0 then exit;
   457 	WriteLnToConsole('Adding theme objects...');
   457     WriteLnToConsole('Adding theme objects...');
   458 
   458 
   459 	for i:=0 to ThemeObjects.Count do 
   459     for i:=0 to ThemeObjects.Count do 
   460 		ThemeObjects.objs[i].Maxcnt := max(1, (ThemeObjects.objs[i].Maxcnt * MaxHedgehogs) div 18); // Maxcnt is proportional to map size, but allow objects to span even if we're on a tiny map
   460         ThemeObjects.objs[i].Maxcnt := max(1, (ThemeObjects.objs[i].Maxcnt * MaxHedgehogs) div 18); // Maxcnt is proportional to map size, but allow objects to span even if we're on a tiny map
   461 	 
   461      
   462 	repeat
   462     repeat
   463 		t := getrandom(ThemeObjects.Count);
   463         t := getrandom(ThemeObjects.Count);
   464 		b := false;
   464         b := false;
   465 		for i:=0 to ThemeObjects.Count do
   465         for i:=0 to ThemeObjects.Count do
   466 			begin
   466             begin
   467 			ii := (i+t) mod ThemeObjects.Count;
   467             ii := (i+t) mod ThemeObjects.Count;
   468 			
   468             
   469 			if ThemeObjects.objs[ii].Maxcnt <> 0 then
   469             if ThemeObjects.objs[ii].Maxcnt <> 0 then
   470 				b := b or TryPut(ThemeObjects.objs[ii])
   470                 b := b or TryPut(ThemeObjects.objs[ii])
   471 			end;
   471             end;
   472 	until not b;
   472     until not b;
   473 end;
   473 end;
   474 
   474 
   475 procedure AddSprayObjects(Surface: PSDL_Surface; var SprayObjects: TSprayObjects);
   475 procedure AddSprayObjects(Surface: PSDL_Surface; var SprayObjects: TSprayObjects);
   476 var i, ii, t: LongInt;
   476 var i, ii, t: LongInt;
   477     b: boolean;
   477     b: boolean;
   478 begin
   478 begin
   479 	if SprayObjects.Count = 0 then exit;
   479     if SprayObjects.Count = 0 then exit;
   480 	WriteLnToConsole('Adding spray objects...');
   480     WriteLnToConsole('Adding spray objects...');
   481 
   481 
   482 	for i:=0 to SprayObjects.Count do 
   482     for i:=0 to SprayObjects.Count do 
   483 		SprayObjects.objs[i].Maxcnt := max(1, (SprayObjects.objs[i].Maxcnt * MaxHedgehogs) div 18); // Maxcnt is proportional to map size, but allow objects to span even if we're on a tiny map
   483         SprayObjects.objs[i].Maxcnt := max(1, (SprayObjects.objs[i].Maxcnt * MaxHedgehogs) div 18); // Maxcnt is proportional to map size, but allow objects to span even if we're on a tiny map
   484 	 
   484      
   485 	repeat
   485     repeat
   486 		t := getrandom(SprayObjects.Count);
   486         t := getrandom(SprayObjects.Count);
   487 		b := false;
   487         b := false;
   488 		for i:=0 to SprayObjects.Count do
   488         for i:=0 to SprayObjects.Count do
   489 			begin
   489             begin
   490 			ii := (i+t) mod SprayObjects.Count;
   490             ii := (i+t) mod SprayObjects.Count;
   491 			
   491             
   492 			if SprayObjects.objs[ii].Maxcnt <> 0 then
   492             if SprayObjects.objs[ii].Maxcnt <> 0 then
   493 				b := b or TryPut(SprayObjects.objs[ii], Surface)
   493                 b := b or TryPut(SprayObjects.objs[ii], Surface)
   494 			end;
   494             end;
   495 	until not b;
   495     until not b;
   496 end;
   496 end;
   497 
   497 
   498 procedure AddObjects();
   498 procedure AddObjects();
   499 var i, int: Longword;
   499 var i, int: Longword;
   500 begin
   500 begin