Swift 为什么精灵开始闪烁?
所以我创造了一个游戏,你轻拍球让它们跳起来。你每轻敲一次就得一分。为什么我的精灵在我达到10点时开始闪烁。我认为这与Swift 为什么精灵开始闪烁?,swift,sprite-kit,Swift,Sprite Kit,所以我创造了一个游戏,你轻拍球让它们跳起来。你每轻敲一次就得一分。为什么我的精灵在我达到10点时开始闪烁。我认为这与update(timeInterval)方法有关。这可能是一个错误或错误的编码 import SpriteKit class GameScene: SKScene { let backgroundNode = SKSpriteNode(imageNamed: "redbackground") override func didMoveToView(view: SKView) {
update(timeInterval)
方法有关。这可能是一个错误或错误的编码
import SpriteKit
class GameScene: SKScene {
let backgroundNode = SKSpriteNode(imageNamed: "redbackground")
override func didMoveToView(view: SKView) {
backgroundNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
self.addChild(backgroundNode)
//=======Ball 1=======//
let ball = Ball()
ball.position = CGPoint(x:self.frame.midX, y:440)
addChild(ball)
ball.physicsBody = SKPhysicsBody(circleOfRadius: 90)
ball.physicsBody?.dynamic = true
ball.physicsBody?.allowsRotation = false
ball.physicsBody?.friction = 0
ball.physicsBody?.angularDamping = 0
ball.physicsBody?.linearDamping = 0
ball.physicsBody?.usesPreciseCollisionDetection = true
ball.physicsBody!.categoryBitMask = 0
}
class Ball: SKSpriteNode {
init() {
let texture = SKTexture(imageNamed: "Ball")
super.init(texture: texture, color: .clearColor(), size: texture.size())
userInteractionEnabled = true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let scene = self.scene as! GameScene
scene.score += 1
physicsBody?.velocity = CGVectorMake(0, 100)
physicsBody?.applyImpulse(CGVectorMake(0, 900))
}
override func update(currentTime: CFTimeInterval) {
if (score >= 10){
self.backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
}
if (score >= 20){
self.backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
}
if (score >= 30) {
self.backgroundNode.texture = SKTexture(imageNamed: "greenbackground")
}
}
导入SpriteKit
类游戏场景:SKScene{
let backgroundNode=SKSpriteNode(图像名为:“redbackground”)
覆盖func didMoveToView(视图:SKView){
backgroundNode.position=CGPoint(x:CGRectGetMidX(self.frame),y:CGRectGetMidY(self.frame))
self.addChild(backgroundNode)
//==========球1=======//
让ball=ball()
ball.position=CGPoint(x:self.frame.midX,y:440)
addChild(球)
ball.physicsBody=SKPhysicsBody(圆圈半径:90)
ball.physicsBody?动态=真
ball.physicsBody?.allowsRotation=false
球体。物理体?摩擦力=0
球.物理体?.angularDamping=0
ball.physicsBody?.linearDamping=0
ball.physicsBody?.usesPreciseCollisionDetection=true
ball.physicsBody!.categoryBitMask=0
}
班级舞会:斯普林特诺德{
init(){
let texture=SKTexture(图像名为:“球”)
super.init(纹理:纹理,颜色:.clearColor(),大小:纹理.size())
userInteractionEnabled=true
}
覆盖功能触摸开始(触摸:设置,withEvent事件:UIEvent?){
让scene=self.scene为!游戏场景
场景分数+=1
physicsBody?速度=CGVectorMake(01100)
physicsBody?应用脉冲(CGVectorMake(0900))
}
覆盖函数更新(currentTime:CFTimeInterval){
如果(分数>=10){
self.backgroundNode.texture=SKTexture(ImageName:“orangebackground”)
}
如果(分数>=20){
self.backgroundNode.texture=SKTexture(ImageName:“yellowbackground”)
}
如果(分数>=30){
self.backgroundNode.texture=SKTexture(ImageName:“greenbackground”)
}
}
查看此内容以了解我的意思。(单击或点击链接)
提前感谢,Jordan正因为如此,它才会闪烁
override func update(currentTime: CFTimeInterval) {
if (score >= 10){
self.backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
}
if (score >= 20){
self.backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
}
if (score >= 30) {
self.backgroundNode.texture = SKTexture(imageNamed: "greenbackground")
}
}
实际上,在更新方法中,当分数变为=10
时,您正在更新纹理每帧
这是绝对错误的
如果要更新纹理,只需在需要更改纹理时执行(例如,当分数从9到10,或从19到20,或从29到30)
但是当纹理从10变为11时,当它保持在10时,更新纹理没有意义,因为你将使用另一个相同的纹理来更新它
你怎么能做到?
只需创建一个shouldUpdateTexture:Bool=false
属性,然后每次更新分数时,如果分数从9到10或19到20或29到30,则将shouldUpdateTexture
转到true
最后,在update
方法中检查shouldUpdateTexture
是否为true,在这种情况下,将其设置回false
并更新纹理
完整代码
class游戏场景:SKScene{
私人风险值得分=0{
迪塞特{
应该更新上下文=旧值<10&&score>=10 | |旧值<20&&score>=20 | |旧值<30&&score>=30
}
}
私有变量shouldUpdateTexture=false
私有var backgroundNode=SKSpriteNode(ImageName:“defaultbackground”)
覆盖函数更新(currentTime:CFTimeInterval){
如果应该更新上下文{
shouldUpdateTexture=false
交换分数{
案例10…19:backgroundNode.texture=SKTexture(图像名为:“orangebackground”)
案例20…29:backgroundNode.texture=SKTexture(图像名为:“yellowbackground”)
案例30…Int.max:backgroundNode.texture=SKTexture(图像名为:“yellowbackground”)
默认值:中断
}
}
}
}
就这样
更新
正如@Knight0fDragon所指出的,将我放入update
方法中的代码移动到didSet
中可能会更快
优点:这样您就不需要在每一帧执行布尔等式检查
Cons:如果在同一帧内多次更改分数
值,则将执行纹理的多次加载
您可以在得分
中添加属性观测者,而不是在更新
中更改背景图像,该属性观测者仅在得分达到特定值时更改背景。例如:
let backgroundNames = ["orangebackground","yellowbackground","greenbackground"]
// The didSet observer is called when the score is updated
var score:Int = 0 {
didSet {
// Check if score is divisible by 10
if score % 10 == 0 {
// Determine the array index
let index = score / 10
// Wrap to avoid index out of range
let name = backgroundNames[index % backgroundNames.count]
print (name)
}
}
}
也就是说,闪烁可能是由节点的呈现顺序造成的。根据苹果的文档
…使用[ignoresSiblingOrder=true],您无法预测
共享相同高度的节点的渲染顺序。渲染
每次渲染新帧时,顺序可能会更改
例如,您可以通过将背景的zPosition
设置为负值来解决此问题
self.backgroundNode.zPosition = -100
因此,背景总是在游戏节点之前绘制。这只是一种替代方法,允许分数发生多次变化,而不会用不必要的代码淹没更新功能
class GameScene: SKScene {
private var score = 0 {
didSet {
///if a change in the 10s happen, then update texture
if(score/10 > oldValue/10)
{
switch score{
case 10...19: backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
case 20...29: backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
case 30...Int.max: backgroundNode.texture = SKTexture(imageNamed: "greenbackground")
default: break
}
}
}
}
private var shouldUpdateTexture = false
private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")
}
然后是优化:(实际上不需要,但可能有助于思考代码)
class游戏场景:SKScene{
让bgTextures=[SKTexture(ImageName:“orangebackground”)、SKTexture(ImageName:“yellowbackground”)、SKTexture(ImageName:“greenbackground”)]
私人风险值得分=0{
迪塞特{
///如果在10秒内发生变化,则更新纹理
让bgIndex=分数/10
如果((bgIndex>oldValue/10)和&scoreclass GameScene: SKScene {
private var score = 0 {
didSet {
///if a change in the 10s happen, then update texture
if(score/10 > oldValue/10)
{
switch score{
case 10...19: backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
case 20...29: backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
case 30...Int.max: backgroundNode.texture = SKTexture(imageNamed: "greenbackground")
default: break
}
}
}
}
private var shouldUpdateTexture = false
private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")
}
class GameScene: SKScene {
let bgTextures = [SKTexture(imageNamed: "orangebackground"),SKTexture(imageNamed: "yellowbackground"),SKTexture(imageNamed: "greenbackground")]
private var score = 0 {
didSet {
///if a change in the 10s happen, then update texture
let bgIndex = score / 10
if((bgIndex > oldValue/10) && score < bgTextures.count * 10)
{
backgroundNode.texture = bgTextures[bgIndex - 1]
}
else
{
backgroundNode.texture = bgTextures[bgTextures.count - 1]
}
}
}
private var shouldUpdateTexture = false
private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")
}