Ich habe ein kurzes Spiel mit einem SurfaceView. Mein "Schiff" ist nur ein weißes Rechteck, und die Hindernisse sind Bitmaps von Asteroiden. Wenn ein Asteroid mit dem Schiff kollidiert, soll eine Explosionsanimation stattfinden, bei der 20 Trümmerstücke (nur ein 10 x 10 weißer Punkt) in alle Richtungen fliegen.Bitmap-Explosionsanimation an einer Stelle drehend, nicht nach außen gehend
Das Problem ist, dass, wenn die Kollision auftritt, werden alle die Trümmer sitzt nur an einem Ort Spinnen in einem Kreis, wie hier gezeigt:
Die Explosion in der Tat an der exakten Position startet meiner Schiff. Die Partikel bewegen sich einfach nicht nach außen. Habe ich den Code an der falschen Stelle platziert? Weiß jemand wo ich damit falsch gelaufen bin? Hier
ist die Klasse:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.Random;
public class GameView extends SurfaceView implements Runnable, SurfaceHolder.Callback {
private Thread gameViewThread = null;
SurfaceHolder surfaceHolder;
boolean okToRun;
/*
SHIP AND ASTEROID STUFF
*/
private Ship ship;
private Point shipPoint;
private Rect textRect = new Rect();
private float oldX;
private float oldY;
private AsteroidController asteroidController;
/*
END SHIP AND ASTEROID STUFF
*/
/*
GAME OVER STUFF
*/
private boolean isMoving = false;
private boolean isGameOver = false;
private long waitTime;
/*
END GAME OVER STUFF
*/
/*
EXPLOSION STUFF
*/
Bitmap explosionBMP;
private Matrix[] explosion = new Matrix[20];
boolean isDestroyed = false;
boolean explosionStarted = false;
float[] explosionXPosition = new float[20];
float[] explosionYPosition = new float[20];
float explosionSpeed = 20.0f;
float[] explosionRotation = new float[20];
/*
END EXPLOSION STUFF
*/
/*
SCREEN DIMENSIONS
*/
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int gameWidth = displayMetrics.widthPixels;
int gameHeight = displayMetrics.heightPixels;
/*
END SCREEN DIMENSIONS
*/
public GameView(Context context) {
super(context);
surfaceHolder = this.getHolder();
okToRun = true;
ship = new Ship(new Rect(100, 100, 200, 200), Color.WHITE);
shipPoint = new Point(gameWidth/2, 3 * gameHeight/4);
ship.update(shipPoint);
asteroidController = new AsteroidController(context);
//JUST SPAWNING ONE ASTEROID FOR NOW
asteroidController.createAsteroid(1);
//JUST A 10 x 10 WHITE DOT
explosionBMP = BitmapFactory.decodeResource(getResources(), R.drawable.explosion_debris);
//DON'T WANT A NULL POINTER RIGHT OFF THE BAT
for(int i = 0; i < explosion.length; i++) {
explosion[i] = new Matrix();
}
setFocusable(true);
}
@Override
public void run() {
while(okToRun) {
if(!surfaceHolder.getSurface().isValid()) {
continue;
}
Canvas gameCanvas = surfaceHolder.lockCanvas();
this.update();
this.draw(gameCanvas);
surfaceHolder.unlockCanvasAndPost(gameCanvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isMoving = true;
oldX = event.getX();
oldY = event.getY();
if (isGameOver && System.currentTimeMillis() - waitTime >= 3000) {
isGameOver = false;
resetGame();
}
break;
case MotionEvent.ACTION_MOVE:
if (!isGameOver && isMoving) {
/*
THIS CODE ALLOWS TOUCH EVENT TO BE ANYWHERE ON SCREEN WHILE
SHIP MOVES ACCORDINGLY
*/
float newX = event.getX();
float newY = event.getY();
float deltaX = getOffsetCoords(oldX, newX, shipPoint.x);
float deltaY = getOffsetCoords(oldY, newY, shipPoint.y);
shipPoint.set((int) deltaX, (int) deltaY);
oldX = newX;
oldY = newY;
}
return false;
}
return true;
}
/*
GET THE DIFFERENCE IN SHIP COORDS AND TOUCH COORDS
*/
private float getOffsetCoords(float oldVal, float newVal, float current) {
return current + (newVal - oldVal);
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
//RANDOMS FOR STARS
Random random0 = new Random();
Random random1 = new Random();
//BACKGROUND
canvas.drawColor(Color.BLACK);
Bitmap single_pixel_star = BitmapFactory.decodeResource(getResources(), R.drawable.single_pixel_star);
Bitmap three_pixel_star = BitmapFactory.decodeResource(getResources(), R.drawable.three_pixel_star);
//Draw random stars on the canvas
canvas.drawBitmap(single_pixel_star, random0.nextInt(canvas.getWidth() - single_pixel_star.getWidth()), random0.nextInt(canvas.getHeight() - three_pixel_star.getHeight()), null);
canvas.drawBitmap(three_pixel_star, random1.nextInt(canvas.getWidth() - three_pixel_star.getWidth()), random1.nextInt(canvas.getHeight() - three_pixel_star.getHeight()), null);
//DRAW ASTEROID(s)
asteroidController.render(canvas);
//DRAW SHIP
ship.draw(canvas);
if (isGameOver) {
ship.removeShip();
isDestroyed = true;
explosionStarted = true;
Paint gameOverPaint = new Paint();
gameOverPaint.setTextSize(200);
gameOverPaint.setColor(Color.RED);
showGameOver(canvas, gameOverPaint, "YOU LOSE!");
/*
SHIP GOES KABOOM!
*/
for(int i = 0; i < explosion.length; i++) {
canvas.drawBitmap(explosionBMP, explosion[i], null);
}
}
}
public void update() {
if (!isGameOver) {
ship.update(shipPoint);
asteroidController.update();
if (asteroidController.isCollision(ship)) {
isGameOver = true;
waitTime = System.currentTimeMillis();
}
}
Matrix[] localExplosionDebris = new Matrix[20];
if(explosionStarted) {
for(int i = 0; i < explosionXPosition.length; i++) {
explosionXPosition[i] = getShipPointX();
explosionYPosition[i] = getShipPointY();
Random rand = new Random();
explosionRotation[i] = (float) rand.nextInt(360);
}
explosionStarted = false;
}
for(int i = 0; i < localExplosionDebris.length; i++) {
localExplosionDebris[i] = new Matrix();
}
if(isDestroyed) {
for(int i = 0; i < localExplosionDebris.length; i++) {
float debrisXSpeed = (float) Math.sin(explosionRotation[i]*(Math.PI/180)) * explosionSpeed - .2f;
float debrisYSpeed = (float) Math.cos(explosionRotation[i]*(Math.PI/180)) * explosionSpeed - .2f;
explosionXPosition[i] += debrisXSpeed;
explosionYPosition[i] -= debrisYSpeed;
localExplosionDebris[i].postRotate(0, explosionBMP.getWidth()/2, explosionBMP.getHeight()/2);
localExplosionDebris[i].postTranslate(explosionXPosition[i], explosionYPosition[i]);
explosion[i].set(localExplosionDebris[i]);
}
}
}
/*
SHOW GAME OVER TEXT ON THE CENTER OF THE SCREEN UNTIL 3 SECONDS HAVE PASSED AND TOUCH EVENT OCCURS
*/
private void showGameOver(Canvas canvas, Paint paint, String gameOverString) {
paint.setTextAlign(Paint.Align.LEFT);
canvas.getClipBounds(textRect);
int canvasH = textRect.height();
int canvasW = textRect.width();
paint.getTextBounds(gameOverString, 0, gameOverString.length(), textRect);
float textX = canvasW/2f - textRect.width()/2f - textRect.left;
float textY = canvasH/2f - textRect.height()/2f - textRect.bottom;
canvas.drawText(gameOverString, textX, textY, paint);
}
/*
RESET SHIP TO ORIGINAL LOCATION AND COLOR
*/
public void resetGame() {
ship = new Ship(new Rect(100, 100, 200, 200), Color.WHITE);
shipPoint = new Point(gameWidth/2, 3 * gameHeight/4);
//TODO STOP BG MUSIC ONCE FILE IS ADDED
//TODO RESET SCORE ONCE ADDED
}
public void pause() {
okToRun = false;
while(true) {
try {
gameViewThread.join();
} catch(InterruptedException e) {
Log.d("ERROR", e.getMessage());
}
break;
}
gameViewThread = null;
}
public void resume() {
okToRun = true;
gameViewThread = new Thread(this);
gameViewThread.start();
}
/*
SELF EXPLANATORY
*/
public int getShipPointX() {
return shipPoint.x;
}
public int getShipPointY() {
return shipPoint.y;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}