2017-09-28 18 views
2

J'ai essayé de faire une animation de sprite sous Android (c'est un exercice d'université), mais j'ai un problème étrange. Au lieu de dessiner le rectangle que j'ai défini comme source, il dessine exactement la moitié de ce rectangle.Canvas.drawBitmap couper la source en deux

est ici le code de ma méthode de dessin

public class Sprite { 
Bitmap image; 
Point frameSize; 
int[] rows; 
public int curFrame; 
public int curRow; 

public void draw(Canvas c, Paint p, Vector2 pos) 
{ 
    Rect src; 
    int left = curFrame * frameSize.x; 
    int top = curRow * frameSize.y; 
    int right = left + frameSize.x; 
    int bottom = top + frameSize.y; 

    src = new Rect(left, top, right, bottom); 
    Rect dest = new Rect((int)pos.x, 0, (int)pos.x + frameSize.x, frameSize.y); 

    c.drawBitmap(image, src, dest, p); 
} 

Voici l'image que je suis en utilisant Megaman SpriteSheet

Tous les cadres sont de taille égale (44x40), et l'image est 440x80, et je donne ce valeur en tant que frameSize lorsque j'appelle la méthode. Point est fondamentalement un objet qui contient une paire de x, y ints.

Vector2 est un objet qui contient une paire de x, y flottants. Je rends également du texte à des fins de débogage.

Voici quelques captures d'écran: screenshot: frame zeroscreenshot: frame onescreenshot: frame two

Je suis désolé, les captures d'écran sont énormes. Je ne sais pas s'il y a un moyen de les montrer plus petits dans StackOverflow

Répondre

-1

enter image description here

Je ne vois pas votre code. Ce qui importe est la suivante:

int left = currIndex * peopleWidth; 
int top = 40; 
int right = left + peopleWidth; 
int bottom = 80; 
//clip the bitmap to show 
Rect src = new Rect(left, top, right, bottom); 
//set the display location in view 
Rect display = new Rect(0, 0, mWidth, mHeight); 
canvas.drawBitmap(mBitmap, src, display, null); 

Voici mon code:

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Rect; 
import android.support.annotation.Nullable; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.View; 

import com.rajesh.customcamera.R; 

import java.util.concurrent.TimeUnit; 

import io.reactivex.Observable; 
import io.reactivex.android.schedulers.AndroidSchedulers; 
import io.reactivex.annotations.NonNull; 
import io.reactivex.functions.Consumer; 

/** 
* Created by rajesh.zhu on 2017/9/28. 
*/ 

public class MovingPeopleView extends View { 
    private static final String TAG = "MovingPeopleView"; 
    private int defaultWidth = 44; 
    private int defaultHeight = 40; 
    private int mWidth = 0; 
    private int mHeight = 0; 
    private int peopleWidth = 44; 
    private int peopleHeight = 40; 
    private int currIndex = 0; 

    private Bitmap mBitmap = null; 
    private boolean isRunning = false; 

    public MovingPeopleView(Context context) { 
     this(context, null); 
    } 

    public MovingPeopleView(Context context, @Nullable AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public MovingPeopleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(context); 
    } 

    @Override 
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     int widthMode = MeasureSpec.getMode(widthMeasureSpec); 
     int widthSize = MeasureSpec.getSize(widthMeasureSpec); 

     int heightMode = MeasureSpec.getMode(heightMeasureSpec); 
     int heightSize = MeasureSpec.getSize(heightMeasureSpec); 

     if (widthMode == MeasureSpec.EXACTLY) { 
      //match_parent || absolute_value 
      mWidth = widthSize; 
     } else if (widthMode == MeasureSpec.AT_MOST) { 
      //wrap_content 
      mWidth = Math.min(defaultWidth, widthSize); 
     } else { 
      mWidth = defaultWidth; 
     } 

     if (heightMode == MeasureSpec.EXACTLY) { 
      mHeight = heightSize; 
     } else if (heightMode == MeasureSpec.AT_MOST) { 
      mHeight = Math.min(defaultHeight, heightSize); 
     } else { 
      mHeight = defaultHeight; 
     } 

     setMeasuredDimension(mWidth, mHeight); 
    } 

    private void init(Context context) { 
     mBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.icon_moving_people); 
     //Log.i(TAG, "Width:" + mBitmap.getWidth() + ", Height:" + mBitmap.getHeight()); 
     //you can set the peopleWidth and peopleHeight here 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     super.draw(canvas); 
     int left = currIndex * peopleWidth; 
     int top = 40; 
     int right = left + peopleWidth; 
     int bottom = 80; 
     //clip in bitmap to show 
     Rect src = new Rect(left, top, right, bottom); 
     //set the show location in view 
     Rect display = new Rect(0, 0, mWidth, mHeight); 
     canvas.drawBitmap(mBitmap, src, display, null); 
    } 

    public void start() { 
     isRunning = true; 
     run(); 
    } 

    public void stop() { 
     isRunning = false; 
    } 

    private void run() { 
     if (isRunning) { 
      Observable 
        .timer(100, TimeUnit.MILLISECONDS) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(new Consumer<Long>() { 
         @Override 
         public void accept(@NonNull Long aLong) throws Exception { 
          currIndex++; 
          if (currIndex == 10) { 
           currIndex = 0; 
          } 
          Log.i(TAG, "run"); 
          invalidate(); 
          run(); 
         } 
        }); 
     } 
    } 

    public void recycler() { 
     if (mBitmap != null) { 
      mBitmap.recycle(); 
      mBitmap = null; 
     } 
    } 
} 

vous pouvez l'utiliser en XML:

<com.rajesh.customcamera.view.MovingPeopleView 
    android:id="@+id/moving_people" 
    android:layout_width="50dp" 
    android:layout_height="50dp" /> 
+0

Cette partie Observable semble dangereux. Vous devriez mettre ce code ailleurs et regarder pour l'abonnement. Peut-être commencer observable dans onAttach un désinscription dans onDetach ou sur le changement de visibilité. –