List all Materials in a SceneKit scene - iphone

I am trying to find a way of listing all the Material objects defined in a scene. Is this even possible, or do I have to traverse the node hierarchy?
Thanks

If the scene is loaded from a file, you can create a scene source (SCNSceneSource) for that file and get all the identifiers for all materials using:
NSArray *allMaterialIdentifiers = [yourSceneSource identifiersOfEntriesWithClass:[SCNMaterial class]];
From there you can either enumerate the identifiers and get the entry with that identifier or filter all entries to only fetch the ones who's identifier is in the list of material identifiers.

Related

pygame-create multiple different instances of sprites [duplicate]

I'm having trouble with getting new sprites to be added. I'm looking for something along the lines of:
def duplicate(sprites):
for d in sprites:
if d.energy >= d.max_energy * 0.9:
d.energy = d.energy / 2
new_d = d.duplicate()
so if 1 sprite had its 'energy' above 90% of its 'max_energy', its energy would be cut in half and now there would be a second sprite that was identical to the first. I'm not sure how to pull that off though.
In general, you need to implement the duplicate method and construct a new instance of the Sprite object in the method.
Another solution is to use the Python copy module. deepcopy can create a deep copy of an object. Unfortunately this cannot be used for pygame.sprite.Sprite objects, as theimage attribute is a pygame.Surface, which cannot be copied deeply. Therefore, a deepcopy of a Sprite will cause an error.
Unless you have nor any other attribute that needs to be copied deeply, you can make a shallow copy of the Sprite. The rect attribute is a pygame.Rect object. The copy of the Sprite needs its own rectangle, so you have to generate a new rectangle instance. Fortunately a pygame.Rect object can be copied by pygame.Rect.copy:
import copy
new_d = copy.copy(d)
new_d.rect = d.rect.copy()

Subclass of SKSpriteNode in .sks file

