2017-02-17 7 views
8

Mam arkusz sprite o wymiarach 612x864 z 5 rzędami i 5 kolumnami. Mój problem polega na tym, jak mogę go załadować i ożywić? Chcę przenieść duszek kota tylko na osi Y. Już próbowałem, ale mój kod nie działa poprawnie. Oto mój kod.Jak załadować arkusz sprite z 5 rzędami i 5 kolumnami w widoku z góry w systemie Android?

W GameView.java

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class GameView extends SurfaceView { 
private Bitmap bmp; 
private SurfaceHolder holder; 
private GameLoopThread gameLoopThread; 
private Sprite sprite; 

public GameView(Context context) { 
    super(context); 
    gameLoopThread = new GameLoopThread(this); 
    holder = getHolder(); 
    holder.addCallback(new SurfaceHolder.Callback() { 

     @Override 
     public void surfaceDestroyed(SurfaceHolder holder) { 
      boolean retry = true; 
      gameLoopThread.setRunning(false); 
      while (retry) { 
       try { 
        gameLoopThread.join(); 
        retry = false; 
       } catch (InterruptedException e) { 
       } 
      } 
     } 

     @Override 
     public void surfaceCreated(SurfaceHolder holder) { 
      gameLoopThread.setRunning(true); 
      gameLoopThread.start(); 
     } 

     @Override 
     public void surfaceChanged(SurfaceHolder holder, int format, 
            int width, int height) { 
     } 
    }); 
    bmp = BitmapFactory.decodeResource(getResources(), R.drawable.catsprite); 
    sprite = new Sprite(this,bmp); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.drawColor(Color.BLACK); 
    sprite.onDraw(canvas); 
} 
} 

GameLoopThread.java

import android.graphics.Canvas; 

public class GameLoopThread extends Thread { 
static final long FPS = 10; 
private GameView view; 
private boolean running = false; 

public GameLoopThread(GameView view) { 
    this.view = view; 
} 

public void setRunning(boolean run) { 
    running = run; 
} 

@Override 
public void run() { 
    long ticksPS = 1000/FPS; 
    long startTime; 
    long sleepTime; 
    while (running) { 
     Canvas c = null; 
     startTime = System.currentTimeMillis(); 
     try { 
      c = view.getHolder().lockCanvas(); 
      synchronized (view.getHolder()) { 
       view.onDraw(c); 
      } 
     } finally { 
      if (c != null) { 
       view.getHolder().unlockCanvasAndPost(c); 
      } 
     } 
     sleepTime = ticksPS-(System.currentTimeMillis() - startTime); 
     try { 
      if (sleepTime > 0) 
       sleep(sleepTime); 
      else 
       sleep(10); 
     } catch (Exception e) {} 
    } 
} 
} 

Sprite.java

import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Rect; 

public class Sprite { 
private static final int BMP_ROWS = 5; 
private static final int BMP_COLUMNS = 5; 
private int x = 0; 
private int y = 0; 
private int ySpeed = 3; 
private GameView gameView; 
private Bitmap bmp; 
private int currentFrame = 1; 
private int width; 
private int height; 

public Sprite(GameView gameView, Bitmap bmp) { 
    this.gameView = gameView; 
    this.bmp = bmp; 
    this.width = bmp.getWidth()/BMP_COLUMNS; 
    this.height = bmp.getHeight()/BMP_ROWS; 
} 

private void update() { 
    if (y > gameView.getWidth() - width - y) { 
     ySpeed = -5; 
    } 
    if (y + y < 0) { 
     ySpeed = 5; 
    } 
    y = y + ySpeed; 
    currentFrame = ++currentFrame % BMP_COLUMNS; 
} 

public void onDraw(Canvas canvas) { 
    update(); 
    int srcX = currentFrame * width; 
    int srcY = 1 * height; 
    Rect src = new Rect(srcX, srcY, srcX + width, srcY + height); 
    Rect dst = new Rect(x, y, x + width, y + height); 
    canvas.drawBitmap(bmp, src, dst, null); 
} 
} 
+2

Należy rozważyć użycie silnika gry, takiego jak LibGDX. Posiada klasy i metody, które sprawiają, że tego typu rzeczy są bardzo bezbolesne. –

+0

p.s. Z tego co wiem, jedynym powodem, dla którego przechodzisz 'GameView' do konstruktora' Sprite' jest wykrywanie kolizji z bokiem ekranu. Sugeruję wysłanie parametru 'int maxY' do konstruktora' Sprite' zamiast 'GameView'. Spowoduje to rozłączenie klas 'Sprite' i' GameView'. –

+0

Dziękuję sir @ Code-Apprentice za komentarz. Spróbuję, używając silnika gry. –

Odpowiedz

3

będę zalecamy używanie this bibliotekę. Jest świetny do animacji Sprite. Ma pewne ograniczenia, ale działa dobrze.

Oto kod jak to zrobiłem.

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.runningcat); 
int width = bitmap.getWidth(); 
int height = bitmap.getHeight(); 

int frameWidth = width/5; //you have 5 columns 
int frameHeight = height/5; //and 5 rows 
int frameNum = 25;    //there would be 25 images 


SpriteSheetDrawer spriteSheetDrawer = new SpriteSheetDrawer(
     bitmap, 
     frameWidth, 
     frameHeight, 
     frameNum) 
     .spriteLoop(true) 
     .frequency(2); //change it as per your need 


DisplayObject displayObject = new DisplayObject(); 
displayObject 
     .with(spriteSheetDrawer) 
     .tween() 
     .tweenLoop(true) 
     .transform(0, 0) //I have changed it according to my need, you can also do this by changing these values 
     .toX(4000, 0) //this one too. 
     .end(); 
//In actual example, it's set as animation starts from one end of the screen and goes till the other one. 


FPSTextureView textureView = (FPSTextureView) findViewById(R.id.fpsAnimation); 
textureView.addChild(displayObject).tickStart(); 
3

Problem dotyczy wartości src, której używasz w metodzie. canvas.drawBitmap(bmp, src, dst, null); srcY powinno wynosić zero. Testowałem tutaj.

private Bitmap character; 
private counter,charFrame; 
private RectF annonymousRectF; 
private Rect annonymousRect; 

public Sprite() { 
    character=BitmapFactory.decodeResource(context.getResources(), R.drawable.flipchar2); 
    annonymousRect=new Rect(); 
    annonymousRectF=new RectF(); 
} 

public void update() { 
    counter++; 
    if(counter%5==0) 
     if(charFrame<NO_CHAR_FRAME-1) 
      charFrame++; 
     else 
      charFrame=0; 
} 

public void draw(){ 
    annonymousRect.set(charFrame*character.getWidth()/NO_CHAR_FRAME,0,(charFrame+1)*character.getWidth()/NO_CHAR_FRAME,character.getHeight()); 
    annonymousRectF.set(-width*.015f,height*.35f,width*.5f,height*.58f); //set value according to where you want to draw 
    canvas.drawBitmap(character, annonymousRect,annonymousRectF, null); 
} 
Powiązane problemy