0 votes

Hi Godot Experts, I am relatively new to Godot and I am having an issue with random character movement on an isometric plane.

I am attempting to recreate an old game I used to play called Ninja Farm that was unfortunately deleted by the developers.

Image Reference

I would like for the ninjas (AI) to randomly move around the scene while staying within the borders of the isometric view. They will then stay in that position for a few seconds, then move in another random direction to create the effect of wandering. Any idea on how to approach this?, I have looked up previous forums and videos but none seem to be relevant to the random movement within borders.

The tilemap I am using for the ground is in isometric view and each tile is 32x16. The area of which I would like the AI to be able to move is 15 tiles by 15 tiles - a square.

Thank you for taking the time to read this. If any more information is required, please ask, thanks.

Godot version 3.2.3.stable
in Engine by (25 points)

1 Answer

+1 vote
Best answer

AStar path finding is going to be your best most performant option here, a video about it can be found here : https://www.youtube.com/watch?v=Ad6Us73smNs

Here is some code that does generally what you want. Note that it does not account for two characters attempting to move to the same grid position at the same time.

extends KinematicBody2D

var move_timer : Timer
var can_move = true
var world_destination = null
var speed = 25
var velocity_vector = Vector2.ZERO

func _ready() -> void:
    move_timer = Timer.new()
    move_timer.one_shot = true
    move_timer.wait_time = 3
    move_timer.connect("timeout", self, "_on_move_timer_timeout")
    self.add_child(move_timer)

func _physics_process(delta: float) -> void:
    if world_destination:
        move_towards_world_destination(delta)
    elif can_move:
        set_world_destination()

func move_towards_world_destination(delta):
    # move towards world_destination in sync with physics step
    var direction_vector = self.position.direction_to(world_destination).normalized()
    velocity_vector = move_and_slide(velocity_vector + (direction_vector * speed * delta))

    # arrived at world_destination
    if abs(self.position.distance_to(world_destination)) < 0.05:
        # snap our position to world_destination to avoid any funny business
        self.position = world_destination
        world_destination = null
        velocity_vector = Vector2.ZERO
        can_move = false
        move_timer.start()

func set_world_destination():
    var move_directions = [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT]
    var current_grid_position = get_current_grid_position()
    randomize()
    # set a random adjacent tile to our potential_grid_position 
    var potential_grid_position = current_grid_position + move_directions[randi() % move_directions.size()]

    # make sure we select a tile within our wonder zone
    while not is_inside_wander_zone(potential_grid_position):
        randomize()
        potential_grid_position = current_grid_position + move_directions[randi() % move_directions.size()]

    # set our world_destination
    world_destination = get_world_position_from_grid_position(potential_grid_position)

func is_inside_wander_zone(grid_position):
    # here is where you can define the grid coordinates of your wander zone
    var wander_zone_start = Vector2(0,0)
    var wander_zone_end = Vector2(15,15)
    var inside_wander_zone = false
    if wander_zone_start.x <= grid_position.x and grid_position.x <= wander_zone_end.x:
        if wander_zone_start.y <= grid_position.y and grid_position.y <= wander_zone_end.y:
            inside_wander_zone = true
    return inside_wander_zone

# here is where you would need to translate self.position to a grid position
func get_current_grid_position():
    var some_translation
    var current_grid_position = self.position * some_translation
    return current_grid_position

# here is here you would need to translate a grid position to a world position
func get_world_position_from_grid_position(grid_position):
    var some_translation
    var current_world_position = grid_position * some_translation
    return current_world_position

# when our timer times out we can move again
func _on_move_timer_timeout():
    can_move = true
by (2,222 points)
selected by
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.