Draw a path with variable width in iOS - ios

I am working on a writing application, My writing is working fine, but what I want to implement is variable stroke width, so that the writing is very realistic and intuitive, as done by "BAMBOO" and "PENULTIMATE" application.
Firstly I want to tell you what I have tried.
1) In iOS, their is no pressure detection, or velocity detection according to my research. For velocity detection, I have to use OPENGL.
2) Due to these limitations, I tried using the method given in this tutorial which is pretty straight forward.Here is the link http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-advanced-freehand-drawing-techniques/
3) This works fine, But here what happens is that, the width increases as I move faster and decreases, as I move slower. But I want is the opposite effect, that is the width should increase as I move slower and when I move fast, the thickness should only be seen only at the edges and for the whole line.
Here are the screenshot of the BAMBOO app and my app.
1)BAMBOO app
In the above image, the line is drawn with speed and you will see that the thickness is only at edges.
2) MY APP
Here you will see that the line is thinner at edges and thick every where else.
So, here are my doubts
1) Is their any better approach to fulfil my requirement, other than what I have tried.
2) If what I have tried, is correct approach to tackle the problem, then what changes I need to make to achieve the desired effect.
Regards
Ranjit

The answer to how to reverse the width behaviour and (and even the same question as yours) is right there in the link that you posted. All I did was to search for the word "width"
The question (my highlighting is not part of the quote):
The final version of this seems to work opposite of the first version. I would like to have the line thicker as the user moves slower and not thinner. Where do I change the code to inverse the final varying thickness to perform or like a pen? Meaning the slower the user moves the thicker or more ink the pen puts down... Thanks! Great tutorials, btw...
And the answer:
thanks for the great tutorial!
with these changes i got the opposite line width cahnge effect:
#define CAPACITY 100
#define FF 20.0
#define LOWER 0.01
#define UPPER 1.5
float frac1 = clamp(FF/len_sq(pointsBuffer[i], pointsBuffer[i+1]), LOWER, UPPER); // ................. (4)
float frac2 = clamp(FF/len_sq(pointsBuffer[i+1], pointsBuffer[i+2]), LOWER, UPPER);
float frac3 = clamp(FF/len_sq(pointsBuffer[i+2], pointsBuffer[i+3]), LOWER, UPPER);
Another search in the same link for the text "float frac1 =" shows that this change should be applied to lines 76-78 (somewhere inside touchesMoved:withEvent: in the code from the article)

In your touchesBegan: method, UItouch is supplied.
UITouch has below instance functions,
– locationInView:
– previousLocationInView:
And below property
#property(nonatomic, readonly) NSTimeInterval timestamp
From the above, i think you can easily calculate velocity.I didn't go through any of mentioned links.I just want to give you an idea of how to calculate velocty based on touch object.

Related

Interact with complex figure in iOS

