determine if a sprite is on screen or not in cocos2d - iphone

i want to determine if the sprite is in the screen or not in cocos2d.
am using the code some thing like these.
CGSize winSize = [CCDirector sharedDirector].winSize;
if (_SmallBlueAlien1.position.x> 0 || _SmallBlueAlien1.position.x > winSize.width || _SmallBlueAlien1.position.y> 0 || _SmallBlueAlien1.position.y > winSize.height)
{
//Sprite is not in the screen)
}
but not working properly. were am mistaking.
correct me

Unless you changed the anchor point of the sprite this is only testing if half of the sprite is on the screen. To fix this you want to check if
_SmallBlueAlien1.position.x > [_SmallBlueAlien1 contentSize].texture.width / 2;
You can follow this process for all the other interactions.
//Edit
As phix23 noted this does not account for rotation or scale but should work if you are doing neither of those.

regardless of the semantics of 'position' in coco, your '>' should be '<' for both x and y, assuming your interpretation of the .position property holds. It is likely however that the 'sprite'.position is in reference to an enclosing object, thus even when your test is corrected, it may still not give you what you want to know ('visible on screen').

Related

Prevent SKPhysicsBody From Pushing SKSpriteNode Upwards

I currently have two SKSpriteNodes on top of each other like so (The white part is one and the brown round circle part is the other one):
The white part is positioned 1/3 the way down on top of the round brown sprite node. In the picture, the brown round part has a SKPhysicsBody applied to it already as seen by the light blue outline around it. When I add a SKPhysicsBody around the top ovalish white part it pushes it up and not in the position I wanted it.
How can I have a SKPhysics body coving both bodies of sprites but not have the physics bodies push on one another which makes the white part move upwards? I would like the white part to stay in the position it was in the first image.
Thanks for anyone help!
Here's the code I used for the SKPhysicsBody's:
// create, position, scale & add the round body
roundBody = SKSpriteNode( imageNamed: "roundBody" )
roundBody.position = CGPoint( x: 207, y: 70 )
roundBody.zPosition = 1
roundBody.xScale = 0.3
roundBody.yScale = 0.3
// add sprite node to view
self.addChild( roundBody )
// create, position, scale & add the head
theHead!.position = CGPoint( x: 207, y: roundBody.frame.maxY / 1.15 )
theHead!.zPosition = 2
theHead!.xScale = 0.3
theHead!.yScale = 0.3
// setting up a SKPhysicsBody for the round body
roundBody.physicsBody = SKPhysicsBody( circleOfRadius: roundBody.size.width / 4 )
roundBody.physicsBody!.dynamic = true
roundBody.physicsBody!.affectedByGravity = true
roundBody.physicsBody!.allowsRotation = false
roundBody.physicsBody!.pinned = false
// setting up a SKPhysicsBody for the head
theHead!.physicsBody = SKPhysicsBody(circleOfRadius: theHead!.size.width / 2 )
theHead!.physicsBody!.dynamic = true
theHead!.physicsBody!.affectedByGravity = false
theHead!.physicsBody!.allowsRotation = false
theHead!.physicsBody!.pinned = false
I was able to figure out that if you use SKPhysicsJointPin it does the exact thing I needed! (Which was to basically pin a sprite head on it's body and share a physics body)
let joinTogether = SKPhysicsJointPin.jointWithBodyA(
roundBody.physicsBody!,
bodyB:theHead!.physicsBody!,
anchor: GPointMake(CGRectGetMidX(roundBody.frame),
CGRectGetMinY(theHead!.frame)))
scene!.physicsWorld.addJoint(joint)
Hope this helps someone in the future!
If you never want it to move, set it's .dynamic property to false. Then other objects may or may not bounce/collide with it (depending upon their collisionBitMask) but it won't move in response to those collisions.
Your own answer is correct and a better solution but just to explain further.
The reason of the bodies colliding is that by default a physics body's collision bit mask is set to all categories which means it will collide with everything. In your code you are not calling
roundBody.physicsBody?.collisionBitMask = ...
which is why its using the default values.
To change that you could give your body and head a different collisionBitMask.
Im sure you will deal with this sooner or later when you handle collisions
Also as a tip it's a better idea to not force unwrap the physics bodies unless you have too, even though you know they exist. So you should replace your ! with ? whenever possible.

Flipping a child sprite's xscale in Spritekit using Swift

Alright I'm offically stumped. I've been able to figure out my problems myself in the past but I'm lost on this one.
I'm trying to flip a child sprite's xscale. I want the flip to occur when the child's x position is negative. With the code below, the sprite does flip, every time the sprite reaches negative position, it loops back and forth flipping until reaching positive again.
I've tried numerous variations, but this is the code in it's simplest form. Any help or alternatives would be appreciative.
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
let pin = childNodeWithName(Pin1) as SKSpriteNode!
let guyPoint = guy.convertPoint(guy.position, fromNode: pin)
if guyPoint.x <= 0 {
guy.xScale = -1
}
else {
guy.xScale = 1
}
}
So if it is constantly flipping it's probably an issue of coordinate space. So check to make sure your convertPoint method is accurately returning the point you want. I would use println() to see what's going on there.
Probably what's happening is you want to flip the xScale when the child node is negative in the scene space or something (i.e. when the child is off the screen) but instead guyPoint might be the position of the child in its parent's coordinate space (so relative to the parent).
Also try with and without the else{} part to see if that changes anything.

