Android帧动画留下尾随余像

时间:2017-08-17 06:48:25

标签: java android animation

我在Stack Overflow上的第一篇文章。我正在使用一本书来学习一些Android游戏编程(24小时内的Android游戏编程,Jonathan Harbour)。无论如何,当我为一个简单的动画演示更新这个Sprite类时,我最终在我的模拟器中出现了一些奇怪的残像: screenshot of emulator, using new code。即使动画继续到下一帧,余像(或者他们所称的任何内容,前一帧图像)仍保留在屏幕上。右边的猫和左上角的小猫受到影响,但显然马图像不是。

我不确定我做错了什么,因为我只是完全从书中复制。我已多次重新检查。以下是的代码。与前一版本相比,Sprite类的更改在每行的末尾都有// - **(为方便起见,我不知道如何加粗代码块)。

/**
* Sprite class
* Requires game.engine.Engine to build
*/

package game.engine;

import java.util.LinkedList;
import java.util.ListIterator;
import android.graphics.*;

// added for frame scratch bitmap
import android.graphics.Bitmap.Config;   //--**

public class Sprite
{
    private Engine p_engine;
    private Canvas p_canvas;
    private Texture p_texture;
    private Paint p_paint;
    public Point position;

    private int p_width, p_height;
    private int p_columns;
    private int p_alpha;
    private LinkedList<Animation> p_anims;
    private int p_frame;
    private Float2 p_scale;
    private float p_rotation;   // note this is in radians

    private Matrix p_mat_translate;   //--**
    private Matrix p_mat_scale;   //--**
    private Matrix p_mat_rotate; //--**
    private Matrix p_matrix;   //--**
    private Bitmap p_frameBitmap;   //--**
    private Canvas p_frameCanvas;   //--**


    public Sprite(Engine engine)
    {
        this(engine, 0, 0, 1);
    }

    public Sprite(Engine engine, int width, int height, int columns)
    {
        p_engine = engine;
        p_width = width;
        p_height = height;
        p_columns = columns;
        p_canvas = null;
        p_texture = new Texture(engine);
        p_alpha = 255;
        p_paint = new Paint();
        p_anims = new LinkedList<Animation>();
        position = new Point(0, 0);
        p_frame = 0;
        p_scale = new Float2(1.0f, 1.0f);
        p_rotation = 0.0f;

        p_mat_translate = new Matrix();   //--**
        p_mat_scale = new Matrix();   //--**
        p_mat_rotate = new Matrix();   //--**
        p_matrix = new Matrix();   //--**
        p_frameBitmap = null;   //--**
        p_frameCanvas = null;   //--**
    }

    public void draw()
    {
        p_canvas = p_engine.getCanvas();

        // fill in size if this sprite is not animated
        if (p_width == 0 || p_height == 0)
        {
            p_width = p_texture.getBitmap().getWidth();
            p_height = p_texture.getBitmap().getHeight();
        }

        // create the frame scratch bitmap
        if (p_frameBitmap == null)
        {
            p_frameBitmap = Bitmap.createBitmap(p_width, p_height, Config.ARGB_8888); //--**
            p_frameCanvas = new Canvas(p_frameBitmap);   //--**
        }

        /**
         * First, copy the animation frame onto a scratch bitmap.
        */

        // define the source rect representing one frame
        int u = (p_frame % p_columns) * p_width;
        int v = (p_frame / p_columns) * p_height;
        Rect src = new Rect(u, v, u+p_width, v+p_height);

        // define the destination location
        int x = 0; //position.x;   //--**
        int y = 0; //position.y;   //--**
        int w = p_width; //(int) (p_width * p_scale.x);   //--**
        int h = p_height; //(int) (p_height * p_scale.y);   //--**
        Rect dst = new Rect(x, y, x+w, y+h);

        // copy frame onto temp bitmap
        p_paint.setAlpha(p_alpha);
        p_frameCanvas.drawBitmap(p_texture.getBitmap(), src, dst, p_paint); //--**


        /**
         * Second, draw the scratch bitmap using matrix transforms.
         */

        // update transform matrices
        p_mat_scale = new Matrix();   //--**
        p_mat_scale.setScale(p_scale.x, p_scale.y);  //--**
        p_mat_rotate = new Matrix();   //--**
        p_mat_rotate.setRotate( (float) Math.toDegrees(p_rotation) ); //--**
        p_mat_translate = new Matrix();   //--**
        p_mat_translate.setTranslate(position.x, position.y);   //--**
        p_matrix = new Matrix(); // set to identity   //--**
        p_matrix.postConcat(p_mat_scale);  //--**
        p_matrix.postConcat(p_mat_rotate);   //--**
        p_matrix.postConcat(p_mat_translate);   //--**

        // draw frame bitmap onto screen
        p_canvas.drawBitmap(p_frameBitmap, p_matrix, p_paint);   //--**

    }

