问题
I am currently writing a joystick app and I want to display the contours of my lidar sensor; I am using sprite kit but it's lagging; I am assuming that it is taking up too much memory
My lidar sensor returns to me 360 data points where each degree represents the distances of where it hit an object (wall)
I am initializing all of my sprite kit nodes in didMoveToView, is there a better way to achieve this? perhaps in init?
I am creating 720 sprite kit nodes because 360 are for the lines and 360 are for the data points (distances)
It seems as if I am creating too many sprite kit nodes (720+)
Also, I am planning to provide video streaming through my app; is Sprite Kit the best option to do this?
import Foundation
import UIKit
import SpriteKit
class GameScene: SKScene {
var visual = SKSpriteNode()
let button = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 100, height: 50), cornerRadius: 10)
var distances: [Int] = [2601, 2600, 33, 2608, 2601, 2594, 2625, 2633, 2637, 2651, 2656, 2666, 2683, 2690, 2705, 2712, 2712, 2739, 2752, 53, 1103, 1060, 1019, 980, 944, 911, 33, 851, 826, 801, 777, 757, 737, 718, 701, 683, 667, 654, 53, 486, 470, 457, 448, 440, 432, 424, 416, 409, 403, 396, 389, 383, 378, 372, 367, 362, 357, 353, 348, 344, 340, 336, 333, 329, 326, 323, 319, 317, 314, 311, 309, 307, 305, 303, 301, 299, 298, 297, 295, 294, 293, 292, 291, 290, 290, 290, 290, 291, 293, 295, 303, 386, 383, 53, 350, 53, 53, 53, 53, 53, 3, 364, 362, 360, 356, 358, 355, 353, 351, 350, 349, 347, 345, 53, 53, 53, 308, 3, 309, 309, 312, 313, 315, 316, 319, 321, 53, 329, 332, 335, 332, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 53, 670, 33, 706, 728, 750, 772, 799, 825, 856, 887, 925, 755, 749, 744, 739, 734, 730, 727, 722, 719, 716, 714, 634, 709, 706, 704, 703, 701, 699, 700, 695, 697, 697, 338, 696, 697, 696, 698, 698, 700, 702, 703, 705, 707, 710, 712, 714, 718, 53, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 53, 53, 3412, 3397, 3384, 53, 3538, 3603, 53, 2426, 2412, 2363, 2330, 2288, 2262, 2214, 2190, 2162, 2130, 53, 53, 53, 2807, 2631, 2408, 2638, 2607, 2601, 2562, 2534, 2515, 2496, 2478, 2462, 2445, 53, 53, 53, 1751, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 3, 53, 53, 53, 53, 53, 2643, 2643, 53, 2660, 53, 2528, 2523, 2221, 1955, 1684, 1677, 1684, 1694, 1705, 1202, 1204, 1211, 1217, 1225, 1233, 1239, 1249, 1259, 1270, 1280, 1289, 1280, 1011, 991, 977, 968, 966, 964, 968, 975, 984, 1003, 2, 53, 1297, 53, 53, 33, 1321, 1299, 1274, 1254, 1233, 1232, 1264, 1293, 3802, 53, 53, 53, 53, 53, 53, 53, 3, 53, 2878, 2870, 2848, 2821, 2803, 2788, 2769, 2753, 2740, 2708, 2711, 2701, 2682, 2656, 2664, 2644, 2644, 2631, 2626, 2616, 2610, 2604, 2605, 2605, 2600, 2598, 2603]
var scalex: [Double] = []
var scaley: [Double] = []
var disx: [Double] = []
var disy: [Double] = []
var somenodes = [SKSpriteNode()]
var newnodes = [SKShapeNode()]
override init(size: CGSize) {
print("this is in init!")
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let rotateAnalogStick = AnalogJoystick(diameter: 100)
override func didMoveToView(view: SKView) {
/* Setup your scene here */
visual.color = UIColor.clearColor()
visual.size = CGSize(width: 350, height: 350)
visual.position = CGPointMake(frame.midX, frame.midY + 150)
addChild(visual)
for index in 0...356 {
var radians = Double(index) * M_PI / 180.0
var x = Double(distances[index]) * cos(Double(radians))
var y = Double(distances[index]) * sin(Double(radians))
disx.append(x)
disy.append(y)
}
var path = CGPathCreateMutable()
var xmin: Double = Double(disx.minElement()!)
var xmax: Double = Double(disx.maxElement()!)
var ymin: Double = Double(disy.minElement()!)
var ymax: Double = Double(disy.maxElement()!)
var scale = max(xmax - xmin, ymax - ymin)
for index in 0...356 {
var radians = Double(index) * M_PI / 180.0
var x = (Double(distances[index]) * cos(Double(radians)) / scale) * 350
var y = (Double(distances[index]) * sin(Double(radians)) / scale) * 350
print("(\(x),\(y))")
var mynode = SKSpriteNode()
mynode.color = UIColor.redColor()
mynode.size = CGSize(width: 2, height: 2)
let circlenode = SKShapeNode()
let circlePath = UIBezierPath(arcCenter: CGPoint(x: 0,y: 0), radius: CGFloat(5), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
circlenode.path = circlePath.CGPath
//change the fill color
circlenode.fillColor = UIColor.blueColor()
//you can change the stroke color
circlenode.strokeColor = UIColor.redColor()
//you can change the line width
circlenode.lineWidth = 0.5
circlenode.zPosition = 1
circlenode.position = CGPointMake(CGFloat(x), CGFloat(y))
newnodes.append(circlenode)
CGPathMoveToPoint(path, nil, 0, 0) // from
CGPathAddLineToPoint(path, nil, CGFloat(x), CGFloat(y)) // to
let shape = SKShapeNode()
shape.path = path
shape.strokeColor = UIColor.purpleColor()
shape.lineWidth = 1
visual.addChild(shape)
visual.addChild(newnodes[index])
}
let newscale = SKAction.scaleTo(0.1, duration: 0.5)
let fadein = SKAction.fadeInWithDuration(0.5)
let fadeout = SKAction.fadeOutWithDuration(0.5)
let outsequence = SKAction.sequence([fadeout])
let insequence = SKAction.sequence([fadein])
for index in 0...visual.children.count {
// visual.children[index].runAction(insequence)
// visual.children[index].runAction(repeatout)
}
button.fillColor = UIColor.blueColor()
button.position = CGPointMake(frame.midX - 50, frame.midY - 110)
addChild(button)
var mylabel = SKLabelNode()
mylabel.color = UIColor.blackColor()
mylabel.fontSize = 12
mylabel.fontName = "AvenirNext-Bold"
mylabel.text = "Contour Display"
mylabel.position = CGPointMake(50, 20)
mylabel.zPosition = 1
button.addChild(mylabel)
backgroundColor = UIColor.whiteColor()
physicsBody = SKPhysicsBody(edgeLoopFromRect: frame)
rotateAnalogStick.position = CGPointMake(frame.midX + 5, rotateAnalogStick.radius + 60)
rotateAnalogStick.stick.color = UIColor.cyanColor()
rotateAnalogStick.substrate.color = UIColor.blackColor()
addChild(rotateAnalogStick)
rotateAnalogStick.trackingHandler = { data in
// cartesian to polar
var r = sqrt(pow(Double(data.velocity.x), Double(2)) + pow(Double(data.velocity.y), Double(2)))
var power = (r - 0)/(50 - 0) * (1-0) + 0
var theta = atan2(Double(data.velocity.y), Double(data.velocity.x)) // atan(Double(data.velocity.y/data.velocity.x)) //
var degrees = theta * (180.0 / M_PI)
var packet = ""
var offset = 0.0
var rdirection = 0.0
var ldirection = 0.0
var rpower = 0.0
var lpower = 0.0
if (degrees >= 65 && degrees <= 115) { // move forward
rpower = power
lpower = power
rdirection = 1
ldirection = 1
} else if (degrees <= 0 && degrees >= -65) || (degrees >= 0 && degrees <= 65) { // move right
offset = 90 - degrees
rdirection = min(degrees, offset)
ldirection = max(degrees, offset)
rpower = (rdirection - 0)/(50 - 0) * (power-0) + 0
lpower = abs(1-rpower)
rdirection = -1
ldirection = 1
} else if (degrees <= -115 && degrees >= -180) || (degrees > 115 && degrees < 180 ) { // move left
offset = 90 - degrees
rdirection = min(degrees, offset)
ldirection = max(degrees, offset)
rpower = abs(1-rpower)
lpower = (rdirection - 0)/(50 - 0) * (power-0) + 0
rdirection = 1
ldirection = -1
} else if (degrees <= -65 && degrees >= -115) { // move down
rpower = power
lpower = power
rdirection = -1
ldirection = -1
}
packet = "\(rdirection) \(ldirection) \(rpower) \(lpower)"
}
view.multipleTouchEnabled = true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch: AnyObject in touches {
// Get the location of the touch in this scene
let location = touch.locationInNode(self)
// Check if the location of the touch is within the button's bounds
if button.containsPoint(location) {
print("button tapped!")
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
回答1:
I'd like to think that SpriteKit can bang out 720 sprites no problem. As cited, your main issue is SKShapeNode
usage.
What you should do is create your "dots" as textures. If you want color/outlines, put them in the texture. Additionally, create your lines out of colored rects (which can be SKSpriteNode
s). If you have multiple circle colors, put them in a texture atlas.
This will give you the better chance of improved throughput with SpriteKit.
You are doing this work in didMoveToView
. How often does it need to be refreshed? If the data is set and the one difference is transforming it (eg. rotate, scale, translate), another approach would be to pre-render the whole thing using Quartz/Core Graphics and then transforming the rendering.
来源:https://stackoverflow.com/questions/40078232/how-to-draw-720-data-points-using-swift