Sie sind auf Seite 1von 50

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

9u
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.

CrearunproyectoJAVAnuevoTitanium:Titanium:
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.
packagecom.libgdx.holalibgdx

importandroid.os.Bundle

importcom.badlogic.gdx.backends.android.AndroidApplication
importcom.libgdx.holalibgx.HolaLibgdx

publicclassHolaLibGdxActivityextendsAndroidApplication{
/**Calledwhentheactivityisfirstcreated.*/
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState)
//Acainicializamosalappdeescritorio.
initialize(newHolaLibgdx(),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:
TextureRegion()
Construyeunaregionsintextutanicoordenadasdefinidas.Sepodrandefinirdespues
empleandolosmtodosdelaclase.
TextureRegion(Texturetexture)
Construyeunaregiondetamaoespecificadoenlatextura.
TextureRegion(Texturetexture,floatu,floatv,floatu2,floatv2)

TextureRegion(Texturetexture,intwidth,intheight)
Construyeunareginconconlascoordenadasdelatexturayelanchoyaltoespecificado.
TextureRegion(Texturetexture,intx,inty,intwidth,intheight)
Defineunateturaespecificandoelpunto(x,y)deorigenyeltamaodelarea(ancho,alto)
TextureRegion(TextureRegionregion)
Construyeunareginconlamismatexturaycoordenadasquelareginpasadacomo
parmetro.
TextureRegion(TextureRegionregion,intx,inty,intwidth,intheight)
Construyeunareginconlamismatexturaycoordenadasquelareginpasadacomo
parmetro.
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.barco2break
}
}
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.

Das könnte Ihnen auch gefallen