I need to be able to interact with a representation of a cilinder that has many different parts in it. When the users taps over on of the small rectangles, I need to display a popover related to the specific piece (form).
The next image demonstrates a realistic 3d approach. But, I repeat, I need to solve the problem, the 3d is NOT required (would be really cool though). A representation that complies the functional needs will suffice.
The info about the parts to make the drawing comes from an API (size, position, etc)
I dont need it to be realistic really. The simplest aproximation would be to show a cilinder in a 2d representation, like a rectangle made out of interactable small rectangles.
So, as I mentioned, I think there are (as I see it) two opposite approaches: Realistic or Simplified
Is there a way to achieve a nice solution in the middle? What libraries, components, frameworks that I should look into?
My research has led me to SceneKit, but I still dont know if I will be able to interact with it. Interaction is a very important part as I need to display a popover when the user taps on any small rectangle over the cylinder.
Thanks
You don't need any special frameworks to achieve an interaction like this. This effect can be achieved with standard UIKit and UIView and a little trigonometry. You can actually draw exactly your example image using 2D math and drawing. My answer is not an exact formula but involves thinking about how the shapes are defined and break the problem down into manageable steps.
A cylinder can be defined by two offset circles representing the end pieces, connected at their radii. I will use an orthographic projection meaning the cylinder doesn't appear smaller as the depth extends into the background (but you could adapt to perspective if needed). You could draw this with CoreGraphics in a UIView drawRect.
A square slice represents an angle piece of the circle, offset by an amount smaller than the length of the cylinder, but in the same direction, as in the following diagram (sorry for imprecise drawing).
This square slice you are interested in is the area outlined in solid red, outside the radius of the first circle, and inside the radius of the imaginary second circle (which is just offset from the first circle by whatever length you want the slice).
To draw this area you simply need to draw a path of the outline of each arc and connect the endpoints.
To check if a touch is inside one of these square slices:
Check if the touch point is between angle a from the origin at a.
Check if the touch point is outside the radius of the inside circle.
Check if the touch point is inside the radius of the outside circle. (Note what this means if the circles are more than a radius apart.)
To find a point to display the popover you could average the end points on the slice or find the middle angle between the two edges and offset by half the distance.
Theoretically, doing this in Scene Kit with either SpriteKit or UIKit Popovers is ideal.
However Scene Kit (and Sprite Kit) seem to be in a state of flux wherein nobody from Apple is communicating with users about the raft of issues folks are currently having with both. From relatively stable and performant Sprite Kit in iOS 8.4 to a lot of lost performance in iOS 9 seems common. Scene Kit simply doesn't seem finished, and the documentation and community are both nearly non-existent as a result.
That being said... the theory is this:
Material IDs are what's used in traditional 3D apps to define areas of an object that have different materials. Somehow these Material IDs are called "elements" in SceneKit. I haven't been able to find much more about this.
It should be possible to detect the "element" that's underneath a touch on an object, and respond accordingly. You should even be able to change the state/nature of the material on that element to indicate it's the currently selected.
When wanting a smooth, well rounded cylinder as per your example, start with a cylinder that's made of only enough segments to describe/define the material IDs you need for your "rectangular" sections to be touched.
Later you can add a smoothing operation to the cylinder to make it round, and all the extra smoothing geometry in each quadrant of unique material ID should be responsive, regardless of how you add this extra detail to smooth the presentation of the cylinder.
Idea for the "Simplified" version:
if this representation is okey, you can use a UICollectionView.
Each cell can have a defined size thanks to
collectionView:layout:sizeForItemAtIndexPath:
Then each cell of the collection could be a small rectangle representing a
touchable part of the cylinder.
and using
collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
To get the touch.
This will help you to display the popover at the right place:
CGRect rect = [collectionView layoutAttributesForItemAtIndexPath:indexPath].frame;
Finally, you can choose the appropriate popover (if the app has to work on iPhone) here:
https://www.cocoacontrols.com/search?q=popover
Not perfect, but i think this is efficient!
Yes, SceneKit.
When user perform a touch event, that mean you knew the 2D coordinate on screen, so your only decision is to popover a view or not, even a 3D model is not exist.
First, we can logically split the requirement into two pieces, determine the touching segment, showing right "color" in each segment.
I think the use of 3D model is to determine which piece of data to show in your case if I don't get you wrong. In that case, the SCNView's hit test method will do most of work for you. What you should do is to perform a hit test, take out the hit node and the hit's local 3D coordinate of this node, you can then calculate which segment is hit by this touch and do the decision.
Now how to draw the surface of the cylinder would be the only left question, right? There are various ways to do, for example simply paint each image you need and programmatically and attach it to the cylinder's material or have your image files on disk and use as material for the cylinder ...
I think the problem would be basically solved.

Adjacent SKPhysicsBody not working properly

