Calling all parent and child nodes - SceneKit - ios

I have a 3D car object with some pan and tap gestures on it and everything is working fine.
The problem is that I found myself need specific angels for the camera to look at each part when I'm zooming it in as its a car and has so many parts, So I wrote all parent and child nodes to specify each of them.
But I feel that it's not a good practice.
Is there another way to do that?
let parentNodeName = result.node.parent?.name
if parentNodeName == "up-side"{
scnCameraOrbit.eulerAngles.x = 2.3 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi * 1.0
}
else if parentNodeName == "front-side"{
if nodeName == "window-front"{
scnCameraOrbit.eulerAngles.x = 2.8 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi + 3.16
}
else if nodeName == "hood"{
scnCameraOrbit.eulerAngles.x = 2.95 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi + 3.16
}
else if nodeName == "bumper-front"{
scnCameraOrbit.eulerAngles.x = 3.45 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi + 3.16
}
else{
scnCameraOrbit.eulerAngles.x = 3.45 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi + 3.16
}
}
else if parentNodeName == "back-side"{
if nodeName == "window-rear"{
scnCameraOrbit.eulerAngles.x = 2.9 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi * 1.0
}
else if nodeName == "bumper-rear"{
scnCameraOrbit.eulerAngles.x = 3.4 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi * 1.0
}
else if nodeName == "trunk"{
scnCameraOrbit.eulerAngles.x = 3.0 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi * 1.0
}
else{
scnCameraOrbit.eulerAngles.x = 3.4 + Float.pi
scnCameraOrbit.eulerAngles.y = Float.pi * 1.0
}
}
else if parentNodeName == "left-side"{
scnCameraOrbit.eulerAngles.x = -Float.pi * 0.0
scnCameraOrbit.eulerAngles.y = -3 * Float.pi * 1.2
}
else if parentNodeName == "right-side"{
scnCameraOrbit.eulerAngles.x = -Float.pi * 0.0
scnCameraOrbit.eulerAngles.y = -2 * Float.pi * 1.2
}
else{
return
}

The IF tests are only called one time on hit test (click), right? If so...
To avoid some of the nested IF's complexity, you might try some enumeration techniques < 24701075 >, quite a few examples in this post - read carefully, some of this is dated and new Swift features are available. You'll need 2 sets (I believe), one for the parent node names and then one set for the node names. Not sure about efficiency, but clarity would improve... opinions vary, but code readability and avoiding debug problems is usually a higher priority for me unless performance is a real problem.

Related

Why multiply and divided is not the same accuracy sometimes in lua?

print((1 / 10 - 0.1) == 0) -- true
print((1 * 0.1 - 0.1) == 0) -- true
print((3 / 10 - 0.3) == 0) -- true
print((3 * 0.1 - 0.3) == 0) -- false
the last one is false, it means is not the 0.
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
> function a(x) return ("%A"):format(x) end
> a(0.1)
0X1.999999999999AP-4
> a(0.3)
0X1.3333333333333P-2
> a(0.1 * 3)
0X1.3333333333334P-2
They are different due to rounding errors.
More details:
0.1 =
0X1.9999999999999999999... * 2^(-4) =
(rounding)
0X1.999999999999A * 2^(-4) =
0X1.999999999999AP-4
0.3 =
0X1.333333333333333333... * 2^(-2) =
(rounding)
0X1.3333333333333 * 2^(-2) =
0X1.3333333333333P-2
0.1 * 3 =
0X1.999999999999AP-4 * 3 =
0X1.999999999999A * 2^(-4) * 3 =
0X4.CCCCCCCCCCCCE * 2^(-4) =
0X1.33333333333338 * 2^(-2) =
(rounding)
0X1.3333333333334 * 2^(-2) =
0X1.3333333333334P-2

Looking for a cleaner more efficient way

