2017-02-17 3 views
8

5 행 5 열의 612x864 크기의 스프라이트 시트가 있습니다. 내 문제는 어떻게로드하고 애니메이션을 적용 할 수 있습니까? 나는 고양이 스프라이트를 y 축에서만 이동하려고합니다. 이미 시도했지만 코드가 제대로 작동하지 않습니다. 여기 내 코드가있다. GameView.java안드로이드에서 상위 5 개 행과 5 개 열로 스프라이트 시트를로드하는 방법은 무엇입니까?

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

LibGDX와 같은 게임 엔진을 사용해야합니다. 그것은 이런 종류의 것을 매우 고통스럽게 만드는 클래스와 메소드를 가지고 있습니다. –

+0

p.s. 내가 말할 수있는 것부터'GameView'를'Sprite' 생성자에 전달하는 유일한 이유는 화면의 측면과의 충돌 감지 때문입니다. 'int maxY' 매개 변수를'GameView'가 아닌'Sprite' 생성자에 보내는 것이 좋습니다. 이것은'Sprite'와'GameView' 클래스를 분리합니다. –

+0

귀하의 의견에 대해 고맙습니다. @ Code-Apprentice. 나는 게임 엔진을 사용해 그것을 시도 할 것이다. –

답변

3

난 당신이 this 라이브러리를 사용하는 것이 좋습니다 것입니다에서

. 그것은 Sprite 애니메이션에 적합합니다. 그것은 몇 가지 제한이 있지만, 잘 작동합니다.

다음은 코드 작성 방법입니다.

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

메소드에 사용중인 src 값에 문제가 있습니다. canvas.drawBitmap(bmp, src, dst, null); srcY는 0이어야합니다. 나는 여기서 시험했다.

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); 
} 
관련 문제