Is it possible to have a repeating object in Tiled/Sprite Kit? - ios

I'm currently building a game using Xcode, sprite kit and now tiled. The game is simple, a person jumping from 1 block to another, but if they hit the side it will be game over. Now is their anyway through tiled to create a block for the person to jump on. And through out the game to keep repeating and coming on for the person to jump on, I would like the object to have different heights and widths? Please Help?!

What you can go for is creating a reuse mechanism that will reuse nodes instead of creating and destroying them. A mechanism well-known from UITableView or UICollectionView.
You would implement a method:
- (SKNode *)dequeueReusableNode;
that gets reused SKNode from some storage, say, NSMutableArray (grabs first object from array, then deletes it from array and returns it). If array is empty, method returns nil.
Then you check if you got a node from the dequeueReusableNode method, if it's nil, you create a new instance of a node. If it's not nil, you configure it with your data.
This goes for every visible node that should be reused.
Nodes that went completely off-screen are sent to reuseQueue – all their property values return to default state, and then node gets added to the end of the NSMutableArray that is the reuseQueue.

Related

Return the owner of a variable - Swift

So I have objects that in turn have sprites associated to them. a snippet of my Object class:
import SpriteKit
class Block {
var sprite : ColourSprite
}
So as you can see, it has a variable that is in fact a SKSprite (ColourSprite is my custom class that inherits from SKSpriteNode).
Now, at some points during the game, these sprites are deleted (i.e sprite.removeFromParent()), but the objects are obviously still somewhere.
I want to be able to send the objects to garbage collection once their sprites are gone. I am thinking that I can do something like sprite.getOwner() but I can't seem to find it. Is this possible?
The only other option I can think of is to manually check all objects and check each one's sprite but I feel that is long and wasteful.
You can check whether the Blocks are still in memory by using Xcode 8.3's new debug panel.
Just after you remove your sprites pause the program and go to that panel. See if there is any Block instances in the left panel. If there is, click on it to check what is retaining it.
If for example your GameScene is retaining the Block, you go to your GameScene and find the property. Then you can just set that to nil after you remove your sprite.

Detecting references for a Swift object allocated by a storyboard

I am developing a game for iOS using Swift. The game is played in rounds, and when a round is over, it is no longer needed. So unlike conventional applications where a storyboard scene may stick around when someone navigates away from it, I want the scene for the round to be destroyed when the game navigates to the scene following the round.
I am pretty confident I have figured out a way to do this because I’m instantiating certain objects in the scene and I have verified that the deinit method for these objects gets call when the round ends and navigation to the next scene occurs. The problem is that for one of the objects, the deinit method is not being called, and I have not been able to figure out why. The storyboard scene should be the only thing referencing the object, and searching through to source code has not revealed any other usages. It seems like something beside the storyboard scene somehow has a reference to the object and keeps it alive when the scene goes away.
I have verified the object is being created by setting a breakpoint in its init method, and that breakpoint gets hit when starting the round.
I’ve tried using the Allocations instrument to track what might be referencing the object. However when I run the game and finish the round. I can find no evidence that the Allocation instrument ever saw the object at all. I suspect the instrument may not track objects that are created by a storyboard scene, especially since I can not find traces of the other storyboard objects that do get deleted with the storyboard.
What can be done to determine why this object seems to survive past the lifetime of the storyboard scene that should own it?
I think found out why the object was not being destroyed. In it's initializer it was applying a closure to something else. The closure contained a reference to a member of the object, and so I think the closure was capturing self strongly even though self was never explicitly needed for things to compile successfully. This might be a bug with the Swift compiler; it could have emitted a warning or error about this; it would have been easier the find and/or prevent the problem. Anyway I changed the closure so that it captures the object's member as unowned and now the object appears to get destroyed.

Undoing last drawn Polyline

