Finding the array indexes of objects on screen - iphone

I have a pie chart made up of 12 slices, which are all within an array. The idea is to be able to touch any particular slice, receive its correct index position within the array, and scale that slice up and down. I have the creation of the slices done, as well as the scaling, but the math behind selecting the correct index has stumped me.
The current code (slicesArray = 12) I have that returns the incorrect index number is:
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
int index = atan2f(point.x-self.view.center.x, point.y-self.view.center.y) * self.slicesArray.count / (2*M_PI);
This image shows the slices, with the black text representing the correct index numbers, while the white text represents what the above code returns.
Thanks for any help.

If you are using an UIImageView to show all images, then Here's my answer will help you.
What you need to do is setTag for individual UIImageView. It will identify touched UIImageView. Its tag will index for your array, and you can also pass it to NSArray to get value from it.

use a for loop to find out which UIView is being touched
UIView *selectedPie;
for (UIView *pie in slicesArray) {
if(CGRectContainsPoint(pie.frame, point)) {
selectedPie = pie;
break;
}
}
and then scale the selectedPie. Hope this helps

Related

UIImage remove some pixels issue

I have the application where user can erase image.
So if user touches some px of the image, alfa of these pixels should become lower.
For instance, if I touched (0,0) pixel of the image one time, (0,0) px opacity should become 0.9. If I touched that px 10 times I shouldn't see image at point (0,0).
What is the best approach to implement that?
This is the coe by which you can detect the touch values
CGPoint StartPoint = [touch previousLocationInView:self];
CGPoint Endpoint = [touch locationInView:self];
NSString *str = [NSString stringWithFormat:#"%f",StartPoint.x];
NSString *strlx = [NSString stringWithFormat:#"%f",StartPoint.y];
NSString *strcx = [NSString stringWithFormat:#"%f",Endpoint.x];
NSString *strcy = [NSString stringWithFormat:#"%f",Endpoint.y];
here touch is the object for UITouch.
I cann't say anything about the opacity.
If you want it fast (as in real time fast) you'll need to use OpenGL.
The best way to do it to create a mask of alpha values which will be applied on the original image using a custom built shader.
The easier way but slower is to get the raw pixels from the UIImage
and applying the alpha values on the raw pixels array and then turning it back to a UIImage (here is a nice example)

How to make a sprite follow a trail?

I'm making a game where the player draws a line and then a sprite should follow and run on it. I have a mutable array and also a draw method which works well. but I'm having trouble figuring out a way to move the sprite. I have tried different approaches but I can't get the iterator to work.
It's supposed to work by iterating through the array. which is populated with CGPoint locations previously stored. I try to move the sprite in ccTouchedEnded but it highlights [toucharray objectAtIndex:0] and says "passing 'id' to parameter of incompatible type 'CGPoint (aka 'struct CGPoint')"
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//remove objects each time the player makes a new path
[toucharray removeAllObjects];
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [ touches anyObject];
CGPoint new_location = [touch locationInView: [touch view]];
new_location = [[CCDirector sharedDirector] convertToGL:new_location];
CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
// add touches to the touch array
[toucharray addObject:NSStringFromCGPoint(new_location)];
[toucharray addObject:NSStringFromCGPoint(oldTouchLocation)];
}
-(void)draw
{
glEnable(GL_LINE_SMOOTH);
for(int i = 0; i < [toucharray count]; i+=2)
{
CGPoint start = CGPointFromString([toucharray objectAtIndex:i]);
CGPoint end = CGPointFromString([toucharray objectAtIndex:i+1]);
ccDrawLine(start, end);
}
}
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// here is the line I can't get to work to move the sprite
_sprite.position = ccpAdd(ccpMult([toucharray objectAtIndex:0], progress), ccpMult([toucharray objectAtIndex:0+1], 1-progress));
}
I did this before, by (what you have so far) creating an array
Mine was with multiple sprites on screen, so I also had 1 definition "Touched sprite"
ontouchstart empty array and add first point (start point) + set TouchedSprite to the Sprite that was closest to the start point)
ontouchmove add point to array
ontouchend (run the array on the sprite by actions (get back to that later)
A few problems is what I got, (1) I could only control 1 sprite at a time and (2) the drawn line had way too many points.
Solution to number 1:
Create a subclass Object of a sprite and create your sprites like that. Within that object create an array (make it accessible with #property and #synthesize) which will allow you to place the drawn path points in. Also create a public method called "runPathAction".
So onTouchStart you clean the Array and set the selected spriteObject. OnTouchMove add the items, OntouchEnd set the array of the selected spriteObject to the local array and then run the "runPathAction" method. (You could have passed it to the method, but I like doing it this way, just in case I want to access the array)
Solution to number 2:
I found that drawing the line creates WAY to many points. So, i created a boolean operator called "CanDraw" and a schedule with a time interval of 0.1 (you can play around with it) to a method which sets canDraw to YES. and then in the onTouchMove you check for "canDraw == YES", add the point and set canDraw=NO;
This way you will have an interval of 0.1 seconds to add the points. Don't forget to remove the schedule onTouchEnd!!!
Now how to run the actions.
You will want a steady speed, so you will need to set a speed variable.
Walk through the array of points and calculate the distance between each point to create a total distance. (PS Don't forget that the first pint is from CurrentLocation to Point0 in the array)
When you have the total distance you can figure out how much delay time you should set in your actions per step. (if you don't do this, you don't know the delay time and if you fix that you get weird movement).
Create a method,
check the "count" of the array. If count = 0 return; (finished!!! do cleanup or whatever)
otherwise run an actionsequence, which at the end calls itself. (the check for count will handle the "break".
grab 1 item of the array CGPoint p = (objectAtIndex:0); and remove that item from the array (removeAtIndex:0).
Run the action with the delay time and there you go!
Record the positions of the path in an array or a list and iterate through that to move your sprite along the trail. I did this in a game I made to create a particle trail behind the player. I used a size 20 array and iterated through that on an interval, updating the array at the iterator's position with the location of my character and then moving the particle effect to the location stored in the array at the position of the iterator plus 1.
You'll need to seed the array with the starting location so that you don't have null values and you'll need a special case for when you're at the end of the array because you don't want to read from an out of bounds location, instead have your code read from the 0 position.

Setting boundary conditions for object to traverse a path through dragging the object

I am developing an application in which there is one object which is draggable.The user can drag this object in a specified path, not outside the path.
For achieving this I had to set the boundary conditions so that if the touch point is beyond that so the object does not move.
My problem is that my object size is lets say 30*30.
Now if I touch the object from its hair means at above portion and then drag it to down it gives one value, but if I touch the same object at some below position lets say his chin , then move the object at the same position where we moved the previous one.Now in this case, the the point of view are different from the previous one.
So I am not able to understand what should I set the boundary conditions,if I set the conditions of first value then in his case the second touch process will not able to move, which is wrong and if I set the second case value then the first case object will able to move below the boundary also.
I am not using cocos 2D.It is simple ipad application.
For more understanding I have added the image now if you touch the green circle on his left portion and moved towards the right, the last value is like 760 but if you touch on the right portion and moved towards the right then the last points come as 780 something. same case happens if object is dragged vertically.
My basic requirement is that the object should only move inside the path shown in image not outside it.
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
// Retrieve the touch point
CGPoint pt = [[touches anyObject] locationInView:gamePice];
startLocation = pt;
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
CGPoint pt1 = [[touches anyObject] locationInView:gamePice];
CGPoint pt = [[touches anyObject] locationInView:self.view];
NSLog(#"moved=%f|%f",pt.x,pt.y);
if (pt.x>=306 && pt.y>=148 && pt.x<=720 && pt.y<=175) { //these conditions how to set
CGRect frame = [gamePice frame];
frame.origin.x += pt1.x - startLocation.x;
frame.origin.y += pt1.y - startLocation.y;
[gamePice setFrame:frame];
}
}
Please suggest how to implement this feature or what approach should I follow.
Make an outer CGRect, lets say , CGRectMake(306, 148,400,100) , its your path rect, you many need multiple rects for that, but for now start with one.
make new frame for gamePice, that will be the frame according to touch location, lets say you make it like this,
CGRect frame = [gamePice frame];
frame.origin.x += pt1.x - startLocation.x;
frame.origin.y += pt1.y - startLocation.y;
then your condition will be,
if (CGRectContainsRect(outerRect, frame) )
{
[gamePice setFrame:frame];
}
// else dont move...

Tracing the position of the images in the scrollview while scrolling

I ve set of images (created dynamically) which are placed in a single row in my UIScrolView.. I want to trace the changes in the locations (i.e I want to get the x,y position of all the images)while scrolling ....
Things I ve tried:
1.I stored all the images in an array
2.Then I printed the locations of images in this delegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
But I can't get result what I want....Instead of that I get the positions of the images which I specified.....How can I get rid of this????
Thanks
I'm not entirely sure I understand what you mean by the location of the images but I think you want the contentOffset property of UIScrollView. If you subtract the x and y values of that from the offset of the frames of your images then you will effectively get where the images are relative to your UIScrollView's parent.
Edit: Here's some code to get you started:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollView.contentOffset;
for (UIView *view in scrollView.subviews) {
CGPoint thisOrigin = view.frame.origin;
thisOrigin.x -= offset.x;
thisOrigin.y -= offset.y;
NSLog(#"thisOrigin = %#", NSStringFromCGPoint(thisOrigin));
}
}
That will get the origin of the images in the coordinate system of the UIScrollView's bounds. If you want just the origin of the images within the coordinate system of the UIScrollView's contents then you just want view.frame.origin itself. But I don't think that's what you want since you said "But I can't get result what I want....Instead of that I get the positions of the images which I specified".

how to exchange one imageview with another imageview

i am displaying 3 images on image views.
i am getting image position by using the fallowing code.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// get touch event
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
NSLog(#"%f %f",touchLocation.x,touchLocation.y);
here in console i got the image positions.
Now what i need is when ever imageview is dragged over the imageview2 i need to exchange imageview2 in the place of image view and imageview in the place of imageview2.
can any one please help me.
Thank u in advance.
I wouldn't be replacing the entire imageView2, I would just change the image in imageView2 to the image in imageView.
First, establish that imageView2 is on top of imageView. Second, create an animation block and remove the image from imageView2, change the image in the imageView to the old image from imageView2, and possibly add a nice smooth transition. I would highly recommend a transition animation, it makes the action much more fluid. Use the positions of the imageViews, it wouldn't matter where the image was placed, it would animate as long as it was over top of imageView2.
Remember, there's nothing wrong with faking it. As long as it looks and acts like you want it to, then it works.