首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >抛光简单蛇游戏

抛光简单蛇游戏
EN

Stack Overflow用户
提问于 2022-04-08 22:04:45
回答 1查看 399关注 0票数 0

在本教程之后,我一直在联合(C#)创建一个简单的蛇游戏,我发现:

https://www.youtube.com/watch?v=U8gUnpeaMbQ&t=1s&ab_channel=Zigurous

我发现这是一个非常好的教程,到最后我有了一个完美的蛇游戏,然而,我想更进一步,使运动更愉快,添加一个尾巴,游戏,等等。

现在我的问题是,如果玩家连续按两个可以接受的方向,试图获取一些食物,蛇的头就会跳过食物,完全错过了。

发生这种情况的原因是以下代码:

代码语言:javascript
复制
private void Update() //Gets Key Inputs and execute Commands
{   
    if (Input.GetKeyDown(KeyCode.UpArrow) )
    {
        while(tempPosition == _segments[0].position)
        {
            for (int i = _segments.Count - 1; i > 0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if(_direction != Vector2.down)
        {
            _direction = Vector2.up;
            tempPosition = _segments[0].position;
        }
        
    }
    else if (Input.GetKeyDown(KeyCode.LeftArrow) )
    {
        while (tempPosition == _segments[0].position)
        {
            for (int i = _segments.Count - 1; i > 0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if (_direction != Vector2.right)
        {
            _direction = Vector2.left;
            tempPosition = _segments[0].position;
        }
    }
    else if (Input.GetKeyDown(KeyCode.RightArrow) )
    {
        while (tempPosition == _segments[0].position)
        {
            for (int i = _segments.Count - 1; i > 0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if (_direction != Vector2.left)
        {
            _direction = Vector2.right;
            tempPosition = _segments[0].position;
        }
    }
    else if (Input.GetKeyDown(KeyCode.DownArrow) )
    {            
        while (tempPosition == _segments[0].position)
        {
            for(int i = _segments.Count -1; i>0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if (_direction != Vector2.up)
        {
            _direction = Vector2.down;
            tempPosition = _segments[0].position;
        }
    }

正如你所看到的,按下一个键会立刻移动蛇的头,导致问题的发生。

然而,如果没有这样的编码,快速连续按下2个键就会使蛇与自身发生碰撞(假设蛇正在向右移动,如果向上和左侧被快速按压,蛇将开始向左移动,然后才能向上移动,与其身体发生碰撞)。

以下是完整的代码:

代码语言:javascript
复制
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class Snake : MonoBehaviour
{
private Vector2 _direction = Vector2.right;
public List<Transform> _segments = new List<Transform>();
public Transform segmentPrefab;
public Transform tail;
public int initialSize = 4;
public int score = 0;
private Vector3 tempPosition;
public GameObject food;
public Text gameOver;
private void Start()
{
    ResetState();
}
private void Update() //Gets Key Inputs and execute Commands
{   
    if (Input.GetKeyDown(KeyCode.UpArrow) )
    {
        while(tempPosition == _segments[0].position)
        {
            for (int i = _segments.Count - 1; i > 0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if(_direction != Vector2.down)
        {
            _direction = Vector2.up;
            tempPosition = _segments[0].position;
        }
        
    }
    else if (Input.GetKeyDown(KeyCode.LeftArrow) )
    {
        while (tempPosition == _segments[0].position)
        {
            for (int i = _segments.Count - 1; i > 0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if (_direction != Vector2.right)
        {
            _direction = Vector2.left;
            tempPosition = _segments[0].position;
        }
    }
    else if (Input.GetKeyDown(KeyCode.RightArrow) )
    {
        while (tempPosition == _segments[0].position)
        {
            for (int i = _segments.Count - 1; i > 0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if (_direction != Vector2.left)
        {
            _direction = Vector2.right;
            tempPosition = _segments[0].position;
        }
    }
    else if (Input.GetKeyDown(KeyCode.DownArrow) )
    {            
        while (tempPosition == _segments[0].position)
        {
            for(int i = _segments.Count -1; i>0; i--)
            {
                _segments[i].position = _segments[i - 1].position;
            }
            this.transform.position = new Vector3(
                Mathf.Round(this.transform.position.x + _direction.x),
                Mathf.Round(this.transform.position.y + _direction.y),
                0.0f
                );
        }
        if (_direction != Vector2.up)
        {
            _direction = Vector2.down;
            tempPosition = _segments[0].position;
        }
    }
    if(Input.GetKeyDown(KeyCode.R))
    {
        ResetState();
    }
}
private void FixedUpdate() //Handles moviment
{
    if (gameOver.gameObject.activeSelf == false)
    {            
        for (int i = _segments.Count - 1; i > 0; i--)
        {
            _segments[i].position = _segments[i - 1].position;
        }
        this.transform.position = new Vector3(
            Mathf.Round(this.transform.position.x + _direction.x),
            Mathf.Round(this.transform.position.y + _direction.y),
            0.0f
            );
    }
}
/*Instantiates a new segment, sets it's position to tail position,
  destroys tail from list and adds new segment in it's place, adds new tail at end*/
private void Grow() 
{
    Transform segment = Instantiate(this.segmentPrefab);
    segment.position = _segments[_segments.Count - 1].position;
    Destroy(_segments[_segments.Count - 1].gameObject);
    _segments.Remove(_segments[_segments.Count - 1]);
    _segments.Add(segment);
    Transform segmenttail = Instantiate(this.tail);

    segmenttail.position = _segments[_segments.Count - 1].position;

    _segments.Add(segmenttail);
}
private void ResetState()
{
    gameOver.gameObject.SetActive(false);
    tempPosition.x = 1000;
    score = 0;
    for (int i = 1; i < _segments.Count; i++)
    {
        Destroy(_segments[i].gameObject);
    }
    _segments.Clear();
    _segments.Add(this.transform);
    for (int i = 1; i < initialSize; i++)
    {
        _segments.Add(Instantiate(this.segmentPrefab));
    }
    _segments.Add(Instantiate(this.tail));
    this.transform.position = Vector3.zero;
    this.GetComponent<SpriteRenderer>().enabled = (true);
    food.GetComponent<Food>().RandomizePosition();
}
private void OnTriggerEnter2D(Collider2D other)
{
    if (other.tag == "Food")
    {
        Grow();
        score++;
    }
    else if(other.tag == "Obstacle")
    {
        for (int i = 1; i < _segments.Count; i++)
        {
            Destroy(_segments[i].gameObject);
        }
        this.GetComponent<SpriteRenderer>().enabled=(false);
        _segments.Clear();
        food.gameObject.SetActive(false);
        gameOver.gameObject.SetActive(true);
    }

}

}

tl;dr:在一个简单的蛇游戏中,当两个方向被快速地按下时,我如何确保蛇在转向第二个方向之前,在没有错误的情况下,向第一个方向移动。

,谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-13 07:43:26

制作一个红色立方体,控制蛇的运动方向,以及遇到食物和吃东西的功能。在Update()中,WSAD和方向键控制蛇头的移动方向。当蛇头向上移动时,它不能向下移动,当蛇向左移动时,它就不能向右移动。

代码语言:javascript
复制
         void Update () {
         if (Input.GetKey(KeyCode.W)||Input.GetKey("up")&&direction!= 
Vector2.down)
    {
        direction = Vector2.up;
    }
    if (Input.GetKey(KeyCode.S) || Input.GetKey("down") && direction != Vector2.up)
    {
        direction = Vector2.down;
    }
    if (Input.GetKey(KeyCode.A) || Input.GetKey("left") && direction != Vector2.right)
    {
        direction = Vector2.left;
    }
    if (Input.GetKey(KeyCode.D) || Input.GetKey("right") && direction != Vector2.left)
    {
        direction = Vector2.right;
    }

}

当蛇与食物相撞后,它的身体就会长出一段。当遇到食物时,它会首先破坏食物,然后增加自己身体的长度。此时,设置的碰撞位标志将变为真,身体长度将增加。然而,当它撞到自己,当它撞到一堵墙时,它就会死掉,此时,它将在一开始就被导入到场景中。

代码语言:javascript
复制
  void OnTriggerEnter(Collider other)
  {
    if (other.gameObject.CompareTag("Food"))
    {
        //Debug.Log("hit it!");
        Destroy(other.gameObject);
        flag = true;

    }
    else
    {
        //SceneManager.LoadScene(0)
        Application.LoadLevel(1);
    }
}

身体每次生长的算法就是吃蛇的难度。Internet上的许多算法都是通过使用链表来实现的。链表的节点表示蛇的增加或减少非常方便。移动时,只需添加一个头节点并删除它。尾节点就足够了,要吃东西,只需要添加一个头节点。这个算法是绝对巧妙的,但由于互联网上有太多,下面是另一个由链接列表实现的吃蛇算法。蛇的头一动也不动,最后的身体移到前面,然后慢慢地向后移动。下面的蓝色方格(身体部分的设置)一步一步地移动,你可以看到这种效果。蛇的身体部分的代码张贴在下面。如果食物被吃了,旗子就是真的。这是为了插入一个预制立方体到蛇的身体,蛇的身体将增长更长。当没有食物的时候,它会在此时观察身体的数量。当数字大于0时,最后一个将放置在前面,循环将一直持续到结束。

代码语言:javascript
复制
  void Move()
  {
    Vector3 VPosition = transform.position;
    transform.Translate(direction);
    if (flag)
    {
        GameObject bodyPrefab = (GameObject)Instantiate(gameObjecgtBody, VPosition, Quaternion.identity);
        Body.Insert(0, bodyPrefab.transform);
        flag = false;
    }
    else if (Body.Count > 0)
    {
        Body.Last().position = VPosition;
        Body.Insert(0, Body.Last());
        Body.RemoveAt(Body.Count - 1);
    }
}

食物的出现是一个随机的过程。此时,食物出现在一个随机的位置。InvokeRepeating(" ShowFood ",1,4);意味着ShowFood()函数将在4秒内被调用,此时它将随机出现在ShowFood中。食物。下面是ShowFood()函数的代码

代码语言:javascript
复制
void ShowFood()
 {
    int x = Random.Range(-30, 30);
    int y = Random.Range(-22, 22);
    Instantiate(SSFood, new Vector2(x,y), Quaternion.identity);
    
  }

特别注意的是,当制作蛇头和蛇身时,如果将碰撞体的体积设置为单元1,则蛇体的侧面也会撞到食物,触发对撞机。所以把对撞机的体积设置为0.8,这略小于1,我也从互联网上找到了信息,希望它能对你有所帮助,这个链接是源代码https://github.com/xiaogeformax/Snake/tree/master/Snake5.2

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71803575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档