swift correct syntax if else while etc - swift

I have a SKSpritenode which can be dragged around the screen, within a boundary.
I have a test for being within the boundary.
if backgroundRect.contains(paddleRect){
let paddleX = paddle.position.x + (touchLocation.x - previousLocation.x)
let paddleY = paddle.position.y + (touchLocation.y - previousLocation.y)
paddle.position = CGPoint(x: paddleX, y: paddleY)
} else {
print ("paddleRect not contained by backgroundRect")
}
At the moment I can drag the paddle around within the background. When I drag the paddle and it hits the edge of the background then it isn't contained within the background and stops so I can't move it anymore.
I would like be able to move it just within the background rectangle but not stop responding to drags at the edge. I know "if else" isn't the correct way to do this, but am wondering how I write it so the paddle keeps moving, within the bounds of the background rectangle.
Is it a "while continue" loop? or something else?

The issue is that once you exit the rectangle, you lose the ability to change the position of the paddle. Because of that, every subsequent check of backgroundRect.contains(paddleRect) will return false, forever.
What you should do instead is always compute the potential position, and either use it, or discard it:
let potentialPosition = CGPoint(
x: paddle.position.x + (touchLocation.x - previousLocation.x),
y: paddle.position.y + (touchLocation.y - previousLocation.y)
)
// This line is approximated, I don't know the exact relation between
// `paddleRect` and `paddle`, but you get the idea
if backgroundRect.contains(potentialPosition) {
paddle.position = potentialPosition
} else {
print ("paddleRect not contained by backgroundRect")
}

Related

Why does SKNode() when assigned to a variable spawns an endless horde of enemies?

So I'm making a game where enemies fly past you and despawn when they die or leave the screen, and I was also making a play/pause button, and in order to do so I made a variable called worldNode and assigned it SKNode(). I made the variable inside no function but inside the GameScene class. Then every time I added something, I would do
worldNode.addChild(thing)
Since that allows me to pick and choose what gets paused and unpaused without freezing the whole game. But when I do it to these lines of code it spawns every enemy in at once, immediately killing the player. This code is from the update function.
if currentWave.enemies.isEmpty {
for (index, position) in positions.shuffled().enumerated() {
let enemy = EnemyNode(type: enemyTypes[enemyType], startPosition: CGPoint(x: enemyStartX, y: position), xOffset: enemyOffsetX * CGFloat(index * 3), moveStraight: true)
worldNode.addChild(enemy)
}
} else {
for enemy in currentWave.enemies {
let node = EnemyNode(type: enemyTypes[enemyType], startPosition: CGPoint(x: enemyStartX, y: positions[enemy.position]), xOffset: enemyOffsetX * enemy.xOffset, moveStraight: enemy.moveStraight)
worldNode.addChild(node)
}
}
only for the addChild(node) does this happen, and I can't leave it out because then they keep flying around the screen. What would I do to fix this?

Swift: SKConstraint for scale? (or equivalent) Stuttering

At the minute I'm using the SKConstraint.positionX(rangex, y: rangey) to confine my SKCameraNode within the game board I've created. This is nice because when you hit the boundary there's no stuttering. But my current way to cap the scale of the camera creates a stutter as it hits the bound as it goes past and pings back.
#objc func zoomedView(_ sender:UIPinchGestureRecognizer) {
if newCamera.xScale > 0.148{
let pinch = SKAction.scale(by: 1/sender.scale, duration: 0.0)
newCamera.run(pinch)
sender.scale = 1.0
} else {newCamera.setScale(0.148)}
}
Is there an SKConstraint for scale (or equivalent) which is a better way to stop this stutter? Thanks :)
There is no direct SKConstraint equivalent for scale, however the reason you're experiencing the stuttering is as you go over the bound it snaps back the next time the function is called, rather before a frame is rendered, so theoretically you could zoom in massively instantaneously, and stay there until you activate the zoom function again.
A way to create an equivalent is to put the code checking whether the scale is greater than x in the rendering loop as outlined here.
So if you were to check at the last possible moment:
override func didFinishUpdate() {
if newCamera.xScale < 0.148{
newCamera.setScale(0.148)
} else if newCamera.xScale > 10{
newCamera.setScale(10)
}
}

How do run an SKAction on a group of SKSpriteNodes with the same name?

