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

抛光简单蛇游戏
EN

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

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

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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-12 23:43:26

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
         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
代码运行次数:0
运行
AI代码解释
复制
  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
代码运行次数:0
运行
AI代码解释
复制
  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
代码运行次数:0
运行
AI代码解释
复制
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

复制
相关文章
js获取iframe中的内容(iframe内嵌页面)
在父页面中定义函数,再到子页面中调用。 父页面parent.html function getFrameId(f){ var frames = document.getElementsByTagName(“iframe”); //获取父页面所有iframe for(i=0;i
全栈程序员站长
2022/08/01
24.7K0
js获取iframe中的内容(iframe内嵌页面)
iframe跨域应用 - 使用iframe提交表单数据
之前我们提到了iframe跨域,今天我们在原有的基础之上进行“实例”的讲解。通过iframe跨域实现表单数据的提交。如果想了解iframe跨域,可以发送“iframe跨域”到“HTML5学堂”公众号。 为何提交数据还要跨域? 在使用iframe跨域之前,可能你的脑海中就出现了这样一个问题:为何提交表单数据还需要跨域呢? 首先我们要知道,网站的数据是存放在服务器上的,而当一个网站很大型,拥有很多的数据时,通常会进行分类,然后将不同类的内容放置在不同的子域名中。 表单数据的提交模式 今天会使用到MD5的知识,因
HTML5学堂
2018/03/12
5.3K0
adminLte解决iframe高度问题
adminLte默认是全局刷新,也就是不存在frame页面,经过修改,可以很容易实现右边内容框用frame实现页面刷新,这样就不需要整个页面全局刷新,点击相应菜单时,只会刷新frame窗口,但是有一个问题就是frame默认高度只有一丁点,百度之后用了自适应也会有各种问题,比如高度只能拉伸不会缩短,在解决的道路上真的是没有一个完美的解决方案,经过自己研究,发现一个非常简单的方法,那就是用js获取window的innerHeight,代码实现window.innerHeight,然后出去顶部的状态栏,以及空白部分,经过测试,窗口高度减去90是最合适的,也可以根据你自己的情况加减,最后调至一个最完美高度,发现任何分辨率都不会有问题!
全栈程序员站长
2022/09/18
9410
vue项目iframe的传值问题
  所以。我把插件的使用封装了一个html页面。vue项目则利用iframe的方式引入。
Dawnzhang
2019/11/21
1.8K0
pyppeteer对于iframe中的滑块
import asyncio import time import numpy, random import pyppeteer async def main(): ip = "xxxxxx" #代理ip port = "xxxx" #代理端口 browser = await pyppeteer.launch({'headless': False, 'args': [
小小咸鱼YwY
2020/12/21
2.8K0
【HTML】Iframe中的onload事件
当iframe.src重新指定一个url时会重新执行iframe的onload事件 <iframe id="indexFrame" name="index" width="800" onload='iFrameHeight("indexFrame");'                 frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> html生成时,会执行iframe中的onload事件 当iframe.sr
悟空聊架构
2018/05/18
3.4K0
DNS在远程调用执行中的应用
纯属蹭log4j2热度文,和安全没有直接的关系,本文只谈DNS以及日志应用; 通过dnslog.cn的截图,分析dnslog.cn的原理,基于此,介绍了可以获取更多信息的ceye的功能;在应用场景上,我们通过该原理提供了用户出口IP同本地DNS递归出口IP的对应关系,延伸出了排障场景和数据分析场景。
hermanzeng
2021/12/14
6K3
DNS在远程调用执行中的应用
深入剖析iframe跨域问题
HTML5学堂:本文当中我们介绍了跨域的基本知识,讲解到了跨域的相关种类,并讲解了解决跨域中的一种方法——如何使用iframe跨域。讲解了iframe跨域的基本原理与流程,并配以实战~ 利利的独白:跨域,是我们的课程中必不可少的一部分,但是我们一直都是在讲解JSONP的跨域方式,虽然也提到了iframe的跨域方式,但是由于时间因素,并没有办法放置到课程中。 本文仅仅讲明了iframe的跨域问题,想了解更多关于iframe标签的基本知识,直接发送 “iframe标签” 到 “HTML5学堂” 的微信。 什么是
HTML5学堂
2018/03/12
14.6K0
深入剖析iframe跨域问题
layui打开iframe窗口不刷新的问题
这个问题可能是我工作以来,最死磕不算bug的一个了,晚上熬夜到三点钟,终于找到了解决的办法。
王小婷
2019/04/29
4K0
layui打开iframe窗口不刷新的问题
网页嵌入Iframe中
<iframe id="reportFrame" width="900" height="400" src="https://www.baidu.com/"></iframe> 如果把第三方网页嵌到iframe中,下面以百度为例 Refused to display 'https://www.baidu.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'. 开发时通过配置代理 <iframe id="reportFra
tianyawhl
2022/08/07
1.8K0
深度学习在环境远程遥感中的应用
本文是关于深度学习在环境远程遥感方面的应用研究进展及面临的挑战。简要介绍由武汉大学张良培教授团队的这篇综述文章。
bugsuse
2020/04/21
1K0
深度学习在环境远程遥感中的应用
JavaScript 处理Iframe自适应高度的问题
 用到的就是iframe嵌套的页面加载完毕的时候,运用onload事件来获取嵌套在iframe中网页的高度,然后赋值给Iframe的高度即可。
aehyok
2018/09/11
1.6K0
iframe编程的一些问题
前几天做一个用iframe显示曲线图的demo,发现对iframe的contentDocument绑定 onclick事件都无效,而在页面中对iframe.contentDocument的onclick 属性为undefined;而当iframe去掉src属性后,在对其绑定onclick事件,该事件生效; 对比之下才发现原来当对iframe.contentDocument绑定事件时,iframe还没有加载 完毕,此时对于contentDocument虽然可以绑定该事件处理函数,但是却无法执行, 因为此时co
欲休
2018/03/15
9610
【JS应用】Iframe 解决跨域
跨域的东西, 简直不要接触太多,网上相关内容一抓一大把,但是突然学习到一个关于前端解决跨域的方式
神仙朱
2019/11/07
15.5K0
【JS应用】Iframe 解决跨域
如何在 WordPress 中嵌入 iFrame
Iframe 是一种将网页嵌入到另一个页面的内容中的方法。这是通过使用 HTML 元素、外部网站的 URL 以及窗口在您的网站上的外观参数来实现的。
海拥
2022/12/11
2.4K0
如何在 WordPress 中嵌入 iFrame
jQuery控制iframe中对象的方法
jQuery中的$()方法很容易获取到DOM中的元素。但是这个方法不适用于引用iframe中的元素。 如下面的html a.htm
EltonZheng
2021/01/26
2.1K0
IE中iframe跨域访问
本文主要讲述了IE浏览器中iframe跨域访问的问题以及如何解决。主要包括三个方面:1.什么是跨域,以及跨域引发的问题;2.如何解决跨域问题,分别从浏览器和服务器两个方面给出方案;3.浏览器和服务器在解决跨域问题的过程中需要注意的一些细节。
高爽
2017/12/28
4.3K0
IE中iframe跨域访问
JavaScript中给 iframe 中的元素添加点击事件
最近在开发一个浏览器插件,需要抓取掌中云平台的数据,由于该平台的页面结构是采用iframe嵌套的方式加载的, 所以在添加事件的时候遇到了一点小麻烦,现特此将解决方法记录如下,以供大家复制粘贴。
越陌度阡
2022/11/27
3.6K0
点击加载更多

相似问题

.Net城域应用中的MarkUpExtension

10

未触发BackgroundTask的城域应用程序问题

12

城域WinRT应用中的AesManaged解密

20

WindowsBase组件结构在城域应用中的应用

13

分组CollectionViewSource在windows 8城域应用中的应用

13
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文