最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

game development - Point-and-Click movement within a tilemap - Stack Overflow

programmeradmin3浏览0评论

I'm trying to learn how to set up an isometric point-and-click game. I have a ChacterBody2D that moves towards wherever the user clicks, and a tilemap with some tiles placed around.

How do I code it so the player only moves if the user has clicked on a valid tile? And to prevent the user from flying across void spaces?

Player Movement Script

extends CharacterBody2D

@export var speed = 400

var target

func _ready():
    target = global_position

func _input(event):
    if event is InputEventMouseButton and event.pressed:
        target = get_global_mouse_position()
        print(event)

func _physics_process(delta):
    velocity = global_position.direction_to(target) * speed
    if global_position.distance_to(target) > 10:
        move_and_collide(velocity * delta)

Thank you!

I'm trying to learn how to set up an isometric point-and-click game. I have a ChacterBody2D that moves towards wherever the user clicks, and a tilemap with some tiles placed around.

How do I code it so the player only moves if the user has clicked on a valid tile? And to prevent the user from flying across void spaces?

Player Movement Script

extends CharacterBody2D

@export var speed = 400

var target

func _ready():
    target = global_position

func _input(event):
    if event is InputEventMouseButton and event.pressed:
        target = get_global_mouse_position()
        print(event)

func _physics_process(delta):
    velocity = global_position.direction_to(target) * speed
    if global_position.distance_to(target) > 10:
        move_and_collide(velocity * delta)

Thank you!

Share Improve this question edited Feb 15 at 0:09 DarkBee 15.6k8 gold badges72 silver badges116 bronze badges asked Feb 14 at 23:59 Samuel ShumakeSamuel Shumake 213 bronze badges 2
  • Is player movement constrained to an isometric grid, or can they move freely (as long as there are valid tiles below them)? – liggiio Commented Feb 15 at 12:15
  • Free movement! I believe I figured this out. I was having trouble adding a reference to the tilemaplayer node, but once I got that done using map = get_node("/root/Node2D/TileMapLayer") and var mouse_pos = get_global_mouse_position() var cell_coord = map.local_to_map(mouse_pos) – Samuel Shumake Commented Feb 16 at 15:52
Add a comment  | 

3 Answers 3

Reset to default 0

I was able to get this working using get_node() to find the TileMapLayer. For some reason, the normal reference wasn't working but this worked for me

extends CharacterBody2D


@export var speed = 200
var target
var map

func _ready():
    target = global_position
    map = get_node("/root/Node2D/TileMapLayer") 

func _input(event):
    if event is InputEventMouseButton and event.pressed:
        var mouse_pos = get_global_mouse_position()
        var cell_coord = map.local_to_map(mouse_pos)
        print(cell_coord)
        if (map.get_cell_tile_data(cell_coord)): # If null tile or not
            target = mouse_pos
        

func _physics_process(delta):
    velocity = global_position.direction_to(target) * speed
    if global_position.distance_to(target) > 10:
        move_and_collide(velocity * delta)

You are working with a TileMap, composed of a TileSet composed of "many little pieces". Every piece of your tileset is basically a "piece repeated a certain amount of times". Since Godot 4.0 you can use scenes as tiles. I didn't test this, but if u can use scenes then you can attach script to them. This means that you can send signals from childs to father. So your code could seem just like this.

In Tile.gd

signal pressed_on_me(my_coordinates)
...
if event is InputEventMouseButton and event.pressed:
    pressed_on_me.emit(my_coordinates)

In father.gd (which can be map2 or TileMapLayer, depends what you prefer)

func _on_pressed_on_me(my_coordinates):
    // move action...

In this way:

  • If u press in a non-valid tile, nothing happens because no signal will be emitted
  • A tile has a specific coordinate, so you don't have to check for non-valid input
  • You separate actions, so if in a future u want to add "special tiles" (lava tiles, water tiles....) you can just configure your tile to have a different speed/effect without touching too much code (or at least you are gonna "touch less your code" than creating something monholitic).

Hope this helps. Greetings

extends CharacterBody2D

@onready var map: TileMapLayer = get_parent().get_node("TileMapLayer")


func _physics_process(_delta: float) -> void:
    if Input.is_action_just_pressed("left_click"):
        var mouse_position := get_global_mouse_position()

        if is_cell_valid(mouse_position):
            # Here, write code to move code to the desired block
            pass
        

func is_cell_valid(mouse_position: Vector2) -> bool:
    var grid_position := map.local_to_map(mouse_position)

    if map.get_cell_source_id(grid_position) == -1:
        return false

    return true
发布评论

评论列表(0)

  1. 暂无评论