簡體   English   中英

將2d游戲世界坐標轉換為屏幕位置

[英]Convert 2d game world coordinates to screen position

我有一個系統可以生成大塊的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偏移值,所以我知道如何移動地圖。 我可以使用這些值作為當前偏移量,如果有人保存游戲,我可以簡單地存儲它們並重新使用它們。 沒有必要的等式,我只需要存儲累積偏移量。

模數(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;
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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM