[Using unity to realize 6 of 100 games] Make a battle flag auto chess game (with source code)

foreword

Explore the infinite charm of war and strategy, let us step into a world full of battle flags together! As the leader of war chess games, Zhanqi game has led a unique fighting trend. Have you ever thought about how creative and fun it would be if you could design and realize your own Zhanqi game?

In this article, we will use the Unity engine to explore how to quickly build a simple and strategic battle flag game demo. With the guidance of this tutorial, you will learn how to use Unity's powerful functions and libraries to create a fascinating battle flag world.

In this demo, we will take a virtual continent as the background, and players will act as the commander of the opposing faction, fighting for control through strategic layout and heroic decision-making. You can choose to perfect this demo, such as each chess piece has unique abilities and characteristics, such as the high health of the guardian swordsman, the powerful attack power of the magician, etc., lead your team by purchasing, upgrading and carefully arranging the positions of the chess pieces Defeat your opponents and reach the ultimate victory goal!

In addition, the recently popular auto chess is also a kind of Zhanqi game. Auto Chess is a variant of war chess games. It retains the core elements of the Zhanqi game, such as strategic layout and combat confrontation, while adding an automated chess piece action mechanism.

In order to help you understand better, we specially prepared some wonderful screenshots and GIF animations of Zhanqi game, showing the exciting moments of Zhanqi game. These screenshots will take you to experience the visual effects and tense fighting atmosphere of the game.

Please add a picture description
Please add a picture description
Please add a picture description
Please add a picture description

Whether you are a fan of the Zhanqi game or a friend who is interested in Unity development, this tutorial will reveal the mysteries of the Zhanqi game for you, and help you build a fascinating Zhanqi game Demo.

As usual, let’s take a look at the final effect of this article to see if you want to read on
insert image description here

Well, let's start our battle flag tour!
The source code is at the bottom of the article

import material

Please add a picture description
Please add a picture description
Please add a picture description
Please add a picture description

start

1. Set the tile gap

Create a new 2D project, open it, and drag the required [ 图片] into the project.
We first drag this [ Tile瓦片] into the scene window
. Since the original size of this picture is too large, we can manually adjust the size of the picture
As for the size of this tile, to what extent should it be adjusted, I suggest to ensure that the
relative distance between adjacent tiles around them 一个单位is [ ], and leave a little gap.
The specific reason will be It is related to the following character [ 移动范围]
insert image description here
In order to achieve this effect, we need to set it first Snap Setting. We hope that when we hold down [cmd/Ctrl], we can drag the object to move [ 一个单位] before the length of
2021. The Snap Setting is at the bottom of the Edit column. I searched for a long time in the Unity2021 menu bar and couldn’t find it. Finally, I found that in the Scene window,
insert image description here
press [ Cmd/Ctrl+D克隆] the current tile game object
. Then, when we want to move the object, (first) hold down the [cmd/ctrl] button
and drag Pull to achieve "Snap Moving", that is, the movement of [one unit] distance length.
insert image description here
If you think that the gap between two adjacent tiles is still a little big,
we can zoom in a little bit. This picture size

2. Place full image tiles

Set the tile as a prefab, as shown in the figure below, and configure the tile map of the whole image
insert image description here

3. Beautify the tile map

Now our (map) picture still looks a bit [boring]. We hope that every time we run the game, [every tile] on the map, he can randomly generate a different tile picture for we appreciate

In the Sprites folder, set the image of Tilesi to multi-image mode, and
perform [automatic cropping] in the sprite editor.
insert image description here
In the Scripts folder, create a new C# script: Tile

public class Tile : MonoBehaviour
{
    
    
    private SpriteRenderer spriteRenderer;//瓦片
    [SerializeField] private Sprite[] sprites;//瓦片集

    private void Start()
    {
    
    
        spriteRenderer = GetComponent<SpriteRenderer>();
        int randomNum = Random.Range(0, sprites.Length);//随机获取0-9下标
        spriteRenderer.sprite = sprites[randomNum];//赋值给瓦片
    }
}

Mount scripts and objects, run the game, now we will (randomly) generate a different map every time we start the game
insert image description here

4. Add tree obstacles

We now hope to add more trees on the picture, and some trees will be used as entities, and some will be used as [obstacles]
. function of

We create three new empty objects trees, background, and obstacles, responsible for managing all trees and obstacles,
using tree game objects as their [parent objects]

Let's build some beautiful trees first
, select [multi-image mode] and then cut them
insert image description here

5. Set different sorting layers

