How to zoom an slide the the screen in Unity? - unity3d

In my 2D Unity Project i had to use a zooming script in my main camera. Zooming works however, the camera just focuses on the middle of the scene. But I want to see the other parts of the scene which remain out of the field of view of camera. So, what should I add to my script in order to move over the scene when it's zoomed?
Here is my script for zooming. I threw it into the main camera.
This picture is the actual scene before zooming:
And this one is after zooming. Please pay attention that it directly focuses on the geometrical centre of the scene and doesn't allow me to move to another point on the scene(right, left, up, down).

I don't know if you're looking to drag whilst zooming or use the mouse position be the center point of the zoom.
If it's the latter, you can do something like this;
float zoomSpeed = 5f;
void Update()
{
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit point; Physics.Raycast(ray, out point, 25); Vector3 Scrolldirection = ray.GetPoint(5);
float step = zoomSpeed * Time.deltaTime;
mycamera.transform.position = Vector3.MoveTowards(transform.position, Scrolldirection, Input.GetAxis("Mouse ScrollWheel") * step);
}
}

Related

How to know end coordinates of animation in Unity?

I want to know coordinates of root bone in the end of animation in Unity. I tried to put unit with Animator controller programmaticaly to the scene, play animation and execute Update() several times. But coordinates are slightly different from the real.
Is there method to know accurate coordinates in the end of animation?
Upd. This code should work as it should, but it doesnt work accurately:
animator.transform.position = new Vector3(0, 0, 0);
animator.transform.rotation = Quaternion.Euler(0, 0, 0);
animator.Play(_hashName, 0, 0);
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
duration = stateInfo.length;
float t = 0;
float delta = 0.01f;
while (t < duration)
{
animator.Update(delta);
t += delta;
}
Vector3 endCoords = animator.transform.position;
Finally I found the brilliant answer on Unity3d forum.
animator.SetTarget(AvatarTarget.Root, 1.0f);
animator.Update(0);
Vector3 position = animator.targetPosition;
It works perfectly.

Moving sprite "smoothly"

I'm trying to move a sprite in a set direction on-screen, using the physicsBody.velocity property. However, the motion is quite "jumpy" (makes the game look like it's lagging). I assume this has something to do with the different time intervals between each call to the update-method. How could I achieve a more "smooth" motion?
Right now this is the code I have in my update-loop to make the sprite move forward:
if (_movingForward) {
CGFloat forwardVel = _ball.physicsBody.velocity.dx;
forwardVel += 20.0;
if (forwardVel > bMaxForwardVelocity) {
forwardVel = bMaxForwardVelocity;
}
_ball.physicsBody.velocity = CGVectorMake(forwardVel, _ball.physicsBody.velocity.dy);
}
As you can see, I'm trying to make the speed pick up, so it doesn't immediately reach it's terminal velocity. This is to make the motion look more natural. However, the lagging is ruining this effect greatly, even when the sprite supposedly is traveling at a set speed.
EDIT 1:
I'm trying to make a platform-style game (like Super Mario etc) where the _ball moves horizontally along the ground when the user taps the screen. The code for moving the ball to the right is included above the edit. The ground is made up of multiple tiles, each 32x32 and positioned right next to each other with no gap in-between.
As per request, here's the code for setting up the _balls physicsBody:
self.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:self.size.width/2.0];
self.physicsBody.dynamic = YES;
self.physicsBody.restitution = 0.5f;
self.physicsBody.usesPreciseCollisionDetection = YES;
self.physicsBody.allowsRotation = NO;
self.physicsBody.mass = 0.5f;
self.physicsBody.friction = 0.0f;
self.physicsBody.linearDamping = 0.0f;
self.physicsBody.categoryBitMask = CollisionCategoryBall;
And here's the code for the physicsBody of each individual tile:
tile.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:tile.size];
tile.physicsBody.dynamic = NO;
tile.physicsBody.categoryBitMask = CollisionCategoryGround;
The physicsWorld is set up like this:
self.physicsWorld.gravity = CGVectorMake(0, -4);
self.physicsWorld.contactDelegate = self;
Thanks!
EDIT 2:
This is a side-scrolling game, so the "camera" follows the ball. Here's the code for moving the background layer:
- (void)centerViewOn:(CGPoint)centerOn {
CGFloat x = Clamp(centerOn.x, (self.size.width / 2.0), (_bgLayer.layerSize.width) - (self.size.width / 2.0));
_worldNode.position = CGPointMake((int)-x, _worldNode.position.y);
}
The reason for the Clamp is so the "camera" doesn't scroll beyond the bounds of the background. This is when the ball is close to either the start or end of the level.
I'm casting the position to an int because without it, small gaps sometimes occur between the tiles. I was told this was because of some inaccuracy or something. However, even without casting the position to int, it's still a bitt "laggy". But because of the gaps between the tiles, it looks even worse.
The issue was with your scrolling code.
change this line :
_worldNode.position = CGPointMake((int)-x, _worldNode.position.y);
to
_worldNode.position = CGPointMake(-x, _worldNode.position.y);
The movement is then silky smooth.
But then you do get those seams. You should solve that in the placement of those tiles. You are likely positioning your _worldNode tiles with float values.

Moving a sprite with touches began, casting and parameters in obj - c?

