- New land generator feature: islands in the sky
authorunc0rr
Fri, 26 Jan 2007 15:31:31 +0000
changeset 365 a26cec847dd7
parent 364 52cb4d6f84b7
child 366 dc50b7933390
- New land generator feature: islands in the sky - Two themes with such islands
hedgewars/uFloat.pas
hedgewars/uLand.pas
hedgewars/uLandTemplates.pas
--- a/hedgewars/uFloat.pas	Wed Jan 24 22:05:05 2007 +0000
+++ b/hedgewars/uFloat.pas	Fri Jan 26 15:31:31 2007 +0000
@@ -74,7 +74,7 @@
            _0_02: hwFloat = (isNegative: false; QWordValue:    85899345);
            _0_03: hwFloat = (isNegative: false; QWordValue:   128849018);
            _0_08: hwFloat = (isNegative: false; QWordValue:   343597383);
-            _0_1: hwFloat = (isNegative: false; QWordValue:   429496729);
+            _0_1: hwFloat = (isNegative: false; QWordValue:   429496730);
            _0_15: hwFloat = (isNegative: false; QWordValue:   644245094);
             _0_2: hwFloat = (isNegative: false; QWordValue:   858993459);
            _0_25: hwFloat = (isNegative: false; QWordValue:  1073741824);
--- a/hedgewars/uLand.pas	Wed Jan 24 22:05:05 2007 +0000
+++ b/hedgewars/uLand.pas	Fri Jan 26 15:31:31 2007 +0000
@@ -52,7 +52,7 @@
        +inttostr(dig[2])+':'
        +inttostr(dig[3])+':'
        +inttostr(dig[4])+'}';
-SendIPC('M' + s)
+//SendIPC('M' + s)
 end;
 
 procedure DrawLine(X1, Y1, X2, Y2: integer; Color: Longword);
@@ -107,118 +107,75 @@
     end
 end;
 
-procedure DrawBezierEdge(var pa: TPixAr; Color: Longword);
-const dT: hwFloat = (isNegative: false; QWordValue: 85899346);
-var x, y, i, px, py: integer;
-    tx, ty, vx, vy, vlen, t: hwFloat;
-    r1, r2, r3, r4: hwFloat;
-    x1, y1, x2, y2, cx1, cy1, cx2, cy2, tsq, tcb: hwFloat;
+procedure DrawEdge(var pa: TPixAr; Color: Longword);
+var i: integer;
 begin
-vx:= 0;
-vy:= 0;
+i:= 0;
 with pa do
-for i:= 0 to Count-2 do
-    begin
-    vlen:= Distance(ar[i + 1].x - ar[i].X, ar[i + 1].y - ar[i].y);
-    t:=    Distance(ar[i + 1].x - ar[i + 2].X,ar[i + 1].y - ar[i + 2].y);
-    if t<vlen then vlen:= t;
-    vlen:= vlen * _1div3;
-    tx:= ar[i+2].X - ar[i].X;
-    ty:= ar[i+2].y - ar[i].y;
-    t:= Distance(tx, ty);
-    if t.QWordValue = 0 then
-       begin
-       tx:= -tx * 10000;
-       ty:= -ty * 10000;
-       end else
-       begin
-       t:= 1/t;
-       tx:= -tx * t;
-       ty:= -ty * t;
-       end;
-    t:= vlen;
-    tx:= tx * t;
-    ty:= ty * t;
-    x1:= ar[i].x;
-    y1:= ar[i].y;
-    x2:= ar[i + 1].x;
-    y2:= ar[i + 1].y;
-    cx1:= ar[i].X   + hwRound(vx);
-    cy1:= ar[i].y   + hwRound(vy);
-    cx2:= ar[i+1].X + hwRound(tx);
-    cy2:= ar[i+1].y + hwRound(ty);
-    vx:= -tx;
-    vy:= -ty;
-    px:= hwRound(x1);
-    py:= hwRound(y1);
-    t:= dT;
-    while t.Round = 0 do
-          begin
-          tsq:= t * t;
-          tcb:= tsq * t;
-          r1:= (1 - 3*t + 3*tsq -   tcb) * x1;
-          r2:= (    3*t - 6*tsq + 3*tcb) * cx1;
-          r3:= (          3*tsq - 3*tcb) * cx2;
-          r4:= (                    tcb) * x2;
-          X:= hwRound(r1 + r2 + r3 + r4);
-          r1:= (1 - 3*t + 3*tsq -   tcb) * y1;
-          r2:= (    3*t - 6*tsq + 3*tcb) * cy1;
-          r3:= (          3*tsq - 3*tcb) * cy2;
-          r4:= (                    tcb) * y2;
-          Y:= hwRound(r1 + r2 + r3 + r4);
-          t:= t + dT;
-          DrawLine(px, py, x, y, Color);
-          px:= x;
-          py:= y
-          end;
-    DrawLine(px, py, hwRound(x2), hwRound(y2), Color)
-    end;
+while i < integer(Count) - 1 do
+    if (ar[i + 1].X = NTPX) then inc(i, 2)
+       else begin
+       DrawLine(ar[i].x, ar[i].y, ar[i + 1].x, ar[i + 1].y, Color);
+       inc(i)
+       end
 end;
 
