Android Miscellaneous Notes

game development

Mobile game development requires developers to define all the characters on the interface and elements that can interact with the player in an object-oriented way. At the same time, it is necessary to design the animation management of the game, the animation background thread support, the determination of game rules, and the control of character behavior.

frame building

Usually, the basic framework of game development generally includes the following modules:

  • Window management: This module is responsible for creating, running, suspending, and resuming the game interface on the Android platform.

    We can think of the game's window as a canvas on which content can be drawn. The window management module is responsible for customizing windows, adding various UI components, and accepting input events from various users. These UI components may be accelerated by hardware such as GPU (eg using OpenGL ES).

    The purpose of this module is not to provide an interface, but to integrate with the game framework. What we need to remember is that application state and window events are things that this module has to handle:

    Create: Method called when the window is created.

    Pause: The method called when the application is paused for default reasons.

    Resume: Method called when the application resumes to the foreground.

  • Input module (Input): This module is closely related to the window management module and is used to monitor and track user input (such as touch events, key events, accelerometer events, etc.).

    In most operating systems, input events (such as touch screen events, key events) are dispatched through the current window, and the window further dispatches these events to the currently selected component. So we only need to pay attention to the events of the component. The UI APIs provided by the operating system provide an event distribution mechanism, and we can easily register and listen to events, which is also the main responsibility of the input module. There are two ways to handle events:

    Polling: In this mechanism, we only check the current state of the input device, whether the previous and subsequent states are saved. This type of input event handling is suitable for handling events such as touch buttons, but not for tracking text input, because the sequence of key events is not preserved.

    Event-based handling: This mechanism provides memoized event handling, which is more suitable for handling text input or other operations that require a key sequence. There are two ways: listening and callback.

    In the Android platform, there are mainly three kinds of input events: touch screen events, key events and accelerometer events. The first two kinds of time use the polling mechanism and the mechanism based on event processing are suitable, and the accelerometer event is usually the polling mechanism.

    There are three types of touch screen events:

    Touch down: Occurs when the phone touches the screen.

    Touch drag: Occurs when the finger is dragged, before the Touch down event was generated.

    Touch up: Occurs when the finger is lifted.

    Each touch event has related auxiliary information: the position of the touch screen, the pointer index (used to track and identify different touch points when multi-touch)

    There are two types of keyboard events:

    Key down: Fired when the keyboard is pressed.

    Key up: Fired when the keyboard is released.

    Each key event also has associated auxiliary information: the Key-down event stores the key code, and the Key-up event stores the key code and the actual Unicode character.

    For accelerometer events, the system continuously polls the status of the accelerometer and identifies it with three-dimensional coordinates.

  • File I/O: This module is used to read resources such as pictures and audio in the assets file.

    Reading and writing files is a very important function in game development. In Java development, we mainly focus on InputStream and OutputStream and their instances, which are standard methods of reading and writing files in Java.

    In game development, more resource files are read, such as configuration files, pictures, audio files, etc. The write-to-file operation is typically used to save user progress and configuration information.

  • Graphics module (Graphics): In actual game development, this module is probably the most complex part, it is responsible for loading images and drawing them to the screen.

    Image manipulation module, used to draw images to the screen. However, in order to draw images with high performance, you have to understand some basic image programming knowledge. Let's start with drawing a 2D image, and the first question to understand is: how exactly is an image drawn to the screen? The answer is quite complicated and we don't need to know all the details.

    • Raster, pixel and framebuffers (Framebuffers)

      Modern displays are all based on raster, which is composed of a two-dimensional grid, that is, a grid of pixels. The length and width of the raster grid, we generally use pixels to represent. If we carefully observe the display (or use a magnifying glass), we can find that there are grids one by one on the display, which is the pixel grid or raster grid. The position of each pixel can be represented by coordinates, so a two-dimensional coordinate system is introduced, which also means that the coordinate values ​​are integers. The monitor receives a constant stream of images from the graphics processor, decodes the color of each pixel (programmed or set by the operating system), and draws it to the screen. The display will be refreshed multiple times per second, and the refresh rate unit is Hz. For example, the mainstream refresh rate of LCD displays is 85Hz.

      The graphics processor needs to obtain pixel information for display on the monitor from a special storage area called the video memory area, or VRAM. This area is commonly referred to as the framebuffer. Therefore a complete screen graphic is called a frame. For each pixel in the display grid, there is a corresponding memory address in the framebuffer. When we need to change what is displayed on the screen, we simply need to change the content in the framebuffer.

      The following image is a simple diagram of the display grid and framebuffer:
      write picture description here

    • VSync and Double Buffering

      In ordinary drawing methods, when the object to be drawn is too complex, especially when it contains bitmaps, the picture will be displayed very slowly at this time. For moving pictures, it will give people the feeling of being "stuck", and sometimes it will cause the screen to flicker. So we use double buffering technology (using two framebuffers). The principle of double buffering can be understood in this way: think of the computer screen as a blackboard. First, we create a "virtual" blackboard in the memory environment, and then draw complex graphics on this blackboard. When the graphics are all drawn, we "copy" the graphics drawn in the memory to another one at a time. on the blackboard (screen). Taking this method can improve the drawing speed and greatly improve the drawing effect. Here is the schematic:

    write picture description here

    To know what vertical sync is, you must first understand how a monitor works. All images on the display are scanned line by line, whether it is interlaced scanning or progressive scanning, the display has two synchronization parameters - horizontal synchronization and vertical synchronization. The horizontal sync signal determines the time when the CRT draws a line across the screen. The vertical sync signal determines the time when the CRT draws from the top of the screen to the bottom and returns to its original position. It is precisely the vertical sync that represents the refresh rate level of the CRT display!

    Turn off vertical synchronization: We usually run the operating system, and the screen refresh rate is generally around 85Hz. At this time, the graphics card will send a vertical synchronization signal every time according to the frequency of 85Hz, and the time interval between the signal and the signal is the resolution of 85. Write one screen image time.

    Turn on vertical sync: In games, a powerful graphics card may quickly draw a screen of images, but without the arrival of the vertical sync signal, the graphics card cannot draw the next screen, and can only be drawn when the signal of 85 units arrives. In this way, the fps is naturally restricted by the operating system refresh rate operating value. That is to say, of course, if the FPS of your game screen can reach or exceed the refresh rate of your monitor after opening, the FPS of your game screen will be limited to the refresh rate of your monitor. If it is not achieved, there will be different degrees of frame skipping. The larger the gap between the FPS and the refresh rate, the more serious the frame skipping. Generally, it is recommended to punch in for high-performance graphics cards, and the game screen will be better! After opening, it can prevent the screen tearing phenomenon when the game screen moves at high speed, such as live football.

    Turn off vertical synchronization, then after finishing one screen in the game, the graphics card and the monitor can start the drawing of the next screen image without waiting for the vertical synchronization signal, which can naturally give full play to the strength of the graphics card.

    However, don't forget that it is precisely because of the existence of vertical synchronization that the game process and the refresh rate of the display can be synchronized, making the picture smooth and stable. Cancellation of the vertical synchronization signal, of course, can be exchanged for faster speed, but in terms of image continuity, the performance is bound to be compromised. This is also the theoretical reason why the picture is discontinuous after turning off vertical sync!

    • image format

      Two of the more popular graphics formats are JPEG and PNG. JPEG is a lossy compression format, PNG is a lossless compression format, so the PNG format can reproduce the original image 100%. Lossy compression formats usually take up little disk space. What total compression format we use depends on our disk space. Similar to audio, we need to fully decompress an image when we load it into memory. So even if your compressed image is only 20K on disk, you still need width×height×color depth storage space in RAM.

    • image overlay

      Suppose there is a framebuffer (framebuffer) that we can render to, and there are several pictures loaded into RAM at the same time, we need to put the pictures in RAM into the framebuffer one by one, such as a background image and a foreground image such as As shown in the figure:

      write picture description here

      This process is called image synthesis and overlay. We need to combine different pictures into a final displayed picture. This item for drawing the picture is important because the picture above will always cover the picture below.
      write picture description here
      There is a problem with the image composition above: the white background of the second image covers the first background image. How can we remove the white background of the second image? This requires alpha blending. Alpha blending is a method of calculating the color value of the source point and the color value of the target point according to a certain algorithm to obtain a transparent effect.

      Below are the RGB values ​​of the final composite image, the formula is as follows

      red = src.red * src.alpha + dst.red * (1 – src.alpha)
      blue = src.green * src.alpha + dst.green * (1 – src.alpha)
      green = src.blue * src.alpha + dst.blue * (1 – src.alpha)  

        
      src and dst are the source and destination images that we need to mix (source image is equivalent to person, target image is equivalent to background). Below is an example.

      src = (1, 0.5, 0.5), src.alpha = 0.5, dst = (0, 1, 0)
      red = 1 * 0.5 + 0 * (10.5) = 0.5
      blue = 0.5 * 0.5 + 1 * (10.5) = 0.75
      red = 0.5 * 0.5 + 0 * (10.5) = 0.25

      Results as shown below

      write picture description here

      The above formula uses two multiplications, and the multiplication consumes a lot of time. In order to improve the operation speed, optimization can be performed. Such as

      red = (src.red- dst.red) * src.alpha + dst.red

      Alpha is a floating point number, we can convert it into integer operation, because a color occupies at most 8Bit, so the Alpha value is at most 256, so we multiply the Alpha value by 256, and then divide it by 256 during the operation, we get the following The formula:

      red = (src.red- dst.red) * src.alpha /256+ dst.red

      Here, Alpha is a number from 0 to 256.

      Specifically for this example, we only need to set the alpha value of the white pixels of the source file to 0. The final effect is as follows:
      write picture description here

    • The interface code of the image module

      With the above introduction, we can start designing the interface of our image module. The following functions need to be implemented:

      1. Load the image from disk into memory in preparation for later drawing to the screen.

      2. clear framebuffer with specific color

      3. Draws a pixel at the specified position in the framebuffer with the specified color.

      4. Draw lines and rectangles on the framebuffer.

      5. Draw the picture in the above memory to the framebuffer, which can be drawn in whole and in part, and alpha blended.

      6. Get the length and width of the framebuffer.

      Two interfaces are used here: Graphics and Pixmap

  • Audio module (Audio): This module is responsible for loading various audios in different game interfaces.

    Audio module programming has always been a complex topic. I don't plan to use some advanced and complex audio processing methods here, mainly to play some background music. Before writing code, let's understand the basics of audio.

    Sampling rate: defines the number of samples per second extracted from continuous signals to form discrete signals. The higher the sampling rate, the better the sound quality. The unit is expressed in Hertz (Hz), and CD is generally 44.1KHz. For each sampling system, a certain storage bit (number of bits) will be allocated to express the sound wave amplitude state of the sound wave, which is called the sampling resolution or sampling accuracy. Increase the dynamic range state of 6db, a 2bit digital audio system expresses thousands of states, that is, the dynamic range of 12db, and so on. For example, 16bit can express 65536 states, and 24bit can express up to 16777216 states. The dynamic range refers to the changing range of the sound from the weakest to the strongest. The hearing range of the human ear is usually 20HZ~20KHZ. A higher sample rate means more storage space. For example, the sound of 60s, the sampling rate is 8KHz, 8bits, about 0.5M, the sampling rate is 44KHz, 16bits, more than 5M, and the ordinary 3-minute pop song will exceed 15M.

    In order not to reduce the quality and take up less space, many better compression methods have been proposed. For example, MP3s and OGGs formats are more popular compression formats on the Internet.

    You can see that the 3min song takes up a lot of space. When we play the game's background music, we can stream the audio instead of preloading it into memory. Usually there is only one background music, so it only needs to be loaded to disk once.

    For some short sound effects, like explosions and gun shots, things are different. These short effects are often called multiple times at the same time, and streaming them from disk for each instance is not a good idea. Fortunately, short sound effects do not take up too much memory space, so just read these sound effects into memory in advance, and then you can play them directly at the same time.

    So our code needs to provide the following functions:

    We need a way to load audio files for streaming playback (Music) and memory playback (Sound), while providing the ability to control playback.

    There are three corresponding interfaces, Audio, Music and Sound

    The Audio interface creates new Music and Sound instances. A Music instance represents a streaming audio file, and a Sound instance represents a short sound effect stored in memory. The methods Audio.newMusic() and Audio.newSound() both take the filename as a parameter and throw an IOException in case the file fails to load (for example, the file does not exist or the file is damaged, etc.).

    The Music interface is a bit more complicated and includes methods for playing music streams, pausing and stopping, looping, volume control (floating point from 0 to 1). Of course, there are also some getter methods in it to get the status of the current music instance. When we no longer need the Music instance, we can destroy it (dispose method), which closes the system resource, the streaming audio file.

    The Sound interface is relatively simple, containing only play() and dispose() methods. The former takes the specified volume as an input parameter, and we can play the sound effect whenever we want. In the latter case, when we disallow the Sound instance, we need to destroy it to free the memory space it occupies.

  • Networking: This module is required if the game offers multiplayer networking.

  • Game framework: This module integrates the above modules to provide an easy-to-use framework to easily implement our games.

    With all the groundwork done, let's finally talk about the game framework itself. Let's take a look at what else we need to do in order to run our game:

    • The game is divided into different screens, each of which performs the same task: judging user input and rendering the screen based on the input. Some programs may not require any user input, but will switch to the next screen after a period of time. (eg Splash interface)

    • The screen needs to be managed in some way (like we need to keep track of the current screen and switch to the next screen at any time)

    • The game needs to allow the screen to access different modules (such as image modules, audio modules, input modules, etc.) so that the screen can load resources, get user input, play sounds, render buffers, etc. Because our game is a real-time game, we need the current screen to update quickly. We therefore need a main loop to implement this. The main loop ends when the game exits. Each loop iteration becomes a frame, and the number of frames per second we call the frame rate (FPS).

    • The game needs to track the state of the window (such as whether to pause the game or resume, etc.), and notify the corresponding processing events.

    • The game framework needs to handle the creation of windows, creation of UI components, etc.

    The code first creates the window and UI components of the game, and then we instantiate the basic components, which ensure the realization of the basic functions of the game. We instantiate our start screen again and make it the current screen. Then note the current time.

    Then we enter the main loop, and we can end the main loop when the user wants to exit. In the main loop, the time difference between the previous frame and the current frame is calculated to calculate the FPS. Finally, we update the state of the current screen and present it to the user. The updateState method depends on the time difference and input state, and the present method includes rendering the state of the screen to the framebuffer, playing audio, etc. The present method also needs to know the time difference between the last call and the present.

    When the main loop is over, we need to clean up and release various resources.

    This is how the game works: process the user's input, update the state, and present it to the user.

    • Gaming and Display Interfaces

      1. Establish window and UI, and establish corresponding event mechanism

      2. Start the main loop of the game

      3. Keep track of the current screen display and update it each time the main loop

      4. The events in the UI thread are transferred to the main thread, and these events are passed to the current display interface in order to synchronize changes.

      5. Make sure you have access to all of the game's basic modules such as Input, FileIO, Graphics, and Audio.