Physicsjs Screen wrap

I am currently having a bit of trouble making objects in my world wrap. It sort of works, but very often objets appear to get stuck on the boundaries. My wrap code is as follows:
// Wrap our position if we are outside of the world bounds
if (this.state.pos.get(0) > 860) {
this.state.pos.set(0, this.state.pos.get(1));
}
else if (this.state.pos.get(0) < 0) {
this.state.pos.set(860, this.state.pos.get(1));
}
if (this.state.pos.get(1) > 640) {
this.state.pos.set(this.state.pos.get(0), 0);
}
else if (this.state.pos.get(1) < 0) {
this.state.pos.set(this.state.pos.get(0), 640);
}
Is there a better way of doing this? Should I use a translation on the object's position vector rather than simply setting it?
Without a jsfiddle it's a bit hard to diagnose, however this might be due to the this.state.old.pos not being set too. If the position (only) is set, then the velocity will be calculated as the difference between the current and the previous positions (in accordance with verlet integration). In that case, you're implicitly giving the body a huge velocity.
I'd recommend adding/subtracting an amount rather than setting, then you can do the same with the old position.
Here's a working example: http://labs.minutelabs.io/Relativistic-Space-Sheep/
With the relevant line of code: https://github.com/minutelabsio/Relativistic-Space-Sheep/blob/master/library/js/mediators/boilerplate.js#L743

Pygame check for collisions with the top most foreground rect

I have 10 sprites which I objects of the main sprite I wrote with different images and starting positions etc. But they all behave the same way. They are sub sprites of the main sprite.
I want to be able to hold mouse click on one's rect and move it round the screen which works perfectly fine. But the problem is they all have the same controls click and drag to move them. So if I am clicking on one of the sprite rects and I drag it over another one it picks it up as well. And I don't want that to happen.
Is there a way to only check for collisions with the top most foreground rect or if someone could explain a way of doing this that would achieve similar results. I have had a look at the rect documentation but I can't find a solution.
def update(self,):
self.move(self.rect)
def move(self,rect):
if pygame.mouse.get_pressed() == (1, 0, 0) and the_rect.collidepoint(pygame.mouse.get_pos()):
self.state = 1
elif pygame.mouse.get_pressed() == (0, 0, 0) and the_rect.collidepoint(pygame.mouse.get_pos()):
self.state = 0
if self.state == 0:
the_rect.centerx = the_rect.centerx
the_rect.centery = the_rect.centery
elif self.state == 1:
(the_rect.centerx, the_rect.centery) = pygame.mouse.get_pos()
Rather than using the pygame.mouse.get_pressed() function, use the event queue and check for a pygame.MOUSEBUTTONDOWN event. It will only get fired once when the button is first pressed.

Drag sprite in cocos2d for the iPhone - with a max velocity

I'm trying to make a game where the user is supposed to drag a sprite up and down on the screen, avoiding incoming obstacles. The last answer here helped me to drag the sprite around on the screen, but I want to set a maximum speed the sprite can be moved (and hopefully with a natural-looking acceleration/deceleration), so it doesn't get too easy to avoid the objects.
Does anybody know how I can modify the code to achieve this, or is there another way to to it?
Thanks :)
You'll need to maintain a CGPoint destinationPosition variable which is the location of your finger and use an update loop to modify it's position:
-(void) update:(ccTime) dt
{
CGPoint currentPosition = draggableObject.position.x;
if (destination.x != currentPosition.x)
{
currentPosition.x += (destination.x - currentPosition.x) / 5.0f; // This 5.0f is how fast you want the object to move to it's destination
}
if (destination.y != currentPosition.y)
{
currentPosition.y += (destination.y - currentPosition.y) / 5.0f;
}
draggableObject.postion = currentPosition;
}
In the ifs, you might want to check if the objects are close to each other, rather than exactly the same number to allow for rounding errors.
You just need to have an if statement in whatever schedule updater you are using, like time, or touches, or whatever.
I'm presuming you have x/y velocities? Just inside your update statement, wherever your acceleration is -
if(acceleration.x > 20){
acceleration.x = 20;
}
if(acceleration.y > 20){
acceleration.y = 20;
}