Java问题中的Pacman

Java问题中的Pacman,java,network-programming,Java,Network Programming,为了完成我的大学作业,我必须制作一个网络版的“吃豆人”。我想我最好先制作一个pacman的本地副本,然后将此功能扩展到网络游戏 我不得不说,我对java GUI开发和在java中利用这些特性相对较新 我已经开始关注上面关于java内游戏开发和pacman游戏示例的链接 我决定将迷宫表示为具有不同值的int数组,表示不同的内容。然而,当主游戏循环中的绘画方法运行时,我正在用这种方法重新绘制整个迷宫 for (int i : theGame.getMaze()) {

为了完成我的大学作业,我必须制作一个网络版的“吃豆人”。我想我最好先制作一个pacman的本地副本,然后将此功能扩展到网络游戏

我不得不说,我对java GUI开发和在java中利用这些特性相对较新

我已经开始关注上面关于java内游戏开发和pacman游戏示例的链接

我决定将迷宫表示为具有不同值的int数组,表示不同的内容。然而,当主游戏循环中的绘画方法运行时,我正在用这种方法重新绘制整个迷宫

    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方法时都使用类似的重画方法,我相信在不可见的图像上也会使用这种方法(有点像双缓冲[我使用了第一个链接解释的缓冲策略]),但有什么更好的方法重画迷宫

任何与此相关的指针/建议都会很有用

谢谢你抽出时间

-主要游戏类

编辑:我刚刚注意到,在尝试查看什么代码花了这么长时间才执行之后,发生了一些非常奇怪的事情

在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);
这使得整个过程顺利进行——但是当我去掉这些线时,整个过程就慢了下来?这是什么原因造成的


哇,这对刚学习Java的人来说是一个相当棘手的问题

我的建议?从对象的角度思考。你能在没有模仿游戏本身行为的用户界面的情况下编写一些东西吗?一旦你开始工作,你可以集中精力解决用户界面的特殊问题。是的,先从本地版本开始,再从网络版开始

我不是一个游戏玩家。我想知道Java2D API能提供什么让你的生活变得更好


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

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

我以前处理这个问题的方法是将迷宫的更新与实际的重画分离成不同的线程(有点像线程MVC)。每当你在迷宫中更改一个单元格时,你会将其标记为“脏”,你的重画线程会不时检查,只重画脏单元格


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

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

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


Romain Guy的优秀著作中讨论了这种技术以及许多其他Java2D性能技巧。

上面列出的代码不能成为1fps问题的根源。。。我的代码远远不止这些,而且运行速度更快


你能对代码进行基准测试并确保它是问题的根源吗?

为了让你不用担心它是Java,我在一个频谱分析仪(比如o-scope)上工作,其中整个GUI部分(跟踪、菜单、按钮和滚轮处理)都是用Java完成的。我到那里的时候是1磅,我离开的时候是12-20磅。这需要进行大量的处理,并且运行在一个非常慢的处理器上

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

小心内环——它们是速度杀手

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


<好运>

首先,我建议您使用命名常量,而不是在代码中使用随机魔法数,并考虑为您的单元类型使用枚举。虽然它不会使代码运行得更快,但肯定会使代码更容易理解。此外,“i”通常用作计数器,而不是返回值。您可能应该称之为
cellType
或类似的名称。我还建议您在舞台地图中使用2D阵列,因为它使许多事情变得更容易,无论是在逻辑上还是在概念上

也就是说,这里有一些东西可以尝试:

setColor()
从循环中拉出并执行一次。编译器可能能够执行循环不变提升,因此可以为您执行此操作(并且可能会),但从概念上讲,您可能无论如何都应该执行此操作,因为您似乎希望所有墙都是一种颜色

试着调用
drawRect()
而不是
fillRect()
,看看这样画是否更快。我认为不会,但值得一试,即使它看起来更丑。类似地,您可以尝试创建一个
图像
,然后绘制该图像。这样做的好处是,告诉图形对象在图像上实现变换非常容易。另外,考虑彻底地解决这个问题,确保它是一个重要的性能命中。 此外,通常您不需要为其图形对象请求父对象并直接在其上实现绘制。相反,您应该重写它的
paintComponent()
方法,只利用提供给您的图形(可能像您那样调用帮助器方法)。Swing组件在默认情况下是双缓冲的,所以您不需要自己实现它;就让它摆动吧