3

我有一个生成大量 2d 游戏地图图块的系统。块是 16x16 瓷砖,瓷砖是 25x25。

块有自己的坐标,例如 0,0、0,1 等。图块根据它们所在的块确定它们在世界中的坐标。我已经验证了块/图块都显示正确x/y 坐标。

我的问题是将它们转换为屏幕坐标。在上一个问题中,有人建议使用:

(worldX * tileWidth) % viewport_width

每个图块的 x/y 都经过此计算,并返回屏幕 x/y 坐标。

这适用于适合视口的图块,但它会为屏幕外的任何内容重置屏幕 x/y 位置计算。

在我的地图中,我在玩家周围的半径内加载了大块瓷砖,因此一些内部瓷砖将在屏幕外(直到它们四处移动,屏幕上的瓷砖位置才会移动)。

我尝试使用将不在屏幕上的图块进行测试:

Tile's x coord: 41
41 * 25 = 1025
Game window: 1024
1025 % 1024 = 1

这意味着图块 x(如果屏幕 0,0 位于地图 0,0,则应位于 x:1025,就在屏幕右侧)实际上位于 x:1,出现在顶部-剩下。

我想不出如何正确处理这个问题——在我看来,我需要tileX * tileWidth确定它的“初始屏幕位置”,然后以某种方式使用偏移量来确定如何让它出现在屏幕上。但是什么抵消?

更新:当玩家移动时,我已经存储了一个 x/y 偏移值,所以我知道如何移动地图。我可以将这些值用作当前偏移量,如果有人保存游戏,我可以简单地存储这些值并重新使用它们。不需要等式,我只需要存储累积偏移量。

4

2 回答 2

1

模数 (worldX*tileWidth % screenWidth) 是导致它重置的原因。模 (%) 为您提供整数除法运算的余数;因此,如果 worldX * tileWidth 大于 screenWidth,它将为您提供 (worldX * tileWidth) / screenWidth 的余数;如果 worldX * tileWidth 为 screenWidth+1,则余数为 1:从行首重新开始。

如果消除模数,它将继续在屏幕边缘绘制图块。如果您的绘图缓冲区与屏幕大小相同,则需要在屏幕边缘添加一个磁贴检查,以确保您只绘制可见的磁贴部分。

如果您试图让播放器在屏幕上居中,则需要将每个图块偏移播放器与图块 0,0 的偏移量(以像素为单位),减去屏幕宽度的一半:

offsetX = (playerWorldX * tileWidth) - (screenWidth / 2);
screenX = (worldX * tileWidth) - offsetX;
于 2013-06-02T19:39:34.817 回答
-1
x = ((worldX*tileWidth) > screenWidth) ? worldX*tileWidth : (worldX*tileWidth)%screenWidth;

那应该行得通。虽然我建议实现类似界面的东西,并让每个图块决定它们想要呈现的位置。像这样的东西

interface Renderable {


void Render(Graphics2D g)
  ..
}

class Tile implements Renderable{
  int x,y
   //other stuff


  Render(Graphics2D g){
   if (!inScreen()){
     return; 
    }
   //...
   //render
   }


  boolean inScreen(){
    //if the map moves with the player you need to define the boundaries of your current screenblock in terms of the global map coordinates
    //What you can do is store this globally in a singleton somewhere or pass it to the constructor of each tile.
    //currentBlock.x is then player.x - screenWidth/2
    //currentBlock.width is then player.x + screenWidth/2;
    //similar for y


    if(this.x < currentBlock.x || this.x > currentBlock.Width)
      return false;
    if (this.y < currentBlock.y || this.y > currentBlock.height)
      return false;
    return true;


   //If the map are in blocks (think zelda on snes where you go from one screenblock to another) you still need to define the boundaries
   //currentBlock.x = (player.x / screenWidth) (integer division) *screenWidth;
   //currentBlock.width = (player.x /screenWidth) (...) * screenWidth  + screenWidth;
   //same for y
   //Then perform above tests

}
于 2013-06-02T18:28:35.220 回答