I am trying to change my Sprite anchor point so that I can rotate over a 0.0f,0.0f anchorpoint. At first my object is rotation at the default anchor point (0.5f,0.5f). However later on I need it to rotate over a 0.0,0.0 AnchorPoint.
The problem is I cannot change the anchor point and change the position accordingly, so it stays on the same position, without the object appearing to quickly move and reposition to its original point.
Is there a way I can set the anchor point and the position of my Sprite at once, without it moving at all?. Thank you.
-Oscar
I found a solution to this with a UIView elsewhere, and rewrote it for cocos2d:
- (void)setAnchorPoint:(CGPoint)anchorPoint forSprite:(CCSprite *)sprite
{
CGPoint newPoint = CGPointMake(sprite.contentSize.width * anchorPoint.x, sprite.contentSize.height * anchorPoint.y);
CGPoint oldPoint = CGPointMake(sprite.contentSize.width * sprite.anchorPoint.x, sprite.contentSize.height * sprite.anchorPoint.y);
newPoint = CGPointApplyAffineTransform(newPoint, [sprite nodeToWorldTransform]);
oldPoint = CGPointApplyAffineTransform(oldPoint, [sprite nodeToWorldTransform]);
CGPoint position = sprite.position;
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
sprite.position = position;
sprite.anchorPoint = anchorPoint;
}
This is a good question, and I don't know the full answer yet.
As you may have noticed, the anchorPoint cannot be changed without affecting scale and rotation.
For scaled sprites:
You have to simultaneously change the anchorPoint and position of your sprite. See this question for a hint
For rotated sprites:
Intuition says you would need to simultaneously change anchorPoint, rotation, and position. (I have no idea how to compute this.)
NOTE: I'm still learning graphics programming, so I'm not 100% able to compute this stuff yet.
I've needed this a couple of times and decided to make a extension for CCNode, tested it abit and seems to work fine. Can be really useful to some :)
It's tested with 1.x but It should work fine in 2.x too. Supports transformed nodes and HD.
Just add this to your project and import whenever you need it - It will be added to all classes deriving from CCNode. (CCSprite, CCLayer)
Interface
#import "cocos2d.h"
#interface CCNode (Extensions)
// Returns the parent coordinate for an anchorpoint. Useful for aligning nodes with different anchorpoints for instance
-(CGPoint)positionOfAnchorPoint:(CGPoint)anchor;
// As above but using anchorpoint in points rather than percentage
-(CGPoint)positionOfAnchorPointInPoints:(CGPoint)anchor;
//Sets the anchorpoint, to not move the node set lockPosition to `YES`. Setting it to `NO` is equal to setAnchorPoint, I thought this would be good for readability so you always know what you do when you move the anchorpoint
-(void)setAnchorPoint:(CGPoint)a lockPosition:(BOOL)lockPosition;
#end
Implementation
#import "CCNode+AnchorPos.h"
#implementation CCNode (Extensions)
-(CGPoint)positionOfAnchorPoint:(CGPoint)anchor
{
float x = anchor.x * self.contentSizeInPixels.width;
float y = anchor.y * self.contentSizeInPixels.height;
CGPoint pos = ccp(x,y);
pos = CGPointApplyAffineTransform(pos, [self nodeToParentTransform]);
return ccpMult(pos, 1/CC_CONTENT_SCALE_FACTOR());
}
-(CGPoint)positionOfAnchorPointInPoints:(CGPoint)anchor;
{
CGPoint anchorPointInPercent = ccp(anchor.x/self.contentSize.width, anchor.y/self.contentSize.height);
return [self positionOfAnchorPoint:anchorPointInPercent];
}
-(void)setAnchorPoint:(CGPoint)a lockPosition:(BOOL)lockPosition
{
CGPoint tempPos = [self positionOfAnchorPoint:a];
self.anchorPoint = a;
if(lockPosition)
{
self.position = tempPos;
}
}
#end
Cocos2d-x + Fixed scale
YourClass.h
virtual cocos2d::Vec2 positionFromSprite(cocos2d::Vec2 newAnchorPoint, cocos2d::Sprite *sprite);
YourClass.m
Vec2 YourClass::positionFromSprite(Vec2 newAnchorPoint, cocos2d::Sprite *sprite) {
Rect rect = sprite->getSpriteFrame()->getRect();
Vec2 oldAnchorPoint = sprite->getAnchorPoint();
float scaleX = sprite->getScaleX();
float scaleY = sprite->getScaleY();
Vec2 newPoint = Vec2(rect.size.width * newAnchorPoint.x * scaleX, rect.size.height * newAnchorPoint.y * scaleY);
Vec2 oldPoint = Vec2(rect.size.width * oldAnchorPoint.x * scaleX, rect.size.height * oldAnchorPoint.y * scaleY);
Vec2 position = sprite->getPosition();
position.x -= oldPoint.x;
position.x += newPoint.x;
position.y -= oldPoint.y;
position.y += newPoint.y;
return position;
}
Related
I added two shaders to my project, one is the same shader from the WWDC 2014 example, and the other has the same code but adding a custom uniform. The problem is that the sprite with the custom uniform is rendered static when the app is running, and with black color on SpriteKit editor in Xcode.
The shader with the custom uniform is below, u_speed is used to control how fast the waves move.
void main()
{
float currTime = u_time * u_speed;
vec2 uv = v_tex_coord;
vec2 circleCenter = vec2(0.5, 0.5);
vec3 circleColor = vec3(0.8, 0.5, 0.7);
vec3 posColor = vec3(uv, 0.5 + 0.5 * sin(currTime)) * circleColor;
float illu = pow(1. - distance(uv, circleCenter), 4.) * 1.2;
illu *= (2. + abs(0.4 + cos(currTime * -20. + 50. * distance(uv, circleCenter)) / 1.5));
gl_FragColor = vec4(posColor * illu * 2., illu * 2.) * v_color_mix.a;
}
This is a project I’ve put together with just the shaders and the two sprites showing the problem.
From what I can tell, there's nothing wrong with your code. There seems to be a bug in how GameScene.sks passes your custom shader uniform into the shader which is causing it to be 0, and the animation to freeze.
If you initialize everything in code rather than in the UI Builder, it works fine. Paste this into your didMoveToView: to see what I mean.
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithColor:[SKColor whiteColor] size:CGSizeMake(100, 100)];
sprite.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:sprite];
SKShader* spin2x = [SKShader shaderWithFileNamed:#"Shader2"];
spin2x.uniforms = #[
[SKUniform uniformWithName:#"u_speed" float:(2.0)],
];
sprite.shader = spin2x;
Adding something like the code below in didMoveToView: did the trick, somehow the uniforms are there but are not read by the shader, this "refreshing" of the values did make it work normally.
for (SKSpriteNode *sprite in self.children) {
if ([sprite isKindOfClass:[SKSpriteNode class]]) {
for (SKUniform *uniform in sprite.shader.uniforms) {
if (uniform.uniformType == SKUniformTypeFloat) {
uniform.floatValue = uniform.floatValue;
}
}
}
}
I am making a game with sprite kit and now I am wondering what the best way is to let the object 'jump'. So it will be launched up vertical with a few pixels.
This is the code of the object I want to jump:
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:#"bal.png"];
sprite.position = CGPointMake(self.frame.size.width/4 + arc4random() % ((int)self.frame.size.width/2), (self.frame.size.height/2 + arc4random() % ((int)self.frame.size.height/2)));
sprite.color = [self randomColor];
sprite.colorBlendFactor = 1.0;
sprite.xScale = 0.2;
sprite.yScale = 0.2;
[self addChild:sprite];
sprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:sprite.size.width/2];
self.physicsWorld.gravity = CGVectorMake(0.0f, -4.0f);
I would try to avoid setting object's velocity directly. Instead I'd apply forces and impulses to the objects. For most cases this works better as it doesn't break the physics simulation. For example this is how I'd make my object jump:
- (void) jump:(SKSpriteNode*)obj
{
if (obj.isTouchingGround)
{
CGFloat impulseX = 0.0f;
CGFloat impulseY = 25.0f;
[object.physicsBody applyImpulse:CGVectorMake(impulseX, impulseY) atPoint:obj.position];
}
}
Give a velocity to the body by changing the velocity property of the physicsBody associated with the sprite.
Specifically, you need to add
sprite.physicsBody.velocity = CGVectorMake(vx,vy);
EDIT : If you want to to do this through actions, make use of one of these two class methods of SKAction
+ (SKAction *)followPath:(CGPathRef)path duration:(NSTimeInterval)sec;
+ (SKAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY duration:(NSTimeInterval)sec;
However, using any of these requires you to calculate stuff based on your velocity vector and take care of gravity yourself(for giving suitable deltaX and deltaY or the correct path) which is quite unnecessary. Why not just mention velocity and let SpriteKit work it out for you?
I rotate my view with CGAffineTransform
[view setTransform:newTransform];
The frame values remain the same after transform is applied but how do I find "rotated" or transformed values of this frame?
(source: informit.com)
I want the exact coordinates of rotated frame edges, that is a, b, c, d points.
One thing to keep in mind is that the transform changes the coordinate system, so you will need to be able to convert between the parent 'view' and the child (transformed) view. Also, transforms preserve the center of the transformed object but not any of the other coordinates. So you need to calculate things in terms of the center. And there are several helpers you will need. (I got most of the following approach from Erica Sadun's book Core iOS Developer's Cookbook).
I usually add these as a category on UIView.
In order to transform the child's coordinates to those of the parent you need something like:
// helper to get pre transform frame
-(CGRect)originalFrame {
CGAffineTransform currentTransform = self.transform;
self.transform = CGAffineTransformIdentity;
CGRect originalFrame = self.frame;
self.transform = currentTransform;
return originalFrame;
}
// helper to get point offset from center
-(CGPoint)centerOffset:(CGPoint)thePoint {
return CGPointMake(thePoint.x - self.center.x, thePoint.y - self.center.y);
}
// helper to get point back relative to center
-(CGPoint)pointRelativeToCenter:(CGPoint)thePoint {
return CGPointMake(thePoint.x + self.center.x, thePoint.y + self.center.y);
}
// helper to get point relative to transformed coords
-(CGPoint)newPointInView:(CGPoint)thePoint {
// get offset from center
CGPoint offset = [self centerOffset:thePoint];
// get transformed point
CGPoint transformedPoint = CGPointApplyAffineTransform(offset, self.transform);
// make relative to center
return [self pointRelativeToCenter:transformedPoint];
}
// now get your corners
-(CGPoint)newTopLeft {
CGRect frame = [self originalFrame];
return [self newPointInView:frame.origin];
}
-(CGPoint)newTopRight {
CGRect frame = [self originalFrame];
CGPoint point = frame.origin;
point.x += frame.size.width;
return [self newPointInView:point];
}
-(CGPoint)newBottomLeft {
CGRect frame = [self originalFrame];
CGPoint point = frame.origin;
point.y += frame.size.height;
return [self newPointInView:point];
}
-(CGPoint)newBottomRight {
CGRect frame = [self originalFrame];
CGPoint point = frame.origin;
point.x += frame.size.width;
point.y += frame.size.height;
return [self newPointInView:point];
}
Swift 4
extension UIView {
/// Helper to get pre transform frame
var originalFrame: CGRect {
let currentTransform = transform
transform = .identity
let originalFrame = frame
transform = currentTransform
return originalFrame
}
/// Helper to get point offset from center
func centerOffset(_ point: CGPoint) -> CGPoint {
return CGPoint(x: point.x - center.x, y: point.y - center.y)
}
/// Helper to get point back relative to center
func pointRelativeToCenter(_ point: CGPoint) -> CGPoint {
return CGPoint(x: point.x + center.x, y: point.y + center.y)
}
/// Helper to get point relative to transformed coords
func newPointInView(_ point: CGPoint) -> CGPoint {
// get offset from center
let offset = centerOffset(point)
// get transformed point
let transformedPoint = offset.applying(transform)
// make relative to center
return pointRelativeToCenter(transformedPoint)
}
var newTopLeft: CGPoint {
return newPointInView(originalFrame.origin)
}
var newTopRight: CGPoint {
var point = originalFrame.origin
point.x += originalFrame.width
return newPointInView(point)
}
var newBottomLeft: CGPoint {
var point = originalFrame.origin
point.y += originalFrame.height
return newPointInView(point)
}
var newBottomRight: CGPoint {
var point = originalFrame.origin
point.x += originalFrame.width
point.y += originalFrame.height
return newPointInView(point)
}
}
You can find out the coordinates of the rotated view by using basic trigonometry. Here is how you can do it:
The first step is to know your view's width and height. Divide them by 2 and you get your triangle's adjacent and opposite sides (cyan and green respectively). In the example above width = 300 and height = 300. So adjacentSide = 150 and oppositeSice = 150.
Find the hypotenuse (red). For this you use the formula: h^2 = a^2 + b^2. After applying this formula we find the hypotenuse = 212.13
Find theta. This is the angle between the adjacentSide (cyan) and the hypotenuse (red). For this you use the formula cos(theta) = (h^2 + a^2 - o^2)/2*h*o. After applying this formula we find that theta = 0.785 (RADIANS). To convert this to degrees we apply the formula degrees = radians * 180 / PI = 45 (degrees). This is the initial (offset) angle of the hypotenuse. This is very important to realize. IF THE VIEW'S ROTATION OF YOUR VIEW IS ZERO THE HYPOTENUSE HAS AN OFFSET ANGLE OF 45(DEGREES). We're going to need theta shortly.
Now that we know the hypotenuse (red) we need the rotationAngle. In this example I used a UIRotationGestureRecognizer to rotate the square view. This class has a "rotation" property which tells us how much the view has rotated. This value is in RADIANS. In the example above the rotation is 0.3597 RADIANS. To convert it to degrees we use the formula degrees = radians * PI / 180. After applying the formula we find the rotation angle to be 20.61 degrees.
We can finally find the offset width (orange) and height (purple). For width we use the formula width = cos(rotationAngle - theta) * hypotenuse and for height we use the formula height = sen(rotationAngle - theta). WE HAVE TO SUBTRACT THETA (IN RADIANS!) FROM THE ROTATION ANGLE (IN RADIANS TOO!) BECAUSE THETA WAS THE INITIAL OFFSET. View it this way: the hypotenuse had an angle of 45(degrees) when the rotation angle was zero. After applying the formulas we find that width = 193.20 and height = -87.60
Finally, we can add those values (width and height) to the center of the square to find the coordinates of the blue point.
-Example-
// Get the center point
CGPoint squareCenter = self.squareView.center;
// Get the blue point coordinates
CGPoint bluePointCoordinates = CGPointMake(squareCenter.x + width, squareCenter.y + height);
The blue point coordinates are (963.20, 272.40)
To better understand the formulas please see the following links:
Trigonometry 1
Trigonometry 2
Also, if you want to play around with the test project I created (it's the one in the image) please feel free to download it from the following link.
UPDATE
Here is a condensed method that will calculate the offset top-right point (blue) you're looking for.
/* Params:
/ viewCenter: The center point (in superView coordinates) of your view
/ width: The total width of your view
/ height: The total height of your view
/ angleOfRotation: The rotation angle of your view. Can be either DEGREES or RADIANS
/ degrees: A boolean flag indicating whether 'angleOfRotation' is degrees
/ or radians. E.g.: If 'angleOfRotation' is expressed in degrees
/ this parameter must be 'YES'
*/
-(CGPoint)calculateTopRightCoordinatesFromViewCenter:(CGPoint)viewCenter viewWidth:(CGFloat)viewWidth viewHeight:(CGFloat)viewHeight angleOfRotation:(CGFloat)angleOfRotation degrees:(BOOL)degrees {
CGFloat adjacent = viewWidth/2.0;
CGFloat opposite = viewHeight/2.0;
CGFloat hipotenuse = sqrtf(powf(adjacent, 2.0) + pow(opposite, 2.0));
CGFloat thetaRad = acosf((powf(hipotenuse, 2.0) + powf(adjacent, 2.0) - pow(opposite, 2.0)) / (2 * hipotenuse * adjacent));
CGFloat angleRad = 0.0;
if (degrees) {
angleRad = angleOfRotation*M_PI/180.0;
} else {
angleRad = angleOfRotation;
}
CGFloat widthOffset = cosf(angleRad - thetaRad) * hipotenuse;
CGFloat heightOffset = sinf(angleRad - thetaRad) * hipotenuse;
CGPoint offsetPoint = CGPointMake(viewCenter.x + widthOffset, viewCenter.y + heightOffset);
return offsetPoint;
}
Hope this helps!
You should use:
CGPoint CGPointApplyAffineTransform (
CGPoint point,
CGAffineTransform t
);
To get a specific point, use the view's bounds and center, and then apply the view's transform to get a new point after transform. This is better than adding code specifically for rotation transform, as it can support any transform as well as chaining.
All of these answers are nuts, this is so simple...
CGPoint topLeft = [rotatedView convertPoint:CGPointMake(0, 0) toView:rotatedView.superview];
CGPoint topRight = [rotatedView convertPoint:CGPointMake(rotatedView.bounds.size.width, 0) toView:rotatedView.superview];
CGPoint bottomLeft = [rotatedView convertPoint:CGPointMake(0, rotatedView.bounds.size.height) toView:rotatedView.superview];
CGPoint bottomRight = [rotatedView convertPoint:CGPointMake(rotatedView.bounds.size.width, rotatedView.bounds.size.height) toView:rotatedView.superview];
Try this code
CGPoint localBeforeTransform = CGPointMake( view.bounds.size.width/2.0f, view.bounds.size.height/2.0f ); // lower left corner
CGPoint localAfterTransform = CGPointApplyAffineTransform(localBeforeTransform, transform);
CGPoint globalAfterTransform = CGPointMake(localAfterTransform.x + view.center.x, localAfterTransform.y + view.center.y);
Why the mess and fuss? Keep it simple? Where x was before the transform, it'll be q rads/degrees further just as every other point around the anchor is.
was going to explain it all, but this chap in this post explained it in even shorter context:
Get the current angle/rotation/radian for a UIview?
CGFloat radians = atan2f(yourView.transform.b, yourView.transform.a);
CGFloat degrees = radians * (180 / M_PI);
I wrote this class that can help us:
TransformedViewFrameCalculator.h
#import <Foundation/Foundation.h>
#interface TransformedViewFrameCalculator : NSObject
#property (nonatomic, strong) UIView *viewToProcess;
- (void)calculateTransformedCornersWithTranslation:(CGPoint)translation
scale:(CGFloat)scale
rotation:(CGFloat)rotation;
#property (nonatomic, readonly) CGPoint transformedTopLeftCorner;
#property (nonatomic, readonly) CGPoint transformedTopRightCorner;
#property (nonatomic, readonly) CGPoint transformedBottomLeftCorner;
#property (nonatomic, readonly) CGPoint transformedBottomRightCorner;
#end
TransformedViewFrameCalculator.m:
#import "TransformedViewFrameCalculator.h"
#interface TransformedViewFrameCalculator ()
#property (nonatomic, assign) CGRect viewToProcessNotTransformedFrame;
#property (nonatomic, assign) CGPoint viewToProcessNotTransformedCenter;
#end
#implementation TransformedViewFrameCalculator
- (void)setViewToProcess:(UIView *)viewToProcess {
_viewToProcess = viewToProcess;
CGAffineTransform t = _viewToProcess.transform;
_viewToProcess.transform = CGAffineTransformIdentity;
_viewToProcessNotTransformedFrame = _viewToProcess.frame;
_viewToProcessNotTransformedCenter = _viewToProcess.center;
_viewToProcess.transform = t;
}
- (void)calculateTransformedCornersWithTranslation:(CGPoint)translation
scale:(CGFloat)scale
rotation:(CGFloat)rotation {
double viewWidth = _viewToProcessNotTransformedFrame.size.width * scale;
double viewHeight = _viewToProcessNotTransformedFrame.size.height * scale;
CGPoint viewCenter = CGPointMake(_viewToProcessNotTransformedCenter.x + translation.x,
_viewToProcessNotTransformedCenter.y + translation.y);
_transformedTopLeftCorner = [self calculateCoordinatesForViewPoint:CGPointMake(0, 0)
fromViewCenter:viewCenter
viewWidth:viewWidth
viewHeight:viewHeight
angleOfRotation:rotation];
_transformedTopRightCorner = [self calculateCoordinatesForViewPoint:CGPointMake(0, viewHeight)
fromViewCenter:viewCenter
viewWidth:viewWidth
viewHeight:viewHeight
angleOfRotation:rotation];
_transformedBottomLeftCorner = [self calculateCoordinatesForViewPoint:CGPointMake(viewWidth, 0)
fromViewCenter:viewCenter
viewWidth:viewWidth
viewHeight:viewHeight
angleOfRotation:rotation];
_transformedBottomRightCorner = [self calculateCoordinatesForViewPoint:CGPointMake(viewWidth, viewHeight)
fromViewCenter:viewCenter
viewWidth:viewWidth
viewHeight:viewHeight
angleOfRotation:rotation];
}
- (CGPoint)calculateCoordinatesForViewPoint:(CGPoint)viewPoint
fromViewCenter:(CGPoint)viewCenter
viewWidth:(CGFloat)viewWidth
viewHeight:(CGFloat)viewHeight
angleOfRotation:(CGFloat)angleOfRotation {
CGPoint centeredViewPoint = CGPointMake(viewPoint.x - viewWidth/2.0, viewPoint.y - viewHeight/2.0);
CGPoint rotatedCenteredViewPoint = CGPointApplyAffineTransform(centeredViewPoint, CGAffineTransformMakeRotation(angleOfRotation));
CGPoint rotatedViewPoint = CGPointMake(rotatedCenteredViewPoint.x + viewCenter.x, rotatedCenteredViewPoint.y + viewCenter.y);
return rotatedViewPoint;
}
For example, I use it to restrict the move/scale/rotation of a sticker inside a container view in the following way:
#property (nonatomic, strong) TransformedViewFrameCalculator *transformedFrameCalculator;
...
self.transformedFrameCalculator = [TransformedViewFrameCalculator new];
self.transformedFrameCalculator.viewToProcess = someView;
...
- (BOOL)transformedView:(UIView *)view
withTranslation:(CGPoint)translation
scale:(double)scale
rotation:(double)rotation
isFullyInsideValidFrame:(CGRect)validFrame {
[self.transformedFrameCalculator calculateTransformedCornersWithTranslation:translation
scale:scale
BOOL topRightIsInsideValidFrame = CGRectContainsPoint(validFrame, self.transformedFrameCalculator.transformedTopRightCorner);
BOOL topLeftIsInsideValidFrame = CGRectContainsPoint(validFrame, self.transformedFrameCalculator.transformedTopLeftCorner);
BOOL bottomRightIsInsideValidFrame = CGRectContainsPoint(validFrame, self.transformedFrameCalculator.transformedBottomRightCorner);
BOOL bottomLeftIsInsideValidFrame = CGRectContainsPoint(validFrame, self.transformedFrameCalculator.transformedBottomLeftCorner);
return topRightIsInsideValidFrame && topLeftIsInsideValidFrame && bottomRightIsInsideValidFrame && bottomLeftIsInsideValidFrame;
}
I have this code into the - (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context method (into a MKOverlayView subclass) to prevent drawing segments that are less than 10 pixels long on a map overlay :
CGPoint origin = [self pointForMapPoint:poly.points[0]];
CGPoint lastPoint = origin;
CGContextMoveToPoint(context, origin.x, origin.y);
for (int i=1; i<poly.pointCount; i++) {
CGPoint point = [self pointForMapPoint:poly.points[i]];
CGFloat xDist = (point.x - lastPoint.x);
CGFloat yDist = (point.y - lastPoint.y);
CGFloat distance = sqrt((xDist * xDist) + (yDist * yDist)) * zoomScale;
if (distance >= 10.0) {
lastPoint = point;
CGContextAddLineToPoint(context, point.x, point.y);
}
}
will the test >= 10.0 will take care about the screen resolution, or may I introduce some [UIScreen mainScreen].scale parameter ?
I believe that test >= 10.0 does not take into account the screen resolution. Apple does most of their drawing arithmetic using "points" instead of pixels- that way code does not have to change for a retina display compared to a normal display.
If you want to draw something just 10.0 pixels wide, you will need to take into account the screen resolution; however, if you do this you'll have to write the method to support both retina display and normal display.
It depends on how the graphics context is configured. If this is in UIView drawing code, the view's scale factor (which is set automatically) will take care of this, if you're drawing into a bitmap context, you have to do it manually.
i use following code to move my Box2D object into screen, but because gravity of my world or something else i dont know why my objects is forced to move down, i am new to box2d.
i want to move my object in entire world without gravity.
-(void) tick:(NSTimer *)timer {
int32 velocityIterations = 8;
int32 positionIterations = 1;
world->Step(1.0f/60.0f, velocityIterations, positionIterations);
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL)
{
UIView *oneView = (UIView *)b->GetUserData();
CGPoint newCenter = CGPointMake(b->GetPosition().x * PTM_RATIO,self.view.bounds.size.height - b->GetPosition().y * PTM_RATIO);
oneView.center = newCenter;
CGAffineTransform transform = CGAffineTransformMakeRotation(- b->GetAngle());
oneView.transform = transform;
}
}
}
my accelerometer code is as follow.
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
b2Vec2 gravity;
gravity.Set( acceleration.x * 1.81, acceleration.y * 1.81 );
world->SetGravity(gravity);
}
pleas if any one work around.
Thanks.
As i understand you want to move your object setting it's position. It's a bad idea because it will provide non-physical behavior of the bodies colliding with your object. That's because if you will only change the position of your body it's velocity for physics engine will be still zero and collision will be processed according to zero speed of your object.
A better solution is to use b2_kinematicBody type for your object. Then you will be able to control it's motion specifying it's velocity vector and physics will behave as expected. Also the gravity (and no other forces) will not be applied to your object because of it's type.
EDIT
//creation
b2BodyDef bDef;
bDef.type = b2_kinematicBody;
bDef.position.Set(5, 6);
b2Body *body = physWorld->CreateBody(&bDef);
//control
body->SetLinearVelocity(b2Vec2(3, 4));