将2d游戏世界坐标转换为屏幕位置

时间:2013-06-02 16:46:27

标签: java

我有一个生成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偏移值,所以我知道如何移动地图。我可以使用这些值作为当前偏移量,如果有人保存游戏,我可以简单地存储它们并重新使用它们。没有必要的等式,我只需要存储累积偏移量。

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:-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

}