CGRectIntersectsRect with coordinates of object - objective-c

I wanted to ask if there is something similar to the Code CGRectIntersectsRect.
For eg:
There is an object, and a block. If the object lands on the top of the Block, it can stay on it. If the object hits the left,right or bottom side of the Block, it should smash against it and fall down.
My Code :
if(CGRectIntersectsRect(Object.frame, Block.frame)){
ObjectJump = 0;
}
But with that code, the object will stay even he jumps from the bottom to the top of the block. Can somebody help me ?

Assuming that the intersection is checked repeatedly, so you know at the start of the intersection, then what matters is how much of the object is above the block and how much is below. If above > below then it's on top.
Currently you check for intersection, but you can also get the intersection of the frames. Once you have that you can compare the heights of the intersection frame and the object frame. If the object frame height > 2 * the intersection frame height then the frames don't overlap much. Assuming that the object can't be inside the block already this is enough information. If the object hit the side of the block then the intersection frame height would be the same as the object frame height.

Related

UICollectionViewLayout with dynamic heights - but NOT using a flow layout

Say you have a UICollectionView with a normal custom UICollectionViewLayout.
So that is >>> NOT <<< a flow layout - it's a normal custom layout.
Custom layouts are trivial, in the prepare call you simply walk down the data and lay out each rectangle. So say it's a vertical scrolling collection...
override func prepare() {
cache = []
var y: CGFloat = 0
let k = collectionView?.numberOfItems(inSection: 0) ?? 0
// or indeed, just get that direct from your data
for i in 0 ..< k {
// say you have three cell types ...
let h = ... depending on the cell type, say 100, 200 or 300
let f = CGRect(
origin: CGPoint(x: 0, y: y ),
size: CGSize(width: screen width, height: h)
)
y += thatHeight
y += your gap between cells
cache.append( .. that one)
}
}
In the example the cell height is just fixed for each of the say three cell types - all no problem.
Handling dynamic cell heights if you are using a flow layout is well-explored and indeed relatively simple. (Example, also see many explanations on the www.)
However, what if you want dynamic cell heights with a (NON-flow) completely normal everyday UICollectionViewLayout?
Where's the estimatedItemSize ?
As far as I can tell, there is NO estimatedItemSize concept in UICollectionViewLayout?
So what the heck do you do?
You could naively just - in the code above - simply calculate the final heights of each cell one way or the other (so for example calculating the height of any text blocks, etc). But that seems perfectly inefficient: nothing at all of the collection view, can be drawn, until the entire 100s of cell sizes are calculated. You would not at all be using any of iOS's dynamic heights power and nothing would be just-in-time.
I guess, you could program an entire just-in-time system from scratch. (So, something like .. make the table size actually only 1, calculate manually that height, send it along to the collection view; calculate item 2 height, send that along, and so on.) But that's pretty lame.
Is there any way to achieve dynamic height cells with a custom UICollectionViewLayout - NOT a flow layout?
(Again, of course obviously you could just do it manually, so in the code above calculate all at once all 1000 heights, and you're done, but that would be pretty lame.)
Like I say above the first puzzle is, where the hell is the "estimated size" concept in (normal, non-flow) UICollectionViewLayout?
Just a warning: custom layouts are FAR from trivial, they may deserve a research paper on their own ;)
You can implement size estimation and dynamic sizing in your own layouts. Actually, estimated sizes are nothing special; rather, dynamic sizes are. Because custom layouts give you a total control of everything, however, this involves many steps. You will need to implement three methods in your layout subclass and one method in your cells.
First, you need to implement preferredLayoutAttributesFitting(_:) in your cells (or, more generally, reusable views subclass). Here you can use whatever calculations you want. Chances are that you will use auto layout with your cells: if so, you will need to add all cell's subviews to its contentView, constrain them to the edges and then call systemLayoutSizeFitting(_:withHorizontalFittingPriority:verticalFittingPriority:) within this "preferred attributes" method. For example, if you want your cell to resize vertically, while being constrained horizontally, you would write:
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
// Ensures that cell expands horizontally while adjusting itself vertically.
let preferredSize = systemLayoutSizeFitting(layoutAttributes.size, withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
layoutAttributes.size = preferredSize
return layoutAttributes
}
After the cell is asked for its preferred attributes, the shouldInvalidateLayout(forPreferredLayoutAttributes:withOriginalAttributes:) on the layout object will be called. What's important, you can't just simply type return true, since the system will reask the cell indefinitely. This is actually very clever, since many cells may react to each other's changes, so it's the layout who ultimately decides if it's done satisfying the cells' wishes. Usually, for resizing, you would write something like this:
override func shouldInvalidateLayout(forPreferredLayoutAttributes preferredAttributes: UICollectionViewLayoutAttributes, withOriginalAttributes originalAttributes: UICollectionViewLayoutAttributes) -> Bool {
if preferredAttributes.size.height.rounded() != originalAttributes.size.height.rounded() {
return true
}
return false
}
Just after that, invalidationContext(forPreferredLayoutAttributes:withOriginalAttributes:) will be called. You usually would want to customize the context class to store the information specific to your layout. One important, rather unintuitive, caveat though is that you should not call context.invalidateItems(at:) because this will cause the layout to invalidate only those items among the provided index paths that are actually visible. Just skip this method, so the layout will requery the visible rectangle.
However! You need to thoroughly think if you need to set contentOffsetAdjustment and contentSizeAdjustment: if something resizes, your collection view as a whole probably will shrink or expand. If you do not account for those, you will have jump-reloads when scrolling.
Lastly, invalidateLayout(with:) will be called. This is the step that's intended for you to actually adjust your sections/rows heights, move something that's been affected by the resizing cell etc. If you override, you will need to call super.
PS: This is really a hard topic, I just scratched the surface. You can look here how complicated it gets (but this repo is also a very rich learning tool).