I'm making a game in Xcode 6 using spriteKit and swift. I have a plane on scene, and to make it look like its moving, I'm create clouds off the scene to the left of the screen. I then us an SKAction to move the cloud to the right side of the screen. This works great. You then click to jump off the plane, and the plane moves up off the scene. I then have it start making the clouds on the bottom of the scene, then they move up off the top of the scene, but the problem is, the already existing clouds still have to move to the right side of the screen. My question is, how do I make it so all of the existing clouds stop their action that moves them to the right, then begin to move up exactly where they are? How do I access the group of existing clouds all at the same time once they have been created? I also want the clouds to slow down after you have jumped when you tap the screen to open your parachute, but this should be able to be done by ending the SKAction that moves the clouds, then using another SKAction on them that moves them up slower, but I don't know how to access a group of SKSpriteNodes.
Here is the code that I have to make the clouds:
//This is how the cloud is first declared at the top of the .swift file
var cloud = SKSpriteNode()
//This is the function that runs every certain interval through an NSTimer
func createCloud()
{
cloud = SKSpriteNode(imageNamed: "cloud")
cloud.xScale = 1.25
cloud.yScale = cloud.xScale/2
cloud.zPosition = -1
self.addChild(cloud)
if personDidJump == false
{
let moveRight = SKAction.moveToX(CGRectGetWidth(self.frame) + CGRectGetWidth(cloud.frame), duration: cloudSpeed)
var apple = CGRectGetWidth(self.frame)
var randomNumber:CGFloat = CGFloat(arc4random_uniform(UInt32(apple)))
cloud.position = CGPointMake(-CGRectGetWidth(cloud.frame), randomNumber)
cloud.runAction(moveRight)
}
if personDidJump == true
{
let moveUp = SKAction.moveToY(CGRectGetHeight(self.frame) + CGRectGetWidth(cloud.frame), duration: cloudSpeed)
var apple = CGRectGetWidth(self.frame)
var randomNumber:CGFloat = CGFloat(arc4random_uniform(UInt32(apple)))
cloud.position = CGPointMake(randomNumber, -CGRectGetHeight(cloud.frame))
cloud.runAction(moveUp)
}
}
Also, should I be worried about deleting the clouds when they move off the scene? Or can I just leave them there because you can't see them, and from what I've seen, they don't lag you.
Any help would be greatly appreciated. Thank you.
-Callum-
Put your clouds in an array. When your player jumps (or whenever you need to move them) run through the array and run your action on each cloud.
stackoverflow.com/a/24213529/3402095
^ That is where I found my answere ^
When you make a node give it a name:
myNode.name = "A Node Name"
self.addChild(myNode)
If there are a lot of these nodes, later you can change properties or preform SKAcions on these nodes or do whatever you want to do by using enumerateChildNodesWithName:
self.enumerateChildNodesWithName("A Node Name")
{
myNode, stop in
myNode.runAction(SKAction.moveToY(CGRectGetHeight(self.Frame), duration: 1)
}
I hope this is useful to whoever may need it.

Move a particular sprite to a target position on touch in unity 4.6

I have just started unity. I have 4 Images(sprites) aligned in a grid. Now i want to move an image to a target position as soon as I touch the image. How can i do that?
I wrote the following code for move:
void Update () {
float step=speed*Time.deltaTime;
transform.position=Vector3.MoveTowards(transform.position,target.position,step);
}
I just don't know to move that particular sprite on which I touch.
Thanks
From http://answers.unity3d.com/questions/420808/how-to-get-position-of-touch-on-touch-screen.html
fingerPos = Input.GetTouch(0).position;
Vector3 pos = fingerPos;
pos.z = transform.position.z;
// simplified check
if (transform.position == Camera.main.ScreenToWorldPoint(pos))
{
// move towards the target as you want
}
Notice that i kept it brief with that if, but, of course, you should check if the touch position is withing the boundaries of your object.

Stage scaling affecting AS3

I have some code that controls a serious of images to produce and 360 spin when dragging mouseX axis. This all worked fine with the code I have used.
I have since had to design for different platform and enlarge the size of the stage i did this by scale to stage check box in the document settings.
While the mouse down is in action the spin works fine dragging through the images as intended but when you you release and start to drag again it doesn't remember the last frame and jumps to another frame before dragging fine again? Why is it jumping like this when all I have done is change the scale of everything?
please see code use to
//ROTATION OF CONTROL BODY X
spinX_mc.stop();
var spinX_mc:MovieClip;
var offsetFrame:int = spinX_mc.currentFrame;
var offsetX:Number = 0;
var percent:Number = 0;
//Listeners
spinX_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
spinX_mc.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function startDragging(e:MouseEvent):void
{
// start listening for mouse movement
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
}
function stopDragging(e:MouseEvent):void
{
("stopDrag")
// STOP listening for mouse movement
spinX_mc.removeEventListener(MouseEvent.MOUSE_MOVE,drag);
// save the current frame number;
offsetFrame = spinX_mc.currentFrame;
removeEventListener(MouseEvent.MOUSE_DOWN, startDragging);
}
// this function is called continuously while the mouse is being dragged
function drag(e:MouseEvent):void
{
trace ("Drag")
// work out how far the mouse has been dragged, relative to the width of the spinX_mc
// value between -1 and +1
percent = (mouseX - offsetX) / spinX_mc.width;
// trace(percent);
// work out which frame to go to. offsetFrame is the frame we started from
var frame:int = Math.round(percent * spinX_mc.totalFrames) + offsetFrame;
// reset when hitting the END of the spinX_mc timeline
while (frame > spinX_mc.totalFrames)
{
frame -= spinX_mc.totalFrames;
}
// reset when hitting the START of the spinX_mc timeline
while (frame <= 0)
{
frame += spinX_mc.totalFrames;
}
// go to the correct frame
spinX_mc.gotoAndStop(frame);
}
By changing
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
to
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = mouseX;
I seem to of solved the problem and everything runs smoothly again.