How to make sprites in Android

2019-04-16 05:44发布

I'm developing a game which includes sprites.

currently I'm loading a bitmap and using Rectangle to get the right frame from the bitmap.

the problem is loading bitmaps takes too much memory and I wont be able to load several sprites at the same time.

what are my alternatives for doing sprite in Android?

2条回答
趁早两清
2楼-- · 2019-04-16 05:50
 /* It is Sprite class */
import android.graphics.*;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;

public class Sprite {

int x;
private int y;
private boolean visibility = true;
private Bitmap sprite;
private int verticalFrame,horizontalFrame;
private int frameWidth,frameHeight;
private int sequence[] = new int[1];
private int maxFrame = 0;
private int currentFrame;
private int color;
private Rect src;
private Rect dest;
private int frameCount;
private Paint p = new Paint();
private int spInitX,spInitY;
private int rotate = 0;
private float currentRotateAngle = 0;
//private Graphics g;
public float velocityY;
public float velocityX;
public int height;

public Sprite(Bitmap sprite){

    this.sprite = sprite;
    this.frameWidth = sprite.getWidth();
    this.frameHeight = sprite.getHeight();
    setFrameCount();
}
public Sprite(Bitmap sprite,int frameWidth,int frameHeight){

    this.sprite = sprite;
    this.frameWidth = frameWidth;
    this.frameHeight = frameHeight;
    setFrameCount();        
}

public void rotate(float angle){
    currentRotateAngle = angle;     
}

public void setImage(Bitmap bm,int frameWidth,int frameHeight){
    this.sprite = bm;
    this.frameWidth = frameWidth;
    this.frameHeight = frameHeight;
}

public Bitmap getBitmap(){
    return sprite;
}
public void paint(Canvas canvas){
    dest.offsetTo(getX(), getY());
//  g.drawImage(sprite, x, y,src.left,src.top,frameWidth,frameHeight);
    canvas.drawBitmap(sprite, src, dest, null);

}


public int getMaxFrame(){
    return maxFrame; 
}
public int getFrameSequenceLength(){
    return sequence.length;
}
public void setFrameSequence(int seq[]){
    sequence = seq;
}

public void previousFrame(){
    if(sequence.length > 1){
          if(frameCount > 0){
             setFrame(sequence[frameCount]);
         frameCount--;
        }else{
         frameCount = sequence.length - 1;
         setFrame(sequence[frameCount]);
        }

     }else{

        setFrame(frameCount);

        if(frameCount > 0){
            frameCount++;
        }else{
            frameCount = maxFrame - 1;
        }
     }
 }

public void setPixel(int x,int y){
    spInitX = x;
    spInitY = y;
    }



public void nextFrame(){
    if(sequence.length > 1){
          if(frameCount < sequence.length){
             setFrame(sequence[frameCount]);
             frameCount++;
          }else{
             frameCount = 0;
             setFrame(sequence[frameCount]);
          }

     }else{

        setFrame(frameCount);

        if(frameCount < maxFrame){
            frameCount++;
        }else{
            frameCount = 0;
        }
     }
}

public int getFrame(){
    return currentFrame;
}
public void setPosition(int x,int y){
    this.x = x;
    this.y = y;

}
public void setFrameCount(){
    verticalFrame = sprite.getHeight() / frameHeight;
    horizontalFrame = sprite.getWidth() / frameWidth;
    src = new Rect(0,0,frameWidth,frameHeight);
    dest = new Rect(0,0,frameWidth,frameHeight);
    maxFrame = verticalFrame * horizontalFrame;
 }

public void setFrame(int frame){

      if(frame < maxFrame){
          currentFrame = frame;  
      }
      int hf = currentFrame % horizontalFrame;
      int vf = currentFrame / horizontalFrame;
      src.left = hf * frameWidth;
      src.right = src.left + frameWidth;
      src.top = vf * frameHeight;
      src.bottom = src.top + frameHeight;
  }

  public boolean collidesWith(Sprite sp,boolean cl){

    int maxHGap = (getWidth() + sp.getWidth())/2;
    int maxVGap = (getHeight() + sp.getHeight())/2;

    int x = getX() + getWidth()/2;
    int y = getY() + getHeight()/2;

    int x1 = sp.getX() + sp.getWidth()/2;
    int y1 = sp.getY() + sp.getHeight()/2;


    if(Math.abs(x - x1) < maxHGap && Math.abs(y - y1) < maxVGap){
        return true;
    }

   return false;
 }


 public void setVisible(boolean v){
    visibility = v;
 }
public final boolean isVisible(){
    return visibility;
}
public  int getX(){
    return x;

}
public  int getY(){
    return y;

}


public void setX(int x) {
    this.x = x;
}
public void setY(int y) {
    this.y = y;
}
public void move(int moveX,int moveY){
    setX(getX()+moveX);
    setY(getY()+moveY);
    //this.y+=y;
    //this.x+=x;
}

  public final int getWidth(){
    return frameWidth;
}
public final int getHeight(){
    return frameHeight;
}
public void setEventY(int i) {
    // TODO Auto-generated method stub

}
public int getEventY() {
    // TODO Auto-generated method stub
    return 0;
}


} 

/*Create Main Thread Class Also */

import java.text.DecimalFormat;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

