unity 生命游戏简单实现

效果图:
高斯帕滑翔机枪:
在这里插入图片描述
通过基础规则 + 初始状态能产生很多令人惊讶的表现
基础规则:

(1)当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
(2)当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
(3)当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
(4)当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。

有个B站视频,介绍了很多不同变化的结构:【生命游戏|第一集】 几个方格演变出一个世界_哔哩哔哩_bilibili
项目包:unity 生命游戏
代码很简单:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LifeGame : MonoBehaviour
{
    
    
    public class CellInfo
    {
    
    
        public CellInfo(Image imgParam)
        {
    
    
            img = imgParam;
            SetState(false);
        }
        public Image img;
        public bool state;
        public void SetState(bool live)
        {
    
    
            state = live;
            img.color = live ? Color.white : Color.black;
        }
        public bool IsDead()
        {
    
    
            return state == false;
        }
        public void SetTmpState(bool bState)
        {
    
    
            tmpState = bState;
        }
        public bool tmpState;
    }
    public int CellLength = 100;
    public Image ImagePrefab;
    public Transform CellsParent;
    public float speed = 1;

    List<List<CellInfo>> Cells = new List<List<CellInfo>>();
    int width;
    int height;
    int round = 0;
    // Start is called before the first frame update
    void Start()
    {
    
    
        width = Screen.width / CellLength;
        height = Screen.height / CellLength;
        var size = new Vector2(CellLength-1, CellLength-1);
        for(int i=0;i<height;++i)
        {
    
    
            List<CellInfo> curCells = new List<CellInfo>();
            Cells.Add(curCells);
            for (int j=0;j< width; ++j)
            {
    
    
                var img = Instantiate(ImagePrefab, CellsParent);
                var rectTrans = (img.transform as RectTransform);
                rectTrans.sizeDelta = size;
                rectTrans.anchoredPosition = new Vector2(j * CellLength, i * CellLength);
                curCells.Add(new CellInfo(img));
            }
        }
    }

    public void ClearState()
    {
    
    
        for (int i = 0; i < height; ++i)
        {
    
    
            for (int j = 0; j < width; ++j)
            {
    
    
                Cells[i][j].SetState(false);
            }
        }
        round = 0;
    }

    public void NextRound()
    {
    
    
        ++round;
        for (int i = 0; i < height; ++i)
        {
    
    
            for (int j = 0; j < width; ++j)
            {
    
    
                UpdateState(i, j);
            }
        }
        ChangeTmpState();
    }
    List<Vector2> roundMap = new List<Vector2>
    {
    
    
        new Vector2(-1,-1),
        new Vector2(0,-1),
        new Vector2(1,-1),
        new Vector2(-1,0),
        new Vector2(1,0),
        new Vector2(-1,1),
        new Vector2(0,1),
        new Vector2(1,1)
    };
    void UpdateState(int y,int x)
    {
    
    
        // 周围存活细胞个数
        int count = 0;
        foreach(var map in roundMap)
        {
    
    
            int mx = x + ((int)map.x);
            int my = y + ((int)map.y);
            if(mx >= 0 && mx < width && my >=0 && my < height)
            {
    
    
                count += Cells[my][mx].state ? 1 : 0;
            }
        }
        var cell = Cells[y][x];
        var newState = cell.state;
        //当前细胞为死亡状态时,当周围有3个存活细胞时,则迭代后该细胞变成存活状态(模拟繁殖);若原先为生,则保持不变。
        if (cell.IsDead() && count == 3) newState = true;
        else if(!cell.IsDead())
        {
    
    
            //当前细胞为存活状态时,当周围的邻居细胞低于两个(不包含两个)存活时,该细胞变成死亡状态(模拟生命数量稀少)。
            if (count < 2) newState = false;
            //当前细胞为存活状态时,当周围有两个或3个存活细胞时,该细胞保持原样。
            if (count == 2 || count == 3) newState = cell.state;
            //当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态(模拟生命数量过多)。
            if (count > 3) newState = false;
        }
        cell.SetTmpState(newState);
    }

    void ChangeTmpState()
    {
    
    
        for (int i = 0; i < height; ++i)
        {
    
    
            for (int j = 0; j < width; ++j)
            {
    
    
                var cell = Cells[i][j];
                cell.SetState(cell.tmpState);
            }
        }
    }
    // Update is called once per frame
    void Update()
    {
    
    
        if(Input.GetMouseButtonDown(0))
        {
    
    
            var mousePos = Input.mousePosition;
            int x = Mathf.FloorToInt(mousePos.x / CellLength);
            int y = Mathf.FloorToInt(mousePos.y / CellLength);
            if (x >= 0 && x < width && y >= 0 && y < height)
                Cells[y][x].SetState(!Cells[y][x].state);
        }

        AutoUpdate();
    }
    float lastTime;
    bool isAuto = false;
    void AutoUpdate()
    {
    
    
        if(isAuto)
        {
    
    
            if(Time.time - lastTime >= speed)
            {
    
    
                lastTime = Time.time;
                NextRound();
            }
        }
    }
    private void OnGUI()
    {
    
    
        GUI.Label(new Rect(Screen.width - 300, 0, 400, 40), $"Round {
      
      round}");
        if (GUI.Button(new Rect(Screen.width - 100, 0, 100, 40), "Reset"))
        {
    
    
            ClearState();
            isAuto = false;
        }
        if (GUI.Button(new Rect(Screen.width - 200, 00, 100, 40), "Next"))
        {
    
    
            NextRound();
        }
        if (GUI.Button(new Rect(Screen.width - 300, 00, 100, 40), "Auto"))
        {
    
    
            isAuto = !isAuto;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/fztfztfzt/article/details/125815221