2016-07-16 114 views
0

我目前正在创建一个2D游戏,我想知道如果瓷砖必须移动或字符?我是否需要在2d瓷砖世界中移动瓷砖或玩家?

我问这个问题,因为我已经创建了“2D瓷砖地图”,但它运行速度太慢,我无法修复它。我现在试了一切,结果是我得到30帧/秒。

运行速度太慢的原因是因为每1ms带一个定时器,瓷砖正在重绘。但我无法弄清楚如何解决这个问题。

如果有人能帮助我,我会非常感激!

我这是怎么使地图:

 public void makeBoard() 
    { 
     for (int i = 0; i < tileArray.GetLength(0); i++) 
     { 
      for (int j = 0; j < tileArray.GetLength(1); j++) 
      { 
       tileArray[i, j] = new Tile() { xPos = j * 50, yPos = i * 50 }; 
      } 
     } 
    } 

在这里,我重绘每1毫秒以上的瓷砖和精灵:

 private void Wereld_Paint_1(object sender, PaintEventArgs e) 
    { 
     //label1.Text = k++.ToString(); 
     using (Graphics grap = Graphics.FromImage(bmp)) 
     { 
      for (int i = 0; i < tileArray.GetLength(0); i++) 
      { 
       for (int j = 0; j < tileArray.GetLength(1); j++) 
       { 
        grap.DrawImage(tileArray[i, j].tileImage, j * 50, i * 50, 50, 50); 
       } 
      } 
      grap.DrawImage(player.movingObjectImage, player.xPos, player.yPos, 50, 50); 
      grap.DrawImage(enemyGoblin.movingObjectImage, enemyGoblin.xPos, enemyGoblin.yPos, 50, 50); 

      groundPictureBox.Image = bmp; 
      // grap.Dispose(); 

     } 
    } 

这是一个特定的定时器间隔:

 private void UpdateTimer_Tick(object sender, EventArgs e) 
    { 
     if(player.Update()==true) // true keydown event is fired 
     { 
      this.Invalidate(); 
     } 
     label1.Text = lastFrameRate.ToString(); // for fps rate show 
     CalculateFrameRate(); // for fps rate show 
    } 
+0

只画那些应该出现在屏幕上的瓦片,并用相机来帮你画的东西:http://stackoverflow.com/questions/9997006/slick2d-and-jbox2d-how- to-draw?answertab = votes#tab-top – user3814613

+0

@ user3814613首先,感谢您的评论!我真的不明白你在说什么。我必须重新绘制所有的瓷砖,因为我希望瓷砖移动,所以它看起来像玩家在“世界”周围走动。此外,我从来没有使用过相机功能,我不知道从哪里开始。 –

+0

您是否阅读过该评论中链接的帖子?如果你有,你不会说*我不知道从哪里开始*。人们提供其他问题的链接来帮助;在他们完成了为你找到它的工作之后忽略他们是不好的。 –

回答

1

正如在评论中提到你的概念是错误的。

  1. 瓦片地图是静态

    从功能的角度,如果玩家移动或地图,从性能的角度来看并不重要:所以在这里只是如何做这个任务的一个简单的总结瓷砖的数量比玩家的数量大得多,所以移动的玩家更快。

    要实现玩家居中或观看视野,您必须移动相机。

  2. 渲染

    重绘每1ms为疯狂,最有可能不可能对当今的计算机,如果你有中等场景的复杂程度。人类视觉无法检测到它,所以没有意义重绘更多25-40 fps。更高fps需求的唯一原因是与显示器刷新同步以避免扫描线伪影(即使LCD使用扫描线刷新也是如此)。为了获得更多的fps,你的显示器的刷新率是毫无意义的(许多fps玩家会反对,但我们的看法是什么,不管他们说什么......)。

    无论如何,如果你的渲染花费了1ms以上(这可能更有可能),那么你的计时器就会失效,因为它应该在第一个处理程序停止之前多次发射。由于同步问题,这通常会导致大规模的慢速拍摄,所以最终的fps通常会比渲染引擎提供的更小。那么如何补救呢?

    1. 设置timer间隔20ms以上
    2. 添加bool _redraw=false 而仅使用它重绘当你需要重绘屏幕。因此,对于任何动作,如玩家移动,相机移动或转动,动画更改将其设置为true
    3. 内部计时器事件处理程序仅在_redraw==true内调用重新绘制并将其设置为false后。

    这会提高性能很多。即使重新绘制时间比定时器间隔还要多,仍然会比目前的方法快得多。

    避免闪烁使用返回缓冲

  3. 相机和剪裁

    你的地图是屏幕最有可能更大,所以没有点重绘所有的瓷砖。您可以将相机视为选择地图右侧部分的方法。如果你的游戏不使用旋转,那么你只需要position,可能是zoom/scale。如果你想旋转,那么2D 3x3均匀矩阵就是这种方式。

    让假设你只得到了位置(无缩放或旋转),那么你可以使用这个转换:

    screen_x=world_x-camera_x 
    screen_y=world_y-camera_y 
    
    world_x=screen_x+camera_x 
    world_y=screen_y+camera_y 
    

    所以camera是你的相机视图位置,world是你平铺位置在地图上的坐标和screen是在屏幕上的位置。如果您在地图上获得了瓦片的indexes,则只需将它们乘以瓦片大小(以像素为单位)即可获得world坐标。

    要仅选择可见图块,需要获取屏幕的角点位置,将其转​​换为世界坐标,然后转换为地图中的索引,并最终只渲染矩形内的这些点在地图中形成的图块+某些误差范围(例如,在所有方向上呈现1个拼贴放大的矩形)。这样,渲染将独立于您的地图大小。这个过程被称为剪辑

