Fit borders to "real" image, cut of white borders SpriteKit objective c - ios

I am learning Spritekit right now and I want to detect a collision between two images.
Just a fun picture as an example :
The image is still a rectangle. How can I fit it that this rectangle will fit to the original face? I don't want the collision early when it hits the rectangle of the Image, I want it to collide when it actually hits the black lines of the face.
I hope you can understand my problem.
Thanks for any help.
EDIT:

There are two issues here:
You probably want to set up your SKPhysicsBody to be a path around your SKSpriteNode. For example, something like the following is close:
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-40, -22, 80, 39)];
node.physicsBody = [SKPhysicsBody bodyWithPolygonFromPath:path.CGPath];
That's probably not quite right, so feel free to tweak those values, but hopefully it illustrates the idea: Come up with a path that defines your boundary, and then set the physicsBody accordingly.
If you want to see the physics outlines, set showsPhysics on the SKView.
You probably want to mask your image so that the corners of the image are transparent (i.e. have an alpha of zero):
So, when that's on a colored background it looks like:
By masking the corners, you don't have to worry about the white corner covering up something else on the scene.

If its an image thats got white borders all around it, u can edit it in Preview and use Alpha to get rid of all of the white around it.
I think in that case, the sprite's collision method will collide with the black lines.

Related

Set corners of UIView (iOS)

I have the following problem: I'm scanning a QR Code with AVFoundation. This works quite well and I can also create a border around the code by adding a subview and set the frame attribute by subview.frame = qrCodeObject.bounds. This only has the problem that the border is only a rectangle and dismisses the perspective of the QR code.
I know that the qrCodeObject has a property corners which incorporates the top right, top left, bottom right and bottom left points of the QR code detected.
My question is now: how can I apply those corner points to the "border" view to make this border to have the same perspective as the QR code? Or in other words: how to "transform" the view according to the corner points?
Thanks a lot in advance!
UPDATE:
Here you can see the problem: the red box is a UIView, having it's frame property set to the QR codes bounds property. This misses perspective. I would like to transform the UIView (the red box) to following the corners property of the QR code, which includes the top right, top left, bottom right and bottom left points (CGPoint) of the QR code. It is important to apply this to a UIView, because I later want to apply it to an ImageView. Also a mask is not usable, as it just hides part of the view, but does not stretch or transform the content of the view.
I found a solution: AGGeometryKit did the trick: https://github.com/hfossli/AGGeometryKit/
Thanks everybody for helping!
You can't transform a CGRect that way, as far as I know. (At least I'm unaware of any framework that can do that kind of image processing.)
What you can do is to draw a polygon using the points of the qrCodeObject.
In drawRect of your UIView, change use CGContext and CGPath to draw the path you'd like.
You want your drawing UIView to be the same size as the one showing the QR code so that you don't have to translate the points onto a second coordinate space.
This answer has directions if you need more guidance on how to do that.
Ok, the problem you are facing is that a CGRect can only represent a rectangle that is not tilted or distorted. What you are dealing with is an image that has different kinds of perspective distortion.
I haven't tried to do this, but it sounds like AVFoundation gives you 4 CGPoint objects for a reason. You need to draw those 4 CGPoints using a UIBezierPath rather than trying to draw a CGRect. Simply create a bezier path that moves to the first point, then draws lines to each subsequent point, and finally, back to the first point. That will give you a quadrilateral that takes into account the distortion of your QR code.
CATransform3DRotate could be your friend, here.
https://guides.codepath.com/ios/Using-Perspective-Transforms might be a good starting point.

Smootly mooving a hole in UIImage?

I have a UIImageView displaing an image. This view's layer is masked with CAShapeLayer in order to create circular "hole" in the image. To create the hole I use UIBezierPath with .usesEvenOddFillRule = true.
It works fine when static. But I need that hole to move with user finger. To do that I create new UIBezierPath with even-odd rule each time user moves their finger. On smaller phones with smaller images it looks OK but on iPhone 6 Plus it is choppy.
Any ideas on how to make it smooth are very wellcome. I cannot just move the frame of masking CAShapeLayer - it would move the hole bot also hide some edges of the image. So the only way is to change its .path each time user moves finger and that is slow.
EDIT: matt's answer would work in some scenarios but not in my case: I am not displaying the whole image only a part of it defined by UIBezierPath. This part is most often oval (but can be rectangular or rounded rectangle) and it has "hole" cut in it. While the hole is mowing with users finger the displayed part/shape of the image does not change - it is static.
The ineficient solution that was in place so far wa:
Create UIBezierPath with boundary of displayed part of the image
Set 'even off fill rule' on it
Add UIBezierPath of the hole to it
Set it as path of CAShapeLayer with some opaque fill color
Use that CAShapeLayer as mask of the UIImageView
This procedure was repeated each time a user moved their finger. I cannot simply move the whole mask layer as that would also change the part of the image being displayed. I what it to stay static and move only the hole in it.
it would move the hole bot also hide some edges of the image
Well, I don't agree. Moving the mask is exactly the way to do this. I don't see why you think there's a problem with that. Perhaps the issue is merely that you have not made the mask layer big enough. It does not have to be the same size as the layer it is masking. In this case, it needs to be about 9 times the size of the masked layer (3 horizontal and 3 vertical), so that it will continue to cover the masked the layer no matter how far in any direction the user slides it.

Spritekit silhouette effect when passing in front of object

