2
头图
This article was first published on the WeChat public "161d6543774a5b Shopee Technical Team ".

Summary

Everyone is familiar with the various "matching and matching" games. The secret of customs clearance is to match three or more identical elements to eliminate them. Usually we call this type of game a "match-3" game. Shopee Candy, a match-3 game embedded in the Shopee shopping platform, is also loved by many users. This article will show you how to create such a match-3 game from the aspects of project origin, game architecture and project toolset.

1. Origin of the project

1.1 Introduction to the game

Shopee Candy is a match-3 casual H5 game for multi-regional markets. Users can get preferential rewards such as Shopee Coins and merchant shopping coupons in the game, which can not only enhance user stickiness, encourage users to spend, but also attract merchants. At the same time, mechanisms such as sharing awards and friend rankings have enhanced the social nature of the game and played a role in bringing new players to the platform. In addition, the simple, lightweight, and highly adaptable features of H5 games are in line with the usage habits of Shopee users. They can be played immediately, and the participation threshold is low while taking into account the fun.

In June 2020, Shopee Candy was launched on the entire Shopee market, with official versions for iOS and Android. Since its launch, Shopee Candy has performed dazzlingly in daily and big promotion activities, with user activity and online time reaching new highs.

Shopee Candy uses the theme of colorful and cute candy elements in style; the gameplay is mainly to limit the number of operation steps and set the number of collected elements as a clearance condition. In the level, users can trigger elimination by exchanging adjacent candies to connect three or more candies of the same color; according to the number and shape of the eliminated candies, prop elements with special elimination ability can also be generated; there is a level mode on the mode. and endless mode.

1.2 Project Introduction

As the project continues to develop, the functional iterations of Shopee Candy can be clearly divided into four categories. The first is various business function modules (props store, task system, exchange store, etc.); second is the algorithm library (Algorithm SDK) responsible for eliminating logic algorithms, calculating scores, and level progress, and the animation system responsible for eliminating effects; last is the service game various tools, including the Map Editor level editor that liberates the productivity of designing levels, the Score Runner that can quantify the difficulty of the level, and the Replayer playback tool that can perform operational review.

2. Game Architecture

2.1 Algorithm library (Algorithm SDK)

As a match-3 game with a rich variety of element elimination, the algorithm part of Shopee Candy is very important and complex. Back in the beginning of the project, algorithms and animations were coupled together. With the increase of product launch and elimination types, we gradually found that the project maintenance cost is getting higher and higher; at the same time, the algorithm itself is independent and has no dependence on animation and business, so the algorithm part is extracted.

2.1.1 Algorithm SDK Implementation

The implementation of Algorithm SDK mainly consists of three parts: Map, Operator and Logic Processing.

(Map)

Map manages map objects and element objects in game levels. According to the characteristics of each element, we manage the elements in the upper, middle and lower layers. This element layered architecture mode can meet the addition of new elements with different special effects. Each layer of elements restricts and influences each other, and complements each other in the elimination process to complete the gorgeous elimination effect in the game.

export default class Grid {
  public middle: CellModel;
  public upper: Upper;
  public bottom: Bottom;

  constructor(info: ICellInfo) {
    const { type } = info;

    this.upper = new Upper(/* ... */);
    this.middle = new CellModel(/* ... */);
    this.bottom = new Bottom(/* ... */);
  }
}

Operation (Operator)

Operator manages all feasible operations of the algorithm, and is the bridge between the entire Algorithm SDK and the outside world. It is responsible for receiving external exchange, double-click and other operation signals, and calling the corresponding algorithm. In the invocation of the main process of Shopee Candy, the operator will collect animation data and communicate with the animation system.

// 元素交换
export function exchange(startPos, endPos): IAnimationData {
  // ... logic process
  // returns animation data
}

// 元素双击
export function doubleClick(pos): IAnimationData {
  // ... logic process
  // returns animation data
}

Logic Processing

Algorithm manages all logical operations of the Algorithm SDK, including: solution guarantee, solution detection, elimination, drop, etc., which is the core of the entire Algorithm SDK.

When elements in the process are eliminated for multiple loops, there may be a problem that logic execution takes too long, resulting in frame loss during user operations. In order to avoid this situation, we divide the logical operation into multiple segments, make the calculation asynchronous, send the data to the animation in advance, and complete the subsequent operations in different frames.

2.1.2 Algorithm SDK Unit Testing

In terms of implementation, we have achieved as much separation and decoupling as possible, but for the huge algorithm library, regular Code Review is far from enough, and front-end testing is very important.

Unit Testing

Many people say that front-end testing is a waste of time and has little effect. The regular front-end business does change frequently, including the business view of Shopee Candy. But thanks to the separation and independence of the algorithm library, we can perform UI-free, pure logic unit tests on it.

Unit Test Application