    // add an animation technique to this sprite
    public void addAnimation(Animation anim)
    {
        p_anims.add(anim);
    }

    // run through all of the animations
    public void animate()
    {
        if (p_anims.size() == 0) return;

        ListIterator<Animation> iterator = p_anims.listIterator();
        while(iterator.hasNext())
        {
            Animation anim = iterator.next();
            if (anim.animating)
            {
                p_frame = anim.adjustFrame(p_frame);
                p_alpha = anim.adjustAlpha(p_alpha);
                p_rotation = anim.adjustRotation(p_rotation);
                p_scale = anim.adjustScale(p_scale);
                position = anim.adjustPosition(position);
            }
            else
            {
                p_anims.remove(anim);
                return;
            }
        }
    }

    /**
     * Color manipulation methods
     */
    public void setAlpha(int alpha)
    {
        p_alpha = alpha;
    }

    public int getAlpha()
    {
        return p_alpha;
    }

    public void setPaint(Paint paint)
    {
        p_paint = paint;
    }

    /**
     * common get/set methods
     */
    public void setTexture(Texture texture)
    {
        p_texture = texture;
    }

    public Texture getTexture()
    {
        return p_texture;
    }

    public void setPosition(Point position)
    {
        this.position = position;
    }

    public Point getPosition()
    {
        return position;
    }

    public int getWidth()
    {
        return p_width;
    }

    public void setWidth(int width)
    {
        p_width = width;
    }

    public int getHeight()
    {
        return p_height;
    }

    public void setHeight(int height)
    {
        p_height = height;
    }

    public Point getSize()
    {
        return new Point(p_width, p_height);
    }

    public int getFrame()
    {
        return p_frame;
    }

    public void setFrame(int frame)
    {
        p_frame = frame;
    }

    public Float2 getScale()
    {
        return p_scale;
    }

    public void setScale(Float2 scale)
    {
        p_scale = scale;
    }

    public void setScale(float scale)
    {
        p_scale = new Float2(scale, scale);
    }

    public float getRotation()
    {
        return p_rotation;
    }

    public void setRotation(float radians)
    {
        p_rotation = radians;
    }
}

我认为问题可能是位图以及它们是如何绘制的或矩阵。我尝试使用p_frameBitmap.eraseColor(Color.TRANSPARENT);

在draw()方法的末尾,如下所示:

        ...
        // draw frame bitmap onto screen
        p_canvas.drawBitmap(p_frameBitmap, p_matrix, p_paint);

        // attempt to clear the scratch bitmap
        p_frameBitmap.eraseColor(Color.TRANSPARENT);

    }
    ...

这摆脱了尾随的图像,但是,左上角的小猫从白色到橙色闪回白色,这似乎是右边大猫的颜色:see here。我无法弄清楚原因。

我也尝试将p_frameCanvas.drawColor(0, Mode.CLEAR);与相应的导入语句import android.graphics.PorterDuff.Mode;一起使用,但结果(闪烁的橙色)是相同的。

以下是 工作的代码(以前的版本):

/**
* Sprite class
* Requires game.engine.Engine to build
*/

package game.engine;

import java.util.LinkedList;
import java.util.ListIterator;

import android.graphics.*;

public class Sprite
{
    private Engine p_engine;
    private Canvas p_canvas;
    private Texture p_texture;
    private Paint p_paint;
    public Point position;

    private int p_width, p_height;
    private int p_columns;
    private int p_alpha;
    private LinkedList<Animation> p_anims;
    private int p_frame;
    private Float2 p_scale;
    private float p_rotation;   // note this is in radians

    public Sprite(Engine engine)
    {
        this(engine, 0, 0, 1);
    }

    public Sprite(Engine engine, int width, int height, int columns)
    {
        p_engine = engine;
        p_width = width;
        p_height = height;
        p_columns = columns;
        p_canvas = null;
        p_texture = new Texture(engine);
        p_alpha = 255;
        p_paint = new Paint();
        p_anims = new LinkedList<Animation>();
        position = new Point(0, 0);
        p_frame = 0;
        p_scale = new Float2(1.0f, 1.0f);
        p_rotation = 0.0f;
    }

