Pacman在Java问题

时间:2009-01-14 23:14:10

标签: java network-programming

对于我的大学任务,我必须制作一个可联网的pacman版本。我认为我最好先制作pacman的本地副本,然后扩展此功能以进行网络播放。

我不得不说我对java GUI开发相对较新,并在java中使用这些功能。

我已经开始关注java中游戏开发的上述链接以及pacman游戏的一个例子。

我决定将迷宫表示为一个int数组,其中不同的值意味着不同的东西。但是当主游戏循环中的paint方法运行时,我正在用这种方法重新绘制整个迷宫。

    for (int i : theGame.getMaze())
    {
        if (i == 4)
        {
            g.setColor(mazeWallColour);
            g.fillRect(curX, curY, cellSize, cellSize);
            curX += 25;
        }
        else
        {
            curX += cellSize;
        }

        index++;


        // Move to new row
        if (index == 25)
        {
            index = 0;
            curX = 10;
            curY += cellSize;
        }
    }

然而,这为我提供的不到1fps。虽然我已经注意到上面链接的示例使用类似的方式重绘每次调用paint方法,我相信这是在一个不可见的图像(有点像双缓冲[有点像第一个链接使用BufferStrategy]解释])什么是重绘迷宫的更好方法?

任何有关此指针/建议都会很有用。

感谢您的时间。

http://pastebin.com/m25052d5a - 主要游戏类。

编辑:在我试图查看执行代码的时间过长之后,我发现了一些非常奇怪的事情。

在paintClear(Graphics g)方法中添加了

ocean = sprites.getSprite("oceano.gif");
g.setPaint(new TexturePaint(ocean, new Rectangle(0,t,ocean.getWidth(),ocean.getHeight())));
g.fillRect(10, 10,getWidth() - 20,getHeight() - 110);

这让整个事情顺利进行 - 然而当我删除这些线条时,整个事情变慢了?有什么可能导致这个?

Updated code

10 个答案:

答案 0 :(得分:4)

首先,我建议您使用命名常量,而不是在代码中使用随机幻数,并考虑使用枚举作为您的单元格类型。虽然它不会让你的代码运行得更快,但它肯定会让它更容易理解。此外,'i'通常用作计数器,而不是返回值。您应该将其称为cellType或类似的东西。我还建议您为舞台地图使用2D数组,因为它可以在后勤和概念上更轻松地实现。

那就是说,这里有几件事要尝试:

setColor()拉出循环并执行一次。编译器可能能够执行循环不变的提升,从而为您(也可能会)执行此操作,但从概念上讲,您应该这样做,因为看起来您希望所有墙都是一种颜色。

尝试拨打drawRect()而不是fillRect(),看看是否吸引得更快。我不认为它会,但它值得一试,即使它看起来更丑。同样,您可以尝试创建Image,然后绘制它。这样做的好处是,很容易告诉Graphics对象在图像上实现转换。另外,请考虑完全解决这个问题并确保它的性能受到重大影响。

此外,通常您不需要为其Graphics对象请求父对象并直接在其上实现绘制。相反,你应该覆盖它的paintComponent()方法,只使用给你的图形(可能像你一样调用辅助方法)。 Swing组件默认是双缓冲的,因此您不需要自己实现;让摆动物体完成它的工作,让你知道什么时候画画。

此外,你最终重新粉刷整个屏幕,这有点过分。如果您致电repaint(Rectangle),Swing可以选择仅重新绘制明确标记为脏的电路板部分。更新其中一个精灵时,只在精灵的旧位置和新位置区域调用repaint(r)。当你完成一个关卡并需要一个新的棋盘时,你可以调用repaint()(不带参数)来重绘整个地图。

您还应该查看Sun's tutorial以获取有关Swing效率的一些提示。

答案 1 :(得分:4)

我仍然认为自己是Java的初学者,但我最近使用你提到的一些技术开发了一个带有动态地图和编辑器的Frogger式游戏,我很乐意提供一些帮助。

如上所述,enum是要走的路。我将我的地图设置为一个二维数组并为每个不同的类型设置一个枚举,在我的地图类中编写一个方法来接收一个图像并将地图中的每个方格划分为我的枚举中的每个值。

可以在Coke and Code找到帮助我进行映射的教程。所有的源代码都在那里,如果你需要一只手的任何一个,尽管你似乎对你正在做的事情有一个正确的把握。如果你仍然需要帮助,我总是可以拖出一些源代码。