change CAMetalLayer background color

My CAMetalLayer background color is black, even if i'm assigning new color as the backgroundColor property.
Am i missing something? Thanks!
Link to the original project :
https://github.com/audiokit/MetalParticles
This project takes a rather unconventional approach to clearing the drawable's texture each frame: it replaces the textures contents with an array of zeros that is the same size as the texture (width * height * 4). Subsequently, it encodes some compute work that actually draws the particles. This is almost certainly not the most efficient way to achieve this effect, but if you want to make the smallest change that could possibly work (as opposed to experimenting with making the code as efficient as possible), Just fill the blankBitmapRawData array with your desired clear color (near line 82 of ParticleLab.swift).
I have gone through your code and can not see a place where you are setting background Color.
The metal layer is added as a sublayer to it, so you have to set it explicitly.
Add this line at the end of your init method in ParticialLab class and see if it works.
self.backgroundColor = UIColor.redColor().CGColor
I found that self.isOpaque = false was needed on the layer.

How to get width/height of a movie clip in CreateJs?

In AS3.0 it is like:
mc.width and mc.height
In AS2.0 it is like:
mc._width and mc._height
What about createJs
mc.????
If the MC was generated by Flash then you can use either myMC.nominalBounds, which returns the first frame's bounds, or myMC.getBounds() which returns the current frame bounds. These values will represent the author-time dimensions, and will not reflect changes you made to the contents of the MC in code.
If the MC was not generated by Flash, then you can still call getBounds(), but it will not include bounds for Shape instances (unless you have set bounds on them with setBounds()).

How to detect if a button is in a desired area in Objective c

How can I detect if a button is in a desired area
I have used if( button.frame.orgin.x == area.framee.orgin.x){
if (button.frame.orgin.y == area.frame.orgin.y )};
The Problem with this code is that it is very exact so it is hard to match up the button with the label. So I would like to know how to detect if a button is inside a desired area. And how to make the area bigger than the button. Thanks In advance
Your best option is probably CGRectContainsRect() which would work something like:
if(CGRectContainsRect(someRect, button.frame))
{
//Button is in area.
}
To expand the rect you can use CGRectInset(), passing negative values to increase the frame size by that amount. This function will maintain the center of the original rect.
CGRect newRect = CGRectInset (smallRect, -10.0f, -10.0f);
You can read more about CGGeometry functions in the docs.
Use GCRectContainsRect(frame1, frame2); to see if an object is contained within another object. Or use CGRectIntersectsRect(frame1, frame2); to see if the rects overlap at all.

looping a sprite vertically objective C sprite builder

Note: for this I am using a program called spritebuilder, which allows me to create a game with less code than would normally be needed. If you know a solution that's just all code, then by all means feel free to share it :)
Also, for this question, I followed a tutorial at this link: Build Your Own Flappy Bird Clone. Just scroll down to the part that says: "Loop the Ground"
So here's my problem. Im currently working on a game, and I created a camera which scrolls vertically long with the character sprite i created, however i need a certain image to loop. When the image leaves the bottom part of the screen I would like it to loop around to the top of the screen, infinitely. For this i created two identical images (in this case its the bark of a tree). One will be on screen, while the other will be offscreen, so as the first image leaves the screen, the second will replace it (seamlessly). I created two objects for the images, and assigned them the name _ground1, and _ground2, and I also created an NSArray in which to store them in. (Please refer to the link above if it is somewhat confusing)
Here is the code that I have:
CCNode *_ground1;
CCNode *_ground2;
NSArray *_grounds;
for (CCNode *ground in _grounds) {
// get the world position of the ground
CGPoint groundWorldPosition = [_physicsNode convertToWorldSpace:ground.position];
// get the screen position of the ground
CGPoint groundScreenPosition = [self convertToNodeSpace:groundWorldPosition];
// if the left corner is one complete width off the screen, move it to the right
if (groundScreenPosition.y <(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
For some reason when I try this, it doesnt seem to work. what happens is that, the camera will travel vertically as it is meant to do, but the images do not loop. Once the two images leave the bottom of the screen, no new images replace them.
i also done this project as above tutorials. it work fine but you have some mistake to set variable in spritebuilder. in your above code replce code as and try it. you only put less than may be it issue.
if (groundScreenPosition.y <=(-1 * ground.contentSize.height)) {
ground.position = ccp(ground.position.x , ground.position.y + 2 * ground.contentSize.height);
}
You are using CCNode objects as _ground1and _ground2.
CCNode objects usually do not have a contentSize, they will return 0 unless you explicitly set them inSpriteBuilder`.
Make sure that you are using CCSprite objects in SpriteBuilder and in your code.
Also, as a friendly hint you should also consider refactoring (renaming) your sprites with more meaningful names for your use case like _treeBark1 and treeBark2 for example.