How to I call SKTileSet init(named:) in objective C? - swift

I was able to create an SKTileSet on xcode but it seems like I am having a difficult time being able to init an SKTileSet with passing through a name like here:
https://developer.apple.com/documentation/spritekit/sktileset/1643819-init
This would be great to save a lot of time programmatically creating the whole set, group, rules and etc...
Thank you!

You have to use the name inside the .sks file for tileSetNamed
With this setup for example:
You should use:
Objective-C
SKTileSet *tileSet = [SKTileSet tileSetNamed:#"Sample Tile Set"];
or Swift 5
let tileSet = SKTileSet(named: "Sample Tile Set")

Related

cant change class resource at runtime godot

im making a project for listening to episodes of a podcast as if they're real cassettes. The idea is that some info about the episode shown on the cassette model + it's audio file are stored in a class, then before putting the cassette in the player, being able to change the class resource the cassette takes from with buttons. My problem is that it doesnt let me change it on runtime, just set it on the ready function.
The way the cassette script loads the data:
onready var data = preload("res://MAGs/Season1/Ep1.tres")
The way im trying to change it:
func _ep_select():
data = load(<different cassette's data>)
If its impossible to change it on runtime, what should i use instead of this?

SWIFT: Load different reality Scenes via Variable

So, i am trying to load different Scenes made in RealityComposer, depending on a variable.
What worked so far:
let SceneAnchor = try! Experience1.loadScene()
arView.scene.anchors.append(SceneAnchor)
return arView
Now i looked into apples Documentation and saw the possibility of:
if let anchor = try? Entity.loadAnchor(named: "Scene") {
arView.scene.addAnchor(anchor)
}
where i thought i could just change "Scene" to "Scene(myVar)"
But once i have more than one scene in my file the first solution doesnt work anymore
and the second one doesnt work as well.
What am i missing?
I also looked into working with filenames and was able to make an array of all my .reality Files and Store them in an Array, so i thought i could recall that via the index, but
arrayName[1].loadScene() doesnt seem to work either, eventhough i can print the filenames to console.
Thanks in advance :)
The fact is that Reality Composer creates a separate static method for each scene load. The name of such method is load+scene name. So, if you have 2 scenes in your Exprerience.xcproject with the names Scene and Scene1, then you have 2 static methods
let scene = Experience.loadScene()
let scene1 = Experience.loadScene1()
Unfortunately it is not possible to use the scene name as a parameter, so, you need to use the switch statement in your app to select the appropriate method.

Swift/SpriteKit - Any way to pool/cache SKReferenceNodes?

Is there a way to pool/cache SKReferenceNodes in SpriteKit using Swift?
I am creating a game using xCodes visual level editor. I am creating different .sks files with the visual level editor that I am than calling in code when I need to. I am calling them in code because I am using them to create random levels or obstacles so I don't need all of them added to the scene at once.
At the moment I am doing it like this
I create a convince init method for SKReferenceNodes to init them with URLs. I am doing this because there is some sort of bug calling SKReferenceNodes by file name directly (https://forums.developer.apple.com/thread/44090).
Using such an extension makes makes the code a bit cleaner.
extension SKReferenceNode {
convenience init(roomName: String) {
let path: String
if let validPath = NSBundle.mainBundle().pathForResource(roomName, ofType: "sks") {
path = validPath
} else {
path = NSBundle.mainBundle().pathForResource("RoomTemplate", ofType: "sks")! // use empty roomTemplate as backup so force unwrap
}
self.init(URL: NSURL(fileURLWithPath: path))
}
}
and than in my scenes I can create them and add them like so (about every 10 seconds)
let room = SKReferenceNode(roomName: "Room1") // will cause lag without GCD
room.position = ...
addChild(room)
This works ok but I am getting some lag/stutter when creating these. So I am using GCD to reduce this to basically no stutter. It works well but I am wondering if I can preload all .sks files first.
I tried using arrays to do this but I am getting crashes and it just doesn't seem to work (I also get a message already adding node that has a parent).
I was trying to preload them like so at app launch
let allRooms = [SKReferenceNode]()
for i in 0...3 {
let room = SKReferenceNode(roomName: "Room\(i)")
allRooms.append(room)
}
and than use the array when I need too. This doesn't work however and I am getting a crash when trying to use code like this
let room = allRooms[0]
room.position =
addChild(room) // causes error/crash -> node already has parent
Has anyone done something similar? Is there another way I can pool/cache those reference nodes?. Am i missing something here?
Speaking about the SKReferenceNode preload, I think the policy to be followed is to load your object, find what kind they are and use the official preloading methods available in Sprite-Kit:
SKTextureAtlas.preloadTextureAtlases(_:withCompletionHandler:)
SKTexture.preloadTextures(_:withCompletionHandler:)
To avoid this kind of error you should create separate instances of the nodes.
Try to doing this:
let room = allRooms[0]
room.position = ...
room.removeFromParent()
addChild(room)
I just figured it out, I was just being an idiot.
Using arrays like I wanted to is fine, the problem I had which caused the crash was the following.
When the game scene first loads I am adding 3 rooms but when testing with the arrays I kept adding the same room
let room = allRooms[0]
instead of using a randomiser.
This obviously meant I was adding the same instance multiple times, hence the crash.
With a randomiser, that doesn't repeat the same room, this does not happen.
Furthermore I make sure to remove the room from the scene when I no longer need it. I have a node in the rooms (roomRemover) which fires a method to remove/create a new room once it comes into contact with the player.
This would be the code in DidBeginContact.
guard let roomToRemove = secondBody?.node.parent?.parent?.parent?.parent else { return }
// secondBody is the roomRemover node which is a child of the SKReferenceNode.
// If I want to remove the whole SKReferenceNode I need to add .parent 4 times.
// Not exactly sure why 4 times but it works
for room in allRooms {
if room == roomToRemove {
room.removeFromParent()
}
}
loadRandomRoom()
Hope this helps someone trying to do the same.

Trouble with SKEmitterNode - doesn't display colors created in sks file

I have the function below to show an emitter. It is supposed to pick which asks file to use for the emitter based upon the color passed into the function. The sks files have been created and named based upon their colors and they display the proper coloring in Xcode.
However when run on the simulator or the device, it does not appear that the coloring from the sks file is honored. No matter what color is passed in, the emitter shows the same particle colors. BTW this is a spark based emitter.
Any ideas what I may be doing wrong?
func showEmitter(theColor:String){
var ourEmitterName:String?
switch(theColor) {
case "black","white":
ourEmitterName = "blackwhiteemitter"
default:
ourEmitterName = "\(theColor)emitter"
}
let emitterPath = NSBundle.mainBundle().pathForResource(ourEmitterName, ofType: "sks")
let thisEmitter:SKEmitterNode = NSKeyedUnarchiver.unarchiveObjectWithFile(emitterPath!) as SKEmitterNode
thisEmitter.zPosition = SceneLevel.background.rawValue
self.addChild(thisEmitter)
}
Thanks for your help - Ken
I found the problem. In my emitters I had the Blend Mode set to 'Add'. After I changed it to 'Alpha' everything worked fine.
Not sure why that solved it, since I don't know to what was 'added' to what.

How to load Vuforia QCAR tracking file data during runtime in iOS

I am working on Augmented reality using Vuforia sdk, and i want to load 3d object on runtime, i want to fetch it from web-service and load it when i need that, So basically my question only is this how can we load any .h file on run time. First is this possible that we can load it on runtime and if possible then how can we do that.
If you have dynamic data, putting it into a .h file doesn't make sense. Headers are only useful while the program is being compiled, not at run time.
AFAIK vuforia just puts arrays of vertical, triangles, etc. into h file. So you don't need to load h file in runtime (and this is impossible, there is no h files when programm is running). Instead you need to get those arrays and give them to vuforia
just download that file from network, store it within application directories and load it like the sample data bundled with the app
NSString * pathToDownloadedFile; //should have path to your file
QCAR::DataSet *dataSet = nil;
QCAR::TrackerManager& trackerManager = QCAR::TrackerManager::getInstance();
QCAR::ImageTracker* imageTracker = static_cast<QCAR::ImageTracker*> (trackerManager.getTracker(QCAR::Tracker::IMAGE_TRACKER));
dataSet = imageTracker->createDataSet();
dataSet->load([pathToDownloadedFile cStringUsingEncoding:NSASCIIStringEncoding], QCAR::DataSet::STORAGE_ABSOLUTE);
imageTracker->activateDataSet(dataSet);