preface

According to the author’s research and development sequence, this paper initially introduced and understood wechat mini-game and Egret engine, and produced egret-Weike-start application initialization program based on egret engine. Here is the text

Wechat games

The official documentation

How to develop and understand micro channel games, start with official documents and official demo. Provide a link
Developers.weixin.qq.com/minigame/de…, you can take a quick look at the official documentation before moving on. Here is a simple summary of wechat documents. Mini games and mini programs are similar in many places. They both provide the same wechat Api, such as obtaining user information, toast and so on, but some of the Api provided is different. Small game to canvas encapsulation, through
wx.createCanvas() Once the canvas is created and getContext gets the object, all that’s left to do is manipulate the native Canvas interface. With this in mind, the mini-game simply encapsulates the interface to create the canvas, leaving the user to draw on the native canvas, and providing no other convenience for development. Here we have a look at wechat developer tools to create a small game project, initialization of an aircraft game demo.
Is a very simple game as shown in the picture above. Here is the general implementation logic of this game:
1. Draw the game area and background pictures
2. Create enemy aircraft object, user aircraft object, bullet object
3. Control the loading of canvas and position change of three objects, control the movement of background pictures and add sound effects
4. Judge bullet collision and fuselage collision, and generate corresponding results (enemy aircraft disappear, game over)
There are interactive operations in the game with the user, including dragging the plane and the button in the cartridge. It is a very simple game in general, and the implementation process is not complicated. The core animation content of the official demo is in the loop method, which uses requestAnimationFrame to achieve interface animation. There are two main ways to implement animations for games, one is requestAnimationFrame animation and the other is timer implementation. Frame animation depends on the processing speed of the device. The default is 60 frames per second, but even simple animations on mobile devices may have a frame rate of 20-30 on less efficient devices. Since frame animations are called n times per second, it may not be necessary to call functions as often, while timers are generally more accurate in timing and number of function calls. For example, if there is a concept of health bar in the plane game, the increase and decrease of health bar can be controlled by a separate timer. You can use both methods in a game, and choose the more appropriate method depending on the application scenario.
Now make a game based on a new requirement, and understand the development of mini-games. Now we need to implement a turn-based game, which also has a lot of pages, the front page is full of buttons and possible pop-ups, there are various list pages, and the most important is the battle page. Before implementing the requirements, you need to provide some common base modules: resource preloading, interface interceptors, simple routing, and so on. Skip the stages, if we get the UI design, start to make the front page, home page has A lot of buttons, we need to add binding to A button event, that we need to give canvas canvas binding A click event, click on the trigger after we get to the current user click position, and took out A button calculated the position of the high and wide range, To determine whether the click position is within the range, and finally trigger the binding method. It seems like a little bit of a hassle, but it can be done. Keep doing it. Later, a pop-up box was needed to be made on the home page. At this time, the click event was bound to button B of the pop-up box, and the same method was used to determine whether button B was clicked. At this time, the B button of the popup box just overlaps with the A button, and the callback of the A button and B button will be executed. The code is as follows:
canvas.addEventListener('click'ButtonB: x,y,width,height, buttonB: x,y,width,height})Copy the code

A button click on the top of the popover will click the button below the popover, which is not expected. To solve this problem, we also need a hierarchy manager to determine who should trigger and who should not trigger based on the hierarchy. With event processing at present we need to implement two basic functions, event listeners pool and element object level manager, because events only binding on the canvas, canvas event triggers, pool needs a event listeners to traverse to monitor the element object in the pool and decide who is triggered (listening pool will also be monitored objects). The listener pool still fetches a set of objects, and the hierarchy manager determines the topmost element in the set to fire. If you think about it, it’s getting more and more complicated. At present, it is not well considered, not only the issue of incident handling, but also other problems, big and small. Using Canvas native development can be a lot of work. So in this way, it is not scientific to implement these by yourself, and it is necessary to use tripartite engine development. Since I used the Egret engine two years ago, I know that the Egret engine has been implemented in terms of event monitoring and hierarchy management. Except for events, graphics drawing, animation and so on, I remember that The Egret engine has been provided. If the engine is used to develop small games, the implementation cost will be greatly reduced.

Egrets engine

The Egret engine is powerful and rich. Here I’ll start with the main tools I use.
  • Egret Engine2D
  • Texture Merger
  • Egret extension libraries
  • Egret Wing

Egret Engine2D

The main core API in development