-procedure BezierizeEdge(var pa: TPixAr; Delta: hwFloat);
-var x, y, i: integer;
-    tx, ty, vx, vy, vlen, t: hwFloat;
-    r1, r2, r3, r4: hwFloat;
-    x1, y1, x2, y2, cx1, cy1, cx2, cy2, tsq, tcb: hwFloat;
-    opa: TPixAr;
+procedure Vector(p1, p2, p3: TPoint; var Vx, Vy: hwFloat);
+var d1, d2, d: hwFloat;
 begin
-opa:= pa;
-pa.Count:= 0;
-vx:= 0;
-vy:= 0;
-with opa do
-for i:= 0 to Count-2 do
-    begin
-    vlen:= Distance(ar[i + 1].x - ar[i].X, ar[i + 1].y - ar[i].y);
-    t:=    Distance(ar[i + 1].x - ar[i + 2].X,ar[i + 1].y - ar[i + 2].y);
-    if t<vlen then vlen:= t;
-    vlen:= vlen * _1div3;
-    tx:= ar[i+2].X - ar[i].X;
-    ty:= ar[i+2].y - ar[i].y;
-    t:= Distance(tx, ty);
-    if t.QWordValue = 0 then
-       begin
-       tx:= -tx * 100000;
-       ty:= -ty * 100000;
-       end else
-       begin
-       t:= 1/t;
-       tx:= -tx * t;
-       ty:= -ty * t;
-       end;
-    t:= vlen;
-    tx:= tx*t;
-    ty:= ty*t;
-    x1:= ar[i].x;
-    y1:= ar[i].y;
-    x2:= ar[i + 1].x;
-    y2:= ar[i + 1].y;
-    cx1:= ar[i].X   + hwRound(vx);
-    cy1:= ar[i].y   + hwRound(vy);
-    cx2:= ar[i+1].X + hwRound(tx);
-    cy2:= ar[i+1].y + hwRound(ty);
-    vx:= -tx;
-    vy:= -ty;
+Vx:= p1.X - p3.X;
+Vy:= p1.Y - p3.Y;
+d:= Distance(p2.X - p1.X, p2.Y - p1.Y);
+d1:= Distance(p2.X - p3.X, p2.Y - p3.Y);
+d2:= Distance(Vx, Vy);
+if d1 < d then d:= d1;
+if d2 < d then d:= d2;
+d:= d * _1div3;
+if d2.QWordValue = 0 then
+   begin
+   Vx:= 0;
+   Vy:= 0
+   end else
+   begin
+   d2:= 1 / d2;
+   Vx:= Vx * d2;
+   Vy:= Vy * d2;
+
+   Vx:= Vx * d;
+   Vy:= Vy * d
+   end
+end;
+
+procedure AddLoopPoints(var pa, opa: TPixAr; StartI, EndI: integer; Delta: hwFloat);
+var i, pi, ni: integer;
+    NVx, NVy, PVx, PVy: hwFloat;
+    x1, x2, y1, y2, cx1, cx2, cy1, cy2: hwFloat;
+    tsq, tcb, t, r1, r2, r3, r4: hwFloat;
+    X, Y: integer;
+begin
+pi:= EndI;
+i:= StartI;
+ni:= Succ(StartI);
+Vector(opa.ar[pi], opa.ar[i], opa.ar[ni], NVx, NVy);
+repeat
+    inc(pi);
+    if pi > EndI then pi:= StartI;
+    inc(i);
+    if i > EndI then i:= StartI;
+    inc(ni);
+    if ni > EndI then ni:= StartI;
+    PVx:= NVx;
+    PVy:= NVy;
+    Vector(opa.ar[pi], opa.ar[i], opa.ar[ni], NVx, NVy);
+
+    x1:= opa.ar[pi].x;
+    y1:= opa.ar[pi].y;
+    x2:= opa.ar[i].x;
+    y2:= opa.ar[i].y;
+    cx1:= x1 - PVx;
+    cy1:= y1 - PVy;
+    cx2:= x2 + NVx;
+    cy2:= y2 + NVy;
     t:= 0;
     while t.Round = 0 do
           begin