function GetDamage(spell, unit)
if spell == _Q and (isReady(_Q) or qActive) and not HasItem(3025) and not HasItem(3100) and not HasItem(3057) and not HasItem(3078) then
return myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
elseif spell == _Q and (isReady(_Q) or qActive) and (HasItem(3057) or sheenActive) then
return myHero:CalcDamage(unit, myHero.damage) + myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
elseif spell == _Q and (isReady(_Q) or qActive) and (HasItem(3025) or fActive) then
return myHero:CalcDamage(unit, myHero.damage) + myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
elseif spell == _Q and (isReady(_Q) or qActive) and (HasItem(3100) or lActive) then
return myHero:CalcMagicDamage(unit, ((myHero.damage * 0.75) + (myHero.ap * 0.5))) + myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
elseif spell == _Q and (isReady(_Q) or qActive) and (HasItem(3078) or tActive) then
return myHero:CalcDamage(unit, (myHero.damage * 2)) + myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
elseif spell == _E and isReady(_E) then
return myHero:CalcMagicDamage(unit, (((myHero:GetSpellData(_E).level * 40) + 15) + (myHero.ap * 0.6)))
else
return 0
end
end
this is my code to return x spell damage to x enemy, however while it works as intended it seems inefficient and ugly also I would like it to work a little differently and I'm not sure how to code it as such.
What I would like it to do is if I do for example GetDamage(all) or something similiar I would like it to return total damage I can do given isReady(spell) returns true ie if spell q and e are ready it would return the total of q and e only or if all were ready then would return all, additionally if I only need to know r's damage I could still just do GetDamage(_R).
Is there a cleaner way to do this using a table or some more efficient manner to get the results I need? Because currently using GetDamage(spell) + GetDamage(spell2) + GetDamage(spell3) etc looks like very bad coding.
Introduce new spell "ALL"
function GetDamage(spell, unit)
local result = 0
if (spell == "ALL" or spell == _Q) and (isReady(_Q) or qActive) then
local bonus = 0
if (HasItem(3057) or sheenActive) then
bonus = myHero:CalcDamage(unit, myHero.damage)
elseif (HasItem(3025) or fActive) then
bonus = myHero:CalcDamage(unit, myHero.damage)
elseif (HasItem(3100) or lActive) then
bonus = myHero:CalcMagicDamage(unit, ((myHero.damage * 0.75) + (myHero.ap * 0.5)))
elseif (HasItem(3078) or tActive) then
bonus = myHero:CalcDamage(unit, (myHero.damage * 2))
end
result = result + bonus + myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
end
if (spell == "ALL" or spell == _E) and isReady(_E) then
result = result + myHero:CalcMagicDamage(unit, (((myHero:GetSpellData(_E).level * 40) + 15) + (myHero.ap * 0.6)))
end
return result
end
Usage examples:
dmg = GetDamage("ALL", unit)
dmg = GetDamage(_Q, unit)
dmg = GetDamage(_E, unit)
EDIT:
There is another way of implementing the same by using a table with spells as keys and functions as values:
spell_dmg_func = {
[_Q] =
function(unit)
if (isReady(_Q) or qActive) then
local bonus = 0
if (HasItem(3057) or sheenActive) then
bonus = myHero:CalcDamage(unit, myHero.damage)
elseif (HasItem(3025) or fActive) then
bonus = myHero:CalcDamage(unit, myHero.damage)
elseif (HasItem(3100) or lActive) then
bonus = myHero:CalcMagicDamage(unit, ((myHero.damage * 0.75) + (myHero.ap * 0.5)))
elseif (HasItem(3078) or tActive) then
bonus = myHero:CalcDamage(unit, (myHero.damage * 2))
end
return bonus + myHero:CalcDamage(unit, ((((myHero:GetSpellData(_Q).level * 20) + 10) + myHero.totalDamage) + qStacks))
end
end,
[_E] =
function(unit)
if isReady(_E) then
return myHero:CalcMagicDamage(unit, (((myHero:GetSpellData(_E).level * 40) + 15) + (myHero.ap * 0.6)))
end
end,
}
function GetDamage(spell, unit)
if spells == "ALL" then
local sum = 0
for spell, func in pairs(spell_dmg_func) do
sum = sum + (func(unit) or 0)
end
return sum
else
return spell_dmg_func[spell](unit) or 0
end
end

How can I change the Double value in my dictionary outside the function?