Manual testing can only ensure that the code does not report errors and the layout is not chaotic after the operation, but it cannot find and eliminate many situations such as the number of elements or the incorrect score. A user's movement or double-click operation in the project controls the same layout, and finally obtains the same result. This result includes the data of the final map, the score obtained by the user, the number of collected or destroyed elements, etc., to ensure stability over multiple iterations.

describe('BOMB', () => {
    it('Exchange each other should be the same crush', () => {
      const source = { row: 0, col: 3 };
      const target = { row: 1, col: 3 };
      const wrapper = mapDecorator(operator);
      const data1 = wrapper({ key: CRUSH_TYPE.BOMB }, source, target);
      const data2 = wrapper({ key: CRUSH_TYPE.BOMB }, target, source);
      // 地图比较
      expect(JSON.stringify(data1.map)).equal(JSON.stringify(data2.map)).equal('xxx');
      // 分数比较
      expect(data1.score).equal(data2.score).equal(150);
      // 步数比较
      expect(data1.passStep).equal(data2.passStep).equal(14);
    });
});

2.2 Animation system (Animation)

After the animation is separated from the algorithm, the animation is used as a system alone, which has the following advantages:

  • High cohesion and low coupling : The algorithm and animation both have high complexity, and the system complexity is reduced after separation, and the modules are more cohesive;
  • High efficiency : The execution of the algorithm does not need to wait for animation, which improves the calculation efficiency;
  • High flexibility : After the algorithm removes the dependence on animation, it can well support the requirements of skipping Bonus and running points.

2.2.1 Scheme design

After separating the animation system, it is necessary to establish a communication mechanism with the algorithm to ensure that the elimination result executed by the algorithm has the corresponding animation playback. The communication is implemented as follows:

  • Establish an event mechanism, and the algorithm and animation communicate with each other through events;
  • Define the animation data structure, distinguish animations by defining different animation types, such as elimination and falling animations, and define complete animation information at the same time, and the animation system will play the corresponding animation after parsing.

For the playback of animations, we introduced a process of " animation queue ". Add the animation data parsed by the algorithm to the queue, play the queue recursively until the queue is empty, and end the animation playback.

When playing a single movie from an animation queue, in order to ensure that the various elements of each other the animation does not affect each other, using the animation system " strategy pattern " design, according to the type of movie execute different strategies to eliminate the animation "element Cohesion " into their respective strategy methods.

//策略配置
const animStrategyCfg: Map<TElementType, IElementStrategy> = new Map([
    [AElement, AStrategy],
    [BElement, BStrategy],
    [CElement, CStrategy],
]);

//获取策略
function getStrategy(elementType):IElementStrategy{
    return animStrategyCfg.get(elementType);
}

//执行策略
function executeStrategy(elementType){
    const strategy = getStrategy(elementType);
    return strategy.execute();
}

The algorithm is responsible for calculating the elimination logic, and the animation system is responsible for playing the corresponding animation. In addition to playing special effects such as keels, it also manipulates the size, position and display of the chessboard elements. Under normal circumstances, the state of the chessboard and the algorithm state should be the same after the animation is played, but in rare cases, problems such as timing and timer exceptions may occur due to device performance and other reasons, resulting in inconsistent states between the two. Display or position misalignment, etc.

Therefore, after the animation is over, " Logic " needs to obtain the algorithm state in real time, check and correct the state of the chessboard, make it match with it, and avoid errors in the display. At the same time, in order to avoid performance problems, this is not a full-scale verification correction, but only for error-prone middle-level elements.

2.2.2 Solving Callback Hell

The animation library that comes with the game engine uses the callback method to execute the logic after the animation is completed. In the case of complex animation, there is often a nested writing method of callbacks, which makes the logic difficult to understand and maintain. In order to solve the problem of callback hell, we encapsulate the promise method on the prototype chain of the animation library, so that the async/await synchronization method can be used.

function animation(callback: Function) {
    tweenA.call(() => {
        tweenB.call(() => {
            tweenC.call(() => {
                sleep.call(callback);
            });
        });
    });
}
async function animation() {
    await tweenA.promise();
    await tweenB.promise();
    await tweenC.promise();
    await sleep.promise();
}

The above shows the effect of changing from the callback writing method to the synchronous writing method. It can be seen that the synchronous writing method is more intuitive, solves the problem of callback hell, and is easier to maintain the code.

3. Project Toolset

The algorithm library and animation system of Shopee Candy were introduced earlier. In fact, our team has also made a lot of tools.

3.1 Map Editor

At the beginning of the establishment of the Shopee Candy game, we needed to create a tool that could flexibly configure levels and test the level's playability and clearance rate.

In daily work, you can quickly configure level board elements by dragging and dropping keyboard shortcuts.