    public void draw()
    {
        p_canvas = p_engine.getCanvas();

        // fill in size if this sprite is not animated
        if (p_width == 0 || p_height == 0)
        {
            p_width = p_texture.getBitmap().getWidth();
            p_height = p_texture.getBitmap().getHeight();
        }

        // define the source rect representing one frame
        int u = (p_frame % p_columns) * p_width;
        int v = (p_frame / p_columns) * p_height;
        Rect src = new Rect(u, v, u+p_width, v+p_height);

        // define the destination location
        int x = position.x;
        int y = position.y;
        int w = (int) (p_width * p_scale.x);
        int h = (int) (p_height * p_scale.y);
        Rect dst = new Rect(x, y, x+w, y+h);

        p_paint.setAlpha(p_alpha);

        //draw the frame
        p_canvas.drawBitmap(p_texture.getBitmap(), src, dst, p_paint);
    }

    // add an animation technique to this sprite
    public void addAnimation(Animation anim)
    {
        p_anims.add(anim);
    }

    // run through all of the animations
    public void animate()
    {
        if (p_anims.size() == 0) return;

        ListIterator<Animation> iterator = p_anims.listIterator();
        while(iterator.hasNext())
        {
            Animation anim = iterator.next();
            if (anim.animating)
            {
                p_frame = anim.adjustFrame(p_frame);
                p_alpha = anim.adjustAlpha(p_alpha);
                p_rotation = anim.adjustRotation(p_rotation);
                p_scale = anim.adjustScale(p_scale);
                position = anim.adjustPosition(position);
            }
            else
            {
                p_anims.remove(anim);
                return;
            }
        }
    }

    /**
     * Color manipulation methods
     */
    public void setAlpha(int alpha)
    {
        p_alpha = alpha;
    }

    public int getAlpha()
    {
        return p_alpha;
    }

    public void setPaint(Paint paint)
    {
        p_paint = paint;
    }

    /**
     * common get/set methods
     */
    public void setTexture(Texture texture)
    {
        p_texture = texture;
    }

    public Texture getTexture()
    {
        return p_texture;
    }

    public void setPosition(Point position)
    {
        this.position = position;
    }

    public Point getPosition()
    {
        return position;
    }

    public int getWidth()
    {
        return p_width;
    }

    public void setWidth(int width)
    {
        p_width = width;
    }

    public int getHeight()
    {
        return p_height;
    }

    public void setHeight(int height)
    {
        p_height = height;
    }

    public Point getSize()
    {
        return new Point(p_width, p_height);
    }

    public int getFrame()
    {
        return p_frame;
    }

    public void setFrame(int frame)
    {
        p_frame = frame;
    }

    public Float2 getScale()
    {
        return p_scale;
    }

    public void setScale(Float2 scale)
    {
        p_scale = scale;
    }

    public void setScale(float scale)
    {
        p_scale = new Float2(scale, scale);
    }

    public float getRotation()
    {
        return p_rotation;
    }

    public void setRotation(float radians)
    {
        p_rotation = radians;
    }

}

无论如何,我已经坚持了很长时间。我对Java很新,所以很容易理解。

TL; DR:我正在使用的Sprite类正在为我的一些动画创建一个残像痕迹。这并没有发生在该课程的先前版本中。当我尝试清除位图时,尾随图像消失但奇怪的是其中一个动画开始闪烁不同的颜色。不熟悉位图和矩阵。

其他信息:

正在运行的实际类是一个名为Game的不同类。我知道通常你会包含整个源代码,所有不同的类一起运行,但这里至少使用了15个不同的类(因为本书教你如何从头开始构建游戏引擎) 。 Sprite类和类似的辅助类(引擎,画布,纹理,动画等)都在一个单独的包中,&#34; game.engine&#34;。以下是实际在模拟器上运行的Game类:

/**
 * Animation System Demo
 * Requires game.engine.Engine to build
 */

import android.graphics.*;
import game.engine.*;

public class Game extends game.engine.Engine
{