var grades: [String : Double]
grades = ["A": 0.0, "A-": 0.0, "B+": 0.0, "B": 0.0, "B-": 0.0, "C+": 0.0, "C": 0.0, "C-": 0.0, "D+": 0.0, "D": 0.0, "D-": 0.0, "F": 0.0]
func calcGPA() {
if let a = grades["A"], amin = grades["A-"], bplu = grades["B+"], b = grades["B"], bmin = grades["B-"], cplu = grades["C+"], c = grades["C"], cmin = grades["C-"], dplu = grades["D+"], d = grades["D"], dmin = grades["D-"], f = grades["F"] {
// Divide by this
let gradesAdded = a + amin + bplu + b + bmin + cplu + c + cmin + dplu + d + dmin + f
//grades multiplied by their values and added ex. a * 4.0 + amin * 3.7
let gradesCalculated = a * 4.0 + amin * 3.7 + bplu * 3.3 + b * 3.0 + bmin * 2.7 + cplu * 2.3 + c * 2.0 + cmin * 1.7 + dplu * 1.3 + d * 1.0 + dmin * 0.7 // Dont do F because it would just add 0
var gpa = gradesCalculated / gradesAdded
if gpa.isNaN {
gpa = 0.0
}
}
}
Is there a way to do something like grades["A"] += 1.0 so that it goes up by one and I can call calcGPA()? I can't figure out how to make this work. Any help on this would be awesome
You can increase a value in your dictionary by force unwrapping the lookup:
grades["A"]! += 1.0
but this is dangerous because it will crash if the key isn't in the dictionary. So, you should check:
if let count = grades["A"] {
grades["A"] = count + 1
}
Here is an updated version of your program:
func calcGPA(_ termGrades: [String]) -> Double? {
var grades: [String: Double] = ["A": 0.0, "A-": 0.0, "B+": 0.0, "B": 0.0, "B-": 0.0, "C+": 0.0, "C": 0.0, "C-": 0.0, "D+": 0.0, "D": 0.0, "D-": 0.0, "F": 0.0]
var gpa: Double?
for grade in termGrades {
if let count = grades[grade] {
grades[grade] = count + 1
} else {
print("Hmmm, \(grade) is not a valid value for a grade")
return nil
}
}
if let a = grades["A"], amin = grades["A-"], bplu = grades["B+"], b = grades["B"], bmin = grades["B-"], cplu = grades["C+"], c = grades["C"], cmin = grades["C-"], dplu = grades["D+"], d = grades["D"], dmin = grades["D-"], f = grades["F"] {
// Divide by this
let gradesAdded = a + amin + bplu + b + bmin + cplu + c + cmin + dplu + d + dmin + f
//grades multiplied by their values and added ex. a * 4.0 + amin * 3.7
let gradesCalculated = a * 4.0 + amin * 3.7 + bplu * 3.3 + b * 3.0 + bmin * 2.7 + cplu * 2.3 + c * 2.0 + cmin * 1.7 + dplu * 1.3 + d * 1.0 + dmin * 0.7 // Dont do F because it would just add 0
gpa = gradesAdded == 0 ? nil : gradesCalculated / gradesAdded
}
return gpa
}
// example calls
calcGPA(["E"]) // nil "Hmmm, E is not a valid value for a grade"
calcGPA(["A-"]) // 3.7
calcGPA(["A", "B"]) // 3.5
calcGPA(["B", "B+", "A-"]) // 3.333333333333333
calcGPA([]) // nil
Notes:
I changed your function to take an array of grades and return a Double? (Optional Double).
nil is returned if anything goes wrong (input array is empty, input array contains invalid grade such as "E").
Divide by zero is avoided ahead of time by checking the divisor before the calculation.
Alternate Solution:
And now for something completely different...
Inspired by #CodeBender's comment, here is an implementation that uses an enum with an associated value to represent the grades:
enum Grade: Double {
case A = 4.0
case Aminus = 3.7
case Bplus = 3.3
case B = 3.0
case Bminus = 2.7
case Cplus = 2.3
case C = 2.0
case Cminus = 1.7
case Dplus = 1.3
case D = 1.0
case Dminus = 0.7
case F = 0
}
func calcGPA(_ termGrades: [Grade]) -> Double? {
if termGrades.count == 0 {
return nil
} else {
let total = termGrades.reduce(0.0) { (total, grade) in total + grade.rawValue }
return total / Double(termGrades.count)
}
}
// example calls
calcGPA([.A, .B]) // 3.5
calcGPA([.B, .Bplus, .Aminus]) // 3.3333333333
calcGPA([.A, .A, .Bplus]) // 3.7666666666
calcGPA([.F, .F, .F]) // 0
calcGPA([]) // nil

