i am a beginning programmer and I am making a flappy-bird kind of game in android studio. I am stuck at making missles coming in from the rightside of the screen. Any hints,tips,tricks on how to approach this problem? I thought myself of making a list of sprites and trying to loop this list an infinite amount of time, but i don't see how.
Kees
public Missles(GamePanel game, Bitmap bmp) {
this.game = game;
this.sprite = bmp;
this.width = bmp.getWidth() / Sprite_Columns;
this.height = bmp.getHeight() / Sprite_Rows;
this.xposition = 1100;
}
private void update() {
//Here we check whether the bitmap touches the bound or not.
//if (xposition > game.getWidth() - width - xspeed) {
// xspeed = -5;
//}
//if (xposition + xspeed < 0) {
// xspeed = 5;
// }
xposition = xposition + xspeed;
currentframe = (currentframe + 1) % Sprite_Columns;
}
public void onDraw(Canvas canvas) {
update();
// Here we cut our bitmap, such that we get the frames from left to right in the columns
int smallrectX = currentframe * width;
//choosing the second row of our sprite sheet, quite confusing y-axis though
int smallrectY = height;
// Making two rectangles, the frame of the spritesheet and
// the position to put it in!
Rect smallrect = new Rect(smallrectX, smallrectY, smallrectX + width, smallrectY + height);
Rect position = new Rect(xposition, yposition, xposition + width, yposition + height);
// making a drawing
canvas.drawBitmap(sprite, smallrect, position, null);
}
}
and my gamepanel:
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {
private Sprite sprite;
private Missles missles;
private SurfaceHolder holder;
private GamePanelThread thread;
private Bitmap bmp;
private Bitmap missle;
private List<Sprite> spriteslist = new ArrayList<Sprite>();
private Bitmap background;
private Bitmap scaledbmp;
private int xposition = 0;
private int xspeed = 1;
public GamePanel(Context context,int resource) {
super(context);
//TODO Auto generated constructor stub
// unpacking sprites and missles
bmp = BitmapFactory.decodeResource(getResources(), resource);
missle = BitmapFactory.decodeResource(getResources(), R.mipmap.angle_sprite);
sprite = new Sprite(this,bmp);
missles = new Missles(this,missle);
// Making the surfaceholder and the thread for the gameloop
holder = getHolder();
holder.addCallback(this);
thread = new GamePanelThread(holder, this);
// This statement improves the performance
setFocusable(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//Here i just creat the scaled background
background = BitmapFactory.decodeResource(getResources(), R.mipmap.cool_background);
float scale = (float)background.getHeight()/(float)getHeight();
int newWidth = Math.round(background.getWidth()/scale);
int newHeight = Math.round(background.getHeight()/scale);
scaledbmp = Bitmap.createScaledBitmap(background, newWidth, newHeight, true);
createSprites();
// starting the thread
thread.setRunning(true);
thread.start();
}
private Sprite createSprite(int resouce) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
return new Sprite(this, bmp);
}
private void createSprites() {
spriteslist.add(createSprite(R.mipmap.angle_sprite));
spriteslist.add(createSprite(R.mipmap.monster_girl_sprite));
spriteslist.add(createSprite(R.mipmap.flyingwoman_sprite));
}
@Override
protected void onDraw(Canvas canvas) {
//Drawing the background and sprites as it is a blackboard.
canvas.drawBitmap(scaledbmp,0,0,null);
sprite.onDraw(canvas);
for (Sprite sprite : spriteslist) {
missles.onDraw(canvas);
}
missles.onDraw(canvas);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// the purpose here is to tell the thread to shut down.
boolean retry = false;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
sprite.up = true;
return true;
}
if(event.getAction() == MotionEvent.ACTION_UP){
sprite.up = false;
return true;
}
return super.onTouchEvent(event);
}
}
and the gameloop:
public class GamePanelThread extends Thread {
private int FPS = 10;
private boolean running;
private SurfaceHolder surfaceholder;
private GamePanel game;
public GamePanelThread(SurfaceHolder surfaceholder, GamePanel game){
super();
this.surfaceholder = surfaceholder;
this.game = game;
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run(){
long startTime;
long sleepTime;
//tijd van gameloop
long ticksPS = 1000 / FPS;
while(running){
startTime = System.nanoTime();
Canvas canvas = null;
try {
canvas = surfaceholder.lockCanvas();
synchronized (surfaceholder)
{
game.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceholder.unlockCanvasAndPost(canvas);
}
sleepTime = ticksPS - (System.nanoTime()- startTime);//laatste deel is hoeveel seconden om 1 loop om te gaan;
try{
if(sleepTime>0) {
this.sleep(sleepTime);
} else {
sleep(10);
}
} catch (Exception e) {}
}
}
}
}
To keep track of an infinite number of sprites will require an infinite number amount of memory and take an infinite amount of time to draw. IE it won't work.
What you instead want, is to create some object, draw it on the screen and quietly recycle it once it goes off the screen.
The topic you need to look up is "object pool".
I would probably have a array of 5-10 missiles. Each of them would have a bitmap, a location & a boolean 'isAlive' flag. When I want to create a missile, I would look for a missile which isAlive==false and activate it. I only need to update, draw & check collisions for the isAlive objects. Once they move off the screen, set isAlive=false and they can be reused again.
This will probably be used for a lot of the stuff in an infinite runner game.