At present, there are more than 30 chessboard elements, and there are complex mutually exclusive coexistence rules between each element:

  • Coexistence: A element and B element can appear on a grid at the same time;
  • Mutually exclusive: A element and B element cannot appear on the same grid at the same time;
  • Big Mutual Exclusion: A element and B element cannot appear on the same board at the same time.

In the face of the relationship between so many elements, it is not appropriate to manually handle the mutual exclusion relationship when configuring the level simply by planning.
So a relational mutex table is needed to maintain the relationship between elements. We pull the data of this table through the Map Editor server, return it to the Web side, and give some error feedback while doing a good job of relationship restrictions.

3.2 Score Runner

In the early stage of the launch, one of the problems encountered was that the speed of level planning could not catch up with the speed of user clearance, and users often urged users to update the level. The design volume of a match-3 game with thousands of levels is a huge difficulty for any team in the research and development work. Among them, the most troublesome and time-consuming to plan the level is the difficulty test and adjustment of the level. Score Runner is a tool that can solve the boring and time-consuming process in red.

Score Runner implements

Let's first look at the layout of one of the levels. There are many possibilities for the operations that can be eliminated on the field. If these possibilities are regarded as a network of data, the operations of the simulated users are nothing more than these possibilities.

So, what's the next step? With different layouts behind these possibility operations, there are more different possibilities. The process is roughly as follows:

  • Traverse the map to get the possibility of each operation;
  • According to each operation, continue to get the possibility of the next step until the last step (pass or fail);
  • Get all the steps to get the maximum and minimum clearance points.

As can be seen from the figure, each possibility can go to the end, but in fact many possibilities users will not operate, such as those with less scores, operations that do not eliminate meaning, etc. For the clearance rate Not scientific, and very inefficient for computational efficiency.

So we added the strategy , and calculated the operation weight order on the data set of possibility elimination. Taking the operation with the highest weight as the best possibility, prune the current huge possibility network structure to obtain a more consistent clearance rate.

example:

levelAverage clearance rate (100 times)Customs clearance record (%)
34165%63/62/71
34268%65/63/76
34360%56/57/67
34460%63/64/56
34547%46/47/47
34651%51/52/49
34750%50/52/42
34847%51/38/51
34963%65/61/62

By analyzing the average clearance success rate, the planning time for verification of the difficulty of the level can be reduced.

3.3 Replayer

After the Score Runner, we use Replayer to replay the running score process to verify the correctness of the running score.

When replaying, the first problem is to ensure that each random result is consistent with the running score. How to guarantee?

random seed is the answer to this question. A random seed is a random number that takes the random number as the object and takes the true random number (seed) as the initial condition. Simply put, it is a pseudo-random method that sets a fixed seed and outputs the same result and order.

In order to access the random seed, we adopt a new random number strategy, which can set the random seed, and each random number is calculated based on the last random number result as the seed.

Such a strategy ensures that every random number in the entire game is recorded, and each random result can be obtained at any time.

At the same time, this strategy also has the following benefits:

  • The traceability of logic algorithm execution;
  • Traceability of random numbers after disconnection and reconnection;
  • The feasibility of replaying the entire game steps of online users;
  • Very little data storage.

4. Future planning

This article introduces the game Shopee Candy in terms of project origin, game architecture, and project toolset.

"Rome wasn't built in a day", only through the cycle of "requirements-reconstruction-launch" can a more complete project be created. In the future, we will improve and optimize Shopee Candy from the following aspects:

1) Implemented configuration development for new elements, reducing development costs

At present, the development of new elements still requires a lot of manpower. It is planned to combine the algorithm library (Algorithm SDK) and Map Editor to realize the configuration development of element attribute classification and layering. It only needs to add configuration algorithms and element animations to realize new elements. element development.

2) provides a smoother gaming experience for low-end devices

Shopee Candy is a strong gameplay project with a special focus on game performance and feel. Due to the uneven performance of mobile devices on the market, it is necessary to pay more attention to the user experience of low-end devices. In the future, optimization strategies for logic and view performance will be formulated for low-end devices to provide users with a smoother gaming experience.

3) operation behavior verification to avoid cheating phenomenon

The front-end relies on obfuscation or encryption to increase the cost of cracking, but it cannot completely prevent cheating. At present, the project is developing an operation behavior verification service, which combines the existing Replyer function to perform secondary operation verification on suspicious settlement behaviors to ensure the fairness of the game.

4) Use machine learning for level design

At present, Shopee Candy has developed thousands of levels. In order to improve the efficiency of level configuration, the follow-up plan is to combine machine learning and the clearance rate of Score Runner statistics for model training, and only need to provide a small amount of manual configuration to automatically generate levels.

Author of this article

Shopee Games - Candy front-end team.


Shopee技术团队
88 声望45 粉丝

如何在海外多元、复杂场景下实践创新探索,解决技术难题?Shopee技术团队将与你一起探讨前沿技术思考与应用。