You are on page 1of 49

IntroduccinalibGDX Descargarlalibrera CrearunproyectoJAVAnuevo PortarelproyectoJAVAaunproyectoAndroid CiclodevidadeunaaplicacinlibGDX Grficos TexturaseInterpolacin TextureRegion TextuimagrePacker Empaquetarimgenesautomaticamente Cargadeimgenesempaquetadas Dibujarimgenesenpantalla Entrada Detectarpulsacionesenlapantallatctil Audio

Sounds Cargarsonidos Reproducirsonidos Descargarsonidos Music Cargarunamsica Descargarunamsica Navegandoentrepantallasdeljuego Vibracin Cmaras Animacin Manualdebuenasprcticas Separarlalgicadelapresentacin PginasparaDesarrollodeJuegos Solucindeproblemas

IntroduccinalibGDX

LibGDXesunframeworkmultiplataformadedesarrollodejuegosparaWindows,Linuxy Android.EstescritoenJavaconunamezcladeC/C++paradarsoporteyrendimientoatareas relacionadasconelusodelafsicayprocesamientodeaudio. LibGDXpermitegenerarunaaplicacinensuPCyutilizarelmismocdigoenAndroid,deesta maneraelprocesodepruebasydepuracinserealizadeformamsrpidaycmodayaque elPCesmuchomsrpidoqueeldispositivoAndroid. ConLibGDXnosaseguramosdequelamismaaplicacinpuedefuncionarcorrectamenteen diferentesdispositivos. LibGDXestcompuestoporunaseriedecomponentesdeserncomunesatodaslas aplicaciones. MarcodeAplicacin,quemanejarelbucleprincipalyademsestarencargadodelclicode vida,esdecir,loseventosdecreacin,destruccin,pausayresumedelamisma. UncomponentedeGrficosquenospermitirgestionarlarepresentacindeimgenesy objetosgrficosenlapantalla. UncomponentedeAudio,quenosfacilitarelaccesoalossonidosymsicadelaaplicacin. UncomponentededeEntradaySalidaparaleeryescribirlosdiferentesficherosdedatos comoporejemplo,imgenes,archivosdeconfiguracin,sonidos,msica,texturas,... UncomponentedeEntradaquegestionaralaentradaatravsdelteclado,pantallatcilo acelermetro.

Adicionalmentepodramosampliarlagamademdulosconotrosdosms. Math,permitelagestinrpidadeclculosmatemticosorientadosaldesarrollode videojuegos. Physics,quebsicamenteesunwrapperdeBox2Dypermitecontrolarlagestindecolisiones. EstegrficomuestraenmayordetalleelsistemademdulosdeLibGDX

Realmente,estosmdulossonslointerfacespblicasqueofrecelalibrera. Lapropiaaplicacinserlaencargadadelagestindelosdiferentesmdulos. Ventajas: Soporte2dfull(bajoyaltonivel) Muchadocumentacin,tutoriales,ejemplosdecdigo ReleasesenformaperidicalaultimafueensetiembreyanteriorenMayo Sepuedeprobarendesktop(antesdesubiramobile) ManejaAudio,input(usuario),fsica,matemtica,archivos MaspoderosoqueAndengine Soporta3d libGDXtedaunaccesomsfcilaBajonivel Posibilidaddetomarunjuegohechoenjavajar2do3dyadaptarloalibgdxparaq funcionenativoenandroid,esohicieronconeljuegoDroidInvaders3d. Desventaja: Elsoportedealtonivelen3destaenconstruccinactualmente Linksdereferencia:
PaginaOficial Wikidelproyecto Blog Foro Juegoen3dyarealizado:DroidInvaders ListadodeEjemplos VideoTutoriales Documentacin

Descargarlalibrera
Paradescargarlalibreradebemosiralawebdelamisma:http://libgdx.badlogicgames.com/

Aladerechapulsamosendownloadydelasdosversionesdelalibreraquenosaparecen, seleccionamoslaversinNightlyBuild.

TraspulsarenDownloadyaslonosquedadescargarlaltimaversindelalibrera.

CrearunproyectoJAVAnuevo
AunqueelobjetivofinalesqueeljuegofuncionesobreAndroid,trabajaremosconunproyecto JAVAqueunavezterminadoseportaraAndroid.

ParacrearunproyectoJAVAenEclipsesimplementeenelmenvamosaFile>New>Java Project.Ledamosunnombrealproyecto(enestecasoDemo1).Elegimoslarutadondese crearenmemoriayledamosaFinish.

Unavezcreadoelproyectoelsiguientepasoseraadirlalibrera.Paraellounabuenaprctica escrearundirectoriodentrodelproyectodondeincluirlaslibrerasqueusemos. ParaelloclickderechosobrenuestroproyectoyNew>Folder.Ennuestroejemploesta carpetalallamaremoslibs. Unavezcreadaestacarpeta,simplementetendremosqueaadiralamismaloque necesitamosparaesteproyecto.Paraaadir,nosvamosaldirectoriodondehemosguardadola libreradescargadaenelapartadoanteriorypodemosarrastrarocopiarlosarchivosque necesitamos(enlaimagen).

Nosquedaraelproyectodeestaforma:

Yatenemoslaslibreraseneldirectorioquehemoscreadodentrodelproyecto.Peroanno formanpartedelmismo,elsiguientepasoesaadirlas.Paraelloseleccionamosloscuatro ficherosdentrodelacarpetalibs,hacemosclickderechoyenelmencontextual seleccionamosBuildPath>AddtoBuildPath.Elproyectoquedadelasiguienteforma:

