3D-kreativ
3D-kreativ

Reputation: 9309

How to pass canvas reference to class

I'm doing a simple game and I have a class that I call GameLoop and inside the run() method the code is passing the reference of the canvas to a method that draws a circle. This code is just some testcode.

My question is how do I pass the reference of the canvas if I want to create several sprite objects(classes) with a circle and put them in a list when the game starts? I have done this before, but then I used bitmap in each sprite object and just passed a reference of the image, but in this case I'm not sure how I would do since the canvas is inside the run() method, and I want to create my sprite objects in a method like initializeGameObjects() once in the beginning. I hope my question isn't unclear!? Preciate some help! Thanks!

// Game loop ---------------------------------------
@Override
public void run() {
    // TODO Auto-generated method stub

    while (gameRunning) {
        if (!surfaceHolder.getSurface().isValid())
            continue;

    canvas = surfaceHolder.lockCanvas();

    // Call method to draw objects on screen
    drawObjects(canvas);

    surfaceHolder.unlockCanvasAndPost(canvas);
    }
}
// End game loop ---------------------------------------

// Method that draw everything on canvas
private void drawObjects(Canvas canvas) {

    // Test
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setColor(Color.WHITE);

    // Clear screen with black color
    canvas.drawRGB(0, 0, 0);

    // Draw a circle
    canvas.drawCircle(100, 100, 100, paint);    
}

Upvotes: 1

Views: 1178

Answers (2)

s.d
s.d

Reputation: 29436

Define an interface:

public interface Renderable{
    public void renderToCanvas(Canvas c);
} 

Define a List of Renderables:

private List<Renderable> sprites = new ArrayList<Renderable>();

create methods to add/remove sprites, make sure they are synchronized:

public synchronized void addSprite(Renderable r){
  sprites.add(r);
}

public synchronized void removeSprite(Renderable r){
  sprites.remove(r);
}

This is drawing method, also synchronized, so you don't end up drawing and modifying sprite list at same time. This is either called in a loop by other thread, or a view's onDraw() method:

public synchronized void draw(Canvas c){
  // lock canvas if needed

  // common drawing code

  for(Renderable r :sprites){
    r.renderToCanvas(c);
  }

  // release canvas if locked
}

Now, you are free to define any type of sprite, Circle, Square or whatever,

public class Circle implements Renderable{
  private Paint mPaint;
  private float mRadius;

  public Circle(Paint p, float r){
    mPaint = p;
    mRadius = r;
  }

  @Override
  public void renderToCanvas(Canvas c){
    c.drawCircle(100, 100, mRadius, mPaint);
  }
}

and add it to sprite list:

addSprite(new Circle(new Paint(),20f));

Note: I used synchronized for simplicity, but there are better alternatives to it like atomic flags.These are required only if you want to add/remove sprites while game loop is running. If you setup all sprites before starting game loop, this is not a problem.

Upvotes: 1

Slihp
Slihp

Reputation: 793

I would implement Runnable and construct a Thread. This way you can have a "setup" method which ultimately calls a "start" method. The "start" method would draw to the canvas before starting the thread.

This is actually better practice for this kind of stuff. You may want to init stuff before starting a thread.

public class Game implements Runnable {
    private Thread thisThread = new Thread(this);
    private boolean gameRunning = false;

    public void startGame() {
       gameRunning = true;
       //Draw to canvas
       thisThread.start();
    }

    @Override
    public void run() {
        while(gameRunning) {
        //Draw other objects
        }
    }
}

Upvotes: 1

Related Questions