I've been reading a book on the cocos2d framework for ios5 for a few days and have developed a small game that the book walks you through. To control the sprite in this game you use the accelerometer:
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.4f;
float sensitivity = 6.0f;
float maxVelocity = 100;
// adjust velocity based on current accelerometer acceleration
playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity;
// we must limit the maximum velocity of the player sprite, in both directions (positive & negative values)
if (playerVelocity.x > maxVelocity)
{
playerVelocity.x = maxVelocity;
}
else if (playerVelocity.x < -maxVelocity)
{
playerVelocity.x = -maxVelocity;
}
// Alternatively, the above if/else if block can be rewritten using fminf and fmaxf more neatly like so:
// playerVelocity.x = fmaxf(fminf(playerVelocity.x, maxVelocity), -maxVelocity);
}
Now I'm wondering if I can change this code to allow the sprite to still accelerate/decelerate along the x axis, but to use touch input rather than the accelerometer, and to go faster the longer the touch is held down for? So a touch to the right would move the sprite to that spot slowly, if the touch is released, it stops moving to that spot. The longer a touch is held down, the faster the sprite moves.
is there anything in the framework to allow me to implement a rotation mechanism that allows my sprite to rotate to the position that the touch was in, so it looks like its facing the point thats been touched?
Well, afaik theres no method that will determine the angle to the touch and then rotate the sprite accordingly, but if you have the x and y coordinates of the sprite and the touch you can calculate it yourself fairly easily.
CGPoint spriteCenter; // this should represent the center position of the sprite
CGPoint touchPoint; //location of touch
float distanceX = touchPoint.x - spriteCenter.x;
float distanceY = touchPoint.y - spriteCenter.y;
float angle = atan2f(distanceY,distanceX); // returns angle in radians
// do whatever you need to with the angle
Once you have the angle you can set the rotation of the sprite.

cocos2d rotating sprite collision detection

I got 2 sprites, ball and arrow.
the arrow is not moving.
the ball is rotating on it's anchor point.
id rotate = [CCRotateBy actionWithDuration:.5 angle: 360];
I want to detect collision when the ball reaches to arrow.
Tried CGRectIntersectsRect but it does not detect collision.
Any help?
Thanks...
You probably don't want this answer, but I would use Box2D or Chipmunk and use the Vertex Helper application to specify vertices.
use circle-circle collision method.. here is the method..
-(float)asbs:(CGPoint)_arrowPos ballPos:(CGPoint)_ballPos
{
float x = _arrowPos.x-_ballPos.x;
float y = _arrowPos.y-_ballPos.y;
float xy = x*x+y*y;
return xy;
}
if([self asbs:arrow.position ballPos:ball.position]<=size)
{
//collision
}
note that size = ball radius + arrow radius * ball radius + arrow radius
the method above is using a(square) + b(square) = c(square) to check distance between two points..
You might need to convert the ball to world space in an update method then call that rather than the balls position. If it is in a parent layer is position will always be static in respect to its parent.

How to rotate image around center point automatically with finger touch

On iPhone, how to implement rotating image around the center point using finger touch ?
Just like wheel, if you put finger on the iPhone screen , then move suddenly, then the image becoming rotating around center point just like the wheel, after a while, it becomes more and more slow , finally stop.
Who can help to give some pieces of codes (Object-C) or some suggest ?
I was working with a "spin the bottle"-app yesterday. On the window I have a ImageView with an bottle that's suppose to response to touches and rotate the way the user swipes his finger. I struggled to get my ImageView to rotate during the touch-events (TouchesBegan, Touchesoved, TouchesEnd). I used this code in TouchesMoved to find out the angle in witch to rotate the image.
public override void TouchesMoved (NSSet touches, UIEvent evt)
{
PointF pt = (touches.AnyObject as UITouch).LocationInView(this);
float x = pt.X - this.Center.X;
float y = pt.Y - this.Center.Y;
double ang = Math.Atan2(x,y);
// yada yada, rotate image using this.Transform
}
THIS IS IMPORTANT! When the ImageView rotates, even the x & y-coordinates changes. So touching the same area all the time would give me different values in the pt and prePt-points. After some thinking, googeling and reading I came up with an simple solution to the problem. The "SuperView"-property of the ImageView.
PointF pt = (touches.AnyObject as UITouch).LocationInView(this.SuperView);
Having that small change in place made it alot easier, no i can use the UITouch-metohs LocationInView and PreviousLocationInView and get the right x & y coordinates. Her is parts of my code.
float deltaAngle;
public override void TouchesMoved (NSSet touches, UIEvent evt)
{
PointF pt = (touches.AnyObject as UITouch).LocationInView(this.Superview);
float x = pt.X - this.Center.X;
float y = pt.Y - this.Center.Y;
float ang = float.Parse(Math.Atan2(dx,dy).ToString());
//do the rotation
if (deltaAngle == 0.0) {
deltaAngle = ang;
}
else
{
float angleDif = deltaAngle - ang;
this.Transform = CGAffineTransform.MakeRotation(angleDif);
}
}
Hope that helped someone from spending hours on how to figure out how to freaking rotate a bottle! :)
I would use the affine transformations - yuou can assign a transformation to any layer or UI element using the transform property.
You can create a rotation transform using CGAffineTransform CGAffineTransformMakeRotation( CGFloat angle) which will return a transformation that rotates an element. The default rotation should be around the centerpoint.
Be aware, the rotation is limited to 360 degrees, so if you want to rotate something more than that (say through 720 degrees) - you have to break the rotation into several sequences.
You may find this SO article useful as well.
The transform property of a view or layer can be used to rotate the image displayed within. As far as the spinning part goes, you just track the location and movement of touches in your view with touchesBegan, touchesMoved, and touchesEnded.
Use the distance and time between the touches updates to calculate a speed, and use that to set a rotational velocity. Once you start the image spinning, update the position periodically (with an NSTimer, maybe), and reduce the rotational velocity by some constant.