当前位置: 首页 > 知识库问答 >
问题:

抛光简单的贪吃蛇游戏

百里成仁
2023-03-14

按照我找到的这个教程,我一直在Unity(C#)中创建了一个简单的贪吃蛇游戏:

https://www.youtube.com/watch?v=U8gUnpeaMbQ

我发现这是一个非常好的教程,到最后我有一个完美的蛇游戏,但是,我想走得更远一点,使运动更加愉快,添加尾巴,Gameover等。

现在我的问题是,如果一个玩家快速连续按下两个可接受的方向试图抓住一些食物,蛇的头会跳过食物,完全错过它。

发生这种情况是由于以下代码位:

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个键会导致蛇与自身碰撞(假设蛇正在向右移动,如果向上和向左快速连续地按压,蛇将开始向左移动,然后才能向上移动,与它的身体碰撞)。

以下是完整代码:

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:在一个简单的蛇游戏中,当两个方向快速连续按下时,我如何确保蛇在转向第二个方向之前会朝第一个方向移动,而不会出现虫子。

谢谢!

共有1个答案

司马萧迟
2023-03-14

做一个红色的立方体,控制蛇移动的方向,还有遇到食物和吃食物的功能,在Update()中,WSAD和方向键控制蛇头的移动方向,而蛇头向上移动时不能向下移动,蛇向左移动时不能向右移动。

         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;
    }

}

蛇与食物相撞后,身体会长出一段,在遇到食物时,会先破坏食物,然后增加自己身体的长度,此时设定的相撞位旗会变成真,身体长度会增加,但当它撞到自己时,撞到墙上时,它会死亡,此时,它会在开始时被导入场景。

  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);
    }
}

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

  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()函数,此时它会随机出现在ShowFood中。食物。下面是ShowFood()函数的代码

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

 类似资料:
  • 本文向大家介绍python实现简单贪吃蛇游戏,包括了python实现简单贪吃蛇游戏的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 代码: 更多有趣的经典小游戏实现专题,分享给大家: C++经典小游戏汇总 python经典小游戏汇总 python俄罗斯方块游戏集合 JavaScript经典游戏 玩不停 java经典小游戏汇

  • 本文向大家介绍js实现贪吃蛇游戏(简易版),包括了js实现贪吃蛇游戏(简易版)的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了js实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 直接开始 效果图: 项目结构:图片自己找的 1.html 2.area.js 3.config.js 4.food.js 5.init.js 6.move.js 7.score.js 8.snake.js

  • 本文向大家介绍python实现贪吃蛇游戏,包括了python实现贪吃蛇游戏的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下 本文稍作改动,修复一些bug,原文链接:python实现贪吃蛇游戏 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 本文向大家介绍python贪吃蛇游戏代码,包括了python贪吃蛇游戏代码的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python贪吃蛇游戏的具体代码,供大家参考,具体内容如下 贪吃蛇游戏截图: 首先安装pygame,可以使用pip安装pygame: pip install pygame 运行以下代码即可: 操作方法: 上下左右键或wsad键控制 ESC键退出游戏 下载代码:贪吃

  • 本文向大家介绍Python写的贪吃蛇游戏例子,包括了Python写的贪吃蛇游戏例子的使用技巧和注意事项,需要的朋友参考一下 第一次用Python写这种比较实用且好玩的东西,权当练手吧 游戏说明: * P键控制“暂停/开始” * 方向键控制贪吃蛇的方向 源代码如下:

  • 本文向大家介绍C语言单链表贪吃蛇小游戏,包括了C语言单链表贪吃蛇小游戏的使用技巧和注意事项,需要的朋友参考一下 C语言实现单链表控制台贪吃蛇小游戏,供大家参考。 编译环境:vs2019 需求: 统计游戏开始后的时间,控制贪吃蛇;吃到食物蛇身加长,得分加一;碰墙或蛇头碰到身体减一条生命;生命消耗完则结束游戏。 思路: 使用wasd键控制蛇的移动方向,蛇头碰到食物得分加一,并在地图上随机产生一个食物,