Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Node
- # Edited 24.05.2021
- # Add some useful functions
- # and cleaned up code
- enum HexTypes{
- vert,
- hor,
- }
- enum GridTypes{
- rect,
- hex
- }
- enum Views{
- iso,
- front,
- }
- const hex_type = HexTypes.vert
- const grid_type = GridTypes.hex
- const view = Views.iso
- const size = 24
- const iso_scale = 2.0
- const hex_map_size = Vector2(9, 7)
- var hex_basis:Transform2D
- var grid_basis:Transform2D
- var grid_map_size:Vector2
- class PriorityStack:
- var items:Array
- func _init():
- items = Array()
- func empty() -> bool:
- return items.size() == 0
- func put(item, priority:int) -> void:
- if empty():
- items.append([item, priority])
- elif priority <= items[0][1]:
- items.insert(0, [item, priority])
- elif priority > items[-1][1]:
- items.append([item, priority])
- else:
- for i in range(len(items)):
- if priority <= items[i][1]:
- items.insert(i, [item, priority])
- break
- func take():
- return items.pop_front()[0]
- func _init():
- var short = int(size*sqrt(3)/2) # 1/2 from short hex diagonal
- var long = int(size/2) # 1/4 from long hex diagonal
- hex_basis = Transform2D()
- grid_basis = Transform2D()
- grid_map_size = Vector2()
- match hex_type:
- HexTypes.vert:
- match view:
- Views.iso:
- var pw = int(long*cos(PI/4))
- var ph = int(short*cos(PI/4))
- grid_basis.x = Vector2(pw, pw/iso_scale)
- grid_basis.y = Vector2(-ph, ph/iso_scale)
- Views.front:
- grid_basis.x = Vector2(long, 0)
- grid_basis.y = Vector2(0, short/iso_scale)
- _:
- grid_basis.x = Vector2(long, 0)
- grid_basis.y = Vector2(0, short/iso_scale)
- hex_basis.x = grid_basis.x*3 + grid_basis.y
- hex_basis.y = grid_basis.y*2
- HexTypes.hor:
- match view:
- Views.iso:
- var pw = int(short*cos(PI/4))
- var ph = int(long*cos(PI/4))
- grid_basis.x = Vector2(pw, pw/iso_scale)
- grid_basis.y = Vector2(-ph, ph/iso_scale)
- Views.front:
- grid_basis.x = Vector2(short, 0)
- grid_basis.y = Vector2(0, long/iso_scale)
- _:
- grid_basis.x = Vector2(short, 0)
- grid_basis.y = Vector2(0, long/iso_scale)
- hex_basis.x = grid_basis.x*2
- hex_basis.y = grid_basis.x+grid_basis.y*3
- match grid_type:
- GridTypes.rect:
- match hex_type:
- HexTypes.vert:
- grid_map_size.x = hex_map_size.x*3+1
- grid_map_size.y = hex_map_size.y*2
- HexTypes.hor:
- grid_map_size.x = hex_map_size.x*2
- grid_map_size.y = hex_map_size.y*3+1
- GridTypes.hex:
- var diagonal = hex_map_size.x*2-1
- match hex_type:
- HexTypes.vert:
- grid_map_size.x = diagonal*3+1
- grid_map_size.y = diagonal*2
- HexTypes.hor:
- grid_map_size.x = diagonal*2
- grid_map_size.y = diagonal*3+1
- # ###########################################
- # _____CONVAERSATIONS_________
- # Here are functions for conversations
- # between screen and grid values
- # ###########################################
- func cell2pixel(cell:Vector2) -> Vector2:
- return cell.x*grid_basis.x + cell.y*grid_basis.y
- func pixel2cell(pixel:Vector2, rounding=true) -> Vector2:
- var res = grid_basis.affine_inverse().xform(pixel)
- if rounding: res = res.floor()
- return res
- func hex2pixel(hex:Vector2) -> Vector2:
- return hex.x*hex_basis.x + hex.y*hex_basis.y
- func pixel2hex(pixel:Vector2) -> Vector2:
- return round_hex(hex_basis.affine_inverse().xform(pixel))
- func round_hex(hex:Vector2) -> Vector2:
- var rx = round(hex.x)
- var ry = round(hex.y)
- var rz = round(-hex.x-hex.y)
- var x_diff = abs(hex.x-rx)
- var y_diff = abs(hex.y-ry)
- var z_diff = abs(-hex.x-hex.y-rz)
- if x_diff > y_diff and x_diff > z_diff:
- rx = -ry-rz
- elif y_diff > z_diff:
- ry = -rx-rz
- return Vector2(rx, ry)
- func get_center_cell(hex:Vector2) -> Vector2:
- if hex_type == HexTypes.vert:
- return Vector2(hex.x*3, hex.y*2+hex.x)
- else: # Horizontal
- return Vector2(hex.x*2+hex.y, hex.y*3)
- func linear2iso(angle:float) -> float:
- return pixel2cell(Vector2(cos(angle), sin(angle)), false).angle()
- func iso2linear(angle:float) -> float:
- return cell2pixel(Vector2(cos(angle), sin(angle))).angle()
- # ###########################################
- # _____GRID_MANIPULATING_________
- # Here are functions for working
- # at grid
- # ###########################################
- func direct_hex(hex1:Vector2, hex2:Vector2) -> Vector2:
- var dx = hex2.x - hex1.x
- var dy = hex2.y - hex1.y
- var dz = -hex2.x-hex2.y + hex1.x+hex1.y
- if dx == 0:
- return Vector2(0, sign(dy))
- elif dy == 0:
- return Vector2(sign(dx), 0)
- elif dz == 0:
- return Vector2(sign(dx), sign(dy))
- else:
- if abs(dz) > abs(dx) and abs(dz) > abs(dy):
- if abs(dx) > abs(dy):
- return Vector2(sign(dx), 0)
- else:
- return Vector2(0, sign(dy))
- elif abs(dy) > abs(dx):
- if abs(dz) > abs(dx):
- return Vector2(0, sign(dy))
- else:
- return Vector2(sign(dx), sign(dy))
- else:
- if abs(dy) > abs(dz):
- return Vector2(sign(dx), sign(dy))
- else:
- return Vector2(sign(dx), 0)
- func in_map(hex:Vector2) -> bool:
- match grid_type:
- GridTypes.hex:
- return _is_in_hex_grid(hex)
- GridTypes.rect:
- if hex_type == HexTypes.vert:
- return _in_rect_grid_vert(hex)
- else: # Hor orientation
- return _in_rect_grid_hor(hex)
- _:
- return true
- func get_map_center() -> Vector2:
- match grid_type:
- GridTypes.hex:
- if hex_type == HexTypes.hor:
- return _get_hor_hex_map_center()
- else: # Vertical
- return _get_vert_hex_map_center()
- GridTypes.rect:
- return Vector2() # Rect map has no center
- _:
- return Vector2()
- func can_stand(hex:Vector2, obsts:PoolVector2Array) -> bool:
- return in_map(hex) and not (hex in obsts)
- func neighbors(hex_pos:Vector2, obsts:PoolVector2Array) -> PoolVector2Array:
- var res:PoolVector2Array = []
- var _neighbors = PoolVector2Array([Vector2(-1, 0), Vector2(1, -1), Vector2(0, -1), Vector2(1, 0), Vector2(0, 1), Vector2(-1, 1)])
- for i in _neighbors:
- if can_stand(i+hex_pos, obsts):
- res.append(i+hex_pos)
- return res
- func find_path(start:Vector2, goal:Vector2, obsts:PoolVector2Array) -> PoolVector2Array:
- var frontier = PriorityStack.new()
- frontier.put(start, 0)
- var came_from = {}
- var cost_so_far = {}
- came_from[start] = start
- cost_so_far[start] = 0
- var current:Vector2
- var new_cost:int
- if not can_stand(goal, obsts):
- return PoolVector2Array()
- while not frontier.empty():
- current = frontier.take()
- if current == goal:
- break
- for next in neighbors(current, obsts):
- new_cost = cost_so_far[current] + 1
- if not (next in cost_so_far) or new_cost < cost_so_far[next]:
- cost_so_far[next] = new_cost
- frontier.put(next, new_cost+hex_distance(goal, next))
- came_from[next] = current
- if frontier.empty() and current != goal:
- return PoolVector2Array()
- current = goal
- var path = PoolVector2Array([current])
- while current != start:
- current = came_from[current]
- path.append(current)
- path.invert()
- path.remove(0) # removes first position
- return path
- func rast_line(hex1:Vector2, hex2:Vector2) -> PoolVector2Array:
- var N = hex_distance(hex1, hex2)
- if N == 0: return PoolVector2Array([hex1])
- var res = PoolVector2Array()
- for i in range(N+1):
- res.append(round_hex(lerp(hex1, hex2, i/N)))
- return res
- func hex_distance(hex1:Vector2, hex2:Vector2) -> int:
- var dif = (hex2-hex1)
- return int(abs(dif.x) + abs(dif.y) + abs(-dif.x-dif.y))/2
- # ###########################################
- # _____DRAWING_________
- # Here are functions for drawing
- # at specific grid according to settings
- # ###########################################
- func draw_hex(hex:Vector2, surf:RID, color:Color, width=1.0, antialiasing=false):
- match hex_type:
- HexTypes.vert:
- _draw_vert_hex(hex, surf, color, width, antialiasing)
- HexTypes.hor:
- _draw_hor_hex(hex, surf, color, width, antialiasing)
- func fill_hex(hex:Vector2, surf:RID, color:Color, antialiasing):
- if hex_type == HexTypes.hor:
- _fill_hor_hex(hex, surf, color, antialiasing)
- else: # Vertical
- _fill_vert_hex(hex, surf, color, antialiasing)
- func draw_cell(cell:Vector2, surf:RID, color:Color, width=1.0, antialiasing=false):
- var pixel = cell2pixel(cell)
- var points = PoolVector2Array([
- pixel,
- pixel+grid_basis.x,
- pixel+grid_basis.x+grid_basis.y,
- pixel+grid_basis.y,
- pixel,
- ])
- VisualServer.canvas_item_add_polyline(surf, points, [color], width, antialiasing)
- func fill_cell(cell:Vector2, surf:RID, color:Color, antialiasing=false):
- var pixel = cell2pixel(cell)
- var points = PoolVector2Array([
- pixel,
- pixel+grid_basis.x,
- pixel+grid_basis.x+grid_basis.y,
- pixel+grid_basis.y,
- ])
- VisualServer.canvas_item_add_polygon(surf, points, [color], [], RID(), RID(), antialiasing)
- func draw_auxiliary_grid(surf:RID, color:Color, width=1.0, antialiasing=false):
- var offset:Vector2
- if hex_type == HexTypes.hor:
- offset = grid_basis.x+grid_basis.y*2
- if grid_type == GridTypes.hex and int(hex_map_size.x)%2 == 0:
- offset += grid_basis.x
- else:
- offset = grid_basis.x*2+grid_basis.y
- if grid_type == GridTypes.hex and int(hex_map_size.x)%2 == 0:
- offset += grid_basis.y
- for i in grid_map_size.x+1:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*i-offset, grid_basis.x*i+grid_basis.y*grid_map_size.y-offset, color, width, antialiasing)
- for i in grid_map_size.y+1:
- VisualServer.canvas_item_add_line(surf, grid_basis.y*i-offset, grid_basis.x*grid_map_size.x+grid_basis.y*i-offset, color, width, antialiasing)
- func draw_grid(surf:RID, color:Color, width=1.0, antialiasing=false):
- match grid_type:
- GridTypes.rect:
- match hex_type:
- HexTypes.vert:
- _draw_vert_rect_grid(surf, color, width, antialiasing)
- HexTypes.hor:
- _draw_hor_rect_grid(surf, color, width, antialiasing)
- GridTypes.hex:
- match hex_type:
- HexTypes.hor:
- _draw_hor_hex_grid(surf, color, width, antialiasing)
- HexTypes.vert:
- _draw_vert_hex_grid(surf, color, width, antialiasing)
- func draw_line(surf:RID, hex1:Vector2, hex2:Vector2, color:Color, width=1.0, antialiasing=false):
- var p1 = hex2pixel(hex1)
- var p2 = hex2pixel(hex2)
- VisualServer.canvas_item_add_line(surf, p1, p2, color, width, antialiasing)
- func draw_polyline(surf:RID, hexes:PoolVector2Array, color:Color, width=1.0, antialiasing=false):
- if len(hexes) < 2: return
- var points = PoolVector2Array()
- for i in hexes:
- points.append(hex2pixel(i))
- VisualServer.canvas_item_add_polyline(surf, points, [color], width, antialiasing)
- # ###########################################
- # _____CALCULATING______
- # Here are functions for calculate several
- # types of stuff
- # ###########################################
- func _get_vert_hex_vertices(hex:Vector2) -> PoolVector2Array:
- var pixel = hex2pixel(hex)
- return PoolVector2Array([
- pixel+2*grid_basis.x,
- pixel+grid_basis.x+grid_basis.y,
- pixel-grid_basis.x+grid_basis.y,
- pixel-2*grid_basis.x,
- pixel-grid_basis.x-grid_basis.y,
- pixel+grid_basis.x-grid_basis.y
- ])
- func _get_hor_hex_vertices(hex:Vector2) -> PoolVector2Array:
- var pixel = hex2pixel(hex)
- return PoolVector2Array([
- pixel+grid_basis.x-grid_basis.y,
- pixel+grid_basis.x+grid_basis.y,
- pixel+2*grid_basis.y,
- pixel-grid_basis.x+grid_basis.y,
- pixel-grid_basis.x-grid_basis.y,
- pixel-2*grid_basis.y,
- ])
- func _get_hor_hex_map_center() -> Vector2:
- return Vector2(int((hex_map_size.x-1)/2), hex_map_size.x-1)
- func _get_vert_hex_map_center() -> Vector2:
- return Vector2(hex_map_size.x-1, int((hex_map_size.x-1)/2))
- func _is_in_hex_grid(hex):
- var center = _get_hor_hex_map_center()
- hex -= center
- return hex_distance(center, hex) < hex_map_size.x
- func _in_rect_grid_hor(hex:Vector2) -> bool:
- return hex.x >= -floor(hex.y/2) and hex.x < hex_map_size.x-ceil(hex.y/2) and hex.y < hex_map_size.y and hex.y >= 0
- func _in_rect_grid_vert(hex:Vector2) -> bool:
- return hex.x >= 0 and hex.x < hex_map_size.x and hex.y >= -floor(hex.x/2) and hex.y < hex_map_size.y-ceil(hex.x/2)
- # ###########################################
- # _____DRAWING_________
- # Here are functions for drawing several
- # types of content
- # ###########################################
- func _draw_hor_hex(hex:Vector2, surf:RID, color:Color, width=1.0, antialiasing=false):
- var points = _get_hor_hex_vertices(hex)
- points.append(points[0])
- VisualServer.canvas_item_add_polyline(surf, points, [color], width, antialiasing)
- func _draw_vert_hex(hex:Vector2, surf:RID, color:Color, width=1.0, antialiasing=false):
- var points = _get_vert_hex_vertices(hex)
- points.append(points[0])
- VisualServer.canvas_item_add_polyline(surf, points, [color], width, antialiasing)
- func _fill_hor_hex(hex:Vector2, surf:RID, color:Color, antialiasing=false):
- var points = _get_hor_hex_vertices(hex)
- VisualServer.canvas_item_add_polygon(surf, points, [color], [], RID(), RID(), antialiasing)
- func _fill_vert_hex(hex:Vector2, surf:RID, color:Color, antialiasing=false):
- var points = _get_vert_hex_vertices(hex)
- VisualServer.canvas_item_add_polygon(surf, points, [color], [], RID(), RID(), antialiasing)
- func _draw_vert_rect_grid(surf:RID, color:Color, width=1.0, antialiasing=false):
- var offset = grid_basis.x*2+grid_basis.y
- # Drawing horizontal lines
- for i in range(1, grid_map_size.x, 3):
- for j in range(1-i%2, grid_map_size.y+1, 2):
- VisualServer.canvas_item_add_line(surf, grid_basis.x*i+grid_basis.y*j-offset, grid_basis.x*(i+2)+grid_basis.y*j-offset, color, width, antialiasing)
- # Drawing vertices
- for i in range(0, grid_map_size.x, 3):
- for j in range(grid_map_size.y):
- if int(hex_map_size.x)%2 == 1 or not(i == grid_map_size.x-1 and (j == 0 or j == grid_map_size.y-1)):
- if j%2 == i%2:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(i+1)+grid_basis.y*j-offset, grid_basis.x*i+grid_basis.y*(j+1)-offset, color, width, antialiasing)
- else:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*i+grid_basis.y*j-offset, grid_basis.x*(i+1)+grid_basis.y*(j+1)-offset, color, width, antialiasing)
- func _draw_hor_rect_grid(surf:RID, color:Color, width=1.0, antialiasing=false):
- var offset = grid_basis.x+grid_basis.y*2
- # Drawing vertical lines
- for i in range(1, grid_map_size.y, 3):
- for j in range(1-i%2, grid_map_size.x+1, 2):
- VisualServer.canvas_item_add_line(surf, grid_basis.x*j+grid_basis.y*i-offset, grid_basis.x*j+grid_basis.y*(i+2)-offset, color, width, antialiasing)
- # Drawing vertices
- for i in range(0, grid_map_size.y, 3):
- for j in range(grid_map_size.x):
- if int(hex_map_size.y)%2 == 1 or not (i == grid_map_size.y-1 and (j == 0 or j == grid_map_size.x-1)):
- if i%2 == j%2:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*j+grid_basis.y*(i+1)-offset, grid_basis.x*(j+1)+grid_basis.y*i-offset, color, width, antialiasing)
- else:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*j+grid_basis.y*i-offset, grid_basis.x*(j+1)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- func _draw_hor_hex_grid(surf:RID, color:Color, width=1.0, antialiasing=false):
- var parity = int(hex_map_size.x)%2
- var offset = grid_basis.x+grid_basis.y*2 + grid_basis.x*(1-parity)
- var start
- for i in range(0, grid_map_size.y/2, 3): # Drawing vertices
- start = hex_map_size.x - i/3 - 1
- for j in range(start, grid_map_size.x/2):
- if abs(i%2 - j%2) != parity:
- # Down diagonal
- VisualServer.canvas_item_add_line(surf, grid_basis.x*j+grid_basis.y*(i+1)-offset, grid_basis.x*(j+1)+grid_basis.y*i-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(i+1)-offset, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*i-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*j+grid_basis.y*(grid_map_size.y-i-1)-offset, grid_basis.x*(j+1)+grid_basis.y*(grid_map_size.y-i)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(grid_map_size.y-i-1)-offset, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(grid_map_size.y-i)-offset, color, width, antialiasing)
- else:
- # Top diagonal
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(j)+grid_basis.y*(i)-offset, grid_basis.x*(j+1)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(i)-offset, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(j)+grid_basis.y*(grid_map_size.y-i)-offset, grid_basis.x*(j+1)+grid_basis.y*(grid_map_size.y-i-1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(grid_map_size.y-i)-offset, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(grid_map_size.y-i-1)-offset, color, width, antialiasing)
- for i in range(1, grid_map_size.y, 3):
- if i <= grid_map_size.y/2:
- start = hex_map_size.x-1 - i/3
- else:
- start = (i-grid_map_size.y/2)/3
- for j in range(abs(parity-i%2), grid_map_size.x+1, 2):
- if j >= start and j <= grid_map_size.x-start:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*j+grid_basis.y*i-offset, grid_basis.x*j+grid_basis.y*(i+2)-offset, color, width, antialiasing)
- func _draw_vert_hex_grid(surf:RID, color:Color, width=1.0, antialiasing=false):
- var parity = int(hex_map_size.x)%2
- var offset = grid_basis.x*2+grid_basis.y + (1-parity)*grid_basis.y
- var start
- for j in range(0, grid_map_size.x/2, 3): # Drawing vertices
- start = hex_map_size.x - j/3 - 1
- for i in range(start, grid_map_size.y/2):
- if abs(i%2 - j%2) != parity:
- # Down diagonal
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(j+1)+grid_basis.y*(i)-offset, grid_basis.x*(j)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(i)-offset, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(j+1)+grid_basis.y*(grid_map_size.y-i)-offset, grid_basis.x*(j)+grid_basis.y*(grid_map_size.y-i-1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(grid_map_size.y-i)-offset, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(grid_map_size.y-i-1)-offset, color, width, antialiasing)
- else:
- # Top diagonal
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(j)+grid_basis.y*(i)-offset, grid_basis.x*(j+1)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(i)-offset, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(i+1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(j)+grid_basis.y*(grid_map_size.y-i)-offset, grid_basis.x*(j+1)+grid_basis.y*(grid_map_size.y-i-1)-offset, color, width, antialiasing)
- VisualServer.canvas_item_add_line(surf, grid_basis.x*(grid_map_size.x-j)+grid_basis.y*(grid_map_size.y-i)-offset, grid_basis.x*(grid_map_size.x-j-1)+grid_basis.y*(grid_map_size.y-i-1)-offset, color, width, antialiasing)
- for i in range(1, grid_map_size.x, 3):
- if i <= grid_map_size.x/2:
- start = hex_map_size.x-1 - i/3
- else:
- start = (i-grid_map_size.x/2)/3
- for j in range(abs(parity-i%2), grid_map_size.y+1, 2):
- if j >= start and j <= grid_map_size.y-start:
- VisualServer.canvas_item_add_line(surf, grid_basis.x*i+grid_basis.y*j-offset, grid_basis.x*(i+2)+grid_basis.y*(j)-offset, color, width, antialiasing)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement