You are here

Chapter 22: How to deal with scaling

In order to really visualize the scaling, we can draw two circles around each asteroid, one as wide as we thought our image was and one as wide as Android says it is.

To do this, we can add two more Paints in the AsteroidHandler constructor:

 public AsteroidHandler(Resources resources, int level) {
  random = new Random();

  paint = new Paint();
  
  yellowPaint = new Paint();
  yellowPaint.setColor(Color.YELLOW);
  yellowPaint.setStyle(Style.STROKE);
  
  whitePaint = new Paint();
  whitePaint.setColor(Color.WHITE);
  whitePaint.setStyle(Style.STROKE);

and use them to draw two circles after drawing each asteroid in AsteroidHandler's draw() method:

 public void draw(Canvas canvas) {
  for (Asteroid asteroid : asteroids) {
   asteroid.draw(canvas, asteroid.x, asteroid.y, paint);
   canvas.drawCircle(asteroid.x, asteroid.y, asteroidRadiuses[asteroid.size], whitePaint);
   canvas.drawCircle(asteroid.x, asteroid.y, asteroid.bitmap.getWidth()/2, yellowPaint);
  }
}

The result speaks for itself:

Having an array of asteroidRadiuses was obviously not meaningful here.

We can easily verify this, by changing the detection itself in AsteroidHandler.update():

  // if (distance <= (asteroidRadiuses[thisAsteroid.size] + asteroidRadiuses[otherAsteroid.size])) {
  if (distance <= (thisAsteroid.bitmap.getWidth() / 2 + otherAsteroid.bitmap.getWidth() / 2)) {

Great! Now we can clearly see that intersections of yellow circles gives red asteroids, while white circles are harmless:

 

After this discovery, I erase all traces of asteroidRadiuses from AsteroidHandler.java. By doing that, I will also have to remove the drawing of the white circles, and while we're at it, we might as well remove the yellow circle and the two new Paints (whitePaint and yellowPaint).

As there is no real use case for bouncing objects in this game, I decided that I won't deal with the physics behind impacts any further in this tutorial. It is likely to cover a few chapters in itself and it is better to cover that in another article.

So, I'm more or less finished with the collision detection for now. (I'll leave the red highlighting of colliding asteroids in the code. It might be of use later on.)

 

Lessons learned in this and the previous chapter are quite a few:

  1. Avoid shortcuts. If I created three versions of asteroid_whole (ldpi, mdpi and hdpi) from the beginning, scaling would not have occurred.
  2. Dig deeper. There is something called BitmapFactory.Options. That one has a property called inScaled that can be set to false and then passed to BitmapFactory.decodeResource() to prevent scaling. Who would have thought...  (It would not have worked well in this game though, as I took the shortcut with only one size of the graphics.)
  3. Take small steps. Make sure that your app is "runnable" all the time. Test after each addition of functionality. No "Big Bang" tests at the end of the project.
  4. Choose your debugging tools wisely. We used "Toast" to verify slow events, such as user input. We used profiling to identify bottlenecks. And now we used additional visualization to troubleshoot frequently updated graphics.
Next chapter will introduce the ship!

Comments

When I draw circles around each asteroid, they have equal radio, because asteroid.bitmap.getWidth()/2 is 50 and asteroidRadiuses[asteroid.size]= 50 too. ¿What should be the value in each case? 
 
Euler.

ajo's picture

Hi Euler,
 
If both circles on your device has the same radius, the scaling is 1:1 in your case.
But in order to make your game work on devices with different scaling, use the getWidth()/2 method.
 
BR - Anders

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer