hedgewars/uLandGenTemplateBased.pas
branchqmlfrontend
changeset 10515 7705784902e1
parent 10510 9329dab04490
child 10562 3388822b3914
equal deleted inserted replaced
10458:f7a199346c3e 10515:7705784902e1
     3 
     3 
     4 uses uLandTemplates, uLandOutline;
     4 uses uLandTemplates, uLandOutline;
     5 
     5 
     6 procedure GenTemplated(var Template: TEdgeTemplate);
     6 procedure GenTemplated(var Template: TEdgeTemplate);
     7 procedure DivideEdges(fillPointsCount: LongWord; var pa: TPixAr);
     7 procedure DivideEdges(fillPointsCount: LongWord; var pa: TPixAr);
       
     8 
       
     9 var minDistance, dabDiv: LongInt; // different details size
     8 
    10 
     9 implementation
    11 implementation
    10 uses uVariables, uConsts, uFloat, uLandUtils, uRandom, SDLh, math;
    12 uses uVariables, uConsts, uFloat, uLandUtils, uRandom, SDLh, math;
    11 
    13 
    12 
    14 
    95     BezierizeEdge(pa, _0_1);
    97     BezierizeEdge(pa, _0_1);
    96 end;
    98 end;
    97 
    99 
    98 procedure FindPoint(si: LongInt; fillPointsCount: LongWord; var newPoint: TPoint; var pa: TPixAr);
   100 procedure FindPoint(si: LongInt; fillPointsCount: LongWord; var newPoint: TPoint; var pa: TPixAr);
    99 const mapBorderMargin = 40;
   101 const mapBorderMargin = 40;
   100     minDistance = 32; // adjust/parametrize this for different details size
       
   101 var p1, p2, p4, fp, mp: TPoint;
   102 var p1, p2, p4, fp, mp: TPoint;
   102     i, t1, t2, iy, ix, aqpb: LongInt;
   103     i, t1, t2, iy, ix, aqpb: LongInt;
   103     a, b, p, q: LongInt;
   104     a, b, p, q: LongInt;
   104     dab, d, distL, distR: LongInt;
   105     dab, d, distL, distR: LongInt;
   105 begin
   106 begin
   125     mp.x:= (p1.x + p2.x) div 2;
   126     mp.x:= (p1.x + p2.x) div 2;
   126     mp.y:= (p1.y + p2.y) div 2;
   127     mp.y:= (p1.y + p2.y) div 2;
   127 
   128 
   128     // don't process too short segments or those which are too close to map borders
   129     // don't process too short segments or those which are too close to map borders
   129     if (p1.x = NTPX)
   130     if (p1.x = NTPX)
   130             or (dab < minDistance * 3) 
   131             or (dab < minDistance * 3)
   131             or (mp.x < LongInt(leftX) + mapBorderMargin)
   132             or (mp.x < LongInt(leftX) + mapBorderMargin)
   132             or (mp.x > LongInt(rightX) - mapBorderMargin)
   133             or (mp.x > LongInt(rightX) - mapBorderMargin)
   133             or (mp.y < LongInt(topY) + mapBorderMargin)
   134             or (mp.y < LongInt(topY) + mapBorderMargin)
   134             or (mp.y > LongInt(LAND_HEIGHT) - mapBorderMargin)
   135             or (mp.y > LongInt(LAND_HEIGHT) - mapBorderMargin)
   135     then
   136     then
   146         d:= DistanceI(mp.x - leftX - mapBorderMargin, mp.y - iy).Round;
   147         d:= DistanceI(mp.x - leftX - mapBorderMargin, mp.y - iy).Round;
   147         t1:= a * (mp.x - mapBorderMargin) + b * (mp.y - iy);
   148         t1:= a * (mp.x - mapBorderMargin) + b * (mp.y - iy);
   148         if t1 > 0 then distL:= d else distR:= d;
   149         if t1 > 0 then distL:= d else distR:= d;
   149 
   150 
   150         // right border
   151         // right border
   151         iy:= (rightX - mapBorderMargin - mp.x) * b div a + mp.y;
   152         iy:= (LongInt(rightX) - mapBorderMargin - mp.x) * b div a + mp.y;
   152         d:= DistanceI(mp.x - rightX + mapBorderMargin, mp.y - iy).Round;
   153         d:= DistanceI(mp.x - rightX + mapBorderMargin, mp.y - iy).Round;
   153         if t1 > 0 then distR:= d else distL:= d;
   154         if t1 > 0 then distR:= d else distL:= d;
       
   155     end else
       
   156     begin
       
   157         distL:= LAND_WIDTH + LAND_HEIGHT;
       
   158         distR:= distL;
   154     end;
   159     end;
   155 
   160 
   156     if b <> 0 then
   161     if b <> 0 then
   157     begin
   162     begin
   158         // top border
   163         // top border
   189                 aqpb:= a * q - p * b;
   194                 aqpb:= a * q - p * b;
   190 
   195 
   191                 if (aqpb <> 0) then
   196                 if (aqpb <> 0) then
   192                 begin
   197                 begin
   193                     // (ix; iy) is intersection point
   198                     // (ix; iy) is intersection point
   194                     iy:= ((Int64(pa.ar[i].x - mp.x) * b + Int64(mp.y) * a) * q - Int64(pa.ar[i].y) * p * b) div aqpb;
   199                     iy:= (((Int64(pa.ar[i].x) - mp.x) * b + Int64(mp.y) * a) * q - Int64(pa.ar[i].y) * p * b) div aqpb;
   195                     if abs(b) > abs(q) then
   200                     if abs(b) > abs(q) then
   196                         ix:= (iy - mp.y) * a div b + mp.x
   201                         ix:= (iy - mp.y) * a div b + mp.x
   197                     else
   202                     else
   198                         ix:= (iy - pa.ar[i].y) * p div q + pa.ar[i].x;
   203                         ix:= (iy - pa.ar[i].y) * p div q + pa.ar[i].x;
   199 
   204 
   220                 aqpb:= a * q - p * b;
   225                 aqpb:= a * q - p * b;
   221 
   226 
   222                 if (aqpb <> 0) then
   227                 if (aqpb <> 0) then
   223                 begin
   228                 begin
   224                     // (ix; iy) is intersection point
   229                     // (ix; iy) is intersection point
   225                     iy:= ((Int64(p1.x - mp.x) * b + Int64(mp.y) * a) * q - Int64(p1.y) * p * b) div aqpb;
   230                     iy:= (((Int64(p1.x) - mp.x) * b + Int64(mp.y) * a) * q - Int64(p1.y) * p * b) div aqpb;
   226                     if abs(b) > abs(q) then
   231                     if abs(b) > abs(q) then
   227                         ix:= (iy - mp.y) * a div b + mp.x
   232                         ix:= (iy - mp.y) * a div b + mp.x
   228                     else
   233                     else
   229                         ix:= (iy - p1.y) * p div q + p1.x;
   234                         ix:= (iy - p1.y) * p div q + p1.x;
   230 
   235 
   239                 aqpb:= a * q - p * b;
   244                 aqpb:= a * q - p * b;
   240 
   245 
   241                 if (aqpb <> 0) then
   246                 if (aqpb <> 0) then
   242                 begin
   247                 begin
   243                     // (ix; iy) is intersection point
   248                     // (ix; iy) is intersection point
   244                     iy:= ((Int64(p2.x - mp.x) * b + Int64(mp.y) * a) * q - Int64(p2.y) * p * b) div aqpb;
   249                     iy:= (((Int64(p2.x) - mp.x) * b + Int64(mp.y) * a) * q - Int64(p2.y) * p * b) div aqpb;
   245                     if abs(b) > abs(q) then
   250                     if abs(b) > abs(q) then
   246                         ix:= (iy - mp.y) * a div b + mp.x
   251                         ix:= (iy - mp.y) * a div b + mp.x
   247                     else
   252                     else
   248                         ix:= (iy - p2.y) * p div q + p2.x;
   253                         ix:= (iy - p2.y) * p div q + p2.x;
   249 
   254 
   254             end;
   259             end;
   255         end;
   260         end;
   256 
   261 
   257     // don't move new point for more than length of initial segment
   262     // don't move new point for more than length of initial segment
   258     // adjust/parametrize for more flat surfaces (try values 3/4, 1/2 of dab, or even 1/4)
   263     // adjust/parametrize for more flat surfaces (try values 3/4, 1/2 of dab, or even 1/4)
   259     d:= dab;
   264     d:= dab * 100 div dabDiv;
       
   265     //d:= dab * (1 + abs(cFeatureSize - 8)) div 6;
       
   266     //d:= dab * (14 + cFeatureSize) div 20;
   260     if distL > d then distL:= d;
   267     if distL > d then distL:= d;
   261     if distR > d then distR:= d;
   268     if distR > d then distR:= d;
   262 
   269 
   263     if distR + distL < minDistance * 2 + 10 then
   270     if distR + distL < minDistance * 2 + 10 then
   264     begin
   271     begin
   334     fps:=Template.FillPoints^;
   341     fps:=Template.FillPoints^;
   335     ResizeLand(Template.TemplateWidth, Template.TemplateHeight);
   342     ResizeLand(Template.TemplateWidth, Template.TemplateHeight);
   336     for y:= 0 to LAND_HEIGHT - 1 do
   343     for y:= 0 to LAND_HEIGHT - 1 do
   337         for x:= 0 to LAND_WIDTH - 1 do
   344         for x:= 0 to LAND_WIDTH - 1 do
   338             Land[y, x]:= lfBasic;
   345             Land[y, x]:= lfBasic;
   339             
   346 
       
   347     minDistance:= sqr(cFeatureSize) div 8 + 10;
       
   348     //dabDiv:= getRandom(41)+60;
       
   349     //dabDiv:= getRandom(31)+70;
       
   350     dabDiv:= getRandom(21)+100;
   340     MaxHedgehogs:= Template.MaxHedgehogs;
   351     MaxHedgehogs:= Template.MaxHedgehogs;
   341     hasGirders:= Template.hasGirders;
   352     hasGirders:= Template.hasGirders;
   342     playHeight:= Template.TemplateHeight;
   353     playHeight:= Template.TemplateHeight;
   343     playWidth:= Template.TemplateWidth;
   354     playWidth:= Template.TemplateWidth;
   344     leftX:= (LAND_WIDTH - playWidth) div 2;
   355     leftX:= (LAND_WIDTH - playWidth) div 2;
   345     rightX:= Pred(leftX + playWidth);
   356     rightX:= Pred(leftX + playWidth);
   346     topY:= LAND_HEIGHT - playHeight;
   357     topY:= LAND_HEIGHT - playHeight;
   347     
   358 
   348     {$HINTS OFF}
   359     {$HINTS OFF}
   349     SetPoints(Template, pa, @fps);
   360     SetPoints(Template, pa, @fps);
   350     {$HINTS ON}
   361     {$HINTS ON}
   351 
   362 
   352     Distort2(Template, @fps, pa);
   363     Distort2(Template, @fps, pa);