@@ -240,12 +197,31 @@
           inc(pa.Count);
           TryDo(pa.Count <= cMaxEdgePoints, 'Edge points overflow', true)
           end;
-    end;
-pa.ar[pa.Count].x:= opa.ar[Pred(opa.Count)].X;
-pa.ar[pa.Count].y:= opa.ar[Pred(opa.Count)].Y;
+until i = StartI;
+pa.ar[pa.Count].x:= opa.ar[StartI].X;
+pa.ar[pa.Count].y:= opa.ar[StartI].Y;
 inc(pa.Count)
 end;
 
+procedure BezierizeEdge(var pa: TPixAr; Delta: hwFloat);
+var x, y, i, StartLoop: integer;
+    opa: TPixAr;
+begin
+opa:= pa;
+pa.Count:= 0;
+i:= 0;
+StartLoop:= 0;
+while i < integer(opa.Count) do
+    if (opa.ar[i + 1].X = NTPX) then
+       begin
+       AddLoopPoints(pa, opa, StartLoop, i, Delta);
+       inc(i, 2);
+       StartLoop:= i;
+       pa.ar[pa.Count].X:= NTPX;
+       inc(pa.Count);
+       end else inc(i)
+end;
+
 procedure FillLand(x, y: integer);
 var Stack: record
            Count: Longword;
@@ -394,6 +370,7 @@
         if getrandom(2) = 0 then
            begin
            for i:= 0 to pred(BasePointsCount) do
+             if pa.ar[i].x <> NTPX then
                pa.ar[i].x:= 2047 - pa.ar[i].x;
            for i:= 0 to pred(FillPointsCount) do
                FillPoints^[i].x:= 2047 - FillPoints^[i].x;
@@ -409,87 +386,35 @@
            end;
      end
 end;
