Reputation: 9309
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
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
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