Otrabuenaprctica,aunquenonecesariaesaadirlainformacincontenidaenelJavadocde lalibrera.Elobjetivodeestoesquecuandosemuestrelaayudaemergentedeeclipseveamos lainformacincontenidaenelJavadocdelalibrera.

ParaellohacemosclickderechosobreelproyectoyenelmencontextualBuildPath> ConfigureBuildPath...trasloquesenosmuestralosiguiente:

Enestaventanadesplegamosgdx.jarytalcomoseveenlaimagenseleccionamosJavadoc location.UnavezhechoestopulsamossobreEdit...

PulsamosenBrowse...ybuscamoslalocalizacindelJavadocqueseencuentraen libgdxnightly>docs>api.UnavezseleccionadoestedirectoriopulsamossobreOkpara confirmarelcambio.Yyatenemosestacaractersticahabilitada. UnavezpreparadoEclipseynuestroproyectoJAVAyapodemosempezaratrabajar. Loprimerosercrearlaclaseprincipaldeljuego,queserlaencargadademanejarycontrolar

todoloqueocurraeneljuego. Paraelloclickderechosobresrc>New>Class.

Creamoslaclaseenelpaquetecom.desarrolladoresandroid.libgdx.demo1 ElnombredelamismaesDemo1Game EstanuevaclaseheredardeGame(com.badlogic.gdx.Game).

Unavezcreadalaclaseprincipaldelproyecto,crearemoselpuntodeentradaparalaejecucin delaaplicacinJAVA.Unaclasequenospermitirlanzareljuego.

Paraellocreamosunaclasequecontengaelmtodomain:

Nombredelaclase:Demo1Desktop Mismopaquetequelaclaseprincipal. Seleccionamoslaopcinpublicstaticvoidmain(String[]args)

Nosquedaraelproyectodelasiguienteforma:

ParapoderlanzareljuegoaadimosenlaclaseDemo1Desktoptenemosqueaadirlo siguiente: newJoglApplication(newDemo1Game(),"Demo1",320,480,false) Losparmetrosindicanlosiguiente: newDemo1Game().InstanciadelaclasequeimplementaGame "Demo1".Queeselttulodelaaplicacin. 320.Anchoenpxeles. 480.Altoenpxeles. false.ParaindicarquenoqueremosutilizarOpenGLS2.0enestecaso.Porloqueseutilizar el1.1 Unavezhechoestoyatenemosunjuegoquenohacenadayquepodemoslanzarcomo aplicacinJAVA. ParalanzarlotenemosquehacerclickderechoenelproyectoyRunAs>JavaApplication Unavezhechoestonossaldrunaventanaparaseleccionarelpuntodeentradadela aplicacinqueennuestroejemploesDemo1Desktop.java

Elresultadodelaejecucinserunapantallanegraconlaresolucinindicada.

PortarelproyectoJAVAaunproyectoAndroid
AhoracrearemoselproyectoparacompilarloenAndroid.Paraefectospracticosusareun ejemploqueyoyatena.HechoenescritoriollamadoHolaLibgdx.

11.Crearcarpetalibsdentrodelproyectoyponerlelassiguienteslibrerasdelasque descargamosincluyendoesascarpetas: Importante!"SEDEBENINCLUIRLASCARPETASarmeabiyarmeabiv7acomoseveenla imagen.Estascarpetasvienenenlaslibrerasquedescargamos"

12.Referenciamoslaslibrerascopiadas.Clickderechoalproyecto/buildpath/configurebuild path...

13.Antesdecerraresapantallaanterioriralapestaaprojectyadjuntarlelareferenciaal proyectodeescritorio.

12.ModificarlaActivityprincipal"HolaLibGdxActivity"paraquenoextiendadeActivitysinode AndroidApplication.(crt+shift+o)pararesolverlosimportsnecesarios. package c o m . l i b g d x . h o l a l i b g d x import a n d r o i d . o s . B u n d l e import c o m . b a d l o g i c . g d x . b a c k e n d s . a n d r o i d . A n d r o i d A p p l i c a t i o n import c o m . l i b g d x . h o l a l i b g x . H o l a L i b g d x public class H o l a L i b G d x A c t i v i t y extends A n d r o i d A p p l i c a t i o n { /**Calledwhentheactivityisfirstcreated.*/ @Override public void o n C r e a t e ( B u n d l e s a v e d I n s t a n c e S t a t e ) {
super. o n C r e a t e ( s a v e d I n s t a n c e S t a t e ) / / A c a i n i c i a l i z a m o s a l a p p d e e s c r i t o r i o . i n i t i a l i z e ( new H o l a L i b g d x ( ) , false) } }

Deberaquedarnosas. 13.Loejecutamosenelemulador.

Desbloqueamoseldispositivoenelemulador.

ySeejecutaexactamentelomismoqueenescritorio.Loquehicimosrecin,tambincompil laaplicacinenunarchivo.apkdentrodeldirectorio/bindelproyectoandroid, esearchivo.apksellevaaldispositivofisicorealyalejecutarloteinstalalaappcreada.

