I'm building game-type app using SpriteKit. In one of the scenes I want to create an area, in with user will be able to draw. Sadly using SKShapeNodes produces jagged lines and causes FPS to drop. I thought about using Core Graphics method, but I need drawn lines to be a part of a Node. So is there a way to use Node as a canvas for CG?
From the SKNode documentation:
Unlike views, you cannot create SKNode subclasses that perform custom drawing.
So I think the answer is no, you can't do that.
Each node does have a scene property, and the scene does have a link to the view that contains it. But the thing that makes sprite animation fast is that sprites are canned -- the images have already been drawn and just need to be copied. Node types other than SKSpriteNode are similarly optimized for speed. Accordingly, there are no drawing methods in the sprite classes -- no opportunity for your code to do custom drawing.
You can draw to a CGImage and create a SKTexture from that using textureWithCGImage:
Related
My goal is to take an existing SKScene and stretch it according to a polynomial function, like one stretching everything toward or away from the center. The stretched form will be continuously rendered and presented to the user. It may be a new scene/image/view or whatever is necessary. The model will simply perform its functions over time in Euclidean form.
My project content is little more than the iOS SpriteKit starter project on Xcode.
I know of the functions in SKScene:
convertPointToView(), and
convertPointFromView()
However, I don't understand how these will be much use for the view since the scene only has aspect fill, fits and resize settings.
I attempted to make a fragment shader to do the actual stretching, however, I could not figure out how to get existing color and position information to draw the new color according to the transformation.
I am using SpriteKit and I only know how to access fragment from among the shaders using SKShader. I do not know how to access vertex shaders from this context. Otherwise, I would have tried to use a vertex shader.
You could go with SceneKit:
Create SCNView with SCNScene
Create SCNNode with SCNPlane geometry (or create custom SCNGeometry)
Create SCNMaterial with your SKScene attached to created material's diffuse.contents property
Attach material to geometry
Attach node to scene
Then you have multiple choices:
Use SCNShadable - either attach shader modifier for geometry or material, or use custom SCNProgram.
Use SCNTechnique on SCNView.
This way you will have your SKScene as texture on a 3D object (plane or something) and have full control of vertex and fragment shaders.
I'm making a game with Sprite Kit in which I generate many instances of an SKSpriteNode. When I detect a collision between two sprites, I can easily get a lot of data about the colliding sprites (position, rotation, scale, etc.).
My question: Is there a way to embed arbitrary information, like a string or integer, into the sprite? Say I wanted to timestamp each sprite with the time it was generated, and then display that when it collides with something.
UIButton come to mind, where you can define button.tag, and use that information later.
SKNode has a userData dictionary where you can store data.
Subclass SKSPriteNode and add properties. This will allow you to attach whatever information you would like to your sprite while retaining the built in SKSpriteNode functionality.
With UIDynamics it is simple to have the physics objects, called dynamic items, control custom views (or indeed anything you want) using the protocol UIDynamitItem with the three properties center, transform and bounds. I would like to do something similar with SpriteKit, but according to the manual:
Unlike views, you cannot create SKNode subclasses that perform custom drawing
Specifically, I would like to have the physics bodies control some vector graphics I currently have in a drawrect. There are two things I am after here:
The first is to let the vector graphics move around like any other node.
The second is to let position, angle and other properties change the exact position of some of the control points.
I am fairly certain that I could achieve this with UIDynamics and dynamic items, but then I wouldn't be able to use actions and other nice sprite kit features.
It would also seem that 1 could be handled by converting the paths to cgpaths and using shape nodes, but that would be limiting, and not cover 2.
Any suggestions?
I'm trying to draw lines in Cocos2d using touches.
I had a system where it would just add a small sprite where you touched, but it's working terribly. So I've been trying to find a way to draw actual lines using a method like ccDrawLine, but every tutorial I find seems to leave out something, and I just can't figure it out.
I've found this tutorial, Drawing line on touches moved in COCOS2D but I don't understand a few things about that.
It seems to reference the same variable from two different files, so I don't understand how it's doing that. (The naughtyTouchArray variable)
I can't find a complete guide on drawing lines, so sorry for the codeless question, but I'm getting frustrated.
Thanks.
The answer you've linked in your question provides good solution to your problem. There is no "two different files". Just two different methods of one layer. One method (ccTouchesMoved:withEvent:) handles touches and fill the array of points to be connected to each other one-by-one with lines. From cocos2d documentation, all drawing must be placed in the draw method of the node. So, another (draw) method just draws lines according to the given array. Cocos2d is based on OpenGL and it fully redraws scene every tick, so you cannot just draw new line. You had to draw all of them.
Or any other node can draw your array in it's draw method, so you can simply pass stored array of points from the layer, that detects touches, to this node.
I have this app using which one can draw basic shapes like rectangle, eclipse, circle, text etc.
I also allow free form drawing, which is stored as set-of-points, on the canvas.
Also a user can resize and move around these objects by operating on the selection handles that appear when an object is selected.
In addition the user should be able to zoom and pan the canvas.
I need some inputs on how to efficiently implement this drawing functionality.
I have following things in mind -
Use UIView's InvalidateRect and drawRect
Have a UIView for the main canvas and for each inserted object - invalidate the correspoding rect and redraw all the objects which intersects that rect in the drawRect function of the UIView.
Have a UIView and use CALayer ?
every one keep mentioning about the CALayer , I dont have much idea on this, before I venture into this I wanted a quick input on whether this route is worth taking.
like, https://developer.apple.com/library/ios/#qa/qa1708/_index.html
Have a UIImageView as canvas and when drawing each object, we do this
i) Draw the object into offscreen CGContext, basically, create a new CGContext by using UIGraphicsBeginImageContext, draw the shape, extract the image out of this CG context and use that as source of UIImageView's image property, but here how do I invalidate only a part of the UIImageView so that only that area gets refreshed.
Could you please suggest what is the best approach?
Is there any other efficient way to get this done?
Thanks.
Using a UIImage is more efficient for rendering multiple objects. But Using a CALayer is more efficient when moving and modifying a single object because you don't have to modify the other objects. So I think the best approach is to use a UIImage for general drawing and a CALayer for the shape that is being modified. In other words:
use a CALayer to draw the shape being added or modified, but don't draw it on the UIImage
use a UIImage to draw the other shapes
But OpenGL is still the most efficient solution, but don't bother with that if you don't have too many objects to draw.
If you want to draw polygons, you'll have to use Quartz framework, and have your drawing methods based on CALayer. It doesn't really matter which view you'll put your CALayers in, UIImageView or UIView. I'll say UIView since you won't be needing UIImageView's properties or methods for drawing.