Диагональное движение, приводящее к недостаткам рисования карты

Я смогла хорошо разобраться в том, что происходит и убивает меня в течение нескольких недель, и я действительно хотела знать, была ли это моя ошибка, или просто слишком быстрое нажатие клавиш или задержка рендеринга? иметь дело с проблемой, потому что я не нашел виновника для этого.

Это происходит, когда, например, я иду по диагонали вниз и вправо, а затем вправо, затем я возвращаюсь вниз, я делаю такие ходы, быстро, это не всегда происходит, но достаточно, чтобы нарушить игру.

Скрипт движения:

extends KinematicBody2D

var velocity = 150
var direction = Vector2()

func _ready():
    set_fixed_process(true)

func _fixed_process(delta):
#-----------MOVIMENT-------------------------------
    direction = Vector2()
    #LEFT
    if Input.is_action_pressed("left"):
        direction += Vector2(-1, 0)
    #RIGHT
    elif Input.is_action_pressed("right"):
        direction += Vector2(1, 0)
    #UṔ
    if Input.is_action_pressed("up"):
        direction += Vector2(0, -1)
    #DOWN
    elif Input.is_action_pressed("down"):
        direction += Vector2(0, 1)

    if direction.x != 0 || direction.y != 0:
        direction = direction.normalized()*velocity
        move(direction*delta)

Сценарий рисования:

extends Control

var map_size = 64
var preScriptUtils = preload("res://scripts/utils_fuctions.gd")
var utils_functions

onready var player = $"../Player"
onready var tile_map = $"../TileMap"
var posTileMap = Vector2()
var posWorld = Vector2()
var prevRect = Rect2()
var newRect = Rect2()

var distance_gen = 2048
var positionMap_rect = 0
var size_rectMap = 0

func _ready():
    utils_functions = preScriptUtils.utils_functions.new()
    set_fixed_process(true)
    posWorld = Vector2(0, 0)
    positionMap_rect = ((distance_gen/32)/2)
    size_rectMap = distance_gen/32
    surround_map(posWorld)

func _fixed_process(delta):
    var posPlayer = player.get_position()

    posTileMap = tile_map.world_to_map(posPlayer) - Vector2(positionMap_rect, positionMap_rect)
    newRect = Rect2(tile_map.map_to_world(posTileMap), Vector2(distance_gen, distance_gen))
    if prevRect.position != newRect.position:
        load_newMap()

func gen_data(var _posWorld=Vector2(0, 0), var _posTileMap=Vector2(0, 0), var size=Vector2(0, 0)):
    var x = 0
    var y = 0
    var pos_modx = 0
    var pos_mody = 0
    while  x < size.x:
        y = 0
        pos_modx = utils_functions.mod(_posWorld.x + x, map_size)
            #NOISE
            var result_noise
        while y < size.y:
            pos_mody = utils_functions.mod(_posWorld.y + y, map_size)
            if (pos_modx >= 0 && pos_mody >= 0) && (pos_modx < map_size && pos_mody < map_size):
                tile_map.set_cell(_posTileMap.x + x, _posTileMap.y + y, biomes(result_noise))
            y += 1
        x += 1

func load_newMap():
    var rectIntersection = newRect.clip(prevRect)
    var _x = 0
    var _y = 0
    #LEFT
    if player.direction.x < 0:
        if int((newRect.size.x - rectIntersection.size.x)/32) == 1:
            _x = int(newRect.position.x/32)
            _y = int(rectIntersection.position.y/32)
            posWorld.x -= 1
            gen_data(Vector2(posWorld.x, posWorld.y), Vector2(_x, _y), Vector2(1, size_rectMap))
    #RIGHT
    elif player.direction.x > 0:
        if int((newRect.size.x - rectIntersection.size.x)/32) == 1:
            _x = int(rectIntersection.end.x/32)
            _y = int(rectIntersection.position.y/32)
            posWorld.x += 1
            Vector2(_x, _y)
            gen_data(Vector2(posWorld.x - 1, posWorld.y), Vector2(_x, _y), Vector2(1, size_rectMap))
    #UP
    if player.direction.y < 0:
        if int((newRect.size.y - rectIntersection.size.y)/32) == 1:
            _x = int(newRect.position.x/32)
            _y = int(newRect.position.y/32)
            posWorld.y -= 1
            gen_data(Vector2(posWorld.x, posWorld.y), Vector2(_x, _y), Vector2(size_rectMap, 1))
    #DOWN
    elif player.direction.y > 0:
        if int((newRect.size.y - rectIntersection.size.y)/32) == 1:
            _x = int(rectIntersection.position.x/32)
            _y = int(rectIntersection.end.y/32)
            posWorld.y += 1
            gen_data(Vector2(posWorld.x, posWorld.y - 1), Vector2(_x, _y), Vector2(size_rectMap, 1))
    prevRect = newRect

func surround_map(var _posWorld=Vector2(0, 0)):
    posTileMap = - Vector2(positionMap_rect, positionMap_rect)
    prevRect = Rect2(tile_map.map_to_world(posTileMap), Vector2(distance_gen, distance_gen))
    gen_data(_posWorld, Vector2(-32, -32), Vector2(64, 64))

Не суетитесь с кодами, это очень просто, что я пытаюсь сделать, я хочу переместить игрока, пока я генерирую свой мир, он отлично работает в 4 направлениях, но когда он включает диагонали, он не идет как и ожидалось. Я рисую вот так, у меня есть две линии, которые я сравниваю с каждым кадром, я беру ретагунло перехвата и вычисляю, где мне следует рисовать или стирать.

Видео о том, что происходит:

http://www.dailymotion.com/video/x6286px

