Get Index on UIslider - ios

I have radar chart with data.I want to give index for slider Based on data count.If i am moving slider the graph value should move.If suppose i am at bellow of middle value slider thumb should go to near index.
for _ in 0..<3 {
let mind = arc4random_uniform(mult) + min
let bre = arc4random_uniform(mult) + min
let rel = arc4random_uniform(mult) + min
dataPoints.append(GraphDataPoints(mindfulness: Double(mind), breathing: Double(bre), relaxation: Double(rel)))
}
self.setChartData(mindfulness: dataPoints[0].mindfulness, breathing: dataPoints[0].breathing, relaxation: dataPoints[0].relaxation)
numberofPointsOnSlider = Float(100 / (dataPoints.count - 1))
numberofPointsOnSlider is percent to move.In lastSliderValue i am storing the slider value.pointIndex have index.
#objc func sliderTouchEvents(slider:UISlider,event: UIEvent){
slider.isContinuous = true
if let touchEvent = event.allTouches?.first{
switch touchEvent.phase{
case .began:
lastSliderValue = slider.value
break
case .moved:
if slider.value.truncatingRemainder(dividingBy: numberofPointsOnSlider) == 0{
if lastSliderValue < slider.value || lastSliderValue > slider.value{
pointIndex = Int(slider.value / numberofPointsOnSlider)
self.isIncrement = false
}
lastSliderValue = slider.value
}
if !animation {
if pointIndex >= 0 && pointIndex < dataPoints.count {
var percentToMove:Float = 0
if lastSliderValue > slider.value && pointIndex > 0 {
percentToMove = (100 * (numberofPointsOnSlider - (slider.value.truncatingRemainder(dividingBy: numberofPointsOnSlider) ))) / numberofPointsOnSlider
mindfulDiff = Float(dataPoints[pointIndex].mindfulness - dataPoints[pointIndex - 1].mindfulness)
relaxationDiff = Float(dataPoints[pointIndex].relaxation - dataPoints[pointIndex - 1].relaxation)
breathingDiff = Float(dataPoints[pointIndex].breathing - dataPoints[pointIndex - 1].breathing)
}else if lastSliderValue < slider.value && pointIndex < dataPoints.count - 1 {
percentToMove = (100 * (slider.value.truncatingRemainder(dividingBy: numberofPointsOnSlider) )) / numberofPointsOnSlider
mindfulDiff = Float(dataPoints[pointIndex].mindfulness - dataPoints[pointIndex + 1].mindfulness)
relaxationDiff = Float(dataPoints[pointIndex].relaxation - dataPoints[pointIndex + 1].relaxation)
breathingDiff = Float(dataPoints[pointIndex].breathing - dataPoints[pointIndex + 1].breathing)
}
mp = Float(dataPoints[pointIndex].mindfulness) - (mindfulDiff / 100 ) * percentToMove
rp = Float(dataPoints[pointIndex].relaxation) - (relaxationDiff / 100 ) * percentToMove
bp = Float(dataPoints[pointIndex].breathing) - (breathingDiff / 100) * percentToMove
UIView.animate(withDuration: 10, animations: {
self.setChartData(mindfulness: Double(self.mp) , breathing: Double(self.bp) , relaxation: Double(self.rp) )
})
}
else {
if (pointIndex < 0) {
pointIndex = 0
}
}
}
break
case .ended:
let progDiff = lastSliderValue - slider.value
print("End movie, \(pointIndex) , \(slider.value) ,progDiff: \(progDiff)")
if progDiff < 0{
if (progDiff * -1) >= numberofPointsOnSlider / 2 {
animation = true
UIView.animate(withDuration: 10, animations: {
slider.value += self.numberofPointsOnSlider + progDiff
})
pointIndex = Int(slider.value / numberofPointsOnSlider)+1
// if isIncrement {
// pointIndex += pointIndex
// }else {
// isIncrement = true
//
// }
mindfulDiff = Float(dataPoints[pointIndex].mindfulness - Double(mp))
relaxationDiff = Float(dataPoints[pointIndex].relaxation - Double(rp))
breathingDiff = Float(dataPoints[pointIndex].breathing - Double(bp))
doGraphAnimate()
}else {
animation = true
UIView.animate(withDuration: 10, animations: {
slider.value = self.lastSliderValue
})
mindfulDiff = Float(dataPoints[pointIndex].mindfulness - Double(mp))
relaxationDiff = Float(dataPoints[pointIndex].relaxation - Double(rp))
breathingDiff = Float(dataPoints[pointIndex].breathing - Double(bp))
doGraphAnimate()
}
}else if progDiff > 0{
if progDiff >= numberofPointsOnSlider / 2 {
animation = true
// if isIncrement {
// print("pointIndex : \(pointIndex)")
// pointIndex += pointIndex
// print("pointIndex Incremented : \(pointIndex)")
// }else{
// isIncrement = true
// }
pointIndex = Int(slider.value / numberofPointsOnSlider)
UIView.animate(withDuration: 10, animations: {
slider.value -= self.numberofPointsOnSlider - (self.lastSliderValue - slider.value)
})
mindfulDiff = Float(dataPoints[pointIndex].mindfulness - Double(mp))
relaxationDiff = Float(dataPoints[pointIndex].relaxation - Double(rp))
breathingDiff = Float(dataPoints[pointIndex].breathing - Double(bp))
doGraphAnimate()
}
else {
animation = true
UIView.animate(withDuration: 10, animations: {
slider.value = self.lastSliderValue
})
mindfulDiff = Float(dataPoints[pointIndex].mindfulness - Double(mp))
relaxationDiff = Float(dataPoints[pointIndex].relaxation - Double(rp))
breathingDiff = Float(dataPoints[pointIndex].breathing - Double(bp))
doGraphAnimate()
}
}
default :
break
}
}
}
Help me, Thankyou .

