草庐IT

swift - 蛇在垂直方 block 中移动

coder 2023-09-15 原文

我正在尝试使用 SpriteKit 制作蛇游戏(就像旧诺基亚手机中的游戏)。问题是,当蛇的方向改变时,蛇在一个静止的垂直 block 中移动,并没有得到 L 形(如图所示)。为了进入上下文,我有一个名为 SKDSpriteNode 的类,它与 SKSpriteNode 相同,但有一个额外的 direction 属性; Snake 类有 directionlength 属性。有一个 snakeBody 属性,类型为 [SKDSpriteNode],包含蛇体的节点。

蛇的方向在游戏开始时分配给.up,然后由用户的滑动分配。 顺便说一句,changeDirection 方法在蛇的方向改变时被调用(使用 didSet)。这是代码和图片:

extension ClassicLevelScene {

func startGame() { snake.direction = .up; moveSnake() }

func checkPlacement(for node: SKDSpriteNode) -> SKAction {
    return SKAction.run({
        if !(node.isInsideFrame(of: self)) { self.gameOver() }
    })
}

func getMovement(for node: SKDSpriteNode) -> (once: SKAction, repetitive: SKAction) {
    let movement = SKAction.move(by: node.direction.getVector(withIntensity: movementSpeed), duration: 0.5)
    let moveAction = SKAction.sequence([movement, checkPlacement(for: node)])
    let repetitiveMoveAction = SKAction.repeatForever(moveAction)
    return (moveAction, repetitiveMoveAction)
}

func moveSnake() {
    for node in snakeBody { 
        node.removeAllActions()
        node.run(getMovement(for: node).1) 
    }
}

func moveOnce() {
    for node in snakeBody { 
        node.removeAllActions()
        node.run(getMovement(for: node).0) 
    }
}

func changeDirection() {
    for i in 0..<snake.length {
        if i == 0 {
            snakeBody[i].direction = snake.direction
            snakeBody[i].run(SKAction.move(by: snakeBody[i].direction.getVector(withIntensity: movementSpeed), duration: 0.5))
        } else {
            snakeBody[i].direction = snakeBody[i-1].direction
            snakeBody[i].run(SKAction.move(to: snakeBody[i-1].oldPosition, duration: 0.5))
        }
    }
}

最佳答案

我需要发布一个答案来向您展示代码,但您应该只移动头部,让尾部拖在后面。现在有更好的方法可以做到这一点,但是为了简化您已经编写的代码,它应该是这样的

extension ClassicLevelScene {

    func startGame() { snake.direction = .up; moveSnake() }

    func checkPlacement(for node: SKSpriteNode) -> SKAction {
        return SKAction.run({
            if !(node.isInsideFrame(of: self)) { self.gameOver() }
        })
    }

    func getMovement(for node: SKDSpriteNode) -> (once: SKAction, repetitive: SKAction) {
        let movement = SKAction.move(by: node.direction.getVector(withIntensity: movementSpeed), duration: 0.5)
        let moveTail = SKAction.run({self.moveTail()})
        let moveAction = SKAction.sequence([movement, moveTail,checkPlacement(for: node)])
        let repetitiveMoveAction = SKAction.repeatForever(moveAction)
        return (moveAction, repetitiveMoveAction)
    }

    func moveTail()
    {
        for i in 1..<snake.length {
                snakeBody[i].direction = snakeBody[i-1].direction
                snakeBody[i].position = snakeBody[i-1].oldPosition
        }
    }

    func moveSnake() {
        let head = snakeBody[0] { 
            head.removeAllActions()
            head.run(getMovement(for: head).1) 
        }
    }

    func moveOnce() {
        let head = snakeBody[0] { 
            head.removeAllActions()
            head.run(getMovement(for: head).0) 
        }
    }

    func changeDirection() {
            let head = snakeBody[0] { 
            head.removeAllActions()
            head.direction = snake.direction
            head.run(SKAction.move(by:  head.direction.getVector(withIntensity: movementSpeed), duration: 0.5))
    }
}

关于swift - 蛇在垂直方 block 中移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45121946/

有关swift - 蛇在垂直方 block 中移动的更多相关文章

  1. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  4. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  5. ruby - 在匿名 block 中产生 - 2

    我没有理解以下行为(另请参阅inthisSOthread):defdef_testputs'def_test.in'yieldifblock_given?puts'def_test.out'enddef_testdoputs'def_testok'endblock_test=procdo|&block|puts'block_test.in'block.callifblockputs'block_test.out'endblock_test.calldoputs'block_test'endproc_test=procdoputs'proc_test.in'yieldifblock_gi

  6. ruby-on-rails - rbenv:从 RVM 移动到 rbenv 后,在 Jenkins 执行 shell 中找不到命令 - 2

    我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions

  7. ruby - Ruby 中的单 block AES 解密 - 2

    我需要尝试一些AES片段。我有一些密文c和一个keyk。密文已使用AES-CBC加密,并在前面加上IV。不存在填充,纯文本的长度是16的倍数。所以我这样做:aes=OpenSSL::Cipher::Cipher.new("AES-128-CCB")aes.decryptaes.key=kaes.iv=c[0..15]aes.update(c[16..63])+aes.final它工作得很好。现在我需要手动执行CBC模式,所以我需要单个block的“普通”AES解密。我正在尝试这个:aes=OpenSSL::Cipher::Cipher.new("AES-128-ECB")aes.dec

  8. ruby-on-rails - 无法在 Rails 助手中捕获 block 的输出 - 2

    我在使用自定义RailsFormBuilder时遇到了问题,从昨天晚上开始我就发疯了。基本上我想对我的构建器方法之一有一个可选block,以便我可以在我的主要content_tag中显示其他内容。:defform_field(method,&block)content_tag(:div,class:'field')doconcatlabel(method,"Label#{method}")concattext_field(method)capture(&block)ifblock_given?endend当我在我的一个Slim模板中调用该方法时,如下所示:=f.form_field:e

  9. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  10. ruby - 在参数为 `yield self` 的方法中使用 `&block` 和在没有参数 `yield self` 的方法中使用 `&block` 有什么区别吗? - 2

    我明白了defa(&block)block.call(self)end和defa()yieldselfend导致相同的结果,如果我假设有这样一个blocka{}。我的问题是-因为我偶然发现了一些这样的代码,它是否有任何区别或者是否有任何优势(如果我不使用变量/引用block):defa(&block)yieldselfend这是一个我不理解&block用法的具体案例:defrule(code,name,&block)@rules=[]if@rules.nil?@rules 最佳答案 我能想到的唯一优点就是自省(introspecti

随机推荐