在移动或调整元素大小时,定位会出错

编程语言 2026-07-11

我一直在研究一种“进化式”的井字棋游戏,它在一个7x7的棋盘上进行,并且有额外的功能和规则来适应。起初我把它做成一个小窗口(1450 x 1018),但现在在移到其他事情之前,我想把分辨率改成4K,或者至少保持16:9的纵横比。问题在于,当前我的实现方式是井字棋的网格只是一个图像,通过一些代码来在图像上找到放置X或O记号的正确位置(也许这并不最优,但现在如果可以的话我想保持这种方式)。现在为了让每位玩家都能在同一台电脑上控制,O玩家用鼠标点击网格来放置O,而X玩家用方向键控制一个光标。但是每当我尝试移动或调整棋盘图像的大小时,仍然只能在棋盘原来的位置放置两种记号和X玩家的光标,仿佛在那儿还有一个看不见的棋盘。我猜这跟它想要在原点和局部位置等方面有关,但我不知道该如何修复。

下面是与标记如何被放置相关的代码(注意handle_move那段,有大量与棋规相关的逻辑我做了裁剪,那里保留的代码与放置记号直接相关):

func _ready() -> void:
    boardSize = $Board.get_rect().size.x
    cellSize = boardSize/7.0

    #Create a Node2D container for Player 2's cursor
    cursorMarker = Node2D.new()
    cursorMarker.name = "CursorMarker"
    add_child(cursorMarker)

    #Create a 1x1 yellow image
    var img := Image.create(1, 1, false, Image.FORMAT_RGBA8)
    img.set_pixel(0, 0, Color(1.0, 1.0, 0.0, 0.471))

    #Make a texture from that image
    var tex := ImageTexture.create_from_image(img)

    #Create a sprite to display it
    var spr := Sprite2D.new()
    spr.texture = tex
    spr.centered = false                     # top-left corner aligns with cell
    spr.scale = Vector2(cellSize, cellSize)  # scale 1×1px up to a full cell
    cursorMarker.add_child(spr)

    updateCursorPosition()
func _input(event):
    #Player 1 input with the mouse
    if event is InputEventMouseButton:
        if event .button_index == MOUSE_BUTTON_LEFT and event.pressed:
            #Check if mouse is on the game board
            if event.position.x < boardSize:
                #Convert mouse position into grid location
                gridPos = Vector2i(event.position / cellSize)
                handle_move(1, gridPos)
    #Player 2 input with arrow keys and Enter
    if event is InputEventKey and event.pressed:
        match event.keycode:
                KEY_UP:
                    player2Cursor.y = max(player2Cursor.y - 1, 0)
                    updateCursorPosition()
                KEY_DOWN:
                    player2Cursor.y = min(player2Cursor.y + 1, 6)
                    updateCursorPosition()
                KEY_LEFT:
                    player2Cursor.x = max(player2Cursor.x - 1, 0)
                    updateCursorPosition()
                KEY_RIGHT:
                    player2Cursor.x = min(player2Cursor.x + 1, 6)
                    updateCursorPosition()
                KEY_ENTER, KEY_KP_ENTER:
                    if canPlace2:
                        handle_move(-1, player2Cursor)
#Runs when Player 1 or 2 tries to make an input
func handle_move(currentPlayer: float, gridPos: Vector2i) -> void:

    ...
    #If the spot is empty, or if it contains the other Player's symbol and the current Player can replace it
            gridData[gridPos.y][gridPos.x] = currentPlayer #Put a 1 or -1 in the corresponding 2D array spot
            var target = gridPos * cellSize + Vector2i(cellSize / 2, cellSize / 2) #Get the location on the image

            #Clear existing markers if replacing
            for cross in get_tree().get_nodes_in_group("crosses"):
                if cross.position == Vector2(target):
                    cross.queue_free()
            for circle in get_tree().get_nodes_in_group("circles"):
                if circle.position == Vector2(target):
                    circle.queue_free()

            createMarker(currentPlayer, target) #Places the marker in the spot

...
func createMarker (player, position, temp=false, gray=false):
    #Create marker node and add it as a child
    if player == 1:
        var circle = circleScene.instantiate()
        circle.position = position
        if gray: #Gray is an optional indicator which makes the symbol dark
enter image description hereenter image description here            circle.modulate = Color(0.5, 0.5, 0.5, 1.0)
        add_child(circle)
        if temp: tempMarker = circle
    elif player == -1:
        var cross = crossScene.instantiate()
        cross.position = position
        if gray:
            cross.modulate = Color(0.5, 0.5, 0.5, 1.0)
        add_child(cross)
        if temp: tempMarker = cross
#Moving Player 2 cursor
func updateCursorPosition() -> void:
    if cursorMarker == null:
        return
    cursorMarker.position = Vector2(player2Cursor) * cellSize

解决方案

我没有看到在调整窗口大小时更新 boardsize 的任何代码。下面给出一些示例代码:

func _ready():
    get_tree().root.size_changed.connect(on_viewport_size_changed)## connect the function to the signal

func on_viewport_size_changed():
    boardsize = $Board.get_rect().size.x
        ##  note that this may mess up some of your other logic

希望这能帮到你!

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章