I made a new .ccb file on SpriteBuilder where I created an animated CCSprite with physicsEnabled and a few physics properties. At a certain point I would like to draw the animated CCSprite on a menu. I don't want to make a copy of the whole .ccb file because now I don't need the physics part I just want to copy the CCSprite and the animation (which is a set of keyframes). What's the best way to achieve this?
You just need to make a new class in Xcode, and then make a new object of that class and add it to the menu. I explain the steps:
Go to that new .ccb file in SpriteBuilder and select the content Node of the CCSprite. (It depends on what kind of .ccb file you created, scene,sprite,node...) Then go to Code Connections and select a name for Custom Class, for example MyAnimatedSprite.
So now go to Xcode, and then make a new file in your project with type CCNode, and name it 'MyAnimatedSprite'.
Now the final step is to add this sprite to the menu.
You must have a Physic Node previously added to the menu .ccb file and also declared in the .m file, because you said your sprite has physics enabled. If you don't have it, simply add it with sprite builder wherever you want, and go to Code Connections and select under custom class, Doc Root Var and call it for this example, '_physicsNode'
Now go to the Menu class in Xcode, and simply add the sprite class to the menu with these lines:
#implementation Menu{
..... YOUR CODE .....
CCPhysicsNode *_physicsNode; //add physics node if you don't have it
}
-(void) didLoadFromCCB{
//create a new object of type MyAnimatedSprite
CCNode *myAnimatedSprite = [CCBReader load:#"MyAnimatedSprite"];
...YOUR CODE....
}
And you will have your sprite in your menu working perfectly :)
Related
A SKScene (.swift file) object can be can be loaded with any scene (.sks) file. This allows you to create mulitple .sks files and load any of them with the same SkScene object. GameScene.swift for example could be instantiated with Level_1.sks or Level_2.sks. Any ideas on how to accomplish this?
I'm not sure if this is the correct approach to make multiple levels, but if you wanna reach this goal simple put in your scene editor with the Scene select click on Custom Class Inspector and write the class name you want (GameScene for example)
According to the Sprite Kit documentation for entities and components
When you add entities (and their components) to a scene in the Xcode SpriteKit Scene Editor, Xcode automatically archive those entities alongside the SpriteKit scene content.
This implies that you can add entities using the scene editor, but I can't find any way to do that. I can add components using the node components inspector, but not entities. How is this done?
Your entities are not added in the SpriteKit scene - they are added in the abstract GKScene.
When you are using the SpriteKit editor, you can think of your nodes as your entities; if you add a component to a sprite, say, and then load up the GKScene, you'll have an entity with two components: the component you added to the sprite, and a GKSKNodeComponent that points to the node.
What the Sprite Kit scene editor is allowing you to do is to have a nice mapping from a GKScene (which has no particular knowledge of a SpriteKit scene or its structure) and a SpriteKit scene by automatically creating entities representing an SKScene's nodes, and giving you a way to attach components to the entities that are associated with their sister nodes in the SKScene, so that you don't have to do it programmatically.
You can, of course, add your own abstract entities and attach components to them beyond the ones that the SpriteKit scene editor supplies. But currently, you'll have to do that programmatically outside of the scene editor, because the scene editor has no concept of an entity that is not associated with a node. (However, I suspect you'll find that you can just use an empty SKNode to act as a container for those types of components, and it will be a lot easier to manage with very little overhead. In other words, I don't think you'd get much value from manually managing those entities and components in code compared to being able to work with them alongside everything else in the SpriteKit scene editor.)
An entity is automatically created and added to the array of entities in the SKScene when a component is added to a SKNode in the scene editor:
Create a subclass of GKComponent.
Open the Scene Editor (click on your GameScene.sks).
Select one of the items in the scene (or add one from the library).
Open the Components Inspector (opt-cmd-7) and click the plus (+) to
select your GKComponent subclass.
You can see an entity is created by adding the following snippet to the scene's update(_:) method. The snippet accesses each entity, searches for a component for GKSKNodeComponent (which was added by the scene editor when you added a component to a SKNode), and then accesses its node (your item(s) in the scene with components added to them):
for entity in self.entities {
if let node = entity.component(ofType: GKSKNodeComponent.self)?.node {
print("node: \(node)")
}
}
Since iOS 13 there has been a bug where there would be problems loading the rootNode from the GKScene so GameplayKit projects and the above technique would not work... UNLESS you add the following to your custom GKComponent subclass:
override class var supportsSecureCoding: Bool {
return true
}
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.
I'm trying to add a view to the main view (a subview) where the user can hand draw, I'm trying to do this using ACEDrawingView, my issue is that I don't know how use the clear, undo etc. features.
This is how I'm using ACEDrawingView which works fine but without any buttons.
1- Created a Simple App project
2- Added a view and set "ACEDrawingView" as its class
3- Complied-ran and it worked great
The question is, how can I clear, undo etc. I tried calling the clear method but nothing happens.
Here is what I have tried that didn't work.
1- Added a button to the main view and created an action for it
2- Imported ACEDrawingView
3- Created an instance of ACEDrawingView
ACEDrawingView *draw = [[ACEDrawingView alloc] init];
4- Called the clear method from ACEDrawingView using the action created in step one
[draw clear];
When I tap the button nothing happens, I don't get any no errors either.
How can I add a clear or undo button?
I'd take a look at the demo application ACEDrawingView provides on GitHub to see how they're doing it. It looks like they use undo, redo and clear in the demo so it should give you a good start.
Here are the steps to add the drawing view and buttons using ACEDrawingView;
1- Create a Simple App project
2- Import (drag and drop) the following four classes to your project
ACEDrawingTools.h
ACEDrawingTools.m
ACEDrawingView.h
ACEDrawingView.h
3- Click the main storyboard and add a view (a view, not a view controller).
4- Select the view you added in step 3 and set "ACEDrawingView" as its class.
5- Compile and run
It this point you should see an empty view where the only thing you can do is draw, no buttons yet.
Now let add some buttons.
6- Go to the main storyboard and add three buttons right below the view you added in step 3, name the buttons clear, undo and redo.
7- Create an action for each button and name them respectably clear, redo and undo
8- Go to viewController.h and add #class ACEDrawingView; right after the import statements and #property (nonatomic, unsafe_unretained) IBOutlet ACEDrawingView *drawingView; right after the interface
9- Go to the main storyboard and link the view you added in step 3 to the outlet drawingView (added in step 8)
10- Got to viewController.m and import ACEDrawingView.h
#import "ACEDrawingView.h"
11- Go to the action for clear and add
[self.drawingView clear];
12- Go to the action for redo and add
[self.drawingView redoLatestStep];
13- Go to the action for undo and add
[self.drawingView undoLatestStep];
14- Done.
You should now be able to clear, undo and redo
Newbie to iOS and Cocos2d ( 2.x )
Ok I want to create a Menu Object and call it from each new Scene.
Example:
Scene1, add menu
Scene2, add same menu as on Scene1
I've only seen how to initialize the CCMenu when you init the Layer itself. you build the items and then add them to the CCMenu and so on.
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:lesson_3._menus_and_scenes
How can I initialize the CCMenu once and then just add it to what ever scene I happen to be viewing? So if I'm viewing Scene1 or Scene2 it's still the same menu.
Does this make sense?
You'll need a different instance of the menu for each scene, so technically speaking, you'll need to initialize it once per scene.
But I think you're asking "how can I write the code once and then reuse that code in each scene." You'll want to create some sort of CC Object that you can reuse. This could be a subclass of a CCMenu, CCLayer, or whatever suits the purpose best. So you may try something like:
#interface MyMenuLayer : CCLayer {
CCMenu *myMenu;
}
#end
Then in the .m file, set up your menu however you like. When you want to include this in Scene1:
MyMenuLayer *menu = [MyMenuLayer node];
[self addChild:menu];
You can use the exact same code in Scene2.
(You could just extend CCMenu instead of CCLayer, but I personally prefer to work with Layers instead of Menus. It's a matter of personal choice.)
It's hard to give a very definitive answer with the information in your question, but I hope this gets you set off on the right path.