大家好!首先,我知道这个问题与Draw images evenly spaced along a path in iOS非常相似。但是,这是在Objective-C(我无法阅读)和它在使用CGImageRefs的普通ViewController中。我需要在swift中使用SKSpriteNodes(不是CGImageRefs)。这是我的问题:
我尝试制作一个让用户绘制简单形状(如圆圈)的程序,并沿着用户绘制的路径以固定间隔放置SKSpriteNodes。我已经让它以缓慢的速度正常工作,但是如果用户绘制太快,那么节点就会放得太远。这是我慢慢画出来的一个例子:
用户绘制的路径,节点彼此相距约60个像素。蓝色是起始节点,紫色是结束节点。
目标是每个节点都有一个物理实体,使实体不会越过用户绘制的线(这些实体不能在均匀间隔的节点之间挤压)。但是,如果用户吸引得过快,我将无法修复防御方面的差距。例如:
注意第7和第8节点之间明显较大的间隙。发生这种情况是因为我画得太快了。许多人的问题略微相似但对我的任务没有帮助(例如,沿着路径均匀地放置特定数量的节点,而不是放置尽可能多的节点以使它们沿路径分开60个像素)。
总之,这是我的主要问题:如何在任何形状的用户绘制路径上完美地间隔节点?预先感谢您的帮助!这是我的GameScene.swift文件:
import SpriteKit
导入GameplayKit
类GameScene:SKScene {
let minDist: CGFloat = 60 //The minimum distance between one point and the next
var points: [CGPoint] = []
var circleNodes: [SKShapeNode] = []
override func didMove(to view: SKView) {
}
func getDistance (fromPoint: CGPoint, toPoint: CGPoint) -> CGFloat {
let deltaX = fromPoint.x - toPoint.x
let deltaY = fromPoint.y - toPoint.y
let deltaXSquared = deltaX*deltaX
let deltaYSquared = deltaY*deltaY
return sqrt(deltaXSquared + deltaYSquared) //Return the distance
}
func touchDown(atPoint pos : CGPoint) {
self.removeAllChildren()
//The first time the user touches, we need to place a point and mark that as the firstCircleNode
print(pos)
points.append(pos)
//allPoints.append(pos)
let firstCircleNode = SKShapeNode(circleOfRadius: 5.0)
firstCircleNode.fillColor = UIColor.blue
firstCircleNode.strokeColor = UIColor.blue
firstCircleNode.position = pos
circleNodes.append(firstCircleNode)
self.addChild(firstCircleNode)
}
func touchMoved(toPoint pos : CGPoint) {
let lastIndex = points.count - 1 //The index of the last recorded point
let distance = getDistance(fromPoint: points[lastIndex], toPoint: pos)
//vector_distance(vector_double2(Double(points[lastIndex].x), Double(points[lastIndex].y)), vector_double2(Double(pos.x), Double(pos.y))) //The distance between the user's finger and the last placed circleNode
if distance >= minDist {
points.append(pos)
//Add a box to that point
let newCircleNode = SKShapeNode(circleOfRadius: 5.0)
newCircleNode.fillColor = UIColor.red
newCircleNode.strokeColor = UIColor.red
newCircleNode.position = pos
circleNodes.append(newCircleNode)
self.addChild(newCircleNode)
}
}
func touchUp(atPoint pos : CGPoint) {
//When the user has finished drawing a circle:
circleNodes[circleNodes.count-1].fillColor = UIColor.purple //Make the last node purple
circleNodes[circleNodes.count-1].strokeColor = UIColor.purple
//Calculate the distance between the first placed node and the last placed node:
let distance = getDistance(fromPoint: points[0], toPoint: points[points.count-1])
//vector_distance(vector_double2(Double(points[0].x), Double(points[0].y)), vector_double2(Double(points[points.count - 1].x), Double(points[points.count - 1].y)))
if distance <= minDist { //If the distance is closer than the minimum distance
print("Successful circle")
} else { //If the distance is too far
print("Failed circle")
}
points = []
circleNodes = []
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
答案 0 :(得分:1)
您可以尝试调整矢量大小:
func touchMoved(toPoint pos : CGPoint) {
let lastIndex = points.count - 1 //The index of the last recorded point
let distance = getDistance(fromPoint: points[lastIndex], toPoint: pos)
if distance >= minDist {
// find a new "pos" which is EXACTLY minDist distant
let vx = pos.x - points[lastIndex].x
let vy = pos.y - points[lastIndex].y
vx /= distance
vy /= distance
vx *= minDist
vy *= minDist
let newpos = CGPoint(x: vx, y:vy)
points.append(newpos)
//Add a box to that point
let newCircleNode = SKShapeNode(circleOfRadius: 5.0)
newCircleNode.fillColor = UIColor.red
newCircleNode.strokeColor = UIColor.red
newCircleNode.position = newpos // NOTE
circleNodes.append(newCircleNode)
self.addChild(newCircleNode)
}
}
它可能不会很完美,但可能看起来更好。
答案 1 :(得分:0)
我已经弄明白了!我受到了Christian Cerri建议的启发,所以我用下面的代码来制作我想要的东西:
// I added the typedef for more easily understood declarations of `p` and `end`.
typedef char array_alias_t[sizeOfAnElement];
// p's type is the same as in the previous code (char (*)[sizeOfAnElement]).
array_alias_t *p = A;
// p + x == &p[x], and &p[nElementsA] is one element past the end of A,
// which is allowed by ISO C, provided you don't dereference the pointer
// (i.e. *end is not allowed).
for (array_alias_t *end = p + nElementsA; p != end; p++) {
if (isPositive(*p)) {
*bStart = *p;
bStart++;
} else {
*bEnd = *p;
bEnd--;
}
}
这导致以下结果:
无论用户移动手指的速度有多快,它都会沿着路径均匀地放置节点。非常感谢您的帮助,我希望将来可以帮助更多的人!