How to match image shape in UIGestureRecognizer in iOS? - iphone

I want to make shape match app like this.
Please check the second image of this link.
please check this link also,
I can drag and drop image but I am unable to match the exact location and unable to fill that image with another one.
Any idea or suggestions would be highly welcome.

//UIImageView *imageView1 (blank image with whom the image has to be matched),
//UIImageView *imageView2 (the coloured image that has to be matched)
Take a NSMutableArray positionArray, now whenever you add any new blank imageview (imageview1 ) to the screen add its additional information to the MutableArray like
UIImageView *imageview = [[UIImageView alloc] initWithFrame:CGRectMake(10,10,100,50)];
[imageview setTag:TagValue];
[imageview setImage:[UIImage imageNamed:#"blankMonkeyShapedImage.png"]];
//Incrementing the TagValue by one each time any blank imageview is added
TagValue++;
NSMutableDictionary *locationDic=[[NSMutableDictionary alloc] init];
[locationDic setValue:[NSNumber numberWithInt:imageview.tag] forKey:#"TagNumber"];
[locationDic setValue:[NSString stringWithFormat:#"Monkey~example"] forKey:#"ImageName"];
[locationDic setValue:[NSNumber numberWithFloat:imageview.frame.origin.x] forKey:#"PosX"];
[locationDic setValue:[NSNumber numberWithFloat:imageview.frame.origin.x] forKey:#"PosY"];
[locationDic setValue:[NSNumber numberWithFloat:imageview.frame.size.width] forKey:#"SizeWidth"];
[locationDic setValue:[NSNumber numberWithFloat:imageview.frame.size.height] forKey:#"SizeHeight"];
[self.view addSubview:imageview];
[positionArray addObject:locationDic];
Now whenever you add any new blank imageview you should repeat the same for it . Coming back to the UIGestureRecognizer selector method
-(void)panGestureRecognizer:(UIPanGestureRecognizer *)gesture
{
CGPoint translation = [gesture translationInView:self.view];
for (int i=0 ; i<[positionArray count]; i++)
{
NSMutableDictionary *lctionDic=[positionArray objectAtIndexPath:i];
float posX=[[lctionDic valueFor:#"PosX"] floatValue];
float posY=[[lctionDic valueFor:#"PosY"] floatValue];
float SizeWidth = [[lctionDic valueFor:#"SizeWidth"] floatValue];
float SizeHeight = [[lctionDic valueFor:#"SizeHeight"] floatValue];
if (translation.x >= posX && translation.x <= posX+SizeWidth &&
translation.y >= posY && translation.y <= posX+SizeHeight )
{
//Condition where the dragged objects position matches any previousluy placed balnk imageview.
if(gesture.view.tag==[[lctionDic valueFor:#"TagNumber"] intValue])
{
NSLog(#"Matched Image's Name is : %#",[lctionDic valueForKey:#"ImageName"]);
break;
}
else
continue;
}
}
}
Take special care at the time of allocating TagValues to the blank imageview and the toBeDragged imageview (both should be saem for same type of image).

That is bit tricky.
You are coder you know which image match what shape, May be you take two imageviews one with shape and other with image..
PS: I am just giving an idea.
So may be you can keep track with tags. Add gesture recogniser to drag images, so you will come to know which shape is being dragged. Now while moving just compare center of shape with center of your image current position. Make sure that you compare range and not exact center.
Hope this much info helps you :)

Related

Setting frame of CCTexture to fit into a predefined frame CCSprite

I am downloading an image from server and displaying it on game scene. I am able to get the CCTexture2D of the image from server and display it on game scene. The problem is that the image from server may vary in size. But I have to display that image on to a predefined frame CCSprite.
CCSprite *temp = [CCSprite spriteWithTexture:[[CCTexture2D alloc] initWithImage:[UIImage imageWithData:data] resolutionType:kCCResolutioniPhoneFourInchDisplay]];
CCRenderTexture *test=[CCRenderTexture renderTextureWithWidth:70 height:70]; //set proper width and height
[test begin];
[temp draw];
[test end];
UIImage *img=[test getUIImageFromBuffer];
sprite_Temp =[CCSprite spriteWithCGImage:img.CGImage key:#"1"];
sprite_Temp.tag = K_TagUserImage;
sprite_Temp.scale=1;
sprite_Temp.position=ccp(432,273);
[self addChild:sprite_Temp z:1];
I am using this code to resize the CCTexture2D to predefined frame CCSprite. But the image gets cropped to the desired frame which is not wanted. Can someone tell me how to get the original image from server to desired frame without getting cropped. Thanks.
try :
CCSprite *temp = [CCSprite spriteWithTexture:[[CCTexture2D alloc] initWithImage:[UIImage imageWithData:data] resolutionType:kCCResolutioniPhoneFourInchDisplay]];
float scaleX = 70./temp.contentSize.width;
float scaleY = 70./temp.contentSize.height;
// if you want to preserve the original texture's aspect ratio
float scale = MIN(scaleX,scaleY);
temp.scale = scale;
// or if you want to 'stretch-n-squeeze' to 70x70
temp.scaleX = scaleX;
temp.scaleY = scaleY;
// then add the sprite *temp
usual disclaimer : not tested, done from memory, beware of divides by 0 :)

uiimage not being put into subview correctly

This is a difficult problem to explain... but i'll do my best.
First a background on the problem, basically i am creating a paint like app for ios and wanted to add a functionality that allows the user to select part of the image (multi-touch shows an opaque rectangle) and delete/copy-paste/rotate that part. I have got the delete and copy-paste working perfectly but the rotation is another story. To rotate the part of the image I first start by copying the part of the image and setting it to be the background of the selected rectangle layer, then the user rotates by an arbitrary angle using a slider. The problem is that sometimes the image ends up being displayed from another location of the rectangle (meaning the copied image hangs off the wrong corner of the rectangle). I thought this could be a problem with my rectangle.frame.origin but the value for that seems to be correct through various tests. It also seems to change depending on the direction that the drag goes in...
These Are Screens of the problem
In each of the above cases the mismatched part of the image should be inside the grey rectangle, i am at a loss as to what the problem is.
bg = [[UIImageView alloc] initWithImage:[self crop:rectangle.frame:drawImage.image]];
[rectangle addSubview:bg];
drawImage is the users drawing, and rectangle is the selected grey area.
crop is a method which returns a part of a given image from a give rect.
I am also having trouble with pasting an arbitrarily rotated image.. any ideas on how to do that?
Edit: adding more code.
-(void)drawRect:(int)x1:(int)y1:(int)x2:(int)y2{
[rectangle removeFromSuperview];
rectangle = [[UIView alloc] initWithFrame:CGRectMake(x1, y1, x2-x1, y2-y1)];
rectangle.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:0.6];
selectionImage = drawImage.image;
drawImage.image = selectionImage;
[drawImage addSubview:rectangle];
rectangleVisible = true;
rectangle.transform = transformation;
Could it have anything to do with how i draw my rectangle? (above) I call this method from a part of a touchesMoved method (below) which may cause the problem (touch 1 being in the wrong location may cause width to be negative?) if so, is there an easy way to remedy this?
if([[event allTouches] count] == 2 && !drawImage.hidden){
NSSet *allTouches = [event allTouches];
UITouch *touch1 = [[allTouches allObjects] objectAtIndex:0];
UITouch *touch2 = [[allTouches allObjects] objectAtIndex:1];
[self drawRect:[touch1 locationInView:drawImage].x :[touch1 locationInView:drawImage].y:
[touch2 locationInView:drawImage].x :[touch2 locationInView:drawImage].y];
}
I'm not sure if this is your problem, but it looks like you are just assuming that touch1 represents the upper left touch. I would start out by standardizing the rectangle.
// Standardizing the rectangle before making it the frame.
CGRect frame = CGRectStandardize(CGRectMake(x1, y1, x2-x1, y2-y1));
rectangle = [[UIView alloc] initWithFrame:frame];

Points Versus Pixels ios

I have uiview , that I zoom in and out in it
I associate it with pinchRecognizerMeasure using
pinchRecognizerMeasure = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(MeasureAndDraw:)];
[pinchRecognizerMeasure setDelegate:self];
[DrawLine addGestureRecognizer:pinchRecognizerMeasure];
[pinchRecognizerMeasure release];
the code of MeasureAndDraw
// get position of touches, for example:
NSUInteger num_touches = [pinchRecognizerMeasure numberOfTouches];
// save locations to some instance variables, like `CGPoint location1, location2;`
if (num_touches >= 1) {
DrawLine.startPoint = [pinchRecognizerMeasure locationOfTouch:0 inView:DrawLine];
}
if (num_touches >= 2) {
DrawLine.endPoint = [pinchRecognizerMeasure locationOfTouch:1 inView:DrawLine];
}
startPoint , endPoint are CGPoint , I want to get the equivalent pixel to it
what shall I do is it correct to do something like
startPoint.X * DrawLine.contentScaleFactor to get the pixl x coordinate or what shall I do
I read http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html , but get confused
any suggestion
Have a look at the contentScaleFactor property of UIView to translate between points and pixels on the device if you really need to.

Please help! Creating new objects (from array?) after an object completes task

I am writing an iPhone application and here is the overall synopsis:
An object is on the screen and moves based on accelerometer input - I have that working - it moves to the edge of the screen and doesn't go off = perfect. Now, what I want to happen is as soon as that object hits any of the four screen edges, it should stop and stay put on the screen, and a new object should 'appear' and start moving due to the accelerometer input, so now two objects would be on the screen, but only 1 moving. Eventually there could be 20 objects built up around the edge, but only 1 object will be moving at a time.
So I have now gotten the help I needed to check for edge hits etc, but I am now trying to switch the way I was getting boxes to show up on the screen. I originally was putting images on the screen through the view controller, but now what I want to do is start with one box in the center, when it hits an edge, it should stop and stay, and a new image will appear in the center and start moving due to accel input as described above. So do I just use an array to pull the images from? Do I not even put .png's on the view controller and should I just code it? Here is some of what I have trying to do this through an array:
//In my .h
UIImageView *blocks;
NSString *blockTypes[3];
//In my .m
blockTypes[0] = #"greenBox1.png";
blockTypes[1] = #"greenBox2.png";
blockTypes[2] = #"greenBox3.png";
Thanks in advance for any help! The help so far has been great!
You should't test if newX and newY are equal to 30 and 50. You should test if they are less than 30 and 50 respectively.
Edit:
I would do it like this:
loat newX = [mutableBoxArray lastObject].center.x + (accel.x * 12);
float newY = [mutableBoxArray lastObject].center.y + (accel.y * -12);
if(newX > 30 && newY > 50 && newX < 290 && newY < 430) {
[[mutableBoxArray lastObject] setCenter: CGPointMake(newX, newY)];
} else {
MyBox *myBox = [[MyBox alloc] init];
[mutableBoxArray addObject: myBox];
[myBox release];
}
Edit 2:
Add the following in your interface file
NSMutableArray *mutableBoxArray;
NSArray *imageNamesArray;
Then in your implementation file in the loadView add
mutableBoxArray = [[NSMutableArray alloc] init];
imageNamesArray = [[NSArray alloc] initWithObjects: #"orangeBox1.png",
#"blueBox1.png", #"greenBox1.png", #"pinkBox1.png", nil];
Then change the above method to
static NSInteger imageInt = 0;
loat newX = [mutableBoxArray lastObject].center.x + (accel.x * 12);
float newY = [mutableBoxArray lastObject].center.y + (accel.y * -12);
if(newX > 30 && newY > 50 && newX < 290 && newY < 430) {
[[mutableBoxArray lastObject] setCenter: CGPointMake(newX, newY)];
} else {
if (imageInt < [imageNamesArray count]) {
UIImage *image = [UIImage imageNamed: [imageNamesArray objectAtIndex: imageInt++]];
UIImageView *imageView = [[UIImageView alloc] initWithImage: image];
[imageView setCenter: CGPointMake(100.0f, 100.0f)];
[mutableBoxArray addObject: imageView];
[imageView release];
}
}

Preloading a UIImageView animation using objective c for the iphone

I have an animated image which works great. It consists of 180 high quality images and it plays fine and loops continuously. My problem is that the first time I load the view containing these images it takes a long time to load. Every subsequent time after that it loads immediately as I am assuming that the images have been cached or preloaded!!! I come from a flash background and as I am sure you aware preloaders are as common as muck so I don't feel this should be difficult to find but after countless googling I cannot find any good examples on preloading or any articles on why there is a delay and what to do about it.
So my question(s) is this:
Is there a checkbox in the info.plist to preload all my images at the start of the app?
How can you preload images and are there any simple example projects that I could look at?
Is this the best way to implement what is essentially a video but has been output to a png sequence?
Is there another method as viewDidLoad does not work as I expect it to do. It traces "FINISHED LOADING IMAGES" (see code below) but the view does not show for a second or two after the images have been loaded so if the view does not show until the images have loaded then neither will the UIActivityIndicatorView which is also in the same view.
How do you do event listening in objective c?
Below is the code in the viewDidLoad which I believe is fairly standard:
Any help is greatly appreciated as I am banging my head on a brick wall on something that seems so basic in ui development. Help :)
- (void)viewDidLoad {
[super viewDidLoad];
imageArray = [[NSMutableArray alloc] initWithCapacity:IMAGE_COUNT];
NSLog(#"START LOADING IMAGES");
// Build array of images, cycling through image names
for (int i = 0; i < IMAGE_COUNT; i++){
[imageArray addObject:[UIImage imageNamed: [NSString stringWithFormat:#"Main_%d.png", i]]];
}
animatedImages = [[UIImageView alloc] initWithFrame:CGRectMake(0,20,IMAGE_WIDTH, IMAGE_HEIGHT)];
animatedImages.animationImages = [NSArray arrayWithArray:imageArray];
animatedImages.animationDuration = 6.0;
animatedImages.animationRepeatCount = 0;
[self.view addSubview:animatedImages];
animatedImages.startAnimating;
[animatedImages release];
NSLog(#"FINISH LOADING IMAGES");
}
Cheers
M
In case someone finds this question, I have an answer, which is to pre-render the images like this.
NSMutableArray *menuanimationImages = [[NSMutableArray alloc] init];
for (int aniCount = 1; aniCount < 21; aniCount++) {
NSString *fileLocation = [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat: #"bg%i", aniCount + 1] ofType: #"png"];
// here is the code to load and pre-render the image
UIImage *frameImage = [UIImage imageWithContentsOfFile: fileLocation];
UIGraphicsBeginImageContext(frameImage.size);
CGRect rect = CGRectMake(0, 0, frameImage.size.width, frameImage.size.height);
[frameImage drawInRect:rect];
UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// then add the resulting image to the array
[menuanimationImages addObject:renderedImage];
}
settingsBackground.animationImages = menuanimationImages;
I have tried multiple other methods of pre-loading images, and this is the only thing I've found that works.
My problem is that the first time I load the view containing these images it takes a long time to load. Every subsequent time after that it loads immediately as I am assuming that the images have been cached or preloaded
you are right at this point ...... as you are using method imageNamed: for this method document quotes.....
This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.
so in my opinion, rather than doing following stuff in viewDidLoad, you should do it earlier where delay is of not considerable......
for (int i = 0; i < IMAGE_COUNT; i++)
{
[imageArray addObject:[UIImage imageNamed: [NSString stringWithFormat:#"Main_%d.png", i]]];
}
another approach
- (void)spinLayer:(CALayer *)inLayer duration:(CFTimeInterval)inDuration
direction:(int)direction
{
CABasicAnimation* rotationAnimation;
// Rotate about the z axis
rotationAnimation =
[CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
// Rotate 360 degress, in direction specified
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 * direction];
// Perform the rotation over this many seconds
rotationAnimation.duration = inDuration;
rotationAnimation.repeatCount = 100;
//rotationAnimation.
// Set the pacing of the animation
//rotationAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// Add animation to the layer and make it so
[inLayer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
}
this method will help in animation call it as follow(I am assuming that you are putting above method in same class where you have imageView.
[self spinLayer:yourImageView.layer duration:5.0
direction:<-1 or 1 for anti clockwise or clockwise spin>];
remember just set only one image to that imageView(which you wish to animate.
thanks,