I have an object that can be moved across the screen with the finger. This object is an image, a small image, like a thumbnail.
On the screen I have a background image where 10 rectangles were drawn. This rectangles are part of the background image. The background image is dumb, just a UIImageView.
I have 10 sounds I want to play every time the thumbnail passes over one of the 10 areas, represented by the 10 rectangles on the background. Each area has its own sound.
All I have is the size of the translating thumbnail and its coordinates (like origin, center, width and height). I have the origin (x and y) coordinates in realtime.
The point is: how to detect if the translating thumbnail is over one of the 10 squares considering a certain tolerance (example +- 10 pixels) and discover what area is it?
The problem: as I have the origin coordinates in realtime I can always create a loop to check if this value is inside one of the 10 rectangles, but this is CPU intensive because the loop will run for each pixel the thumbnail scrolls.
Any other ideas on how to do that?
thanks for any help.
You could poll for the coordinates at a predefined interval instead of constantly.
The idea behind this is in the main loop to set off a (say 1 second) timer. When the timer finishes it fires an event in which you can inquire the current location. Then use that value to check to see which rectangle it's in.
I would use a timer to fire a method which checks them every .2-.5 seconds:
[NSTimer scheduledTimerWithTimeInterval:.2 target:self selector:#selector(checkPointInRects) userInfo:nil repeats:YES];
Use touchesBegan,moved,ended to cache the current touches and refer to them in the checkPointInRects method. You can use CGRectContainsPoint to determine if the point lies in any given rectangle.
Related
Context
For the purpose of a MWE we will be using the following image of a stick figure:
with the goal of having a chain of these sprites move, hand-in-hand, across the screen:
It is worthwhile to note that the stick figure image itself is wider than the arm-span of this stick figure. The background is, however, transparent.
Depending on the application, one may make a class that either inherits from SKSpriteNode or encapsulates it, e.g. a class called Person, to store additional information, where there may be an array var people = [Person]().
Questions
1.) Suppose you had two instances of the aforementioned Person class with each sprite taking a stick figure image. How could one position them - programmatically - such that the sprites are touching ''hand in hand'' although the image has a transparent background? Of course one could spend some time fiddling about to get find a spacing parameter to ensure this is achieved, but that parameter would always have to be, via trial-and-error, re-calculated if the sprites were re-scaled.
2.) Given a chain of these sprites, hand in hand, how could one animate them to move across the screen at the same velocity? If one calculates the spacing parameter alluded to in 1.) then an SKAction could be given to each Person such that their end position is offset (but total distance traveled is the same), where the TimeInterval is maintained the same. Is there a way to tell all the sprites to move to the left until off the screen at a rate of $x$ pixels per second?
It looks like you've mostly answered your own questions already, but here are some additional ideas:
Make the spacing value proportional to the size of the sprite.
Yes, there is an SKAction that moves a sprite a given distance over a given period of time (effectively a velocity): let moveAction = SKAction.moveBy(x: 10, y: 0, duration: 2)
I'm repeatedly shrinking an image (and then render it to a new full sized image) by a small amount, and the result is that a stripe down the middle is not being shrunk. I'm assuming this has to do with the resize method cocos2d uses. If I increase the amount I scale down the image by the resize is too fast, and if I decrease the shrink size the bar down the middle gets even bigger! the following code is called 60 times a second. the picture below shows the result! So.. any suggestions on how to get rid of the bar?
[mySprite setScaleX:rtt.scaleX - .05];
I wasn't sure quite what you meant, but did you mean you're calling this line 60 times a second?
[mySprite setScaleX:rtt.scaleX - .05];
If so then your sprite's scale will become negative in a third of a second...
Every time you manipulate an image, you lose information.
A better approach would be to always resize from the original, and just change the resize amount each time, rather than continually resizing the result of the last resize operation.
I'm new to cocos2d engine, so hope this helps. If your shrinking an image, I would suggest using CCScaleBy. You can try something like this...
CCScaleBy *yourSprite = [CCScaleBy actionWithDuration: .01 scaleX: .95 scaleY: 1.0f];
This will scale your sprite down by 5% each time its called. Then you can have it replaced by the new image when it reaches what you would consider its smallest pixel point. The duration may need to be played with, but thought this would help.
This is a multi-part question:
How can one create an animation-block and hook it up with a timer such that the animation block runs when the image is put on display in the iPhone?
How can any one of the following three effects be applied to an image?
throb effect
pulse effect (same thing as throb as far as I can guess)
fade-away or fade-out effect
Apply the size or alpha transforms to your image within the animation block, and then create a callback function (called after the animation is complete) that calls a function that applies the opposite animated transform to your image. Then the callback for that function will start the cycle again, and so on.
I need to animate controls by moving them along the x axis from x to x-1000.
My container view is 200 pixels across and each control is 100 pixels wide.
There is a maximum of 4 controls (the controls are heavy and I need to re-use them)
So therefore, as I animate the controls from x to x-1000, I need to re-use them.
So as control 1 goes off to the left, it becomes invisible and needs to be re-positioned to the right hand side of the container view.
As I will be using an ease in function, the control needs to inherit the same speed and deceleration is it had before; so it literally just animates from right to left, once off screen, instantly re-positioned to the right of the container view, and carries on animating from right to left at the same deceleration rate.
Is there anyway to invoke a function for each frame of a CAPropertyAnimation? or something along those lines?
As far as I know, you can't get velocity information from core animation.
You will have to roll your own animation for this. Setup a timer, and give each view an xVelocity. Every time the timer fires, have it adjust the xVelocity of all objects (you could apply a sine curve to it to give it an ease/out effect). Then change the center point of all the objects.
I am trying to figure out how can you drag an image while constraining its movement along a certain path.
I tried several tricks including animation along a path, but couldn't get the animation to play and pause and play backwards - so that seems out of the question.
Any ideas ? anyone ?
What you're basically trying to do is match finger movement to a 'translation' transition.
As the user touches down and starts to move their finger you want to use the current touch point value to create a translation transform which you apply to your UIImageView. Here's how you would do it:
On touch down, save the imageview's starting x,y position.
On move, calculate the delta from old point to new one. This is where you can clamp the values. So you can ignore, say, the y change and only use the x deltas. This means that the image will only move left to right. If you ignore the x and use y, then it only moves up and down.
Once you have the 'new' calculated/clamped x,y values, use it to create a new transform using CGAffineTransformMakeTranslation(x, y). Assign this transform to the UIImageView. The image moves to that place.
Once the finger lifts, figure out the delta from the original starting x,y, point and the lift-off point, then adjust the ImageView's bounds and reset the transform to CGAffineTransformIdentity. This doesn't move the object, but it sets it so subsequent accesses to the ImageView use the actual position and don't have to keep adjusting for transforms.
Moving along on a grid is easy too. Just round out the x,y values in step 2 so they're a multiple of the grid size (i.e. round out to every 10 pixel) before you pass it on to make the translation transform.
If you want to make it extra smooth, surround the code where you assign the transition with UIView animation blocks. Mess around with the easing and timing settings. The image should drag behind a bit but smoothly 'rubber-band' from one touch point to the next.
See this Sample Code : Move Me