XNA sound pan depend on X coord - xna

I need play a sound panning depend on X coord of explosion.
Vector2 PositionOfExplosion = ExplosionCoord;
myScreenWidth = 480; //Windows phone
float SoundPan = ??? //Mus be something like MathHelper.Clamp(???, -1, 1);
_explosion1.Play(myVolumen, myPitch, SoundPan); // Pan from -1.0 left to 1.0 right. 0 is center
Resuming,
If explosion is in
X=0 Pan= -1
...
X=120 Pan= -0.5
...
X=240 Pan= 0
...
x=360 Pan = 0.5
...
x=480 Pan= 1
Sorry my english.
Thanks.

pan = (PositionOfExplosion.X - 240.0f) / 240.0f
You can then clamp to -1..1.

Related

continuos smooth incremental rotation of a node (camera)

I'm trying to incrementally rotate the camera around x-axis by 5 degrees. it works fine except for animation at 355 jumps suddenly. it happens due to animation chaining. if my following method is called in SCNSceneRendererDelegate then it is not time based rotation. the SCNSceneRendererDelegate is triggered in each frame. and it means my scene animation action with duration is not ready yet. by lowering the animation duration, the animation is not smooth anymore. doing a timer based with same interval as the animation duration looks bad as well. is there anyway to get this animation smooth?
-(void) updateCameraRotation
{
SCNQuaternion oldRotScnQuat = _cameraNode.presentationNode.rotation;
GLKQuaternion glQuatOldRot = GLKQuaternionMakeWithAngleAndAxis(oldRotScnQuat.w, oldRotScnQuat.x, oldRotScnQuat.y, oldRotScnQuat.z);
float xan = GLKMathDegreesToRadians(5);
GLKQuaternion newx = GLKQuaternionIdentity;
GLKVector3 vec = GLKVector3Normalize(GLKVector3Make(1, 0, 0));
double result = sinf(xan/2);
newx = GLKQuaternionMakeWithAngleAndAxis(cosf(xan/2), vec.x *result, vec.y * result, vec.z * result);
newx = GLKQuaternionNormalize(newx);
glQuatOldRot = GLKQuaternionMultiply(glQuatOldRot, newx);
axis = GLKQuaternionAxis(glQuatOldRot);
angle = GLKQuaternionAngle(glQuatOldRot);
[_cameraNode runAction:[SCNAction rotateToAxisAngle:SCNVector4Make(axis.x, axis.y, axis.z, angle) duration:1]];
}
SLERP is used to make smooth rotations between two known attitudes. Try and avoid needless conversions between axis-angle and quaternions (leave them in quaternions if possible).
http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
You will also need to calculate the angle between the quaternion axes: https://math.stackexchange.com/questions/90081/quaternion-distance
I have used both these functions myself and they work well.
Rather than adding 5 degrees per frame, you can specify a scalar t in the range of [0, 1].
For instance, when rotating from quaternion P to Q, R = SLERP(P,Q,t) will give you the quaternion R from P to Q. If t = 0 then R = P, if t = 1 then R = Q.
Try to provide a CABasicAnimation with byValue set to your 5 degrees and set repititions to be infinite. Won't that work?

SpriteKit move rotated physicsBody with applyImpulse

I want to move a physicsBody with the applyImpulse method in a direction based on the physicsBody rotation.
Foe example, the physicsBody is a square in shape, I call a "move" which will apply an impulse to make it move up vertically. I then call a method to rotate the physicsBody 45 degrees right. If I call the "move" method again, the physicsBody will move diagonally right and up.
I suggest that you follow Sprite Kit’s coordinate and rotation conventions. Specifically, your sprite image should be facing right at zero degrees (the default value), and a positive value is a counter-clockwise rotation. That said, here's one way to apply an impulse in the direction a sprite is facing:
// Specify the force to apply to the SKPhysicsBody
CGFloat r = 5;
// Create a vector in the direction the sprite is facing
CGFloat dx = r * cos (sprite.zRotation);
CGFloat dy = r * sin (sprite.zRotation);
// Apply impulse to physics body
[sprite.physicsBody applyImpulse:CGVectorMake(dx,dy)];
UPDATED:
Fixed with the below thanks to #0x141E
-(void)characterJump {
CGFloat radianFactor = 0.0174532925;
CGFloat rotationInDegrees = _body.zRotation / radianFactor;
CGFloat newRotationDegrees = rotationInDegrees + 90;
CGFloat newRotationRadians = newRotationDegrees * radianFactor;
CGFloat r = 500;
CGFloat dx = r * cos(newRotationRadians);
CGFloat dy = r * sin(newRotationRadians);
[_body.physicsBody applyImpulse:CGVectorMake(dx, dy)];
}

Stop SKAction at collision with PhysicsBody

