1 /*
2 * OpenClonk, http://www.openclonk.org
3 *
4 * Copyright (c) 1998-2000, Matthes Bender
5 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6 * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7 *
8 * Distributed under the terms of the ISC license; see accompanying file
9 * "COPYING" for details.
10 *
11 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12 * See accompanying file "TRADEMARK" for details.
13 *
14 * To redistribute this file separately, substitute the full license texts
15 * for the above references.
16 */
17
18 /* Create map from dynamic landscape data in scenario */
19
20 #include "C4Include.h"
21 #include "landscape/C4Map.h"
22
23 #include "landscape/C4Texture.h"
24 #include "lib/C4Random.h"
25 #include "graphics/CSurface8.h"
26
C4MapCreator()27 C4MapCreator::C4MapCreator()
28 {
29 Reset();
30 }
31
Reset()32 void C4MapCreator::Reset()
33 {
34 MapBuf=nullptr;
35 Exclusive=-1;
36 }
37
SetPix(int32_t x,int32_t y,BYTE col)38 void C4MapCreator::SetPix(int32_t x, int32_t y, BYTE col)
39 {
40 // Safety
41 if (!Inside<int32_t>(x,0,MapWdt-1) || !Inside<int32_t>(y,0,MapHgt-1)) return;
42 // Exclusive
43 if (Exclusive>-1) if (GetPix(x,y)!=Exclusive) return;
44 // Set pix
45 MapBuf->SetPix(x,y,col);
46 }
47
SetSpot(int32_t x,int32_t y,int32_t rad,BYTE col)48 void C4MapCreator::SetSpot(int32_t x, int32_t y, int32_t rad, BYTE col)
49 {
50 int32_t ycnt,xcnt,lwdt,dpy;
51 for (ycnt=-rad; ycnt<=rad; ycnt++)
52 {
53 lwdt= (int32_t) sqrt(double(rad*rad-ycnt*ycnt)); dpy=y+ycnt;
54 for (xcnt=-lwdt; xcnt<lwdt+(lwdt==0); xcnt++)
55 SetPix(x+xcnt,dpy,col);
56 }
57 }
58
DrawLayer(int32_t x,int32_t y,int32_t size,BYTE col)59 void C4MapCreator::DrawLayer(int32_t x, int32_t y, int32_t size, BYTE col)
60 {
61 int32_t cnt,cnt2;
62 for (cnt=0; cnt<size; cnt++)
63 {
64 x+=Random(9)-4; y+=Random(3)-1;
65 for (cnt2=Random(3); cnt2<5; cnt2++)
66 { SetPix(x+cnt2,y,col); SetPix(x+cnt2+1,y+1,col); }
67 }
68 }
69
GetPix(int32_t x,int32_t y)70 BYTE C4MapCreator::GetPix(int32_t x, int32_t y)
71 {
72 // Safety
73 if (!Inside<int32_t>(x,0,MapWdt-1) || !Inside<int32_t>(y,0,MapHgt-1)) return 0;
74 // Get pix
75 return MapBuf->GetPix(x,y);
76 }
77
Create(CSurface8 * sfcMap,C4SLandscape & rLScape,C4TextureMap & rTexMap,int32_t iPlayerNum)78 void C4MapCreator::Create(CSurface8 *sfcMap,
79 C4SLandscape &rLScape, C4TextureMap &rTexMap,
80 int32_t iPlayerNum)
81 {
82 double fullperiod= 20.0 * M_PI;
83 BYTE ccol;
84 int32_t cx,cy;
85
86 // Safeties
87 if (!sfcMap) return;
88 iPlayerNum=Clamp<int32_t>(iPlayerNum,1,C4S_MaxPlayer);
89
90 // Set creator variables
91 MapBuf = sfcMap;
92 MapWdt = MapBuf->Wdt; MapHgt = MapBuf->Hgt;
93
94 // Reset map (0 is sky)
95 MapBuf->ClearBox8Only(0,0,MapBuf->Wdt, MapBuf->Hgt);
96
97 // Surface
98 ccol=rTexMap.GetIndexMatTex(rLScape.Material.c_str());
99 auto amplitude= (float) rLScape.Amplitude.Evaluate();
100 auto phase= (float) rLScape.Phase.Evaluate();
101 auto period= (float) rLScape.Period.Evaluate();
102 if (rLScape.MapPlayerExtend) period *= std::min(iPlayerNum, C4S_MaxMapPlayerExtend);
103 float natural= (float) rLScape.Random.Evaluate();
104 int32_t level0= std::min(MapWdt,MapHgt)/2;
105 int32_t maxrange= level0*3/4;
106 double cy_curve,cy_natural; // -1.0 - +1.0 !
107
108 double rnd_cy,rnd_tend; // -1.0 - +1.0 !
109 rnd_cy= (double) (Random(2000+1)-1000)/1000.0;
110 rnd_tend= (double) (Random(200+1)-100)/20000.0;
111
112 for (cx=0; cx<MapWdt; cx++)
113 {
114
115 rnd_cy+=rnd_tend;
116 rnd_tend+= (double) (Random(100+1)-50)/10000;
117 if (rnd_tend>+0.05) rnd_tend=+0.05;
118 if (rnd_tend<-0.05) rnd_tend=-0.05;
119 if (rnd_cy<-0.5) rnd_tend+=0.01;
120 if (rnd_cy>+0.5) rnd_tend-=0.01;
121
122 cy_natural=rnd_cy*natural/100.0;
123 cy_curve=sin(fullperiod*period/100.0*(float)cx/(float)MapWdt
124 +2.0*M_PI*phase/100.0) * amplitude/100.0;
125
126 cy=level0+Clamp((int32_t)((float)maxrange*(cy_curve+cy_natural)),
127 -maxrange,+maxrange);
128
129
130 SetPix(cx,cy,ccol);
131 }
132
133 // Raise bottom to surface
134 for (cx=0; cx<MapWdt; cx++)
135 for (cy=MapHgt-1; (cy>=0) && !GetPix(cx,cy); cy--)
136 SetPix(cx,cy,ccol);
137 // Raise liquid level
138 Exclusive=0;
139 ccol=rTexMap.GetIndexMatTex(rLScape.Liquid.c_str());
140 int32_t wtr_level=rLScape.LiquidLevel.Evaluate();
141 for (cx=0; cx<MapWdt; cx++)
142 for (cy=MapHgt*(100-wtr_level)/100; cy<MapHgt; cy++)
143 SetPix(cx,cy,ccol);
144 Exclusive=-1;
145
146 // Layers
147 // Base material
148 Exclusive=rTexMap.GetIndexMatTex(rLScape.Material.c_str());
149
150 int32_t cnt,clayer,layer_num,sptx,spty;
151
152 // Process layer name list
153 for (clayer=0; clayer<C4MaxNameList; clayer++)
154 if (rLScape.Layers.Name[clayer][0])
155 {
156 // Draw layers
157 ccol=rTexMap.GetIndexMatTex(rLScape.Layers.Name[clayer]);
158 layer_num=rLScape.Layers.Count[clayer];
159 layer_num=layer_num*MapWdt*MapHgt/15000;
160 for (cnt=0; cnt<layer_num; cnt++)
161 {
162 // Place layer
163 sptx=Random(MapWdt);
164 for (spty=0; (spty<MapHgt) && (GetPix(sptx,spty)!=Exclusive); spty++) {}
165 spty+=5+Random((MapHgt-spty)-10);
166 DrawLayer(sptx,spty,Random(15),ccol);
167
168 }
169 }
170
171 Exclusive=-1;
172 }
173
ValidateTextureIndices(C4TextureMap & rTextureMap)174 void C4MapCreator::ValidateTextureIndices(C4TextureMap &rTextureMap)
175 {
176 int32_t iX,iY;
177 for (iY=0; iY<MapHgt; iY++)
178 for (iX=0; iX<MapWdt; iX++)
179 if (!rTextureMap.GetEntry(GetPix(iX,iY)))
180 SetPix(iX,iY,0);
181 }
182