    Canvas canvas;
    Timer timer;
    Sprite kitty;
    Texture kitty_image;
    Sprite horse;
    Texture horse_image;
    Sprite runningCat;
    Texture runningCat_image;
    Sprite ship;
    Texture ship_image;

public Game()
{
    canvas = null;
    timer = new Timer();
    kitty = null;
    kitty_image = null;
    horse = null;
    horse_image = null;
    runningCat = null;
    runningCat_image = null;
    ship = null;
    ship_image = null;

}

public void init() {
    setScreenOrientation(Engine.ScreenModes.LANDSCAPE);

}

public void load() {
    /**
     * create kitty sprite
     */
    kitty = new Sprite(this, 32, 32, 12);
    kitty_image = new Texture(this);

    if (!kitty_image.loadFromAsset("cutekitties.png"))
    {
        fatalError("Error loading cutekitties");
    }
    kitty.setTexture(kitty_image);
    kitty.position = new Point(20, 60);
    kitty.setAlpha(0);

    /**
     * create horse sprite
     */
    horse = new Sprite(this, 152, 154, 4);
    horse_image = new Texture(this);
    if (!horse_image.loadFromAsset("horserunning.png"))
    {
        fatalError("Error loading horserunning");
    }
    horse.setTexture(horse_image);
    horse.position = new Point(20, 260);

    /**
     * create running cat sprite
     */
    runningCat = new Sprite(this, 512, 256, 2);
    runningCat_image = new Texture(this);
    if (!runningCat_image.loadFromAsset("runningcat.png"))
    {
        fatalError("Error loading runningcat");
    }
    runningCat.setTexture(runningCat_image);
    runningCat.position = new Point(300, 90);

    /**
     * create ship sprite (NO FRAMES)
     */
    ship = new Sprite(this);
    ship_image = new Texture(this);
    if (!ship_image.loadFromAsset("ship1.png"))
    {
        fatalError("Error loading ship1");
    }
    ship.setTexture(ship_image);
    ship.position = new Point(300, 300);
    ship.setScale(0.5f);

    /**
     * add animation techniques to the sprites
     */

    kitty.addAnimation(new FrameAnimation(12, 14, 1));
    kitty.addAnimation(new AlphaAnimation(0, 255, 5));

    horse.addAnimation(new FrameAnimation(0, 7, 1));
    horse.addAnimation(new ThrobAnimation(0.5f, 3.0f, 0.01f));

    runningCat.addAnimation(new FrameAnimation(0, 7, 1));
    runningCat.addAnimation(new CircularMovementAnimation(
            runningCat.position.x, runningCat.position.y, 
            60, 0.0, 0.1f) );

    ship.addAnimation(new ThrobAnimation(0.2f, 1.5f, 0.1f));
}

public void draw() {
    canvas = getCanvas();
    drawText("Animation System Demo", 10, 20);

    // draw the kitty
    kitty.draw();
    int x = kitty.position.x;
    int y = kitty.position.y + 128;
    drawText("Frame: " + toString(kitty.getFrame()), x, y);
    drawText("Alpha: " + kitty.getAlpha(), x, y+30);

    // draw the horse
    horse.draw();
    x = horse.position.x;
    y = horse.position.y + 128;
    drawText("Frame: " + horse.getFrame(), x, y);
    drawText("Scale: " + toString(horse.getScale()), x, y+30);

    // draw the running cat
    runningCat.draw();
    x = runningCat.position.x;
    y = runningCat.position.y + 128;
    drawText("Frame: " + runningCat.getFrame(), x, y);
    drawText("Pos: " + toString(runningCat.position.x) + ", " + 
            toString(runningCat.position.y), x, y+30);

    // draw the ship
    ship.draw();
    x = ship.position.x;
    y = ship.position.y+128;
    drawText("Pos: " + toString(ship.position.x) + ", " +
            toString(ship.position.y), x, y+30);
}

public void update() {

    // set animation to 50 fps
    if (timer.stopwatch(20))    //ms, 20 milliseconds per frame, 50 frames in 1 second
    {

        // update kitty animation
        kitty.animate();

        // reset alpha animation
        if (kitty.getAlpha() >= 255)
        {
            kitty.setAlpha(0);
            kitty.addAnimation(new AlphaAnimation(0, 255, 1));
        }

        // update horse animation
        horse.animate();

        // reset throb animation
        if (horse.getScale().x <= 0.5f)
        {
            horse.addAnimation(new ThrobAnimation(0.5f, 3.0f, 0.01f));
        }

        // update running cat animation
        runningCat.animate();

        // update ship animation
        ship.animate();

        // reset throb animation
        if (ship.getScale().x <= 0.2f)
        {
            ship.addAnimation(new ThrobAnimation(0.2f, 1.5f, 0.1f));
        }


    }

}

//end of class
}

0 个答案:

没有答案