DO you mean you want slider to move only at certain discrete positions when you move it ? But your spec is not totally clear.
If so, this is how I, so that if slider moves from 0 to 14 it will show 14, from 15 to 85, it will show 85. I let you adapt to get the exact working you want.
I use this IBAction for the slider
#IBAction fileprivate func changeRowSlider(_ sender: NSSlider) {
let movedPosition = Int(sender.doubleValue)
if movedPosition == 0 {
sender.integerValue = 0
return
}
if movedPosition <= 14 {
sender.integerValue = 14
return
}
if movedPosition <= 85 {
sender.integerValue = 85
return
}
sender.integerValue = 100 // last case: move to maxValue
}

Related

How do you update something in an SKAction while using repeat repeatForever?

As you'll see below, I'm trying to update the durationNumber, so that the colorSwitch object turns faster. The durationNumber does update, but colorSwitch doesn't rotate faster. How do I accomplish this?
func turnWheel() {
var durationNumber = 2.0
let rotateAction = SKAction.rotate(byAngle: .pi/2, duration: durationNumber)
let switchAction = SKAction.run {
if let newState = SwitchState(rawValue: self.switchState.rawValue + 1) {
self.switchState = newState
} else {
self.switchState = .green
}
if self.score > self.scoreCheck {
self.scoreCheck += 1
durationNumber *= 0.5
}
}
colorSwitch.run(SKAction.repeatForever(SKAction.sequence([rotateAction, switchAction])))
}
You're changing the value of the local variable, but not changing the SKAction object itself. You need to change rotateAction.duration to have any effect on the action itself.
if self.score > self.scoreCheck {
self.scoreCheck += 1
durationNumber *= 0.5
rotateAction.duration = durationNumber
}
Do not update your duration, instead update your speed
func turnWheel() {
var durationNumber = 2.0
let rotateAction = SKAction.rotate(byAngle: .pi/2, duration: durationNumber)
let switchAction = SKAction.run {
if let newState = SwitchState(rawValue: self.switchState.rawValue + 1) {
self.switchState = newState
} else {
self.switchState = .green
}
if self.score > self.scoreCheck {
self.scoreCheck += 1
colorSwitch.speed *= 2
}
}
colorSwitch.run(SKAction.repeatForever(SKAction.sequence([rotateAction, switchAction])))
}

Make PanGesture becoming to slider