I am having a problem when trying to put two blocks that have physics bodies on top of one another.
http://s1173.photobucket.com/user/Kyle_Decot/media/example_zps02f027fe.mp4.html
As you can see in the video I am able to place my block on top of the stacked blocks even though they are placed right on top of one another.
Both the player block and the other blocks inherit from a base Block class which looks like this
#import "Block.h"
#implementation Block
+ (void)loadSharedAssets {
}
- (id)initWithColor:(UIColor *)color size:(CGSize)size {
self = [super initWithColor:color size:size];
if (self) {
self.texture = [SKTexture textureWithImageNamed:#"tile"];
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: self.size];
self.physicsBody.usesPreciseCollisionDetection = YES;
self.physicsBody.dynamic = NO;
}
return self;
}
#end
Update
I've added a picture to make the problem a little more clear. Essentially the problem is that even though the blue blocks are right above one another, I am still able to jump up (w/ the red block) and sit on the edge of the bottom blue block (which shouldn't be possible). It seems something is off w/ the physics bodies or something.
You can see that the red block is slightly higher than the adjacent blue block for some reason and "sits" on the edge of the bottom blue block. when I jump up against it.
EDIT: replaced original suggestion with answer
Scrolling to section 4.5 Edge Shapes of the box2d documentation and you will find the cause of this (SpriteKit uses Box2D under the hood for it's physics implementation)
In many cases a game environment is constructed by connect several edge shapes end-to-end. This can give rise to an unexpected artifact when a polygon slides along the chain of edges. In the figure below we see a box colliding with an internal vertex. These ghost collisions are caused when the polygon collides with an internal vertex generating an internal collision normal.
The two edges here (edge1 and edge2) are the left hand side edges of the two blue boxes in your game (so picture it rotated 90 digs counter-clockwise)
Box2D introduced ChainShapes to get around this issue (which you can find referenced in section 5.6 Edge Shapes.
The idea is to replace groups of square physics bodies with a chain of these vertices whenever generating more than one box at the same time.
I believe you can access these within SpriteKit by using bodyWithEdgeChainFromPath and passing in a Core Graphics path consisting of the corner points of the boxes you want to combine to form the collision chain
I could imagine that tiny numerical errors in the simulation run by SpriteKit, in particular regarding collision detection and motion will make the red box indeed sit on the edge of the lower blue box. This position may be stable simply because the blue box accelerates the red box leftwards for the short amount of time it remains on screen.
A solution could be to use specific body types that merge the different configurations of boxes with smooth left vertical surfaces that occur in your game. In the specific case, it would be a box that is twice as high than wide. Before you spend a lot of time on this, you could test first of all, if removing the lower blue box stops the red box from getting stuck.
You don't need to define different Block classes for different box configurations: your initWithColor:(UIColor *)color size:(CGSize)size already appears to accept different sizes, but you might want to provide additional texture tiles and identifiers for those to select from.
EDIT: since you've clarified your question a bit and you seem to want the red one to fall back to the ground, while the blue blocks stay where they were, it seems that the bodies may be too rough, which makes them stick, and the red one doesn't slide off.
There's the friction property - modifying it can turn the body from a rough one (1.0) to one that's as smooth as an ice cube (0). Per the documentation, the default value is 0.2, which may still be too rough for your needs. Try setting it to physicsBody.friction = 0.0 in all involved bodies.
EDIT 2: it seems that it's a deeper bug. You can try the following workarounds to achieve your desired effect, if you want to sacrifice a little accuracy:
set your first blue block physics body to the target rectangle size, then make each subsequent lower block body 1-2 pixels narrower, so that you evade the 'lip'
set your physics bodies to circles rather than rectangles if all else fails - bodyWithCircleOfRadius:self.size.width*0.5. For a fast enough simulation, this might do.

Should I use a sprite(image) or should I draw?

Below is a screenshot from a famous structure building game.
As you can see rods are attached together with ball joints. I'm trying to achieve something similar with Cosos2d on iPhone. I've got two questions here:
Should I draw those ball joints or should I just add them as sprites?
I guess the rods are not drawn bur are rather images. But considering that the length of the rods will change depending on need, how do I make rods with different lengths from just one image?
I am not sure what would be the best approach for one. I would imagine that either way would be fine, but it would be harder to achieve whatever visual affect you want through drawing them. I think the hardest part would be making sure that they are anchored to vertices in a grid system that has the dimension that you want.
As for (2) you can always scale your image.
CCSprite *rod = [CCSprite spriteWithFile:#"rod.png"];
rod.scaleY = 2.0; //or scaleX
Then rotate and change its anchor points as needed.
Again I imagine the most difficult part would be anchoring them and positioning them correctly, so that align properly with the vertices.

Smooth Rotation using Bullet and Ogre3D

I've been suffering from an issue regarding the implementation of orienting characters in a game I'm implementing using Ogre3D and Bullet physics.
What I have: A Direction Vector that the character is moving in, along with its current orientation.
What I need: To set the orientation of the character to face the way it is moving.
I have a snippet of code that sort of does what I want:
btTransform src = body->getCenterOfMassTransform();
btVector3 up = BtOgre::Convert::toBullet(Ogre::Vector3::UNIT_X);
btVector3 normDirection = mDirection.normalized();
btScalar angle = acos(up.dot(normDirection));
btVector3 axis = up.cross(normDirection);
src.setRotation(btQuaternion(axis, angle));
body->setCenterOfMassTransform(src);
Where 'body' is the rigidbody I'm trying to orient.
This snippet has a couple of problems however:
1) When changing direction, it tends to 'jitter' i.e. it rapidly faces one way, then the opposite for a second or so before correcting itself to the orientation it is supposed to be at.
2) Most times that the code is run I get an assertion error from Bullet's btQuaternion on
assert(d != btScalar(0.0));
Can anyone help?
Thanks!
I think you shouldn't use functions like 'acos' for such things, as it may cause some inconsistencies in border-cases as the 180 vs 0 rotation mentioned above. You can also get high numerical error for such data.
The second thing is that - in general - you should avoid setting explicit position and rotation in physics engines, but rather apply forces and torques to make your body moving as you want. Your current approach may work perfectly now, but when you add another object and force you character to occupy the same space, your simulation will explode. And at this stage it's very hard to fix it, so it's better to do it right from start :) .
I know that finding correct force/torque can be tricky but it's the best way to make your simulation consistent.

