What do you recommend me if I have two layers (which are added to a parallaxNode) and on each layers I've added sprites which I want to restrict the order that the player won't be able to remove sprite5 until it removes first the previous ones: sprite1, sprite2, sprite3 and sprite4 and so one.
I'm using Juan's example for dynamically touch detection
What will be the dynamical option for this?
UPDATE:
if([sprite tag] == tag_collection_1 && [sprite GetCanTrack]) {
//Set others to NO & call remove sprite method
[[TSprite FindByTag:tag_collection_number] SetCanTrack:NO];
[self removeSpriteMethod:touchLocation];
} else if ([sprite tag] == tag_collection_number && [sprite GetCanTrack]) {
// and so on
}
Use a fifo stack implementation. If you want to remove the sprite, you first check if it's at the bottom of the stack and when you do remove it, you pop it from the stack as well. Practically you will have an NSMutableArray and look at the first item if the object is in that position before you remove it. If you have added 1,2,3,4,5 in that order and want only to be able to remove them in the same order you check if the object you are trying to remove is at index 0 in the array first.
Related
I am trying to make a game which allows moving objects by snapping them on the grid, I already figured out to snape them to grid but there is one thing little problem, I want to check if there is already a game object placed on that same grid so that I won't let the dragging game object snap to that same spot but the thing is that I have a different game object shapes.
see for yourself
Click to see the image
how can I achieve that?
Since you're on a square grid I think the best way to do this is with Physics2D.Boxcast(). Basically what you're doing is casting a box at the snap vector before moving the game object.
So in your code before you move the game object to the snap location:
RaycastHit2D hit = Physics2D.BoxCast(snapTo, boxSize, 0.0f, Vector2.zero);
if (hit == null)
{
// We're clear to move
}
else
{
// Something is in the way
}
Where snapTo is the Vector2 of the location you're going to snap to and boxSize is a Vector2 equal to the size of one grid position (you might need to play around with this a bit). The last two arguments, 0.0f refers to the angle of the box, which we don't need so just set it to zero and Vector2.zero is the direction of the cast, but we're casting in one spot so this also doesn't matter.
I'm assuming that only one game object can occupy the space at once, so there will only ever be one hit. If there's a chance for more than one you can change it to RaycastHit2D[] hits and Physics2D.BoxCastAll then check if hits.Length is greater than 0.
I had some troubles with Physics2D.Boxcast() , so instead i used Physics2D.OverlapBox() and it is working just fine.
isColl = Physics2D.OverlapBox(ObjectToMove.position, size, 0f, layerM);
if (isColl == true)
{
// Something is in the way
}
else
{
//Clear to go
}
Im trying to see when my circleGroup Class Object has left the screen
(am pretty new at this so any suggestions welcome!)
including any other way to remove the class once it is off screen
circleGroup Class contains a blank SKSpriteNode, and 8 other sprites are grouped around the blank SKSpriteNode as children (these have physics),
Gamelayer:
Always logs (0,0)
NSLog(#"_mycircleGroup.position.y #%f",_mycircleGroup.position.y);
//outputs myArc.position.y #0.000000
which means I can't check when Class is off screen
if (_mycircleGroup.position.y < 0)
{
NSLog(#"_mycircleGroup off screen");
//[_mycircleGroup removeFromParent];
//[self myMethod];
}
Any ideas how I might read position?
with thanks
:)
Solution,
I needed to be logging the parent node inside of the class
so in this case I have a class and in it is a parent sprite which i need to track (Since it seems like nodes with physics don't track)
if (self.myCircleClass.parentSpriteThatEveryThingIsAddedTo.position.y < 0)
{
NSLog(#"my arc off screen");
//[twoSpritesWithParticlesBridge removeFromParent];
//[self addStaticLinkedSpriteWithParticles];
}
As above with thanks to WangYudong for jogging my logic :P
Solution, I needed to be logging the parent node inside of the Class so in this case I have a class and in it is a parent sprite which I need to track (Since it seems like nodes with physics don't track, so I couldn't track te entire object, just the object without physics...)
if (self.myCircleClass.parentSpriteThatAllOtherSpritesParentedTo.position.y < 0)
{
NSLog(#"my arc off screen");
//[twoSpritesWithParticlesBridge removeFromParent];
//[self addStaticLinkedSpriteWithParticles];
}
Take everything with a pinch of salt, non definite and completely questionable! (since I'm new at coding), but hope it helps someone :)
For a simple game, I have 4 different platforms (all on one spritesheet). I initially add 5 of each to a CCSpriteBatchNode, and set them all as not visible. When I set my platforms I want to take a platform of a certain type from my CCSpriteBatchNode and change it to make it visible and position it.
I am having trouble finding platforms of a specific type that aren't visible. Or vice-versa?
I know you can use [batchnode getchildbytag:tag] but as far as I know that only returns one sprite. Is there any way I can put pointers to each platform of a specific type into an array, so that I can iterate through the array and find all the not visible sprites?
Thanks!
As suggested by Drama, you will have no choice than to 'iterate' the children. As for identifying which sprite corresponds to which platform, a few ways exist. A simple one would be to use the 'tag' property of the sprite -- assuming you do not use it for any other purpose.
// some constants
static int _tagForIcyPlatform = 101;
static int _tagForRedHotPlatform = 102;
... etc
// where you create the platforms
CCSptiteBatchNode *platforms= [CCSpriteBatchNode batchNodeWithFile:#"mapItems_playObjects.pvr.gz"];
CCSprite *sp = [CCSprite striteWithSpriteFrameName:#"platform_icy.png"];
sp.tag = _tagForIcyPlatform;
[platforms addChild:sp];
sp = [CCSprite striteWithSpriteFrameName:#"platform_redHot.png"];
sp.tag = _tagForRedNotPlatform;
[platforms addChild:sp];
// ... etc
// where you want to change properties of
-(void) setVisibilityOf:(int) aPlatformTag to:(BOOL) aVisibility {
for (CCNode *child in platforms.children) {
if (child.tag != aPlatformTag) continue;
child.visible = aVisibility;
}
}
once again, this works if you are not using tags of platform's children for another purpose. If you need the tags for some other purpose, consider using an NSMutableArray in the class, one per platform type, and store in that array the pointer to your sprites of the appropriate type.
There's not a super straightforward way to do that. You'll need to iterate through the children and inspect each child individually.
For coding efficiency, consider adding a category to CCSpriteBatchNode that performs this function for you. That way you can easily replicate it as needed.
i was just wondering if someone could explain this code for me so i can actually learn from it. I am trying to make my app have a scroller that scrolls left to right with loads of pictures (from internet) but the thing is, it must have lazy loading. so i did some tutorials and figured out how to do it but i truly don't understand it. So i was hoping some kind soul would explain how to lazy load step by step
This is the code i had learned from the tutorials:
-(void)scrollViewDidScroll:(UIScrollView *)myScrollView {
/**
* calculate the current page that is shown
* you can also use myScrollview.frame.size.height if your image is the exact size of your scrollview
*/
int currentPage = (myScrollView.contentOffset.y / currentImageSize.height);
// display the image and maybe +/-1 for a smoother scrolling
// but be sure to check if the image already exists, you can do this very easily using tags
if ( [myScrollView viewWithTag:(currentPage +1)] ) {
return;
}
else {
// view is missing, create it and set its tag to currentPage+1
}
/**
* using your paging numbers as tag, you can also clean the UIScrollView
* from no longer needed views to get your memory back
* remove all image views except -1 and +1 of the currently drawn page
*/
for ( int i = 0; i < currentPages; i++ ) {
if ( (i < (currentPage-1) || i > (currentPage+1)) && [myScrollView viewWithTag:(i+1)] ) {
[[myScrollView viewWithTag:(i+1)] removeFromSuperview];
}
}
}
About Lazy loading on scrollView, I would greatly advised to use UITableView instead. Apple did a great job with performance on this component.
You can have them horizontal (see this EasyTableView code, it works great) and stop the page mode if you want a continuous scroll (pagingEnabled = NO;) so you'll be able to get the behavior you are looking for.
Lazy loading is basically fetching large pieces of data (lets say images in this example) only when you need them. In your code, you have a delegate method that is called when you scroll a UIScrollView.
The -(void)scrollViewDidScroll:(UIScrollView *)myScrollView function decides when to actually get data. So as your scrolling, you find out where you are in the scroll view (say you have 10 images you want to load-- you want to know if the screen is currently showing image number 1, 2, 3, etc.). This is what the currentPage integer holds.
Now that you know which page you're looking at, we want to actually fetch the image.
if ( [myScrollView viewWithTag:(currentPage +1)] ) {
return;
}
The code above checks if the image AFTER the image the person is currently looking at exists (hence the currentPage + 1). If it does, we've already fetched it and we quit the function. Otherwise:
else {
// view is missing, create it and set its tag to currentPage+1
}
Here, we lazy load the image. This is done, for example, by creating a new thread and downloading the image from a server. We do this while the view is not the currentPage because we don't want the image to "pop in" while the user is scrolling. The view to which we add the image gets a tag (UIView has a "tag" property); we set the tag to currentPage+1, which later allows us to index the view in case we need it.
Finally, we have:
/**
* using your paging numbers as tag, you can also clean the UIScrollView
* from no longer needed views to get your memory back
* remove all image views except -1 and +1 of the currently drawn page
*/
for ( int i = 0; i < currentPages; i++ ) {
if ( (i < (currentPage-1) || i > (currentPage+1)) && [myScrollView viewWithTag:(i+1)] ) {
[[myScrollView viewWithTag:(i+1)] removeFromSuperview];
}
}
Here, we use our currentPage variable and iterate through all our views by indexing them by the tag we set. If the tag is not one off from the currentPage (remember, we don't want any pop in!) we remove it from the scrollview and free some memory up.
Hope that helped.
Perhaps this will help you.
Downloads the Asynchronous ImageView files from here https://github.com/nicklockwood/AsyncImageView/ and include them into your project.
Drag the ImageView on xib file and change it's class to AsynchronousImageView rather than UIImageView
Write this in you .h file
IBOutlet AsynchronousImageView *_artworkImg;
Write this in your .m file
[_artworkImg loadImageFromURLString:#"Your Image Url"];
I'm trying to make a simple game and I am currently trying to make an arrow shoot out.
So far I have two functions,
-(void)ccTouchesBegan
Touches began does some math and gets a vector from the initial shooting point of arrow and the thumbpress, then passes this data into another function:
-(void)shatArrow:(CGPoint)cl:(CGPoint)nv{
}
What I want is for the shatArrow function to call a ccTime function that runs solely for the purpose of making the arrow move, and once the arrow is done with it's projection, the ccTime function will stop, and can be called again later when needed.
How would I go about this?
Schedule the update selector (ie in the init method of your class):
[self scheduleUpdate];
Then implement the update method:
-(void) update:(ccTime)delta
{
if (isArrowMoving)
{
// arrow move code here
if (arrow movement should end)
{
isArrowMoving = NO;
}
}
}
You can keep the update method running, unless you have hundreds of arrows it won't affect performance.
-(void) shootArrow:(CGPoint)cl:(CGPoint)nv
{
isArrowMoving = YES;
// other arrow movement init code here
}
Btw, it's "shoot, shot, shot" and not "shoot, shot, shat" or something like that. (I suppose you didn't ask for a #LinguisticsOverflow answer) ;)