Programación de Videojuegos en Android Con libGDX PDF

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 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
publicvoidpauhttp://2dgameartforprogrammers.blogspot.com/se(){
}

@Override
publicvoidrender(floatdelta){//deltaeseltiempotranscurridodesdelaultimallamada
porsilalogicalonecesita.
World.update()//aquiactualizamoslalogicadeljuego.
//Pintarimgenes.
}

@Override
publicvoidresize(intwidth,intheight){
}

@Override
publicvoidresume(){
}

@Override
publicvoidshow(){
}

PginasparaDesarrollodeJuegos

WikideLibGDXenespaol
https://github.com/Jackgris/wikiLibGDX_es

DescargarSonidos
http://www.mysoundfx.com/

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

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

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

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.

También podría gustarte