I made a PanGuesture as a slider, Here blow is the responds func:
func respondsToPenGesture(sender: UIPanGestureRecognizer) {
if (sender.state == UIGestureRecognizerState.Began) {
if noFilterEffectButton.selected == false {
startPanLocation = sender.locationInView(self.newEffectView)
persentageNumber.text = String(startNumber)
persentageNumber.hidden = false
}
} else if (sender.state == UIGestureRecognizerState.Changed) {
let stopLocation = sender.locationInView(self.newEffectView)
let abscissaChange = stopLocation.x - startPanLocation!.x
if newEffectView.hidden == false {
if abs(abscissaChange) > 0 {
if noFilterEffectButton.selected == false{
if let effectCurrent = self.currentEffect {
effectCurrent.adjustParams(CGFloat(abscissaChange/6))
}
}
}
if noFilterEffectButton.selected == false {
var printChangingNumber = startNumber + Int(abscissaChange)
if printChangingNumber > 100 {
printChangingNumber = 100
} else if printChangingNumber < 0 {
printChangingNumber = 0
}
persentageNumber.text = String(printChangingNumber)
}
}
} else if (sender.state == UIGestureRecognizerState.Ended) {
let stopLocation = sender.locationInView(self.newEffectView)
let abscissaChange = stopLocation.x - startPanLocation!.x
startNumber = startNumber + Int(abscissaChange)
if startNumber > 100 {
startNumber = 100
} else if startNumber < 0 {
startNumber = 0
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5*Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
self.persentageNumber.text = String(self.startNumber)
self.persentageNumber.hidden = true
}
}
}
percentageNumber is a label show the changes on the screen. And the adjustParams() function:
func adjustParams(value: CGFloat) {
newValue = value + newValue
self.adjust = newValue
print("AdjustNumber")
print(adjust)
}
And I override this function for exactly one effect:
override func adjustParams(value: CGFloat) {
super.adjustParams(value)
lastAutValueChange = lastAutValueChange + value/200
lastIntensityChange = lastIntensityChange + value/200
var currentAutValue = lastAutValueChange
var currentIntValue = lastIntensityChange
currentIntValue = currentIntValue < -1.0 ? -1.0 : currentIntValue
//value = value > 1.0 ? 1.0 : value
//autValue = value < -1.0 ? -1.0 : autValue
if (currentIntValue >= 0) {
currentIntValue = 1.0
} else {
currentIntValue += 1
}
if (currentAutValue <= 0) {
currentAutValue = 0
} else {
if currentAutValue > 1 {
currentAutValue = 1
}
}
print(currentIntValue)
print(currentAutValue)
self.autoTuneModule.setIntensity(Float(currentIntValue))
self.audioUnit.finalMix = Double(currentAutValue)
}
The test answer is not matchable for the exactly changes and the percentNumber shows on the screen. How could I change my functions to make them matchable for each others?
(By the way, I want to do something like the slider in Prisma, if there is something like it, please let me know about it).

Maths formula of cleaner way for bounding box logic?

Below I have written some bounding box logic which is a bit verbose. Is there a way to make it more readable, so the check looks cleaner and more concise?
func validatePosition(position:SCNVector3, forNode node:SCNNode) -> SCNVector3 {
var newPosition = position
var maxVector = SCNVector3Zero
var minVector = SCNVector3Zero
let success = self.actionDelegate?.getBoundingBox(&minVector, max: &maxVector)
guard success == true else {
return newPosition
}
if newPosition.x < minVector.x && newPosition.x < 0 {
newPosition.x = minVector.x
}
if newPosition.y < minVector.y && newPosition.y < 0 {
newPosition.y = minVector.y
}
if newPosition.z < minVector.z && newPosition.z < 0 {
newPosition.z = minVector.z
}
if newPosition.x > maxVector.x && newPosition.x > 0 {
newPosition.x = maxVector.x
}
if newPosition.y > maxVector.y && newPosition.y > 0 {
newPosition.y = maxVector.y
}
if newPosition.z > maxVector.z && newPosition.z > 0 {
newPosition.z = maxVector.z
}
return newPosition
}
Try this:
extension ClosedInterval {
func clamp(value : Bound) -> Bound {
return self.start > value ? self.start
: self.end < value ? self.end
: value
}
}
extension SCNVector3 {
func clamp(min min:SCNVector3, max: SCNVector3) -> SCNVector3 {
let x = (min.x...max.x).clamp(self.x)
let y = (min.y...max.y).clamp(self.y)
let z = (min.z...max.z).clamp(self.z)
return SCNVector3(x, y, z)
}
}
func validatePosition(position:SCNVector3, forNode node:SCNNode) -> SCNVector3 {
var newPosition = position
var maxVector = SCNVector3Zero
var minVector = SCNVector3Zero
let success = self.actionDelegate?.getBoundingBox(&minVector, max: &maxVector)
guard success == true else {
return newPosition
}
newPosition = position.clamp(min: minVector, max: maxVector)
return newPosition
}

