hedgewars/uLand.pas
changeset 3133 1ab5f18f4df8
parent 3058 2ebc20485344
child 3138 1798518e1d73
equal deleted inserted replaced
3132:72ad441d4c2f 3133:1ab5f18f4df8
    39     hasGirders: boolean;  
    39     hasGirders: boolean;  
    40     isMap: boolean;  
    40     isMap: boolean;  
    41     playHeight, playWidth, leftX, rightX, topY, MaxHedgehogs: Longword;  // idea is that a template can specify height/width.  Or, a map, a height/width by the dimensions of the image.  If the map has pixels near top of image, it triggers border.
    41     playHeight, playWidth, leftX, rightX, topY, MaxHedgehogs: Longword;  // idea is that a template can specify height/width.  Or, a map, a height/width by the dimensions of the image.  If the map has pixels near top of image, it triggers border.
    42     LandBackSurface: PSDL_Surface;
    42     LandBackSurface: PSDL_Surface;
    43 
    43 
       
    44 type direction = record x, y: integer; end;
       
    45 var DIR_N: direction = (x: 0; y: -1);
       
    46 var DIR_E: direction = (x: 1; y: 0);
       
    47 var DIR_S: direction = (x: 0; y: 1);
       
    48 var DIR_W: direction = (x: -1; y: 0);
       
    49 var DIR_NONE: direction = (x: 0; y: 0);
       
    50 
    44 procedure initModule;
    51 procedure initModule;
    45 procedure freeModule;
    52 procedure freeModule;
    46 procedure GenMap;
    53 procedure GenMap;
    47 function  GenPreview: TPreview;
    54 function  GenPreview: TPreview;
    48 procedure CheckLandDigest(s: shortstring);
    55 procedure CheckLandDigest(s: shortstring);
    49 function  LandBackPixel(x, y: LongInt): LongWord;
    56 function  LandBackPixel(x, y: LongInt): LongWord;
    50 
    57 
    51 implementation
    58 implementation
    52 uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, uSHA, uIO, uAmmos, uLandTexture;
    59 uses uConsole, uStore, uMisc, uRandom, uTeams, uLandObjects, uSHA, uIO, uAmmos, uLandTexture;
       
    60 
       
    61 operator=(const a, b: direction) c: Boolean;
       
    62 begin
       
    63     c := (a.x = b.x) and (a.y = b.y);
       
    64 end;
    53 
    65 
    54 type TPixAr = record
    66 type TPixAr = record
    55               Count: Longword;
    67               Count: Longword;
    56               ar: array[0..Pred(cMaxEdgePoints)] of TPoint;
    68               ar: array[0..Pred(cMaxEdgePoints)] of TPoint;
    57               end;
    69               end;
   635 
   647 
   636 if SDL_MustLock(Surface) then
   648 if SDL_MustLock(Surface) then
   637     SDL_UnlockSurface(Surface);
   649     SDL_UnlockSurface(Surface);
   638 end;
   650 end;
   639 
   651 
       
   652 procedure GenMaze;
       
   653 const small_cell_size = 128;
       
   654     medium_cell_size = 192;
       
   655     large_cell_size = 256;
       
   656     braidness = 25;
       
   657     maze_inverted = false; //false makes more sense for now
       
   658 
       
   659 var x, y: Longint;
       
   660     bg_color, fg_color: Longint;
       
   661     cellsize: LongInt; //selected by the user in the gui
       
   662     seen_cells_x, seen_cells_y: Longint; //number of cells that can be visited by the generator, that is every second cell in x and y direction. the cells between there are walls that will be removed when we move from one cell to another
       
   663     start_x, start_y: Longint; //first visited cell, must be between 0 and seen_cells_x/y - 1 inclusive
       
   664     num_edges_x, num_edges_y: Longint; //number of resulting edges that need to be vertexificated
       
   665     num_cells_x, num_cells_y: Longint; //actual number of cells, depending on cell size
       
   666     seen_list: array of array of Boolean;
       
   667     xwalls: array of array of Boolean;
       
   668     ywalls: array of array of Boolean;
       
   669     x_edge_list: array of array of Boolean;
       
   670     y_edge_list: array of array of Boolean;
       
   671     maze: array of array of Boolean;
       
   672     pa: TPixAr;
       
   673     num_vertices: Longint;
       
   674     off_y: LongInt;
       
   675 
       
   676 function is_cell_seen(x: Longint; y: Longint): Boolean;
       
   677 begin
       
   678 if (x < 0) or (x >= seen_cells_x) or (y < 0) or (y >= seen_cells_y) then
       
   679     is_cell_seen := true
       
   680 else
       
   681     is_cell_seen := seen_list[x, y];
       
   682 end;
       
   683 
       
   684 function is_x_edge(x, y: Longint): Boolean;
       
   685 begin
       
   686 if (x < 0) or (x > num_edges_x) or (y < 0) or (y > num_cells_y) then
       
   687     is_x_edge := false
       
   688 else
       
   689     is_x_edge := x_edge_list[x, y];
       
   690 end;
       
   691 
       
   692 function is_y_edge(x, y: Longint): Boolean;
       
   693 begin
       
   694 if (x < 0) or (x > num_cells_x) or (y < 0) or (y > num_edges_y) then
       
   695     is_y_edge := false
       
   696 else
       
   697     is_y_edge := y_edge_list[x, y];
       
   698 end;
       
   699 
       
   700 procedure see_cell(x: Longint; y: Longint);
       
   701 var dir: direction;
       
   702     tries: Longint;
       
   703 begin
       
   704 seen_list[x, y] := true;
       
   705 case GetRandom(4) of
       
   706     0: dir := DIR_N;
       
   707     1: dir := DIR_E;
       
   708     2: dir := DIR_S;
       
   709     3: dir := DIR_W;
       
   710 end;
       
   711 tries := 0;
       
   712 while (tries < 5) do
       
   713 begin
       
   714     if is_cell_seen(x + dir.x, y + dir.y) then
       
   715     begin
       
   716         //we have already seen the target cell, decide if we should remove the wall anyway
       
   717         //(or put a wall there if maze_inverted, but we're not doing that right now)
       
   718         if not maze_inverted and (GetRandom(braidness) = 0) then
       
   719         //or just warn that inverted+braid+indestructable terrain != good idea
       
   720         begin
       
   721             case dir.x of
       
   722                 -1: if x > 0 then ywalls[x-1, y] := false;
       
   723                 1: if x < seen_cells_x - 1 then ywalls[x, y] := false;
       
   724             end;
       
   725             case dir.y of
       
   726                 -1: if y > 0 then xwalls[x, y-1] := false;
       
   727                 1: if y < seen_cells_y - 1 then xwalls[x, y] := false;
       
   728             end;
       
   729         end;
       
   730         if dir = DIR_N then //TODO might want to randomize that
       
   731             dir := DIR_E
       
   732         else if dir = DIR_E then
       
   733             dir := DIR_S
       
   734         else if dir = DIR_S then
       
   735             dir := DIR_W
       
   736         else
       
   737             dir := DIR_N;
       
   738     end
       
   739     else //cell wasn't seen yet, go there
       
   740     begin
       
   741         case dir.y of
       
   742             -1: xwalls[x, y-1] := false;
       
   743             1: xwalls[x, y] := false;
       
   744         end;
       
   745         case dir.x of
       
   746             -1: ywalls[x-1, y] := false;
       
   747             1: ywalls[x, y] := false;
       
   748         end;
       
   749         see_cell(x + dir.x, y + dir.y);
       
   750     end;
       
   751 
       
   752     tries := tries + 1;
       
   753 end;
       
   754 
       
   755 end;
       
   756 procedure add_vertex(x, y: Longint);
       
   757 begin
       
   758 writelntoconsole('add_vertex('+inttostr(x)+', '+inttostr(y)+')');
       
   759 if x = NTPX then
       
   760 begin
       
   761     pa.ar[num_vertices].x := NTPX;
       
   762     pa.ar[num_vertices].y := 0;
       
   763 end
       
   764 else
       
   765 begin
       
   766     pa.ar[num_vertices].x := x*cellsize;
       
   767     pa.ar[num_vertices].y := y*cellsize + off_y;
       
   768 end;
       
   769 num_vertices := num_vertices + 1;
       
   770 end;
       
   771 
       
   772 procedure add_edge(x, y: Longint; dir: direction);
       
   773 var i: integer;
       
   774 begin
       
   775 if dir = DIR_N then
       
   776 begin
       
   777     dir := DIR_W
       
   778 end
       
   779 else if dir = DIR_E then
       
   780 begin
       
   781     dir := DIR_N
       
   782 end
       
   783 else if dir = DIR_S then
       
   784 begin
       
   785     dir := DIR_E
       
   786 end
       
   787 else
       
   788 begin
       
   789     dir := DIR_S;
       
   790 end;
       
   791 
       
   792 for i := 0 to 3 do
       
   793 begin
       
   794         if dir = DIR_N then
       
   795             dir := DIR_E
       
   796         else if dir = DIR_E then
       
   797             dir := DIR_S
       
   798         else if dir = DIR_S then
       
   799             dir := DIR_W
       
   800         else
       
   801             dir := DIR_N;
       
   802 
       
   803     if (dir = DIR_N) and is_x_edge(x, y) then
       
   804         begin
       
   805             x_edge_list[x, y] := false;
       
   806             add_vertex(x+1, y);
       
   807             add_edge(x, y-1, DIR_N);
       
   808             break;
       
   809         end;
       
   810 
       
   811     if (dir = DIR_E) and is_y_edge(x+1, y) then
       
   812         begin
       
   813             y_edge_list[x+1, y] := false;
       
   814             add_vertex(x+2, y+1);
       
   815             add_edge(x+1, y, DIR_E);
       
   816             break;
       
   817         end;
       
   818 
       
   819     if (dir = DIR_S) and is_x_edge(x, y+1) then
       
   820         begin
       
   821             x_edge_list[x, y+1] := false;
       
   822             add_vertex(x+1, y+2);
       
   823             add_edge(x, y+1, DIR_S);
       
   824             break;
       
   825         end;
       
   826 
       
   827     if (dir = DIR_W) and is_y_edge(x, y) then
       
   828         begin
       
   829             y_edge_list[x, y] := false;
       
   830             add_vertex(x, y+1);
       
   831             add_edge(x-1, y, DIR_W);
       
   832             break;
       
   833         end;
       
   834 end;
       
   835 
       
   836 end;
       
   837 
       
   838 begin
       
   839 case cMazeSize of
       
   840     0: cellsize := small_cell_size;
       
   841     1: cellsize := medium_cell_size;
       
   842     2: cellsize := large_cell_size;
       
   843 end;
       
   844 
       
   845 num_cells_x := LAND_WIDTH div cellsize;
       
   846 if num_cells_x mod 2 = 0 then num_cells_x := num_cells_x - 1; //needs to be odd
       
   847 num_cells_y := LAND_HEIGHT div cellsize;
       
   848 if num_cells_y mod 2 = 0 then num_cells_y := num_cells_y - 1;
       
   849 num_edges_x := num_cells_x - 1;
       
   850 num_edges_y := num_cells_y - 1;
       
   851 seen_cells_x := num_cells_x div 2;
       
   852 seen_cells_y := num_cells_y div 2;
       
   853 
       
   854 SetLength(seen_list, seen_cells_x, seen_cells_y);
       
   855 SetLength(xwalls, seen_cells_x, seen_cells_y - 1);
       
   856 SetLength(ywalls, seen_cells_x - 1, seen_cells_y);
       
   857 SetLength(x_edge_list, num_edges_x, num_cells_y);
       
   858 SetLength(y_edge_list, num_cells_x, num_edges_y);
       
   859 SetLength(maze, num_cells_x, num_cells_y);
       
   860 
       
   861 num_vertices := 0;
       
   862 
       
   863 (*
       
   864 TODO - Inverted maze
       
   865 if maze_inverted then
       
   866 begin
       
   867     bg_color := 0;
       
   868     fg_color := COLOR_LAND;
       
   869 end
       
   870 else
       
   871 begin*)
       
   872     bg_color := COLOR_LAND;
       
   873     fg_color := 0;
       
   874 //end;
       
   875 
       
   876 playHeight := num_cells_y * cellsize;
       
   877 playWidth := num_cells_x * cellsize;
       
   878 off_y := LAND_HEIGHT - playHeight;
       
   879 
       
   880 for x := 0 to playWidth do
       
   881     for y := 0 to off_y - 1 do
       
   882         Land[y, x] := fg_color;
       
   883 
       
   884 for x := 0 to playWidth do
       
   885     for y := off_y to LAND_HEIGHT - 1 do
       
   886         Land[y, x] := bg_color;
       
   887 
       
   888 for y := 0 to num_cells_y - 1 do
       
   889     for x := 0 to num_cells_x - 1 do
       
   890         maze[x, y] := false;
       
   891 
       
   892 start_x := GetRandom(seen_cells_x);
       
   893 start_y := GetRandom(seen_cells_y);
       
   894 
       
   895 for x := 0 to seen_cells_x - 1 do
       
   896     for y := 0 to seen_cells_y - 2 do
       
   897         xwalls[x, y] := true;
       
   898 
       
   899 for x := 0 to seen_cells_x - 2 do
       
   900     for y := 0 to seen_cells_y - 1 do
       
   901         ywalls[x, y] := true;
       
   902 
       
   903 for x := 0 to seen_cells_x - 1 do
       
   904     for y := 0 to seen_cells_y - 1 do
       
   905         seen_list[x, y] := false;
       
   906 
       
   907 for x := 0 to num_edges_x - 1 do
       
   908     for y := 0 to num_cells_y - 1 do
       
   909         x_edge_list[x, y] := false;
       
   910 
       
   911 for x := 0 to num_cells_x - 1 do
       
   912     for y := 0 to num_edges_y - 1 do
       
   913         y_edge_list[x, y] := false;
       
   914 
       
   915 see_cell(start_x, start_y);
       
   916 
       
   917 for x := 0 to seen_cells_x - 1 do
       
   918     for y := 0 to seen_cells_y - 1 do
       
   919         if seen_list[x, y] then
       
   920             maze[(x+1)*2-1, (y+1)*2-1] := true;
       
   921 
       
   922 for x := 0 to seen_cells_x - 1 do
       
   923     for y := 0 to seen_cells_y - 2 do
       
   924         if not xwalls[x, y] then
       
   925             maze[x*2 + 1, y*2 + 2] := true;
       
   926 
       
   927 
       
   928 for x := 0 to seen_cells_x - 2 do
       
   929      for y := 0 to seen_cells_y - 1 do
       
   930         if not ywalls[x, y] then
       
   931             maze[x*2 + 2, y*2 + 1] := true;
       
   932 
       
   933 for x := 0 to num_edges_x - 1 do
       
   934     for y := 0 to num_cells_y - 1 do
       
   935         if maze[x, y] xor maze[x+1, y] then
       
   936             x_edge_list[x, y] := true
       
   937         else
       
   938             x_edge_list[x, y] := false;
       
   939 
       
   940 for x := 0 to num_cells_x - 1 do
       
   941     for y := 0 to num_edges_y - 1 do
       
   942         if maze[x, y] xor maze[x, y+1] then
       
   943             y_edge_list[x, y] := true
       
   944         else
       
   945             y_edge_list[x, y] := false;
       
   946 
       
   947 for x := 0 to num_edges_x - 1 do
       
   948     for y := 0 to num_cells_y - 1 do
       
   949         if x_edge_list[x, y] then
       
   950         begin
       
   951             x_edge_list[x, y] := false;
       
   952             add_vertex(x+1, y+1);
       
   953             add_vertex(x+1, y);
       
   954             add_edge(x, y-1, DIR_N);
       
   955             add_vertex(NTPX, 0);
       
   956         end;
       
   957 
       
   958 pa.count := num_vertices;
       
   959 
       
   960 RandomizePoints(pa);
       
   961 BezierizeEdge(pa, _0_25);
       
   962 RandomizePoints(pa);
       
   963 BezierizeEdge(pa, _0_5);
       
   964 
       
   965 DrawEdge(pa, 0);
       
   966 
       
   967 for x := 0 to num_cells_x - 1 do
       
   968     for y := 0 to num_cells_y - 1 do
       
   969         if maze[x, y] then begin
       
   970             FillLand(cellsize div 2 + cellsize * x, cellsize div 2 + cellsize * y + off_y);
       
   971             break;
       
   972         end;
       
   973 
       
   974 MaxHedgehogs:= 32;
       
   975 hasGirders:= false;
       
   976 leftX:= 0;
       
   977 rightX:= playWidth;
       
   978 topY:= off_y;
       
   979 hasBorder := true;
       
   980 end;
       
   981 
   640 procedure GenLandSurface;
   982 procedure GenLandSurface;
   641 var tmpsurf: PSDL_Surface;
   983 var tmpsurf: PSDL_Surface;
   642 begin
   984 begin
   643     WriteLnToConsole('Generating land...');
   985     WriteLnToConsole('Generating land...');
   644     GenBlank(EdgeTemplates[SelectTemplate]);
   986     case cMapGen of
       
   987         0: GenBlank(EdgeTemplates[SelectTemplate]);
       
   988         1: GenMaze;
       
   989     end;
   645     AddProgress();
   990     AddProgress();
   646 
   991 
   647     tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, 0);
   992     tmpsurf:= SDL_CreateRGBSurface(SDL_SWSURFACE, LAND_WIDTH, LAND_HEIGHT, 32, RMask, GMask, BMask, 0);
   648 
   993 
   649     TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true);
   994     TryDo(tmpsurf <> nil, 'Error creating pre-land surface', true);
   836 function GenPreview: TPreview;
  1181 function GenPreview: TPreview;
   837 var x, y, xx, yy, t, bit: LongInt;
  1182 var x, y, xx, yy, t, bit: LongInt;
   838     Preview: TPreview;
  1183     Preview: TPreview;
   839 begin
  1184 begin
   840 WriteLnToConsole('Generating preview...');
  1185 WriteLnToConsole('Generating preview...');
   841 GenBlank(EdgeTemplates[SelectTemplate]);
  1186 case cMapGen of
       
  1187     0: GenBlank(EdgeTemplates[SelectTemplate]);
       
  1188     1: GenMaze;
       
  1189 end;
   842 
  1190 
   843 for y:= 0 to 127 do
  1191 for y:= 0 to 127 do
   844     for x:= 0 to 31 do
  1192     for x:= 0 to 31 do
   845         begin
  1193         begin
   846         Preview[y, x]:= 0;
  1194         Preview[y, x]:= 0;