This is the 7th day of my participation in Gwen Challenge

preface

In the first three chapters (juejin.cn/post/696995…) , (juejin. Cn/post / 697032…). , (juejin. Cn/post / 697068…). LibGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX: libGDX

In order to more clearly describe the functions of each API, we will use a large number of codes and descriptions to explain the functions and uses of each API. Therefore, we will divide the development of small games into four parts. Due to space constraints, we will divide it into three chapters to explain the main contents of each part.

  1. Loading resources
  2. Graphics rendering, screen clearing and sound playback
  3. Mouse keyboard input and movement
  4. Small game complete summary

This chapter is about rendering and clearing the screen

Rendering barrels

It’s time to render our buckets. The first thing we’re going to do is clear the screen in dark blue. Simply change the Render () method to something like this:


	@Override
	public void render(a) {
	ScreenUtils.clear(0.0.0.2 f.1); . more to come here ... }Copy the code

Clear (r, g, b, a) represents the red, green, blue and alpha components of the color, respectively, and each component is within the range of [0, 1].

Next, we need to tell our camera to make sure it’s updated. The camera uses mathematical entities called matrices, which are responsible for setting the coordinate system used for rendering. These matrices need to be recalculated every time we change a camera property (for example, location). In our simple example, we don’t do this, but it’s usually a good habit to update the camera every frame:


 camera.update();

Copy the code

Now we can render our bucket:


	batch.setProjectionMatrix(camera.combined);
	batch.begin();
	batch.draw(bucketImage, bucket.x, bucket.y);
	batch.end();

Copy the code

The first line tells SpriteBatch to use the coordinate system specified by the camera. As mentioned earlier, this is done through something called a projection matrix, which the camera.combined field is used to specify. From here SpriteBatch renders everything in the coordinate system.

Next we tell SpriteBatch to start a new batch task. Why do we need this batch task? This involves the principle of OpenGL rendering. Theoretically speaking, if every image needs to be rendered by GPU once, so many images on a screen need to be rendered once, which is obviously inefficient. So we gave OpengL many image rendering tasks at once and asked it to render them for us at once, which effectively increased the frame rate of the game and reduced gpu usage.

Using SpriteBatch helps optimize OpenGL rendering efficiency. It logs all drawing commands spriteBatch.begin () and spriteBatch.end () in between. Once we call spriteBatch.end (), it immediately commits all of our drawing rendering requests, making rendering much faster. All of this may seem like a lot of trouble at first, but that’s the difference between rendering 500 sprites at 60 frames per second and 100 sprites at 20 frames per second.

Add raindrops and render raindrops

For raindrops, we keep a List of Rectangle instances, each of which holds the position and size of the raindrops.


   private Array<Rectangle> raindrops;
Copy the code

The Array Array is used to replace standard Java collections like the libGDX utility class ArrayList. The problem with the latter is that they produce waste in various ways. This Array class tries to minimize garbage. LibGDX also provides other garbage collector aware collections, such as hash-maps or sets.

We also need to keep track of the last time raindrops were generated, so we add another field:


   private long lastDropTime;
Copy the code

We’re going to store time in nanoseconds, which is why we’re using long.

To make it easy to create raindrops, we’ll write a method called spawnRaindrop() that instantiates a Rectangle object and sets it to a random position on the top edge of the screen and adds it to the Raindrops array.


   private void spawnRaindrop(a) {
      Rectangle raindrop = new Rectangle();
      raindrop.x = MathUtils.random(0.800-64);
      raindrop.y = 480;
      raindrop.width = 64;
      raindrop.height = 64;
      raindrops.add(raindrop);
      lastDropTime = TimeUtils.nanoTime();
   }
Copy the code

This method is self-explanatory. MathUtils is a libGDX class that provides static methods for various mathematical computations. In this case, it will return a random value between 0 and 800-64. TimeUtils is another libGDX class that provides some very basic date-time static methods. In this case, we record the current time in nanoseconds, based on which we will later decide whether to produce a new droplet.

In the create() method, we now instantiate the raindrop array and generate our first raindrop:

We need to instantiate the array in the create() method:


   raindrops = new Array<Rectangle>();
   spawnRaindrop();
Copy the code

Next, we add a few lines of code to the Render () method that checks how much time has passed since we generated a new raindrop and creates a new raindrop if necessary:


   if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop();
Copy the code

We also need to make the drop move, at a constant rate of 200 pixels per second. If the raindrops are below the bottom edge of the screen, remove them from the array.


   for (Iterator<Rectangle> iter = raindrops.iterator(); iter.hasNext(); ) {
      Rectangle raindrop = iter.next();
      raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
      if(raindrop.y + 64 < 0) iter.remove();
   }
Copy the code

We also need to render raindrops. Add raindrops to the SpriteBatch rendering code:


   batch.begin();
   batch.draw(bucketImage, bucket.x, bucket.y);
   for(Rectangle raindrop: raindrops) {
      batch.draw(dropImage, raindrop.x, raindrop.y);
   }
   batch.end();
Copy the code

One final piece of logic: If a raindrop hits the bucket, we want to play the sound of the drop and remove the raindrop from the array. Simply add the following lines to the raindrop update loop:


      if(raindrop.overlaps(bucket)) {
         dropSound.play();
         iter.remove();
      }
Copy the code

The rectangle.overlaps () method checks whether a Rectangle overlaps another. In this example, we let the water drop sound play by itself and remove the drops from the array.

Clear the screen and reclaim the object instance

Users can close the application at any time. There is nothing special to do for our simple little game demo. But in general, cleaning up a few object instances we created earlier is good for reducing memory footprint and improving game performance.

Any libGDX class that implements the Disposable interface and therefore has the Dispose () method needs to be manually cleaned up when no longer in use. In our example, for textures, sound and music and SpriteBatch. As excellent program apes, we rewrite the ApplicationAdapter. The dispose () method is as follows:


   @Override
   public void dispose(a) {
      dropImage.dispose();
      bucketImage.dispose();
      dropSound.dispose();
      rainMusic.dispose();
      batch.dispose();
   }
Copy the code

Once a resource is reclaimed, it should not be accessed in any way.

Disposables is usually a resource that the Java garbage collector does not process. That’s why we need to process them manually. LibGDX provides several ways to help with resource management.

So far, you’ve seen the libGDX API for resource management and graphics rendering, sound playback, and how to clean up object instances and reclaim the contents of memory. The next chapter will show you how to use input devices such as a mouse and keyboard to move sprites around in the game.

If you think the blogger wrote well, you are welcome to “follow, like, favorites”.