I'm using SpriteKit .sks file Can I make a sprite in .sks into an instance of subclass of SKSpriteNode?
This is the init method in my subclass:
init(imageNamed: String) {
let blockTexture = SKTexture(imageNamed: imageNamed)
super.init(texture: blockTexture, color: nil, size: blockTexture.size())
}
In GameScene.swift I can create an instance like this:
var myObj = Block(imageNamed: "Block")
My question is how can I relate this instance with .sks file?
I tried this line of code but it doesn't work.
myObj = childNodeWithName("block1") as Block
Any help?
Thanks.
There are a couple of issues here to address...
How .sks loading works
When you load a .sks file, SpriteKit instantiates everything within using NSKeyedUnarchiver. This means that all the nodes inside are loaded as whatever base classes they were specified as by Xcode when it created the .sks file — SKSpriteNode for sprites with texture art, SKLabelNode for text, SKFieldNode for physics fields, etc. And Xcode doesn't currently provide an option for setting custom classes for the nodes inside a .sks file.
(The one exception for this is changing the runtime class of the scene itself — the top level container for everything in the .sks file. And that's only because of the custom SKNode.unarchiveFromFile implementation provided for you in the project template. Its technique for changing classes at load time works when you have one and only one instance of a particular class in an archive — good for SKScene, not so good for the many nodes in a scene.)
How casting works
When you write something like:
myObj = childNodeWithName("block1") as Block
You're telling the compiler something like: "Hey, you know that thing you got from childNodeWithName? All you know is that it's an SKNode, but I know it's really a Block, so please let me call Block methods on it." (And the compiler says, "Okay, whatever.")
But then at run time, that thing you got had better really be a Block, or your app will crash because you tried to do something Blocky with something that's not a Block. And, per the bit about .sks loading above, that thing isn't and can't be a Block — Xcode doesn't know how to put Blocks into a .sks file. So you can't get a Block out of it, so your app is guaranteed to crash.
Workarounds
So, if you can't put custom classes into a .sks file, what can you do? It depends a bit on what exactly you're trying to accomplish. But there's a good trick that might also be good game/app design in general: use the .sks file for general layout and configuration, and use a second pass to bring in things that need custom behavior.
For example, if you're building a level in a 2D platform game, you wouldn't really want to have the .sks file contain an instance of your Plumber class even if you could — that class probably has lots of details about how tall or fat the guy is, how high he jumps, the shape of his mustache, etc, and you don't want to have to set those up again every time you make a new level, much less have them saved again in each level's .sks file. Instead, the only thing you really need to know in each level file is the position he starts at. So, drag out an "Empty Node" in Xcode, and at load time, replace that node with an instance of your Plumber class, like so:
let spawnPoint = childNodeWithName("spawnPoint")
let player = Plumber()
player.position = spawnPoint.position
addChild(player)
spawnPoint.removeFromParent()
If you have more configuration details that you want to set in the .sks file, you might consider automating that process.
Make a method that does the above node-swapping trick. (Call it something like replaceNode(_:withNode:).)
Make an initializer for your custom class that takes a SKNode or SKSpriteNode, and have it set all its inherited properties (or at least the ones you care about, like color and texture) from that node.
Use enumerateChildNodesWithName:usingBlock: with a search pattern to find all the nodes in your scene with a certain kind of name, and replace them with a new node created using your initializer. Something like:
enumerateChildNodesWithName("//brick_[0-9]*") { node, stop in
self.replaceNode(node, withNode: BrickBlock(node))
}
enumerateChildNodesWithName("//question_[0-9]*") { node, stop in
self.replaceNode(node, withNode: QuestionBlock(node))
}

How to programmatically assign a random sprite to game object?

I have a function that generates a game object on screen every 100 frames:
var trash : Transform ;
function Update()
{
if(count == 1)
{
Instantiate(trash,new Vector3(UnityEngine.Random.Range(-3f,3f),UnityEngine.Random.Range(-3f,3f),UnityEngine.Random.Range(-3f,3f)), Quaternion.identity);
}
else if(count == 100)
{
count = 0;
}
}
Now, I want each of those generated objects to pick a random sprite from my assets. I thought about making a sprite array and picking from that, but I'm not sure how to go about doing so or how to assign the sprite to the object.
Anu help would be much appreciated!
I know it's late, but I just did it for myself, so I'm sharing.
Basically - put your assets in a folder and choose randomly from them to assign to the object you're duplicating.
Create a Resources folder under Assets.
Create another sub-folder for your relevant sprite assets, under Resources, lets call it CookiesImages.
Create your prefab object, and locate it under Assets/Prefabs/Resources (this is the object that you want to duplicate multiple times with different assets).
Create a script for this prefab object.
Create a static Object array (will hold the sprites).
In your Awake() method, init this Object array by loading all the resources from your assets folder:
if (objectsArray == null)
{
objectsArray= Resources.LoadAll("CookiesImages", typeof(Sprite));
}
In the Start() method, get a random index 0 --> objectsArray.Length and call Instantiate to create a sprite to assign to your prefab object.
this.GetComponent<SpriteRenderer>().sprite = Instantiate(objectsArray[index]) as Sprite;
At the beginning, I tried assigning them to an array variable from the unity UI, but I realized that in the way I described it's much more flexible.
Well, you can generate an array of sprites of the length of your choosing with:
Sprite[] _sprites = new Sprite[quantity desired]
Then using the resources folder and the Resources.Load method (found here: http://docs.unity3d.com/ScriptReference/Resources.Load.html), you could load all your sprites into the array one after the other. Then using your random number generator, you can access sprites at random from it.
Still probably not the best way of doing it, but I would imagine it is considerably better and easier to maintain than the prefab method, but different situations call for different approaches.

CCArray with CCSprites in Cocos2D/Kobold2D

I am developing a Cocos2D/Kobold2D game with ARC. I want to store CCSprite references in a CCArray. All the CCSprite objects are added as children to a parent CCNode. Is it a good idea to wrap the CCSprite objects with [NSValue valueWithNonretainedObject:..] for weak references? In all examples I found the CCSprites were stored retained in CCArrays...
There is really no need to use NSValue.
If you add objects to an NSArray or CCArray or any collection, they will be retained. It is your duty to make sure the objects are removed respectively the collection released at the appropriate time.
In many cases you don't actually need to store node references separately. You have the children array, just iterate over it and select the nodes you need to work with, for example by tagging them or by using the userObject property.

Box2D and wrapping worlds

I really stuck at implementing wrapping world with Box2D. I want to create game object appearing from left when it hides to the right and vice versa and the same for top-down.
My idea is to use object wich contains NSArray with 9 elements for superposition matrix (it's a quantum state when object exists at different locations at the same time, isn't it?).
Every element must contain the body. It covers all situations and has a more clear logic for me. For example, if my object doesn't touch any edges it holds only one "center" body (4th element). If it touches right edge i add "left-warped" body to 3rd element.
The main problem is creating body without adding to the world. First i must just add it to the array and then safely proccess adding outside of
world->Step();
For example… In collision logic (pseudocode)
[self.bodies addObjectAtIndex:index] = [self masterBody];
where
-(b2Body*)masterBody;
returns a template (master copy) for object body. But i can't write this method because there is only one
world->CreateBody(&bodyDef);
method and i must use it to create fixtures.
I can create separately only definition of the body, but full creation (with fixtures) can't be made without adding it to the world. But adding to the world msut be processed outside physics step.
Any ideas? Use separate world for storing template bodies of every game object?