I have a SpriteNode which is affected by gravity only on the y-Axis and can be moved with the accelerometer on the x-Axis. I also have a border (SKPhysicsBody) on my Scene which keeps my node inside my scene. The problem is now that my node ignores the border when it performs its SKAction caused by the accelerometer.
My code for the x movement/ accelerometer and its action:
birdNode is my SpriteNode
float destX = 0.0;
float currentX = birdNode.position.x;
BOOL shouldMove = NO;
if (data.acceleration.x < -0.1) {
destX = currentX + (data.acceleration.x * playerXSpeed);
shouldMove = YES;
}
else if (data.acceleration.x > 0.1) {
destX = currentX + (data.acceleration.x * playerXSpeed);
shouldMove = YES;
}
if (shouldMove) {
if (birdNode.position.x + destX < self.frame.size.width || birdNode.position.x - destX > 0) {
SKAction *moveBird = [SKAction moveToX:destX duration:0.1];
[birdNode runAction:moveBird];
}
}
I assume that you have your collision bit masks properly set up to handle collisions. You should confirm this with a test to double check.
I believe your issue is with the speed of your object. If the object is moving too fast, and I do not see any velocity limits in your posted code, your object can move past the screen boundary in one update cycle.
For example, your current object's position is (400,100). Given enough velocity, your object's next update: position could be (600,100). This means that your object literally jumped past the boundary without causing a collision.
The solution is to either limit the velocity or to institute a position check before setting your object's new position. For example, if the new x position is > the screen width then set the x position to the max allowed screen width x.

iOS GestureRecognizers All Directions

I am fairly new to iOS development. I have just started about a month or two ago. I have an idea for an application, but it would require Gesture Recognizers. I have looked for the documentation for Gesture Recognizers but as far as I can tell, it can only detect 4 directions. Up, left, right, and down. Is there anyway to write some code that will let you detect any direction the user swipes. For example, if the user were to swipe towards the upper-right direction or bottom-right direction, is there a way to detect that?
EDIT: After thinking about this I have come up with a better way to explain what I need code for. If I was developing a game for iOS and the user is usually in a camera view (birds-eye view) and I wanted to allow them to move their view in a map so that they could perhaps view an enemy's base or their ally's base, how would I detect those diagonal swipes rather than just up, right, left, and down swipes?
I think you are a little confused.
UISwipeGestureRecognizer is a subclass of UIGestureRecognizer, and, as you say, it only detects swipes for those 4 directions.
But then there's UIPanGestureRecognizer which you can use to detect movement in any direction. It gives you a method called translationInView: which gives you just that, the change of the position of your finger in whichever direction.
I ran across your question, since it was something similar to what I wanted to do, but then ended up not using it. So I figured I'd leave the code here for posterity. Just use an UIPanGestureRecognizer and set a method similar to this one for your target/selector:
typedef enum {
NONE = 0,
LEFT = 1,
RIGHT = 2,
UP = 4,
DOWN = 8
} BLDirection;
-(void)detectDirection:(UIPanGestureRecognizer*)pan {
if (pan.state == UIGestureRecognizerStateEnded) {
CGPoint stopPan = [pan translationInView:self.view];
CGPoint velocity = [pan velocityInView:self.view];
int direction = NONE;
// first determine the directions
if (velocity.x < 0) {
direction |= LEFT;
} else if (velocity.x > 0) {
direction |= RIGHT;
}
if (velocity.y < 0) {
direction |= UP;
} else if (velocity.y > 0) {
direction |= DOWN;
}
// now we figure out the angle of the swipe
double x2 = stopPan.x;
double x1 = 0;
double y2 = abs(stopPan.y);
double y1 = 0;
// angle is in degrees
double angle = atan((y2 - y1 + 1) / (x2 - x1 + 1)) * 57.29577951308233; // 180/pi
// mask out the vertical directions if they aren't sufficiently strong
if ((angle < 0 && angle < -55) || (angle > 0 && angle > 55)) {
direction &= (UP | DOWN);
}
// mask out the horizontal directions if they aren't sufficiently strong
if ((angle < 0 && angle > -35) || (angle > 0 && angle < 35)) {
direction &= (LEFT | RIGHT);
}
NSLog(#"Direction is %s%s%s%s", ((direction & UP) == UP) ? "UP" : "",
((direction & DOWN) == DOWN) ? "DOWN" : "",
((direction & LEFT) == LEFT) ? "LEFT" : "",
((direction & RIGHT) == RIGHT) ? "RIGHT" : "");
// do something here now that you know the direction. The direction could be one of the following:
// UP
// DOWN
// LEFT
// RIGHT
// UP|LEFT
// UP|RIGHT
// DOWN|LEFT
// DOWN|RIGHT
}
}

Collision accuracy

Not quite sure how to word this but I've been using
if (CGRectIntersectsRect(ball.frame, bottom.frame)) {
[self finish ];
}
for my collision detection and it run the code perfectly but the ball sometimes collides with the bottom and runs the code but you can clearly see there is a gap in between the objects. i have created the images my self and they have no background around them. i was wondering if theres any other way of coding it or making it so the it doesn't run the code until the intersect x amount of pixels into one another.
You can implement ball-line collision in many ways. Your solution is in fact a rectangle - rectangle collision detection. Here is how I did it in one of my small gaming projects. It gave me best results and it's simple.
Let's say that a ball has a ballRadius, and location (xBall, yBall). The line is defined with two points (xStart, yStart) and (xEnd, yEnd).
Implementation of a simple collision detection:
float ballRadius = ...;
float x1 = xStart - xBall;
float y1 = yStart - yBall;
float x2 = xEnd - xBall;
float y2 = yEnd - yBall;
float dx = x2 - x1;
float dy = y2 - y1;
float dr = sqrtf(powf(dx, 2) + powf(dy, 2));
float D = x1*y2 - x2*y1;
float delta = powf(ballRadius*0.9,2)*powf(dr,2) - powf(D,2);
if (delta >= 0)
{
// Collision detected
}
If delta is greater than zero there are two intersections between ball (circle) and line. If delta is equal to zero there is one intersection – perfect collision.

Resources