JAVA背景动画(线性渐变油漆)

时间:2014-02-03 03:28:30

标签: java performance graphics awt gradient

java.awt中的一个LinearGradientPaint对象在绘制后可能看起来不错,但是我有一个问题,就是在某种游戏模型中绘制动画背景,这需要我很长时间才能构建。

我想使用Graphics2D绘画对象在背景上绘制一个动画彩虹渐变,除了当我这样做时,我注意到重新绘制面板有很多延迟。它应该每秒重绘至少30帧,这只有在图形对象使用的Paint对象不是彩虹渐变时才可能。

即使将其作为单独的线程运行也无法解决问题。下面是我在每个帧结束时尝试做的代码:

gamePanel.executor.execute(new Runnable(){
        public void run()
        {
            while(true)
            {
                if (Background.selectedBackgroundIndex >= Background.SKY_HORIZON_GRADIENT_PAINT &&
                        Background.selectedBackgroundIndex < Background.SPACE_PAINT)
                {
                    float displacementValue = 1.0f;

                    if (Background.backgroundShape.y < ((-2990.0f) + CannonShooterModel.gamePanel.getSize().height) && gamePanel.horizonGoingDown)
                        gamePanel.horizonGoingDown = false;
                    else if (Background.backgroundShape.y > (-10.0f) && !gamePanel.horizonGoingDown)
                        gamePanel.horizonGoingDown = true;

                    Point2D.Double startPoint = (Point2D.Double)(((LinearGradientPaint)Background.background).getStartPoint()), 
                            endPoint = (Point2D.Double)(((LinearGradientPaint)Background.background).getEndPoint());

                    if (gamePanel.horizonGoingDown)
                        Background.backgroundShape.y -= displacementValue;
                    else
                        Background.backgroundShape.y += displacementValue;

                    startPoint.setLocation(0, Background.backgroundShape.y);
                    endPoint.setLocation(0, Background.horizonGradientPaintHeight + Background.backgroundShape.y);


                    // Should be done in another thread, particularly in arithmetic calculations.
                    Background.background = new LinearGradientPaint(startPoint, endPoint,
                            ((LinearGradientPaint)Background.background).getFractions(), 
                            ((LinearGradientPaint)Background.background).getColors());

                }

                for (int a = 0; a < PlayerUnit.weapon.bullets.length; a++)
                {
                    if (PlayerUnit.weapon.bullets[a] != null)
                    {
                        if (PlayerUnit.weapon instanceof Pistol &&
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).x + ((Pistol)PlayerUnit.weapon).bulletWidth >= 0 &&
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).x <= CannonShooterModel.gamePanel.getSize().width &&
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).y + ((Pistol)PlayerUnit.weapon).bulletWidth >= 0)
                        {
                            if (PlayerUnit.weapon.weaponAngles[a] >= 0)
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).x +=
                                        PlayerUnit.weapon.bulletSpeed * Math.cos(PlayerUnit.weapon.weaponAngles[a]);
                            else
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).x -=
                                    PlayerUnit.weapon.bulletSpeed * Math.cos(PlayerUnit.weapon.weaponAngles[a]);

                            if (PlayerUnit.weapon.weaponAngles[a] >= 0)
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).y -=
                                        PlayerUnit.weapon.bulletSpeed * Math.sin(PlayerUnit.weapon.weaponAngles[a]);
                            else
                                ((Ellipse2D.Float)PlayerUnit.weapon.bullets[a]).y +=
                                    PlayerUnit.weapon.bulletSpeed * Math.sin(PlayerUnit.weapon.weaponAngles[a]);
                        }
                        else
                            PlayerUnit.weapon.bullets[a] = null;
                    }
                }

                //System.out.println(Background.backgroundShape.y);

                repaint();

                try
                {
                    Thread.sleep(1000 / 60);
                }
                catch (InterruptedException ex)
                {
                }
            }
        }
    });

类Background,PlayerUnit和CannonShooterModel对我的游戏模型很重要。这是一个直立的射击游戏,应该是用各种武器和敌人设计的。

这个彩虹渐变我使用了八个不同颜色对象的数组。对于每个通过的帧,我根据需要更改渐变绘制所需的两个Point2D.Float对象的y坐标。为了使动画工作,我必须再次实例化LinearGradientPaint的另一个对象,使用前一个对象的一些先前属性,并让它由类型Paint的变量背景引用。

问题是,LinearGradientPaint没有可以在两个端点上进行平移的方法,并且get方法不返回LinearGradientPaint对象包含的实际对象。 (我的意思是,get方法返回Point2D的新对象,其值与LinearGradientPaint对象的那些值相同。)

对于每个传递的帧,我不仅要更改与渐变关联的形状的y坐标属性,还要设置再次实例化LinearGradientPaint所需的两个Point2D对象的位置。

我想重新解释这个更简单,因为我可能会遇到一些英语知识,尽管这是我的主要语言。如果您需要重新解释,请告诉我。

2 个答案:

答案 0 :(得分:3)

您可以尝试一些解决方案。

您可以创建BufferedImage,而不是填充整个可绘制区域,而1的宽度为LinearGradientPaint像素,高度等于您要填充的区域(假设您是垂直填充)。然后,您可以将BufferedImage应用于此Graphics2D的{​​{1}}并填写它(完成后不要忘记处理Graphics上下文。)

然后,您只需使用Graphics#drawImage(Image, x, y, width, height, ImageObserver)来实际绘制图像。一般来说,重新缩放图像似乎更快,然后填充LinearGradientPaint,尤其是当您认为只是水平拉伸图像时。

另一种选择是生成已经应用BufferedImage的基本LinearGradientPaint,您只需根据需要绘制此偏移量。这可能要求你至少涂两次才能让它“缝合”起来......

答案 1 :(得分:0)

如果您只是让背景渐变上下移动,是否可以在初始化时将其写入图像,然后垂直移动并包裹图像?