Optimizing Performance for Level Generation

I'm generating simple game maps using a method described in this post. I'm using the second method of starting with a seed tile and randomly growing out. I'm testing it in a Swift playground on a 30x30 array. The problem is my method takes several minutes to generate a 30x30 map, and maps in my real game might exceed 100x100 tiles. How can I optimize the following code to run faster?
import UIKit
import SpriteKit
var map = [[String]](count: 30, repeatedValue:[String](count: 30, repeatedValue:" "))
var landTiles = [(y: Int,x: Int)]()
landTiles.append((15,x: 15))
let minX = 3
let maxX = 28
let minY = 3
let maxY = 28
var coastTiles = [(y: Int,x: Int)]()
var hasReachedBounds = false
while !hasReachedBounds {
coastTiles = []
for tile in landTiles {
let coastal = isCoastal(tile.y, x: tile.x)
if coastal {
coastTiles.append(tile)
}
}
let numTiles = UInt32(coastTiles.count)
print(map)
let randomTile = coastTiles[Int(arc4random_uniform(numTiles))]
if randomTile.x <= minX || randomTile.x >= maxX || randomTile.y <= minY || randomTile.y >= maxY {
hasReachedBounds = true
break
}
let coastal = isCoastal(randomTile.y, x: randomTile.x)
if !coastal{
continue
}
let randomPosition = arc4random_uniform(4) + 1
switch randomPosition {
case 1:
landTiles.append((randomTile.y + 1, randomTile.x))
map [randomTile.y + 1][randomTile.x] = "&"
case 2:
landTiles.append((randomTile.y, randomTile.x + 1))
map [randomTile.y][randomTile.x + 1] = "&"
case 3:
landTiles.append((randomTile.y - 1, randomTile.x))
map [randomTile.y - 1][randomTile.x] = "&"
case 4:
landTiles.append((randomTile.y, randomTile.x - 1))
map [randomTile.y][randomTile.x - 1] = "&"
default: break
}
}
func isCoastal (y: Int, x: Int) -> Bool{
if map[y + 1][x] == " " || map[y][x + 1] == " " || map[y - 1][x] == " " || map[y][x - 1] == " "{
return true
} else {
return false
}
}
print(map)

Need help getting for loop to iterate correctly

I am working on this for homework, and I have most of this done my problem is there is something wrong in one of the for loops as the display I get is only one line when it should be a line for every value in the range 50,000 - 60,000 with a step value of 50.
def computeTax(status, taxableIncome):
print("Taxable Income/" + "\t" + "Single/" + "\t" + "Married Joint/" + \
"\t" + "Married Separate/" + " " + "Head of Household")
for taxableIncome in range(50000, 60001, 50):
for status in range(1, 5, 1):
if (status == 1): #tax calculation for single person
tax1 = 8350 * .10 + (33950 - 8350) * 0.15 + \
(taxableIncome - 33950) * 0.25
tax1 = round(tax1,0)
if (status == 2): #tax calculation for married file jointly
tax2 = 16700 * .10 + (67900 - 16700) * 0.15 + \
(taxableIncome - 67900) * 0.15
tax2 = round(tax2,0)
if (status == 3): #tax calculation for married file separately
tax3 = 8350 * .10 + (33950 - 8350) * 0.15 + \
(taxableIncome - 33950) * 0.25
tax3 = round(tax3,0)
if (status == 4): #tax calculation for head of household
tax4 = 11950 * .10 + (45500 - 11950) * 0.15 + \
(taxableIncome - 45500) * 0.25
tax4 = round(tax4,0)
print(str(tax1) + "\t" + str(tax2) + "\t" + str(tax3) + "\t" + str(tax4))
return (status, taxableIncome)
computeTax(range(1, 5, 1),range(50000, 60001, 50))
I'm not familiar with python, but do you have to define code blocks like you would with PHP?
EG
if (status == 1): #tax calculation for single person
{
tax1 = 8350 * .10 + (33950 - 8350) * 0.15 + \
(taxableIncome - 33950) * 0.25
tax1 = round(tax1,0)
}
Like I said; not familiar with Python, but I thought I might have an answer for you; if I'm completely off then sorry and good luck.

Resources