Но есть эти недостатки не только при слишком быстром нажатии, но и при медленном движении, когда по диагонали вниз-вправо, а затем влево или вправо-влево и затем назад-вправо, перемещение по диагонали, кажется, является проблемой, я Я перепробовал много фигур, у меня почти записная книжка, я все набросал, пытаясь это выяснить, я тоже попробовал с диагональными проверками и получаю тот же результат, сегодня я потерял еще один день, и он не покидает место, я недели, как это, когда я думаю, что я это исправил, не совсем.

Я использую Годо.

До 1:

С ответом @Ryan1729 я понял, что на самом деле думал не так, но пытаюсь исправить свою логику, выполнив что-то вроде ниже, и ошибка продолжается, я запутался:

if direction.x != 0 || direction.y != 0:
        var vetor_normalized = direction.normalized()
        if abs(vetor_normalized.x) < 1 && abs(vetor_normalized.y) < 1:
            var vx = Vector2(direction.x, 0)
            var vy = Vector2(0, direction.y)
            vx = vx.normalized()*velocity
            move(vx*delta)
            vy = vy.normalized()*velocity
            move(vy*delta)

        else:
            direction = direction.normalized()*velocity
            move(direction*delta)

Up2:

Сейчас я так и сделал, кажется, что исправил недостатки, но появились другие, которых я до сих пор не понимаю, этот вопрос 0 слишком меня смущает.

  var oldPosWorld = Vector2(0, 0)
  var rect_tileMap = Vector2(-32, -32) 

func load_newMap():
 var posPlayer = Vector2(int(player.get_position().x/32), int(player.get_position().y/32))
    #LEFT
    if posPlayer.x < oldPosWorld.x:
            pos_tileMap.x -= 1
            posWorld.x -= 1
            gen_data(Vector2(posWorld.x, posWorld.y), Vector2(pos_tileMap.x, pos_tileMap.y), Vector2(1, size_rectMap))
    #RIGHT
    elif posPlayer.x > oldPosWorld.x:
            pos_tileMap.x += 1
            posWorld.x += 1
            gen_data(Vector2(posWorld.x - 1, posWorld.y), Vector2(pos_tileMap.x + 63, pos_tileMap.y), Vector2(1, size_rectMap))
    #UP
    if posPlayer.y < oldPosWorld.y:
            pos_tileMap.y -= 1
            posWorld.y -= 1
            gen_data(Vector2(posWorld.x, posWorld.y), Vector2(pos_tileMap.x, pos_tileMap.y), Vector2(size_rectMap, 1))
    #DOWN
    elif posPlayer.y > oldPosWorld.y:
            pos_tileMap.y += 1
            posWorld.y += 1
            gen_data(Vector2(posWorld.x, posWorld.y - 1), Vector2(pos_tileMap.x, pos_tileMap.y + 63), Vector2(size_rectMap, 1))

oldPosWorld = posPlayer

Движения вправо и внизу правы, проблема в том, что слева и выше остаются левые над этим пустым пространством (то есть, с негативами).

Если я поставлю x - 1 слева, чтобы решить проблему, это произойдет со мной:

Я решил это, изменив:

var posPlayer = Vector2(int(player.get_position().x/32), int(player.get_position().y/32))

проверками вроде этого:

if ((player.get_position().x)/32)

но теперь я получаю это, перейдя в стороны, а затем вверх:

Up 3:

Я не собираюсь обращать на это внимание, чтобы не расстраиваться, если я ошибаюсь, но по результатам тестов неудача прекратилась. Код выглядел бы так, если присваивать int (player.get_position (). X / 32) отдельно для oldPosWorld.x, в том числе и для y, поскольку до того, как я назначил позицию игроку только один раз для переменной postPlayer, вызвал ошибки, когда вы вошли вверх-вниз, если, как это было до сих пор с предыдущей позицией х, при этом все обновляется в нужное время.

еще так налево и вверх

Я не совсем понимаю, почему, и, честно говоря, не так скоро я узнаю, я слишком устал, чтобы смотреть на это. Но я хотел бы понять, чтобы не ошибаться. Помимо этого, это, кажется, происходит сейчас, как и ожидалось.

#LEFT
if int(player.get_position().x/32) < oldPosWorld.x:
            rect_tileMap.x -= 1
            posWorld.x -= 1
            gen_data(Vector2(posWorld.x, posWorld.y), Vector2(rect_tileMap.x, rect_tileMap.y), Vector2(1, size_rectMap))
            oldPosWorld.x = int(player.get_position().x/32)

2 ответа

Я думаю, что проблема в том, что вам нужно дискретное движение (перемещение вверх и вправо на 1 вверх и 1 вправо), но вы нормализуете вектор до длины 1 в первом фрагменте кода. В недиагональных случаях это ничего не делает, потому что векторы уже имеют длину 1. Но в диагональных случаях вектор есть длина sqrt(2) до нормализации, (вы можете использовать теорему Пифагора, чтобы показать это.) Таким образом, ваш вектор сокращается до чего-то вроде Vector2(sqrt(2)/2, sqrt(2)/2)), (sqrt(2)/2 составляет около 0,707,), что вызывает смещение картины.

Редактировать: мое лучшее предположение сейчас, что проблема в том, что вы звоните gen_data дважды, когда игрок движется по диагонали. Я думаю, что вы хотите выяснить смещения x и y, а затем перерисовать карту.

Подводя итог, ошибка была в обновлении (которое в данном случае было бы oldPosWorld), потому что они были двумя блоками if, я бы вводил один за другим и, не обновляя позицию, рисует неправильный путь, потому что он находится в поздней позиции:

Видео работает:

http://www.dailymotion.com/video/x62e6l9

Другие вопросы по тегам