Since the characters will be created later, we hope that all [pictures related to the background] will be rendered behind the characters. Configure
insert image description here
different sorting levels.
insert image description here
We set the tiles and tree sorting layers as background, because the trees must be displayed in front of the tiles. We can set the layer sorting to 50, place different trees, and enrich the scene, as follows
insert image description here

6. Tile interaction

In order to be able to better interact, we hope that when our mouse [selects] each tile, the tile can give us a certain amount of feedback. We hope that when the mouse [enters the tile], the tile can be enlarged. When we [ When leaving the tile], the tile can return to its original size

We can use Unity's built-in [ OnMouseEnter] and [ OnMouseExit] methods to achieve it
. Just remember that there is a prerequisite for implementing these two methods, that is, the object we want to detect with the mouse, that is, the tile here. [ Collider2D] collider component must be added

Let's add a collider to the tile first, remember to apply all prefabs
insert image description here
to improve the Tile script code

private void OnMouseEnter()
{
    
    
     transform.localScale += Vector3.one * 0.05f;
 }

 private void OnMouseExit()
 {
    
    
     transform.localScale -= Vector3.one * 0.05f;
 }

Effect
insert image description here

6. Tile interaction optimization

We can also observe a detail. Now when a tile is partially enlarged, it will still be rendered below by adjacent tiles
in order to ensure that when we zoom in on each tile, this tile can be rendered at the [top] , we can also adjust its rendering layer order

The tile is located at position 0 (sequence) of the Background layer
, and the order of the solid tree is 50.
We only need to ensure that the order of the enlarged tiles
is above other tiles and below the solid tree (that is, at 0 to 50), we set it to [25] here

Improve the Tile script code

private void OnMouseEnter()
{
    
    
     transform.localScale += Vector3.one * 0.05f;
     spriteRenderer.sortingOrder = 25;
 }

 private void OnMouseExit()
 {
    
    
     transform.localScale -= Vector3.one * 0.05f;
     spriteRenderer.sortingOrder = 0;
 }

final effect
insert image description here

6. Whether the tile allows characters

We are about to start the most important first step of judgment, whether this tile allows the character to walk.
If there are [trees] on this tile, then our character cannot walk on this tile.
The basis of our judgment is, if There are [trees] or [people] on the tile, then this tile is [not allowed] to stand on people, and the player cannot move to this tile

Improve the Tile script code

public bool canWalk;//是否能走
public LayerMask obLayerMask;//检测层

private void Start()
{
    
    
    CheckObstacle();
}

private void CheckObstacle()
{
    
    
	//参数1:圆形检测的中心点位置,那也就是我们瓦片的中心点位置
	//参数2:范围,spriteRenderer.bounds.extents.x获取图片一半的长度
	//参数3:检测层
    Collider2D collider = Physics2D.OverlapCircle(transform.position, spriteRenderer.bounds.extents.x, obLayerMask);
    if (collider != null)//检测不为空,说明有障碍物在这个瓦片上呀
        canWalk = false;
    else
        canWalk = true;//这个瓦片,我们的角色是可以行走的
}

Go back to Unity, create a new Layer layer, name it Obstacle, select all [Entity Tree] game objects, and set it as the Obstacle layer. Recall the
insert image description here
definition of [Physics:2D.Raycast] or [Physics:2D.OverlapCircle]
and their The method detects the game object with [Collider component] added

And don't forget to add a collision body to each tree
insert image description here

7. Add roles

Add a character, you can just find a character picture, or you can use the one I prepared
insert image description here
注意: remember to put 锚点设置在人物脚the position when cutting the character, this is very 关键, I didn’t pay attention at the beginning, when setting the position of the character, there will be an offset and
insert image description here
drag directly The anchor point is definitely inaccurate. The deviation of the anchor point at different positions in each picture will cause the character to shake, so it is best to manually modify the position of the anchor point. Here I set it to 0.5x0.15
insert image description here

If you want to place the character on which tile by default, just set the xy coordinates of the character to correspond. Don’t drag and drop, otherwise the xy coordinates will be inaccurate, and the rendering of the walking route will be inaccurate. Add the corresponding animation and collider to the character, remember to
insert image description here
modify Sort layer as Forground
insert image description here

8. Add game management script

What we hope is that when the mouse clicks on the character, the character can display the corresponding movable range. If there is an obstacle, the tile cannot be moved.

We first need to traverse all the tiles
, then filter out all the tiles that meet the requirements,
then highlight these tiles
, and then we can display: these tiles that our character can move, because we need
to traverse all the tiles
Well, we will also need to highlight and reset all the tiles.
We will use the array of all tiles over and over again.

