Draw a hypothetical line in swift - ios

So in my game a have this paddle and a ball, and i want to calculate which side of the paddle that the ball hits, i found this answer in C# which shows drawing two lines like this:
So what i want to do is draw two hypothetical lines(meaning invisible to the user) so i can calculate if the ball is greater then both the lines or if its in contact with one of the sides of the paddle.
How do i draw these lines in sprite kit and swift?
UPDATE
I found the original answer, its HERE

You can check the position of the ball in relation to the paddle.
If(ballNode.position.x > paddleNode.position.x) {
// ball is on the right of the paddle
} else {
// ball is on the left of the paddle
}
If(ballNode.position.y > paddleNode.position.y) {
// ball is above the paddle
} else {
// ball is below the paddle
}

Related

Detecting when SKSpriteNode is completely below another SKSpriteNode

For a game I'm creating, an SKSpriteNode gradually makes its way down the user's screen. There's another SKSpriteNode (position is static) near the bottom of the screen, leaving only a little bit of space for the original SKSpriteNode to fit in. I need to detect when the first SKSpriteNode is COMPLETELY below the second SKSpriteNode, which I'm having a bit of trouble with. Here's the code I'm currently using:
if (pos.y > barPosY) //pos.y = 1st SKSpriteNode, barPosY = 2nd SKSpriteNode
{
touchedTooEarly = true
}
For some reason, when the first SKSpriteNode goes just a little bit over the 2nd SKSpriteNode (not all the way), it still detects it as being completely over. Is there a coordinate space issue I'm missing?
The logic
A sprite a covers a sprite b if
b.frame is inside a.frame
b.zPosition is below a.zPosition
The extension
Now let's build an extension
extension SKSpriteNode {
func isCoveredBy(otherSprite: SKSpriteNode) -> Bool {
let otherFrame = CGRect(
origin: convertPoint(otherSprite.position, fromNode: otherSprite),
size: otherSprite.frame.size
)
return zPosition < otherSprite.zPosition && CGRectContainsRect(frame, otherFrame)
}
}
Problem #1: transparency
This mechanism totally ignores transparency.
Problem #2: same sprite
If you compare 2 sprites of the same type the function CGRectContainsRect will return true only when they are exactly aligned. Althoug you can solve this problem creating a smaller rectangle when you compare the sprites.

Put a ball inside a rectangle trapped inside, with some velocity and restitution

In this scene:
let rectangle = SKShapeNode(rectangleOfSize: CGSize(300, 400))
rectangle.fillColor = UIColor.clearColor()
rectangle.strokeColor = UIColor.grayColor()
rectangle.strokeWidth = 10
self.addChild(rectangle)
I want to put a ball inside this rectangle, trapped inside, with some velocity and restitution, that will be bouncing and changing the vector direction when collides with one of the walls.
I am not 100% sure if you can do that with SKShapeNodes and physics bodies because the physics body will apply to the whole shape node (with center).
Since you want to make the rectangle visible you can could either make a SKSpriteNode subclass with 4 SKSpriteNodes sides and than shape them as a rectangle.
Alternatively you could just draw a rectangle border in your program of choice, just make sure the centre is nothing basically, and export as PNG. Than just create a SKSpriteNode with the image.
let rectangle = SKSpriteNode(imageNamed: "Rectangle")
let texture = SKTexture(imageNamed: "Rectangle")
rectangle.physicsBody = SKPhysicsBody(texture: texture, size: texture.size())
rectangle.physicsBody?.collisionBitMask = 1
Now if you have drawn the rectangle correctly it will only have a physics body on the 4 sides since you did not draw a centre.
Than you simply create your ball and give it a physics body like above, with the same collision bitMask. Position it in the centre of the rectangle and give it an impulse or something. It should bounce around as you wish without leaving the rectangle.
If you are unsure about physics bodies than you need to read a bit about it, e.g
http://www.techotopia.com/index.php/A_Swift_iOS_8_Sprite_Kit_Collision_Handling_Tutorial

Adding SKPhysicsBody causes the SKSpriteNode to shake

