|
|
|
|
Reply From: |
pospathos |
In my opinion you should devide space in grid cells to simulate 8 dir movement, and move from cell to cell (not actual TileMap just virtual grid space for movement, if you already dont use TileMap for level, if you do then things are easier). Cell size is dependent of how granular you want 8dir movement to be (or if you use TileMap in game you should use cell size of TileMap). Devide your start and goal position by cell size so you get start and goal cell positions, and use some of line algorithms ( Line drawing on a grid ) to store grid points of a line deffned by start and goal in array. Then you need to move from one array index to another (multiply cell positions by cell size to get actual pixel position) until you reach the last one. If you need to land exactly on goal point you should replace last cell position from line array with your goal position and move there. Hope it helps.
Two line algorithms:
static func WalkGrid( p0 : Vector2, p1 : Vector2) -> Array:
var dx = p1.x - p0.x
var dy = p1.y - p0.y
var nx = abs(dx)
var ny = abs(dy)
var signX = 1 if dx > 0 else -1
var signY = 1 if dy > 0 else -1
var p : Vector2 = p0 # Point to walk on grid. set it to Start point
var points : Array = [p] # Add Start position to array
var ix : int = 0
var iy : int = 0
while ix < nx || iy < ny:
if ( ( 1 + ( ix << 1) ) * ny < ( 1 + ( iy << 1) ) * nx ):
p.x += signX
ix +=1
else:
p.y += signY
iy += 1
points.append(p)
return points
static func BresenhamLine(p0 : Vector2, p1 : Vector2):
var s = Vector2()
var dx = abs(p1.x-p0.x); s.x = 1 if p0.x<p1.x else -1
var dy = abs(p1.y-p0.y); s.y = 1 if p0.y<p1.y else -1
var err = (dx if dx>dy else -dy)/3
var e2
var points = []
while true:
points.append(p0)
if p0.x == p1.x && p0.y == p1.y:
break
e2 = err
if e2 > -dx:
err -= dy
p0.x += s.x
if e2 < dy:
err +=dx
p0.y += s.y
return points
pospathos | 2018-12-04 07:48
Thanks for the suggestions!
The TileMap solved half of my problems. With grid on board I was able to smooth the moving.
You and the commenter suggested using line/pathfinding algorithms and that’s the thing I want to avoid.
What I came with is:
var target_pos = Vector2()
var unit_pos = Vector2()
var speed = 100
func _input(event):
if event.is_action_released("rmb"):
target_pos = get_global_mouse_pos().snapped(Vector2(64,64))
func _process(delta):
if target_pos.x-unit_pos.x < 0:
set_pos(get_pos()+Vector2(-1,0)*speed*delta)
if target_pos.x-unit_pos.x > -1:
set_pos(get_global_pos().snapped(Vector2(64,0)))
if target_pos.x-unit_pos.x > 0:
set_pos(get_pos()+Vector2(1,0)*speed*delta)
if target_pos.x-unit_pos.x < 1:
set_pos(get_global_pos().snapped(Vector2(64,0)))
if target_pos.y-unit_pos.y < 0:
set_pos(get_pos()+Vector2(0,-1)*speed*delta)
if target_pos.y-unit_pos.y > -1:
set_pos(get_global_pos().snapped(Vector2(0,64)))
if target_pos.y-unit_pos.y > 0:
set_pos(get_pos()+Vector2(0,1)*speed*delta)
if target_pos.y-unit_pos.y < 1:
set_pos(get_global_pos().snapped(Vector2(0,64)))
if abs(target_pos.x-unit_pos.x) < 1 and abs(target_pos.y-unit_pos.y) < 1:
set_pos(target_pos)
unit_pos = get_global_pos()
Now, if someone could tell if it’s Godot-proper?
It seem to be ok, at least your idea. One question, I am curious: why do you need to simulate 8 dir movement? You can just change appropriate sprite animation direction depending of vector of movement and use Godot’s Navigation2D/NavigationPolygon for movement of units (even on individual tiles you can set NavigationPolygon).
pospathos | 2018-12-05 18:10
Warcraft didn’t used anything as elaborate as Navigation nodes provides.
It’s AI was because of this really bad, and I want to achieve something similar in terms of clunkiness.
Also I don’t want to use pre-calculated lines, paths etc, to make it even more stupid.