From bb78baa7102eeb9d64ab479be0a18b89896ee4ea Mon Sep 17 00:00:00 2001 From: Alain STARK Date: Wed, 17 Aug 2022 00:02:10 +0200 Subject: [PATCH 1/2] Multiple small code reorganisation in class Terrain --- project.godot | 4 ++ ui/map/map.gd | 2 + utils/Global.gd | 9 +++ utils/terrain/Terrain.gd | 128 +++++++++++++++++---------------------- world/game.gd | 6 +- world/game.tscn | 2 + 6 files changed, 75 insertions(+), 76 deletions(-) create mode 100644 utils/Global.gd diff --git a/project.godot b/project.godot index 5fbb305..4c8af13 100644 --- a/project.godot +++ b/project.godot @@ -36,6 +36,10 @@ config/name="Societer" run/main_scene="res://world/game.tscn" config/icon="res://icon.png" +[autoload] + +Global="*res://utils/Global.gd" + [gui] common/drop_mouse_on_gui_input_disabled=true diff --git a/ui/map/map.gd b/ui/map/map.gd index b06d140..4b85850 100644 --- a/ui/map/map.gd +++ b/ui/map/map.gd @@ -3,6 +3,8 @@ extends Node2D var terrain func create_map(): + + Global.print_debug("Create river") var river = {"size": 3, "color": "blue"} terrain.get_edge(16).set_data("river", river) diff --git a/utils/Global.gd b/utils/Global.gd new file mode 100644 index 0000000..6ce19df --- /dev/null +++ b/utils/Global.gd @@ -0,0 +1,9 @@ +extends Node + +var debug = true + +# Debuging messages +func print_debug(message): + if debug: + print(message) + diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index 717c8fe..7d87404 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -17,21 +17,22 @@ class Triangles: func _should_continue(): return (_curr < _end) - func _iter_init(arg): + func _iter_init(_arg): _curr = 0 return _should_continue() - func _iter_next(arg): + func _iter_next(_arg): _curr += 1 return _should_continue() - func _iter_get(arg): + func _iter_get(_arg): var triangle = Triangle.new(_curr,_terrain) return triangle func size(): return _end +# Triangle object class Triangle: var _idx var _terrain @@ -85,7 +86,8 @@ class Triangle: for point in points(): polygon.append(point.point2d()) return polygon - + +# Points iterator class Points: var _terrain var _curr @@ -99,21 +101,22 @@ class Points: func _should_continue(): return (_curr < _end) - func _iter_init(arg): + func _iter_init(_arg): _curr = 0 return _should_continue() - func _iter_next(arg): + func _iter_next(_arg): _curr += 1 return _should_continue() - func _iter_get(arg): + func _iter_get(_arg): var point = Point.new(_curr,_terrain) return point func size(): return _end - + +# Point object class Point: var _idx var _terrain @@ -176,6 +179,7 @@ class Point: break return list_points +# Edges iterator class Edges: var _terrain var _curr @@ -189,21 +193,22 @@ class Edges: func _should_continue(): return (_curr < _end) - func _iter_init(arg): + func _iter_init(_arg): _curr = 0 return _should_continue() - func _iter_next(arg): + func _iter_next(_arg): _curr += 1 return _should_continue() - func _iter_get(arg): + func _iter_get(_arg): var edge = Edge.new(_curr,_terrain) return edge func size(): return _end +# Edge object class Edge: var _idx var _terrain @@ -243,12 +248,14 @@ class Edge: func opposite(): return Edge.new(_terrain._halfedges[_idx], _terrain) - -const terrain_file = "user://terrain.save" -var width: int -var height: int -var spacing: int +# Terrain instance variables +const terrain_file = "user://terrain_%s.save" + +var _width: int +var _height: int +var _spacing: int +var _name: String var _points = PoolVector3Array() var _halfedges var _triangles @@ -258,33 +265,18 @@ var _points_data = [] var _edges_data = [] var _triangles_data = [] var _file = File.new() -var _debug = true - -""" -func general_type_of(obj): - var typ = typeof(obj) - var builtin_type_names = ["nil", "bool", "int", "real", "string", "vector2", "rect2", "vector3", "maxtrix32", "plane", "quat", "aabb", "matrix3", "transform", "color", "image", "nodepath", "rid", null, "inputevent", "dictionary", "array", "rawarray", "intarray", "realarray", "stringarray", "vector2array", "vector3array", "colorarray", "unknown"] - - if(typ == TYPE_OBJECT): - return obj.type_of() - else: - return builtin_type_names[typ] -""" -func _print_debug(message): - if _debug: - print(message) - -func _init(width:int=1600, height:int=800, spacing:int=30, create=false): +# Terrain constructor +func _init(width:int=1600, height:int=800, spacing:int=30, create=false, name:String="delaunay"): if _file.file_exists(terrain_file) and not create: - _print_debug("loading...") - _load() + Global.print_debug("loading : %s ..." % (name)) + _load(name) else: - _print_debug("Creating...") + Global.print_debug("Creating : %s ..." % (name)) var delaunay: Delaunator - self.width = width - self.height = height - self.spacing = spacing + _width = width + _height = height + _spacing = spacing _create_points() delaunay = Delaunator.new(_points) @@ -292,35 +284,36 @@ func _init(width:int=1600, height:int=800, spacing:int=30, create=false): _triangles = PoolIntArray(delaunay.triangles) # Initialize _points_to_halfedges - for edge_idx in edges(): - var edge = get_edge(edge_idx) + for edge in get_edges(): var endpoint = _triangles[edge.next_half().get_index()] - if (! _points_to_halfedges.has(endpoint) or _halfedges[edge_idx] == -1): - _points_to_halfedges[endpoint] = edge_idx + if (! _points_to_halfedges.has(endpoint) or _halfedges[edge.get_index()] == -1): + _points_to_halfedges[endpoint] = edge.get_index() # Initialise _points_data - for point_idx in points(): + for point_idx in self.get_points().size(): _points_data.append({}) # Initialise _edges_data - for edge_idx in edges(): + for edge_idx in self.get_edges().size(): _edges_data.append({}) # Initialise _triangle_data - for triangle_idx in triangles(): + for triangle_idx in self.get_triangles().size(): _triangles_data.append({}) _save() - + +# Create points on the terrain func _create_points(): - var rect = Rect2(Vector2(0, 0), Vector2(width, height)) + var rect = Rect2(Vector2(0, 0), Vector2(_width, _height)) var poisson_disc_sampling: PoissonDiscSampling = PoissonDiscSampling.new() - var points2d = poisson_disc_sampling.generate_points(spacing, rect, 5) + var points2d = poisson_disc_sampling.generate_points(_spacing, rect, 5) _points.resize(points2d.size()) for point_idx in points2d.size(): _points[point_idx].x = points2d[point_idx].x _points[point_idx].z = points2d[point_idx].y +# Terrain methodes func get_triangles(): var triangles = Triangles.new(self) return triangles @@ -341,45 +334,34 @@ func get_edge(idx): func get_triangle(idx): return Triangle.new(idx, self) - -func triangles(): - return _triangles.size() / 3 - -func points(): - return _points.size() - -func edges(): - return _triangles.size() - -# Voronoi - -func centroid(points): - return Vector3((points[0].x + points[1].x + points[2].x) / 3.0, 0.0, (points[0].z + points[1].z + points[2].z) / 3.0) - func _save(): - _file.open(terrain_file, File.WRITE) - _file.store_var(width) - _file.store_var(height) - _file.store_var(spacing) + _file.open(terrain_file % (_name), File.WRITE) + _file.store_var(_width) + _file.store_var(_height) + _file.store_var(_spacing) + _file.store_var(_name) _file.store_var(_points) _file.store_var(_halfedges) _file.store_var(_triangles) _file.store_var(_points_to_halfedges) + _file.store_var(_data) _file.store_var(_points_data) _file.store_var(_edges_data) _file.store_var(_triangles_data) _file.close() -func _load(): - _file.open(terrain_file, File.READ) - width = _file.get_var() - height = _file.get_var() - spacing = _file.get_var() +func _load(name): + _file.open(terrain_file % (name), File.READ) + _width = _file.get_var() + _height = _file.get_var() + _spacing = _file.get_var() + _name = _file.get_var() _points = _file.get_var() _halfedges = _file.get_var() _triangles = _file.get_var() _points_to_halfedges = _file.get_var() + _data = _file.get_var() _points_data = _file.get_var() _edges_data = _file.get_var() _triangles_data = _file.get_var() diff --git a/world/game.gd b/world/game.gd index 02460cd..bbbfecd 100644 --- a/world/game.gd +++ b/world/game.gd @@ -24,12 +24,12 @@ func _ready(): noise.octaves = octaves terrain = Terrain.new(width,height,spacing,true) init_points_data() - print(terrain.get_point(3)) + # print(terrain.get_point(3)) emit_signal("world_loaded", terrain) func init_points_data(): - for index in terrain.get_points().size(): - terrain.get_point(index).set_elevation(find_elevation(terrain.get_point(index).point2d())) + for point in terrain.get_points(): + point.set_elevation(find_elevation(point.point2d())) # points_data.append({ # "elevation": 0, # "used": false, diff --git a/world/game.tscn b/world/game.tscn index 3556972..04f54ff 100644 --- a/world/game.tscn +++ b/world/game.tscn @@ -8,4 +8,6 @@ script = ExtResource( 2 ) [node name="UI" parent="." instance=ExtResource( 1 )] +[connection signal="world_loaded" from="." to="UI/Map" method="_on_Game_world_loaded"] + [editable path="UI"] -- 2.36.2 From f6b83bd1ced52229c23b6dfb9cd484ee14d62841 Mon Sep 17 00:00:00 2001 From: Alain STARK Date: Wed, 17 Aug 2022 23:47:00 +0200 Subject: [PATCH 2/2] load, save, list terrain --- utils/terrain/Terrain.gd | 190 ++++++++++++++++++++++++++------------- world/game.gd | 21 ++++- 2 files changed, 147 insertions(+), 64 deletions(-) diff --git a/utils/terrain/Terrain.gd b/utils/terrain/Terrain.gd index 75e4cfb..b97a366 100644 --- a/utils/terrain/Terrain.gd +++ b/utils/terrain/Terrain.gd @@ -256,7 +256,6 @@ class Edge: return line # Terrain instance variables -const terrain_file = "user://terrain_%s.save" var _width: int var _height: int @@ -270,44 +269,79 @@ var _data = {} var _points_data = [] var _edges_data = [] var _triangles_data = [] -var _file = File.new() + +var _created = false +var _loaded = false +var _list = [] # Terrain constructor -func _init(width:int=1600, height:int=800, spacing:int=30, create=false, name:String="delaunay"): - if _file.file_exists(terrain_file) and not create: +func _init(width:int=1600, height:int=800, spacing:int=30, create=false, name:String=""): + var terrain_dir = Directory.new() + terrain_dir.open("user://") + if not terrain_dir.dir_exists("terrain"): + terrain_dir.make_dir("terrain") + terrain_dir.change_dir("terrain") + terrain_dir.list_dir_begin() + var filename = terrain_dir.get_next() + while filename != "": + if terrain_dir.file_exists(filename): + # Ok terrain file found + var terrain = {} + var terrain_filename = "user://terrain/%s" % (filename) + var file = File.new() + file.open(terrain_filename, File.READ) + terrain["width"] = file.get_var() + terrain["height"] = file.get_var() + terrain["spacing"] = file.get_var() + terrain["name"] = file.get_var() + file.close() + _list.append(terrain) + filename = terrain_dir.get_next() + terrain_dir.list_dir_end() + + var file = File.new() + var terrain_filename = "user://terrain/terrain_%s.save" % (name) + if file.file_exists(terrain_filename) and not create: Global.print_debug("loading : %s ..." % (name)) - _load(name) + load(name) else: - Global.print_debug("Creating : %s ..." % (name)) - var delaunay: Delaunator - _width = width - _height = height - _spacing = spacing - _create_points() - delaunay = Delaunator.new(_points) + if name: + create(width, height, spacing, name) + + +func create(width:int, height:int, spacing:int, name:String): + Global.print_debug("Creating : %s ..." % (name)) + var delaunay: Delaunator + _width = width + _height = height + _spacing = spacing + _name = name + _create_points() + delaunay = Delaunator.new(_points) - _halfedges = PoolIntArray(delaunay.halfedges) - _triangles = PoolIntArray(delaunay.triangles) + _halfedges = PoolIntArray(delaunay.halfedges) + _triangles = PoolIntArray(delaunay.triangles) - # Initialize _points_to_halfedges - for edge in get_edges(): - var endpoint = _triangles[edge.next_half().get_index()] - if (! _points_to_halfedges.has(endpoint) or _halfedges[edge.get_index()] == -1): - _points_to_halfedges[endpoint] = edge.get_index() - - # Initialise _points_data - for point_idx in self.get_points().size(): - _points_data.append({}) + # Initialize _points_to_halfedges + for edge in get_edges(): + var endpoint = _triangles[edge.next_half().get_index()] + if (! _points_to_halfedges.has(endpoint) or _halfedges[edge.get_index()] == -1): + _points_to_halfedges[endpoint] = edge.get_index() + + # Initialise _points_data + for point_idx in self.get_points().size(): + _points_data.append({}) - # Initialise _edges_data - for edge_idx in self.get_edges().size(): - _edges_data.append({}) + # Initialise _edges_data + for edge_idx in self.get_edges().size(): + _edges_data.append({}) - # Initialise _triangle_data - for triangle_idx in self.get_triangles().size(): - _triangles_data.append({}) - - _save() + # Initialise _triangle_data + for triangle_idx in self.get_triangles().size(): + _triangles_data.append({}) + + _created = true + save() # Create points on the terrain func _create_points(): @@ -341,37 +375,71 @@ func get_edge(idx): func get_triangle(idx): return Triangle.new(idx, self) -func _save(): - _file.open(terrain_file % (_name), File.WRITE) - _file.store_var(_width) - _file.store_var(_height) - _file.store_var(_spacing) - _file.store_var(_name) - _file.store_var(_points) - _file.store_var(_halfedges) - _file.store_var(_triangles) - _file.store_var(_points_to_halfedges) - _file.store_var(_data) - _file.store_var(_points_data) - _file.store_var(_edges_data) - _file.store_var(_triangles_data) - _file.close() +func save(): + var terrain_dir = Directory.new() + var file = File.new() + var terrain_filename = "user://terrain/terrain_%s.save" % (_name) + terrain_dir.open("user://") + if not terrain_dir.dir_exists("terrain"): + terrain_dir.make_dir("terrain") + terrain_dir.change_dir("terrain") + Global.print_debug("Save file : %s" % (terrain_filename)) + file.open(terrain_filename, File.WRITE) + file.store_var(_width) + file.store_var(_height) + file.store_var(_spacing) + file.store_var(_name) + file.store_var(_points) + file.store_var(_halfedges) + file.store_var(_triangles) + file.store_var(_points_to_halfedges) + file.store_var(_data) + file.store_var(_points_data) + file.store_var(_edges_data) + file.store_var(_triangles_data) + file.close() + +func load(name): + var terrain_dir = Directory.new() + var file = File.new() + var terrain_filename = "user://terrain/terrain_%s.save" % (name) + terrain_dir.open("user://") + if not terrain_dir.dir_exists("terrain"): + terrain_dir.make_dir("terrain") + if terrain_dir.file_exists(terrain_filename): + Global.print_debug("Load file : %s" % (terrain_filename)) + file.open(terrain_filename, File.READ) + _width = file.get_var() + _height = file.get_var() + _spacing = file.get_var() + _name = file.get_var() + _points = file.get_var() + _halfedges = file.get_var() + _triangles = file.get_var() + _points_to_halfedges = file.get_var() + _data = file.get_var() + _points_data = file.get_var() + _edges_data = file.get_var() + _triangles_data = file.get_var() + file.close() + _loaded = true + else: + Global.print_debug("The file : %s does not exist" % (terrain_filename)) + +func list(): + return _list + +func is_created(): + return _created + +func is_loaded(): + return _loaded -func _load(name): - _file.open(terrain_file % (name), File.READ) - _width = _file.get_var() - _height = _file.get_var() - _spacing = _file.get_var() - _name = _file.get_var() - _points = _file.get_var() - _halfedges = _file.get_var() - _triangles = _file.get_var() - _points_to_halfedges = _file.get_var() - _data = _file.get_var() - _points_data = _file.get_var() - _edges_data = _file.get_var() - _triangles_data = _file.get_var() - _file.close() +func exists(name): + for terrain in _list: + if name == terrain["name"]: + return true + return false func get_triangles_as_polygon(): var list_polygon = [] diff --git a/world/game.gd b/world/game.gd index 89fc0c7..1175dae 100644 --- a/world/game.gd +++ b/world/game.gd @@ -22,10 +22,25 @@ func _ready(): rng.randomize() noise.seed = rng.randi() noise.octaves = octaves - terrain = Terrain.new(width,height,spacing,true) + # terrain = Terrain.new(width,height,spacing,false) + + var terrain_name="bonjour" + terrain = Terrain.new() - init_data() - emit_signal("world_loaded", terrain) + print(terrain.list()) + + if terrain.exists(terrain_name): + terrain.load(terrain_name) + else: + terrain.create(width,height,spacing,"bonjour") + + if terrain.is_created() or terrain.is_loaded(): + init_data() + emit_signal("world_loaded", terrain) + else: + Global.print_debug("Pas de terrain, pas de construction ...") + Global.print_debug("Pas de construction ..., pas de palais ...") + Global.print_debug("Pas de palais ..., pas de palais.") func init_data(): for point in terrain.get_points(): -- 2.36.2