Figure 1 – Versiuni software pe platformele iOS și Android 1 https:www.statista.com [624023]
1 UNIVERSITATEA DE VEST DIN TIMIȘOARA FACULTATEA DE MATEMATICĂ și INFORMATICĂ PROGRAMUL DE STUDII DE LICENȚĂ: INFORMATICĂ ROMÂNĂ LUCRARE DE LICENȚĂ COORDONATOR: ABSOLVENT: [anonimizat] 2018
2 UNIVERSITATEA DE VEST DIN TIMIȘOARA FACULTATEA DE MATEMATICĂ și INFORMATICĂ PROGRAMUL DE STUDII DE LICENȚĂ: INFORMATICĂ ROMÂNĂ MOUNTAIN HILL RACING JOC MOBIL PENTRU PLATFORMA IOS BAZAT PE FIZICA COORDONATOR: ABSOLVENT: [anonimizat] 2018
3 Rezumat Jocurile întotdeauna au fost văzute ca o activitate distractivă fiind folosite în scop recreațional. Dar cum lumea a evoluat și totul se mișcă la o viteză mult mai mare, majoritatea oamenilor nu au timpul necesar de a ieși cu prietenii la activități recreaționale precum jocurile de fotbal, tenis, sau orice alt tip de joc. Însă nevoile oamenilor sunt tot aceleași. Pentru a funcționa corect pe lângă nevoile fiziologice și cele biologice, oamenii au nevoie să fie relaxați, să se simtă bine. De aceea odată cu apariția tehnologiei necesare au apărut și jocurile video, acestea putând oferi o portiță temporara de ieșire din lumea reală și a stresului asociat acesteia. Astfel, odată cu evoluția tehnologică au apărut dispozitive mobile capabile să ruleze jocuri video, acestea având avantajul că pot fi folosite de oriunde. Astfel, scopul acestei lucrări este crearea unui joc pentru platforma mobilă iOS. Un joc care să fie atât distractiv cât și relaxant.
4 Abstract Games have always been seen as a fun activity being used in recreational purpose. But as the world evolved and everything moves at a much higher speed, most people do not have the time to go out with their friends to recreational activities such as football, tennis, or any other type of game. But people's needs are the same. To function properly besides physiological and biological needs, people have the need to be relaxed, to feel good. Therefore, with the emergence of the necessary technology, video games also appeared, which could provide a temporary exit gateway from the real world and the associated stress. Thus, with the technological evolution, mobile devices have been developed to be able to play video games, with the advantage that they can be used anywhere. Thus, the purpose of this work is to create a game for the iOS mobile platform. A game that is both fun and relaxing.
5 Cuprins Rezumat Abstract 1 Introducere ………………………………………………………………………………………………………… 7 1.1 Motivul alegerii platformei iOS …………………………………………………………………….. 7 1.2 Platforma iOS ……………………………………………………………………………………………… 8 1.3 Jocurile video ………………………………………………………………………………………………. 9 1.4 Telefoane mobile de gaming ………………………………………………………………………… 11 1.5 Jocurile video mobile în 2018 și în viitor ………………………………………………………. 11 1.6 Scop ………………………………………………………………………………………………………….. 12 2 Jocuri pe platforme mobile ………………………………………………………………………………… 13 3 Tehnologii folosite în cadrul aplicației …………………………………………………………………. 15 3.1 Xcode ………………………………………………………………………………………………………… 15 3.1.1 Caracteristicile principale ……………………………………………………………………….. 15 3.1.2 Inteface Builder ……………………………………………………………………………………… 16 3.1.3 Assistant Editor ……………………………………………………………………………………… 16 3.2 Swift …………………………………………………………………………………………………………. 17 3.2.1 Opționale ……………………………………………………………………………………………….. 17 3.2.2 Optional Binding (atribuirea opționalelor) ……………………………………………….. 19 3.3 SpriteKit …………………………………………………………………………………………………… 20 3.3.1 Texture Atlas …………………………………………………………………………………………. 20 3.3.2 Fizica …………………………………………………………………………………………………….. 21 3.3.3 Scene Editor …………………………………………………………………………………………… 22
6 3.4 Adobe Photoshop ……………………………………………………………………………………….. 23 4 Prezentarea aplicației ………………………………………………………………………………………… 24 4.1 Descriere …………………………………………………………………………………………………… 24 4.2 Gameplay ………………………………………………………………………………………………….. 24 4.3 Modul de implementare ……………………………………………………………………………… 26 4.3.1 Crearea unui nou proiect ………………………………………………………………………… 26 4.3.2 Descrierea funcționalității ……………………………………………………………………….. 28 4.3.3 Conectarea corpurilor fizice …………………………………………………………………….. 30 4.3.4 Crearea terenului ……………………………………………………………………………………. 31 4.3.5 Deplasarea mașinii și camera …………………………………………………………………… 33 4.3.6 Controlul în timpul săriturilor și testarea coliziunilor ………………………………… 34 5 Concluzii ………………………………………………………………………………………………………….. 37 5.1 Viitoare îmbunătățiri …………………………………………………………………………………. 37 Bibliografie ……………………………………………………………………………………………………………… 39
7 1 Introducere 1.1 Motivul alegerii platformei iOS Principalul motiv pentru care s-a decis ca acest joc să fie dezvoltat pe platforma iOS și nu platforma Android este cunoscut sub termenul de fragmentare. Fragmentarea este termenul folosit pentru a descrie situația în care unii utilizatori folosesc versiuni software mai vechi decât alții pe aceeași platforma. Această fragmentare fiind o problema destul de mare pentru dezvoltatorii de software. Deoarece cu cât diversitatea versiunilor software este mai mare cu atât mai greu îi este unui dezvoltator să optimizeze aplicația sa pentru toate aceste versiuni. Deoarece platforma iOS a avut un avantaj fată de platforma Android la acest capitol și încă are inclusiv pe ultima versiune software iOS 11.3 lansata la data de 29 Martie 2018. Conform site-ului1, 65% din dispozitivele mobile iOS rulează o versiune de iOS 11 și 28% ruleaza versiunea iOS 10. în timp ce ultima versiune a platformei Android este folosita pe doar 1% din totalul de dispozitive și peste 40% folosesc versiuni mai vechi de 3 ani (Figure 1). [1]
Figure 1 – Versiuni software pe platformele iOS și Android 1 https://www.statista.com /
8 1.2 Platforma iOS Platforma iOS este un sistem de operare mobil, care are la bază Unix. Este creat de Apple și este folosit exclusiv pe produsele lor hardware. Este al doilea cel mai popular sistem de operare folosit pe telefoane mobile inteligente, pe prima poziție fiind sistemul de operare Android. Cu toate că aceste sisteme de operare erau foarte diferite în primi ani de la lansare, acum la mai mult de un deceniu de la lansare ambele încep să devină foarte similare. Inițial sistemul de operare a fost folosit pe iPhone, dar apoi a fost extins către iPod Touch la câteva luni de la lansare, iar 3 ani mai târziu în 2010, Apple a lansat încă un produs , iPad, rulând același sistem de operare. Toate dispozitivele ce rulează iOS sunt touch-screen, prin urmare interfața utilizator se face prin manipularea directă folosind gesturi touch. Dar Apple nu s-a limitat doar la atât, sistemul de operare fiind capabil să interpreteze și alte metode de comunicare cu ajutor-ul senzorilor încorporați în dispozitive. Precum accelerometrul, giroscopul, senzorul de proximitate, etc. Întotdeauna Apple si-a dorit un produs inovator, de aceea a încercat de mai multe ori să profite la maxim de tehnologia curentă aducând noi moduri de interacționare cu telefonul. O caracteristică foarte interesantă fiind "3D Touch", acesta fiind exact cea ce numele sugerează, ci anume a 3-a dimensiune pe care ecranul senzitiv o poate interpreta, adică forța de apasare ce este exercitată asupra ecranului. Sistemul de operare profită din plin integrând diferite scurtături care pot fi accesate cu ajutorul unor apăsări mai ferme asupra ecranului. Un mare avantaj al acestui sistem de operare este că și hardware-ul este creat tot de Apple, de aceea aceste produse au o imagine ca fiind foarte stabile și cu mult mai puține bug-uri. Dar aceasta stabilitate nu este datorata doar acestui lucru, ci și faptului că este closed-source. Precum orice sistem de operare modern și matur iOS este un sistem de operare multitasking, trecerea de la o aplicație la alta se face foarte ușor, majoritatea gesturilor fiind foarte intuitive. iOS vine la pachet și cu un asistent virtual "Siri", care s-a îmbunătățit odată cu maturizarea sistemului de operare. [2]
9 1.3 Jocurile video Un joc video este un joc electronic jucat pe un ecran video care presupune interacțiunea cu o interfață utilizator pentru a genera un răspuns. Interacțiunea cu interfața utilizator se poate realiza în mai multe moduri în funcție de platforma pe care ne jucam. Exemple de platforme pentru jocuri video sunt: computerele personale, consolele de jocuri, telefoanele mobile, tabletele, etc. Pentru o consolă sau un computer personal interacțiunea cu interfața utilizator se poate realiza cu ajutorul tastaturii și a mouse-ului, sau cu ajutorul unui joystick. Pentru telefoanele mobile sau tablete interacțiunea se mai poate realiza și cu ajutorul ecranului senzitiv al acestora. Jocurile video au prezentat un interes pentru oameni încă din 1947 când a fost inventat primul joc video, ci anume un simulator pentru un aruncător de rachete. Jocurile video reprezintă un interes pentru oameni deoarece adesea acestea oferă recompense jucătorilor (puncte, bonusuri, deblocarea unor noi nivele mai grele, etc.) dar de cele mai multe ori au și un scop care este atins la sfârsitul jocului, astfel stârnindu-le curiozitatea și determinându-i să se joace în continuare. Jocurile video se pot clasifica în mai multe clase: • Jocuri video complexe • Jocuri video cu scop educațional • Jocuri video ocazionale Jocurile video complexe presupun ca jucătorul să petreacă mai mult timp dobândind experiența și cunoștințele necesare pentru a putea îndeplini scopul jocului și prin urmare sunt jocuri de dimensiuni mai mari și care necesita ecrane mai mari pentru a putea reprezenta tot contentul grafic necesar. De aceea aceste jocuri de obicei sunt destinate consolelor video sau computerelor personale, fiind jucate acasă sau într-un loc special destinat (sălilor de jocuri) într-o poziție relaxata care permite jucarea pe perioade mai lungi de timp. A doua categorie de jocuri video sunt cele cu scop educațional, acestea fiind ideale pentru toate platformele. Exact cum sugerează și denumirea acestea au ca scop principal dobândirea de cunoștințe noi, încercând să facă acest lucru într-un mod mai distractiv decât clasicele metode de învățare.
10 Cea de-a treia categorie sunt jocurile video ocazionale, acestea nu necesita reguli complexe de învățat astfel ele fiind o alegere grozavă pentru platformele mobile deoarece acestea permit utilizatorilor să se joace oriunde s-ar afla. [3] Astfel nu este de mirare că cele mai populare tipuri de aplicații, conform site-ului2, în Apple App Store în luna mai 2018 sunt jocurile video, cu un procent de 24.93% din totalul aplicaților descărcate.
Figure 2 – statistica cele mai populare tipuri de aplicații în mai 2018 în Apple App Store 2 https://www.statista.com/statistics/270291/popular-categories-in-the-app-store/
11 1.4 Telefoane mobile de gaming Cum jocurile video reprezintă cele mai populare aplicații pentru telefoanele mobile este normal ca producătorii acestora să aducă pe piață modele special concepute pentru așa ceva, astfel dotând telefoanele mobile cu ecrane de dimensiuni cat mai generoase, de rezoluții foarte înalte, procesoare grafice de cea mai înaltă performanta și cu baterii cat mai mari pentru a putea livra energia necesara acestor componente de top pe perioade îndelungate. Cele mai extravagante dintre ele venind chiar și cu dispozitive în plus specializate pentru răcire. Însă chitul de răcire nu este totul, producătorii de telefoane mobile pentru gaming au decis să meargă mai departe creând și dock-uri speciale pentru ele ducând experiența de gaming la un alt nivel. Prin intermediul acestor dock-uri jucătorii bucurându-se de o forma mai ergonomica în mana, un ecran în plus și o baterie inclusa în acesta pentru sesiuni de gaming și mai lungi. [4] 1.5 Jocurile video mobile în 2018 și în viitor Astfel în 2018 venitul total produs de industria jocurilor video de pe platformele mobile o să genereze 51% din venitul total din industria jocurilor video. Adică mai mult decât consolele video și computerele personale împreună și va continua să crească în următorii ani. [5]
Figure 3 – grafic venit industria jocurilor video.
12 1.6 Scop Plecând de la aceste cifre și văzând cat de mare este aceasta industrie a jocurilor video și mai ales potențialul care îl are în viitor, scopul acestei lucrări este de a crea un joc video ușor de jucat dar în același timp foarte distractiv, adică un joc perfect pentru platforma mobilă iOS. Jocul "Mountain Hill Racing" va fi dezvoltat astfel încât corpurilor fizice să se comporte cat mai real și cu grafică la fel de reală.
13 2 Jocuri pe platforme mobile Unul dintre cele mai de succes jocuri pe platformele mobile care implementează un sistem fizic foarte real îl reprezintă seria "Hill Climb Racing3" lansată spre sfarșitul anului 2012 atât pe platforma iOS cât și pe platforma Android, iar apoi, un an mai târziu a apărut pe Windows Phone și Windows 8.1. Figure 4 – Hill Climb Racing în Apple App Store Un joc care se bucură de un rating de 4.4 stele atât în Apple App Store4 (platforma iOS) cât și în Magazinul Google Play5 (platforma Android). În primul an de la lansarea sa jocul a fost descărcat de peste 100 de milioane de ori, iar in 2014 depășind 200 de milioane de descărcări. Scopul jocului este acela de-a urca cât mai mult dintr-un munte cu o mașina. Modul în care jocul este implementat îi determină pe jucători să petreacă cât mai multe ore în acest joc dacă vor să parcurgă distanțe mari. Acest lucru nu se datorează dificultății jocului, se datorează faptului că jucătorii sunt nevoiți să strângă cât mai multe puncte și bănuți pentru a putea cumpăra noi componente pentru mașină. Astfel mașina devenind mai performantă și prin urmare capabilă să parcurgă distanțe mai mari. Această abordare a jocului este una foarte inteligentă deoarece jucătorii rămân captivați încercând să îndeplinească acest scop, dar în același timp nu sunt nici descurajați cum se intâmplă în jocuri foarte dificile. 3 https://fingersoft.net/games/hill-climb-racing/ 4 https://itunes.apple.com/us/app/hill-climb-racing/id564540143?mt=8 5 https://play.google.com/store/apps/details?id=com.fingersoft.hillclimb&hl=ro
14 Odată cu versiunea 1.31.0 jocul a introdus un element nou "Garajul" oferind jucătorilor libertatea de a crea proprile lor mașini. Cea de-a doua versiune a jocului creat de dezvoltatorul Fingersoft6, este "Hill Climb Racing 27" care de asemenea se bucură de un rating de 4.6 stele pe ambele platforme mobile. Jocul a fost lansat 4 ani mai târziu de la lansarea primei versiuni și anume la sfârșitul anului 2016. Această versiune a introdus modul multiplayer cu 4 jucători care concurează in 4 locații diferite, fiecare încercând să scoată timpul cel mai bun. Peste acest mod multiplayer printre cele mai importante imbunătățiri aduse de a doua versiune este grafica mult mai bună a jocului. [1] Dupa succesul generat de această serie de jocuri, au apărut foarte multe soluții alternative, unele dintre ele chiar 3D. Astfel de jocuri sunt: • Bike Race: Motorcycle Racing8 • MMX Hill Dash – OffRoad Racing9 • MMX Hill Dash 2 – Race Offroad10 • Happy Racing – Online Wheels11 • Monster Trucks Racing12
6 https://fingersoft.net 7 https://fingersoft.net/games/hill-climb-racing-2/ 8 https://itunes.apple.com/us/app/bike-race-motorcycle-racing/id510461758?mt=8 9 https://itunes.apple.com/us/app/mmx-hill-dash-offroad-racing/id1057961675?mt=8 10 https://itunes.apple.com/us/app/mmx-hill-dash-2-race-offroad/id1271725269?mt=8 11 https://itunes.apple.com/us/app/happy-racing-online-wheels/id1191488599?mt=8 12 https://itunes.apple.com/us/app/monster-trucks-racing/id949846482?mt=8
15 3 Tehnologii folosite în cadrul aplicației 3.1 Xcode Xcode13 este un mediu de dezvoltare integrat (IDE14 – Integrated Development Environment) special creat pentru sistemul de operare macOS15 de către Apple16. Acesta conține o suită de instrumente de dezvoltare software de asemenea create de Apple pentru a ajuta la dezvoltarea software pentru toate sistemele de operare iOS, macOS, watchOS și tvOS. Prima oară a fost lansat în anul 2003, de atunci au fost lansate mai multe versiuni, ultima versiune stabilă fiind versiunea 9.4.1, aceasta este disponibilă utilizatorilor de macOS gratuit prin intermediul Mac App Store. Însă dezvoltatorii înregistrați pot accesa versiuni mai vechi sau chiar versiuni beta, indisponibile în Mac App Store pentru toți utilizatori, prin intermediul website-ului Apple Developer17. 3.1.1 Caracteristicile principale Xcode suporta cod sursa pentru limbajele de programare C, C++, Objective-C, Objective-C++, Java, AppleScript, Python, Ruby, ResEdit și Swift. Suita Xcode conține majoritatea documentației Apple Developer și integrează Interface Builder18, o aplicație folosită la crearea interfeței grafice pentru utilizatori. [6] 13 https://developer.apple.com/xcode 14 https://en.wikipedia.org/wiki/Integrated_development_environment 15 https://www.apple.com/macos 16 https://www.apple.com 17 https://developer.apple.com 18 https://en.wikipedia.org/wiki/Interface_Builder
16 3.1.2 Inteface Builder Complet integrata în Xcode IDE, rolul acesteia este de a ajuta la prototiparea unei interfețe utilizator fără scrierea unei linii de cod. După terminarea prototipării design-ului, putem conecta interfața la sursă în editorul din Xcode, amenajând ferestre, butoane și slidere pentru crearea unei interfețe utilizator funcțională. 3.1.3 Assistant Editor Butonul Assistant Editor împarte editorul Xcode în două, cu principalul document în stânga și un panou editor asistent inteligent în partea dreaptă. Asistentul editor (Figure 5) afișează în mod automat fișiere care Xcode crede că sunt cele mai importate în funcție de munca pe care o efectuam în editorul principal. [7]
Figure 5 – Interface Builder și Assistant Editor
17 3.2 Swift Swift19 este un limbaj de programare special creat de Apple cu scopul de a înlocui Objective – C. Swift este un limbaj de programare open-source modern, codul este compilat și optimizat astfel încât să obțină performanta maxima pe platformele hardware moderne, în timp ce sintaxa limbajului este una care să fie eficiență din punct de vedere al dezvoltării. Este un echilibru intre simplitatea sintaxei codului, siguranță și performantă fără a face rabat la niciuna dintre ele. De aceea este o alegere buna pentru orice program, de la cele mai simple pana la cele mai complexe. Astfel codul este mult mai ușor de scris și citit, iar prin urmare mult mai ușor de întreținut. Swift elimina unele erori ce pot apărea într-un program implementând metode moderne de programare: • Variabilele sunt întotdeauna inițializate înainte de folosire. • Indicii matricelor sunt verificați să nu iasă în afara limitelor. • Întregi sunt verificați pentru overflow. • Opționalele asigura faptul că valorile nule (nil) sunt tratate în mod explicit. • Memoria este gestionată în mod automat. [8] 3.2.1 Opționale Opționalele sunt un doar un nou tip în limbajul de programare Swift. Opționalele se folosesc oricând se dorește ca o variabilă să nu aibă neapărat o valoare, ci anume să poată fi și nulă (nil). Dacă o variabilă este de tipul întreg atunci ea tot timpul va avea o valoare întreagă, dar daca este de tipul întreg opțional atunci ea poate să nu aibă nici o valoare adică să fie nulă. În Swift dacă se dorește ca o variabila să fie opțională trebuie să se pună semnul întrebării (?) după tipul variabilei. De exemplu: 19 https://developer.apple.com/swift/ var x: Int? = nil var y: Int = 17
18 În exemplul mai sus menționat variabila x este de tipul întreg opțional, iar cea de-a doua este de tipul întreg și obligatoriu trebuie să aibă o valoare atribuită. Swift afișează tipul variabilei împachetat în loc să folosească tot numele, adică în loc de Optional<Int> afișează Int?, însă ambele sunt același lucru. Opționalele nu sunt altceva decât o enumerație cu doua cazuri. Optional.none este echivalentă cu nil și Optional.some (împachetată) înmagazinează o valoare împachetată. Deci: Valoare unei variabile opționale trebuie întotdeauna despachetată înainte de a putea fi utilizată. Pentru acest lucru se folosește semnul exclamării. De exemplu:
Figure 6 – nu se poate utiliza o variabila nedespachetată.
var formaScurta: Int? = 21 var formaLunga: Optional<Int> = 21 //ambele sunt acelasi lucru var a: Int? = nil var a = Optional<Int>.None //ambele sunt acelasi lucru let b: String? = "Hello world" let b = Optional<String>.Some("Hello world")
19 Figure 7 – variabila despachetată se poate utiliza 3.2.2 Optional Binding (atribuirea opționalelor) Pentru a putea atribui o opțională unei variabile neopționale putem folosii una din metodele: if let, guard let sau switch.
Figure 8 – if let exemplu
20 Optional Binding se folosește când nu se știe cu sigurantă dacă o variabilă opțională are o valoare și se dorește atribuirea acesteia unei alteia neopțională. Deoarece aceasta întâi verifică dacă opționala are o valoare, după care se execută atribuirea în cazul pozitiv, iar în caz contrar atribuirea nu se executa și astfel evitam ca programul să dea crash. [9] 3.3 SpriteKit SpriteKit20 este un framework creat de Apple, pentru a ajuta la dezvoltarea de jocuri 2D pentru platformele Apple, astfel încât să fie eficiente din punct de vedere al energiei consumate în timp ce livrează performanta înaltă. Precum orice framework de jocuri, SpriteKit asigură un motor de randat al texturilor grafice, a fizicii, coliziunilor, sunetului, etc. Ce este afișat pe ecran este desenat de obiectul SKScene. Toate animațiile sunt randate de un obiect al SpriteKit, numit SKView. O scena SKScene conține elemente grafice, animații, sunete, etc. SKScene este folositor deoarece, în jocurile video poate fi nevoie de mai multe scene, o scena poate fi meniul principal, alta scenă poate fi cea în care se desfășoară acțiunea, etc. Astfel se poate folosi doar un obiect SKView în care se face comutarea intre scene. Totul în SpriteKit se bazează pe noduri, astfel scena este creata din mai multe noduri sub forma unui arbore, cu nodul SKScene fiind rădăcina. Scena și ordinea descendenților determină ordinea în care conținutul este desenat pe ecran. Toate nodurile au niște coordonate specifice în funcție de nodul părinte. Toate modificările făcute asupra unui nod părinte se vor efectua și pe copii acestuia. De exemplu daca redimensionam un nod, automat redimensionam și toți copii acestuia. 3.3.1 Texture Atlas Texturile sunt reprezentate în SpriteKit ca obiecte SKTexture, texturile sunt folosite când avem nevoie să folosim aceeași imagine în mai multe locuri. Un atlas de texturi este o colecție de 20 https://developer.apple.com/spritekit/
21 texturi care sunt folosite împreună. De exemplu se dorește crearea unei mașini care este compusă din mai multe componente: roți, arcuri, caroserie, etc. În această situație se poate crea un atlas cu toate aceste texturi, iar făcând acest lucru se folosește mai putină memorie și astfel se poate îmbunătății performanța. 3.3.2 Fizica Chiar daca se poate modifica individual poziția fiecărui nod din scena, nu puține sunt situațiile când se dorește ca nodurile să interacționeze intre ele și cu alte forte din exterior, precum gravitația, fricțiunea și altele. Toate acestea pot fi realizate mult mai ușor fiind folosit motorul fizic implementat în SpriteKit. Pentru realizarea acestui lucru trebuie create corpuri fizice care mai apoi trebuie atașate nodurilor din scena noastră. Motorul fizic permite ajustarea oricărei caracteristici a corpului fizic, astfel încât interacțiunea să fie cat mai reală. Se pot defini proprietăți precum masa, densitatea, coeficientul de fricțiune, suprafața, forma și alte însușiri fizice ale corpului. Se poate configura chiar și accelerația gravitațională a lumii în care se execută simularea sau chiar să se aplice individual forțe exterioare pe corpurile fizice, astfel fiind posibilă modificarea vitezei sau direcției de deplasare. Se pot alege ce corpuri fizice să fie afectate de aceste acțiuni sau care corpuri se pot atinge intre ele. Pentru simulări mai complexe sunt situații când trebuie conectate două corpuri sau mai multe intre ele, motorul fizic din SpriteKit permițând realizarea acestui lucru cu ușurință și chiar să se decidă cum să fie conectate intre ele, de exemplu: • printr-un arc folosindu-se SKPhysicsJointSpring. • să fie fix legate între ele folosindu-se SKPhysicsJointFixed. • se poate seta distanta maximă la care se pot depărta doua corpuri unul de altul, exact cum ar fi conectate cu o sfoara folosind SKPhysicsJointLimit. • se poate stabili direcția pe care cele doua corpuri se pot deplasa folosind SKPhysicsJointSliding. • pot fi legate printr-un bolț, într-un punct care le permite rotirea individuală corpurilor folosindu-se SKPhysicsJointPin. [10]
22 Figure 9 – Tip legături corpuri fizice 3.3.3 Scene Editor SpriteKit are integrat un editor de nivel. Rolul acestuia este de a crea nivele mult mai rapid fără nevoia de a implementa totul din cod. Scene Editor (Figure 10) este un editor de tipul drag and drop. Orice obiect poate fi tras în scena, după care i se pot seta toate caracteristicile sale fizice. [11]
23 Figure 10 – Scene Editor 3.4 Adobe Photoshop Adobe Photoshop este un program de prelucrare a imaginilor, program dezvoltat de către compania Adobe Systems. Adobe Photoshop este un program care rulează atât pe sistemul de operare Mac OS X cât și Microsoft Windows, prima versiune a sa fiind lansată la începutul anului 1990. Principalul motiv pentru care Photoshop este clasat peste alte programe de editare a imaginilor este complexitatea sa. [12]
24 4 Prezentarea aplicației 4.1 Descriere Mountain Hill Racing este un joc de curse care se desfășoară pe munte după cum sugerează chiar titlul acestuia, dar acest joc nu se vrea doar un simplu joc de curse, ci unul care combină distracția oferită de acest gen împreună cu genul simulator, dorind ca experiența jucătorului să fie cat se poate de plăcută. Toate aceste lucruri fiind posibile datorită tehnologiilor prezentate mai sus. La baza jocului se află motorul SpriteKit, făcând posibile toate aceste simulările fizice, luând în calcul toate elementele care pot să intervină și în lumea reala, precum gravitația, forța de frecare, greutatea și densitatea corpurilor fizice. Toate acestea combinate livrând o experiență unica. După cum s-a precizat, deoarece jocul este destinat platformei mobile iOS, s-a dorit crearea un joc care să fie relaxant și să poată fi jucat în aproape orice situate, de aceea s-a decis implementarea unui control intuitiv, care devine natural după doar câteva minute de la primul contact. 4.2 Gameplay Gameplay-ul jocului se realizează utilizând numai doua degete, unul folosit pentru accelerarea mașinii, iar celălalt pentru frânare. Accelerarea realizându-se apăsând în partea dreapta a ecranului sau mai precis înaintea mașinii (Figure 11 – zona roșie) și frânarea apăsând în partea stângă a ecranului sau în spatele mașinii (Figure 12 – zona roșie). După frânare, adică după ce mașina s-a oprit din mișcare dacă încă menținem apăsat butonul, mașina va începe să se deplaseze în direcția opusă deplasării inițiale adică dacă mașina se deplasa pe direcția înainte, în dreapta scenei și apăsăm în stânga ecranului mașina va începe să frâneze, iar după oprire aceasta va începe să se deplaseze pe direcția înapoi. Aceeași logică aplicându-se și pentru direcția opusă.
25 Figure 11 – Accelerare – zona roșie.
Figure 12 – Frânare -zona roșie. Datorită fizicii jocului foarte reale la accelerări sau frânări mai agresive, mașina își distribuie înainte sau înapoi centrul de greutate având tendința de a se răsturnă, mai ales când mașina este pe o pantă mai abruptă. Aspectul acesta face jocul unul interesant. Dar totuși această fizică foarte apropiată de cea din lumea reală în multe situații face dificilă deplasarea pe un teren atât de abrupt și accidentat. Deoarece mașina la viteze mai mari poate să se desprindă de la sol, astfel fiind necesar un control asupra inclinația mașinii când aceasta se află în aer. Astfel a fost căutată o soluție ce permite acest lucru fără a complica controlul jocului. Fiind un joc ocazional trebuie păstrat un control cât mai minimalist. De aceea ideea de a face acest lucru cu ajutorul accelerometrului nu este o soluție, accelerometrul reprezentat un impediment în utilizarea jocului în timpul deplasării cu un mijloc de transport(mașină, tren, avion). De aceea s-a implementat controlul înclinației mașinii în timp ce aceasta se află în aer fără a necesita mutarea în vre-un fel a poziției degetelor pe ecran. Astfel totul pare foarte natural, jucătorul începând să facă acest lucru aproape inconștient după câteva minute de acomodare. Mai exact la apăsarea în partea dreapta a ecranului mașina începe să se rotească invers acelor de ceasornic, adică exact cum
26 se comporta și pe pământ în timpul accelerării datorită distribuirii greutăți pe puntea spate, iar când apăsăm în partea stângă mașina se rotește în sensul acelor de ceasornic. 4.3 Modul de implementare Implementarea jocului a fost făcută cu ajutorul tehnologiilor prezentate în capitolul anterior, mediul de dezvoltare integrat Xcode, se poate procura foarte ușor pe macOS, din marketul disponibil, pentru instalarea sa fiind nevoie doar de un click pe butonul "Install", aceștia fiind toți pași necesari pentru a ne bucura de acest mediu de dezvoltare care are deja integrat framework-ul SpriteKit și compilatorul pentru limbajul de programare Swift. 4.3.1 Crearea unui nou proiect Pentru crearea unui nou proiect (joc) pentru platforma mobila iOS folosind SpriteKit cu limbajul de programare Swift sunt necesare doar câteva click-uri in mediul de dezvoltare integrat Xcode: 1. Create a new Xcode project. (Figure 13)
Figure 13 – Pagina de pornire a mediului de dezvoltare integrat Xcode.
27 2. În stânga sus se selectează tipul de șablon dorit, în acest caz fiind iOS. (Figure 14) 3. Se selectează tipul aplicației ce urmează dezvoltată, acesta fiind Game după care se apasă pe butonul Next. (Figure 14)
Figure 14 – Selectarea șablonului și tipului de aplicație dorit. 4. Se completează numele aplicației, se aleg limbajul de programare și framework-ul dorit. Apoi se apasă din nou butonul Next.
Figure 15 – Configurarea opțiunilor noului proiect.
28 4.3.2 Descrierea funcționalității După crearea proiectului toate fișierele necesare pentru un joc video sunt create. Cel mai important fiind GameScene.swift. Aceasta este scena creata automat odată cu crearea proiectului. Este importantă deoarece din această clasa avem acces la metoda didMove(to:), aceasta fiind metoda apelata imediat după ce scena este prezentată în view (porțiunea de scena ce este vizibilă pe ecran). [13] Toate nodurile scenei o să fie adăugate în interiorul clasei GameScene, iar cele folosite la inițializare o să fie adăugate în interiorul metodei didMove(to:). Mașina din acest joc a fost creată într-o clasa separată, numită CarClass.swift, pentru a tine totul cât mai bine organizat. Deoarece se dorește un joc care să poată fi scalat cat mai repede odată cu introducerea în market, dorim să avem un control cat mai complex asupra anumitor caracteristici, de aceea constructorul acestei clase primește ca parametru un CGFloat prin care se specifică înălțimea suspensiei mașinii ce urmează a fi creată. Un CGFloat nu este altceva decât un Float regulat pe sistemele de 32 biți și un Double în cele pe 64 biți. În această clasă sunt declarate toate componentele necesare mașinii. Aceste componente sunt declarate sub forma de constante, deoarece valorile/proprietățile acestora nu se vor schimba pe parcursul jocului. De exemplu: În secvența de cod de mai sus sunt declarate roțile și caroseria mașinii, acestea fiind niște noduri peste care s-a aplicat câte o imagine. //Nodul ce conține imaginea caroseriei let carBodyFrame = SKSpriteNode(imageNamed: "carFrame.png") //Nodul ce conține imaginea roții de pe puntea față let wheelFront = SKSpriteNode(imageNamed: "wheel1.png") //Nodul ce conține imaginea roții de pe puntea spate let wheelRear = SKSpriteNode(imageNamed: "wheel1.png")
29 După declararea acestora este constructorul/inițializatorul clasei. Aici se va seta poziția inițială a mașinii și se vor atribui corpuri fizice fiecărui nod, ca mai apoi să poată fi simulată fizica asupra lor. Pentru fiecare nod avem mai multe opțiuni când alegem să atribuim corpul fizic: acesta poate fi dinamic sau nu, inițial toate corpurile fizice create sunt dinamice. Daca nu sunt dinamice, forte exterioare nu pot acționa asupra lor mutându-le din poziția inițială. Forte precum gravitația sau forte exercitate de un alt corp precum în urma unui impact, acestea rămânând nemișcate în cazul în care nu sunt dinamice. SpriteKit atribuie o masa fiecărui corp în funcție de suprafața sa. Deci cu cat corpul fizic este mai mare, este și mai greu. Dar aceste proprietăți se pot modifica și individual în caz că dorim ca un corp să fie mai dens decât altul. Un corp fizic atribuit unui nod poate avea mai multe forme: 1. rotund, acesta este cea mai eficienta forma în calcularea coliziunilor 2. dreptunghiulara 3. forma personalizata, creează un contur din mai multe puncte 4. sau poate lua forma imaginii aplicate pe nod. [14]
Figure 16 – exemple forme corpuri fizice. Ultima este cea mai precisa în cazul coliziunilor dar și cea mai costisitoare cu resursele de procesare. Astfel în cazul caroseriei mașinii, cea mai buna opțiune este cea personalizata deoarece este suficient de precisa pentru coliziunile necesare, astfel se salvează resurse importante de calcul, deci prin urmare înseamnă mai putina energie consumata pentru a menține un număr constant de 60 de cadre pe secunda, necesar pentru o experiență de gaming plăcută.
30 Pentru crearea corpului de forma personalizata mai întâi trebuie creata traiectoria din puncte, un path, iar apoi atribuim corpul fizic nodului ce reprezintă caroseria mașinii. Pentru roti evident cel mai indicat este să cream un corp de forma rotunda. 4.3.3 Conectarea corpurilor fizice După ce fiecare corp fizic este creat, acestea trebuie conectate intre ele astfel încât împreună să se comporte precum o mașină. Procesul de conectare al roti de caroseria mașinii astfel încât aceste doua corpuri să interacționeze intre ele ca și cum ar fi legate printr-un arc este puțin mai complex decât pare la prima vedere. Roata și caroseria nu pot fi conectate doar cu un arc, deoarece în acest caz roata nu s-ar deplasa fata de caroserie doar perpendicular, pe axa Y, ci s-ar deplasa și pe axa X, prin urmare este nevoie și de un slider (un SKPhysicsJointSliding – astfel încât roata și caroseria sa se deplaseze doar pe o axa unul fata de celălalt). Dar odată adăugate aceste 2 legături apare o alta problema, mai exact corpurile nu se pot roti în jurul punctului de ancorare (fiecare obiect creat are un punct de ancorare, în mod implicit acesta este exact în centrul obiectului). Acest lucru se datorează legăturii de tip sliding, deoarece nu permite obiectelor să se rotească, ci decât să se apropie sau să se depărteze unul de altul. O soluție a acestei probleme este crearea celui de-al treilea obiect și legăturile să se facă în felul următor: let path = CGMutablePath() path.addLines(between: [CGPoint(x: __, y: __), CGPoint(x: __, y: __), …………………, CGPoint(x: __, y: __)]) path.closeSubpath() carBodyFrame.physicsBody = SKPhysicsBody(polygonFrom: path) wheelFront.physicsBody = SKPhysicsBody(circleOfRadius: __) wheelRear.physicsBody = SKPhysicsBody(circleOfRadius: __)
31 • se creează un arc intre caroserie și cel de-al treilea obiect sau roata • se creează o legătura sliding intre caroserie și cel de-al treilea obiect • se leagă printr-un bolț (SKPhysicsJointPin) roata și cel de-al treilea obiect. Observație: • cel de-al treilea obiect trebuie să fie de dimensiuni mai mici decât roata, în caz contrar, roata nu va face contact cu alte obiecte, acestea intrând în contact cel de-al treilea obiect și se vor opri la el. Exemplu cod pentru crearea acestei legături: carBodyFrame = obiectul fizic atașat nodului corespunzător caroseriei pinRear = cel de-al treilea obiect fizic wheelRear = obiectul fizic atașat nodului corespunzător rotii din spate 4.3.4 Crearea terenului Cu toate că în capitolul anterior a fost prezentat Scene Editor și rolul sau în crearea de nivele mult mai ușor, datorită interfeței drag and drop. în cazul creării terenului nu este o soluție practică, //Legătura sliding intre caroserie și cel de-al treilea obiect let slideRear = SKPhysicsJointSliding.joint(withBodyA: myCar.carBodyFrame.physicsBody!, bodyB: myCar.pinRear.physicsBody!, anchor: myCar.pinRear.position, axis: CGVector(dx: 0, dy: 1)) //Legătura de tip arc intre caroserie și roata din spate let springRear = SKPhysicsJointSpring.joint(withBodyA: myCar.carBodyFrame.physicsBody!, bodyB: myCar.wheelRear.physicsBody!, anchorA: myCar.wheelRear.position, anchorB: myCar.wheelRear.position) //Legătura cu un bolț intre roata și cel de-al treilea obiect let pinRearWheel = SKPhysicsJointPin.joint(withBodyA: myCar.pinRear.physicsBody!, bodyB: myCar.wheelRear.physicsBody!, anchor: myCar.pinRear.position)
32 deoarece terenul pe care mașina se deplasează trebuie să fie de forma neregulata fără a avea porțiuni de teren care formează unghiuri drepte. Terenul trebuie să fie precum o linie curba, iar Scene Editor permite crearea de nivele cu obiecte poziționate exact peste o placa din grilaj. Acest lucru nefiind practic pentru acest tip de aplicare. O soluție foarte simpla și eficienta este crearea unei linii cu ajutorul SKShapeNode. Aceasta creând linia, trecând prin punctele specificate și în același timp rotunjind linia folosindu-se de metoda Bézier21. După crearea liniei putem să îi setam diferite proprietăți precum grosimea liniei, textura aplicata peste aceasta și altele. Aceasta este o soluție foarte buna deoarece permite crearea cu ușurință a nivelelor, acestea putând fi salvate sub forma unor vectori de puncte. Fiecare porțiune de teren este generata din mai multe astfel de straturi paralele unul sub altul, din ce în ce mai deschise la culoare, pentru a crea impresia de adâncime (Figure 17).
Figure 17 – Straturi teren. 21 https://en.wikipedia.org/wiki/Bézier_curve
//groundXY este un vector cu mai multe seturi de puncte. //in acest caz linia este creata folosind primul set de puncte. let splineShapeNode = SKShapeNode(splinePoints: &groundXY[0], count: groundXY[0].count)
33 Fiecare strat în parte este un nod al scenei, de aceea trebuie eliminate odată ce nu mai este nevoie de ele în scena, adică când s-a trecut de acea porțiune de teren. Daca acest lucru nu se realizează o să afecteze performata, deoarece memoria va începe să se umple. 4.3.5 Deplasarea mașinii și camera Pentru a deplasa mașina este nevoie ca o forță să acționeze asupra acesteia, mai exact asupra roților, deoarece este o mașină de teren tracțiunea acesteia va fi integrală, deci se vor aplica forte de rotație asupra ambelor roți. După cum s-a zis în subcapitolul anterior "Gameplay", mașina se va deplasa înainte la apăsarea în partea dreapta și invers la apăsarea în partea stângă a ecranului. Pentru a realiza acest lucru mai întâi trebuie detectata locația unde este atins ecranul și apoi cat timp este menținut contactul cu ecranul. Trebuie știut cat timp ecranul este atins deoarece se dorește aplicarea de forte asupra roților doar cat timp jucătorul accelerează/frânează, în rest mașina deplasându-se datorită inerției( dacă aceasta exista) sau altor forțe exterioare, precum gravitația. Pentru a realiza acest lucru, framework-ul SpriteKit are disponibile funcții gata implementate precum touchesBegan()22, touchesMoved()23, touchesEnded()24 și update()25. Funcția touchesBegan() este apelata automat când se atinge ecranul, funcția touchesMoved() este apelată cat timp locația de atingere a ecranului se modifica, funcția touchesEnded() este apelată când ecranul nu mai este atins iar funcția update() este apelată la fiecare cadru al jocului. Pentru a determina cat timp ecranul este atins cel mai simplu este să se folosească o variabila de tip boolean care este inițializată cu valoarea false. în funcția touchesBegan() se setează cu true, iar în funcția touchesEnded() aceasta revine înapoi la valoare false. Însă pentru a decide daca jucătorul dorește să accelereze sau să frâneze, la fiecare atingere a ecranului trebuie să se decidă daca poziția 22 https://developer.apple.com/documentation/uikit/uiresponder/1621142-touchesbegan 23 https://developer.apple.com/documentation/uikit/uiresponder/1621107-touchesmoved 24 https://developer.apple.com/documentation/uikit/uiresponder/1621084-touchesended 25 https://developer.apple.com/documentation/spritekit/skscene/1519802-updatea
34 atingerii este înainte sau după mașina, și din nou se va folosi o alta variabila de tip boolean care va deveni true în cazul în care se atinge înaintea mașinii, și false în caz contrar. Apoi în funcția update(), daca ecranul este atins, se va determina direcția de deplasare cu ajutorul variabilei setata la verificarea poziției atingerii ecranului fată de poziția mașinii. Pentru a aplica cuplu unei roți se folosește funcția applyTorque()26 asupra corpului fizic aplicat peste nodul rotii. Se recomanda utilizarea unui cuplu mai mare pentru roata spate în cazul deplasării înainte și un cuplu mai mare pentru roata fata în cazul deplasării înapoi, datorită distribuirii de greutate. Daca nu se tine cont de acest lucru și se aplica un cuplu egal pe ambele punți atunci una dintre punți nu va avea suficienta greutate și roata corespunzătoare va derapa, neavând suficienta aderenta. Deoarece mașina se va deplasa în jurul scenei avem nevoie și de o camera care să facă acest lucru, altfel mașina va ieși în afara câmpului vizual. Pentru a crea o camera se declara o variabila de tip SKCameraNode()27. Nodul se adaugă în scena după care poziția acestuia se va modifica în funcția update() în funcție de poziția mașinii. 4.3.6 Controlul în timpul săriturilor și testarea coliziunilor Pentru a putea controla înclinația mașinii în timp ce aceasta se află în aer, mai întâi trebuie să știm dacă mașina atinge sau nu pământul. Acest lucru se poate realiza verificând daca are loc o coliziune între o componenta a mașinii și pământ. Această verificare se poate face relativ ușor cu ajutorul funcțiilor didBegin()28 și didEnd()29. Funcția didBegin() este apelată automat când are loc o coliziune, iar funcția didEnd() este apelată când o coliziune este încheiată. Aceste funcții primesc ca parametru un obiect numit contact, acesta conține cele doua corpuri fizice între care are loc, respectiv se încheie coliziunea. Cele doua corpuri nu sunt transmise într-o anumită ordine. 26 https://developer.apple.com/documentation/spritekit/skphysicsbody/1519588-applytorque 27 https://developer.apple.com/documentation/spritekit/skcameranode 28 https://developer.apple.com/documentation/spritekit/skphysicscontactdelegate/1449595-didbegin 29 https://developer.apple.com/documentation/spritekit/skphysicscontactdelegate/1449599-didend
35 Fiecare corp fizic are următoarele proprietăți: • categoryBitMask30 • collisionBitMask31 • contactTestBitMask32 Proprietatea categoryBitMask este un număr de tip UInt32 care poate fi asignat unui corp fizic, în acest caz terenului și corpurilor ce compun mașina (caroserie și roți). Trebuie asignate categorii tuturor corpurilor asupra cărora se dorește verificarea de coliziuni. Proprietatea collisionBitMask este tot un număr de tip UInt32 care definește cu care dintre categoriile de corpuri se poate ciocni. Inițial acest număr este setat pentru toate corpurile fizice. Astfel toate corpurile interacționând între ele. Proprietatea contactTestBitMask este de asemenea un număr de tip UInt32 care definește categoriile de corpuri despre care vrem să fim informați când le lovim. [15] Deci daca în funcția didBegin() sunt trimiși ca parametrii categoria corespunzătoare mașinii și categoria corespunzătoare terenului înseamnă că are loc o coliziune între mașină și teren deci aceasta este pe pământ. Același lucru se face și în funcția didEnd() doar că în acest caz înseamnă că mașina nu mai este in contact cu terenul, prin urmare înseamnăse că aceasta se află în aer. Astfel se poate folosi o variabilă de tip boolean care este true când mașina este pe pământ și false în caz contrar. Această variabilă se verifică în funcția update() daca este falsă, iar dacă aceasta este falsă se apelează o funcție care va roti mașina, pe același principiu cum se rotesc roțile, aplicand cuplu asupra ei cu funcția applyTorque(), doar că se aplică un cuplu mult mai mic deoarece se dorește ca mașina să poată fi ajustată foarte puțin, suficient încât jucătorul să prevină o răsturnare a mașinii. 30 https://developer.apple.com/documentation/spritekit/skphysicsbody/1519869-categorybitmask 31 https://developer.apple.com/documentation/spritekit/skphysicsbody/1520003-collisionbitmask 32 https://developer.apple.com/documentation/spritekit/skphysicsbody/1519781-contacttestbitmask
36 //functia didBegin() – apelata automat la inceprea unei coliziuni func didBegin(_ contact: SKPhysicsContact) { let contactMask = contact.bodyA.categoryBitMask & contact.bodyB.categoryBitMask switch contactMask { case myCar.carCategory & groundCategory: isOnGround = true print("Masina este pe pamant") default: break } } //functia didEnd() – apelata automat la terminarea coliziunii func didEnd(_ contact: SKPhysicsContact) { let contactMask = contact.bodyA.categoryBitMask & contact.bodyB.categoryBitMask switch contactMask { case myCar.carCategory & groundCategory: isOnGround = false print("Masina este în saritura") default: break } }
37 5 Concluzii 5.1 Viitoare îmbunătățiri Momentan aplicația este într-un stadiu de prototip, însă pentru a putea fi pusă în magazinul Apple App Store trebuie să fie terminată. Versiunea terminată pentru magazin va conține: • Sunete – pentru motorul mașinii. – pentru coliziuni, acestea fiind diferite în funcție de materialele care intră în contact. • Mai multe vehicule și mult mai complexe din punct de vedere vizual. • Posibilitatea de upgrade a componentelor mașinii : – amortizoarelor. – roților. – motorului. • Adăugarea unui caracter care să reprezinte șoferul mașinilor, acesta la rândul său să poată fi customizat (diferite tipuri de persoane și o gamă de haine și accesori dedicate) • Crearea de nivele care să crească în dificultate odată cu înaintarea pe teren. • Crearea unui sistem de recompense: bănuți, combustibil, puncte (in funcție de distanța parcursă și timpul necesar pentru parcurgerea ei) – bănuții vor fi folosiți la cumpărarea de componente pentru mașină sau accesorii pentru șofer, iar punctele pentru deblocarea noilor nivele. • Diferite condiții meteo ale nivelelor, aceste condiții meteo o să afecteze aderența terenului. • Posibilitatea de a juca nivele atât pe timp de zi, cat și pe timp de noapte. • Crearea de efecte vizuale (fum scos în urma mașinii în timpul accelerării, aruncarea de pietre, apă, etc de la roți) • O îmbunătățire vizuală a nivelelor, acestea vor fi cat se poate de complexe din punct de vedere vizual, inclusiv decorul (cerul, norii, copacii, etc.)
38 • Va suporta curse intre mai mulți jucători (multiplayer), atât online, cat și offline cu posibilitatea de a concura contra timpului altor jucători sau chiar contra propriului timp. • Va fi complet funcțional, de exemplu nivelul se va opri automat când jucătorul termină combustibilul sau moare, răsturnându-se cu mașina. • Va conține un meniu complex, cu posibilitatea de a opri efectele sonore, de a edita caracterul, de a reseta sau schimba nivelul și un buton dedicat pentru închiderea jocului.
39 Bibliografie [1] Hill Climb Racing (video game), https://en.wikipedia.org/wiki/Hill_Climb_Racing_(video_game), 24.03.2018 [2] Felix Richter, Fragmentation Remains an Issue în the Android Universe, https://www.statista.com/chart/5930/adoption-of-ios-and-android-versions/, 12.04.2018 [3] iOS, https://en.wikipedia.org/wiki/IOS, 08.06.2018 [4] Video game, https://en.wikipedia.org/wiki/Video_game#Casual_games, 10.03.2018 [5] Jason Evangelho, The Asus ROG Phone, https://www.forbes.com/sites/jasonevangelho/2018/06/04/the-asus-rog-phone-embraces-mobile-gaming-boasts-best-specs-on-the-market/#46c6181754fd, 04.06.2018 [6] Kyle Orland, Mobile gaming cements its dominance, takes majority of worldwide sales , https://arstechnica.com/gaming/2018/05/mobile-platforms-now-account-for-more-than-half-of-all-game-spending/, 02.05.2018 [7] Xcode, https://en.wikipedia.org/wiki/Xcode, 16.06.2018 [8] Xcode IDE, https://developer.apple.com/xcode/ide, 23.06.2018 [9] About Swift, https://docs.swift.org/swift-book/, 20.06.2018 [10] Optional, https://developer.apple.com/documentation/swift/optional, 20.06.2018 [11] SpriteKit, https://developer.apple.com/documentation/spritekit, 20.06.2018 [12] Introduction to the SpriteKit Scene Editor, https://www.raywenderlich.com/158961/introduction-spritekit-scene-editor, 12.10.2017 [13] Adobe Photoshop, https://ro.wikipedia.org/wiki/Adobe_Photoshop, 10.12.2017 [14] didMove(to:), https://developer.apple.com/documentation/spritekit/skscene/1519607-didmove, 10.01.2018 [15] SKPhysicsBody, https://developer.apple.com/documentation/spritekit/skphysicsbody, 19.04.2018 [16] Loading a level: categoryBitMask, collisionBitMask, contactTestBitMask, https://www.hackingwithswift.com/read/26/2/loading-a-level-categorybitmask-collisionbitmask-contacttestbitmask, 15.06.2018
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Figure 1 – Versiuni software pe platformele iOS și Android 1 https:www.statista.com [624023] (ID: 624023)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
