More optimized way to create a "Hex Painter" (currently using draw functions extensively)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Beamer159

I am making a hex painter. If I scale the size up, it slows down drastically. I believe that the slowdown is either because each hex is an Area2D with collision which doesn’t scale well, or because program prints everything via draw_line for the hex outlines and draw_polygon for the filled in spaces, and these functions are inefficient. What would be a more optimized alternative?

:bust_in_silhouette: Reply From: estebanmolca

Try using Tilemaps, see the documentation in the editor about TileMap and TileSet to see all their methods. You can change the texture of each cell or keep the same by changing the color by modulating, deleting, collisions, etc. To detect each cell with the mouse you can use its collisions or by position proximity. For the continuity of the selection with the mouse you can use a popular algorithm:

I created an empty tilemap with very small cells (4x4 pixel, no collision), and the drawing is fast.

func _process(delta):
	var pos=$TileMap.world_to_map(get_local_mouse_position())
	$TileMap.set_cell(pos.x, pos.y,0)

Although to avoid empty spaces you have to use the algorithm that I mentioned above or perhaps use a linear interpolation between each position of the mouse.

https://godotengine.org/asset-library/asset/111

Here is an example:

extends Node2D
var pos=Vector2.ZERO

func _input(event):
	if Input.is_mouse_button_pressed(BUTTON_LEFT) and event is InputEventMouseMotion:
		var pos=$TileMap.world_to_map(event.position)
		var line=interpolated_line(event.position-event.relative, event.position)	
		for i in line:
			var w=$TileMap.world_to_map(Vector2(i[0], i[1]))
			$TileMap.set_cell(w.x,w.y,0)
		
func interpolated_line(p0, p1):
	var points = []
	var dx = p1[0] - p0[0]
	var dy = p1[1] - p0[1]
	var N = max(abs(dx), abs(dy))
	for i in N+1:
		var t = float(i) / float(N)
		var point = [round(lerp(p0[0], p1[0], t)), round(lerp(p0[1], p1[1], t))]
		points.append(point)
	return points

estebanmolca | 2021-03-06 08:17