ios - Arrastre un SKSpriteNode(siga los movimientos de sus dedos) con SKPhysics(colisión)
objective-c sprite-kit (1)
Lo que hago es crear un SKNode, llamémoslo ''a'', con un cuerpo de física muy pequeño conectado. Este nuevo nodo está conectado a través de SKPhysicsJointSpring al nodo que quiero mover, llamémoslo ''b''. El nuevo nodo a rastrea el movimiento de mis dedos, y el muelle se asegura de que el nodo objetivo b lo siga. Debido a que el nodo b se posiciona usando la física, la detección de colisiones funciona como se esperaba.
Desea arrastrar un SKSpriteNode (siga los movimientos de sus dedos) con SKPhysics (colisión habilitada)
2 soluciones fallidas:
1)
a) Solución: cambie la posición del SKSpriteNode
b) Problema: el SKSpriteNode pasará "mágicamente" a través de una pared inesperadamente cuando el usuario arrastra rápidamente el SpriteNode a través de la pared (la física parece no funcionar)
c) código:
@property (nonatomic) CGPoint translationBy;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self selectNodeForTouch:positionInScene];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
CGPoint translation = CGPointMake(positionInScene.x - previousPosition.x, positionInScene.y - previousPosition.y);
[self panForTranslation:translation];
}
- (void)panForTranslation:(CGPoint)translation {
CGPoint position = [_selectedNode position];
if([[_selectedNode name] isEqualToString:PLAYER_NAME]) {
[_selectedNode setPosition:CGPointMake(position.x + translation.x, position.y + translation.y)];
}
}
2) Después de buscar por aquí encontré este consejo de @ LearnCocos2D "Cuando usas la física, mantente firme al mover el cuerpo físico a través de la fuerza, el impulso o cambiando la velocidad del cuerpo directamente". Así que lo intenté:
a) Solución: aplique un impulso en el nodo de sprite.
b) Problema: el nodo de sprite seguirá moviéndose incluso si no arrastré el nodo de sprite. (Comportarse como un barco flotante. Esperar que actúe como un automóvil una vez que se detiene el arrastre, el nodo del sprite se detendrá, una vez que comience la resistencia, seguirá el dedo).
c) Código:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self selectNodeForTouch:positionInScene];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
CGPoint translation = CGPointMake(positionInScene.x - previousPosition.x, positionInScene.y - previousPosition.y);
CGVector forceVector = CGVectorMake(translation.x, translation.y);
[self.player.physicsBody applyImpulse:forceVector];
//[self.player.physicsBody setVelocity:CGVectorMake(0, 0)];
}
- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Actualizado:
Del comentario: "i) Podrías determinar la distancia del nodo a la ubicación del dedo, luego establecer la velocidad en cada actualización: para que esté exactamente en la posición del dedo en el siguiente cuadro. Ii) Si la posición del dedo y del nodo son De forma idéntica, esto cancelará cualquier movimiento, de lo contrario, el nodo se adherirá a su dedo mientras realiza todas las colisiones físicas y continuará empujando objetos entre sí y el dedo en los casos en que esté obstruido ".
a) Pregunta: ¿Cómo desactivar la película?
b) Problema: el nodo de sprite se moverá muy lejos con un pequeño golpe (accidental).
c) código:
@property (nonatomic) CGPoint translationBy;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
// 1) You could determine the distance of the node to the finger location,
CGPoint xyTranslation = CGPointMake(positionInScene.x - previousPosition.x, positionInScene.y - previousPosition.y);
if (fabsf(positionInScene.x - previousPosition.x) < kPlayerMovementThreshold) {
xyTranslation.x = 0;
}
if (fabsf(positionInScene.y - previousPosition.y) < kPlayerMovementThreshold) {
xyTranslation.y = 0;
}
self.translationBy = xyTranslation;
}
static const CGFloat kPlayerMovementSpeed = 55.0f;
static const CGFloat kPlayerMovementThreshold = 1.0f;
-(void)update:(CFTimeInterval)currentTime{
// ii) then set the velocity every update: so that it will exactly be on the finger''s position the next frame.
CGFloat dx = self.translationBy.x*kPlayerMovementSpeed;
CGFloat dy = self.translationBy.y*kPlayerMovementSpeed;
CGVector velocityVector = CGVectorMake(dx,dy);
[self.player.physicsBody setVelocity:velocityVector];
}