freg  0.3
Free-Roaming Elementary Game
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
worldmap.cpp
Go to the documentation of this file.
1  /* freg, Free-Roaming Elementary Game with open and interactive world
2  * Copyright (C) 2012-2014 Alexander 'mmaulwurff' Kromm
3  * mmaulwurff@gmail.com
4  *
5  * This file is part of FREG.
6  *
7  * FREG is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * FREG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with FREG. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include <qmath.h>
21 #include <QSettings>
22 #include "worldmap.h"
23 #include "header.h"
24 
25 const float PI = 3.141592f;
26 
27 WorldMap::WorldMap(const QString world_name) :
28  mapSize(),
29  map(home_path + world_name + "/map.txt"),
30  spawnLongitude(),
31  spawnLatitude()
32 {
33  if ( map.open(QIODevice::ReadOnly | QIODevice::Text) ) {
34  mapSize = int(qSqrt(1+4*map.size())-1)/2;
35  } else {
36  GenerateMap(world_name, DEFAULT_MAP_SIZE, SHRED_WATER, 0);
37  mapSize = ( map.open(QIODevice::ReadOnly | QIODevice::Text) ) ?
38  DEFAULT_MAP_SIZE : 1;
39  }
41 }
42 
43 void WorldMap::MakeAndSaveSpawn(const QString world_name, const int size,
44  long * longitude, long * latitude)
45 {
46  QSettings map_info(home_path+world_name+"/map.ini", QSettings::IniFormat);
47  *longitude = map_info.value("spawn_longitude", GetSpawnCoordinate(size)).
48  toLongLong();
49  *latitude = map_info.value("spawn_latitude", GetSpawnCoordinate(size)).
50  toLongLong();
51  map_info.setValue("spawn_longitude", qlonglong(*longitude));
52  map_info.setValue("spawn_latitude" , qlonglong(*latitude ));
53 }
54 
56  size = qMax(size/4, 1);
57  return (qrand()%size) + size;
58 }
59 
61 long WorldMap::GetSpawnLatitude() const { return spawnLatitude; }
62 
63 char WorldMap::TypeOfShred(long longi, long lati) const {
64  --longi;
65  --lati;
66  //return '-'; // for testing purposes
67  if (
68  longi >= mapSize || longi < 0 ||
69  lati >= mapSize || lati < 0 )
70  {
71  return OUT_BORDER_SHRED;
72  } else if ( not map.seek((mapSize+1)*longi+lati) ) {
73  return DEFAULT_SHRED;
74  }
75  char c;
76  map.getChar(&c);
77  return c;
78 }
79 
80 float WorldMap::Deg(const int x, const int y, const int size) {
81  const float x_cent = x-size/2.f;
82  const float y_cent = y-size/2.f;
83  float fi;
84  if ( x_cent > 0 && y_cent >= 0 ) {
85  fi = atanf(y_cent/x_cent);
86  } else if ( x_cent>0 && y_cent<0 ) {
87  fi = atanf(y_cent/x_cent)+2*PI;
88  } else if ( x_cent<0 ) {
89  fi = atanf(y_cent/x_cent)+PI;
90  } else if ( qFuzzyCompare(x_cent, 0.f) && y_cent>0 ) {
91  fi = PI/2;
92  } else if ( qFuzzyCompare(x_cent, 0.f) && y_cent<0 ) {
93  fi = 3*PI/2;
94  } else {
95  fi = 0;
96  }
97  return 360*fi / 2 / PI;
98 }
99 
100 float WorldMap::R(const int x, const int y, const int size) {
101  return sqrtf( (x-size/2.f)*(x-size/2.f)+(y-size/2.f)*(y-size/2.f) );
102 }
103 
105  const int min_rad,
106  const int max_rad,
107  const char ch,
108  const int size,
109  char * const map)
110 {
111  Q_ASSERT(min_rad < max_rad);
112  float maxs[360] = { float(qrand()%(max_rad - min_rad) + min_rad) };
113  for (int x=1; x<360; ++x) {
114  maxs[x] = ( x > 345 ) ? // connect beginning and end of circle
115  maxs[x-1] + (maxs[0] - maxs[345]) / 15 :
116  qBound(float(min_rad),
117  maxs[x-1]+(qrand()%400-200)/200.f, float(max_rad));
118  }
119  for (int y=0; y<size; ++y)
120  for (int x=0; x<size; ++x) {
121  if ( R(x, y, size) < maxs[Round(Deg(x, y, size))] ) {
122  map[x*size+y] = ch;
123  }
124  }
125 }
126 
128  const QString world_name,
129  int size,
130  const char outer,
131  const int seed)
132 {
133  qsrand(seed);
134  size = qMax(10, size);
135 
136  char * const map = new char[size*size];
137  memset(map, outer, size*size);
138 
139  const float min_rad = size/3.0f;
140  const float max_rad = size/2.0f;
141  Circle(min_rad, max_rad, SHRED_WASTE, size, map);
142  Circle(min_rad/2, max_rad/2, SHRED_DEAD_FOREST, size, map);
143  Circle(min_rad/3, max_rad/3+1, SHRED_DEAD_HILL, size, map);
144  Circle(min_rad/4, max_rad/4+1, SHRED_MOUNTAIN, size, map);
145 
146  int lakes_number = (qrand() % size) + 5;
147  while ( lakes_number-- ) {
148  char type = SHRED_WATER;
149  switch ( qrand()%4 ) {
150  case 1: type = SHRED_ACID_LAKE; break;
151  case 2: type = SHRED_LAVA_LAKE; break;
152  case 3: type = SHRED_CRATER; break;
153  }
154  const float lake_size = qrand() % (size/10) + 1;
155  const int lake_start_x = qrand() % int(size-lake_size);
156  const int lake_start_y = qrand() % int(size-lake_size);
157  const int border = (lake_size-1)*(lake_size-1)/2/2;
158  for (int x=lake_start_x; x<lake_start_x+lake_size; ++x)
159  for (int y=lake_start_y; y<lake_start_y+lake_size; ++y) {
160  if ( (x-lake_start_x-lake_size/2)*(x-lake_start_x-lake_size/2)
161  + (y-lake_start_y-lake_size/2)*(y-lake_start_y-lake_size/2)
162  < border )
163  {
164  map[x*size+y] = type;
165  }
166  }
167  }
168 
169  long spawn_longitude, spawn_latitude;
170  MakeAndSaveSpawn(world_name, size, &spawn_longitude, &spawn_latitude);
171  PieceOfEden(spawn_latitude-1, spawn_longitude-1, map, size);
172 
173  FILE * const file =
174  fopen(qPrintable(home_path + world_name + "/map.txt"), "wb");
175  for (int y=0; y<size; ++y, fputc('\n', file))
176  for (int x=0; x<size; ++x) {
177  fputc(map[x*size+y], file);
178  }
179  delete [] map;
180  fclose(file);
181 }
182 
183 void WorldMap::PieceOfEden(const int x, const int y,
184  char * const map, const size_t size)
185 {
186  if ( (x+5)*size + y+5 > size*size) return;
187  char eden[][7] = {
188  "^~~~~^",
189  "~~%%~~",
190  "~%++%~",
191  "~%++%~",
192  "~~%%~~",
193  "^~~~~^"
194  };
195  for (int j=0; j<6; ++j)
196  for (int i=0; i<6; ++i) {
197  map[(x+j)*size + y+i] = eden[i][j];
198  }
199 }
const QString home_path
Definition: main.cpp:50
long spawnLongitude
Definition: worldmap.h:52
static float Deg(int x, int y, int size)
Definition: worldmap.cpp:80
static void MakeAndSaveSpawn(QString world_name, int size, long *longitude, long *latitude)
Definition: worldmap.cpp:43
static void PieceOfEden(int x, int y, char *map, size_t map_size)
Definition: worldmap.cpp:183
long spawnLatitude
Definition: worldmap.h:53
long GetSpawnLongitude() const
Definition: worldmap.cpp:60
int Round(const float x)
For positive numbers only.
Definition: header.h:217
static void Circle(int min_rad, int max_rad, char ch, int size, char *map)
Definition: worldmap.cpp:104
long GetSpawnLatitude() const
Definition: worldmap.cpp:61
const char OUT_BORDER_SHRED
Definition: header.h:83
static void GenerateMap(QString world_name, int size, char outer, int seed)
Definition: worldmap.cpp:127
const char DEFAULT_SHRED
Definition: header.h:82
static float R(int x, int y, int size)
Definition: worldmap.cpp:100
char TypeOfShred(long longi, long lati) const
Definition: worldmap.cpp:63
const float PI
Definition: worldmap.cpp:25
WorldMap(QString)
Definition: worldmap.cpp:27
QFile map
Definition: worldmap.h:51
long mapSize
Definition: worldmap.h:50
static int GetSpawnCoordinate(int size)
Definition: worldmap.cpp:55
const int DEFAULT_MAP_SIZE
Definition: header.h:81