2014-06-11 12 views
9

Pracuję nad grą sprite-kit, w której węzły spawnują się poniżej najniższego punktu na ekranie, a grawitacja jest ustawiona tak, aby unosiły się na górze ekranu. Wszystko działa idealnie, ale szybko zaczyna spowalniać FPS, a w końcu opóźnienia i zakłócenia stają się bardzo powolne. Myślałem, że sposobem rozwiązania tego byłoby usunąć węzły z rodziców po ich dalszy obok punktu, to był kod użyłem w aktualizacji:Jak prawidłowo usunąć węzeł po przekroczeniu granicy ekranu?

-(void)update:(CFTimeInterval)currentTime { 

    if (_bubble1.position.y > CGRectGetMaxX(self.frame)+40) { 
     [self removeFromParent]; 
    } 

} 

A w przypadku jest to potrzebne, jak ja zrodził powiedział bańka wybraną metodę initWithSize:

-(void)didMoveToView:(SKView *)view { 

    [self performSelector:@selector(spawnBubbles) withObject:nil afterDelay:1.0]; 
    [self performSelector:@selector(spawnBubbles1) withObject:nil afterDelay:1.5]; 

} 

-(void)spawnBubbles { 
    randomPosition = arc4random() %260*DoubleIfIpad; 
    randomPosition = randomPosition + 20*DoubleIfIpad; 

    randomNumber = arc4random() %7; 
    randomNumber = randomNumber + 1; 

    myColorArray = [[NSArray alloc] initWithObjects:colorCombo1, colorCombo2, colorCombo3, colorCombo4, colorCombo5, colorCombo6, colorCombo7, colorCombo8, nil]; 
    myRandomColor = [myColorArray objectAtIndex:randomNumber]; 

    _bubble1 = [SKShapeNode node]; 
    [_bubble1 setPath:CGPathCreateWithEllipseInRect(CGRectMake(-25*DoubleIfIpad, -25*DoubleIfIpad, 50*DoubleIfIpad, 50*DoubleIfIpad), nil)]; 
    _bubble1.strokeColor = _bubble1.fillColor = myRandomColor; 
    _bubble1.position = CGPointMake(randomPosition, CGRectGetMinY(self.frame)-60); 
    _bubble1.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:20]; 
    _bubble1.physicsBody.categoryBitMask = CollisionBubble; 

    [self addChild:_bubble1]; 

    [self runAction:[SKAction sequence:@[ 
             [SKAction waitForDuration:1.0], 
             [SKAction performSelector:@selector(spawnBubbles) onTarget:self], 
             ]]]; 

} 

Jak mogę to zrobić tak, że węzły są odpowiednio utylizowane, gdy opuszczają ekran? I jak mogę utrzymać FPS na stałym poziomie 60 FPS?

Z góry dziękuję !!

+1

„FPS” jest luźno powiązana z liczbą węzłów. inne czynniki przyczynią się do tego bardziej. –

+0

Naprawdę ?! jak to, co @BradAllred – user3576196

+0

Masz tylko jedną bańkę ivar, musisz użyć tablicy, aby uzyskać dostęp do wszystkich później. Za pomocą kodu aktualizacji można usunąć tylko dymek, który został utworzony jako ostatni. Łatwiej jest uruchomić akcję, która często sprawdza pozycję i wywołuje metodę removeFromParent, gdy jest to konieczne. – LearnCocos2D

Odpowiedz

12

Zalecam użycie wbudowanego wykrywania kontaktu w spritekit. Utwórz skspritenode naśladujący dach, na którym znajduje się zestaw ciał fizycznych, który wykrywa kontakt z bąbelkami. Utwórz zdarzenie w przypadku kontaktu między węzłem dachu a węzłem bąbelkowym, który po prostu usunie bąbelki. Zapewni to usunięcie bąbelków i utrzyma stały FPS.

Przykład zdarzenia wezwał kontakt:

- (void)bubble:(SKSpritenode*)bubble didCollideWithRoof:(SKSpriteNode*)roof{ 
[bubble removeFromParent];} 