我强烈建议看一下这些相关QA S:

演示中的链接进行质量检查只使用GDI和直接像素访问的位图的Win32应用程序的形式,所以你可以用你的代码比较性能(他们应该是相似的)和调整你的代码,直到它的行为应该。

+0

首先,谢谢你的帮助:)我完成了第2步,但现在我不需要第3步。我有一个想法如何做到这一点。但首先,我想摆脱de 30 fps p/s。你有什么技巧可以在每20ms绘制完整的地图达到50/60 fps左右?我只画出与屏幕一样大的地图,所以没有瓷砖出现。后来我将执行其余的......谢谢你的时间! –

+0

@MYil第一个链接的QA也是我的演示源代码,速度足够快。没有看到你怎么渲染很难说瓶颈在哪里......你怎么渲染精灵?还是你只有瓷砖(没有透明度或面具)?无论如何错误地编码gfx渲染可以痛苦缓慢... – Spektre

+0

感谢您的答案!奥克,生病要尽可能清楚:)我有一个装满瓷砖的二维阵列。那些瓷砖是类,在这些类中有一个图像。该图像大约1kb。我每隔1ms(或20ms,给出相同的性能)将图像重绘为位图。并在一个大型的电影箱上绘画。位图大小与图片框大小一样大。每当我按下一个keydown事件时,重绘就完成了。然后计时器将打开精灵类中的移动方法并使其移动。让我把我的代码porition,挂在:) –

1

您是否正在自己编写瓷砖实施?可能问题在于,你在绘制所有瓷砖的每一帧中。

具有滚动贴图的2D引擎应该在比屏幕更大的精灵上绘制贴图,然后绘制该精灵周围的快速操作(您需要指定您正在使用的语言,以便我可以提供一些提示如何真正让那么快 - 基本上是一个在显存加快位块,但每一种语言都有它的方式来做到这一点)

enter image description here

当这个超级精灵的边界是靠近屏幕边缘比一个阈值(通常是一半瓦片),较大的精灵会在当前位置周围重新绘制 - 但是不需要在这个上绘制所有的图块!开始复制这个重新生成的精灵上的supersprite,你只需要绘制由于偏移量而从前一个supersprite中丢失的图块。

enter image description here

+1

忘了在我的答案中提到这一点。所以+1。顺便说一句,这被称为回缓冲或双缓冲,而不是超级精灵......我的理解是,超级精灵用来结合层的精灵,以提高每个瓷砖基础上的动画性能,而不是阴影屏幕......但这个想法是正确的 – Spektre

+0

back/double buffering具有精确的含义,并且每帧都有一个后台缓冲区,并为前台缓冲区交换 - 在这里您创建一个预发布的表单,之后您可以在后台或前台缓冲区上刷新 - 因此它是正交的 - 但想法是相似的,有图形卡推最大像素,而不是CPU –

+0

嗯,我认为你是正确的超滚动阴影屏幕完全不适合账单... – Spektre