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