We create a new C# script GameManager
to manage some core variables in the game and some commonly used method
tiles can actually be generated dynamically. Here I use drag and drop directly for convenience.

set as a singleton

public class GameManager : MonoBehaviour
{
    
    
    public static GameManager instance;
    public Tile[] tiles;//在这个游戏中所有的贴图

    public Unit selectedUnit;//被选中的角色

    private void Awake()
    {
    
    
        if(instance == null)
        {
    
    
            instance = this;
        }
        else
        {
    
    
            if(instance != this)
            {
    
    
                Destroy(gameObject);
            }
        }
        DontDestroyOnLoad(gameObject);
    }
}

Create a new C# script Unit and add the Unit script to the role game object. What
the mouse wants to click is the Unit object (so write it in the Unit script)

Our mouse clicks on our character.
When our mouse enters the range of the character Collider
and presses the left mouse button, this method will be called (OnMouseDown]
So inside the method
, when we click on this character, the movable tiles will be displayed.

Declare an integer type, and the variable moveRange of type int
indicates the number of grids that the current character can move.
We first set it to three
. If we create different characters later,
we can also use
[ScriptableObject]) or [Inheritance]
to carry out code modification refactor

We can also use the feature [Range]
to control the selectable range of this variable within the integers 1~7. In the
[ShowWalkableTiles]) method, we want to get the size of
a rhombus around the character centered on itself. , the Unit code
is determined by the movement range of the character

insert image description here

9. Logic of character movement range

How should we obtain the tiles that the character can walk on?

We can first make such a judgment

If our character’s moving range is equal to 1
, then what about our character’s walking range, it should look like this?
insert image description here
If our character’s moving range is equal to 2
, then our walking range can reach the additional eight points.
insert image description here
We will set all movable The tile position coordinates are marked on the picture.
We can find that the position coordinates of the tiles we can reach. The addition of X and Y values ​​​​will determine the 小于等于movement range of the character.
insert image description here
We can respectively go through the x distance between the character and each tile. Axis distance
The Y-axis distance between the character and each tile, add and compare
If the sum of the X-axis and Y-axis distances is less than or equal to the character’s movement range
, then these tiles are the range we can move The
other tiles are the ones outside of our character's movement range

10. Visualization of character movement range

Improve the Unit code

public class Unit : MonoBehaviour
{
    
    
    [SerializeField] [Range(1,7)]
    private int moveRange = 3;

    private void OnMouseDown()
    {
    
    
        ShowWalkableTiles();
    }

