How to convert touch point to CG vector - ios

I'm trying to get the player to move to the direction of the player touch without stopping, or direction of swipe would be better because it seems more natural. However I only can find out how to do so with SKAction.move(by: vector) but the location variable I get from touches.first is a CG point.
I'm not sure what a vector point is so I can't figure out how to convert the touch point to a vector point to make this happen.
Any help would be really appreciated. I'm almost finished with my player movement and excited to move onto whats next
if let location = touches.first?.location(in: self) {
let horizontalAction = SKAction.move(to: location, duration: 1.0)
horizontalAction.timingMode = SKActionTimingMode.easeOut
player?.run(horizontalAction)

Related

chasing enemy in an endless runner

I've been trying to code this for days now, without success.
My game is a 2D endless runner. My hero is locked onto a specific point on the X-axis. The obstacles are randomly spawned (height and distance) buildings.
I'd like to add a chasing enemy to the game. Currently for visuals only.
chasingCopNode = CopSprite.newInstance(position: CGPoint(x: -90, y: 0))
let follow = SKAction.moveTo(x: thiefNode.position.x - 50, duration: 5)
let wait = SKAction.wait(forDuration: 2)
let fallBehind = SKAction.moveTo(x: -90, duration: 4)
let chasingSequence = SKAction.sequence([follow, wait, fallBehind])
chasingCopNode.run(chasingSequence)
chasing = true
self.addChild(chasingCopNode)
I created this to move tha chasing sprite along the X-axis.
In my update function, I simply update the Y position of the enemy with the hero's Y position.
That is working, but not quite the thing I need. Since the Y positions are the same, the enemy sprite is flying sometimes (because there is no building under it).
I couldn't come up with any working ideas for the movement on the Y-axis.
I was thinking maybe add a function that calculates the needed Y impulse for the enemy to land on the next building, but I was not able to do that correctly.
thank you for your help!

SCNNode at camera position

I am trying to make my node start at the same position that I tap in a game but I can't figure it out
here is my code for where to position the node. I get my location from the tap gesture recognizer by:
let myLocation = recognizer.location(in: self.view)
Then I get the x and y position into a float value:
let myx = Float(myLocation.x * 0.01)
let myy = Float(myLocation.y * 0.01)
Then I set the nodes position(the camera is set at 30)
shapeNode.position = SCNVector3(x:myx, y:myy, z: 30.0)
The position is off by a lot and I can't figure out why...
Someone please help
First you need to convert location from 2D on screen into 3D in real world using hittest() to place object in real world

Swift 4 and SpriteKit: Move node to a new touch location

I'm trying to move a node to a touch location using physicsBody (as opposed to SKAction). I am trying to use applyForce, but I may be going about this wrong.
In my touchesBegan function I record the touch location in a constant and pass it into my movePlayer function. The initial touch works as expected. However, subsequent touches seem to move from a relative position, which makes me think that I should recalculate my vector. I'm just not sure how to do this. Any help is appreciated.
func movePlayer(to touchPoint: CGPoint) {
let vector = CGVector(dx: touchPoint.x, dy: touchPoint.y)
player.physicsBody?.applyForce(vector, at: player.position)
player.physicsBody?.velocity = vector
playerIsMoving = true
}

rotate camera use lookat function with pan gesture

I try use lookat function rotate camera with pan gesture. I use swift and Metal(in this case Metal work the same with OpenGLES). Here is my code
The lookat function:
let kEye = V3f(0.0, 0.0, -2.0)
var ktarget = V3f(0.0, 0.0, 0.0)
let kUp = V3f(0.0, 1.0, 0.0)
var viewMatrix = lookAt(kEye, center: ktarget, up: kUp)
The pan gesture:
func pan(panGesture: UIPanGestureRecognizer){
if panGesture.state == UIGestureRecognizerState.Changed{
let pointInView = panGesture.locationInView(self.view)
let xDelta = (lastPanLocation.x - pointInView.x)/self.view.bounds.width * panSensivity
let yDelta = (lastPanLocation.y - pointInView.y)/self.view.bounds.height * panSensivity
lastPanLocation = pointInView
var viewDirection = rotationM3f(kUp, angle: Float(-xDelta)) * viewDirection
var toRotateAround = Cross(viewDirection, b: kUp)
viewDirection = rotationM3f(toRotateAround, angle: Float(-yDelta)) * viewDirection
ktarget = kEye + viewDirection
} else if panGesture.state == UIGestureRecognizerState.Began {
lastPanLocation = panGesture.locationInView(self.view)
}
}
At the beginning, it works fine, pan the camera after a while, the viewDirection and toRotateAround vector will become -0.0,-0.0,0.0, when finger move vertically but the camera does not look up and down, Anyone knows what is wrong in the code? Thanks~~~
You only modify the view direction (ktarget in the end) but forget about kUP. Once these 2 vectors become parallel the cross product is zero and everything breaks.
The solution you are looking for is recomputing the kUp vector by using a cross product of viewDirection and toRotateAround.
When using rotations like this you need to think of your data as base vectors and a position (location=kEye, forward=ktarget-keye, up=kUp, right=cross(forward, up)). The base vectors are always perpendicular to each other (I suggest them to be normalized as well) and when you rotate you always rotate one of these vectors around another base vectors and after the rotation you need to recompute the 3rd vector by using a cross product.
So to rotate left or right you would rotate the forward around up and then use a cross product between forward and up to get the right vector. (The right vector here is optional since you do not use it)
To rotate up or down you rotate forward vector around right vector and use a cross product between the forward and right to get the new top vector.
Then for tilting left or right you rotate up around forward and get the right vector with cross product of the 2 used vectors.
If you see the logic you will find out there are always 2 ways of rotating along one axis. For instance to rotate left or right you might as well rotate the right vector around up and find the new forward vector by using a cross product of right and up.
There is a trick though. The procedure described here works great for a free movement such as a flight simulation where you can "tilt". It is not appropriate for a movement such as for a first person shooter where up is always in the center of the screen horizontally (I hope you see the difference). To create this FPS way you actually do need to keep up as (0,1,0) but then forward must never be (0,1,0) but it can be (0.001, 0.09, 0) which is pretty close to looking directly upwards. So as long as you limit the upwards angle to some value you should be fine. There are other ways as well...

SKSpriteNode has given itself teleporting capabilities and it can't be stopped

If anyone has ever played league of legends, they know that you click an area to make a player move to that spot. They don't get there instantly, it takes a little bit of time. I've tried to add this functionality to a game that I am trying to make. The problem is, the character tends to sometimes move slowly towards the touched area, which is great because that is what I want, but some times there is an inconsistency where it teleports instantaneously to the touched spot. Can anyone see the problem?
let touch = touches.anyObject()! as UITouch
let location = touch.locationInNode(self)
let moveAction = SKAction.moveTo(location, duration: 3.0)
if(tankTurn) // Tank's turn when tankTurn is true.
{
tank.runAction(moveAction)
tank.position = location
tankTurn = false
}// if statement

Resources