Why is setting a .text property messing with NSTimers

I'm programming a game in xcode 7 using swift and it is an endless game where you avoid falling objects. I have an NSTimer:
#IBAction func startNow(sender: UIButton) {
player.center.x = 160
explosion.center.x = 1000
explosion.center.y = 1000
for f in r {
random = Int(arc4random_uniform(350))
f.image = UIImage(named: "blueSQ1")
if random == 20 {
f.image = UIImage(named: "moneyRain")
}
}
random1 = Int(arc4random_uniform(5))
if random1 <= 3 {
r10.image = UIImage(named: "blackSQ1")
}
slider.value = Float(player.center.x + 122)
shieldImg.image = UIImage(named: "nil")
ad = 1.5
moveDown.invalidate()
speed1 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed2 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed3 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed4 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed5 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed6 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed7 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed8 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed9 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed10 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed11 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed12 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed13 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed14 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
speed15 = ad + CGFloat(Float(arc4random()) / Float(UINT32_MAX))
for x in r {
x.center.y = 55
x.center.x = CGFloat(20+arc4random_uniform(285))
}
moveDown = NSTimer.scheduledTimerWithTimeInterval(0.015, target:self, selector: Selector("updatePos"), userInfo: nil, repeats: true)
timeyWimey = NSTimer.scheduledTimerWithTimeInterval(0.1, target:self, selector: Selector("incrementTime"), userInfo: nil, repeats: true)
checkShield = NSTimer.scheduledTimerWithTimeInterval(0.1, target:self, selector: Selector("ifShielded"), userInfo: nil, repeats: true)
}
func incrementTime() {
timer+=0.1
scoreProgress.setProgress(Float(timer/highscore), animated: false)
//time.text = "Time: \(timer)"
}
func updatePos() {
start.center.y = 10000
startOut.center.y = 10000
coinsLabel.center.y = 10000
buyShieldOut.center.y = 10000
ifDone()
r1.center.y += speed1
r2.center.y += speed2
r3.center.y += speed3
r4.center.y += speed4
r5.center.y += speed5
r6.center.y += speed6
r7.center.y += speed7
r8.center.y += speed8
r9.center.y += speed9
r10.center.y += speed10
r11.center.y += speed11
r12.center.y += speed12
r13.center.y += speed13
r14.center.y += speed14
r15.center.y += speed15
for q in r {
if ((q.center.x)+3 > player.center.x - 15) && ((q.center.x)-3 < player.center.x + 15) && ((q.center.y)+3 > player.center.y - 15) && ((q.center.y)-3 < player.center.y + 15)
{
if (shield == 0) && ((q.image == UIImage(named: "blueSQ1")) || (q.image == UIImage(named: "blackSQ1")))
{
explosion.center.y = 10000
explosion.center.x = 10000
start.text = "RESTART"
start.center.y = 289
timeyWimey.invalidate()
y = Float(round(10*timer)/10)
timeOut.text = "Previous time: \(y)"
coins += Int(y*10)
coinsLabel.text = "Coins: \(coins)"
if y > highscore {
highscore = y
}
highTime.text = "Best time: \(highscore)"
startOut.center.y = 289
coinsLabel.center.y = 130
buyShieldOut.center.y = 167
moveDown.invalidate()
timer = 0
}
if shield == 1 && q.image == UIImage(named: "blueSQ1")
{
activated = true
}
if q.image == UIImage(named: "moneyRain") {
coins += 500
q.image = UIImage(named: "whiteSQ")
}
if q.image == UIImage(named: "green2") {
}
}
}
if ((explosion.center.x)+18 > player.center.x - 15) && ((explosion.center.x)-18 < player.center.x + 15) {
if shield == 1
{
shield = 0
activated = false
}
start.text = "RESTART"
start.center.y = 289
timeyWimey.invalidate()
y = Float(round(10*timer)/10)
timeOut.text = "Previous time: \(y)"
coins += Int(y*10)
coinsLabel.text = "Coins: \(coins)"
if y > highscore {
highscore = y
}
highTime.text = "Best time: \(highscore)"
startOut.center.y = 289
coinsLabel.center.y = 130
buyShieldOut.center.y = 167
moveDown.invalidate()
explosion.center = player.center
timer = 0
}
}
This works fine. But I have commented out the time.text line as when it is active the falling objects repeatedly go back to the top of the screen and begin falling again, then go back to the top of the screen again etc. very quickly - a fraction of a second. It seems to make no sense. Any help would be much appreciated.

