如何使用 SpriteKit 制作类似马里奥的角色动作?

Posted

技术标签:

【中文标题】如何使用 SpriteKit 制作类似马里奥的角色动作?【英文标题】:How do I make a Mario-like character movement with SpriteKit? 【发布时间】:2015-06-26 20:36:44 【问题描述】:

我正在使用 SpriteKit 制作游戏,但我无法让我的角色动作与超级马里奥相似。

我想让他根据触摸的方向向侧面移动,以及用户何时松开我希望他停下来。

有没有人可以帮助我编写必要的代码?

这是我的 GameScene.swift 文件:

import SpriteKit


class GameScene: SKScene, SKPhysicsContactDelegate 

let character = SKSpriteNode(texture: SKTexture(imageNamed: "character"))
var move = false

override func didMoveToView(view: SKView) 
    /* Setup your scene here */
    //world
    self.physicsWorld.gravity = CGVectorMake(0.0, -5.0)
    self.physicsWorld.contactDelegate = self
    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)

    //background
    var background = SKSpriteNode(imageNamed: "background")
    background.size.height = self.frame.size.height
    background.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
    self.addChild(background)


    //character
    character.position = CGPointMake(self.frame.size.width * 0.6, self.frame.size.height * 0.6)
    character.setScale(0.015)
    character.physicsBody = SKPhysicsBody(circleOfRadius: CGFloat(character.size.width / 2))
    character.physicsBody?.dynamic = true
    self.addChild(character)


    //platform 1
    var platformTexture = SKTexture(imageNamed: "platform")
    var platform = SKSpriteNode(texture: platformTexture)
    platform.position = CGPointMake(self.frame.size.width * 0.6, CGRectGetMidY(self.frame))
    platform.physicsBody = SKPhysicsBody(rectangleOfSize: platform.size)
    platform.physicsBody?.dynamic = false
    platform.setScale(0.25)
    self.addChild(platform)

    //platform 2
    var platformTexture2 = SKTexture(imageNamed: "platform")
    var platform2 = SKSpriteNode(texture: platformTexture2)
    platform2.position = CGPointMake(self.frame.size.width * 0.4, self.frame.size.height * 0.3)
    platform2.physicsBody = SKPhysicsBody(rectangleOfSize: platform2.size)
    platform2.physicsBody?.dynamic = false
    platform2.setScale(0.25)
    self.addChild(platform2)


    //platform main
    var platformTexture3 = SKTexture(imageNamed: "platform")
    var platform3 = SKSpriteNode(texture: platformTexture2)
    platform3.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame) + platform3.size.height / 3)
    platform3.physicsBody = SKPhysicsBody(rectangleOfSize: platform3.size)
    platform3.physicsBody?.dynamic = false
    platform3.setScale(1)
    platform3.size.width = platform3.size.width * CGFloat(2.0)
    self.addChild(platform3)




override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
   var charPos = character.position
    /* Called when a touch begins */
   for touch: AnyObject in touches 
    let location = touch.locationInNode(self)
    //Hold finger at upper area to move character constantly to the right.
    if location == charPos
        character.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 20))
    
    else 

    
    if location.y > 400
        //moving allowed, force is applied in update method. read the docs about applyImpulse and applyForce methods and the differences between those two.
        move = true

    else

        if location.x < CGRectGetMidX(self.frame)
            character.physicsBody?.applyImpulse(CGVector(dx: -10, dy: 0))
         else if location.x > CGRectGetMidX(self.frame)
            character.physicsBody?.applyImpulse(CGVector(dx: 10, dy: 0))
                        
    




override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) 






 func update(currentTime: CFTimeInterval) 
    /* Called before each frame is rendered */

【问题讨论】:

【参考方案1】:

Mario 使用了一个相当简单的角色移动系统 - 使用像 SpriteKit 一样的完全成熟的物理系统来模仿它会遇到问题。

马里奥是一款基于瓷砖的游戏,我想他有一个XY position、一个xVelocity 和一个yVelocity。每个 runloop 都会计算他的速度并更新他的位置。这就是为什么你可以在空中改变方向(你的控制器改变了他的速度)。

您将使用物理引擎来反映这一点,并且您绝对不想通过施加冲动来控制角色:它们会随着时间的推移而解决(因为它们会变慢),而您无法控制它。

【讨论】:

【参考方案2】:
// : Disable continuous movement and one movement per keyboard tapped or continuous movement when keyboard is held
// Swift-Mario Game: I need help to disable continuous movement, and I want one movement per keyboard tapped and continuous movement when keyboard is Held.


func run(direction: String) 

    if direction == "right" 

        let rightAnimation = SKAction.animateWithTextures([rightTexture1, rightTexture2, rightTexture3, rightTexture4], timePerFrame: 0.08)
        let rightAnimationContinuous = SKAction.repeatActionForever(rightAnimation)

        let moveRight = SKAction.moveByX(10, y: 0, duration: 0.1)
        let moveRightForEver = SKAction.repeatActionForever(moveRight)

        hero.runAction(SKAction.group([rightAnimationContinuous, moveRightForEver]), withKey: "runningRight")

     else if direction == "left" 

        let leftAnimation = SKAction.animateWithTextures([leftTexture1, leftTexture2, leftTexture3, leftTexture4], timePerFrame: 0.08)
        let leftAnimationContinuous = SKAction.repeatActionForever(leftAnimation)

        let moveLeft = SKAction.moveByX(-10, y: 0, duration: 0.1)
        let moveLeftForEver = SKAction.repeatActionForever(moveLeft)

        hero.runAction(SKAction.group([leftAnimationContinuous, moveLeftForEver]), withKey: "runningLeft")
    

    self.runAction(SKAction.repeatActionForever(runningsound), withKey: "runsound") 


func stop(direction: String) 

    if direction == "right" 

        hero.removeAllActions()
        hero.texture = rightTextureStill

     else if direction == "left" 

        hero.removeAllActions()
        hero.texture = leftTextureStill
    

    self.removeActionForKey("runsound")

【讨论】:

以上是关于如何使用 SpriteKit 制作类似马里奥的角色动作?的主要内容,如果未能解决你的问题,请参考以下文章

在 Spritekit 中扩展圆形切口过渡效果

使用 spritekit 和目标 c 更改英雄的外观

SpriteKit给游戏弹跳角色添加一个高度标示器

SpriteKit:SKSpriteNode 包含另一个 SKSpriteNodes 但只有一个 SKPhysicsBody

我正在使用 SpriteKit 制作游戏,但我的视图只占据了屏幕上看似安全的区域。如何扩展此视图?

通过在 SpriteKit/Swift 中向上滑动来跳跃角色