在本教程之后,我一直在联合(C#)创建一个简单的蛇游戏,我发现:
https://www.youtube.com/watch?v=U8gUnpeaMbQ&t=1s&ab_channel=Zigurous
我发现这是一个非常好的教程,到最后我有了一个完美的蛇游戏,然而,我想更进一步,使运动更愉快,添加一个尾巴,游戏,等等。
现在我的问题是,如果玩家连续按两个可以接受的方向,试图获取一些食物,蛇的头就会跳过食物,完全错过了。
发生这种情况的原因是以下代码:
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:在一个简单的蛇游戏中,当两个方向被快速地按下时,我如何确保蛇在转向第二个方向之前,在没有错误的情况下,向第一个方向移动。
,谢谢!
发布于 2022-04-12 23:43:26
制作一个红色立方体,控制蛇的运动方向,以及遇到食物和吃东西的功能。在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);
}
}
身体每次生长的算法就是吃蛇的难度。Internet上的许多算法都是通过使用链表来实现的。链表的节点表示蛇的增加或减少非常方便。移动时,只需添加一个头节点并删除它。尾节点就足够了,要吃东西,只需要添加一个头节点。这个算法是绝对巧妙的,但由于互联网上有太多,下面是另一个由链接列表实现的吃蛇算法。蛇的头一动也不动,最后的身体移到前面,然后慢慢地向后移动。下面的蓝色方格(身体部分的设置)一步一步地移动,你可以看到这种效果。蛇的身体部分的代码张贴在下面。如果食物被吃了,旗子就是真的。这是为了插入一个预制立方体到蛇的身体,蛇的身体将增长更长。当没有食物的时候,它会在此时观察身体的数量。当数字大于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()函数将在4秒内被调用,此时它将随机出现在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
https://stackoverflow.com/questions/71803575
复制相似问题