Mathematics, physics, AI knowledge

  • math

    Two-point distance, trigonometric functions

  • physics

    One-dimensional space motion (velocity), acceleration, force (gravity, support force, friction [static friction, sliding friction]), Newton's law, momentum and impulse (collision)

  • TO THE

    Game rules are divided into three parts, rule objects, rule events and corresponding rules. The objects we are talking about are mainly characters controlled by players. Of course, non-controlling characters also have their own rules and events. At this time, we need to give them intelligence similar to human beings. So we can simplify it into one sentence: let NPCs in the game gain the ability to analyze, judge, and design corresponding behaviors, which we call game AI design.

    What does AI do to the game?

    1. Increase the challenge of players
    2. Create a more realistic virtual world
    3. Increase the playability of the game
    4. Assist other functions

    Types of AI Design

    1. fsm (finite state machine) finite state machine. This is the simplest and oldest AI technology. If you know the program, you can simply understand it as a set of conditional judgments composed of if, else or switch and case.

    2, fusm (fuzzy state machine) fuzzy state machine. The noun explanation for it may be very complicated, and we don't need to relate to those. We can understand its true meaning in the simplest way: adding random features to fsm.

    3. Scalability AI. This concept may be of great interest, while it's actually not that mysterious and we rm users are actually in touch with it all the time. Among the friends who read this post, I believe that a considerable number of them do not know programming. In fact, programmers don't care about the balance in the game. What they need to do is to implement the functions of the game. Game progress, they don't care at all. Then we started talking about fsm for so long. Who is fusm for? Haha, it is for planning and for ourselves. Yes, this is just to facilitate our adjustment and logical judgment. Often, programmers make a set of tools for us to set up and test, and that set of tools is extensibility ai.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325735023&siteId=291194637