Texture Merger

Texture Merger can merge disparate textures into whole diagrams, parse SWFS, GIF animations, create Egret bitmap text, and export configuration files for Egret. I mainly use the Sprite graph function, the collection of pictures to a picture, and will export a JSON Sprite graph in the picture location and other configuration information

Egret extension libraries

The extension library provides more advanced apis on top of the core engine functions. Once configured in the engine configuration file, the extension library directly loads the methods and objects into the EGRET global object. The main extension libraries I use are:

  1. RES: indicates the resource management library
  2. EUI: EUI is a UI extension library based on Egret core display list. It encapsulates a large number of common UI components, which can meet most of the interactive interface requirements. Even more complex components, you can combine or extend them based on EXISTING EUI components to quickly achieve the requirements.
  3. Game: This library doesn’t seem to have a specific definition, I mainly use: ScrollView. To handle pages that need scrolling
  4. Tween: Soft animation library, similar to the GreenSock library

Egret Wing

Egret’s code editor, like other editors, recommends it.

egret launcher

Of course, you also need to install an Egret Launcher to manage the engine, tools and project packaging. Small games need to be packaged before they can be used in wechat developer tools






Begin EGREt development

You can quickly through the official tutorials, so that a better understanding on the below, developer.egret.com/cn/github/e… . This article is not a tutorial so I will omit the tutorial on the egret website. Now we use Egret Launcher to create an initialization project. After initialization, the file structure is shown below. I expanded the resource and SRC folders, because these are the two folders we need to operate. Egrets use typescript.

With Wing, you can start debugging right away and preview it in the browser or in its own container. Ts is the boot file. In main, the image resource defined in resource is preloaded with await first, so loading effect will appear after preview starts. The loading is written in loadingui.ts in SRC. The page shown in figure 2 was created directly in main, and a button was added that would pop up when clicked. The effect is shown below.

So far, the initial demo has shown us how to draw the image and bind the event. As shown below, I just captured the code for the Click button. To draw the image, I first need to create a corresponding EGREt or EUI object. Button, Egret. TextField, egret.Bitmap, etc., and then set the corresponding properties of the object, such as label, X and Y coordinates, width, height, etc. Load the canvas with main’s addChild (this is the main object, main inherits from Eui.uilayer). The code in the demo uses this.stage.addChild when loading. AddChild can be loaded into the canvas directly or by using stage.addChild. The Egret encapsulated addEventListener method is used in the same way as the native JS listener method.

So to summarize the demo code, we can use addChild inside the main entry object to load a view object, such as text, buttons, etc., into the canvas. We can also addChild to view container A in main, we can add text buttons to view container A and so on, so we can addChild to view container B again in view container A, so we have A hierarchy of nesting main->A->B, If you imagine that the DOM element is div.main->div.A->div.B, let’s use code for comparison:

class Main extends eui.UILayer {


    protected createChildren(): void {

        let A = new egret.DisplayObjectContainer();
        this.addChild(A);

        let textA = new egret.TextField();
        textA.text = 'text A Description';
        A.addChild(textA);

        let B = new egret.DisplayObjectContainer();
        A.addChild(B);
        
        let buttonB = new eui.Button();
        buttonB.label = 'button B'; B.addChild(buttonB); }}Copy the code

The corresponding

<div class="main">
    <div class="A">
        <span>text A Description</span>
        <div class="B">
            <button value="button B"></button>
        </div>
    </div>
</div>Copy the code

Based on the understanding of the above code and the requirements we need to do (implement a turn-based game, this game also has many pages, the front page contains many buttons and possible pop-ups, also has various list pages, and the most important battle page). In main, I write an initElement method to create the base container. The code below is shown in the following figure. By default, addChild determines the relationship between the top and bottom container based on the order in which the first one is loaded. First, a background Layer is created at the bottom Layer, followed by ScrollView and baseContent, into which the page container is loaded. If the page needs to scroll, the page view object is loaded into the SV. If the page does not need to scroll, the page view object is loaded into baseContent.

With the base container ready, we can create a home page. I will create three files: base.ts, index_ui. ts, and index.ts. Index inherits from Index_ui, Index_ui inherits from Base. All _UI inherits base, which defines common methods and properties. Because a page to the end may be a large amount of code, and even more messy, so we split a page into page and page_UI, _UI to write view-related code, page to call the method of _UI, processing requests and writing logic, to achieve the effect of view and logic separation. Once the front page is written, you need to create a simple route to add Index to the SV container using the method provided by the route. From epage I have written the route directly into main, and from changePage is the page switching method. The code looks like this:

The effect of switching pages is achieved through the Remove and Add view containers. Here are the rules for writing _UI pages. Here is part of the Index_ui code. El_layout defines and manages the layout information of page elements in advance. Reference the elements of the Index logic page to the $EL object to make it easier to call and manipulate. Put the data information in $data. Before you create a page view element, you need to pass the y coordinate of the first element to $firstEleY so that the pageContentCenter method can get the exact height of the page content. The pageContentCenter method performs the following steps: PageContentCenter is vertically centered based on the height of the current page and then matches the height of the current device.

class Index_ui extends Base {
    public el_layout = {
        indexbg: {x:0, y:0, w:750, h:1665},
        gold: {x:300, y:100, w:300, h:39}
    };
    public constructor() {
        super();
        this.RES_index = RES.getRes('index');
        this.RES_common = RES.getRes('common');
    }
    public RES_index;
    public RES_common;
    public $el = {
        gold: Object(egret.TextField)
    }
    public $data = {
        gold: '0'
    }

    public async createView() {
Copy the code

Let RES_bg = new egret.bitmap (res.getres (‘indexbg’)); $util. SetLayout (RES_bg, enclosing el_layout [‘ indexbg ‘]); RES_bg. FillMode = egret. BitmapFillMode. REPEAT; this.$main.PageBg.addChild(RES_bg); // Load it into the PageBg of main to keep the background from scrolling

// The top element must pass the value this.$firstEleY = this.el_layout.gold.y;

        this.pageContentCenter(true); // According to the content of the calculation process is centered}}Copy the code

The core code of a simple development package has been built, and then we need to package some other tool classes, as shown below: configuration file ($config), wrapper interceptor ($API), filter ($filter), utility function ($util), wechat API Package (Wx). Platform.ts is a file automatically generated by Egret, and a WX. TS file is written according to its rules. As the interface forms of different platforms are different, Egret recommends developers encapsulate Platform logic in this way to ensure the stability of the overall structure. Egret recommends that developers encapsulate all interfaces in asynchronous promise-based form.

Next to SRC is the Texture folder, which contains TextureMeger’s sprites files for later management.

Easy to initialize demo, I have updated to github github.com/zimv/egret-… . Egret-resource is the source code, egret-resource_wxgame is the egret-packaged folder that runs in developer tools. Egret-resource_wxgame should be ignored in Ignore, so run the demo in developer tools. The current program uses Egret engine version 5.2.5.

A few random pages are written in the demo to see the effect:



pit

And stepped on a lot of pits, the following record:

  • In the background of the public account set the service class into the game class, enter appId will automatically open the developer tool game development interface
  • Small game custom font wechat support is poor
  • Some functions and APIS need to be registered to use the small program, such as forwarding function, currently registered a personal small game for early development
  • Use The Wing tool to edit the code, compile and debug, and the compiled code will be stored in the bin-debug folder. On my MAC, there are three options in the project menu: compile, debug and clean. I added a xx file, but kept reporting errors during debugging. There was no new file in the browser source and no bin-debug. After a long time, I always thought that there was something wrong with my code, but finally I realized there might be something wrong with the compiler. The new file appears in bin-debug. It should be a bug, pay more attention to check the file in bin-debug for updates
  • Res.getresbyurl is a network asynchronous load. AddChild is required to ensure that the hierarchy is normal. The texture property of the object is modified after the request is completed.
  • TextField font size less than 10 affects the layout, and whether the text is wrapped depends on the height of the element set
  • Webgl mode could not load web URL images
  • ScrollView has the addChild method, but the code in the method is thrown incorrectly, indicating that the interface cannot be used. Its child element bindings such as touchStart Move will fail, so now add a baseContent to the container and switch the parent container as needed
  • MeasuredHeight The measuredHeight interface measures only the actual height of the uppermost and lowermost elements, so $firstEleY should be specified for the first element if y is greater than 0
  • All images are compressed with tools to reduce the size of the upload code and improve the speed of resource loading

Once all this is in place, it’s all about the physical work, and of course the most important core gameplay implementations, animations, and interactions, which can be the most difficult parts of a game to implement. Warehouse address: github.com/zimv/egret-… .


Follow the official account of the great poet, the first time to get the latest articles.