I make a logical game for Android. And everything would be fine if it were not for one BUT ... When drawing using the surfaceview, there is a problem when you need to draw many objects. FPS sags to 25-30. More specifically:
There is a two-dimensional array of cells of the field (targets) and an array of elements of the same size that need to be moved (balls). In the method of drawing the playing field, I first run through the array of cells, and then - through the array of elements.
private void presentField(){ Graphics g = game.getGraphics(); fieldCanvas.drawRect(0,0,fieldBitmap.getWidth(),fieldBitmap.getHeight(),clearPaint); for(int j=0;j<world.getLevel().getSizeJ();j++){ for(int i=0;i<world.getLevel().getSizeI();i++){ drawGameElement(world.getLevel().getField()[i][j],j,i); } } int chipI=0; int chipJ=0; for(int j=0;j<world.getLevel().getSizeJ();j++){ for(int i=0;i<world.getLevel().getSizeI();i++){ fieldCanvas.drawBitmap(elementBitmap,j*200+getBallShiftX(candyElement),i*200+getBallShiftY(candyElement),null); //} if(world.getLevel().getBalls()[i][j].getColor()!= GameElement.ElementColor.CHIP) { drawGameElement(world.getLevel().getBalls()[i][j], j, i); } else { chipI = i; chipJ = j; } } } drawGameElement(world.getLevel().getBalls()[chipI][chipJ],chipJ,chipI); g.drawBitmap(fieldBitmap, dstRect); } Here is the method that performs the drawing:
private void drawGameElement(GameElement element, int x, int y){ Bitmap atlas=null; int candyShiftX=0; int candyShiftY=0; if(element instanceof Target){ if(element.getColor()== GameElement.ElementColor.CHIP){ fieldCanvas.drawBitmap(Assets.chipTarget, x*200,y*200, null); } else { atlas=Assets.targets; } } else if (element instanceof Ball){ candyShiftX=getBallShiftX((Ball) element); candyShiftY=getBallShiftY((Ball) element); if(element.getColor()== GameElement.ElementColor.CHIP){ fieldCanvas.drawBitmap(Assets.chip, (x*200)+candyShiftX,(y*200)+candyShiftY, null); } else { atlas=Assets.candys; } } if(atlas!=null){ atlasRect.left=getPicIdByColor(element.getColor())*200; atlasRect.top=0; atlasRect.right=(getPicIdByColor(element.getColor())*200)+200; atlasRect.bottom=200; fieldDstRect.left=(x*200)+candyShiftX; fieldDstRect.top=(y*200)+candyShiftY; fieldDstRect.right=(x*200)+200+candyShiftX; fieldDstRect.bottom=(y*200)+200+candyShiftY; fieldCanvas.drawBitmap(atlas,atlasRect,fieldDstRect,null); } } Since the size of the field at each level is different, I draw the fields and elements not in the main Bitmap, but in the auxiliary one. When I run through both arrays, I draw an auxiliary Bitmap in the main one.
I keep the pictures of the elements and fields in the atlases (except for the field and the element that need to be managed, but I don’t think that this detail is important here).
At the first levels, everything works fine - for example, the field size is 3 by 3, FPS is 60. But when the field size becomes 5 by 6, then the FPS drops by half, or even more.
Does anyone know a way to align the FPS with so many elements?
Here is the Assets class:
public class Assets { public static Bitmap background; public static Bitmap curtain; public static Bitmap loadingLabel; public static Bitmap playButtonLabel; public static Bitmap aboutButtonLabel; public static Bitmap winLabel; public static Bitmap targets; public static Bitmap candys; //public static Bitmap blueBall; //public static Bitmap redBall; public static Bitmap chip; //public static Bitmap blueTarget; //public static Bitmap redTarget; public static Bitmap chipTarget; public static Bitmap lockedPack; public static Bitmap pack1; public static Bitmap pack2; public static Bitmap lockedLevel; public static Bitmap levels; public static Bitmap escapeLabel; public static Bitmap escapeButtons; public static Bitmap lives; public static Bitmap lowEnergy; public static Bitmap cat; } I get the pictures from the Assets folder via AssetManager:
Assets.targets = g.newBitmap("targets.png"); Here is my newBitmap method:
public Bitmap newBitmap(String fileName) { Bitmap bitmap=null; InputStream in=null; try{ in = assets.open(fileName); bitmap = BitmapFactory.decodeStream(in); if(bitmap==null) throw new RuntimeException("Couldn't load bitmap from asset '"+fileName+"'" ); } catch (IOException ex){ throw new RuntimeException("Couldn't load bitmap from asset '"+fileName+"'" ); } finally { if(in!=null){ try { in.close(); } catch (IOException ex) { ex.printStackTrace(); } } } return bitmap; }