Godot:如何将玩家的移动限制为仅某些图块?

问题描述 投票:1回答:1

我正在尝试创建'Stone Age'克隆。而且我正在尝试找到一种方法来将玩家的运动限制在某些范围内。意味着玩家只能在某些图块上移动。

到目前为止,我所做的是制作两个TileMap,一个用于“可行走的地板”,另一个用于“不可行走的地板”。我将它们放在不同的碰撞层上,我的播放器仅与“不可行走的地板”碰撞。因此,玩家无法进入:此处(https://i.imgur.com/sPGCS0V.png):步行地板为棕色瓷砖,步行地板为'FLOOR'。

此方法是个问题,因为我有要移动播放器的平台。 (上面有箭头的磁贴)但是,如果所有背景都无法行走,则我的玩家在平台上时会与它发生碰撞,因此他将无法使用平台移动...

有更好的方法吗?

game-engine godot
1个回答
1
投票

我在this指南中找到了一种解决方案,并对其进行了少许修改。简而言之,解决方案是在运动方向上使用ray-cast,并查看是否存在碰撞。

[我所做的是创建一个tilemap,并将所有允许玩家移动的tile称为'walkable_ [something]'。在播放器脚本中,我从射线投射中检测到碰撞,我检查了光线投射与之碰撞的瓦片的名称。如果名称以“ walkable”开头,则允许移动,在所有其他情况下,我不允许移动。

onready var ray = $RayCast2D

var speed = 256 # big number because it's multiplied by delta
var tile_size = 64 # size in pixels of tiles on the grid

var last_position = Vector2() # last idle position
var target_position = Vector2() # desired position to move towards
var movedir = Vector2() # move direction

func _process(delta):
    # MOVEMENT
    if ray.is_colliding():
        var collision = ray.get_collider()
        if collision is TileMap:
            var tile_name = get_tile(collision)     
            if !(tile_name.begins_with("Walkable")):                
                position = last_position
                target_position = last_position
            else:
                position += speed * movedir * delta

                if position.distance_to(last_position) >= tile_size - speed * delta: # if we've moved further than one space
                    position = target_position # snap the player to the intended position


    else:
        position += speed * movedir * delta

        if position.distance_to(last_position) >= tile_size - speed * delta: # if we've moved further than one space
            position = target_position # snap the player to the intended position

这是get_tile()函数,它获取与光线投射碰撞的图块的字符串名称。因为光线碰撞返回了whole贴图,所以我们需要知道与哪个特定的贴图发生碰撞。因此,我使用了播放器的位置+射线投射矢量的方向来找出正确的图块。首先,我将图块宽度和高度增加了一半,因为播放器位置被视为播放器节点的左上角。例如,如果玩家是一个2x2大小的正方形,并且他位于(0,0)上。这意味着它的左上角在0,0上。这意味着1,1是正方形的中心。

func get_tile(tile_map):    
    if tile_map is TileMap:
        var v = Vector2(tile_size / 2 , tile_size /2)
        var tile_pos = tile_map.world_to_map(position + v + ray.cast_to)
        var tile_id = tile_map.get_cellv(tile_pos)
        if (tile_id == -1):
            return "None"
        else:
            return tile_map.tile_set.tile_get_name(tile_id)

为了完整起见,here是完整播放器脚本的粘贴框。

© www.soinside.com 2019 - 2024. All rights reserved.