CiclodevidadeunaaplicacinlibGDX
Esteapartadodescribecmoseestructuraunaaplicacinlibgdx. LAAPLICACION Eselprincipalpuntodeentradaparacualquieraplicacinlibgdx.LainterfazApplication determinalaplataformaylosgraficosdefondoquesernutilizadosporlaaplicacin.Lainterfaz tambinproporcionalosmtodosparaaccederagrficos,audio,archivosdeentraday mdulosdeE/S.TambindaaccesoaunmdulodeLoggingelcualfuncionaentodaslas plataformas. LibGDXescompatibleactualmentecondosbackendsdeaplicacionesdeescritorio(lwjgly JOGL)yotraparaAndroid. ParacrearunaaplicacinlibGDX,sehadeimplementarlainterfazApplicationListener primero. APPLICATIONLISTENER ApplicationListenereselresponsabledelainicializacindelaaplicacin,laactualizacindel estadodeljuego(esdecir,lalgicadeljuego),renderizacindelaimagen,pausadodeljuego, guardarelestadoylaliberacindelosrecursosalsalirdelaaplicacin. Estambinellugardondeloseventosdelciclodevidasonmanejados.Cadaaplicacin/juego, sinimportarelbackendy/oplataformadedestinotendrqueimplementarlainterfaz ApplicationListener.Laimplementacinesexactamentelamismaparatodaslasplataformas. Portanto,ApplicationesresponsabledelcircuitodejuegoyApplicationListeneresellugar dondeseimplementalalgicadeljuego. LaimplementacindelainterfazApplicationListener

Loseventosquesondesencadenadosporlosenlaaplicacindelciclodevidatalcomose describe: create():Sellamaunavezcuandosecrealaaplicacin. resize(intwidth,intheight):Sellamaaestemtodocadavezquelapantalladeljuego cambiasutamaoyeljuegonoestenelestadodepausa.Tambinselellamaslounavez justodespusdelmtodocreate().Losparmetrossonlanuevaanchurayalturadelapantalla. render():Mtodollamadoporelbucledeljuegodelaaplicacincadavezqueserenderiza.La actualizacindeljuegotambintienelugaraquantesdelarepresentacinreal. pause():Elmtododepausase llamajustoantesquesedestruyalaaplicacin.EnAndroidse llamacuandoelbotndeiniciosepresionaohayaunallamadaentrante.Enelescritoriose llamajustoantesdedispose()alsalirdelaaplicacin.Esunbuenlugarparaguardarelestado deljuegoenAndroid,yaquenosegarantizaqueseareanudado. resume():EstemtodoesllamadosloenAndroid,cuandolaaplicacinrecibeelfoco.Enel escritorioestemtodonoserllamadonunca. dispose():Selellamacuandolaaplicacinsedestruye.Esprecedidoporunapausa().

Ciclodevidadeunaaplicacion
Losmtodosantesmencionadossonprovocadosporlaaplicacindurantesuciclodevida. ElsiguientediagramamuestralasdiferentesfasesporlasquepasaunaaplicacinlibGDX:

Grficos
ElmdulodegrficosesunresumendelacomunicacinconelGPUyproporcionamtodosde convenienciaparaobtenerlasinstanciasdeOpenGLES.Seencargadetodoelcdigo repetitivonecesariosparahacerseconelejemplodeOpenGLyseocupadetodaslas implementacionesproporcionadasporelfabricante. Dependiendodelhardwaresubyacente,loscontenedorespuedenseropuedennoestar disponible. Elmdulodegrficostambinproporcionamtodosparagenerarmapasdepixelsytexturas. EnelsiguientecdigopodemosvercmoobtenerunainstanciadelaAPIOpenGL1.0:
GL10 gl = Gdx.graphics.getGL10 ();

Elmtododevuelveunainstanciaquepuedeserusadaparadibujarenlapantalla.Enelcaso quelaconfiguracindehardwarenoseacompatibleconOpenGLES1.0,devuelvenull. Elsiguientefragmentodecdigoborralapantallaylapintaderojo:


gl.glClearColor(0.1f, 0.0f, 0.0f, 1); gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

TexturaseInterpolacin
Textureesuna"imagen"enlamemoriadelchipgrfico(lasimgenesendiscosecargarnen estazonadememoria).EnOpenGLelanchoyaltodeunatexturatienequeserpotenciade2 (...32,64,128,256,512,1024,etc).Aunqueenlosejemplossedefinenlatexturacuadrada,no tieneporquseras.Puedestenerunatexturade128x32,32x256,etc. Porejemplo,elHTCG1soportacomomucho,unatexturade1024x1024(Aunquepuedestener msdeunatexturaalavez).Intentarutilizartexturasmsgrandesenestedispositivo provocarnerroreseneljuego.Larecomendacinesquenopasesdelvalor1024para establecerelanchooaltodetustexturas. UnparmetromuyimportantequehayqueindicaralahoradecrearunobjetoTextureesun valorTextureOptionsqueindicarqumtodoseutilizarpararedimensionarlasimgenes quetenemosdentrodelatextura.(Paranocomplicarlascosas,dejaremosesaexplicacin).

Sepuedenelegirlossiguientesmodos: NEAREST: Laimagenaparecerpixelada.Esmuchomsrpido,perolaimagentienemenorcalidad. Original:

AmpliadaconNEAREST:

BILINEAR: Laimagenaparecemsdifuminada.Esunpocomslento,peronoverspxelesenlamisma. Original:

AmpliadaconBILINEAR:

REPEATING: Silatexturaesde32x32ytienequedibujarsesobreunasuperficiede64x64,veremos4 imgenesrellenandoesehueco.Comosipusiramoslamismaimagenunayotravez repitindola.EstemodonofuncionaconlosSpritesnormales,asqueporahora,vamosa ignorarlo. Cuandoutilizasimgenesquecontienenvaloresalpha(transparencia)puedesencontrartecon