    private void ShowWalkableTiles()
    {
    
    
        for (int i = 0; i < GameManager.instance.tiles.Length; i++)
        {
    
    
            float distX = Mathf.Abs(transform.position.x - GameManager.instance.tiles[i].transform.position.x);
            float distY = Mathf.Abs(transform.position.y - GameManager.instance.tiles[i].transform.position.y);

            if(distX + distY <= moveRange)
            {
    
    
                //Tile is Walkable or not (without obstacle)
                if (GameManager.instance.tiles[i].canWalk)
                    GameManager.instance.tiles[i].HighlightTile();
            }
        }
    }

Tile script defines walkable area highlighting method

public void HighlightTile()
{
    
    
    if (canWalk)
    {
    
    
        spriteRenderer.color = highlightColor;
    }
    else
    {
    
    
        spriteRenderer.color = Color.white;
    }

}

Mount the script and bind the parameters.
insert image description here
insert image description here
insert image description here
If you find that all the settings are correct, but the click has no effect and the OnMouseDown method is not called, you can properly adjust the z-axis of the character to prevent the occlusion
insert image description here
effect. You can see that the tiles occupied by obstacles and trees The film prohibits walking, which is the effect we want
insert image description here

11. Character movement

The next step is: we need to allow our character to actually move to the point we want to move to.
After we select the character and click on the tile, the character can move.
That is to say, the method of our movement should be written in the Tile tile. Inside the script
, we can use the OnMouseDown method to move the character in the Tile script of the tile.
Our character will move to the position of the tile we clicked.

Because in the future,
we may have more than one character.
In the GameManager script,
we declare a variable of type Unit selectedUnit
to represent the character we are currently clicking on with the mouse.

public Unit selectedUnit;//被选中的角色

In the Unit script, create a Move method

Since the movement of the character requires a [process], and we hope that the movement of the character is based on the route of the tiles, rather than point-to-point direct movement, here we need to use the coroutine function, [coroutine Program function] can divide a function into multiple frames to execute (executed in a certain order), and move in the [horizontal direction] first

insert image description here
insert image description here

[SerializeField] private float moveSpeed;

//MARKER 这个方法会在【Tile脚本】中OnMouseDown函数中被【调用】
public void Move(Transform _trans)
{
    
    
    StartCoroutine(MoveCo(_trans));
}

IEnumerator MoveCo(Transform _trans)
{
    
    
    //角色先水平方向移动
    while (transform.position.x != _trans.position.x)
    {
    
    
        transform.position = Vector2.MoveTowards(transform.position, new Vector2(_trans.position.x, transform.position.y), moveSpeed * Time.deltaTime);
        yield return new WaitForSeconds(0);
    }

    //水平方向到达目的地X后,再垂直方向移动
    while (transform.position.y != _trans.position.y)
    {
    
    
        transform.position = Vector2.MoveTowards(transform.position, new Vector2(transform.position.x, _trans.position.y), moveSpeed * Time.deltaTime);
        yield return null;
    }
}

12. Reset tile color

After the character has finished moving, we certainly hope that the [highlighted] tiles we started with can be reset back to their original colors to ensure all subsequent operations

We can create a ResetTile method in the Tile script
to modify the [color attribute] once

public void ResetTile()
{
    
    
    spriteRenderer.color = Color.white;
}

Create a ResetTiles method in the Unit script
to traverse all tiles and reset them back to their original colors

private void ResetTiles()
{
    
    
    for (int i = 0; i < GameManager.instance.tiles.Length; i++)
    {
    
    
        GameManager.instance.tiles[i].ResetTile();
    }
}

Call this method after the character has finished moving

IEnumerator MoveCo(Transform _trans)
{
    
    
	//。。。
	ResetTiles();
}

Call the move method in the tile script

private void OnMouseDown()
{
    
    
     //Player Move to "this" TILE 当我们选择了角色,点击这块瓦片,那么角色就会移动到这个瓦片上!
     if (GameManager.instance.selectedUnit != null)
         GameManager.instance.selectedUnit.Move(this.transform);
 }

Finally, don't forget that we also need to specify in OnMouseDown in the Unit script of this character
GameManager.instance.selectedUnit = this;

private void OnMouseDown()
{
    
    
    GameManager.instance.selectedUnit = this;
    //。。。
}

Effect
insert image description here
ps: There is a tile in the above picture that is not displayed, because the collision volume of the obstacles and trees below me is set too large, which affects the tiles above. I adjusted it myself. Here is an explanation

12. Limit the number of moves

Finally, there is still a problem left, our character can move infinitely

Introduce the canMove parameter in Tile to determine which tile character is movable, so as to limit the number of times the character can move

public bool canMove;

public void HighlightTile()
{
    
    
    if (canWalk)
    {
    
    
        canMove = true;
        spriteRenderer.color = highlightColor;
    }
    else
    {
    
    
        spriteRenderer.color = Color.white;
    }
}

public void ResetTile()
{
    
    
    spriteRenderer.color = Color.white;
    //重置所有的canMove为false
    canMove = false;
}
private void OnMouseDown()
{
    
    
    //Player Move to "this" TILE 当我们选择了角色,点击这块瓦片,那么角色就会移动到这个瓦片上!
    if (canMove && GameManager.instance.selectedUnit != null)
        GameManager.instance.selectedUnit.Move(this.transform);
}

13. Final effect

insert image description here

other

In fact, there is still a lot of room for development in the future, such as adding different characters and enemies, improving character movement and attack animations, etc. I will not repeat them here, and leave it to everyone to expand freely.

Source code download

https://gitcode.net/unity1/battleflag
insert image description here

reference

【Video】https://www.bilibili.com/video/BV1vQ4y1M7gy/

end

Gifts of roses, hand a fragrance! If the content of the article is helpful to you, please don't be stingy with yours 点赞评论和关注, so that I can receive feedback as soon as possible. Every time you write 支持is the biggest motivation for me to continue to create. Of course, if you find something in the article 存在错误or something 更好的解决方法, you are welcome to comment and private message me!

Well, I am 向宇, https://xiangyu.blog.csdn.net

A developer who worked silently in a small company, out of hobbies, recently began to study unity by himself. If you encounter any problems, you are also welcome to comment and private message me. Although I may not know some problems, I will check the information of all parties and try to give the best suggestions. I hope it can help more people who want to learn programming. People, encourage each other~
insert image description here

Guess you like

Origin blog.csdn.net/qq_36303853/article/details/132175469