Daniel Schuller och jag bildade Bigyama 2012, efter att ha arbetat på många titlar som Magic The Gathering: Duel of the Planeswalkers och Star Wars: Battlefront. Företaget startade med en olyckad hoppa i PlayStation Home och ett besök i Skottland innan vi återvände till Nottingham och fokuserade på våra kärntalenter: programmering och bra spel! Vårt första steg var att leverera de tekniska kakorna för att hjälpa Fallen Tree Games ta med Quell Memento till PlayStation Vita.
Denna artikel diskuterar hur vi på Bigyama porterade Quell Memento till Vita. Om du vill veta mer om designen av Quell, kolla in Fallen Trees artikel, The Making of Quell.
Memento är det tredje spelet i Quell-serien; De tidigare spelen hade gjort mycket bra på mobilen och jag hade känt Joe och Lewis vid FTG under en tid, med att ha arbetat med dem på Free Radical Design före dess avlivning. Det var jättebra att få chansen att arbeta med dem igen och ha chansen att arbeta på en ny plattform.
Någon gång tillbaka hade jag träffat laget från Honeyslug, utvecklare av den framgångsrika PSP Mini Kahoots som sedan fortsatte med att utveckla Vita-lanseringen titeln Frobisher Says. De sätter oss i kontakt med utvecklarrelationerna på SCEE (Sony Computer Entertainment Europe).
Vi gick till SCEE-studion i London och diskuterade alternativen - PSP Mini, PlayStation Mobile eller PlayStation Vita - var och en ger utvecklare tillgång till Vita med varierande funktionalitet. Efter några e-postmeddelanden fram och tillbaka bestämde vi oss för att det bästa alternativet för Quell var att skapa ett inbyggt Vita-spel, vilket gav oss full tillgång till kraften i Vita och alla funktioner i PSN, såsom leaderboards och troféer.
Ofta bestämmer den första uppgiften för att skapa ett spel vilken motor som ska användas. Det finns ett antal motorer tillgängliga på Vita, men de flesta är fullständigt överkill från ett tekniskt perspektiv och bara otänkbart ur en finansiell perspektiv för ett projekt av denna storlek.
Det finns också den ofta förbisedda PhyreEngine, som utvecklats av Sony själva och fri att använda av registrerade PlayStation-utvecklare. Det har använts för att utveckla spel från Demon Souls till Colin McRae: Dirt and Journey. Återigen, som du förmodligen kan föreställa dig att det var så mycket mer än vad vi verkligen behövde, som att försöka knäcka en mutter med en slädehammer.
Bekvämt använde Quell Memento Fallen Tree Games egen motor och både motor- och spelkoden skrevs med C. C och dess varianter är standardspråket som används för att skapa spel och om du utvecklar ett spel att släppa på många olika plattformar, så verkligen borde inte gå med någonting annat.
Detta gjorde vårt beslut uppenbart: vi skulle hamna Fallen Tree Games motor själv till Vita. Det var gratis, det var byggt speciellt för att köra Quell-spelen och det var en bra codebase.
Det kan låta kontraintuitivt att ignorera alla motorer som redan kör på Vita och välja en motor som inte gör det, men att flytta ett spel till en ny motor kan innebära att hela spelet spelas för den motorn eftersom den fungerar på ett helt annat sätt . Att ta emot motorn adresserar problemet. Du behöver inte oroa dig för att återskapa varje enskild spelfunktion - du måste bara återskapa funktionaliteten som de alla sitter ovanpå.
Om du har tur kan en hamn ge dig möjlighet att utveckla din egen teknik för en ny plattform när du blir betald för att göra det. Bigyama har sin egen in-house-motor och hade Quell Memento byggts på en motor utan källkodstillträde, såsom UDK eller Unity, skulle det ha varit värt att överväga.
Skönheten i att utveckla en hamn är att du har ett tydligt mål att sträva efter.
Skönheten i att utveckla en hamn är att du har ett tydligt mål att sträva efter.
Det kan tyckas skrämmande först, men det kan brytas ner på några nyckelområden: grafik, användarinmatning, ljud, nätverk och spara spel.
Som jag redan nämnde, portade motorn menade att det inte fanns någon signifikant spelkod som skulle skrivas eller omskrivas. i det här fallet, att få dessa nyckelområden att fungera borde betyda att spelet i stor utsträckning tar hand om sig själv. De tidiga stadierna för att göra ett spel är ett streck för att hitta det roliga i spelet, men med en hamn är det ett streck för att få tillräckligt med springer för att ta reda på var den är trasig.
När du gör en port, börja med grafiken.
Det är det bästa stället att börja - om du inte kan visa något på skärmen kommer det att vara mycket svårt att veta om du gör framsteg. Vi började på grafiken innan vi ens fick händerna på en Vita. Vitas grafik API är mycket lik OpenGL och Quell Memento använder redan OpenGL.
Quell använde en fast funktionsrörledning (vilket innebär att användaren endast kan konfigurera steg i renderingsprocessen genom en fast uppsättning funktioner), men Vita använde en programmerbar pipeline (shader-program tillåter steg av reningsprocessen som tidigare fixats för att programmeras som användaren önskar).
Vi hade en kort period mellan att bli licensierade utvecklare och ta emot utvecklingspaket, så i vår egen motor (som använde Lua / C ++ / OpenGL) emulerade vi uppförandet av OpenGL-matrisstacken med hjälp av shaders och lite anpassad kod. Detta innebar att all befintlig Quell-kod - som baserades på den traditionella fasta rörledningen - kunde förbli i stort sett orörd.
// Del av vårt omslag för att emulera OpenGL-matrisstacken // Du kan hitta hela filen här: https://github.com/balaam/glfacade Matrix4 glfCalcProjMatrix () Matrix4 mat; matte = mat.identitet (); för (int i = 0; i < (int)g_glFacade.projectStack.size(); i++) mat = mat * g_glFacade.projectStack[i]; return mat;
När vi hade kits hade vi snabbt något igång. Det var ett litet arbete att göra, som att konvertera färgformat av snitten till det som förväntas av shader och ompaketera vertexdata från flera separata buffertar, som var och en innehåller separata vertexattribut - position, UV och så vidare - i en enda interfolierad buffert som visas i diagrammet nedan:
Med tillägg av en mycket grundläggande skuggare hade vi snart vår stänkskärm igång på satsen ... typ av:
Med tillägg av en enkel skuggning för att applicera texturer blev det snart det här:
Som jag nämnde använde Quell den fasta funktionsrörledningen och Vita-programmen var programmerbar - vilket innebär att alla renderingar måste konverteras för att använda shaders istället för den fasta funktionen att ange en mängd olika rendertillstånd för att uppnå en viss effekt.
Det finns ett par tankskolor om hur man hanterar dina shaders. En är att skapa en separat skuggning för varje material eller effekt; den andra är "uber-shader" -metoden, en stor skuggning med hjälp av förprocessordefinitioner för att producera varianterna som behövs vid sammanställningstiden. Varje har sina egna fördelar och nackdelar:
Individuella shaders - Fördelar:
Individuella shaders - Nackdelar:
Uber-shader - Fördelar:
Uber-shader - Nackdelar:
I verkligheten brukar de flesta projekt använda en kombination av båda metoderna. För vår Quell-port valde vi att gå helt och hållet med det individuella shader-tillvägagångssättet, eftersom våra krav var så enkla och korrekta.
Spelet förlitade sig på relativt få olika kombinationer av OpenGL render states. För att ge en uppfattning om hur enkla våra shader-krav var, har jag lagt till det mest komplexa här:
float4 main (float4 vColor: COLOR0, float2 vTexCoord: TEXCOORD0, float2 vTexCoord1: TEXCOORD1, float2 vTexCoord2: TEXCOORD2, enhetlig sampler2D testTex: TEXUNIT0, enhetlig sampler2D testTex1: TEXUNIT1, enhetlig sampler2D testTex2: TEXUNIT2) float4 texResult = tex2D (testTex, vTexCoord ); float4 texResult2 = tex2D (testTex1, vTexCoord1); float4 texResult3 = tex2D (testTex2, vTexCoord2); float4 currentCol = texResult; currentCol [0] = texResult3 [0] * vColor [0]; currentCol [1] = texResult3 [1] * vColor [1]; currentCol [2] = texResult3 [2] * vColor [2]; currentCol [3] = ((texResult2 [3]) * (texResult [3])) * vColor [3]; returnera currentCol;
Quell Vita-koden hade totalt 13 shaders: åtta shader-program (en toppunkt och sju fragmentskärmar) kombinerad med specifika blandningslägen. Det var ganska enkelt att byta kod i Quell-motorn som ställde in alla OpenGL-variablerna med samtal för att ställa in en skuggare istället:
rlSetBlend (RL_BLEND_RGBA); rlSetMultiTexture (0, rlGetTexture (quellGame_getAtlasImage (QUELLATLAS_SURROUND, true))); rlSetMultiTexBlend (0, RL_TEXBLEND_MODULATE_PASS_INV_ALPHA_TO_NEXT); rlSetMultiTexture (1, rlGetTexture (paneDesatTexture)); rlSetMultiTexBlend (1, RL_TEXBLEND_PREVIOUS_ALPHA_WITH_TEX_ALPHA);
blev:
rlSetShader (RL_SHADER_BLEND_RGBA_4);De
rl
(render layer) funktioner är en uppsättning funktioner som paketerar OpenGL-funktionaliteten; de 4
i RL_SHADER_BLEND_RGBA_4
helt enkelt indikerat att detta var vår fjärde variant av denna RGBA shader - med så få shaders vi inte krävde en särskilt beskrivande namngivningskonvention. Dessa rl
funktioner finns redan i Quell-motorn, men om spelet som ska portas inte använder denna typ av abstraktion är det något du vill lägga till tidigt. Det gör det möjligt att abstrahera renderingskoden så att plattformsspecifika ändringar kan göras utan att påverka spelkoden.
Idealisten i mig skulle verkligen ha velat ha implementerat ett uber-shader-baserat system. Detta skulle dock ha varit överkill och krävde arbete från FTG killarna att stödja, något vi arbetade hårt för att minimera. Porting skiljer sig inte från någon annan programmeringsuppgift, eftersom du alltid kommer att väga upp "att få jobbet gjort" mot din idealiserade vision om hur det skall ske.
I slutändan var det väldigt få huvudvärk för att få grafiksidan av spelet igång, även om det fanns några frustrerande bortkastade spårningar som jag antog var ett minneskryss i renderingskoden. Det var ett tag innan jag insåg det, till skillnad från samtal som glDrawArrays
i OpenGL, där din matris kopieras när du ringer, gör inte Vitas röstsamtal inte - det vill säga, du kan inte återanvända den vertikala bufferten du skickar till Vita ritar samtal tills det är färdigt att rita. Som du kan se från skärmdumpen nedan kan det göra en massa röra.
Åtgärden för detta var helt enkelt att använda befintlig funktionalitet i API: n för att vänta tills det gjordes med bufferten, men det var en tidig påminnelse om farorna med att göra antaganden om hur sakerna fungerar på en ny plattform (och även vad ditt fel kan vara på någon plattform).
Vi hade tur här eftersom de tidigare spelen redan hade släppts på Sonys Xperia Play, vilket innebär att det inte krävdes mycket arbete för att få knapparna att fungera - många fysiska kontroller som finns på Vita finns på Xperia och relaterad funktionalitet var redan på plats.
Detta innebar att det egentligen bara handlade om att kartlägga hårdvarutangenterna till programvarutangenterna och passera knappen "pressade" och "frigjorda" till den befintliga ingångshanteringskoden.
Eftersom spelet hade sitt ursprung på mobila enheter var det samma för frontpanelen. Den bakre pekskärmen krävde lite finess, det uppenbara problemet är att du inte bara kan mata dem båda i samma ström av ingångar, för om en spelare röra båda paneler och släpper framsidan, kanske spelet vill registrera det som motsvarande att släppa tillbaka eller det kan inte.
Det var också lite arbete med att få inmatningar från bakpanelen (som inte är lika stor som skärmen) för att känna som om de mappades korrekt till frontskärmen. Detta uppnåddes genom att man ignorerade en gräns för dödzon runt kanten på bakpanelen och skalar inmatningarna inuti detta område för att kartlägga till skärmen.
// bakre ingångar verkar inte helt matcha intervallet på frontskärmen // sträcker sig i kod // dessa är värden som kände sig lättillgängliga #definera REAR_DEADZONE_MIN_X 10 #define REAR_DEADZONE_MIN_Y 75 #define REAR_DEADZONE_MAX_X 950 #define REAR_DEADZONE_MAX_Y 430 #define REAR_STRETCH_X 960 # definiera REAR_STRETCH_Y 544 statisk vec2 vitaMapRearInputToScreen (int inputX, int inputY) vec2 sträcktInput; stretchedInput.x = (inputX-REAR_DEADZONE_MIN_X) * REAR_STRETCH_X / (REAR_DEADZONE_MAX_X-REAR_DEADZONE_MIN_X); sträcktInput.x = clampf (sträcktInput.x, 0, REAR_STRETCH_X); stretchedInput.y = (inputY-REAR_DEADZONE_MIN_Y) * REAR_STRETCH_Y / (REAR_DEADZONE_MAX_Y-REAR_DEADZONE_MIN_Y); stretchedInput.y = clampf (sträcktInput.y, 0, REAR_STRETCH_Y); returnera sträcktInput;
Sammantaget tror jag att vi kom ganska lätt här, delvis på grund av hur spelet bygger helt och hållet på en enkel svepande gest. Att dra över radikalt olika gränssnitt kan vara en verklig huvudvärk och, dåligt gjort, har potential att förinta ett annat bra spel. Hade vi portat ett tredje persons actionspel till Wii, hade det här avsnittet varit avsevärt längre.
Jag kommer inte att ljuga; Jag har en riktig kärlek / hatrelation med ljud. I min tid på Free Radical Design spenderade jag mycket tid på att arbeta med ljudkillar på motortekniken och ljuddesigners för att få ljud till spel och åtnjutit det oerhört. Ljud lyfter verkligen ett spel och tar det till liv.
Tyvärr har den mer låga sidan av saker, med dess cocktail av filformat, samplingsfrekvenser, komprimering, röster, bussar, filströmmar och så vidare, aldrig riktigt entusiasmerat mig på samma sätt. Så vi närmade oss denna uppgift med lite ångest.
Tack och lov, Vita SDK kommer fylld med (regelbundet uppdaterade) prover som grundligt täcker alla sätt att använda ljud API. Det minsta du kommer att vilja, även i de enklaste 2D-spelen, är möjligheten att spela enstaka ljud (spelljudseffekterna) och förmågan att strömma ljud (musik och andra stora filer som är för stora för att fortsätt ladda i minnet hela tiden). I många 2D-spel kan du nog även välja att hålla enbart med mono och spara lite extra minne - kanske till och med låta dig undvika att strömma helt.
Med lite bra referens till arbetet från proverna hade vi allt ljud igång om några dagar. Det enda andra stora arbetet med ljudet var en senomkopplare i ljudformat från VAG till ett proprietärt format med en mycket högre nivå av komprimering vilket minskade vår ljudminnesanvändning till cirka 30% av det som tidigare varit.
I slutet var processen för att genomföra ljudet en mycket mindre smärtsam upplevelse än vad jag hade frukat.
Quell Memento är ett enspelarspel utan nätverksspel och begränsade onlinefunktioner, så teoretiskt sett borde det ha varit en av de enklare områdena. Verkligheten pekar fint på en av utmaningarna med att överföra till en PlayStation-plattform: de fruktade TRC: erna (Technical Requirement Checklist - en lista över gör och inte utvecklare måste uppfylla för att klara QA).
Jag borde påpeka att Sony inte är unik här; Microsoft och Nintendo har sina motsvarigheter. Till skillnad från mobil, där onlinefunktionalitet ofta tillhandahålls av någon tredjepartsplattformslösning, eller PC, där den enda personen som dömmer din implementering kommer att vara slutanvändare, brukar det här området vara mycket kontrollerat på konsolerna. Detta har delvis att göra med att funktionaliteten som tillhandahålls av en tjänst som PSN beter sig på ett konsekvent sätt över titlarna och att föräldrarslussar, åldersgränser och så vidare följs.
Som ett resultat, kan du ta mer tid än vad du förväntar dig om du skickar till en konsol, även för ett spel med relativt enkla onlinefunktioner. För en hamn kan överensstämmelse med TRC: er vara en av de mest påträngande delarna av det arbete du måste göra. Särskilda krav på hur man hanterar händelser som förlust av anslutning eller förnekande av åtkomst till funktioner på grund av föräldralås och tid och sätt på vilket du måste vidarebefordra dessa saker till användaren, kan mycket väl kräva en grad fram och tillbaka mellan din spel och nätverkskomponenter som helt enkelt inte existerade i det ursprungliga spelet.
Vi använde ett bibliotek som tillhandahålls av Sony, som omsluter alla de låga inställningarna och nedbrytningen av PSN och online-uppgifter till ett ganska enkelt gränssnitt, vilket ger återkallelser för alla asynkrona uppgifter. Samtalen från spelet till online-funktionaliteten kan kokas ner till några olika grupper - inloggning, butik och leaderboards - var och en med några parametrar för att specificera detaljerna.
Allt detta innebar att en onlineförfrågan skulle kunna utlösas med några få rader kod och vi slutade med förmodligen inte mer än fem eller sex olika funktioner som kallades från spelet för att stödja onlinetegenskaperna.
Återuppringningarna från Sony-omslaget ger ganska granulär detalj på allt som går fel, men för det mesta kan dessa helt enkelt klassificeras som en framgång eller ett misslyckande och lämplig återkoppling till spelet utlöst. Detta innebar att vi också kunde koka ner återuppringningarna från motorn till spelet i lika få samtal.
Felstater hanterades så mycket som möjligt i motorkoden. Detta innebar att Fallen Tree-killar kunde fortsätta utveckla Quell utan att behöva oroa sig för Vita-specifika misslyckanden.
Om en motorfunktion till exempel hade ett förutsättningsanrop som eventuellt skulle kunna misslyckas, istället för att kräva att spelet kräver några förutsättningar och sedan dess begäran, vi skulle kalla förutsättningen tyst, caching själva begäran. Om förutsättningen misslyckades skulle vi dumpa förfrågan och anmäla spelet via normal återuppringning, med hjälp av dialogrutan från motorsidan. Efter framgång skulle förfrågan utföras som avsedd.
Detta fungerade i allmänhet bra; som med något system som läggs till senare och gör sitt bästa för att vara icke-påträngande var det en eller två mindre än eleganta kodstycken, men det gjorde jobbet.
Spara spel är värda att nämna eftersom de, som med nätverksfunktionaliteten ovan, är föremål för en hög grad av granskning när det gäller TRC. Spara spel är benägen för två viktiga fel: springer ur fillagring eller slutar spara kvot.
(Jag har uteslutit att spara korruption eftersom det verkligen inte är mycket du kan göra om en korrupt räddning, systemet kommer att varna dig och du kan informera användaren, men alla du kan göra är att ta bort den och gå vidare ... och kanske har tyst litet gråt på alla de förlorade timmarna.)
Att köra ut av filsystemlagring är ganska självförklarande: det finns helt enkelt inte tillräckligt med utrymme för att spara vad du vill ha. Spara kvoten är inställd under utvecklingen av ditt spel; Det är i grunden en självdeklarerad gräns för hur mycket minne ditt program någonsin behöver för att spara speldata. Denna kvot är inte allokerad vid installationen av ditt spel, dock - det kan inte garanteras att det existerar.
Vid hantering av var och en av dessa har du verkligen två alternativ.
Om spelet går tom för filsystemlagring kan du:
När det gäller spridning av spara kvot kan du:
Quells natur gjorde det möjligt för oss att hantera detta ganska kortfattat genom att gå med alternativ 2 respektive 1. Quell är inte ett spel där du kanske vill hoppa tillbaka till din räddning för fem minuter sedan, så det krävs bara en spara och det här skapas automatiskt, sparas och laddas. Innehållet och därmed storleken på spara är något förutsägbart.
På den första spelningen försöker vårt spara system att allokera den maximala mängd minne som någonsin kommer att behövas för din spara fil. Om det inte kan göra det, det vill säga om det redan finns tillräckligt med filsystemlagring, visas det standardmeddelandet som visas nedan:
Spelaren får inte fortsätta tills de har löst det här problemet själv (genom att minimera eller stänga appen och radera vissa data). När de slår OK kommer det att försöka igen att allokera minnet. När den här inledande spara skapats framgångsrikt är det säkert att anta att en brist i filsystemet och spara kvot aldrig kommer att inträffa.
Jag har redan kortfattat nämnt TRCs (Technical Checklist Checklist) och som en ansvarsfriskrivning skulle jag säga att jag är lycklig TRCs finns; som en gamer saker, som PSN har blivit så en integrerad del av den erfarenhet som jag uppskattar att jag kan förvänta mig en viss grad av överensstämmelse över spelets beteende.
Som sagt, som en utvecklare, är de en smärta. Vi hade tur att spelet var relativt enkelt och sålunda kunde många TRCs helt enkelt ignoreras, eftersom de inte var tillämpliga. Även om du arbetar med att få ett relativt enkelt spel till någon av konsolerna, skulle jag dock starkt rekommendera dig att bekanta dig med reglerna för den plattformen tidigt och hänvisa till dem ofta. Vad som kan ha varit acceptabelt på en plattform kanske inte flyger på en annan och du vill inte vänta tills du får en stor lista med anledningar till varför du misslyckades QA att inse att du gör allt fel.
För ett litet team utan en dedikerad QA-avdelning kan det tyckas som en väldigt skrämmande uppgift, men en liten del av mening och planering kan göra skillnaden.
För det första är massor av kraven bara ett uttryckligt sätt att be dig att inte göra dumma saker som du förmodligen inte vill göra ändå - tack och lov hade FTG-killarna redan undvikit att göra någonting dumt så det var en bra start.
För det andra behöll vi ett kalkylblad över alla krav och om de för närvarande passerade, misslyckades, kunde inte testas ännu, eller helt enkelt inte var tillämpliga. Som viktiga funktioner gick in i spelet kunde vi göra en sopning av denna lista för att uppdatera statusen för varje krav och samtidigt uppdatera våra minnen på vilka restriktioner som tillämpas.
När vi nådde vår QA-fas, hade vi en ganska klar uppfattning om var vi stod i fråga om TRC och fann oss inte inför några obehagliga överraskningar.
Se till att du har tydligt överens om tidsramar och mål. Det här är mer en affärsproblem än teknisk men viktig om du portar ett spel till någon annan, även om det bara är ett hobbyprojekt bland vänner. (Du vill stanna vänner, eller hur?)
När vi började arbeta med Quell Memento var det inte färdigt och det fanns en allmän känsla för när slutdatumet skulle vara, ingenting sattes i sten. I slutändan tog hela projektet längre tid än väntat.
I efterhand hade det varit bättre att vänta på att spelet är helt färdigt - eller åtminstone mycket mer komplett - innan vi börjar vår hamn. När vi porterade motorn var det sällan påverkat av ny gameplay och innehåll, men det fanns tillfällen då funktioner krävde motorändringar. Det fanns också tider när framsteg på porting motorn var blockerad när vi väntade på nya funktioner som skulle läggas till.
Vi har ett bra förhållande med killarna på FTG och hade turen i dessa situationer för att ha flexibilitet att byta till våra egna projekt för dessa perioder (bland annat undersöka några av Vitas mer unika egenskaper som den utvidgade verkligheten), men som alla vem som någonsin har försökt lite multitasking borde veta, det här är inte det effektivaste sättet att arbeta.
Det är svårt att peka på några enskilda standout-lektioner som vi lärde oss. vi fick mer av en inkrementell ackumulering av kunskap om nya verktyg, API och processer.
I framtiden skulle vi kanske vara djärvare i att tvinga (eller åtminstone föreslå) förändringar i spelkoden där det kände sig rimligt - vi kan ha gjort några uppgifter hårdare än vad de behövde vara den här gången. Men definitionen av "rimlig" kommer alltid att variera vildt från projekt till projekt.
Dessutom skulle vi förmodligen vänta på att ett spel blir mer komplett innan vi börjar arbeta på en hamn i framtiden, eftersom fler människor arbetar solidt på mindre tid. Återigen kan genomförbarheten av detta variera enormt mellan projekt beroende på utgivningsplanen. Efter att ha gjort det en gång kan vi nu bättre uppskatta hur lång tid vi behöver.
Viktigast av allt har vi fått månader av värdefull erfarenhet på en ny plattform, inklusive dess inlämningsprocess - till och med att få en chans att undersöka några av dess unika egenskaper För ett lag som i stor utsträckning bygger på arbete för uthyrning och kontraktsarbete som källa till inkomst, värdet av detta kan inte underskattas.
Mitt råd för någon av er som överväger en hamn till Vita skulle vara att ge den en spricka. Jag tror att det finns en viss mystik kring konsolutveckling. Vi hade turen att ha erfarenhet på detta område, men även utan det borde du inte bli avstängd.
Sony är väldigt välkomnande till indier och småutvecklare (något som jag tror är synlig för det bredare spelet dev community) och om du har en rimlig grad av teknisk spelutvecklingskunskap, då med det stora stödet från Sony Developer Support Team du bör Det går inte i några oöverstigliga utmaningar.
Quell Memento för Vita finns nu i SCEA och SCEE.