I have two SkSpriteNodes called left-ball and right-ball.THey flow from sides of the screen.
I implemented the collision detection for these two balls. However I noticed that before I add collision detection, the balls were moving smoothly without any shaking effect, but after I add the collision detection, the balls were shaking and moving in their path.
I am using the same bit category for both of these balls:
static const int ballHitCategory = 1;
without shaking:
with shaking:
Here is what I tried in code:
_leftBall.physicsBody=[SKPhysicsBody bodyWithRectangleOfSize:_leftBall.frame.size];
_leftBall.physicsBody.categoryBitMask=ballHitCategory;
_leftBall.physicsBody.contactTestBitMask=ballHitCategory;
_leftBall.physicsBody.collisionBitMask=ballHitCategory;
_leftBall.physicsBody.dynamic=YES;
_leftBall.physicsBody.usesPreciseCollisionDetection=YES;
_rightBall.physicsBody=[SKPhysicsBody bodyWithRectangleOfSize:_rightBall.frame.size];
_rightBall.physicsBody.categoryBitMask=ballHitCategory;
_rightBall.physicsBody.contactTestBitMask=ballHitCategory;
_rightBall.physicsBody.collisionBitMask=ballHitCategory;
_rightBall.physicsBody.dynamic=YES;
_rightBall.physicsBody.usesPreciseCollisionDetection=YES;
-(void)didBeginContact:(SKPhysicsContact *)contact
{
_leftBall = (SKSpriteNode*)contact.bodyA.node;
_rightBall = (SKSpriteNode *)contact.bodyB.node;
if(_leftBall.physicsBody .categoryBitMask == ballHitCategory || _rightBall.physicsBody.categoryBitMask == ballHitCategory)
{
NSLog(#" hit the ");
//setup your methods and other things here
[_leftBall removeFromParent];
[_rightBall removeFromParent];
}
}
Please note that shake happens only after I add the collision detection, If I remove the above code, everything is fine.
What is the proper way to add collision detection without effecting the skspritenode ?
so youre moving the sprites using non physics code.. but theyre still part of the physics simulation. I'm guessing theyre fighting against the force of gravity.
either set affectedByGravity on each sprite to false
or you can turn off gravity in your game completely
[self.physicsWorld setGravity:CGVectorMake(0, 0)];
Don't worry about the Gravity. You should set your spritenode:
_leftBall.physicsBody.dynamic=YES;
_leftBall.physicsBody.affectedByGravity=NO;
Same on _rightBall

How to attach a new sprite to a moving sprite?

I'm using SpriteKit for a game where there is a ball and a character. The character is moving in a line with SKAction and the user can move the ball by touch. When the ball and character makes contact, I'd like the ball to be attached to the character.
func didBeginContact(contact: SKPhysicsContact) {
if contact.bodyA.categoryBitMask == charMask && contact.bodyB.categoryBitMask == ballMask{
println("contact")
if contactMade {
let movingBall = contact.bodyB.node!.copy() as! SKSpriteNode
//this line of code doesn't affect anything no matter what coordinates i set it to
movingBall.position = contact.bodyA.node!.position
contact.bodyB.node!.removeFromParent()
contact.bodyA.node!.removeAllActions()
contact.bodyA.node!.addChild(movingBall)
}
}
}
The current issue is that when I do contact.bodyA.node!.addChild(ball) (character node), the ball gets attached to the far left side of the character instead of on the character and it seems setting movingball.position does not affect it. I've also tried doing addChild to the scene and although it adds the ball to the correct place, it doesn't move with the character without another SKAction. What did I do wrong/what can I do to fix it?
Also, instead of using 2 sprites like that, should I use separate sprites so that theres a character sprite without a ball, character sprite with a ball and the ball itself, then just change the node's texture when they contact?
as movingBall is to be a child of bodyA.node, it's position needs to be in bodyA.node's coordinate space. So if you gave it coordinates of (0,0) it'd be in the middle:
Replace:
movingBall.position = contact.bodyA.node!.position
with
movingBall.position = CGPointZero
and see how that looks. the ball should be positioned directly on top of bodyA.node.

CGRectIntersectsRect at a specific point of the objects?

Like in a Mario game where if you jump and land on top of a monster, the monster gets knocked out.
I'm using CGRectIntersectsRect between the two objects (player and monster); however, the monster will get knocked out from any direction.
How do I intersect two objects at specific points of the objects?
I actually created separate blank objects in each direction for this to work. Is there a more efficient solution?
Instead of CGRectIntersectsRect you can use CGRectIntersection to get a new CGRect of the area of intersection. If the player hit from the side, then this rectangle will be taller than it is wide. If the player hit from the top the rectangle will be wider than it is tall, but you will need to check for top vs. bottom maybe. In that case, you can compare the Y values of the enemy rectangle with the intersection. If the player hit from the top, the Y values of the intersection and the enemy rectangle will be equal. Otherwise, the player hit from the bottom.
typedef NS_ENUM(NSUInteger, IntersectFrom) {
IntersectFromNotIntersect,
IntersectFromTop,
IntersectFromBottom,
IntersectFromLeft,
IntersectFromRight
};
IntersectFrom CGRectGetIntersectFrom(CGRect rectPlayer, CGRect rectMonster) {
CGRect rectIntersect = CGRectIntersection(rectPlayer, rectMonster);
if(!CGRectIsNull(rectIntersect)) {
if(CGRectGetWidth(rectIntersect) < CGRectGetHeight(rectIntersect)) {
// LEFT or RIGHT
if(CGRectGetMinX(rectIntersect) == CGRectGetMinX(rectMonster)) {
return IntersectFromLeft;
}
else {
return IntersectFromRight;
}
}
else {
// TOP or BOTTOM
if(CGRectGetMinY(rectIntersect) == CGRectGetMinY(rectMonster)) {
return IntersectFromBottom;
}
else {
return IntersectFromTop;
}
}
}
else {
return IntersectFromNotIntersect;
}
}

Resources