queteaparezcan"halos"querodeanlosbordesdelasmismas.Aquesdondeentraenjuegola tcnica"premultipliedalpha",lacualcorrigeeseproblema.Intentaevitarutilizar"premultiplied alpha"amenosqueveascosasrarasenlosbordesdetusimgenes,comosobrasohalos resplandecientesquenodeberanestar. Siquieresunainterpolacinbilineal,estableces: TextureOptions.BILINEAR Siquieresunainterpolacinbilinealcon"premultipliedalpha",estableces: TextureOptions.BILINEAR_PREMULTIPLYALPHA LomismoocurresiquieresinterpolacinNEARESTconosin"premultipliedalpha".Escosa tuyaexplorarlosvaloresquepuedeselegirdeTextureOptions. Parafinalizar,decirqueTextureOptions.DEFAULT= TextureOptions.NEAREST_PREMULTIPLYALPHA

TextureRegion
Defineunrearectangulardeunatextura.Elsistemadecoordenadasutilizadotienesuorigen enlaesquinasuperiorizquierdaconelejexapuntandohacialaderechayelejeyapuntando haciaabajo. LastextureRegionsonempleadasparacrearnuevasimagenes(otambinllamadosactoresde tipoimagen)asociadasaunreadeunatextura. Tienevariasopcionesparaconstruirunobjetodeestaclase,sonlossiguientes:
T e x t u r e R e g i o n ( )

Construyeunaregionsintextutanicoordenadasdefinidas.Sepodrandefinirdespuesempleando losmtodosdelaclase.
T e x t u r e R e g i o n ( T e x t u r e t e x t u r e )

Construyeunaregiondetamaoespecificadoenlatextura.
T e x t u r e R e g i o n ( T e x t u r e t e x t u r e , f l o a t u , f l o a t v , f l o a t u 2 , f l o a t v 2 )

T e x t u r e R e g i o n ( T e x t u r e t e x t u r e , i n t w i d t h , i n t h e i g h t )

Construyeunareginconconlascoordenadasdelatexturayelanchoyaltoespecificado.
T e x t u r e R e g i o n ( T e x t u r e t e x t u r e , i n t x , i n t y , i n t w i d t h , i n t h e i g h t )

Defineunateturaespecificandoelpunto(x,y)deorigenyeltamaodelarea(ancho,alto)
T e x t u r e R e g i o n ( T e x t u r e R e g i o n r e g i o n )

Construyeunareginconlamismatexturaycoordenadasquelareginpasadacomoparmetro.
T e x t u r e R e g i o n ( T e x t u r e R e g i o n r e g i o n , i n t x , i n t y , i n t w i d t h , i n t h e i g h t )

Construyeunareginconlamismatexturaycoordenadasquelareginpasadacomoparmetro.

UnejemplodeseleccindeunreaconTextureRegioneselsiguiente
TextureRegion texture = new TextureRegion(new Texture( Gdx.files.internal("data/jugador.png")), 0, 0, 40, 40);

TexturePacker
EmpaquetaimagenesenunTextureAtlas.

Loidealesalmacenarmuchasimgenesmspequeasenunaimagenms grande,obligaralatexturamsunavez,luegodibujarporcionesdelamismamuchas veces.libgdxtieneunaclaseTexturePackerqueesunaaplicacindelneadecomandos queempaquetamuchasimgenesmspequeasen1imgenmsgrande. TexturePackersebasaenestealgoritmo.Tambintieneunafuerzabruta,elembalajede variasmanerasyluegoelegirelresultadomseficiente.

Empaquetarimgenesautomaticamente
Sedeberimportarlalibreria:gdxtools.jar ElcdigoparaejecutarelTexturePacker: Settingssettings=newSettings() settings.padding=2 settings.maxHeight=1024 settings.maxWidth=1024 settings.incremental=true TexturePacker.process(settings,"images","data") Sedebertenerenelproyectounacarpetaimages,conlasimagenesaprocesar.Elproceso generarlacarpetadataconelpackrealizado.

Cargadeimgenesempaquetadas
AsiserecuperanlastexturasdeuntextureAtlasGeneradoporunpacker. publicstaticAtlasRegionbackground atlas=newTextureAtlas(Gdx.files.internal("data/pack")) background=atlas.findRegion("background")

