mirror of
https://github.com/glest/glest-source.git
synced 2025-08-11 10:54:01 +02:00
- moved game map entity into a shared source file in shared lib, which is now shared by the main game and the map editor
This commit is contained in:
@@ -4,6 +4,26 @@ UseAutoconf ;
|
||||
|
||||
Package license.txt readme.txt ;
|
||||
|
||||
#ALWAYS getSVNVersion : @getSVNVersion_action ;
|
||||
|
||||
rule getSVNVersion {
|
||||
echo 'hi' ;
|
||||
}
|
||||
|
||||
actions getSVNVersion_action
|
||||
{
|
||||
# echo '"'`svnversion`'"' >sources/glest_game/facilities/svn_version_tmp.h
|
||||
echo '"'`svnversion`'"' ;
|
||||
echo 'hi' ;
|
||||
# if diff -N svn_version_tmp.hpp src/svn_version.hpp >/dev/null; then
|
||||
# rm svn_version_tmp.hpp
|
||||
# else
|
||||
# mv svn_version_tmp.hpp src/svn_version.hpp
|
||||
# fi
|
||||
}
|
||||
|
||||
ALWAYS getSVNVersion ;
|
||||
|
||||
#### Library ####
|
||||
|
||||
SubDir TOP shared_lib sources ;
|
||||
@@ -37,6 +57,7 @@ LIB_DIRS =
|
||||
sound
|
||||
sound/openal
|
||||
xml
|
||||
map
|
||||
glew
|
||||
lua
|
||||
streflop
|
||||
|
@@ -2629,214 +2629,4 @@ void MenuStateCustomGame::cleanupFactionTexture() {
|
||||
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
}
|
||||
|
||||
|
||||
// =======================================
|
||||
|
||||
MapPreview::MapPreview() {
|
||||
altFactor = 3;
|
||||
waterLevel = 4;
|
||||
//cells = NULL;
|
||||
cells.clear();
|
||||
startLocations = NULL;
|
||||
reset(128, 128, 10.f, 1);
|
||||
resetFactions(8);
|
||||
title = "";
|
||||
desc = "";
|
||||
author = "";
|
||||
refAlt = 10;
|
||||
}
|
||||
|
||||
MapPreview::~MapPreview() {
|
||||
delete [] startLocations;
|
||||
startLocations = NULL;
|
||||
|
||||
if(hasFileLoaded() == true) {
|
||||
//for (int i = 0; i < h; i++) {
|
||||
// delete [] cells[i];
|
||||
//}
|
||||
//delete [] cells;
|
||||
|
||||
fileLoaded = false;
|
||||
}
|
||||
//cells = NULL;
|
||||
cells.clear();
|
||||
}
|
||||
|
||||
|
||||
float MapPreview::getHeight(int x, int y) const {
|
||||
return cells[x][y].height;
|
||||
}
|
||||
|
||||
int MapPreview::getSurface(int x, int y) const {
|
||||
return cells[x][y].surface;
|
||||
}
|
||||
|
||||
int MapPreview::getObject(int x, int y) const {
|
||||
return cells[x][y].object;
|
||||
}
|
||||
|
||||
int MapPreview::getResource(int x, int y) const {
|
||||
return cells[x][y].resource;
|
||||
}
|
||||
|
||||
int MapPreview::getStartLocationX(int index) const {
|
||||
return startLocations[index].x;
|
||||
}
|
||||
|
||||
int MapPreview::getStartLocationY(int index) const {
|
||||
return startLocations[index].y;
|
||||
}
|
||||
|
||||
bool MapPreview::inside(int x, int y) {
|
||||
return (x >= 0 && x < w && y >= 0 && y < h);
|
||||
}
|
||||
|
||||
void MapPreview::reset(int w, int h, float alt, int surf) {
|
||||
if (w < 16 || h < 16) {
|
||||
throw runtime_error("Size of map must be at least 16x16");
|
||||
return;
|
||||
}
|
||||
|
||||
if (w > 1024 || h > 1024) {
|
||||
throw runtime_error("Size of map can be at most 1024x1024");
|
||||
return;
|
||||
}
|
||||
|
||||
if (alt < 0 || alt > 20) {
|
||||
throw runtime_error("Height must be in the range 0-20");
|
||||
return;
|
||||
}
|
||||
|
||||
if (surf < 1 || surf > 5) {
|
||||
throw runtime_error("Surface must be in the range 1-5");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (cells != NULL) {
|
||||
for (int i = 0; i < this->w; i++) {
|
||||
delete [] cells[i];
|
||||
}
|
||||
delete [] cells;
|
||||
}
|
||||
*/
|
||||
cells.clear();
|
||||
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->maxFactions = maxFactions;
|
||||
|
||||
cells.resize(w);
|
||||
|
||||
//cells = new Cell*[w];
|
||||
for (int i = 0; i < w; i++) {
|
||||
//cells[i] = new Cell[h];
|
||||
cells[i].resize(h);
|
||||
for (int j = 0; j < h; j++) {
|
||||
cells[i][j].height = alt;
|
||||
cells[i][j].object = 0;
|
||||
cells[i][j].resource = 0;
|
||||
cells[i][j].surface = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::resetFactions(int maxPlayers) {
|
||||
if (maxPlayers<1 || maxPlayers>8){
|
||||
throw runtime_error("Max Players must be in the range 1-8");
|
||||
}
|
||||
|
||||
if (startLocations != NULL) {
|
||||
delete [] startLocations;
|
||||
startLocations = NULL;
|
||||
}
|
||||
|
||||
maxFactions = maxPlayers;
|
||||
|
||||
startLocations = new StartLocation[maxFactions];
|
||||
for (int i = 0; i < maxFactions; i++) {
|
||||
startLocations[i].x = 0;
|
||||
startLocations[i].y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int MapPreview::getHeightFactor() const {
|
||||
return altFactor;
|
||||
}
|
||||
|
||||
int MapPreview::getWaterLevel() const {
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
void MapPreview::loadFromFile(const string &path) {
|
||||
altFactor = 3;
|
||||
waterLevel = 4;
|
||||
//cells = NULL;
|
||||
cells.clear();
|
||||
startLocations = NULL;
|
||||
reset(128, 128, 10.f, 1);
|
||||
resetFactions(8);
|
||||
title = "";
|
||||
desc = "";
|
||||
author = "";
|
||||
refAlt = 10;
|
||||
|
||||
FILE *f1 = fopen(path.c_str(), "rb");
|
||||
if (f1 != NULL) {
|
||||
|
||||
//read header
|
||||
MapFileHeaderPreview header;
|
||||
size_t bytes = fread(&header, sizeof(MapFileHeaderPreview), 1, f1);
|
||||
|
||||
altFactor = header.altFactor;
|
||||
waterLevel = header.waterLevel;
|
||||
title = header.title;
|
||||
author = header.author;
|
||||
desc = header.description;
|
||||
|
||||
//read start locations
|
||||
resetFactions(header.maxFactions);
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
bytes = fread(&startLocations[i].x, sizeof(int32), 1, f1);
|
||||
bytes = fread(&startLocations[i].y, sizeof(int32), 1, f1);
|
||||
}
|
||||
|
||||
//read Heights
|
||||
reset(header.width, header.height, 10, 1);
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
bytes = fread(&cells[i][j].height, sizeof(float), 1, f1);
|
||||
}
|
||||
}
|
||||
|
||||
//read surfaces
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
bytes = fread(&cells[i][j].surface, sizeof(int8), 1, f1);
|
||||
}
|
||||
}
|
||||
|
||||
//read objects
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
int8 obj;
|
||||
bytes = fread(&obj, sizeof(int8), 1, f1);
|
||||
if (obj <= 10) {
|
||||
cells[i][j].object = obj;
|
||||
} else {
|
||||
cells[i][j].resource = obj - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f1);
|
||||
|
||||
fileLoaded = true;
|
||||
} else {
|
||||
throw runtime_error("error opening map file: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
}}//end namespace
|
||||
|
@@ -15,90 +15,12 @@
|
||||
#include "main_menu.h"
|
||||
#include "chat_manager.h"
|
||||
#include "simple_threads.h"
|
||||
#include "game.h"
|
||||
#include "map_preview.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
namespace Glest{ namespace Game{
|
||||
|
||||
struct MapFileHeaderPreview {
|
||||
int32 version;
|
||||
int32 maxFactions;
|
||||
int32 width;
|
||||
int32 height;
|
||||
int32 altFactor;
|
||||
int32 waterLevel;
|
||||
int8 title[128];
|
||||
int8 author[128];
|
||||
int8 description[256];
|
||||
};
|
||||
|
||||
// ===============================================
|
||||
// class Map
|
||||
// ===============================================
|
||||
|
||||
class MapPreview {
|
||||
public:
|
||||
static const int maxHeight = 20;
|
||||
static const int minHeight = 0;
|
||||
|
||||
private:
|
||||
struct Cell {
|
||||
int surface;
|
||||
int object;
|
||||
int resource;
|
||||
float height;
|
||||
};
|
||||
|
||||
struct StartLocation {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
RandomGen random;
|
||||
string title;
|
||||
string author;
|
||||
string desc;
|
||||
string recScn;
|
||||
int type;
|
||||
int h;
|
||||
int w;
|
||||
int altFactor;
|
||||
int waterLevel;
|
||||
//Cell **cells;
|
||||
std::vector<std::vector<Cell> > cells;
|
||||
int maxFactions;
|
||||
StartLocation *startLocations;
|
||||
int refAlt;
|
||||
bool fileLoaded;
|
||||
|
||||
public:
|
||||
MapPreview();
|
||||
~MapPreview();
|
||||
float getHeight(int x, int y) const;
|
||||
int getSurface(int x, int y) const;
|
||||
int getObject(int x, int y) const;
|
||||
int getResource(int x, int y) const;
|
||||
int getStartLocationX(int index) const;
|
||||
int getStartLocationY(int index) const;
|
||||
int getHeightFactor() const;
|
||||
int getWaterLevel() const;
|
||||
bool inside(int x, int y);
|
||||
|
||||
int getH() const {return h;}
|
||||
int getW() const {return w;}
|
||||
int getMaxFactions() const {return maxFactions;}
|
||||
string getTitle() const {return title;}
|
||||
string getDesc() const {return desc;}
|
||||
string getAuthor() const {return author;}
|
||||
|
||||
void reset(int w, int h, float alt, int surf);
|
||||
void resetFactions(int maxFactions);
|
||||
|
||||
void loadFromFile(const string &path);
|
||||
bool hasFileLoaded() const { return fileLoaded; }
|
||||
};
|
||||
|
||||
using namespace Shared::Map;
|
||||
|
||||
namespace Glest { namespace Game {
|
||||
|
||||
// ===============================
|
||||
// class MenuStateCustomGame
|
||||
|
@@ -115,7 +115,7 @@ void UndoPoint::revert() {
|
||||
//std::cout << "attempting to restore the surface array" << std::endl;
|
||||
for (int i = 0; i < w; i++) {
|
||||
for (int j = 0; j < h; j++) {
|
||||
Program::map->setSurface(i, j, surface[j * w + i]);
|
||||
Program::map->setSurface(i, j, static_cast<MapSurfaceType>(surface[j * w + i]));
|
||||
}
|
||||
}
|
||||
if (change != ctAll) break;
|
||||
@@ -141,13 +141,13 @@ void UndoPoint::revert() {
|
||||
// class Program
|
||||
// ===============================================
|
||||
|
||||
Map *Program::map = NULL;
|
||||
MapPreview *Program::map = NULL;
|
||||
|
||||
Program::Program(int w, int h) {
|
||||
cellSize = 6;
|
||||
ofsetX = 0;
|
||||
ofsetY = 0;
|
||||
map = new Map();
|
||||
map = new MapPreview();
|
||||
renderer.init(w, h);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ void Program::pirateChangeMapHeight(int x, int y, int Height, int radius) {
|
||||
}
|
||||
|
||||
void Program::changeMapSurface(int x, int y, int surface, int radius) {
|
||||
map->changeSurface((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, surface, radius);
|
||||
map->changeSurface((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, static_cast<MapSurfaceType>(surface), radius);
|
||||
}
|
||||
|
||||
void Program::changeMapObject(int x, int y, int object, int radius) {
|
||||
@@ -261,17 +261,17 @@ void Program::randomizeMap() {
|
||||
}
|
||||
|
||||
void Program::switchMapSurfaces(int surf1, int surf2) {
|
||||
map->switchSurfaces(surf1, surf2);
|
||||
map->switchSurfaces(static_cast<MapSurfaceType>(surf1), static_cast<MapSurfaceType>(surf2));
|
||||
}
|
||||
|
||||
void Program::reset(int w, int h, int alt, int surf) {
|
||||
undoStack.clear();
|
||||
redoStack.clear();
|
||||
map->reset(w, h, (float) alt, surf);
|
||||
map->reset(w, h, (float) alt, static_cast<MapSurfaceType>(surf));
|
||||
}
|
||||
|
||||
void Program::resize(int w, int h, int alt, int surf) {
|
||||
map->resize(w, h, (float) alt, surf);
|
||||
map->resize(w, h, (float) alt, static_cast<MapSurfaceType>(surf));
|
||||
}
|
||||
|
||||
void Program::resetFactions(int maxFactions) {
|
||||
|
150
source/glest_map_editor/program.h
Normal file
150
source/glest_map_editor/program.h
Normal file
@@ -0,0 +1,150 @@
|
||||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _MAPEDITOR_PROGRAM_H_
|
||||
#define _MAPEDITOR_PROGRAM_H_
|
||||
|
||||
//#include "map.h"
|
||||
#include "map_preview.h"
|
||||
#include "renderer.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
using std::stack;
|
||||
using namespace Shared::Map;
|
||||
|
||||
namespace MapEditor {
|
||||
|
||||
class MainWindow;
|
||||
|
||||
enum ChangeType {
|
||||
ctNone = -1,
|
||||
ctHeight,
|
||||
ctSurface,
|
||||
ctObject,
|
||||
ctResource,
|
||||
ctLocation,
|
||||
ctGradient,
|
||||
ctAll
|
||||
};
|
||||
|
||||
// =============================================
|
||||
// class Undo Point
|
||||
// A linked list class that is more of an extension / modification on
|
||||
// the already existing Cell struct in map.h
|
||||
// Provides the ability to only specify a certain property of the map to change
|
||||
// =============================================
|
||||
class UndoPoint {
|
||||
private:
|
||||
// Only keep a certain number of undo points in memory otherwise
|
||||
// Big projects could hog a lot of memory
|
||||
const static int MAX_UNDO_LIST_SIZE = 100; // TODO get feedback on this value
|
||||
static int undoCount;
|
||||
|
||||
ChangeType change;
|
||||
|
||||
// Pointers to arrays of each property
|
||||
int *surface;
|
||||
int *object;
|
||||
int *resource;
|
||||
float *height;
|
||||
|
||||
// Map width and height
|
||||
static int w;
|
||||
static int h;
|
||||
|
||||
public:
|
||||
UndoPoint();
|
||||
~UndoPoint();
|
||||
void init(ChangeType change);
|
||||
void revert();
|
||||
|
||||
inline ChangeType getChange() const { return change; }
|
||||
};
|
||||
|
||||
class ChangeStack : public std::stack<UndoPoint> {
|
||||
public:
|
||||
static const int maxSize = 100;
|
||||
|
||||
void clear() { c.clear(); }
|
||||
|
||||
void push(UndoPoint p) {
|
||||
if (c.size() >= maxSize) {
|
||||
c.pop_front();
|
||||
}
|
||||
stack<UndoPoint>::push(p);
|
||||
}
|
||||
};
|
||||
|
||||
// ===============================================
|
||||
// class Program
|
||||
// ===============================================
|
||||
|
||||
class Program {
|
||||
private:
|
||||
Renderer renderer;
|
||||
int ofsetX, ofsetY;
|
||||
int cellSize;
|
||||
//static Map *map;
|
||||
static MapPreview *map;
|
||||
friend class UndoPoint;
|
||||
|
||||
ChangeStack undoStack, redoStack;
|
||||
|
||||
public:
|
||||
Program(int w, int h);
|
||||
~Program();
|
||||
|
||||
//map cell change
|
||||
void glestChangeMapHeight(int x, int y, int Height, int radius);
|
||||
void pirateChangeMapHeight(int x, int y, int Height, int radius);
|
||||
void changeMapSurface(int x, int y, int surface, int radius);
|
||||
void changeMapObject(int x, int y, int object, int radius);
|
||||
void changeMapResource(int x, int y, int resource, int radius);
|
||||
void changeStartLocation(int x, int y, int player);
|
||||
|
||||
void setUndoPoint(ChangeType change);
|
||||
bool undo();
|
||||
bool redo();
|
||||
|
||||
//map ops
|
||||
void reset(int w, int h, int alt, int surf);
|
||||
void resize(int w, int h, int alt, int surf);
|
||||
void resetFactions(int maxFactions);
|
||||
void setRefAlt(int x, int y);
|
||||
void flipX();
|
||||
void flipY();
|
||||
void randomizeMapHeights();
|
||||
void randomizeMap();
|
||||
void switchMapSurfaces(int surf1, int surf2);
|
||||
void loadMap(const string &path);
|
||||
void saveMap(const string &path);
|
||||
|
||||
//map misc
|
||||
bool setMapTitle(const string &title);
|
||||
bool setMapDesc(const string &desc);
|
||||
bool setMapAuthor(const string &author);
|
||||
void setMapAdvanced(int altFactor, int waterLevel);
|
||||
|
||||
//misc
|
||||
void renderMap(int w, int h);
|
||||
void setOfset(int x, int y);
|
||||
void incCellSize(int i);
|
||||
void resetOfset();
|
||||
|
||||
int getObject(int x, int y);
|
||||
int getResource(int x, int y);
|
||||
static const MapPreview *getMap() {return map;}
|
||||
};
|
||||
|
||||
}// end namespace
|
||||
|
||||
#endif
|
@@ -37,7 +37,7 @@ void Renderer::init(int clientW, int clientH) {
|
||||
assertGl();
|
||||
}
|
||||
|
||||
void Renderer::renderMap(Map *map, int x, int y, int clientW, int clientH, int cellSize) {
|
||||
void Renderer::renderMap(MapPreview *map, int x, int y, int clientW, int clientH, int cellSize) {
|
||||
float alt;
|
||||
float showWater;
|
||||
|
||||
|
33
source/glest_map_editor/renderer.h
Normal file
33
source/glest_map_editor/renderer.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martio Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _MAPEDITOR_RENDERER_H_
|
||||
#define _MAPEDITOR_RENDERER_H_
|
||||
|
||||
#include "map_preview.h"
|
||||
|
||||
using namespace Shared::Map;
|
||||
|
||||
namespace MapEditor {
|
||||
|
||||
// ===============================================
|
||||
// class Renderer
|
||||
// ===============================================
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
void init(int clientW, int clientH);
|
||||
void renderMap(MapPreview *map, int x, int y, int clientW, int clientH, int cellSize);
|
||||
};
|
||||
|
||||
}// end namespace
|
||||
|
||||
#endif
|
173
source/shared_lib/include/map/map_preview.h
Normal file
173
source/shared_lib/include/map/map_preview.h
Normal file
@@ -0,0 +1,173 @@
|
||||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martio Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
#ifndef _MAPPREVIEW_MAP_H_
|
||||
#define _MAPPREVIEW_MAP_H_
|
||||
|
||||
#include "util.h"
|
||||
#include "types.h"
|
||||
#include "randomgen.h"
|
||||
#include <vector>
|
||||
|
||||
using Shared::Platform::int8;
|
||||
using Shared::Platform::int32;
|
||||
using Shared::Platform::float32;
|
||||
using Shared::Util::RandomGen;
|
||||
|
||||
namespace Shared { namespace Map {
|
||||
|
||||
enum MapSurfaceType {
|
||||
st_Grass = 1,
|
||||
st_Secondary_Grass,
|
||||
st_Road,
|
||||
st_Stone,
|
||||
st_Ground
|
||||
|
||||
};
|
||||
|
||||
static const int MAX_TITLE_LENGTH = 128;
|
||||
static const int MAX_AUTHOR_LENGTH = 128;
|
||||
static const int MAX_DESCRIPTION_LENGTH = 256;
|
||||
|
||||
static const int MIN_MAP_CELL_DIMENSION = 16;
|
||||
static const int MAX_MAP_CELL_DIMENSION = 1024;
|
||||
|
||||
static const int MIN_MAP_CELL_HEIGHT = 0;
|
||||
static const int MAX_MAP_CELL_HEIGHT = 20;
|
||||
static const int DEFAULT_MAP_CELL_HEIGHT = 10;
|
||||
|
||||
static const int MIN_MAP_FACTIONCOUNT = 1;
|
||||
static const int MAX_MAP_FACTIONCOUNT = 8;
|
||||
static const int DEFAULT_MAP_FACTIONCOUNT = 8;
|
||||
|
||||
static const int DEFAULT_MAP_CELL_WIDTH = 128;
|
||||
static const int DEFAULT_MAP_CELL_LENGTH = 128;
|
||||
|
||||
static const MapSurfaceType DEFAULT_MAP_CELL_SURFACE_TYPE = st_Grass;
|
||||
|
||||
static const int DEFAULT_MAP_CELL_HEIGHT_FACTOR = 3;
|
||||
static const int DEFAULT_MAP_WATER_DEPTH = 4;
|
||||
|
||||
struct MapFileHeader {
|
||||
int32 version;
|
||||
int32 maxFactions;
|
||||
int32 width;
|
||||
int32 height;
|
||||
int32 altFactor;
|
||||
int32 waterLevel;
|
||||
int8 title[MAX_TITLE_LENGTH];
|
||||
int8 author[MAX_AUTHOR_LENGTH];
|
||||
int8 description[MAX_DESCRIPTION_LENGTH];
|
||||
};
|
||||
|
||||
// ===============================================
|
||||
// class Map
|
||||
// ===============================================
|
||||
|
||||
class MapPreview {
|
||||
public:
|
||||
static const int maxHeight = 20;
|
||||
static const int minHeight = 0;
|
||||
|
||||
private:
|
||||
struct Cell {
|
||||
int surface;
|
||||
int object;
|
||||
int resource;
|
||||
float height;
|
||||
};
|
||||
|
||||
struct StartLocation {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
RandomGen random;
|
||||
string title;
|
||||
string author;
|
||||
string desc;
|
||||
string recScn;
|
||||
int type;
|
||||
int h;
|
||||
int w;
|
||||
int altFactor;
|
||||
int waterLevel;
|
||||
//Cell **cells;
|
||||
std::vector<std::vector<Cell> > cells;
|
||||
|
||||
int maxFactions;
|
||||
//StartLocation *startLocations;
|
||||
std::vector<StartLocation> startLocations;
|
||||
int refAlt;
|
||||
|
||||
bool fileLoaded;
|
||||
|
||||
public:
|
||||
MapPreview();
|
||||
~MapPreview();
|
||||
float getHeight(int x, int y) const;
|
||||
MapSurfaceType getSurface(int x, int y) const;
|
||||
int getObject(int x, int y) const;
|
||||
int getResource(int x, int y) const;
|
||||
int getStartLocationX(int index) const;
|
||||
int getStartLocationY(int index) const;
|
||||
int getHeightFactor() const;
|
||||
int getWaterLevel() const;
|
||||
bool inside(int x, int y);
|
||||
|
||||
void setRefAlt(int x, int y);
|
||||
void setAdvanced(int altFactor, int waterLevel);
|
||||
void setTitle(const string &title);
|
||||
void setDesc(const string &desc);
|
||||
void setAuthor(const string &author);
|
||||
|
||||
int getH() const {return h;}
|
||||
int getW() const {return w;}
|
||||
int getMaxFactions() const {return maxFactions;}
|
||||
string getTitle() const {return title;}
|
||||
string getDesc() const {return desc;}
|
||||
string getAuthor() const {return author;}
|
||||
|
||||
void glestChangeHeight(int x, int y, int height, int radius);
|
||||
void pirateChangeHeight(int x, int y, int height, int radius);
|
||||
void changeSurface(int x, int y, MapSurfaceType surface, int radius);
|
||||
void changeObject(int x, int y, int object, int radius);
|
||||
void changeResource(int x, int y, int resource, int radius);
|
||||
void changeStartLocation(int x, int y, int player);
|
||||
|
||||
void setHeight(int x, int y, float height);
|
||||
void setSurface(int x, int y, MapSurfaceType surface);
|
||||
void setObject(int x, int y, int object);
|
||||
void setResource(int x, int y, int resource);
|
||||
|
||||
void flipX();
|
||||
void flipY();
|
||||
void reset(int w, int h, float alt, MapSurfaceType surf);
|
||||
void resize(int w, int h, float alt, MapSurfaceType surf);
|
||||
void resetFactions(int maxFactions);
|
||||
void randomizeHeights();
|
||||
void randomize();
|
||||
void switchSurfaces(MapSurfaceType surf1, MapSurfaceType surf2);
|
||||
|
||||
void loadFromFile(const string &path);
|
||||
void saveToFile(const string &path);
|
||||
|
||||
void resetHeights(int height);
|
||||
void sinRandomize(int strenght);
|
||||
void decalRandomize(int strenght);
|
||||
void applyNewHeight(float newHeight, int x, int y, int strenght);
|
||||
|
||||
bool hasFileLoaded() const {return fileLoaded;}
|
||||
};
|
||||
|
||||
}}// end namespace
|
||||
|
||||
#endif
|
820
source/shared_lib/sources/map/map_preview.cpp
Normal file
820
source/shared_lib/sources/map/map_preview.cpp
Normal file
@@ -0,0 +1,820 @@
|
||||
// ==============================================================
|
||||
// This file is part of Glest (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
// by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version
|
||||
// ==============================================================
|
||||
|
||||
|
||||
#include "map_preview.h"
|
||||
|
||||
//#include <cmath>
|
||||
#include "math_wrapper.h"
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace Shared { namespace Map {
|
||||
|
||||
// ===============================================
|
||||
// class MapPreview
|
||||
// ===============================================
|
||||
|
||||
// ================== PUBLIC =====================
|
||||
|
||||
MapPreview::MapPreview() {
|
||||
fileLoaded = false;
|
||||
altFactor = DEFAULT_MAP_CELL_HEIGHT_FACTOR;
|
||||
waterLevel = DEFAULT_MAP_WATER_DEPTH;
|
||||
//cells = NULL;
|
||||
cells.clear();
|
||||
//startLocations = NULL;
|
||||
startLocations.clear();
|
||||
reset(DEFAULT_MAP_CELL_WIDTH, DEFAULT_MAP_CELL_LENGTH, DEFAULT_MAP_CELL_HEIGHT, DEFAULT_MAP_CELL_SURFACE_TYPE);
|
||||
resetFactions(DEFAULT_MAP_FACTIONCOUNT);
|
||||
title = "";
|
||||
desc = "";
|
||||
author = "";
|
||||
refAlt = DEFAULT_MAP_CELL_HEIGHT;
|
||||
}
|
||||
|
||||
MapPreview::~MapPreview() {
|
||||
//delete [] startLocations;
|
||||
//startLocations = NULL;
|
||||
startLocations.clear();
|
||||
|
||||
//for (int i = 0; i < h; i++) {
|
||||
// delete [] cells[i];
|
||||
//}
|
||||
//delete [] cells;
|
||||
//cells = NULL;
|
||||
cells.clear();
|
||||
}
|
||||
|
||||
float MapPreview::getHeight(int x, int y) const {
|
||||
return cells[x][y].height;
|
||||
}
|
||||
|
||||
MapSurfaceType MapPreview::getSurface(int x, int y) const {
|
||||
return static_cast<MapSurfaceType>(cells[x][y].surface);
|
||||
}
|
||||
|
||||
int MapPreview::getObject(int x, int y) const {
|
||||
return cells[x][y].object;
|
||||
}
|
||||
|
||||
int MapPreview::getResource(int x, int y) const {
|
||||
return cells[x][y].resource;
|
||||
}
|
||||
|
||||
int MapPreview::getStartLocationX(int index) const {
|
||||
return startLocations[index].x;
|
||||
}
|
||||
|
||||
int MapPreview::getStartLocationY(int index) const {
|
||||
return startLocations[index].y;
|
||||
}
|
||||
|
||||
static int get_dist(int delta_x, int delta_y) {
|
||||
float dx = delta_x;
|
||||
float dy = delta_y;
|
||||
|
||||
return static_cast<int>(sqrtf(dx * dx + dy * dy));
|
||||
}
|
||||
|
||||
void MapPreview::glestChangeHeight(int x, int y, int height, int radius) {
|
||||
|
||||
for (int i = x - radius + 1; i < x + radius; i++) {
|
||||
for (int j = y - radius + 1; j < y + radius; j++) {
|
||||
if (inside(i, j)) {
|
||||
int dist = get_dist(i - x, j - y);
|
||||
if (radius > dist) {
|
||||
int oldAlt = static_cast<int>(cells[i][j].height);
|
||||
int altInc = height * (radius - dist - 1) / radius;
|
||||
if (height > 0) {
|
||||
altInc++;
|
||||
}
|
||||
if (height < 0) {
|
||||
altInc--;
|
||||
}
|
||||
int newAlt = refAlt + altInc;
|
||||
if ((height > 0 && newAlt > oldAlt) || (height < 0 && newAlt < oldAlt) || height == 0) {
|
||||
if (newAlt >= 0 && newAlt <= 20) {
|
||||
cells[i][j].height = static_cast<float>(newAlt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MapPreview::pirateChangeHeight(int x, int y, int height, int radius) {
|
||||
// Make sure not to try and blanket change the height over the bounds
|
||||
// Find our goal height for the center of the brush
|
||||
|
||||
int overBounds = refAlt + height;
|
||||
int goalAlt = overBounds;
|
||||
if (overBounds > 20) {
|
||||
goalAlt = 20;
|
||||
}
|
||||
else if (overBounds < 0) {
|
||||
goalAlt = 0;
|
||||
}
|
||||
|
||||
// If the radius is 1 don't bother doing any calculations
|
||||
if (radius == 1) {
|
||||
if(inside(x, y)){
|
||||
cells[x][y].height = goalAlt;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Old height reference points and compute gradients
|
||||
// from the heights of the sides and corners of the brush to the center goal height
|
||||
float gradient[3][3]; // [i][j]
|
||||
int indexI = 0;
|
||||
for (int i = x - radius; i <= x + radius; i += radius) {
|
||||
int indexJ = 0;
|
||||
for (int j = y - radius; j <= y + radius; j += radius) {
|
||||
// round off the corners
|
||||
int ti, tj;
|
||||
if (abs(i - x) == abs(j - y)) {
|
||||
ti = (i - x) * 0.707 + x + 0.5;
|
||||
tj = (j - y) * 0.707 + y + 0.5;
|
||||
} else {
|
||||
ti = i;
|
||||
tj = j;
|
||||
}
|
||||
if (inside(ti, tj)) {
|
||||
gradient[indexI][indexJ] = (cells[ti][tj].height - goalAlt) / radius;
|
||||
//} else if (dist == 0) {
|
||||
//gradient[indexI][indexJ] = 0;
|
||||
}
|
||||
else {
|
||||
// assume outside the map bounds is height 10
|
||||
gradient[indexI][indexJ] = (10.0 - goalAlt) / radius;
|
||||
}
|
||||
//std::cout << "gradient[" << indexI << "][" << indexJ << "] = " << gradient[indexI][indexJ] << std::endl;
|
||||
//std::cout << "derived from height " << cells[ti][tj].height << " at " << ti << " " << tj << std::endl;
|
||||
indexJ++;
|
||||
}
|
||||
indexI++;
|
||||
}
|
||||
//std::cout << endl;
|
||||
|
||||
// A brush with radius n cells should have a true radius of n-1 distance
|
||||
radius -= 1;
|
||||
for (int i = x - radius; i <= x + radius; i++) {
|
||||
for (int j = y - radius; j <= y + radius; j++) {
|
||||
int dist = get_dist(i - x, j - y);
|
||||
if (inside(i, j) && dist < radius) {
|
||||
// Normalize di and dj and round them to an int so they can be used as indicies
|
||||
float normIf = (float(i - x)/ radius);
|
||||
float normJf = (float(j - y)/ radius);
|
||||
int normI[2];
|
||||
int normJ[2];
|
||||
float usedGrad;
|
||||
|
||||
// Build a search box to find the gradients we are concerned about
|
||||
// Find the nearest i indices
|
||||
if (normIf < -0.33) {
|
||||
normI[0] = 0;
|
||||
if (normIf == 0) {
|
||||
normI[1] = 0;
|
||||
}
|
||||
else {
|
||||
normI[1] = 1;
|
||||
}
|
||||
}
|
||||
else if (normIf < 0.33) {
|
||||
normI[0] = 1;
|
||||
if (normIf > 0) {
|
||||
normI[1] = 2;
|
||||
}
|
||||
else if (normIf < 0) {
|
||||
normI[1] = 0;
|
||||
}
|
||||
else /*(normIf == 0)*/ {
|
||||
normI[1] = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
normI[0] = 2;
|
||||
if (normIf == 1) {
|
||||
normI[1] = 2;
|
||||
}
|
||||
else {
|
||||
normI[1] = 1;
|
||||
}
|
||||
}
|
||||
// find nearest j indices
|
||||
if (normJf < -0.33) {
|
||||
normJ[0] = 0;
|
||||
if (normJf == 0) {
|
||||
normJ[1] = 0;
|
||||
}
|
||||
else {
|
||||
normJ[1] = 1;
|
||||
}
|
||||
}
|
||||
else if (normJf < 0.33) {
|
||||
normJ[0] = 1;
|
||||
if (normJf > 0) {
|
||||
normJ[1] = 2;
|
||||
}
|
||||
else if (normJf < 0) {
|
||||
normJ[1] = 0;
|
||||
}
|
||||
else /*(normJf == 0)*/ {
|
||||
normJ[1] = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
normJ[0] = 2;
|
||||
if (normJf == 1) {
|
||||
normJ[1] = 2;
|
||||
}
|
||||
else {
|
||||
normJ[1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which gradients to use and take a weighted average
|
||||
if (abs(normIf) > abs(normJf)) {
|
||||
usedGrad =
|
||||
gradient[normI[0]] [normJ[0]] * abs(normJf) +
|
||||
gradient[normI[0]] [normJ[1]] * (1 - abs(normJf));
|
||||
}
|
||||
else if (abs(normIf) < abs(normJf)) {
|
||||
usedGrad =
|
||||
gradient[normI[0]] [normJ[0]] * abs(normIf) +
|
||||
gradient[normI[1]] [normJ[0]] * (1 - abs(normIf));
|
||||
}
|
||||
else {
|
||||
usedGrad =
|
||||
gradient[normI[0]] [normJ[0]];
|
||||
}
|
||||
|
||||
|
||||
float newAlt = usedGrad * dist + goalAlt;
|
||||
|
||||
// if the change in height and what is supposed to be the change in height
|
||||
// are the same sign then we can change the height
|
||||
if ( ((newAlt - cells[i][j].height) > 0 && height > 0) ||
|
||||
((newAlt - cells[i][j].height) < 0 && height < 0) ||
|
||||
height == 0) {
|
||||
cells[i][j].height = newAlt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::setHeight(int x, int y, float height) {
|
||||
cells[x][y].height = height;
|
||||
}
|
||||
|
||||
void MapPreview::setRefAlt(int x, int y) {
|
||||
if (inside(x, y)) {
|
||||
refAlt = static_cast<int>(cells[x][y].height);
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::flipX() {
|
||||
//Cell **oldCells = cells;
|
||||
std::vector<std::vector<Cell> > oldCells = cells;
|
||||
|
||||
//cells = new Cell*[w];
|
||||
cells.clear();
|
||||
cells.resize(w);
|
||||
for (int i = 0; i < w; i++) {
|
||||
//cells[i] = new Cell[h];
|
||||
cells[i].resize(h);
|
||||
for (int j = 0; j < h; j++) {
|
||||
cells[i][j].height = oldCells[w-i-1][j].height;
|
||||
cells[i][j].object = oldCells[w-i-1][j].object;
|
||||
cells[i][j].resource = oldCells[w-i-1][j].resource;
|
||||
cells[i][j].surface = oldCells[w-i-1][j].surface;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
startLocations[i].x = w - startLocations[i].x - 1;
|
||||
}
|
||||
|
||||
//for (int i = 0; i < w; i++) {
|
||||
// delete [] oldCells[i];
|
||||
//}
|
||||
//delete [] oldCells;
|
||||
}
|
||||
|
||||
void MapPreview::flipY() {
|
||||
//Cell **oldCells = cells;
|
||||
std::vector<std::vector<Cell> > oldCells = cells;
|
||||
|
||||
//cells = new Cell*[w];
|
||||
cells.clear();
|
||||
cells.resize(w);
|
||||
|
||||
for (int i = 0; i < w; i++) {
|
||||
//cells[i] = new Cell[h];
|
||||
cells[i].resize(h);
|
||||
for (int j = 0; j < h; j++) {
|
||||
cells[i][j].height = oldCells[i][h-j-1].height;
|
||||
cells[i][j].object = oldCells[i][h-j-1].object;
|
||||
cells[i][j].resource = oldCells[i][h-j-1].resource;
|
||||
cells[i][j].surface = oldCells[i][h-j-1].surface;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
startLocations[i].y = h - startLocations[i].y - 1;
|
||||
}
|
||||
|
||||
//for (int i = 0; i < w; i++) {
|
||||
// delete [] oldCells[i];
|
||||
//}
|
||||
//delete [] oldCells;
|
||||
}
|
||||
|
||||
void MapPreview::changeSurface(int x, int y, MapSurfaceType surface, int radius) {
|
||||
int i, j;
|
||||
int dist;
|
||||
|
||||
for (i = x - radius + 1; i < x + radius; i++) {
|
||||
for (j = y - radius + 1; j < y + radius; j++) {
|
||||
if (inside(i, j)) {
|
||||
dist = get_dist(i - x, j - y);
|
||||
if (radius >= dist) {
|
||||
cells[i][j].surface = surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::setSurface(int x, int y, MapSurfaceType surface) {
|
||||
cells[x][y].surface = surface;
|
||||
}
|
||||
|
||||
void MapPreview::changeObject(int x, int y, int object, int radius) {
|
||||
int i, j;
|
||||
int dist;
|
||||
|
||||
for (i = x - radius + 1; i < x + radius; i++) {
|
||||
for (j = y - radius + 1; j < y + radius; j++) {
|
||||
if (inside(i, j)) {
|
||||
dist = get_dist(i - x, j - y);
|
||||
if (radius >= dist) {
|
||||
cells[i][j].object = object;
|
||||
cells[i][j].resource = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::setObject(int x, int y, int object) {
|
||||
cells[x][y].object = object;
|
||||
if (object != 0) cells[x][y].resource = 0;
|
||||
}
|
||||
|
||||
void MapPreview::changeResource(int x, int y, int resource, int radius) {
|
||||
int i, j;
|
||||
int dist;
|
||||
|
||||
for (i = x - radius + 1; i < x + radius; i++) {
|
||||
for (j = y - radius + 1; j < y + radius; j++) {
|
||||
if (inside(i, j)) {
|
||||
dist = get_dist(i - x, j - y);
|
||||
if (radius >= dist) {
|
||||
cells[i][j].resource = resource;
|
||||
cells[i][j].object = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::setResource(int x, int y, int resource) {
|
||||
cells[x][y].resource = resource;
|
||||
if (resource != 0) cells[x][y].object = 0;
|
||||
}
|
||||
|
||||
void MapPreview::changeStartLocation(int x, int y, int faction) {
|
||||
if ((faction - 1) < maxFactions && inside(x, y)) {
|
||||
startLocations[faction].x = x;
|
||||
startLocations[faction].y = y;
|
||||
}
|
||||
}
|
||||
|
||||
bool MapPreview::inside(int x, int y) {
|
||||
return (x >= 0 && x < w && y >= 0 && y < h);
|
||||
}
|
||||
|
||||
void MapPreview::reset(int w, int h, float alt, MapSurfaceType surf) {
|
||||
if (w < MIN_MAP_CELL_DIMENSION || h < MIN_MAP_CELL_DIMENSION) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Size of map must be at least %dx%d",MIN_MAP_CELL_DIMENSION,MIN_MAP_CELL_DIMENSION);
|
||||
throw runtime_error(szBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (w > MAX_MAP_CELL_DIMENSION || h > MAX_MAP_CELL_DIMENSION) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Size of map can be at most %dx%d",MAX_MAP_CELL_DIMENSION,MAX_MAP_CELL_DIMENSION);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
if (alt < MIN_MAP_CELL_HEIGHT || alt > MAX_MAP_CELL_HEIGHT) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Height must be in the range %d-%d",MIN_MAP_CELL_HEIGHT,MAX_MAP_CELL_HEIGHT);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
if (surf < st_Grass || surf > st_Ground) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Surface must be in the range %d-%d",st_Grass,st_Ground);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
//if (cells != NULL) {
|
||||
// for (int i = 0; i < this->w; i++) {
|
||||
// delete [] cells[i];
|
||||
// }
|
||||
// delete [] cells;
|
||||
//}
|
||||
cells.clear();
|
||||
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->maxFactions = maxFactions;
|
||||
|
||||
//cells = new Cell*[w];
|
||||
cells.resize(w);
|
||||
for (int i = 0; i < w; i++) {
|
||||
//cells[i] = new Cell[h];
|
||||
cells[i].resize(h);
|
||||
for (int j = 0; j < h; j++) {
|
||||
cells[i][j].height = alt;
|
||||
cells[i][j].object = 0;
|
||||
cells[i][j].resource = 0;
|
||||
cells[i][j].surface = surf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::resize(int w, int h, float alt, MapSurfaceType surf) {
|
||||
if (w < MIN_MAP_CELL_DIMENSION || h < MIN_MAP_CELL_DIMENSION) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Size of map must be at least %dx%d",MIN_MAP_CELL_DIMENSION,MIN_MAP_CELL_DIMENSION);
|
||||
throw runtime_error(szBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (w > MAX_MAP_CELL_DIMENSION || h > MAX_MAP_CELL_DIMENSION) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Size of map can be at most %dx%d",MAX_MAP_CELL_DIMENSION,MAX_MAP_CELL_DIMENSION);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
if (alt < MIN_MAP_CELL_HEIGHT || alt > MAX_MAP_CELL_HEIGHT) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Height must be in the range %d-%d",MIN_MAP_CELL_HEIGHT,MAX_MAP_CELL_HEIGHT);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
if (surf < st_Grass || surf > st_Ground) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Surface must be in the range %d-%d",st_Grass,st_Ground);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
int oldW = this->w;
|
||||
int oldH = this->h;
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->maxFactions = maxFactions;
|
||||
|
||||
//create new cells
|
||||
//Cell **oldCells = cells;
|
||||
std::vector<std::vector<Cell> > oldCells = cells;
|
||||
|
||||
//cells = new Cell*[w];
|
||||
cells.resize(w);
|
||||
for (int i = 0; i < w; i++) {
|
||||
//cells[i] = new Cell[h];
|
||||
cells[i].resize(h);
|
||||
for (int j = 0; j < h; j++) {
|
||||
cells[i][j].height = alt;
|
||||
cells[i][j].object = 0;
|
||||
cells[i][j].resource = 0;
|
||||
cells[i][j].surface = surf;
|
||||
}
|
||||
}
|
||||
|
||||
int wOffset = w < oldW ? 0 : (w - oldW) / 2;
|
||||
int hOffset = h < oldH ? 0 : (h - oldH) / 2;
|
||||
//assign old values to cells
|
||||
for (int i = 0; i < oldW; i++) {
|
||||
for (int j = 0; j < oldH; j++) {
|
||||
if (i + wOffset < w && j + hOffset < h) {
|
||||
cells[i+wOffset][j+hOffset].height = oldCells[i][j].height;
|
||||
cells[i+wOffset][j+hOffset].object = oldCells[i][j].object;
|
||||
cells[i+wOffset][j+hOffset].resource = oldCells[i][j].resource;
|
||||
cells[i+wOffset][j+hOffset].surface = oldCells[i][j].surface;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
startLocations[i].x += wOffset;
|
||||
startLocations[i].y += hOffset;
|
||||
}
|
||||
|
||||
//delete old cells
|
||||
//if (oldCells != NULL) {
|
||||
// for (int i = 0; i < oldW; i++)
|
||||
// delete [] oldCells[i];
|
||||
// delete [] oldCells;
|
||||
//}
|
||||
}
|
||||
|
||||
void MapPreview::resetFactions(int maxPlayers) {
|
||||
if (maxPlayers < MIN_MAP_FACTIONCOUNT || maxPlayers > MAX_MAP_FACTIONCOUNT) {
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"Max Players must be in the range %d-%d",MIN_MAP_FACTIONCOUNT,MAX_MAP_FACTIONCOUNT);
|
||||
throw runtime_error(szBuf);
|
||||
}
|
||||
|
||||
//if (startLocations != NULL) {
|
||||
// delete [] startLocations;
|
||||
// startLocations = NULL;
|
||||
//}
|
||||
startLocations.clear();
|
||||
|
||||
maxFactions = maxPlayers;
|
||||
|
||||
//startLocations = new StartLocation[maxFactions];
|
||||
startLocations.resize(maxFactions);
|
||||
for (int i = 0; i < maxFactions; i++) {
|
||||
startLocations[i].x = 0;
|
||||
startLocations[i].y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::setTitle(const string &title) {
|
||||
this->title = title;
|
||||
}
|
||||
|
||||
void MapPreview::setDesc(const string &desc) {
|
||||
this->desc = desc;
|
||||
}
|
||||
|
||||
void MapPreview::setAuthor(const string &author) {
|
||||
this->author = author;
|
||||
}
|
||||
|
||||
void MapPreview::setAdvanced(int altFactor, int waterLevel) {
|
||||
this->altFactor = altFactor;
|
||||
this->waterLevel = waterLevel;
|
||||
}
|
||||
|
||||
int MapPreview::getHeightFactor() const {
|
||||
return altFactor;
|
||||
}
|
||||
|
||||
int MapPreview::getWaterLevel() const {
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
void MapPreview::randomizeHeights() {
|
||||
resetHeights(random.randRange(8, 10));
|
||||
sinRandomize(0);
|
||||
decalRandomize(4);
|
||||
sinRandomize(1);
|
||||
}
|
||||
|
||||
void MapPreview::randomize() {
|
||||
randomizeHeights();
|
||||
|
||||
int slPlaceFactorX = random.randRange(0, 1);
|
||||
int slPlaceFactorY = random.randRange(0, 1) * 2;
|
||||
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
StartLocation sl;
|
||||
float slNoiseFactor = random.randRange(0.5f, 0.8f);
|
||||
|
||||
sl.x = static_cast<int>(w * slNoiseFactor * ((i + slPlaceFactorX) % 2) + w * (1.f - slNoiseFactor) / 2.f);
|
||||
sl.y = static_cast<int>(h * slNoiseFactor * (((i + slPlaceFactorY) / 2) % 2) + h * (1.f - slNoiseFactor) / 2.f);
|
||||
startLocations[i] = sl;
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::switchSurfaces(MapSurfaceType surf1, MapSurfaceType surf2) {
|
||||
if (surf1 >= st_Grass && surf1 <= st_Ground && surf2 >= st_Grass && surf2 <= st_Ground) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
for (int j = 0; j < h; ++j) {
|
||||
if (cells[i][j].surface == surf1) {
|
||||
cells[i][j].surface = surf2;
|
||||
}
|
||||
else if (cells[i][j].surface == surf2) {
|
||||
cells[i][j].surface = surf1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw runtime_error("Incorrect surfaces");
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::loadFromFile(const string &path) {
|
||||
|
||||
FILE *f1 = fopen(path.c_str(), "rb");
|
||||
if (f1 != NULL) {
|
||||
|
||||
//read header
|
||||
MapFileHeader header;
|
||||
size_t bytes = fread(&header, sizeof(MapFileHeader), 1, f1);
|
||||
|
||||
altFactor = header.altFactor;
|
||||
waterLevel = header.waterLevel;
|
||||
title = header.title;
|
||||
author = header.author;
|
||||
desc = header.description;
|
||||
|
||||
//read start locations
|
||||
resetFactions(header.maxFactions);
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
bytes = fread(&startLocations[i].x, sizeof(int32), 1, f1);
|
||||
bytes = fread(&startLocations[i].y, sizeof(int32), 1, f1);
|
||||
}
|
||||
|
||||
//read Heights
|
||||
reset(header.width, header.height, DEFAULT_MAP_CELL_HEIGHT, DEFAULT_MAP_CELL_SURFACE_TYPE);
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
bytes = fread(&cells[i][j].height, sizeof(float), 1, f1);
|
||||
}
|
||||
}
|
||||
|
||||
//read surfaces
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
bytes = fread(&cells[i][j].surface, sizeof(int8), 1, f1);
|
||||
}
|
||||
}
|
||||
|
||||
//read objects
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
int8 obj;
|
||||
bytes = fread(&obj, sizeof(int8), 1, f1);
|
||||
if (obj <= 10) {
|
||||
cells[i][j].object = obj;
|
||||
}
|
||||
else {
|
||||
cells[i][j].resource = obj - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f1);
|
||||
|
||||
fileLoaded = true;
|
||||
}
|
||||
else {
|
||||
throw runtime_error("error opening map file: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MapPreview::saveToFile(const string &path) {
|
||||
|
||||
FILE *f1 = fopen(path.c_str(), "wb");
|
||||
if (f1 != NULL) {
|
||||
|
||||
//write header
|
||||
MapFileHeader header;
|
||||
|
||||
header.version = 1;
|
||||
header.maxFactions = maxFactions;
|
||||
header.width = w;
|
||||
header.height = h;
|
||||
header.altFactor = altFactor;
|
||||
header.waterLevel = waterLevel;
|
||||
strncpy(header.title, title.c_str(), 128);
|
||||
strncpy(header.author, author.c_str(), 128);
|
||||
strncpy(header.description, desc.c_str(), 256);
|
||||
|
||||
fwrite(&header, sizeof(MapFileHeader), 1, f1);
|
||||
|
||||
//write start locations
|
||||
for (int i = 0; i < maxFactions; ++i) {
|
||||
fwrite(&startLocations[i].x, sizeof(int32), 1, f1);
|
||||
fwrite(&startLocations[i].y, sizeof(int32), 1, f1);
|
||||
}
|
||||
|
||||
//write Heights
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
fwrite(&cells[i][j].height, sizeof(float32), 1, f1);
|
||||
}
|
||||
}
|
||||
|
||||
//write surfaces
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
fwrite(&cells[i][j].surface, sizeof(int8), 1, f1);
|
||||
}
|
||||
}
|
||||
|
||||
//write objects
|
||||
for (int j = 0; j < h; ++j) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
if (cells[i][j].resource == 0)
|
||||
fwrite(&cells[i][j].object, sizeof(int8), 1, f1);
|
||||
else {
|
||||
int8 res = cells[i][j].resource + 10;
|
||||
fwrite(&res, sizeof(int8), 1, f1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f1);
|
||||
|
||||
}
|
||||
else {
|
||||
throw runtime_error("Error opening map file: " + path);
|
||||
}
|
||||
|
||||
void randomHeight(int x, int y, int height);
|
||||
}
|
||||
|
||||
// ==================== PRIVATE ====================
|
||||
|
||||
void MapPreview::resetHeights(int height) {
|
||||
for (int i = 0; i < w; ++i) {
|
||||
for (int j = 0; j < h; ++j) {
|
||||
cells[i][j].height = static_cast<float>(height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::sinRandomize(int strenght) {
|
||||
float sinH1 = random.randRange(5.f, 40.f);
|
||||
float sinH2 = random.randRange(5.f, 40.f);
|
||||
float sinV1 = random.randRange(5.f, 40.f);
|
||||
float sinV2 = random.randRange(5.f, 40.f);
|
||||
float ah = static_cast<float>(10 + random.randRange(-2, 2));
|
||||
float bh = static_cast<float>((maxHeight - minHeight) / random.randRange(2, 3));
|
||||
float av = static_cast<float>(10 + random.randRange(-2, 2));
|
||||
float bv = static_cast<float>((maxHeight - minHeight) / random.randRange(2, 3));
|
||||
|
||||
for (int i = 0; i < w; ++i) {
|
||||
for (int j = 0; j < h; ++j) {
|
||||
float normH = static_cast<float>(i) / w;
|
||||
float normV = static_cast<float>(j) / h;
|
||||
|
||||
float sh = (sinf(normH * sinH1) + sin(normH * sinH2)) / 2.f;
|
||||
float sv = (sinf(normV * sinV1) + sin(normV * sinV2)) / 2.f;
|
||||
|
||||
float newHeight = (ah + bh * sh + av + bv * sv) / 2.f;
|
||||
applyNewHeight(newHeight, i, j, strenght);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::decalRandomize(int strenght) {
|
||||
//first row
|
||||
int lastHeight = DEFAULT_MAP_CELL_HEIGHT;
|
||||
for (int i = 0; i < w; ++i) {
|
||||
lastHeight += random.randRange(-1, 1);
|
||||
lastHeight = clamp(lastHeight, minHeight, maxHeight);
|
||||
applyNewHeight(static_cast<float>(lastHeight), i, 0, strenght);
|
||||
}
|
||||
|
||||
//other rows
|
||||
for (int j = 1; j < h; ++j) {
|
||||
int height = static_cast<int>(cells[0][j-1].height + random.randRange(-1, 1));
|
||||
applyNewHeight(static_cast<float>(clamp(height, minHeight, maxHeight)), 0, j, strenght);
|
||||
for (int i = 1; i < w; ++i) {
|
||||
height = static_cast<int>((cells[i][j-1].height + cells[i-1][j].height) / 2.f + random.randRange(-1, 1));
|
||||
float newHeight = static_cast<float>(clamp(height, minHeight, maxHeight));
|
||||
applyNewHeight(newHeight, i, j, strenght);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPreview::applyNewHeight(float newHeight, int x, int y, int strenght) {
|
||||
cells[x][y].height = static_cast<float>(((cells[x][y].height * strenght) + newHeight) / (strenght + 1));
|
||||
}
|
||||
|
||||
}}// end namespace
|
Reference in New Issue
Block a user