我在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
}