How to get all Points Along a Line in Swift?

I am writing a program in Swift which requires a method that uses specification of two CGPoints and returns all points in a straight line in-between them. At the moment I am trialling the following method, but it is very glitchy and refuses to get all points for some lines. I was just wondering if there is a more efficient way of doing this?
func addPointsInLine(#start: CGPoint, end: CGPoint){
var speed = 0
var startNo = trackPoints.count
var endNo = startNo
var xDiff = start.x - end.x
var yDiff = start.y - end.y
var xChange = 0.0
var yChange = 0.0
var newPointX = start.x
var newPointY = start.y
var ended = false
xChange = Double(xDiff) / Double(yDiff)
yChange = Double(yDiff) / Double(xDiff)
/*if(xDiff > 0){
xChange = sqrt(xChange * xChange)
}
if(yDiff > 0){
yChange = sqrt(yChange * yChange)
}*/
println("xc \(xChange)")
println("yc \(yChange)")
var y = Double(start.y)
var x = Double(start.x)
while !ended {
println(trackPoints.count)
speed++
endNo++
if(CGPointMake(newPointX, newPointY) == end){
ended = true
}
if(yChange > xChange){
y++
x += xChange
trackPoints.append(TrackPoint(x: Int(x), y: Int(y)))
if(CGFloat(Int(y)) == end.y){
ended = true
println("end")
//break
}
/* if(yChange > 0){
if(CGFloat(Int(y)) > end.y){
ended = true
println("end>y")
// break
}
}
if(yChange < 0){
if(CGFloat(Int(y)) < end.y){
ended = true
println("end<y")
//break
}
}*/
if(xChange > 0){
if(CGFloat(Int(x)) >= end.x){
ended = true
println("end>x")
//break
}
}
if(xChange < 0){
if(CGFloat(Int(x)) <= end.x){
ended = true
println("end<x")
//break
}
}
} else {
x++
y += yChange
trackPoints.append(TrackPoint(x: Int(x), y: Int(y)))
if(CGFloat(Int(x)) == end.x){
ended = true
println("end")
//break
}
/* if(xChange > 0){
if(CGFloat(Int(x)) >= end.x){
ended = true
println("end>x")
//break
}
}
if(xChange < 0){
if(CGFloat(Int(x)) <= end.x){
ended = true
println("end<x")
//break
}
}*/
if(yChange > 0){
if(CGFloat(Int(y)) > end.y){
ended = true
println("end>y")
// break
}
}
if(yChange < 0){
if(CGFloat(Int(y)) < end.y){
ended = true
println("end<y")
//break
}
}
}
}
println("finished")
var i = startNo
println(startNo)
println(endNo)
while i < endNo {
trackPoints[i].speed = speed
i++
}
println("finish2")
}
I think firstly finding all points isn't possible because there are infinite points in a straight line. Take example of line joining (0,0) to (1, 0). All the following points and many more are on the said line (0.00001,0) (0.0000000000001,0) (0.01,0)
So you need to limit the amount of points you need to find like all the points with Integer co-ordinates. All the points 1 unit apart, starting from starting point etc.
Next you can use one of equations of line to get points: Equations of Line
Try this,
func findAllPointsBetweenTwoPoints(startPoint : CGPoint, endPoint : CGPoint) {
var allPoints :[CGPoint] = [CGPoint]()
let deltaX = fabs(endPoint.x - startPoint.x)
let deltaY = fabs(endPoint.y - startPoint.y)
var x = startPoint.x
var y = startPoint.y
var err = deltaX-deltaY
var sx = -0.5
var sy = -0.5
if(startPoint.x<endPoint.x){
sx = 0.5
}
if(startPoint.y<endPoint.y){
sy = 0.5;
}
repeat {
let pointObj = CGPoint(x: x, y: y)
allPoints.append(pointObj)
let e = 2*err
if(e > -deltaY)
{
err -= deltaY
x += CGFloat(sx)
}
if(e < deltaX)
{
err += deltaX
y += CGFloat(sy)
}
} while (round(x) != round(endPoint.x) && round(y) != round(endPoint.y));
allPoints.append(endPoint)
}

Resources