-(*
-procedure NormalizePoints(var pa: TPixAr);
-const brd = 32;
-var isUP: boolean;  // HACK: transform for Y should be exact as one for X
-    Left, Right, Top, Bottom,
-    OWidth, Width, OHeight, Height,
-    OLeft: integer;
-    i: integer;
-begin
-TryDo((pa.ar[0].y < 0) or (pa.ar[0].y > 1023), 'Bad land generated', true);
-TryDo((pa.ar[Pred(pa.Count)].y < 0) or (pa.ar[Pred(pa.Count)].y > 1023), 'Bad land generated', true);
-isUP:= pa.ar[0].y > 0;
-Left:= 1023;
-Right:= Left;
-Top:= pa.ar[0].y;
-Bottom:= Top;
 
-for i:= 1 to Pred(pa.Count) do
-    with pa.ar[i] do
-         begin
-         if (y and $FFFFFC00) = 0 then
-            if x < Left then Left:= x else
-            if x > Right then Right:= x;
-         if y < Top then Top:= y else
-         if y > Bottom then Bottom:= y
-         end;
-
-if (Left < brd) or (Right > 2047 - brd) then
-   begin
-   OLeft:= Left;
-   OWidth:= Right - OLeft;
-   if Left < brd then Left:= brd;
-   if Right > 2047 - brd then Right:= 2047 - brd;
-   Width:= Right - Left;
-   for i:= 0 to Pred(pa.Count) do
-       with pa.ar[i] do
-            x:= round((x - OLeft) * Width div OWidth + Left)
-   end;
-
-if isUp then // FIXME: remove hack
-   if Top < brd then
-      begin
-      OHeight:= 1023 - Top;
-      Height:= 1023 - brd;
-      for i:= 0 to Pred(pa.Count) do
-          with pa.ar[i] do
-               y:= round((y - 1023) * Height div OHeight + 1023)
-   end;
-end;*)
-
-procedure RandomizePoints(var pa: TPixAr);
+procedure RandomizePoints(var pa: TPixAr; MaxRad: integer);
 const cEdge = 55;
-      cMinDist = 14;
+      cMinDist = 0;
 var radz: array[0..Pred(cMaxEdgePoints)] of integer;
     i, k, dist: integer;
 begin
 radz[0]:= 0;
 for i:= 0 to Pred(pa.Count) do
   with pa.ar[i] do
-    begin
-    radz[i]:= Min(Max(x - cEdge, 0), Max(2048 - cEdge - x, 0));
-    radz[i]:= Min(radz[i], Min(Max(y - cEdge, 0), Max(1024 - cEdge - y, 0)));
-    if radz[i] > 0 then
-      for k:= 0 to Pred(i) do
-        begin
-        dist:= Min(Max(abs(x - pa.ar[k].x), abs(y - pa.ar[k].y)), 50);
-        if radz[k] >= dist then
+    if x <> NTPX then
+      begin
+      radz[i]:= Min(Max(x - cEdge, 0), Max(2048 - cEdge - x, 0));
+      radz[i]:= Min(radz[i], Min(Max(y - cEdge, 0), Max(1024 - cEdge - y, 0)));
+      if radz[i] > 0 then
+        for k:= 0 to Pred(i) do
           begin
-          radz[k]:= Max(0, dist - cMinDist * 2);
-          radz[i]:= Min(dist - radz[k], radz[i])
-          end;
-        radz[i]:= Min(radz[i], dist)
-      end
-    end;
+          dist:= Min(Max(abs(x - pa.ar[k].x), abs(y - pa.ar[k].y)), MaxRad);
+          radz[k]:= Max(0, Min((dist - cMinDist) div 2, radz[k]));
+          radz[i]:= Max(0, Min(dist - radz[k] - cMinDist, radz[i]))
+        end
+      end;
 
 for i:= 0 to Pred(pa.Count) do
   with pa.ar[i] do
     if ((x and $FFFFF800) = 0) and ((y and $FFFFFC00) = 0) then
       begin
-      x:= x + integer(GetRandom(radz[i] * 2 + 1)) - radz[i];
-      y:= y + integer(GetRandom(radz[i] * 2 + 1)) - radz[i]
+      x:= x + integer(GetRandom(7) - 3) * (radz[i] * 5 div 7) div 3;
+      y:= y + integer(GetRandom(7) - 3) * (radz[i] * 5 div 7) div 3
       end
 end;
 
@@ -505,17 +430,19 @@
 
 SetPoints(Template, pa);
 BezierizeEdge(pa, _1div3);
