如何使用 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 一样的完全成熟的物理系统来模仿它会遇到问题。
马里奥是一款基于瓷砖的游戏,我想他有一个X
、Y 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:SKSpriteNode 包含另一个 SKSpriteNodes 但只有一个 SKPhysicsBody