public class MainThread extends Thread {
boolean isPaused;

private static final String TAG = MainThread.class.getSimpleName();

// desired fps
private final static int MAX_FPS = 50;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS;

/* Stuff for stats */
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp
// we'll be reading the stats every second
private final static int STAT_INTERVAL = 1000; // ms
// the average will be calculated by storing
// the last n FPSs
private final static int FPS_HISTORY_NR = 10;
// last time the status was stored
private long lastStatusStore = 0;
// the status time counter
private long statusIntervalTimer = 0l;
// number of frames skipped since the game started
private long totalFramesSkipped = 0l;
// number of frames skipped in a store cycle (1 sec)
private long framesSkippedPerStatCycle = 0l;

// number of rendered frames in an interval
private int frameCountPerStatCycle = 0;
private long totalFrameCount = 0l;
// the last FPS values
private double fpsStore[];
// the number of times the stat has been read
private long statsCount = 0;
// the average FPS since the game started
private double averageFps = 0.0;

// Surface holder that can access the physical surface
private SurfaceHolder surfaceHolder;
// The actual view that handles inputs
// and draws to the surface
private GameView gv;

// flag to hold game state
private boolean running;

public void setRunning(boolean running) {
    this.running = running;
}

public MainThread(SurfaceHolder surfaceHolder, GameView gv) {
    super();
    this.surfaceHolder = surfaceHolder;
    this.gv = gv;
}

public MainThread(Setting setting) {
    // TODO Auto-generated constructor stub
}

public void setPause(int i) {
    synchronized (gv.getHolder()) {

        if (i == 0) {
            isPaused = false;
        }
        if (i == 1) {
            isPaused = true;
        }
    }
}

@Override
public void run() {
    Canvas canvas;
    Log.d(TAG, "Starting game loop");

    initTimingElements();

    long beginTime; // the time when the cycle begun
    long timeDiff; // the time it took for the cycle to execute
    int sleepTime; // ms to sleep (<0 if we're behind)
    int framesSkipped; // number of frames being skipped

    sleepTime = 0;

    while (running) {
        canvas = null;
        // try locking the canvas for exclusive pixel editing
        // in the surface
        try {
            canvas = this.surfaceHolder.lockCanvas();
            synchronized (surfaceHolder) {
                beginTime = System.currentTimeMillis();
                framesSkipped = 0; // resetting the frames skipped
                // update game state
                this.gv.update();
                // render state to the screen
                // draws the canvas on the panel
                this.gv.render(canvas);
                // calculate how long did the cycle take
                timeDiff = System.currentTimeMillis() - beginTime;
                // calculate sleep time
                sleepTime = (int) (FRAME_PERIOD - timeDiff);

                if (sleepTime > 0) {
                    // if sleepTime > 0 we're OK
                    try {
                        // send the thread to sleep for a short period
                        // very useful for battery saving
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                    }
                }

                while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                    // we need to catch up
                    this.gv.update(); // update without rendering
                    sleepTime += FRAME_PERIOD; // add frame period to check
                                                // if in next frame
                    framesSkipped++;
                }

                if (framesSkipped > 0) {
                    Log.d(TAG, "Skipped:" + framesSkipped);
                }
                // for statistics
                framesSkippedPerStatCycle += framesSkipped;
                // calling the routine to store the gathered statistics
                storeStats();
            }
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } finally {
            // in case of an exception the surface is not left in
            // an inconsistent state
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        } // end finally
    }
   }

 private void storeStats() {
    frameCountPerStatCycle++;
    totalFrameCount++;
    // assuming that the sleep works each call to storeStats
    // happens at 1000/FPS so we just add it up
    // statusIntervalTimer += FRAME_PERIOD;

    // check the actual time
    statusIntervalTimer += (System.currentTimeMillis() - statusIntervalTimer);

    if (statusIntervalTimer >= lastStatusStore + STAT_INTERVAL) {
        // calculate the actual frames pers status check interval
        double actualFps = (double) (frameCountPerStatCycle / (STAT_INTERVAL / 1000));

        // stores the latest fps in the array
        fpsStore[(int) statsCount % FPS_HISTORY_NR] = actualFps;

        // increase the number of times statistics was calculated
        statsCount++;

        double totalFps = 0.0;
        // sum up the stored fps values
        for (int i = 0; i < FPS_HISTORY_NR; i++) {
            totalFps += fpsStore[i];
        }

        // obtain the average
        if (statsCount < FPS_HISTORY_NR) {
            // in case of the first 10 triggers
            averageFps = totalFps / statsCount;
        } else {
            averageFps = totalFps / FPS_HISTORY_NR;
        }
        // saving the number of total frames skipped
        totalFramesSkipped += framesSkippedPerStatCycle;
        // resetting the counters after a status record (1 sec)
        framesSkippedPerStatCycle = 0;
        statusIntervalTimer = 0;
        frameCountPerStatCycle = 0;

        statusIntervalTimer = System.currentTimeMillis();
        lastStatusStore = statusIntervalTimer;
        // Log.d(TAG, "Average FPS:" + df.format(averageFps));
        gv.setAvgFps("FPS: " + df.format(averageFps));
    }
  }

  private void initTimingElements() {
    // initialise timing elements
    fpsStore = new double[FPS_HISTORY_NR];
    for (int i = 0; i < FPS_HISTORY_NR; i++) {
        fpsStore[i] = 0.0;
    }
    Log.d(TAG + ".initTimingElements()",
            "Timing elements for stats initialised");
  }

 }
查看更多
疯言疯语
3楼-- · 2019-04-16 06:03

Try this one:

import org.cocos2d.layers.CCLayer;
public class GameLayer extends CCLayer{

   CCSprite mSprite;    

 protected GameLayer() {
    super();
    CGSize winSize = CCDirector.sharedDirector().winSize();     
    mSprite = new CCSprite("image.png");
    mSprite.setPosition(CGPoint.ccp(mSprite.getContentSize().width/2.0f, mSprite.getContentSize().height/2.0f));
    addChild(mSprite);
 }
查看更多
登录 后发表回答