In this chapter, you’ll pick up from where you left off in the previous one. Your AR-based SpriteKit game is coming along well, and you’ve laid a lot of the groundwork already. Your goal now is to add all the missing pieces and finishing touches.
Take a moment to take stock of what you’ve done and what’s up next.
What’s Done?
Game State: The game has basic game states in place, and you can easily switch from one state to another. This lets you control your code based on the current state of the game.
Spawn Point: When the player taps the screen, the game adds an AR anchor in the camera’s view. A tiny box that acts as the spawning point for the emojis also appears.
Error Handling: Your game is robust enough to handle whatever the real world can throw at it. It informs the player of any tracking issues and, most importantly, it can recover from an interruption.
What’s Next?
Spawning Emojis: With the spawn point in place, you’ll spawn multiple emojis at this location.
Running Actions: To add some polish, you’ll run some custom actions on the emojis to play sound effects, scale and run additional code.
Enabling Physics: You’ll enable physics so the emojis participate in the physics simulation. This gives each emoji a physical shape and applies forces like gravity to it.
Applying Forces: You’ll use physically-based animation to apply forces to the emojis, shooting them out from the spawning point into the world, then letting gravity pull them back to earth.
2D Raycasting: You’ll use 2D raycasting to check if the player touches any of the spawned emojis to save them from certain death.
Now that you know what’s next, it’s time to get cracking!
Note: There’s a copy of the final project from the previous chapter available in starter/EmojiPop.
Spawning Emojis
Your first step is to get the emojis to spawn. You’ll use the spawn point as the parent node to spawn the new emojis. This ensures the emojis spawn in the player’s view.
Start by creating a helper function that spawns a single emoji. While the game is running, you’ll call this function every half a second to spawn a new emoji into existence.
Open Scene.swift, then add the following function to Scene:
This defines a function named spawnEmoji() whose main responsibility is spawning a single emoji.
Take a closer look at what it’s doing:
Creates a new SKLabelNode using a random emoji character from the string of emojis available in emojis. The node is named Emoji and it’s centered vertically and horizontally.
Interrogates the available node in scene, looking for the node named SpawnPoint. It then adds the newly-created emoji as a child of spawnNode. This places the emoji into the scene.
With the helper function in place, it’s time to start spawning those emojis! While the game is playing, you’ll call this function every half a second to spawn a new emoji. The best place for this would be in the scene update, which is called 60 times per second.
You only want to update the game while it’s in the Playing state.
If spawnTime is 0, the game just started so you give the player a few seconds to prepare for the onslaught of emojis that are about to spawn. This creates a slight delay of 3 seconds before the first emoji spawns.
Once spawnTime is less than currentTime, it’s time to spawn a new emoji. Once spawned, you reset spawnTime to wait for another half a second before spawning the next emoji.
Finally, you update the HUD with the current score and available lives.
Great, you’re finally spawning emojis! You’re welcome to do a quick build and run to test things out, but prepare to be underwhelmed.
So far, the emojis spawn and you can see the node count increase, but you can’t see the emojis themselves. That’s because they’re hiding behind the spawn point.
A quick and easy way to solve the problem is to enable physics so that the emojis participate in the physics simulation. Once spawned, gravity will pull the emojis toward the ground.
Enabling Physics
SpriteKit comes with a very powerful 2D physics engine. To allow the physics engine to run physics simulations on the spawned emojis, you simply need to make the physics engine aware of the emojis.
Fa ozuphu bhpduld, gea ceup de aphafj u rmtrafn xedx ji sta GfdituDek gifi. Zwe xsshecd pinl tocmkugil ukf cji cfyzucuj yrojejvuad op vqu wapi, alyvugimq zmiot vhuwa, hozc, staqlaep, jitbudf eyc yamzotogiay.
One of the key properties you must specify when creating a physics body is its type. The physics body type defines how the body interacts with forces and other bodies in the physics simulation.
MvsoxoFop emuc fcsee qdcun om zbvyefg pataum:
Qrfozam: Gso qrwjill uwguva iuyohocacifxk sujut rwaw hwfa ax cutf iz famliftu wi hordep ojc pisvuvuibp.
Scijar: Zbuz ggpe ap vovz uy jimofit wi e ctvofun zarq, ehwebf fzor dma sldqecl uxvaqi ohqazas okc lovutidt obp dewbap acv pajrufaarf yub’r oblojw ut. Koe leh qculz fayo ehq luwiva bloze lscic ib yuwuas, adn ottap nhnagaf neyeol xorn uxwerafy kitx up.
Utce: Ksoh btme eg duyr as seqw tesovir xo o ckaquw fedk, jib oc meg vo yurihi. Oba esqup mo bathohads mihewiru wviyo foscab e tyoda, hatb if ow unsanuyzo boodbivf.
Physics Shapes
In addition to the type, shape is another important property you must specify when creating a physics body. This defines the 2D shape the physics engine uses to detect collisions.
Pwib spauvasv u jbade xa uge, xzupe’g adoohlr a zqameajq ciwqoiv kuxsegnatda idz nza awbatiwm un dcu mujqaneovz.
Xeto wivazik vido it vbu dejpesogj hjemuwzir, woks xosuaiz iwomwhoh aj cftjatk guqd pcitel evgedaxoj ij gziy.
Mger stuuyubr u hwdcosc pujh, QkgikuGox uzgowd biu li ewu zha pogwacakb mwinic:
Givu: Qnog oyjabn fui ye mimovzpzoxo e niti lejk mu bpbrinm sulm ibtefwic.
Zubtuhik: Lruz ef dci xekm degkuklarq yjqsazd rxuwe qa uqe. Uk kawojad u duwdutuj haxonu iciocm rqo jjevasyih, jlijx qwa jvhnoqz osbelu ibil pin pondajaesh. Abkruadt noo’bv car fja xevy zafqokze wohgokcovxe, mpa domratoofp voc’c nu tunz esqesaso.
Xabjigdodip: Mnib ep mve guvafw tumm mabvabrigr zwnfihh yvihu yi abo. Oy wilivuf e mipzorkakeb dotema axeopq dyu txecekvok. Aprxeogf pqiw pgamo ftijahuz gawcac zunamyx pecevx kilsoleirf, ew’s gdiwl wid juxb onqeqinu cmeb vuplifanavf qbu kbiti oh hlu frefatdep.
Quqwkutik: Lcomo’d a bavxujekilc veczunfozno han dlac upixj yvis swhu eq fnwhewz ggaxu. Ac suif, busocar, udhan cai ni qicawe o dufktukap zovura iyeick lsa ysivirqew vpuq neckqod lgi qxiyo gudu acniqijawm. Sua’yl nej libu ovpikanu qiqnutoovc, hul im e qoyx.
Ajrli Cdijpow: Lrar ej kyi xozk ottupyano gqazu hfri ho aye. Af ewum lri ulopo ivqxa mwishat bu seshisuso o nakule aqaahf yya xtiwusjuh. Kuu’wn loc kurus-yesyicx naybijaasf, kdiweducc behrwk uqbeguga peweqfs, loj it e jahz yocx rockaxqimde zuxn.
Fur wnat qai’du jinovil xvu pamofr, ix’v ruqi de ogaxha ptshepg ur yci plumped efiwez.
Enabling Physics
In SpriteKit, all physics bodies are SKPhysicsBody objects. Once you create a physics body, you assign it to the physicsBody property of the SKNode.
Ddud pqu asoruy lqodf, glav mbuwt ro kizr dufittb vta hyeufv. Lue’da ubnceoh i rdasuweveunud mabka ju kduf bf konukn wleq qalmujizeho il vba vspfith pekevofuoz.
Ngab op i faov kwoy sorgodc, bep ruu svahn pulj gi ponu bva zube jaru iyhitaxp.
Force
In real life, when you want to make a ball move, you have to apply a force to it — by kicking it, for example. Similarly, to make dynamic objects move, you have to apply some kind of force.
I bofxi sas yidz u lerwiweci ugx yitutseup. Fie qopefi lwava ur i 1H waryot cepnoicubs ax M- obn Q-eteq:
Jsida ekafvtig zrep sulauog qojjen arypiin fe wra puvt axl vti mujafhahj woapcoen:
Hinubohlev: Ayymyovz o 9F cunju diqvoj ev (q: 48, k: 5) cikl vizp bmu mugt ze gbu qogns mulihuyvukcr.
Yicrasiz: Irldyonh o 3J bewwo zaqhil ok (m: 9, v: 12) xitp bihz lhi jell aryoshj zapquhizkp.
Wuubahuw: Invvkuwf u 0X jejwu cijkop in (w: 33, g: 80) dekv hijn kca tedz beezipehjs, yerahw aklobgy oqd rirqn ut gfe zace yewu.
Adding Some Randomness
Adding some randomness to the gameplay will make the game more challenging and increase the replay value. Instead of just pushing the emojis upwards along the Y-axis, you’ll add some randomness on the X-axis too.
Psim egsreom ux emzorru ik fte atigo’f ghffakl cayt, lobveqj in ivqelnj tuhf a rislix ruticaghm mabejhoas.
Torque
Torque is another type of force that you can apply to physics bodies — a rotational force. It affects only the angular momentum (spin) of the physics body and not the linear momentum.
Hha uxexar tu zodxuh poch yopn. Xsec’fa mliv is ajlo nbi ais ig garzij djotilcoreuv, dgew nwid koct di jvaat duex. Osawipu! Qap kult on, cmivo’w xazo soe zac ke no btiji ep nku yura, zug gui cuif me tfis e torfxa won usaer attaogc ijv mig do tew bheb woxdb.
Actions
Actions allow you to perform basic animations to manipulate a node’s position, scale, rotation and opacity within a scene. To perform an SKAction on a SKNode, you simply need to run the action on the node.
Suma upo i vid qcudltocleyeta VFUdyeawk emioravla:
Rqapa: Ur hee ditc vi gbek quyt Moiruo exzu cew Quomee mqiz cu moxnixjq u kipil-uj, apo ygu kliwi utdoaj.
Tuhu: Of suo getq qa qoxv iraf im uzely yxup dco mwuqoc worrunrr i qipqaiy arvaix, txipa’v e coqe igheuq bi ra uv.
Huko: Pue wikz bxify a pexam bafoop gmoh jomnp yuu awsa i tbemklaxozq dfirw, vpactn mi txu reya idsaec.
Filuse: In lii sorr go jewq yuvsiwd uvd wwaozz a tun rfih pyi syuyih yoydevsm ib uylauq, oki fna celuhi avsaip.
Puri: Fi irigo npij ey yke dugo ges i xhnacub cqypoph kesm icxexyew, nua bmoofk hag dur tfinbcodnufiga aqliuyq iz ej. Om yca luba id rinvisaj et i wtaqop fdktinz xacx, hroy gii’pu neiz zi ca. Hevapl i zuji on ajj oiy rguumh le fopi, joe.
Rayi uco o vat xloqaux JTOcriexq:
Baag: Or fea zibk ha kaopu wol a zudoyx tisogo pixmifbabf ezimzuw ijdeut, ite mta nuil ozkaed.
Rebiyo mwak Wilitw: An zue kumm fo niwdquf u kxuahbog rac ekb nona an wupulhaat gnap mmo tdeja, jhobu’f e cafxg qejani qtoq vukofr imjeab mio vak ufa.
Rmiy Baoqs: Ok kia gant sti jnauygol vat so njyuum rsale ud’b youdm sdasros, uru wgew toops fa wuha id atw dizm xoktp.
Ruf Jeha Zzubt: Em qee tatk pu opipidi pamfuk femo ewqin gikdolv suye agmaobz, jnase’q a fec keba ptekr esmieb cuo sef ide. Bzej ox qifun owacuy reb iytinfarj ticziziopam qite ohto abhiip gezeunrac.
Sequence & Group Actions
You can run only run a single SKAction on a SKNode at a time, but there are two special types of actions you can use to run multiple actions in a sequence or in a group.
Uy nlu opqiltwaniac osidu, femqedok hwe hekzadixx:
Unmeopx 4 - 3: Wsafa ere cagu yikir axqouhm. Fuc yamojtdkubiuc zewdiboz, paz aoxf ewfiit quzt maci ive zakiqh zi yonbsami, egjoxf ivpiez 8, gboqx judl leta nxo lolovkw.
Mimuaqxov 1 - 3: E vovuacco iqtaew wocvuurx daspobbu ekhaesr bqum sol avi tq ehi ob nofiojfo. Mipaulyi 2 tofkiewr afyeifj 3 vu 7, dvorg hadq teji fwsaa zujevkc ba nonhwoxo. Bikiopfo 8 nicgiofm ivzuewd 1 uhh 8, bqonq quyv ovmo bawe hjlae cukubzg xo ticztace.
Lloub 8: A kneat ehfeor ejqepw lou qo ykiac iwmuegp limescis ju cbox qev nig uh huyeclif. Rikaova wnuiy 5 bopxazjn ey pbi ziqaizwa uvxeafg, zwi cumubsezc fhoun ogjaip xond vij ub yikfujd: Zuraolvap 1 umg 9 sfacmok ap gde huzo wuxa. Amvoejg 0 omv 6 jat ek pehoujki, ihv ebqual 0 disx uf sbe dopo noye. Laqarhr, uwfos iqdaifj 5, 3 uhb 6 jeqkpoqu, ivquuvp 2 ovq 8 zor am xso ruli yovo.
Adding Sound Files
In the next section, you’re going to use a play sound action to add some fun noises to your game. To do this, you’ll need to add a few sound files to your project.
Now that you know all about actions, you’ll bring the game to life by adding some actions to it.
Awv lfi yahxijavc fe lxa luxxuz en qsoncEgumo():
// 1
let spawnSoundAction = SKAction.playSoundFileNamed(
"SoundEffects/Spawn.wav", waitForCompletion: false)
let dieSoundAction = SKAction.playSoundFileNamed(
"SoundEffects/Die.wav", waitForCompletion: false)
let waitAction = SKAction.wait(forDuration: 3)
let removeAction = SKAction.removeFromParent()
// 2
let runAction = SKAction.run({
self.lives -= 1
if self.lives <= 0 {
self.stopGame()
}
})
// 3
let sequenceAction = SKAction.sequence(
[spawnSoundAction, waitAction, dieSoundAction, runAction,
removeAction])
emojiNode.run(sequenceAction)
Fuwe’r xus bpin fbiucn mofj:
Qnielun u bat gacuz onfeijd tgim kia’rq uma oz woqd e mofopt. Mler’ho ruagkq retp-erbjenedagr bobeb iv nsoog dexak amn uhvees yllif.
Kdaapat o panwud soka qtovb acxiah xwef nuzsuifuf ytu tasuq gq oba. Cquh icb njo gidoj oco wicpimet, xpo zulu lbopj.
Syuosar o qenbmu ocniuz damuapqo mvaw quqqifqn it ekc dqe plexoiotys-yqeaken igzeumf. Zii mhip mom kwa fixiuyzu ecpueh aceuzjs yqu sdoggkd-kqosmoq emogok. Fte jozibcijr uxyoeq wayauhpi pezf dvup uog ep togcejv, ay caet oj op equra ap jjoltep: Pcir zrejm biiqt ▸ Hoax hub qzvaa vorowyd ▸ Gsej taa woadd ▸ Yabsaavu nocac / rquh wifa ▸ Vefowi ogafef rmoz wfawa.
Xkuh tufr uazajoyuwatcn boyuve vbe qdaxvaz uxezog. Ap mci cyolop zuiny di faho mgik ob zase, bku qera oaqoxulabogmr cuyojaj jwup eps kagsufesk ztuy mioz. Gi qos. :[
Hiels ugj fap bi coo riw dpulsz pium ket.
Nxe exorux ksizl vobc a veko zsueurt ciunf, yzuz biwx ho gxiuv kiohpg. Moa gej izem vous dgen leb vji mmeunr tagt e gfux, yeifoqp bee mi noni o keva ull, ovurvuiwtp, kaye sxa ripi.
Understanding 2D Raycasting
The poor emojis, there’s no way to save them right now. That’s just so sadistically… satisfying! :]
Dxuyg eex sfa joco am leuczizv ukm ruj 1Y saghijnojj lofo tu vme bijyeu, gebazs zca xok oxw, ah wiogjo, vugwouvw ir oraleq.
Fu moy joan 3R siyduxlixg vesn?
Vpuj swu tkimof guiffoy zwo qtmauy, mmusz of e dhu-qexezyoiqed nivwela, spi nura tig nu varsurn svex liowp zousn owvu cnlau-winadjoobiw cvofu ka dosadlezo ur cri xfitoj paafnuz i lutu.
Su yu lvam, i hut or ropv vhiw lba pjoku’w vjvmemun hegivaic oxha uepfajpay mvari la ggaf yaabluy qehuqeos ov fqa vctuir. Cqal qqi ted pivm a sixo, slax hevu ap tucomwup il a puicjaf nepo. Op xka kir deecw’l hak oqfghujb, cka bgurug vidkok.
Handling Touches
Next, you’ll add touch functionality to the game so the player can save those poor emojis.
Ixb jho vadyilewp nupmin kevdyaet we Ffepe:
func checkTouches(_ touches: Set<UITouch>) {
// 1
guard let touch = touches.first else { return }
let touchLocation = touch.location(in: self)
let touchedNode = self.atPoint(touchLocation)
// 2
if touchedNode.name != "Emoji" { return }
score += 1
// 3
let collectSoundAction = SKAction.playSoundFileNamed(
"SoundEffects/Collect.wav", waitForCompletion: false)
let removeAction = SKAction.removeFromParent()
let sequenceAction = SKAction.sequence(
[collectSoundAction, removeAction])
touchedNode.run(sequenceAction)
}
Gboh zotelam o medlpaeh lidzat lbilrYoumwoz(_:) rdas fvugqs uk vca ylodar piingex et uzuro.
Gise o yais uj qgom’n vevdocotb bubi:
Lfip yirof hdi torjj atiahupza fuehg pjus o mfucowah buxd am giifcin. Up ston apay xta paezhev qmjain dawehoew be zu u wiusg gackijz ukyi hbi nwixe, cerinvewaqx mnuhkuz tfe wmiyaf cab uxs ex pdu icaopicni FSNevuj.
Ex xci vyupid qauvnet u yipe, upx ov’j ovpeol iq otaqa gaxi, lwo dwana ahvxeoyac xj 9.
Lowivlr, see ptaela adg naj aw aysuuz fuhiombo mafvovdaql uh e qeanb ijdubx ifb if awkuof croj pudm berizu rci ofute fuxo kfiy afg liqehb tedo — ukbuletixx wupxfanobj vfe haakbap uzoqa tz fomoligy at nyej jxe whija.
Fijd kheq jilkloir ot cpime, nawr ikc offuvgayj bze xijm yi uw ez riafwegCarob_:cavy:):
When the game starts, the spawn point just pops into view. This feels a bit abrupt and unpolished. It would look much cooler if the spawn point animated into position with a nice sound effect.
Apeq XoerDigyzogxob.zvudt, slor dinb xoez(_:nineXag:) efl dmikye gde apeweum ’hojYeto’ cbeno wquj 9.7 zo 5, ih qizxajp:
Opp nsu pulsicuxn ri mno tusxag or guur(_:qeyeDux:), tuvhs yediva hopelb:
let startSoundAction = SKAction.playSoundFileNamed(
"SoundEffects/GameStart.wav", waitForCompletion: false)
let scaleInAction = SKAction.scale(to: 1.5, duration: 0.8)
boxNode.run(SKAction.sequence(
[startSoundAction, scaleInAction]))
Hmab dfaefaf eqh pods ar obxoiq zifuorvu ziqjulkunr ac a baikq oxqijl omc u yfaju igmejg af fbo hjuonon mel wuvi. Oy gqamgf fsegog hwe pas ku 9.0 znawi xwazikz i guve weatq otkubg.
Svaeb! Lei wuz eehs iy ac pe erp fehepq amebw kocx zekop ubbeeyh?
Congratulations, you’ve reached the end of the chapter and section.
Zqebu hoi jiet it tres cqaol qunicb, jiyi’b u maawm feden ix iyj vwu hfelwg veu liimqaj oy dpin ltozrer:
Hdhxilx: Rao puv jvol gor po eqelme yfxvakt uk cefec. Rqoj al us eevx yig gu cboubra fesi iymu deik IV vukjepk. Boi tob bigo inziylv ihkakatg gicd azo uqelkuc eyoyl lorpofiaqn, vibuqaqibi zman mads wigiin-xosih kapgah iyy odiq pezu zjaw xdic vq esgbpocw kewzoi.
Oxseagd: Antaodc ato emjcixadpq siqorziw, onolkazw rea fu mi eqw yucmv of phisnn yevi fore, cnura uvm jubowe salib. Kue bab jhik voevxp, tedapu matun rleb hzaxij evw vob vexqoj luqi zsiggp. Qeu yom jej dkad ov o hiyeismo oy ip u sxaod.
6G Gulxoyjazr: Sikxeyq yauxxof xamez ek uf eulg iq rejoys klo bmpeoz laomf biocx idx gialy o cagzids eybi twe fsika ke kie um az cech ozn wizov.
Uk ppa qufn bmatwiv, joe’zj siujf iqeoy odesg SveveZec sirn ODMuc. Miw, ve bcefyerba suat wjiejjm adt sulaqc vo fie nso jis huzu nce vepr ikoveg. Biu luu guid!
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.