I'm having performance problems with using UIDynamicAnimations and creating and deleting items

63 views Asked by At

I made an app based on UIDynamicBehavior. It's a game where you have a circle in the middle of the screen and there are balls launching out of the middle to the outer circle (when they hit it they disappear) where the interval between this "launches" get shorter and shorter (this does not cause the problem, you will see later). Well the problem is after about a 100 circles everything gets very laggy and each "launch" just freezes the whole game for a moment until the problem becomes so big the whole thing just freezes.

The problem seems to be that I'm somehow not deleting the balls correctly. Even if the intervals don't change and the number of balls that are on the screen at the same time is always the same (3-4) the problem still occurs.

This is also not a memory problem since the memory usage stays at around 20MB but the processor goes from 0% at the start and it just keeps rising and rising until its at 100% and the whole thing just stops.

So when a ball I created this is all the code there:

func lunchMyBall(timer: NSTimer!){
    let myBall = createBall()
    var angle = Int(arc4random_uniform(70))
    angle = angle+1-35
    if angle < 0 {
        angle = -angle
        angle = angle-70
    } else {
        angle = angle+70
    }
    if arc4random()%2 == 1 {
        angle = -angle
    }
    print("angle: \(angle)")
    if lastBallAngle == nil {
        myBall.angle = Double(angle)
    }else{
        switch lastBallColorIndex! {
        case 1: switch myBall.colorIndex {
            case 1: myBall.angle = lastBallAngle! + Double(angle)
            case 2: myBall.angle = lastBallAngle! + Double(angle)-90
            case 3: myBall.angle = lastBallAngle! + Double(angle)+180
            case 4: myBall.angle = lastBallAngle! + Double(angle)+90
        default: break
            }
        case 2: switch myBall.colorIndex {
            case 1: myBall.angle = lastBallAngle! + Double(angle)+90
            case 2: myBall.angle = lastBallAngle! + Double(angle)
            case 3: myBall.angle = lastBallAngle! + Double(angle)-90
            case 4: myBall.angle = lastBallAngle! + Double(angle)+180
            default: break
            }
        case 3: switch myBall.colorIndex {
            case 1: myBall.angle = lastBallAngle! + Double(angle)+180
            case 2: myBall.angle = lastBallAngle! + Double(angle)+90
            case 3: myBall.angle = lastBallAngle! + Double(angle)
            case 4: myBall.angle = lastBallAngle! + Double(angle)-90
            default: break
            }
        case 4: switch myBall.colorIndex {
            case 1: myBall.angle = lastBallAngle! + Double(angle)-90
            case 2: myBall.angle = lastBallAngle! + Double(angle)+180
            case 3: myBall.angle = lastBallAngle! + Double(angle)+90
            case 4: myBall.angle = lastBallAngle! + Double(angle)
            default: break
            }
        default: break
        }
    }
    if myBall.angle! > 360 {
        myBall.angle = myBall.angle! - 360
    }else if myBall.angle! < 0 {
        myBall.angle = myBall.angle! + 360
    }
    let tempAngle = CGFloat((myBall.angle!/360)*2*M_PI)
    lastBallAngle = myBall.angle
    lastBallColorIndex = myBall.colorIndex
    dataSource?.lunchMyBall(myBall, angle: tempAngle)
    let timer = NSTimer.scheduledTimerWithTimeInterval(Double(difficulty), target: self, selector: "lunchMyBall:", userInfo: nil, repeats: false)
    timer.tolerance = 0.01
}

func createBall() -> UIItemView {
    var frame = CGRect(origin: CGPointZero, size: CGSize(width: 10, height: 10))
    frame.origin = (CGPoint(x: (dataSource?.getCircleCenter().x)!-5, y: (dataSource?.getCircleCenter().y)!-5))

    let ballView = UIItemView(frame: frame, color: UIColor.random())

    return ballView
}

And this is how I add it to the behavior:

func lunchBall(ball: UIView, angle: CGFloat) {
    let myLunchBehavior: UIPushBehavior? = lunchBehavior
    let myBall = ball as! UIItemView
    myBall.angle = 360-((Double(angle)/(2*M_PI))*360)
    myLunchBehavior!.setAngle(angle, magnitude: 0.01)
    myLunchBehavior!.addItem(ball)
    myBall.pushBehavior = myLunchBehavior
    dynamicAnimator?.referenceView?.addSubview(ball)
    addChildBehavior(myBall.pushBehavior!)
    collisionBehavior.addItem(ball)
}

And this is how I delete it:

func collisionBehavior(behavior: UICollisionBehavior, beganContactForItem item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?, atPoint p: CGPoint) {
    print("did")
    if let myItem = item as? UIItemView {
        if (isPointInAngle(myItem.angle!, colorIndex: myItem.colorIndex) == true) {
            dataSource?.scoreChanged(true)
            print("true")
        }else{
            dataSource?.scoreChanged(false)
            print("false")
        }

        collisionBehavior.removeItem(myItem)
        removeChildBehavior(myItem.pushBehavior!)
        myItem.pushBehavior?.removeItem(myItem)
        myItem.removeFromSuperview()
    }
}

This is set up to fire when a collision with the other circle occurs.

I'm sorry for the big amount of code but I really can't find out where the problem is happening so it's really hard for me to pin point it.

I have been working on this problem for more than 2 days now and still can't figure it out. I tried everything, reusing behaviors (instead of deleting it I made an array so the next ball just takes it from there and sets a new angle), multi-threading (I'm not really experienced with that), I also looked in to Time Profiler but nothing really made sense to me there since I'm a beginner. I would really really appreciate it someone that knows what he's doing would be able to just throw an eye over it to check and spot any problems since I think the problem should probably be pretty obvious for an experienced programmer. Here is the link to my project if that helps. So you can see I have two things that I suppose are important. I have a sub class of a UIDynamicBehavior where I have all my behaviors set up and a basic swift class "BallLauncher" that is supposed to be what causes the balls to launch so there also could be problems there.

0

There are 0 answers