Dibujarimgenesenpantalla
CreamoslaclaseAssetparaalmacenarlosrecursosdeimagenes. */ publicclassAssets{ /**Contieneelpaquetedetexturas.*/ publicstaticTextureAtlasatlas /**Regionesdentrodelaimagendetexturaempaquetada*/ publicstaticAtlasRegionbackground publicstaticAtlasRegionsoundoff publicstaticAtlasRegionsoundon publicstaticAtlasRegionstart publicstaticAtlasRegiontitle

/** *Load. */ publicstaticvoidload(){ atlas=newTextureAtlas(Gdx.files.internal("data/pack")) background=atlas.findRegion("background") soundoff=atlas.findRegion("soundoff") soundon=atlas.findRegion("soundon") start=atlas.findRegion("start") title=atlas.findRegion("title")

} publicstaticvoiddispose(){ atlas.dispose() }

publicclassHolaLibgdxExampleimplementsApplicationListener{ /**Theguicam.*/ OrthographicCameraguiCam /**Seutilizaparadibujaryoptimizarlasimagenesenelrenderizadodelapantalla.*/ SpriteBatchbatcher

@Override publicvoidcreate(){ } @Override publicvoiddispose(){ batcher.dispose() } @Override publicvoidpause(){ } @Override publicvoidrender(){ GL10gl=Gdx.graphics.getGL10()//referenciaaOpenGL1.0 gl.glClearColor(0,1,0,1) gl.glClear(GL10.GL_COLOR_BUFFER_BIT) guiCam=newOrthographicCamera(10,15) //definiciondenuestrapropiamedidadeljuego guiCam.position.set(10f/2,15f/2,0) //Dondeestaramirandolacamara batcher=newSpriteBatch() //crearsolamenteunbatcherporpantallayeliminarlocuandonoseuse

guiCam.update() batcher.setProjectionMatrix(guiCam.combined) //DibujandoelBackground batcher.disableBlending() //seeliminagraficamentelatransparenciayaqueesunfondo batcher.begin() batcher.draw(Assets.background,0,0,10,15) batcher.end() //DibujandoelementosenpantallaactivamoselBlending batcher.enableBlending() batcher.begin() batcher.draw(Assets.title,1,8,8,6) batcher.draw(Assets.start,2,5,6,1) batcher.draw(Assets.soundon,2,3,6,1) batcher.end() } @Override publicvoidresize(intarg0,intarg1){ } @Override publicvoidresume(){ } }

Entrada
Elmdulodeentradapermitecapturarlosdiversasformasdeentradadecada plataforma.Permitesaberdelestadodecadatecla,lapantallatctilyelacelermetro. Enelescritoriolapantallatctilsesustituyeporelratn,mientrasqueelacelermetrono estdisponible. Enelfragmentodecdigosiguienteseobtieneeltouchactualdecoordenadassihayun touchdelcelular(odelratnenelescritorio): if(Gdx.input.isTouched()){ System.out.println("deentradaseprodujoenx="+x+",y="+y) } Demanerasimilaratodoslosmediosdeentradapuedenserconsultadosymanipulados.

Detectarpulsacionesenlapantallatctil
SedebedifinirunVector,unareaficticiadondesecaptareleventodepulsacindeldedo. UsamostambienelobjetodeOrthographicCamera,paraconvertirlospixelesennuestra medidaenmetros.LuegopreguntamossielbotonquecreamosBoundingBoxtieneuntouch. Yescribimoselcdigoparamanejareseevento.

Audio
LibGDXcuentaconunmdulodeaudioqueofrecedostiposderecursos:Elsonidoyla msica. AmbostipossoportanelformatoWAV,MP3yOGG.Tambinofreceaccesoalhardwarede sonido. Ladiferenciaentreelsonidoylamsicaesqueelsonidosealmacenaenmemoriayseusa cadavezquesequierereproduciralgunodeellos,mientrasquelamsicasonstreamsde sonidoqueestnalmacenadosenficherosyalosqueseaccedecadavezquesequiere reproduciralgo. Elsiguientefragmentodecdigoreproduceunficherodemsicadesdeeldiscoconelvolumen alamitad:

Musicmusic=Gdx.audio.newMusic(Gdx.files.getFileHandle("data/myMusicFile.mp3", FileType.Internal)) music.setVolume(0.5f) music.play() music.setLooping(true)

Sounds
Soundesunaclasedestinadaalareproduccindeunefectodesonido.Lonormalescargarel sonidodesdeunarchivoamemoriayluegoreproducirloatravsdelmtodoSound.play().Los sonidossongeneralmentecortos,llegandoadurarunospocossegundosyaquealser cargadosenmemoriapuedenllegaraocupardemasiado,incidiendodirectamenteenel rendimiento. Cuandoyanovayamosausarmsesesonidosernecesariollamaralmtodo Sound.dispose()paraliberarmemoriaeneldispositivo.

Cargarsonidos
LosArchivosparalosefectosdesonidolospondremosdentrodeunacarpetallamadadata ParacargarenmemoriaunefectodesonidotanslosernecesariodefinirlocomotipoSound yllamaralmtodoGdx.audio.newSoundpasandocomoparmetroelficherodentrodel directoriodata. Elsiguientefragmentodecdigocargaunsonidoenmemoria. Soundexplosion explosion=Gdx.audio.newSound(Gdx.files.internal("data/explosion.ogg")) Puestoqueelsonidoserunacosaqueslosecargarunavezdurantetodalavidadela aplicacin,haremoslallamadaanewSoundennuestromtododestinadoalacargadedatos.

Reproducirsonidos
Parareproducirunsonidopreviamentecargadoenmemoriatanslosernecesariohaceruna llamadaalmtodoplaydelsonidopasandocomoparmetrounvalorentre0y1que representarelvolumen. explosion.play(1)

Descargarsonidos
Unavezquenoqueramoshacerusodelsonidosernecesariodescargarlodememoriayaque enlosdispositivosmviles,lamemoriaRAMsiguesiendounelementomuyprecidado. Paradescargardememoriaunsonidotanslosernecesariollamaralmtododisposedel objeto.Estopodemoshacerloennuestroapartadodestinadoaladescargadedatosobienen elmtododisposedelaaplicacin,comoyahemosvistoenelapartadodeciclodevidadela aplicacin. explosion.dispose()

Music
Musiceslaclasedelibgdxparacargararchivosdesonidoennuestrosjuegosderivadelaclase Disposableconstadelossiguientesmtodos: play()Comienzaalacancin,enelelcasodeestarpausadalareanudadondese quedoyenelcasodequesehubieraparadolacomienzadesdeelprincipio. pause()Pausalacancin,silacancinnohaempezadoaunoestayahafinalizado, estemtodoesignoradoalllamarlo. stop()Paralacancin.Lasiguientevezquesellamealmtodoplay()lacancin comenzardesdeelprincipio. isPlaying()Funcinquedevuelveunbooleano,indicandosiesverdadonoquela cancinestasonando. setLopping()Admitecomoparmetrounbooleanoparaindicarsiseactivalafuncin loopenlacancin,estafuncinactivalarepeticinindefinidadelamsica,detalforma quesisellamaalprocedimientoindicandotrue,lacancinserepiteindefinidamente hastaquelaparemosohastaquedesactivemoselloop. isLopping()Funcinquedevuelveunbooleano,indicandosiesverdadonoquela cancinestasonando. setVolume()Varaelvolumendelsonido,admiteporparmetros(01),conun0se poneensilencioycon1seponeelvolumenalmximo. getPosition()Funcinquedevuelveunfloatconlaposicindelacancinen milisegundos dispose()Eseldestructordelaclase.Esmuyconvenientellamarlocuandonosea necesarialamusicayaqueconsumememoriadeldisposivo LibgdxsoportalosformatosMP3,OGGyWAV.EsconvenienteusarOggencasitodoslos casos. Sinecesitamscontrolsobreeldispositivodeaudio,puedeutilizarelAudioDeviceyclases Audiorecorderquetambinseobtienedelainterfazdeaudio.Estasclasespermitenala salidadelasmuestrasdePCMparaeldispositivofsicodeaudio,ascomomuestrasPCM registrodeunmicrfonoconectado.

Cargarunamsica
Lasmsicassepuedenalmacenardeformainternaenelproyectoqueestamosdesarrollando oenunarutafija(porejemploparaponercomomsicaunsonidostandarddelsistema) ParacargarunamsicaenmemoriadebemosinstanciarunobjetodelaclaseMusicpasandole comoparmetrounpunteroalficherodeltipoFileHandlenativodejava,delasiguienteforma: Musicmusic=Gdx.audio.newMusic(Gdx.files.getFileHandle("data/8.12.mp3",FileType.Internal))

Enesteejemplolacancin8.12.mp3estaguardadadentrodelacarpetadelproyectodata,por loqueeltipodearchivoleindicamosqueesinterno.FileType.Internal.Enelcasodenopoder abrirelarchivosegeneraunaexcepcinGdxRuntimeException LostiposposiblesdeficherossonlosnativosdeJavadetipoFile.FileType,estosson: ExternalPathrelativoalaraizdelalmacenamientoSDdeandroid. InternalPathrelativoalarutadelaaplicacionandroidodichodeotromodorelativoal directorioraizdelaaplicacincreada. ClasspathElpathdelficheroestaenunarutarelativaalaraizdelClashpath AbsoluteElpathestaindicadodeformaabsoluta,indicandoelfilesystemquelo contiene.

Reproducirunamsica
Parareproducirunamsicacomohemosmencionadoantesbastaconllamaralmetodoplay() desdeelobjetoinstanciadodetipoMusic. Vamosaverlomasclaramenteconunpequeoejemplodecomodejarunamsica reproducindoseenunbucleinfinito dondelamsicaesunarchivomp3almacenadoenunacarpetaquehemosllamadodata Musicmusic=Gdx.audio.newMusic(Gdx.files.getFileHandle("data/8.12.mp3",FileType.Internal)) music.setLooping(true) music.play()

Descargarunamsica
Unavezquenoqueramoshacerusodelsonidosernecesariodescargarlodememoria. Paradescargardememoriaunsonidotanslosernecesariollamaralmtododisposedel objeto.Estopodemoshacerloennuestroapartadodestinadoaladescargadedatosobienen elmtododisposedelaaplicacin,comoyahemosvistoenelapartadodeciclodevidadela aplicacin. Enelcasodequelamsicaestuvieraenunbuclelolgicoespararlaantesdeeliminarlapor seguirunasecuencialgica,yenparteporestticadelaprogramacin,estossehace llamandoalmtodostop,portantoelordenseria: music.stop() music.dispose()

Navegandoentrepantallasdeljuego

GameextiendedeAplicationListenerparaimplementarmultiplespantallas. UnaScreenesunapantalladeunjuego.Opciones,Menuprincipal,nivel1,nivel2,creditos,etc. Paracambiarentrepantallasharemos: ScreengameScreen=newGameScreen(game) game.setScreen(gameScreen) return esdecir,creamoslascreen,yselaseteamosalainstanciadeljuego.

Vibracin
Paraagregarlealjuegodelarkanoid(eldelvideotutorial)quevibrealchocarlabarritaconla paredizquierdapormodificamoselmtodorender()delaclaseGameScreen. try{ Gdx.input.vibrate(200) System.out.println("vibra") }catch(Exceptione){ System.out.println(e) }

Cmaras
OrthographicCameraguiCam guiCam=newOrthographicCamera(10,15)//definiciondenuestrapropiamedidadeljuego

10x15metros:Estoesporquedividmoslos320x480pixelesenbloquesde32px. guiCam.position.set(10f/2,15f/2,0)//Dondeestaramirandolacamara

Animacin
Crearemosunpersonajedeunpersonajeyharemosunaanimacin,esdecir,quecamine comosiseestuvieramoviendo.
Aquseveelejemplodeunhombrecorriendo.Laimagensepuedevercomounamatrizdeimgeneslas cualessevanarecorrercondosciclosysevanapasarporimagenaunvector. Cuandosecrealaanimation,selepasaporparametrolavelocidadconlaquesemueveelframeyelvector deimgenes. PorltimocuandoseinvocaalspriteBatch.draw()seleindicaelvectorquecontienelasimgenes,la posicindeXydeYendondesequierendibujarlasmismas.

UsaremoslasiguienteImagencomosecuencia:

Copiaremosestaimagen,enlacarpeta/imagendelproyecto Creamosunaclasequeimplementescreenanimacin:

publicclassAnimationScreenimplementsScreen{ Gamegame staticfinalfloatWORLD_WIDTH=5 staticfinalfloatWORLD_HEIGHT=3.3f privatestaticfinalintFRAME_COLS=6//#1 privatestaticfinalintFRAME_ROWS=5//#2 OrthographicCameraguiCam SpriteBatchbatcher AnimationwalkAnimation//#3 TexturewalkSheet//#4 TextureRegion[]walkFrames//#5 SpriteBatchspriteBatch//#6 TextureRegioncurrentFrame//#7 floatpositionX=1 floatstateTime//#8 Inicializamosenelconstructorloreferentealaanimacin: publicAnimationScreen(Gamegame){ this.game=game batcher=newSpriteBatch() guiCam=newOrthographicCamera(WORLD_WIDTH,WORLD_HEIGHT) guiCam.position.set(WORLD_WIDTH/2,WORLD_HEIGHT/2,0)

walkSheet=newTexture(Gdx.files.internal("images/man.png"))//#9 TextureRegion[][]tmp=TextureRegion.split(walkSheet, walkSheet.getWidth()/FRAME_COLS,walkSheet.getHeight() /FRAME_ROWS)//#10 walkFrames=newTextureRegion[FRAME_COLS*FRAME_ROWS] intindex=0 for(inti=0i<FRAME_ROWSi++){ for(intj=0j<FRAME_COLSj++){ walkFrames[index++]=tmp[i][j] } } walkAnimation=newAnimation(0.025f,walkFrames)//#11

spriteBatch=newSpriteBatch()//#12 stateTime=0f//#13 }

Ahoraenelrenderhacemos: Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT)//#14 stateTime+=Gdx.graphics.getDeltaTime()//#15 currentFrame=walkAnimation.getKeyFrame(stateTime,true)//#16 spriteBatch.begin()

spriteBatch.draw(currentFrame,positionX,2)//#17 spriteBatch.end() update(delta) (16:obtenemoselframecorrespondienteenbasealtiempoquellevamoviendose) MetodoUpdate publicvoidupdate(floatdelta){ positionX+=0.1f }

Sinecesitanelcdigofuentecompletodeesteejemplo:javi10823@gmail.com

Manualdebuenasprcticas
TODO:Introduccinacosasparasermseficientesylimpiosescribiendocdigo. Paraserlimpiosyeficientesescribiendocdigoesimportantetenerencuentavariascosas comocreacionesdemtodosparasimplificarelcdigo,nohacercondicionesmuylargaso muchosbuclesanidados,estossonsoloalgunosejemplos,ahoraexplicareunpocomas extensoalgunosdelospuntosmencionadosanteriormente. Definirvariablesalprincipiodelaclase/mtodo,deestaformasetieneunaccesorpidoaesa variableysabemosdeunsimplevistazoqueatributostiene. Respetarlasreglasdenomenclaturadeloslenguajestalescomolossiguientes: Losnombresdelasvariablescomienzanconletrasminsculas,yencasodecontener variaspalabrasselepondrmaysculaalaprimeraletradecadapalabraapartirdelasegunda palabra. Losnombresdelosmtodosseescribirnenminsculasiguiendolamismareglaque elnombradodelasvariables.Porlogeneral,elnombredeestossuelenserverbos. Lasvariablesfinalesseescribirnintegramenteenmayscula,separando,sifuera necesario,diferentespalabraspormediodelcarcterguinbajo_ Elnombredelospaquetesserealizarintegramenteenminscula,aunquecontenga variaspalabras. Elnombredelasclasescomenzarconlaprimeraletraenmaysculaylassiguientes enminscula.Encasodecontenervariaspalabrasselasdistingirponiendomaysculala primeraletradecadapalabra. Tabularelcdigoparaunamayorcompresindelmismo.Enjava,adiferenciadeotros lenguajesdeprogramacincomopuedeserpython,noesnecesarioquelaslineasdecdigo estntabuladasparaperteneceraunmtodo/funcin/claseyaqueparaestoseutilizanlas llaves,perodeestaformasehaceelcdigomslegible. Realizarunestudioquerelacioneeltiempodeprocesamientovsalmacenamiento.En ocasionesunalistapuedeestarmuybienparaalmacenardatos,perounarraytieneunacceso inmediatoaldatocontenido. Sivesqueprogramandoescribesvariasveceslomismo,creacionesdeobjetoquevaranmuy poco,comprobacindeunobjeto,cambiarunobjeto,lomasprobableesquepuedascambiarlo porunafuncinounmtodo.Porejemplo: Crearuncasillerode10x10,estoimplicadibujarocrear100casillas,escribiras 100veces: batcher.draw(casilla,posX,posY,1,1)

Yestonoeseficiente,peropodrasdibujarlocon: for(inti=1i<11i++){ for(intj=1j<11j++){ batcher.draw(casilla,i,j,1,1)} } } Usarswitchcasesivesquecomparaslomismodentrodemuchosif,teniendoen cuentaqueuncasesolocompruebaintegeryenumerados. Antesdecrearunmtodocomprobarquenoexisteya,oparecido,paraquepuedas modificarlo,siemprequealmodificarlonohayanadadependiendodeel. Usarvariosforanidadoshacequeelprogramaseralenticemucho,yaquepodemos encontrarnosconrecorridosconmuchoselementosylosrecorretodosporloqueralentiza muchoynoeseficiente,estonosueleaparecermuchoperohayquetenercuidadoalahorade meterforwhileodo,unodentrodeotrosyaquepuededarproblemas Otradelascosasquehayquetenerencuentaalahoradeprogramaresserlimpioyno escribircomosenosvanocurriendolascosasydejarloas,yaquesidespusalguienquiere usarnuestroocdigoosimplementesabercomofuncionaleseraimposible,poresocuando estemosprogramandohayqueintentardejarlineassimples,oexplicarconcomentarioscuando veamosquealgopuedequenoseentienda. Loquetambinayudaraalahoradelalimpiezaydelaclaridadseranlaclases,lomas importanteenelcasodelaprogramacinorientadaaobjetos.Siemprequevallasautilizarun objetoquevayaatenermasdeunapropiedadseutilizanclases.Algunosejemplos: Pelotaenunespacio:Ademsdesunombretendrunxeyindicandosuposicin. Personaje:Ademsdesunombrepuedetenersuposicinindicadaconxey,un inventarioguardadoenunarray,ocualquiercosa. Enestosyenmuchosmaslacreacindeunaclaseeslomejor,cuandoveasqueestas creandodosvariablesparaguardarinformacinsobreunobjetodentrodeunaclase seguramentepodrsinstanciareseobjetodesdeotraclaseyseramasclaroqueponiendo tantosatributos.

Separarlalgicadelapresentacin
Conlgicanosreferimosatodaslascomprobaciones,modificacionesocreacionesquese hacenantesderenderizar,yaqueelprocesoderenderizadosoloyaeslentosimetestambin todalalogicaaraqueeljuegosealento,porestoesrecomendablehacerloenunaclaseaparte. Parahacerlapartelgicabastaconcrearunclaseapartedelrenderizadodondecomprobemos loquehagafaltaantesdepintarenpantalla.Porejemplo: Cambiarlavelocidaddeunapelotaalchocarconunapared: //Choqueenparedizquierda if(ball.position.x0.25<1){ ball.position.x=1+0.25f ball.direction.x=ball.VELOCITY } Comprobarelvalordeunacasillaparapintarladeuncolordiferente: publicAtlasRegioncasilla(intx,inty){ switch(matriz[x][y]){ case0:returnAssets.casillaGbreak case1:returnAssets.casillaBbreak case2:returnAssets.casillaRbreak case3:returnAssets.barcobreak default:returnAssets.barco2 break } } Actualizarvaloresdelasvariables. Enresumentodoloquenoseadibujarenpantallaydebaejecutarsesiempresehadeponer fueradelrenderizado,peroteniendoencuentaqueelrenderlodebellamar,sihicieramosla partelogicaenunaclasellamadaWorlddeberiaquedaralgoparecidoaesto: publicclassWorld{ //atributosinternos //constructor publicWorld(){

initialize()//metodointerno,abajocreado. } //inicializarvariablesolimpiar publicvoidinitialize(){ } //actualizacion publicvoidupdate(){ //aquideberirtodoloqueformapartedelalgicaparaelrenderizadodela pantalla,teniendoencuentaquehayquellamarlodesdeelrender,queseelpuedepasarlos parmetrosquesenecesiten } } PuedehaberdistintosWorld,ypuedeusarseenlaspantallasquesenecesiten,notieneporque sersolodeuna. ParausarelWorldhayquellamarlodesdeelrender,peroantestienequehaberunobjeto desdeelquellamarlo,queseracreadoenlaclasedelapantalla,aquiunejemplo: publicclassGameScreenimplementsScreen{ Worldworld //Atributos publicGameScreen(){ this.world=newWorld()//estollamaalcontructor,quealavezllamaalinizialite. //inicializaciondeatributos. } @Override publicvoiddispose(){ } @Override

publicvoidhide(){ } @Override publicvoidpause(){ } @Override publicvoidrender(floatdelta){//deltaeseltiempotranscurridodesdelaultimallamada porsilalogicalonecesita. World.update()//aquiactualizamoslalogicadeljuego. //Pintarimgenes. } @Override publicvoidresize(intwidth,intheight){ } @Override publicvoidresume(){ } @Override publicvoidshow(){ } }

PginasparaDesarrollodeJuegos
DescargarSonidos
http://www.mysoundfx.com/

Musicaparadarambienteatujuego
http://pro.jamendo.com/es/

TutorialcreacinSpritesAnimadasdesdecero
http://ilovepixel.net/tutorial.html

2dGameArtForProgrammers
http://2dgameartforprogrammers.blogspot.com/

CrearunpersonajeparaAnimacin
http://2dgameartforprogrammers.blogspot.com/2011/10/creatinggamecharacter.html

Caras
http://2dgameartforprogrammers.blogspot.com/2011/11/creatingbasicface.html

Fondos http://2dgameartforprogrammers.blogspot.com/2011/10/morefunwithgradients.html

Solucindeproblemas
TODO:Sedescribenlosproblemasquemspuedenaparecerjuntoconsussoluciones.

You might also like