SpriteKit enemy sprites skip after contact with player -
i have made game basic idea player sprite has either collide or avoid falling enemy sprites depending on letter assigned enemy. problem when player makes contact sprite, surrounding enemies skip forward significantly. makes game hard play because there isn't enough time player move out of way of oncoming enemy sprites. happens on device , simulator.
to see mean, @ brief video. can see lag @ 00:06 , 00:013: https://www.dropbox.com/s/8pp66baxc9uhy26/simulatorscreensnapz002.mov?dl=0
here code player , enemy contact:
class gameplaysceneclass: skscene, skphysicscontactdelegate { private var player:player? private var center = cgfloat() private var canmove = false, moveleft = false private var itemcontroller = itemcontroller() private var scorelabel: sklabelnode? private var wordlabel: sklabelnode? private var score = 0 private var theword = "" private var vowelpressed = false let correct = soundsfx("correct.wav") let wrong = soundsfx("nomatch.wav") let explosion = soundsfx("explosion.wav") var arrayofstrings: [string]? var thecheckedword = "" var currentcount = 0 var itemsarray = [string]() var partialexists = false var characterscore = 0 var onepointletters = [12, 14, 18, 19, 20] var twopointletters = [4, 7] var threepointletters = [2, 3, 13, 16] var fourpointletters = [6, 8, 22, 23, 25] var fivepointletters = [11] var eightpointletters = [10, 24] var tenpointletters = [17, 26] var letter = 0 var scorearray = [int]() var matchingterms = [string]() var gravity:cgfloat = -0.35 var result = cgsize() let synth = avspeechsynthesizer() var myutterance = avspeechutterance(string:"") override func didmove(to view: skview) { soundengine.shared.backgroundmusicvolume = 1.0 soundengine.shared.playbackgroundmusic("jungle audio-1.m4a", loop: true) initializegame() } override func update(_ currenttime: timeinterval) { manageplayer() } override func touchesbegan(_ touches: set<uitouch>, event: uievent?) { touch in touches { let location = touch.location (in: self) if atpoint(location).name == "lettera" { print ("letter pressed") vowelpressed = true theword = theword + "a" wordlabel?.text = theword if theword.characters.count >= 3 { checkword() } vowelpressed = false } else if atpoint(location).name == "lettere" { print ("letter e pressed") vowelpressed = true theword = theword + "e" wordlabel?.text = theword if theword.characters.count >= 3 { checkword() } vowelpressed = false } else if atpoint(location).name == "letteri" { print ("letter pressed") vowelpressed = true theword = theword + "i" wordlabel?.text = theword if theword.characters.count >= 3 { checkword() } vowelpressed = false } else if atpoint(location).name == "lettero" { print ("letter o pressed") vowelpressed = true theword = theword + "o" wordlabel?.text = theword if theword.characters.count >= 3 { checkword() } vowelpressed = false } else if atpoint(location).name == "letteru" { print ("letter u pressed") vowelpressed = true theword = theword + "u" wordlabel?.text = theword if theword.characters.count >= 3 { checkword() } vowelpressed = false } else if atpoint(location).name == "pause" { showpausealert() } else if atpoint(location).name == "delete" { theword = "" thecheckedword = "" wordlabel?.text = theword } else { if location.x > center && !vowelpressed { moveleft = false } else if location.x < center && !vowelpressed { moveleft = true } canmove = true } } } override func touchesended(_ touches: set<uitouch>, event: uievent?) { canmove = false } func didbegin(_ contact: skphysicscontact) { if !gamepaused { var firstbody = skphysicsbody() var secondbody = skphysicsbody() if contact.bodya.node?.name == "player" { firstbody = contact.bodya secondbody = contact.bodyb } else { firstbody = contact.bodyb secondbody = contact.bodya } if firstbody.node?.name == "player" && secondbody.node?.name == "tile" { letter = secondbody.node?.userdata?.value(forkey:"key") as! int print ("the value of letter \(letter)") var lettercode = string(describing: letter) var lettervalue = int(lettercode) var finallettervalue = lettervalue!+64 var asciicode = character(unicodescalar(finallettervalue)!) var letterstring = string(describing:asciicode) theword = theword + letterstring print (theword) if onepointletters.contains(letter) { characterscore += 1 } else if twopointletters.contains(letter) { characterscore += 2 } else if threepointletters.contains(letter) { characterscore += 3 } else if fourpointletters.contains(letter) { characterscore += 4 } else if fivepointletters.contains(letter) { characterscore += 5 } else if eightpointletters.contains(letter) { characterscore += 8 } else if tenpointletters.contains(letter) { characterscore += 10 } wordlabel?.text = theword thecheckedword = theword.lowercased() print ("the checked word \(thecheckedword)") checkword() secondbody.node?.removefromparent() } if firstbody.node?.name == "player" && secondbody.node?.name == "bomb" { explosion.play() firstbody.node?.removefromparent() secondbody.node?.removefromparent() theword = "" score = 0 scorelabel?.text = string(score) var delaytimer = skaction.wait(forduration:1) run (delaytimer) restartgame() } } } private func initializegame() { { // solution assumes you've got file in bundle if let path = bundle.main.path(forresource: "en", oftype: "txt"){ let data = try string(contentsoffile:path, encoding: string.encoding.utf8) arrayofstrings = data.components(separatedby: "\n") } } catch let err nserror { // error print(err) } physicsworld.contactdelegate = self physicsworld.gravity = cgvector(dx:0,dy:gravity) player = childnode(withname: "player") as? player! player?.initializeplayer() player?.position = cgpoint(x:0, y: -420) scorelabel = childnode(withname: "scorelabel") as? sklabelnode! scorelabel?.text = string(score) wordlabel = childnode(withname:"wordlabel") as? sklabelnode! wordlabel?.text = "" center = self.frame.size.width/self.frame.size.height var spawnblocks = skaction.repeatforever(skaction.sequence([skaction.wait(forduration:1),skaction.run(spawnitems)])) var removeblocks = skaction.repeatforever(skaction.sequence([skaction.wait(forduration:1),skaction.run(removeitems)])) if gamepaused == true { self.scene?.ispaused = true } self.run(spawnblocks) self.run(removeblocks) } private func checkword() { thecheckedword = theword.lowercased() if (arrayofstrings?.contains(thecheckedword))! { print ("yes! \(thecheckedword) word") correct.play() print ("the current value of score \(score)") score += characterscore print ("current gravity setting \(gravity)") scorelabel?.text = string(score) characterscore = 0 matchingterms = (arrayofstrings?.filter({$0.hasprefix(thecheckedword) }))! if matchingterms.count == 1 { characterscore = 0 print ("current gravity setting \(gravity)") theword = "" thecheckedword = "" wordlabel?.text = "" } } else if !(arrayofstrings?.contains(thecheckedword))! { matchingterms = (arrayofstrings?.filter({$0.hasprefix(thecheckedword) }))! if matchingterms.count == 0 { wrong.play() characterscore = 0 if score >= 5 { score -= 5 } theword = "" thecheckedword = "" wordlabel?.text = "" } } }
here code enemies:
import spritekit struct collidertype { static let player: uint32 = 0 static let tile_and_bomb: uint32 = 1; } public var bounds = uiscreen.main.bounds public var width = bounds.size.width public var height = bounds.size.height class itemcontroller { private var minx = cgfloat(-(width/2)), maxx = cgfloat(width/2) private var vowelnumbers = [1, 5, 9, 15, 21] func spawnitems() -> skspritenode { let item: skspritenode? if int(randombetweennumbers(firstnum: 0, secondnum: 10)) > 7 { item = skspritenode(imagenamed: "bomb") item!.name = "bomb" item!.setscale(0.6) item!.physicsbody = skphysicsbody(circleofradius: item!.size.height / 2) print ("the value of width \(width)") } else { var num = int(randombetweennumbers(firstnum: 1, secondnum: 26)) if vowelnumbers.contains(num) { num = num + 1 } item = skspritenode(imagenamed: "tile \(num)") item?.userdata = nsmutabledictionary() item!.name = "tile" item!.userdata!.setvalue(num, forkey:"key") item!.zrotation = 0 item!.setscale(0.9) item!.physicsbody = skphysicsbody(circleofradius: item!.size.height / 2) if gamepaused == true { item!.ispaused = true } else { item!.ispaused = false } } item!.physicsbody?.categorybitmask = collidertype.tile_and_bomb; item!.physicsbody?.isdynamic = true item!.zposition = 3 item!.anchorpoint = cgpoint(x: 0.5, y: 0.5) item!.position.x = randombetweennumbers(firstnum: minx, secondnum: maxx) item!.position.y = 600 return item! } func randombetweennumbers(firstnum: cgfloat, secondnum: cgfloat) -> cgfloat { return cgfloat(arc4random()) / cgfloat(uint32_max) * abs(firstnum - secondnum) + min(firstnum, secondnum); } }
and here code player:
import spritekit class player: skspritenode { private var minx = cgfloat(-300), maxx = cgfloat(300) func initializeplayer() { name = "player" physicsbody = skphysicsbody(circleofradius: size.height/2) physicsbody?.affectedbygravity = false physicsbody?.isdynamic = false physicsbody?.categorybitmask = collidertype.player physicsbody?.contacttestbitmask = collidertype.tile_and_bomb } func move(left:bool){ if left { position.x -= 15 if position.x < minx { position.x = minx } } else { position.x += 15 if position.x > maxx { position.x = maxx } } } }
consider calling checkword()
method skaction:
let checkwordsaction = skaction.run() { [weak self] in self?.checkword() } self.run(checkwordsaction)
that way, if array big, code not interrupted because walking check word.
also i'm not sure of trying wait action @ end of didbegin(contact:)
method, when colliding bombs. if trying wait 1 second before restarting game, keep in mind calling wait action way not pause code. put scene on idle 1 second , restart game in background. if intended effect, it's ok, might better using run(_:completion:)
method instead , call restartgame()
completion closure:
let waitaction = skaction.wait(1) self.run(waitaction) { [weak self] in self?.restartgame() }
hope helps!
Comments
Post a Comment