I have been working on a polyline overlay and have been helped very well when I was stuck, I am hoping for some more assistance again.
In my project I am drawing polylines on a map from touches began to touches moved. the coordinates of where my finger is dragged is added to my array and displayed.
When I want to clear my lines i simply empty the array, this is fine
However, If i want to remove/undo the last line drawn. I was under the impression that I could just minus the last value from my array, but while thinking more deeply I realized that I may have a problem. Each element in the array is a coordinate where my finger last touched.
I havent tried this yet, but I am imagining if I only minus the last value of the array, I am going to spend a long time "erasing" a line which I drew.
I was looking for a method, by which when i press "Undo" it erases the entire line i drew. Even if that line extends from North America to England.
The OP wishes to be able to undo the last line that was drawn. The problem he imagines is that removing a single element from the array would visually only remove a part of the line drawn by the user.
What he wishes to do is to remove all the elements within the array that make up the line.
I haven't done a lot on drawing but my solution to your problem should work.
Do the following, create an enumerated data type that would create three possible states for each coordinate drawn to the screen/added to the array.
This data type would look something like this:
typedef NS_ENUM(NSInteger, PKLinePointState) {
PKLinePointStart,
PKLinePointMiddle,
PKLinePointEnd
};
The idea here is that you will use this data type to determine which elements in your array are the starting points and which elements in your array are the ending points. This way you can make determine the lines in your array, and so therefor be able to determine how many elements to delete until you hit a coordinate that has status of PKLinePointStart.
You don't want to store just coordinates in your array, instead you want to store a data model which will hold more information so that you can do the sexy things you wish to accomplish.
The first data model will be used to store the start and ending coordinates and elements within the array. This will make it easier work with your coordinates. This is what it would look like:
LinePointModel.h
typedef NS_ENUM(NSInteger, PKLinePointState) {
PKLinePointStart,
PKLinePointMiddle,
PKLinePointEnd
};
#interface LinePointModel : NSObject
#property (assign) CGPoint linePointCoordinate;
#property (assign) PKLinePointState linePointState;
#end
//you may want to create a custom initialiser so that the coordinate and state are initialised straight away.
//It would look something like this -(instanceType)initWithLinePointCoordinate:(CGPoint)coordinate andLinePointState:(PKLinePointState)linePointstate;
LinePointModel.m
//I'll let you complete the initialiser method in the implementation file.
Now that you've created your data model that will store your coordinates properly in the coordinates array, here's how I would add them to the array.
The logic Phase 1:
When the user taps on a screen - the touchesBegan method gets called, you would want to create an instance of the LinePointModel and have its coordinate value set to the first coordinate the user taps on the screen and would set the state to PKLinePointStart which would mark the beginning of the line. Add this element to the array.
Then, when the user drags across the screen, you will receive multiple coordinates from the touchesMoved. Here you will create an instance of the same data model again setting the coordinate but this time the state will be stored as PKLinePointMiddle, we dont really care about these points, since we wont be checking against this state, but its still good to give it a value so that we know that any elements within the array that have this state only servers to form a point, points which eventually make a whole line. Here these instances will keep getting added to the array as many times as it needs until the user finally stops dragging - drawing the current line - on the screen.
Soon as the the touchesEnded method gets called - signifying the end of the line - the user lifting up his finger, this is where you create your last instance of the the data model, set the coordinate accordingly, and finally the state would be the PKLinePointEnd state. Again, you would add this instance of within the array too.
Now you have a meaningful custom array that keeps track of all the coordinates but lets you know which element has the starting state, midde and ending state.
Every starting state is coupled with the ending state with as many middle elements needed to make up the line.
If you want to stop here, you simply run the for loop, and determine the latest start and end elements added within your array. :)
The logic Phase 2 - Improving the algorithm:
Now you dont wan't to be looping through thousands of elements in an array just to determine how far in your array you have to go back to just to delete a line, that would be inefficient. This is where your second data model will be useful. This second data model will keep track of your lines and store which elements in your array make up its line by storing the start and end index or even better, store the array of the coordinates which is what we will do.
LineArrayModel.h
#interface LineArrayModel : NSObject
#property (nonatomic, retain) NSMutableArray *arrayOfLinePoints; //What matters.
//#property (assign) int lineNumber;
//#property (assign) CGFloat lineThickness;
//#property (strong, nonatomic) UIColor *lineColor;
#end
Using this data model, you would then create a temporary array whenever a user draws a line on the screen, and as soon as they are done drawing a line, you would grab the array and store it in an instance of LineArrayModel; and it's this instance that you would use to store in a new array called, myLinesArray. This is the array that you would then use to draw your lines on your screen.
Then to simply undo a line you just remove the last instance of LineArrayModel in the array that stores all your lines, and then simply redraw your lines if necessary.
Let me know how you get on.

Core Data Insert on Child Context creates extra instances

I am using Core Data in a multi-threaded way. It's working fine so far and I'm quite happy and have patted myself on the back a few times. Except one small thing.
I have for example a data model Hand. I have another model: Finger.
A Hand as a one-to-many relationship with Finger
in my awakeFromInsert method on Hand, I have:
- (void)awakeFromInsert
{
[super awakeFromInsert];
if(self.fingers.count == 0)
{
// creates instances in current context. sets their hand to this one.
[self addFingersToHand];
}
}
Here's the problem. If I create this hand on the background 'working' context, then save that and its parent contexts, it would appear that a Hand is inserted on the parent context, some fingers are also created, THEN the fingers that were created on the child context are merged, leaving 10 fingers on one hand. O_O
Did this make sense and what have I done incorrectly? I want to make sure that if I create a Hand it will have 5 and only 5 fingers on one hand.
Strange. When you push up a Hand with 5 fingers to the parent context via save:, I am not even sure awakeFromInsert should be called. But even if it is called, self.fingers.count should evaluate to 5, not 0. Did you check with breakpoints what exactly is happening?
Maybe you need to check again where exactly you are inserting stuff.

How do you remove elements when changing scenes?

In a space shooter, I add enemies through a separate LUA file. These enemies have timers that create shots. When changing scenes, I want to remove all instances of enemies, stop their timers and remove all shots.
I have been able to remove the individual enemies by adding them to the scene's display group, but I can't do that with the timers or the shots.
How do I do this?
While creating a timer, just do as follows:
declare the timer at the top of you scene to get it a global scope on the scene, as:
local timer_1
Then use the timer as:
timer_1 = timer.performWithDelay(1000,myFunction,-1)
Then you can stop it as:
if(timer_1)then
timer.cancel(timer_1)
end
Keep coding.................. :)
What i would do (and that's how i handle this kind of issue in my game actually) is create a table to keep track of the enemies, then make it so enemies are object oriented classes owning both the timers and the shots.
Example:
You could create an 'enemy' class (local myEnemy) which has an internal timer (myEnemy.timerID) and an internal table of shots fired (myEnemy.shots).
Even better, add a 'destroy' method to the enemy (myEnemy.destroy()) that stops the timers and destroys the shot, then when you change scene you just have to iterate through your table, call the destroy method on each enemy, and timers / shots will be destroyed automatically :)
I don't know if your code is object oriented already but in this kind of case it makes things a lot easier :)
Let me know if you need anymore info
Cheers

Resources