You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现围绕动态枢轴点的轨道视角切换?(仿OSRS视角)

复刻OSRS视角效果的代码问题排查

我正在尝试复刻《Old School Runescape》(OSRS)的视角效果,采用精灵堆叠来模拟3D环境而非使用真正的3D对象。核心逻辑是:玩家在世界中移动时,新的枢轴点应基于当前所在的瓦片,已定义位置的对象需要根据当前枢轴点调整自身位置。

对比效果:
我的游戏效果
OSRS原版效果

我的实现代码:

import math

import pygame
from math import *
from pygame import Vector2

import shader


class DrawingObject:
    def __init__(self, mainWindow, modMapSurface, mapCenter, worldPosX, worldPosY, playerPosX, playerPosY, camRotAngle, camTiltAngle):
        self.mainWindow = mainWindow
        self.modMapSurface = modMapSurface
        self.mapCenter = mapCenter
        self.worldPosX = worldPosX
        self.worldPosY = worldPosY
        self.playerPosX = playerPosX
        self.playerPosY = playerPosY
        self.camRotAngle = camRotAngle
        self.camTiltAngle = camTiltAngle

        DrawingObject.draw(self)

    def draw(self):
        objectImageList = []
        imageScale = 4

        # worldPosX, worldPosY, imageFilePath
        worldObjectList = \
        [
            [512, 512, "Graphics\\person.png"],
            [640, 512, "Graphics\\testBlock3.png"],
            [768, 512, "Graphics\\testBlock2.png"],
            [896, 896, "Graphics\\frog.png"],
        ]

        for i in range(len(worldObjectList)):
            currentObjectImage = pygame.image.load(worldObjectList[i][2]).convert_alpha()

            # Scale
            imageWdith =  currentObjectImage.get_width()
            imageHeight = currentObjectImage.get_height()
            scaledWidth = imageWdith * imageScale
            scaledHeight = imageHeight * imageScale

            currentObjectImage = pygame.transform.scale(currentObjectImage, (scaledWidth, scaledHeight))

            cellCount = currentObjectImage.get_width() // currentObjectImage.get_height()
            print(cellCount)

            objPosX = worldObjectList[i][0]
            objPosY = worldObjectList[i][1]

            for i in range(cellCount):
                imageObjectRect = pygame.Rect(scaledHeight * i, 0, scaledHeight, scaledHeight)
                objectImageList.append(imageObjectRect)

                objectSurface = pygame.Surface((scaledHeight, scaledHeight))
                objectSurface.blit(currentObjectImage, (0, 0), objectImageList[i])

                objectSurface.set_colorkey([0, 0, 0])

                # Call shader function
                #shader.shader(objectSurface, cellCount, i)

                objectSurfaceRot = pygame.transform.rotate(objectSurface, self.camRotAngle)
                objectRotWidth, objectRotHeight = objectSurfaceRot.get_size()

                # Object drawing
                modObjectSurface = pygame.transform.scale(objectSurfaceRot, (objectRotWidth, objectRotHeight / 90 * self.camTiltAngle))
                #objectCenter = modObjectSurface.get_rect(center=(originPosX + self.worldPosX, originPosY + self.worldPosY - imageScale * i))

                # Orbit
                #distance = math.sqrt((objPosX - objPosY)**2 + (self.worldPosX - self.worldPosY)**2)
                distance = Vector2(self.worldPosX, self.worldPosY).distance_to((objPosX, objPosY))
                pivot = (self.worldPosX, self.worldPosY - imageScale * i)
                orbOffset = Vector2()

                # Need distance from player to obj
                orbOffset.from_polar((distance, -self.camRotAngle))
                newPos = pivot + orbOffset
                orbRect = modObjectSurface.get_rect(center = newPos)

                self.mainWindow.blit(modObjectSurface, orbRect)

当前遇到的问题:

  • 世界对象无法随世界位置进行正确调整
  • 旋转相机时对象会出现上下“弹跳”的现象,相机倾斜度越低,该“弹跳”表现得越明显
    我尝试过多种方式计算世界对象与玩家世界位置的距离,但最终的移动效果仍偏差很大。

内容的提问来源于stack exchange,提问作者PyGuy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:32:21