CCParallaxNode parallaxRatio (explanation)

I feel stupid asking this question, but I can not find a clear answer anywhere (or much of an answer at all) so I feel I must ask. Is there anyone out there who can explain clearly how the parallaxRatio of CCParallaxNode works?
I have checked the source of CCParallaxNode and it does not explain it at all. I have searched the internet and stackOverflow extensively. I have tried to do good old trial and error. I'm still confused.
[parallaxLayer addChild:backgroundEffect_subtleRed z:100 parallaxRatio:ccp(0.5, 0.5) positionOffset:backgroundEffect_subtleRed.position];
In this piece of code I am trying to add a particle emitter to a parallaxLayer and have it move somewhat like you would expect an object on a parallax layer to move. Unfortunately I do not see the particles at all. I have had this problem anytime I try to add anything to a parallaxNode when I want it to move. I have been using CCParallaxNode to create static UI layers, but have not been able to use them for what they were built to do.
In summary:
parallaxRatio takes a CGPoint. What do the floats in the CGPoint apply to? Are they ratios of x and y in relation to the window? Are they (parallaxLayerMovementInRelationTo, parentNode)? A working piece of example code would be very helpful.
Thank you.
To quote from a cocos2d book I own:
[paraNode addChild:para1 z:1 parallaxRatio:CGPointMake(0.5f, 0) positionOffset:topOffset];
[paraNode addChild:para2 z:2 parallaxRatio:CGPointMake(1, 0) positionOffset:topOffset];
[paraNode addChild:para3 z:4 parallaxRatio:CGPointMake(2, 0) positionOffset:midOffset];
[paraNode addChild:para4 z:3 parallaxRatio:CGPointMake(3, 0) positionOffset:downOffset];
"The CCParallaxNode is created like any other node, but its children are added using a special initializer. With it you specify the parallax ratio, which is a CGPoint used as a multiplier for any movement of the CCParallaxNode In this case, para1 would move at half the speed, para2 at the normal speed, para3 at double the speed of the CCParallaxNode, and so on"
So basically, its the ratio that the individual layers are moved in the relation to the movement of the whole CCParallaxNode.

Resources