I'm working on a sprite kit game and I'm trying to create a particular silhouette lighting effect whenever objects pass in front of a particular object (in this case a red sun). I want anything in front of it to appear black, and everything else to appear as normal (so if an object is partially in front, only that part should be black).
But I'm not sure how to do it in an efficient way. I've tried playing around with different SKBlendModes but so far haven't had much success. The major challenge seems to be achieving the effect whilst preserving the colour of the sun behind.
I'm not sure if it's possible to achieve this with the existing SKBlendModes, or if something else will be required.
I've attached a diagram to illustrate what I'm going for and an image of the current best fit.
You can create the silhouette effect with an SKCropNode, a mask node, and a background node. An SKCropNode selectively mask pixels of the sprite nodes in its node tree. Here, it will provide the silhouette effect by hiding/revealing portions of a black circle.
First, create the following objects:
A shape node (yellow circle) with its zPosition set to -1
A sprite node (black circle) with the same size as the yellow one
A crop node (SKCropNode) and a mask node (SKNode)
Next,
Add the yellow circle at the center of the scene
Add the black sprite as a child of the crop node
Assign the mask node to the maskNode property of the crop node
Add the crop node at the center of the scene
Since the mask node currently has no children, the black circle will be completely hidden and the entire yellow circle beneath it will be visible. As we add sprites to the mask node, the pixels of the black circle that intersect with the sprite will be unmasked (shown in black), producing the silhouette effect.
All that's left is to add a "presentation" node that will be displayed when the mask node's sprite is outside of the black circle. The presentation node will mirror the mask node's sprite's position and rotation. This should be done in didSimulatePhysics to ensure that the presentation and mask-node sprites are synchronized after the physics and actions have been updated.
But wait...if the presentation node moves over the yellow circle, won't it eclipse the Sun? Not if we set its presentation node's zPosition to -2.
The following shows an implementation of the above:
This problem was interesting to me, so I came up with a simple solution. It's not perfect nor does it scale very well, but the basics fulfill your need I believe and it may point others in the right direction.
I don't use any special SKBlendMode. Instead, I am using a duplicate object for the object which moves in front of the sun. This duplicate object is cropped using an SKCropNode with a duplicate of the sun as the maskNode. So, my node tree is as follows:
SKSpriteNode (sun) (the white sun)
SKSpriteNode (object1) (the rotating purple square with alpha 0.25)
SKCropNode
maskNode: SKSpriteNode (sunDuplicate = [sun copy])
SKSpriteNode (object1duplicate, same size as object1 but with [SKColor blackColor])
Inside the update method, align the duplicate with the original to ensure animation is properly forwarded.
- (void)update:(CFTimeInterval)currentTime {
self.object1duplicate.position = self.object1.position;
self.object1duplicate.zRotation = self.object1.zRotation;
}
As I said, this doesn't scale very well since you'll manually have to add duplicate objects and keep track of them for each object moving in front of the sun object. Perhaps SKShader can be of more elegant use.

UIimageview fit to round shape

I have an UIImageview that contains a circle (The obstacle) and then another UIImageview that contains another image (my character). When my circle hits my character the game ends.
My problem occurs when the game ends on the character touching the UIImageview box that my circle is within, rather than the circle inside the UIImageview box.
The solutions I can think of are:
Make the UIImageview rounded to fit my circle.
Somehow detect a collision between my characters pixels and the circles pixels rather than the UIImageviews.
Help and ideas would be really appreciated. I am a beginner with xcode.
Thanks!
Couple of different techniques:
1)UIView#layer.cornerRadius - Super simple to implement, just set that one property. But really bad for scrolling elements like table views.
2)UIImageView as a mask - Also easy to implement. Basically make a square image with a transparent circle in the middle and slap it on top of your view with a new UIImageView. If your circle design has some reflections or styling, this might make your life easier.
3)Custom drawing - Make a UIView subclass and override drawRect to draw your image and clip it to a circular path.
Hope that helps!
EDIT:
You can read this answers.
1)Fill an UIBezierPath with a UIImage
2)iOS: Inverse UIBezierPath (bezierPathWithOvalInRect)
3)How to mask a square image into an image with round corners in the iPhone SDK?

ccDraw. Fill screen everywhere except on sprite

So I am trying to get a very basic "flashlight"-style thing going in one of my games.
The way I was getting it to work, was having a layer on top of my game screen, and this layer would draw a black rectangle with ~ 80% opacity, creating the look of darkness on top of my game scene.
ccDrawSolidRect(ccp(0,0), ccp(480,320), ccc4f(0, 0, 0, 0.8));
What I want to do is draw this rectangle EVERYWHERE on the screen, except for around a cone of vision that will represent the "light source".
What this would create would be a dark overlay on top of everything except for the light, giving it the illusion of a torch/light/flashlight.
The only way I can foresee this happening is by using ccDrawSolidPoly(), but since the position of the light source changes, so would the vertices for the poly.
Any suggestions on how to achieve this would be great.
You can use ccDrawSolidPoly() and avoid having to manually update vertices. For this you can create a new subclass of CCNode representing your light object, and do your custom shape drawing in its -(void)draw method.
The ccDraw...() functions will draw relative to the local sprite coordinates, so you can then move and rotate your new sprite to suit your needs and cocos2d will do the vertices transformations for you.
Update: I found out that you might be better off subclassing CCDrawNode instead of CCNode, as it has some facilities for raw OpenGL drawing (OpenGL's vertexArrayBuffer and vertexBufferObject internal variables and a buffer for vertices, their colors and their texCoords). If your stuff is very simple, maybe subclassing the plain CCNode is enough.
Could a png be used instead as a mask, as the layer above
Like that binocular vision you sometimes see in cartoons?
Or a filter similar to a photoshop mask that darkens as it grows outwardly to wards the edge of the screen
Just a thought anyway...
A picture of more of what your trying to explain might be good too

Resources