Need help with moving UIImageViews in a circle via touch - objective-c

I'm designing an app that involves linear graphs. What I have right now is a line with three dots: one in the center for moving the whole line, and the other two, lower and higher on the line, for rotating it. The problem that I have is figuring out how to rotate the other two dots when the user touches on either of them.
I haven't actually done much with the rotation dots yet, but here's my code so far:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* touch = [touches anyObject];
CGPoint point = [touch locationInView:graph];
if (CGRectContainsPoint(moveDot.frame, point)) {
moveDotIsTouched = YES;
}
if (CGRectContainsPoint(rotateDot1.frame, point)) {
rotateDot1IsTouched = YES;
}
if (CGRectContainsPoint(rotateDot2.frame, point)) {
rotateDot2IsTouched = YES;
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* touch = [touches anyObject];
CGPoint point = [touch locationInView:graph];
if (moveDotIsTouched) {
if ((point.y > 0) && (point.y < 704))
{
if (point.y < 64) {rotateDot1.hidden = YES;}
else {rotateDot1.hidden = NO;}
if (point.y > 640) {rotateDot2.hidden = YES;}
else {rotateDot2.hidden = NO;}
moveDot.center = CGPointMake(moveDot.center.x, point.y);
rotateDot1.center = CGPointMake(moveDot.center.x+64, moveDot.center.y-64);
rotateDot2.center = CGPointMake(moveDot.center.x-64, moveDot.center.y+64);
graph.base = -(point.y)/32 + 11;
if (graph.base < 0) {[functionField setText:[NSString stringWithFormat:#"y = %.2fx %.2f", graph.slope, graph.base]];}
else if (graph.base > 0) {[functionField setText:[NSString stringWithFormat:#"y = %.2fx + %.2f", graph.slope, graph.base]];}
else {[functionField setText:[NSString stringWithFormat:#"y = %.2fx", graph.slope]];}
[yintField setText:[NSString stringWithFormat:#"%.2f", graph.base]];
[self changeTable];
}
}
[graph setNeedsDisplay];
}
The numbers involving the positioning of the dots are measured in pixels. The only way I can really think of rotating the outside dots is by calculating a radius and making sure the dots are within the radius, but I'm wondering if there isn't something simpler than that. Does anyone know a simple way to move a UIImageView in a circle?

KTOneFingerRotationGestureRecognizer is a custom UIGestureRecognizer for doing one finger rotations in iOS apps. It tracks finger movement around a central point. I don't know if this is exactly what you want, but it may point you in the right direction.

Related

Objective-C moving a player with joypad

i currently use a joypad that can move a player when touches began and moved. the problem is: If i touch on the Joypad and keep touching it without moving my finger or release it, how can I make the player keep moving?
Here's some code:
- (void)updateVelocity:(CGPoint)point {
// Calculate distance and angle from the center.
CGRect frame = _player.image.frame;
float dx = point.x - padCenter.x;
float dy = point.y - padCenter.y;
frame.origin.x += dx/10;
frame.origin.y += dy/10;
if (!(frame.origin.x < 0 || frame.origin.y < 0 || frame.origin.x > SCREEN_SIZE_X - frame.size.width || frame.origin.y > SCREEN_SIZE_Y - frame.size.height)) //if the players won't exit the screen then move it
_player.image.frame = frame;
}
This is to move the player.
And this when the touch began/moved
-(void)touchesBegan :(CGPoint )point{ //same as moved
if (isPointInCircle(point, padCenter , JOYSTICK_RADIUS)){
isPressed = YES;
[self updateVelocity:point];
}
}
here's the viewcontroller's touchesBegan method:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ //same as Moved
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView: [touch view]];
[joypad touchesBegan:point];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
[joypad touchesEnded];
}
Like I said, if I touch in the Joypad's area without moving the finger the player moves only once. Any ideas to keep it moving until I release the finger?
Here is a full blown tutorial for the D-pad controls you are looking for. Here is the .zip file for SneakyInput which has analog and D-Pad code, for cocos2d. These do most of the work for you!
:) HTH

Need CCRenderTexture to render faster ios

I'm making a drawing app, and I'm having the users draw with CCRenderTexture. It basically keeps rendering a picture of a black circle to simulate drawing. When I move my finger slowly, it works really well since the circles come together to form a line. However, when I move my finger quickly, it ends up just being a bunch of circles that aren't connected (http://postimage.org/image/wvj3w632n/). My question is how I get the render texture to render the image faster or have it fill in the blanks for me.
Also, I'm not completely sold on this method, but it's what I've found while looking around. Feel free to suggest whatever you think would be better. I was originally using ccdrawline but it really killed my performance. Thanks!
The gaps between start point and the end points need to be sorted out. I am pasting code that might help you to resolve the situation you showed in the link.
in .h file
CCRenderTexture *target;
CCSprite* brush;
in the init method of .m file
target = [[CCRenderTexture renderTextureWithWidth:size.width height:size.height] retain];
[target setPosition:ccp(size.width/2, size.height/2)];
[self addChild:target z:1];
brush = [[CCSprite spriteWithFile:#"brush_i3.png"] retain];
add the touches method I am showing the touchesMoved code.
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint start = [touch locationInView: [touch view]];
start = [[CCDirector sharedDirector] convertToGL: start];
CGPoint end = [touch previousLocationInView:[touch view]];
end = [[CCDirector sharedDirector] convertToGL:end];
printf("\n x= %f \t y= %f",start.x,start.y);
float distance = ccpDistance(start, end);
if (distance > 1)
{
int d = (int)distance;
for (int i = 0; i < d; i++)
{
float difx = end.x - start.x;
float dify = end.y - start.y;
float delta = (float)i / distance;
[brush setPosition:ccp(start.x + (difx * delta), start.y + (dify * delta))];
[target begin];
[brush setColor:ccc3(0, 255, 0)];
brush.opacity = 5;
[brush visit];
[target end];
}
}
}
Hopefully it would work for you.
Its not that CCRenderTexture draws too slow its that the event only fires so often. You do need to fill in the gaps between the touch points you receive.
There is a great tutorial here about it which you may have already seen, http://www.learn-cocos2d.com/2011/12/how-to-use-ccrendertexture-motion-blur-screenshots-drawing-sketches/#sketching

How to add movable UIView as subview with dynamic size at runtime in objective C?

I need to add a UIView as subview of a UIView where a UIImageview is displayed. What I need to implement is that when the image is loaded in my UIIMageview, at the same time I am showing the UIView call it as newView. In the beginning,I am showing it with static size say 190X170 and alpha as 0.5. Once i tap my finger on that view,it should move on the whole UIImageview. Once it is moved at the last,that coordinated I am taking and cropping my image with the same points. Now I am done with the moving part using the code below.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
if (CGRectContainsPoint(newView.frame, touchLocation))
{
dragging = YES;
oldX = touchLocation.x;
oldY = touchLocation.y;
}
if (dragging)
{
newView.layer.borderColor = [UIColor clearColor].CGColor;
newView.layer.borderWidth = 1.0f;
CGRect frame = newView.frame;
frame.origin.x = newView.frame.origin.x + touchLocation.x - oldX;
x = frame.origin.x;
NSLog(#"x value : %d",x);
frame.origin.y = newView.frame.origin.y + touchLocation.y - oldY;
y = frame.origin.y;
NSLog(#"y value : %d",y);
newView.frame = frame;
}
oldX = touchLocation.x;
oldY = touchLocation.y;
}
What I need to implement is to resize the UIView on taping two fingers like that of UIScrollview. I tried to implement the UIScrollview but it is not giving me good effect. I tried to implement
NSUInteger resizingMask = NSViewHeightSizable | NSViewWidthSizable;
[self.view setAutoresizesSubviews:YES];
[newView setAutoresizingMask:resizingMask];
but in vain. Nothing is taking place.
Can anybody show me a path for the same. Thanks in advance.
To provide the zoom in zoom out feature you can use the UIPinchGuestureRecognizer. If you are using iOS 5 then it will be pretty easy for you.
here is the very cool tutorial for that hope it will help for you.
http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more

Trying to rotate my sprite smoothly at a constant speed. But it decreases the speed

(I'm using cocos2d for iphone)
First I'll explain you my code: (the important parts)
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
float dstAngle = CC_RADIANS_TO_DEGREES(-ccpToAngle(ccpSub(location, plane.position)));
plane.dstAngle = dstAngle;
}
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
float dstAngle = CC_RADIANS_TO_DEGREES(-ccpToAngle(ccpSub(location, plane.position)));
plane.dstAngle = dstAngle; }
If I touch the screen I calculate the angle between my plane and the touch location.
Now I set the "destination" angle of the plane.
My "plane" is a subclass.
In my header file I have these float values:
//this is in my plane subclass
float diffAngle_;
float startAngle_;
float dstAngle_;
float smoothRotationSpeed_;
EDIT: In my init of the layer I set the "smoothRotationSpeed" to a value. The "rotationTick" method IS scheduled.
I have a tick method to rotate the plane (also in the plane subclass)
-(void)rotateTick:(ccTime)dt {
startAngle_ = [self rotation];
if (startAngle_ > 0)
startAngle_ = fmodf(startAngle_, 360.0f);
else
startAngle_ = fmodf(startAngle_, -360.0f);
diffAngle_ =dstAngle_ - startAngle_;
if (diffAngle_ > 180)
diffAngle_ -= 360;
if (diffAngle_ < -180)
diffAngle_ += 360;
[self setRotation: startAngle_ + diffAngle_ * dt]; //smooth rotate
}
-(void)setSmoothRotationSpeed:(float)smoothRotationSpeed {
[self schedule:#selector(rotateTick:)]; //this will be called if the "smoothRotationSpeed" value is changed
}
The problem is now if I touch a location the sprites rotates to it correctly but at first it rotates a little bit fast and than it looses it's speed..
The nearer it is to the destination angle the slower it moves...
But I want it to move at a constant speed. This "constant" speed is defined in the "smoothRotationSpeed" value but how can I implement it in my code?
If I set the interval to the "smoothRotationSpeed" value it wouldn't be smooth. It would lag.
Would anyone like to help me please?
You're incrementing the rotation of your sprite based on the difference between the target and current angles, so the closer the current angle is to the target angle, the smaller is the increment you're applying to the current rotation. But from what you're saying, that's not what you want. So you could simply do something like this:
-(void)rotateTick:(ccTime)dt {
startAngle_ = [self rotation];
if (startAngle_ > 0)
startAngle_ = fmodf(startAngle_, 360.0f);
else
startAngle_ = fmodf(startAngle_, -360.0f);
diffAngle_ =dstAngle_ - startAngle_;
if (diffAngle_ > 180)
diffAngle_ -= 360;
if (diffAngle_ < -180)
diffAngle_ += 360;
if ( fabs(diffAngle_) < smoothRotationSpeed_*dt ) // finished rotation
{
[self setRotation: dstAngle_]; // go to the end position
}
else if (diffAngle_ > 0)
{
[self setRotation: startAngle_ + smoothRotationSpeed_* dt]; //smooth rotate
}
else
{
[self setRotation: startAngle_ - smoothRotationSpeed_* dt]; //smooth rotate
}
}
-(void)setSmoothRotationSpeed:(float)smoothRotationSpeed
{
smoothRotationSpeed_ = smoothRotationSpeed;
[self schedule:#selector(rotateTick:)]; //this will be called if the "smoothRotationSpeed" value is changed
}

how to resize UIView with corner handles - similar to 'Pages', 'Keynote'

I need to add handles (to the corners) of view, so user can resize this view with them. Something similar to edit graphic in Apples 'pages' or 'keynote' apps. (or in any other graphic app).
I did try to add handles subviews to a given view, but those views received touches only in place where both overlapping, inside given view bounds. I need to be able to drag any of the corners handles which will change frame or bounds of that given view. (this part I have already working).
any suggestions, tutorials, links will be appreciated :)
I'm new, so I can't :( post images, so
please take a look at link
I would make a UIGripView that inherits from UIView that is on top of the view you want.
It would:
Be given a view to manipulate and size itself accordingly (a little larger, but with the same center)
Draw itself (the grips and borders) -- implement -(void) drawRect:(CGRect)rect
Register gesture recognizers
When a grip is moved, resize the underlying view and yourself accordingly
When the center is moved, move the center of the underlying view and yourself.
It might make it easier to deal with gestures if you make each grip a UIView as well, but it's not hard to make some zones in your view and check which one the touch is in.
(Remember to make the touch zones big enough)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
touchStart = [[touches anyObject] locationInView:self];
isResizingLR = (self.bounds.size.width - touchStart.x < kResizeThumbSize && self.bounds.size.height - touchStart.y < kResizeThumbSize);
isResizingUL = (touchStart.x <kResizeThumbSize && touchStart.y <kResizeThumbSize);
isResizingUR = (self.bounds.size.width-touchStart.x < kResizeThumbSize && touchStart.y<kResizeThumbSize);
isResizingLL = (touchStart.x <kResizeThumbSize && self.bounds.size.height -touchStart.y <kResizeThumbSize);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint touchPoint = [[touches anyObject] locationInView:self];
CGPoint previous=[[touches anyObject]previousLocationInView:self];
float deltaWidth = touchPoint.x-previous.x;
float deltaHeight = touchPoint.y-previous.y;
if (isResizingLR) {
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y,touchPoint.x + deltaWidth, touchPoint.y + deltaWidth);
}
if (isResizingUL) {
self.frame = CGRectMake(self.frame.origin.x + deltaWidth, self.frame.origin.y + deltaHeight, self.frame.size.width - deltaWidth, self.frame.size.height - deltaHeight);
}
if (isResizingUR) {
self.frame = CGRectMake(self.frame.origin.x ,self.frame.origin.y + deltaHeight, self.frame.size.width + deltaWidth, self.frame.size.height - deltaHeight);
}
if (isResizingLL) {
self.frame = CGRectMake(self.frame.origin.x + deltaWidth ,self.frame.origin.y , self.frame.size.width - deltaWidth, self.frame.size.height + deltaHeight);
}
if (!isResizingUL && !isResizingLR && !isResizingUR && !isResizingLL) {
self.center = CGPointMake(self.center.x + touchPoint.x - touchStart.x,self.center.y + touchPoint.y - touchStart.y);
}
}