przykład wykrywanie Kontakt:

- (void)didBeginContact:(SKPhysicsContact *)contact 
{ 
SKPhysicsBody *firstBody, *secondBody; 
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) 
{ 
    firstBody = contact.bodyA; 
    secondBody = contact.bodyB; 
} 
else 
{ 
    firstBody = contact.bodyB; 
    secondBody = contact.bodyA; 
} 

if (firstBody.categoryBitMask==bubbleCategory && secondBody.categoryBitMask == roofCategory) 
{ 
    [self bubble:(SKSpriteNode*)firstBody.node didCollideWithRoof:(SKSpriteNode*)secondBody.node]; 
}} 

Bubble potrzebuje:

_bubble.physicsBody.contactTestBitMask = roofCategory; 

dachu:

SKSpriteNode *roof = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(self.scene.size.width, 1)]; 
roof.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(self.scene.size.width, 1)]; 

    roof.position = CGPointMake(self.scene.size.width/2,self.scene.size.height) 
    roof.physicsBody.dynamic = NO; 
    roof.physicsBody.categoryBitMask = floorCategory; 
    roof.physicsBody.contactTestBitMask = bubbleCategory; 
    [self addChild:roof]; 
4

1/init sceny za physicsBody własność z następującego kodu:

physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) // or CGRectInset(frame, -10, -10) if you need insets 

2/stworzyć własną kategorię, maski do sceny i węzły sprite:

let boundaryCategoryMask: UInt32 = 0x1 << 1 
let someNodeCategoryMask: UInt32 = 0x1 << 2 

3/Set właściwa categoryBitMask, collisionBitMask i contactTestBitMask dla twojej sceny i węzłów sprite physicsBody właściwości:

// Scene 
physicsBody!.categoryBitMask = boundaryCategoryMask 

// Sprite node 
/* ... */ 
someNode.physicsBody!.categoryBitMask = someNodeCategoryMask 
someNode.physicsBody!.contactTestBitMask = boundaryCategoryMask 

Jako przykład następująca realizacja Swift SKScene pokazuje, w jaki sposób usunąć wszystkie węzły sprite, które wykraczają poza ramy sceny za:

class GameScene: SKScene, SKPhysicsContactDelegate { 

    let boundaryCategoryMask: UInt32 = 0x1 << 1 
    let squareCategoryMask: UInt32 = 0x1 << 2 


    override func didMoveToView(view: SKView) { 
     // Scene 
     backgroundColor = SKColor.whiteColor() 
     physicsWorld.contactDelegate = self 
     physicsBody = SKPhysicsBody(edgeLoopFromRect: frame) 
     physicsBody!.categoryBitMask = boundaryCategoryMask 

     // Square 
     let square = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 80, height: 80)) 
     square.zPosition = 0.1 
     square.position = CGPoint(x: size.width/2.0 - square.size.width/2, y: size.height - square.size.height) 
     square.physicsBody = SKPhysicsBody(rectangleOfSize: square.frame.size) 
     square.physicsBody!.dynamic = true 
     square.physicsBody!.affectedByGravity = true 
     square.physicsBody!.categoryBitMask = squareCategoryMask 
     // square.physicsBody!.collisionBitMask = 0 // don't set collisions (you don't want any collision) 
     square.physicsBody!.contactTestBitMask = boundaryCategoryMask // this will trigger -didBeginContact: and -didEndContact: 
     addChild(square) 
    } 

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { 
     // Check if the array containing the scene’s children is empty 
     println("children: \(children)") 
    } 

    func didBeginContact(contact: SKPhysicsContact) { 
     if contact.bodyA.categoryBitMask == squareCategoryMask { 
      contact.bodyA.node?.removeFromParent() 
      println("square removed") 
     } 

     if contact.bodyB.categoryBitMask == squareCategoryMask { 
      contact.bodyB.node?.removeFromParent() 
      println("square removed") 
     } 
    } 

    func didEndContact(contact: SKPhysicsContact) { 
     /* ... */ 
    } 

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

} 
Powiązane problemy