2017-11-16 6 views
0

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:

screenshot of explosion

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) { 

    } 
} 

Antwort

0

ich einige boolean Variablen neu geordnet und ich habe jetzt eine Explosion. In der folgenden if-Anweisung, können Sie sehen, was ich auf Kommentar:

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); 
     } 

    } 

Und in einem anderen if-Anweisung, fügte ich eine Bedingung, gegeben, um das auf Kommentar booleans (siehe oben) diese Aussage, setzen sie dann in einem sonst:

if (!isGameOver) { 
     ship.update(shipPoint); 
     asteroidController.update(); 

     if (asteroidController.isCollision(ship) && !isDestroyed) { //<--added the && !isDestroyed 
      isGameOver = true; 
      isDestroyed = true; //<-- added this 
      explosionStarted = true; //<-- and this 
      waitTime = System.currentTimeMillis(); 
     } else { 
      isGameOver = false; //<-- then reset here 
      isDestroyed = false; //<-- and here 
      explosionStarted = false; //<-- and here 
     } 
    } 

Alles fertig. :-)

Showing proof that it works now

Verwandte Themen