答案 2 :(得分:3)

上面列出的代码不能成为1fps问题的根源......我的代码远远超过了运行得更快的代码。

您可以对该代码进行基准测试,并确保它是问题的根源吗?

答案 3 :(得分:3)

看起来你对Thread.sleep的调用没有按照你的意图行事,但我不认为这是你麻烦的根源。你有:

Thread.sleep(Math.max(0, startTime - System.currentTimeMillis()));

startTime将始终小于System.currentTimeMillis(),因此startTime - System.currentTimeMillis()将始终为负数,因此您的睡眠将始终为0毫秒。它与您显示的示例不同,因为该示例在执行计算之前将startTime增加40毫秒。它计算了将绘图时间填充到40毫秒的睡眠时间。

无论如何,回到你的问题。我建议您测量一下,以确定您的时间花在哪里。在知道什么是缓慢之前,没有必要进行优化。您已经知道如何使用System.currentTimeMillis()。尝试使用它来衡量所有时间的位置。这一切都花在了墙上吗?


编辑 - 我看到这被标记为已被接受,所以当我确定睡眠时间时,我是否应该推断问题消失了?我没有很多Java GUI经验,但我可以推测,也许你的代码正在挨饿其他重要的线程。通过将线程设置为具有最大优先级并且只调用sleep(0),您几乎可以保证进程中没有其他线程可以执行任何操作。这是解释原因的a post from Raymond Chen's blog

答案 4 :(得分:2)

我不是游戏开发者,但该帧速率似乎很慢。

我不太确定您的代码是如何工作的,但是提高渲染性能的一种可能性是找到显示器中那些变化不大的部分(例如迷宫的墙壁)并避免重新为每个帧创建它们。

创建一个包含常量元素(迷宫?,背景)的BufferedImage,然后为每个帧重新绘制它。在这个缓冲图像的顶部,绘制可变元素(PacMan,鬼,点等)。

这项技术以及许多其他Java2D性能提示将在Romain Guy的优秀书籍Filthy Rich Clients中进行讨论。

答案 5 :(得分:2)

就这样你不用担心它是Java,我在频谱分析仪(如o-scope)上工作,整个GUI部分(跟踪,菜单,按钮和滚轮处理)都是用Java完成的。当我到达那里它得到1fps,当我离开它是12-20。这有很多处理正在进行,并且运行速度非常慢。

仅查看更新需要更新的GUI部分。通常,您可以重绘整个屏幕,但只需将剪切区域设置为真正更新的部分。

小心内圈 - 他们是速度杀手。

尽量避免分配和释放大量对象。我不是说不要使用对象,我说不要为每个像素创建一个:)

祝你好运

答案 6 :(得分:1)

哇,给别人学习Java是个非常棘手的问题。

我的建议?从对象的角度思考。你能写一些没有模仿游戏本身行为的用户界面的东西吗?一旦你开始工作,你就可以专注于用户界面的特殊问题。是的,从网络部分之前的本地版本开始。

我不是游戏玩家。我想知道Java2D API会让你的生活变得更好吗?

你需要多长时间才能完成它?

答案 7 :(得分:1)

这可能听起来很明显,但是你的性能问题是因为你正在重新绘制整个迷宫,这不需要完成,而是你只需要重绘迷宫的改变部分。

之前我解决这个问题的方法是将迷宫的更新从实际重绘分离到不同的线程(有点像线程MVC)。每次更改迷宫中的单元格时都会将其标记为“脏”,重绘线程会立即检查,然后仅重绘脏单元格。

对于极端通用的建议表示抱歉

答案 8 :(得分:1)

默认情况下,Java / Swing双缓冲区。如果你正在使用Swing,你不需要像其他答案那样单独进行双缓冲。

我同意Allain的观点,即您列出的代码不能成为1fps的原因。我编写了效率极低的Java / Swing动画代码,运行速度比你描述的快得多。做一些更多的测试来缩小缓慢的原因。

答案 9 :(得分:1)

如果可能,您应该保留迷宫的图像,并在一个库调用中绘制它。它可能也不需要是全分辨率 - 如果你想要一个块状,8位的感觉,我希望图形库会非常乐意使用8 ^)

此外,正如其他人所提到的,您只需重新绘制需要更新的屏幕部分即可节省时间。这可能很难实现,但可能允许您显着提高帧速率。一定要做一些实验,以确保在施加所需的努力之前就是这种情况!