-for i:= 0 to Pred(Template.RandPassesCount) do RandomizePoints(pa);
-//NormalizePoints(pa);
+for i:= 0 to Pred(Template.RandPassesCount) do RandomizePoints(pa, 1000);
+BezierizeEdge(pa, _1div3);
+RandomizePoints(pa, 1000);
+BezierizeEdge(pa, _0_1);
 
-DrawBezierEdge(pa, 0);
+DrawEdge(pa, 0);
 
 with Template do
      for i:= 0 to pred(FillPointsCount) do
          with FillPoints^[i] do
               FillLand(x, y);
 
-DrawBezierEdge(pa, COLOR_LAND)
+DrawEdge(pa, COLOR_LAND)
 end;
 
 function SelectTemplate: integer;
--- a/hedgewars/uLandTemplates.pas	Wed Jan 24 22:05:05 2007 +0000
+++ b/hedgewars/uLandTemplates.pas	Fri Jan 26 15:31:31 2007 +0000
@@ -21,6 +21,8 @@
 uses SDLh, uFloat;
 {$INCLUDE options.inc}
 
+const NTPX = Low(TSDL_Rect.x); 
+
 type PPointArray = ^TPointArray;
      TPointArray = array[0..64] of TSDL_Rect;
      TEdgeTemplate = record
@@ -32,7 +34,7 @@
                      canMirror, canFlip: boolean;
                      end;
 
-const Template0Points: array[0..17] of TSDL_Rect =
+const Template0Points: array[0..18] of TSDL_Rect =
       (
        (x:  410; y: 1024; w:    1; h:    1),
        (x:  160; y:  760; w:  130; h:  170),
@@ -51,14 +53,15 @@
        (x: 1588; y:  194; w:  148; h:  332),
        (x: 1618; y:  472; w:  276; h:  314),
        (x: 1710; y:  850; w:  130; h:   86),
-       (x: 1734; y: 1024; w:    1; h:    1)
+       (x: 1734; y: 1024; w:    1; h:    1),
+       (x: NTPX; y:    0; w:    1; h:    1)
       );
       Template0FPoints: array[0..0] of TPoint =
       (
        (x: 1023; y:    0)
       );
 
-const Template1Points: array[0..14] of TSDL_Rect =
+const Template1Points: array[0..15] of TSDL_Rect =
       (
        (x:  400; y: 1024; w:   25; h:    1),
        (x:  284; y:  892; w:  254; h:   58),
@@ -74,14 +77,15 @@
        (x: 1270; y:  194; w:  120; h:  392),
        (x: 1514; y:  194; w:  364; h:  362),
        (x: 1450; y:  652; w:  315; h:  232),
-       (x: 1460; y: 1024; w:   25; h:    1)
+       (x: 1460; y: 1024; w:   25; h:    1),
+       (x: NTPX; y:    0; w:    1; h:    1)
       );
       Template1FPoints: array[0..0] of TPoint =
       (
        (x: 1023; y:    0)
       );
 
-const Template2Points: array[0..20] of TSDL_Rect =
+const Template2Points: array[0..21] of TSDL_Rect =
       (
        (x:  354; y: 1024; w:    1; h:    1),
        (x:  232; y:  926; w:  226; h:   60),
@@ -103,14 +107,71 @@
        (x: 1702; y:  246; w:  156; h:  258),
        (x: 1700; y:  548; w:  132; h:  340),
        (x: 1534; y:  898; w:  252; h:   82),
-       (x: 1604; y: 1024; w:    1; h:    1)
+       (x: 1604; y: 1024; w:    1; h:    1),
+       (x: NTPX; y:    0; w:    1; h:    1)
       );
       Template2FPoints: array[0..0] of TPoint =
       (
        (x: 1023; y:    0)
       );
 
