{"id":9392,"date":"2012-08-27T13:17:52","date_gmt":"2012-08-27T11:17:52","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=9392"},"modified":"2012-08-27T13:17:52","modified_gmt":"2012-08-27T11:17:52","slug":"6-come-aggiungere-profondita-ai-nostri-videgiochi-in-2d","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/6-come-aggiungere-profondita-ai-nostri-videgiochi-in-2d\/","title":{"rendered":"6. Come aggiungere profondit\u00e0 ai nostri videgiochi in 2D"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/08\/corso-programmazione-videogame-cocos2d-06.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/08\/corso-programmazione-videogame-cocos2d-06.jpg\" alt=\"corso-programmazione-videogame-cocos2d-06\" title=\"corso-programmazione-videogame-cocos2d-06\" width=\"200\" height=\"100\" class=\"alignleft size-full wp-image-9402\" \/><\/a> Bentornati, dopo una piccola pausa estiva, al nostro <strong>corso di programmazione videogame per iPhone e iPad con cocos2d<\/strong>. Oggi vedremo un concetto che ci accompagner\u00e0 anche nella prossima lezione, parleremo infatti di come aggiungere una illusione di profondit\u00e0 ai nostri videgiochi in 2D.<\/p>\n<p>Se avete giocato almeno ad un platform 2D pi\u00f9 recente del primissimo Mario Bros, avrete sicuramente fatto caso che, nonostanze l&#8217;assenza di una terza dimensione, i programmatori riescono comunque a fornire un certo effetto di profondit\u00e0.<br \/>\nQuesto effetto viene ottenuto sfruttando un aspetto molto interessante e caratteristico della percezione visiva chiamato &#8220;parallasse&#8221;.<!--more--><\/p>\n<p><a href=\"http:\/\/it.wikipedia.org\/wiki\/Parallasse\" target=\"_blank\">Wikipedia<\/a> recita: &#8220;<em>La parallasse \u00e8 il fenomeno per cui un oggetto sembra spostarsi rispetto allo sfondo se si cambia il punto di osservazione.<\/em>&#8220;.<\/p>\n<p>Questo aspetto \u00e8 quello che permette al cervello di ricostruire le informazioni sulla profondit\u00e0 da un&#8217;immagine che altrimenti sarebbe solo 2d. Poich\u00e9 tra i due occhi c&#8217;\u00e8 una certa distanza \u00e8 come se cambiasse il &#8220;punto di osservazione&#8221; quindi nell&#8217;immagine recepita dai due occhi gli oggetti &#8220;cambiano&#8221; leggermente posizione rispetto allo sfondo. Questa differenza viene rapidamente calcolata dal nostro cervello e l&#8217;informazione viene utilizzata per ricavare i dati sulla profondit\u00e0.<\/p>\n<p>Questo fenomeno \u00e8 chiaramente visibile ad occhio nudo su breve distanza, basta chiudere alternativamente gli occhi e fissare un oggetto vicino, ma \u00e8 valido anche su scala astronomica, infatti la distanza tra la terra e i pianeti viene stimata effettuando due misurazioni in tempi diversi. Se la terra si trova in posizione diversa l&#8217;immagine che si ottiene \u00e8 diversa e quindi si pu\u00f2 calcolare la distanza.<\/p>\n<p>Ok, dopo questa breve incursione del mondo della fisica torniamo al nostro corso per ripondere alla domanda che sicuramente vi starete ponendo: &#8220;Ok, bello ma io con cocos che cosa me ne faccio della parallasse?&#8221;.<\/p>\n<p>Beh noi sfruttiamo il concetto inverso, se \u00e8 vero che l&#8217;oggetto sembra spostarsi cambiando punto di osservazione, \u00e8 vero anche il contrario, infatti noi faremo veramente spostare gli oggetti della nostra scena per simulare un cambio di punto d&#8217;osservazione. Semplice, no?<\/p>\n<p>Facciamo un esempio pi\u00f9 chiaro, immaginate di essere su un treno in corsa e guardare fuori dal finestrino, cosa vedete? Vetrete probabilmente le forme indistinte dei cespugli che scorrono velocissme, mentre sullo sfondo un paesaggio che scorre lento e, ancora pi\u00f9 lontano, delle montagne che sembrano immobili. Oggi tenteremo di ricostruire questo effetto con le sprite e le classi cocos2d.<\/p>\n<p>Facciamo i nostri esperimenti con la parallasse creando un nuovo progetto cocos2d, nell&#8217;immagine qui in basso potete vedere quello che andremo a realizzare:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/08\/come-aggiungere-profondita-giochi-corso-cocos2d-01.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/08\/come-aggiungere-profondita-giochi-corso-cocos2d-01.png\" alt=\"come-aggiungere-profondita-giochi-corso-cocos2d-01\" title=\"come-aggiungere-profondita-giochi-corso-cocos2d-01\" width=\"550\" height=\"275\" class=\"aligncenter size-full wp-image-9399\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/08\/come-aggiungere-profondita-giochi-corso-cocos2d-01.png 961w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/08\/come-aggiungere-profondita-giochi-corso-cocos2d-01-300x150.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Sono evidenti in questa immagine i 4 livelli:<\/p>\n<ul>\n<li>il primo piano verde scruro<\/li>\n<li>il secondo piano verde chiaro<\/li>\n<li>lo sfondo con le montagne innevate<\/li>\n<li>il cielo con le nuvole<\/li>\n<\/ul>\n<p>Ci serviranno le immagini, ma prima di darvi il link per il download ragioniamo un attimo e facciamo un paio di conti.<\/p>\n<p>In questo esempio non faremo un vero e proprio scroll continuo, ma simuleremo la profondit\u00e0 muovendo gli oggetti sullo schermo a diversa velocit\u00e0.<br \/>\nCi serviranno quindi delle immagini pi\u00f9 grandi dello schermo, cos\u00ec da porterle muovere avanti e indietro senza problemi, ma pi\u00f9 grandi di quanto? Non \u00e8 necessario che siano tutte della stessa dimensione!<\/p>\n<p>Partiamo dal livello in primissimo piano, per visualizzare bene l&#8217;aminazione ci sposteremo verso destra di 160 punti, quindi ci servir\u00e0 avere un&#8217;immagine lunga 480 + 160 punti = 640 punti. Tradotto in pixel significa 640 pixel per iphone non retina e 1280 per iphone con il retina display.<\/p>\n<p>Ricordo che io utilizzo il simulatore in modalit\u00e0 &#8220;non retina&#8221; perch\u00e9 altrimenti avrei difficolt\u00e0 a postare gli screenshot, ma ricordate per i vostri progetti di aggiungere anche le immagini con il suffisso &#8220;-hd&#8221;.<\/p>\n<p>Per quanto riguarda i livelli successivi bisogna calcolare quanto sar\u00e0 il loro spostamento quando il primo piano si sposter\u00e0 di 160punti&#8230; la regola \u00e8 che pi\u00f9 il valore tende a zero e pi\u00f9 sembrer\u00e0 lontano e distante.<\/p>\n<p>Facendo alcune prove decidiamo di spostare il livello secondario dell&#8217;80% rispetto al primo piano, mentre il livello con le montagne lo spostiamo del 40%, fanno rispettivamente 128 e 64 pixel.<\/p>\n<p>Per il restante livello, quello con le nuvole, potremmo decidere di lasciarlo completamente fermo, ma per ottenere un effetto pi\u00f9 carino lo spostiamo di un 10%, ovvero 16 pixel.<\/p>\n<p>In questo modo otteniamo le seguenti misure:<\/p>\n<ul>\n<li>Primo piano: 640px<\/li>\n<li>Secondo piano 608px<\/li>\n<li>Montagne: 544 px<\/li>\n<li>Cielo: 496px<\/li>\n<\/ul>\n<p>Trovate le immagini dentro il progetto che potete scaricare seguendo link a fondo lezione.<\/p>\n<p>Quello che faremo sar\u00e0 quindi incorporare le immagini adatte e poi aggiungere nel nostro progetto di copia un&#8217;istanza della classe CCParallaxNode.<\/p>\n<p>Il codice che ci permette di ottenere questo risultato \u00e8 il seguente:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n-(id) init\r\n{\r\n        \/\/ always call \"super\" init\r\n        \/\/ Apple recommends to re-assign \"self\" with the \"super\" return value\r\n        if( (self=[super init])) {\r\n        \/\/ ask director the the window size\r\n                CGSize size = [[CCDirector sharedDirector] winSize];\r\n       \r\n        CCSprite *lev0 = [CCSprite spriteWithFile:@\"liv_0.png\"]; \/\/1\r\n        CCSprite *lev1 = [CCSprite spriteWithFile:@\"liv_1.png\"]; \/\/2\r\n        CCSprite *lev2 = [CCSprite spriteWithFile:@\"liv_2.png\"]; \/\/3\r\n        CCSprite *lev3 = [CCSprite spriteWithFile:@\"liv_3.png\"]; \/\/4\r\n               \r\n        lev0.anchorPoint = CGPointMake(0, 0); \/\/5\r\n        lev1.anchorPoint = CGPointMake(0, 0); \/\/6\r\n        lev2.anchorPoint = CGPointMake(0, 0); \/\/7\r\n        lev3.anchorPoint = CGPointMake(0, 0); \/\/8\r\n       \r\n        CCParallaxNode *paraNode  = [CCParallaxNode node]; \/\/9\r\n        [paraNode addChild:lev0 z:0 parallaxRatio:CGPointMake(0.1f, 0)positionOffset:CGPointMake(0, 0)]; \/\/10\r\n       \r\n        [paraNode addChild:lev1 z:1 parallaxRatio:CGPointMake(0.2f, 0)positionOffset:CGPointMake(0, 60)]; \/\/11\r\n                [paraNode addChild:lev2 z:2 parallaxRatio:CGPointMake(0.4f, 0) positionOffset:CGPointMake(0., 45)];   \/\/12    \r\n        [paraNode addChild:lev3 z:3 parallaxRatio:CGPointMake(1, 0) positionOffset:CGPointMake(0, -20)];   \/\/13\r\n       \r\n        [self addChild:paraNode z:0 tag:0001]; \/\/14\r\nCCMoveBy *move1 = [CCMoveBy actionWithDuration:2 position:CGPointMake(-160, 0)]; \/\/15\r\nCCMoveBy *move2 = [CCMoveBy actionWithDuration:2 position:CGPointMake(160, 0)];  \/\/16\r\n       \r\nCCSequence *pingpong = [CCSequence actions:move1,move2, nil]; \/\/17\r\nCCRepeatForever *repeatPingpong = [CCRepeatForever actionWithAction:pingpong]; \/\/18\r\n[paraNode runAction:repeatPingpong]; \/\/19\r\n        }\r\n        return self;\r\n}\r\n<\/pre>\n<p>Vediamo in dettaglio cosa fa.<\/p>\n<p>#1-4 Creo le 4 sprite utilizzando quattro immagini separate, vale qui lo stesso ragionamento che abbiamo fatto per gli sprite sheet. Il livello 0 \u00e8 costituito dalle nuvole, il livello 4 dalle montagne in primo piano.<\/p>\n<p>#5-8 Imposto l&#8217;anchorPoint della sprite nell&#8217;angolo in basso a sinistra. Non \u00e8 un passo necessario, ma ci semplificher\u00e0 i calcoli successivi<\/p>\n<p>#9 Alloco un nodo di tipo CCPalarallaxNode, questo speciale oggetto  \u00e8 quello che automaticamente calcoler\u00e0 lo spostamento delle 4 sprite.<\/p>\n<p>#10-13 Aggiungo al CCPalarallaxNode le sprite che avevo creato, per ciascuna sprite possiamo impostare la sua percentuale di spostamento attraverso la propriet\u00e0 parallaxRatio.<br \/>\nAd esempio parallaxRatio:CGPointMake(0.1f, 0) vuol dire che seguir\u00e0 gli spostamenti lungo l&#8217;asse X del 10%, mentre ventuali spostamenti lungo l&#8217;asse Y verranno ignorati.<br \/>\nIl secondo parametro positionOffset, specifica invece l&#8217;offset da assegnare alle singole sprite, come potete vedere io ho assegnato un offset verticale per far s\u00ec che si possano vedere tutte le sprite.<\/p>\n<p>#14 Aggiungo il CCPalarallaxNode alla scena corrente.<\/p>\n<p>#15 &#8211; 16 Creo due azioni, per muovere il livello.<\/p>\n<p>#17 Inserisco le due azioni all&#8217;interno di una CCSequence<\/p>\n<p>#18 Creo una CCRepeatForver utilizzando la sequenza appena creata<\/p>\n<p>#19 Eseguo l&#8217;azione. \u00c8 importante notare che noi muoviamo l&#8217;intero CCPalarallaxNode e lui si occupa di muovere tutte le sprite al suo interno in funzione del parallaxRatio che abbiamo impostato.<\/p>\n<p>In questo modo siamo riusciti ad ottenere con molta semplicit\u00e0 un effetto di simulazione tridimensionale.<\/p>\n<p>Potete scaricare l&#8217;intero progetto da <a href=\"https:\/\/github.com\/ignazioc\/Cocos2d.Lesson60-ParallaxExample\" target=\"_blank\">qui<\/a>: <\/p>\n<p>Ed ecco il video in cui potrete vedere il risultato finale:<\/p>\n<p><center><br \/>\n<iframe loading=\"lazy\" width=\"480\" height=\"360\" src=\"http:\/\/www.youtube.com\/embed\/1olB2ji4UkY?rel=0\" frameborder=\"0\" allowfullscreen><\/iframe><br \/>\n<\/center>    <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bentornati, dopo una piccola pausa estiva, al nostro corso di programmazione videogame per iPhone e iPad con&#8230;<\/p>\n","protected":false},"author":53,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1119],"tags":[1145,1175,1121,1174,1173],"class_list":["post-9392","post","type-post","status-publish","format-standard","hentry","category-corso-programmazione-videogiochi","tag-ccnode-cocos2d","tag-come-creare-giochi-iphone","tag-corso-cocos2d","tag-profondita-cocos2d","tag-profondita-videogame-2d"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/9392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=9392"}],"version-history":[{"count":14,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/9392\/revisions"}],"predecessor-version":[{"id":9408,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/9392\/revisions\/9408"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=9392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=9392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=9392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}