-const EdgeTemplates: array[0..2] of TEdgeTemplate =
+const Template3Points: array[0..16] of TSDL_Rect =
+      (
+       (x:  348; y: 1024; w:    1; h:    1),
+       (x:  236; y:  852; w:  208; h:   72),
+       (x:  498; y:  710; w:  308; h:   60),
+       (x:  728; y:  852; w:  434; h:   40),
+       (x: 1174; y:  712; w:  332; h:   40),
+       (x: 1402; y:  838; w:  226; h:   36),
+       (x: 1530; y: 1024; w:    1; h:    1),
+       (x: NTPX; y:    0; w:    1; h:    1),
+       (x: 1660; y:  498; w:  111; h:  111),
+       (x: 1270; y:  476; w:   34; h:  102),
+       (x:  682; y:  414; w:  284; h:  132),
+       (x:  230; y:  328; w:  126; h:  168),
+       (x:  410; y:  174; w:  114; h:  100),
+       (x:  790; y:  172; w:  352; h:  120),
+       (x: 1274; y:  128; w:   60; h:  240),
+       (x: 1434; y:  222; w:  254; h:  116),
+       (x: NTPX; y:    0; w:    1; h:    1)
+      );
+      Template3FPoints: array[0..0] of TPoint =
+      (
+       (x: 1023; y:    0)
+      );
+
+const Template4Points: array[0..22] of TSDL_Rect =
+      (
+       (x:  418; y: 1024; w:    1; h:    1),
+       (x:  248; y:  900; w:  186; h:   62),
+       (x:  272; y:  692; w:  254; h:  138),
+       (x:  610; y:  768; w:   90; h:  166),
+       (x:  820; y:  616; w:  224; h:  258),
+       (x: 1242; y:  758; w:   96; h:  146),
+       (x: 1550; y:  698; w:  224; h:  134),
+       (x: 1530; y:  902; w:  210; h:   54),
+       (x: 1532; y: 1024; w:    1; h:    1),
+       (x: NTPX; y:    0; w:    1; h:    1),
+       (x:  202; y:  418; w:  110; h:   92),
+       (x:  252; y:  312; w:  160; h:   32),
+       (x:  150; y:  168; w:  134; h:   78),
+       (x:  702; y:  160; w:  132; h:   84),
+       (x:  702; y:  308; w:  230; h:   36),
+       (x:  720; y:  408; w:  166; h:   96),
+       (x: NTPX; y:    0; w:    1; h:    1),
+       (x: 1702; y:  434; w:  202; h:   42),
+       (x: 1252; y:  388; w:  134; h:   98),
+       (x: 1214; y:  152; w:  116; h:  154),
+       (x: 1428; y:  252; w:  150; h:   70),
+       (x: 1750; y:  152; w:   86; h:  220),
+       (x: NTPX; y:    0; w:    1; h:    1)
+      );
+      Template4FPoints: array[0..0] of TPoint =
+      (
+       (x: 1023; y:    0)
+      );
+
+const EdgeTemplates: array[0..4] of TEdgeTemplate =
       (
        (BasePoints: @Template0Points;
         BasePointsCount: Succ(High(Template0Points));
@@ -124,14 +185,28 @@
         FillPoints: @Template1FPoints;
         FillPointsCount: Succ(High(Template1FPoints));
         RandPassesCount: 3;
-        canMirror: true; canFlip: false;
+        canMirror: false; canFlip: false;
        ),
        (BasePoints: @Template2Points;
         BasePointsCount: Succ(High(Template2Points));
         FillPoints: @Template2FPoints;
         FillPointsCount: Succ(High(Template2FPoints));
         RandPassesCount: 3;
-        canMirror: true; canFlip: false;
+        canMirror: false; canFlip: false;
+       ),
+       (BasePoints: @Template3Points;
+        BasePointsCount: Succ(High(Template3Points));
+        FillPoints: @Template3FPoints;
+        FillPointsCount: Succ(High(Template3FPoints));
+        RandPassesCount: 3;
+        canMirror: false; canFlip: false;
+       ),
+       (BasePoints: @Template4Points;
+        BasePointsCount: Succ(High(Template4Points));
+        FillPoints: @Template4FPoints;
+        FillPointsCount: Succ(High(Template4FPoints));
+        RandPassesCount: 3;
+        canMirror: false; canFlip: false;
        )
       );