Sei sulla pagina 1di 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

9u

IntroduccinalibGDX


LibGDXesunframeworkmultiplataformadedesarrollodejuegosparaWindows,Linuxy
Android.EstescritoenJavaconunamezcladeC/C++paradarsoporteyrendimientoa
tareasrelacionadasconelusodelafsicayprocesamientodeaudio.

LibGDXpermitegenerarunaaplicacinensuPCyutilizarelmismocdigoenAndroid,de
estamaneraelprocesodepruebasydepuracinserealizadeformamsrpidaycmoda
yaqueelPCesmuchomsrpidoqueeldispositivoAndroid.
ConLibGDXnosaseguramosdequelamismaaplicacinpuedefuncionarcorrectamenteen
diferentesdispositivos.

LibGDXestcompuestoporunaseriedecomponentesdeserncomunesatodaslas
aplicaciones.

MarcodeAplicacin ,quemanejarelbucleprincipalyademsestarencargadodelciclo
devida,esdecir,loseventosdecreacin,destruccin,pausayresumedelamisma.

Uncomponentede Grficos quenospermitirgestionarlarepresentacindeimgenesy


objetosgrficosenlapantalla.

Uncomponentede Audio ,quenosfacilitarelaccesoalossonidosymsicadela


aplicacin.

Uncomponentedede EntradaySalida paraleeryescribirlosdiferentesficherosdedatos


comoporejemplo,imgenes,archivosdeconfiguracin,sonidos,msica,texturas,...

Uncomponentede Entrada quegestionaralaentradaatravsdelteclado,pantallatcilo


acelermetro.

Adicionalmentepodramosampliarlagamademdulosconotrosdosms.

Math,permitelagestinrpidadeclculosmatemticosorientadosaldesarrollode
videojuegos.

Physics,quebsicamenteesunwrapperdeBox2Dypermitecontrolarlagestinde
colisiones.

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.

Traspulsaren
Download
yaslonosquedadescargarlaltimaversindelalibrera.

CrearunproyectoJAVAnuevoTitanium:Titanium:
AunqueelobjetivofinalesqueeljuegofuncionesobreAndroid,trabajaremosconun
proyectoJAVAqueunavezterminadoseportaraAndroid.

ParacrearunproyectoJAVAenEclipsesimplementeenelmenvamosa File>New>
JavaProject.Ledamosunnombrealproyecto(enestecasoDemo1).Elegimosla ruta
dondesecrearenmemoriayledamosa Finish
.

Unavezcreadoelproyectoelsiguientepasoseraadirlalibrera.Paraellounabuena

prcticaescrearundirectoriodentrodelproyectodondeincluirlaslibrerasqueusemos.
ParaelloclickderechosobrenuestroproyectoyNew>Folder .Ennuestroejemploesta
carpetalallamaremos libs
.

Unavezcreadaestacarpeta,simplementetendremosqueaadiralamismaloque
necesitamosparaesteproyecto.Paraaadir,nosvamosaldirectoriodondehemosguardado
lalibreradescargadaenelapartadoanteriorypodemosarrastrarocopiarlosarchivosque
necesitamos(enlaimagen).

Nosquedaraelproyectodeestaforma:


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

Otrabuenaprctica,aunquenonecesariaesaadirlainformacincontenidaenelJavadoc
delalibrera.Elobjetivodeestoesquecuandosemuestrelaayudaemergentedeeclipse
veamoslainformacincontenidaenelJavadocdelalibrera.

ParaellohacemosclickderechosobreelproyectoyenelmencontextualBuildPath>
ConfigureBuildPath... trasloquesenosmuestralosiguiente:

Enestaventanadesplegamosgdx.jarytalcomoseveenlaimagenseleccionamosJavadoc
location.Unavezhechoestopulsamossobre
Edit...

Pulsamosen Browse...
ybuscamoslalocalizacindelJavadocqueseencuentraen
libgdxnightly>docs>api .Unavezseleccionadoestedirectoriopulsamossobre
Ok para
confirmarelcambio.Yyatenemosestacaractersticahabilitada.

UnavezpreparadoEclipseynuestroproyectoJAVAyapodemosempezaratrabajar.

Loprimerosercrearlaclaseprincipaldeljuego,queserlaencargadademanejary
controlartodoloqueocurraeneljuego.

Paraelloclickderechosobresrc>New>Class .

Creamoslaclaseenelpaquetecom.desarrolladoresandroid.libgdx.demo1

Elnombredelamismaes
Demo1Game
EstanuevaclaseheredardeGame( com.badlogic.gdx.Game ).

Unavezcreadalaclaseprincipaldelproyecto,crearemoselpuntodeentradaparala
ejecucindelaaplicacinJAVA.Unaclasequenospermitirlanzareljuego.

Paraellocreamosunaclasequecontengaelmtodo main:

Nombredelaclase:
Demo1Desktop

Mismopaquetequelaclaseprincipal.
Seleccionamoslaopcinpublicstaticvoidmain(String[]args)

Nosquedaraelproyectodelasiguienteforma:

ParapoderlanzareljuegoaadimosenlaclaseDemo1Desktoptenemosqueaadirlo
siguiente:

new JoglApplication( newDemo1Game(), "Demo1"
,320,480,
false
)

Losparmetrosindicanlosiguiente:

new Demo1Game().InstanciadelaclasequeimplementaGame

"Demo1" .Queeselttulodelaaplicacin.
320.Anchoenpxeles.
480.Altoenpxeles.

false .ParaindicarquenoqueremosutilizarOpenGLS2.0enestecaso.Porloquese
utilizarel1.1

Unavezhechoestoyatenemosunjuegoquenohacenadayquepodemoslanzarcomo
aplicacinJAVA.

Paralanzarlotenemosquehacerclickderechoenelproyectoy RunAs>JavaApplication
Unavezhechoestonossaldrunaventanaparaseleccionarelpuntodeentradadela
aplicacinqueennuestroejemploes Demo1Desktop.java

Elresultadodelaejecucinserunapantallanegraconlaresolucinindicada.

PortarelproyectoJAVAaunproyectoAndroid

AhoracrearemoselproyectoparacompilarloenAndroid.Paraefectospracticosusareun
ejemploqueyoyatena.HechoenescritoriollamadoHolaLibgdx.

11.Crearcarpetalibsdentrodelproyectoyponerlelassiguienteslibrerasdelasque
descargamosincluyendoesascarpetas:

Importante!"SEDEBENINCLUIRLASCARPETASarmeabiyarmeabiv7acomoseveenla
imagen.Estascarpetasvienenenlaslibrerasquedescargamos"

12.Referenciamoslaslibrerascopiadas.Clickderechoalproyecto/buildpath/configure
buildpath...

13.Antesdecerraresapantallaanterioriralapestaaprojectyadjuntarlelareferenciaal
proyectodeescritorio.


12.ModificarlaActivityprincipal"HolaLibGdxActivity"paraquenoextiendadeActivitysino
de
AndroidApplication .(crt+shift+o)pararesolverlosimportsnecesarios.
package com.libgdx.holalibgdx

importandroid.os.Bundle

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

public class

HolaLibGdxActivity extends

AndroidApplication {
/**Calledwhentheactivityisfirstcreated.*/

@Override

public
voidonCreate(BundlesavedInstanceState){
super
.onCreate(savedInstanceState)
//Acainicializamosalappdeescritorio.
initialize(new

HolaLibgdx false
(), )
}
}

Deberaquedarnosas.
13.Loejecutamosenelemulador.



Desbloqueamoseldispositivoenelemulador.


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

CiclodevidadeunaaplicacinlibGDX
Esteapartadodescribecmoseestructuraunaaplicacinlibgdx.

LAAPLICACION

Eselprincipalpuntodeentradaparacualquieraplicacinlibgdx.LainterfazApplication
determinalaplataformaylosgraficosdefondoquesernutilizadosporlaaplicacin.La
interfaztambinproporcionalosmtodosparaaccedera grficos ,
audio,
archivosde
entrada y
mdulosdeE/S .Tambindaaccesoaunmdulode Logging elcualfuncionaen
todaslasplataformas.

LibGDX escompatibleactualmentecondosbackendsdeaplicacionesdeescritorio(lwjgly
JOGL)yotraparaAndroid.

Paracrearunaaplicacin libGDX ,sehadeimplementarlainterfazApplicationListener


primero.

APPLICATIONLISTENER

ApplicationListenereselresponsabledelainicializacindelaaplicacin,laactualizacindel
estadodeljuego(esdecir,lalgicadeljuego),renderizacindelaimagen,pausadodel
juego,guardarelestadoylaliberacindelosrecursosalsalirdelaaplicacin.

Estambinellugardondeloseventosdelciclodevidasonmanejados.Cadaaplicacin/
juego,sinimportarelbackendy/oplataformadedestinotendrqueimplementarlainterfaz
ApplicationListener .Laimplementacinesexactamentelamismaparatodaslas
plataformas.

Portanto,ApplicationesresponsabledelcircuitodejuegoyApplicationListener esellugar
dondeseimplementalalgicadeljuego.

Laimplementacindelainterfaz ApplicationListener

Loseventosquesondesencadenadosporlosenlaaplicacindelciclodevidatalcomose
describe:

create():Sellamaunavezcuandosecrealaaplicacin.

resize(intwidth,intheight): Sellamaaestemtodocadavezquelapantalladeljuego
cambiasutamaoyeljuegonoestenelestadodepausa.Tambinselellamaslouna
vezjustodespusdelmtodocreate().Losparmetrossonlanuevaanchurayalturadela
pantalla.

render(): Mtodollamadoporelbucledeljuegodelaaplicacincadavezqueserenderiza.
Laactualizacindeljuegotambintienelugaraquantesdelarepresentacinreal.

pause(): Elmtododepausase llamajustoantesquesedestruyalaaplicacin.EnAndroid



sellamacuandoelbotndeiniciosepresionaohayaunallamadaentrante.Enelescritorio
sellamajustoantesde dispose()alsalirdelaaplicacin.Esunbuenlugarparaguardarel
estadodeljuegoenAndroid,yaquenosegarantizaqueseareanudado.

resume(): EstemtodoesllamadosloenAndroid,cuandolaaplicacinrecibeelfoco.Enel
escritorioestemtodonoserllamadonunca.
dispose(): Selellamacuandolaaplicacinsedestruye.Esprecedidoporunapausa().

Ciclodevidadeunaaplicacion

Losmtodosantesmencionadossonprovocadosporlaaplicacindurantesuciclodevida.

Elsiguientediagramamuestralasdiferentesfasesporlasquepasaunaaplicacin
libGDX
:

Grficos
ElmdulodegrficosesunresumendelacomunicacinconelGPUyproporcionamtodos
deconvenienciaparaobtenerlasinstanciasdeOpenGLES.Seencargadetodoelcdigo
repetitivonecesariosparahacerseconelejemplodeOpenGLyseocupadetodaslas
implementacionesproporcionadasporelfabricante.
Dependiendodelhardwaresubyacente,loscontenedorespuedenseropuedennoestar
disponible.
Elmdulodegrficostambinproporcionamtodosparagenerarmapasdepixelsytexturas.
EnelsiguientecdigopodemosvercmoobtenerunainstanciadelaAPIOpenGL1.0:

GL10 gl
=Gdx
.
graphics
.
getGL10
();

Elmtododevuelveunainstanciaquepuedeserusadaparadibujarenlapantalla.Enel
casoquelaconfiguracindehardwarenoseacompatibleconOpenGLES1.0,devuelvenull.

Elsiguientefragmentodecdigoborralapantallaylapintaderojo:

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

TexturaseInterpolacin

Texture esuna"imagen"enlamemoriadelchipgrfico(lasimgenesendiscosecargarn
enestazonadememoria).EnOpenGLelanchoyaltodeunatexturatienequeserpotencia
de2(...32,64,128,256,512,1024,etc).Aunqueenlosejemplossedefinenlatextura
cuadrada,notieneporquseras.Puedestenerunatexturade128x32,32x256,etc.

Porejemplo,elHTCG1soportacomomucho,unatexturade1024x1024(Aunquepuedes
tenermsdeunatexturaalavez).Intentarutilizartexturasmsgrandesenestedispositivo
provocarnerroreseneljuego.Larecomendacinesquenopasesdelvalor1024para
establecerelanchooaltodetustexturas.

Unparmetromuyimportantequehayqueindicaralahoradecrearunobjeto Textureesun
valor
TextureOptions queindicarqumtodoseutilizarpararedimensionarlasimgenes
quetenemosdentrodelatextura.(Paranocomplicarlascosas,dejaremosesaexplicacin).

Sepuedenelegirlossiguientesmodos:

NEAREST :
Laimagenaparecerpixelada.Esmuchomsrpido,perolaimagentienemenorcalidad.

Original:

Ampliadacon
NEAREST
:

BILINEAR :
Laimagenaparecemsdifuminada.Esunpocomslento,peronoverspxelesenla
misma.

Original:


Ampliadacon
BILINEAR
:

REPEATING:
Silatexturaesde32x32ytienequedibujarsesobreunasuperficiede64x64,veremos4
imgenesrellenandoesehueco.Comosipusiramoslamismaimagenunayotravez
repitindola.EstemodonofuncionaconlosSpritesnormales,asqueporahora,vamosa
ignorarlo.

Cuandoutilizasimgenesquecontienenvaloresalpha(transparencia)puedesencontrarte
conqueteaparezcan"halos"querodeanlosbordesdelasmismas.Aquesdondeentraen
juegolatcnica"
premultipliedalpha
",lacualcorrigeeseproblema.Intentaevitarutilizar
"premultipliedalpha"amenosqueveascosasrarasenlosbordesdetusimgenes,como
sobrasohalosresplandecientesquenodeberanestar.

Siquieresunainterpolacinbilineal,estableces:

TextureOptions .
BILINEAR

Siquieresunainterpolacinbilinealcon"
premultipliedalpha",estableces:

TextureOptions .
BILINEAR_PREMULTIPLYALPHA

Lomismoocurresiquieresinterpolacin NEAREST conosin"premultipliedalpha


".Escosa
tuyaexplorarlosvaloresquepuedeselegirdeTextureOptions .

Parafinalizar,decirque
TextureOptions .
DEFAULT =
TextureOptions .
NEAREST_PREMULTIPLYALPHA

TextureRegion

Defineunrearectangulardeunatextura.Elsistemadecoordenadasutilizadotienesu
origenenlaesquinasuperiorizquierdaconelejexapuntandohacialaderechayelejey
apuntandohaciaabajo.
LastextureRegionsonempleadasparacrearnuevasimagenes(otambinllamadosactores
detipoimagen)asociadasaunreadeunatextura.

Tienevariasopcionesparaconstruirunobjetodeestaclase,sonlossiguientes:

()
TextureRegion
Construyeunaregionsintextutanicoordenadasdefinidas.Sepodrandefinirdespuesempleando
losmtodosdelaclase.

TextureRegion
( texture)
Texture
Construyeunaregiondetamaoespecificadoenlatextura.

TextureRegion
( texture,floatu,floatv,floatu2,floatv2)
Texture

TextureRegion
( texture,intwidth,intheight)
Texture
Construyeunareginconconlascoordenadasdelatexturayelanchoyaltoespecificado.

TextureRegion
( texture,intx,inty,intwidth,intheight)
Texture
Defineunateturaespecificandoelpunto(x,y)deorigenyeltamaodelarea(ancho,alto)

TextureRegion
( region)
TextureRegion
Construyeunareginconlamismatexturaycoordenadasquelareginpasadacomoparmetro.

TextureRegion
( region,intx,inty,intwidth,intheight)
TextureRegion
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.libgdxtieneunaclaseTexturePackerqueesunaaplicacindelneade
comandosqueempaquetamuchasimgenesmspequeasen1imgenmsgrande.

TexturePackersebasaenestealgoritmo.Tambintieneunafuerzabruta,elembalaje
devariasmanerasyluegoelegirelresultadomseficiente.

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,mientrasqueelacelermetro
noestdisponible.

Enelfragmentodecdigosiguienteseobtieneeltouchactualdecoordenadassihay
untouchdelcelular(odelratnenelescritorio):

if(Gdx.input.isTouched()){
System.out.println("deentradaseprodujoenx="+x+",y="+y)
}
Demanerasimilaratodoslosmediosdeentradapuedenserconsultadosy
manipulados.

Detectarpulsacionesenlapantallatctil

SedebedifinirunVector,unareaficticiadondesecaptareleventodepulsacindeldedo.
UsamostambienelobjetodeOrthographicCamera,paraconvertirlospixelesennuestra
medidaenmetros.LuegopreguntamossielbotonquecreamosBoundingBoxtieneun
touch.
Yescribimoselcdigoparamanejareseevento.

Audio

LibGDXcuentaconunmdulodeaudioqueofrecedostiposderecursos:Elsonidoyla
msica.
AmbostipossoportanelformatoWAV,MP3yOGG.Tambinofreceaccesoalhardwarede
sonido.

Ladiferenciaentreelsonidoylamsicaesqueelsonidosealmacenaenmemoriayseusa
cadavezquesequierereproduciralgunodeellos,mientrasquelamsicasonstreamsde
sonidoqueestnalmacenadosenficherosyalosqueseaccedecadavezquesequiere
reproduciralgo.

Elsiguientefragmentodecdigoreproduceunficherodemsicadesdeeldiscoconel
volumenalamitad:

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

Sounds

Soundesunaclasedestinadaalareproduccindeunefectodesonido.Lonormalescargar
elsonidodesdeunarchivoamemoriayluegoreproducirloatravsdelmtodo
Sound.play(). Lossonidossongeneralmentecortos,llegandoadurarunospocossegundos
yaquealsercargadosenmemoriapuedenllegaraocupardemasiado,incidiendo
directamenteenelrendimiento.

Cuandoyanovayamosausarmsesesonidosernecesariollamaralmtodo
Sound.dispose() paraliberarmemoriaeneldispositivo.

Cargarsonidos

LosArchivosparalosefectosdesonidolospondremosdentrodeunacarpetallamada data

Paracargarenmemoriaunefectodesonidotanslosernecesariodefinirlocomotipo
Sound yllamaralmtodo Gdx.audio.newSound pasandocomoparmetroelfichero
dentrodeldirectorio
data
.

Elsiguientefragmentodecdigocargaunsonidoenmemoria.

Soundexplosion
explosion=Gdx.audio.newSound(Gdx.files.internal("data/explosion.ogg"))

Puestoqueelsonidoserunacosaqueslosecargarunavezdurantetodalavidadela
aplicacin,haremoslallamadaa newSound ennuestromtododestinadoalacargade
datos.

Reproducirsonidos
Parareproducirunsonidopreviamentecargadoenmemoriatanslosernecesariohacer
unallamadaalmtodoplay
delsonidopasandocomoparmetrounvalorentre0y1que
representarelvolumen.

explosion.play(1)

Descargarsonidos
Unavezquenoqueramoshacerusodelsonidosernecesariodescargarlodememoriaya
queenlosdispositivosmviles,lamemoriaRAMsiguesiendounelementomuyprecidado.

Paradescargardememoriaunsonidotanslosernecesariollamaralmtodo dispose del


objeto.Estopodemoshacerloennuestroapartadodestinadoaladescargadedatosobien
enelmtodo disposedelaaplicacin,comoyahemosvistoenelapartadodeciclodevida
delaaplicacin.

explosion.dispose()

Music
Musiceslaclasedelibgdxparacargararchivosdesonidoennuestrosjuegos derivadela
claseDisposable constadelossiguientesmtodos:
play() Comienzaalacancin,enelelcasodeestarpausadalareanudadondese
quedoyenelcasodequesehubieraparadolacomienzadesdeelprincipio.
pause() Pausalacancin,silacancinnohaempezadoaunoestayaha
finalizado,estemtodoesignoradoalllamarlo.
stop() Paralacancin.Lasiguientevezquesellamealmtodoplay()lacancin
comenzardesdeelprincipio.
isPlaying() Funcinquedevuelveunbooleano,indicandosiesverdadonoquela
cancinestasonando.
setLopping() Admitecomoparmetrounbooleanoparaindicarsiseactivala
funcinloopenlacancin,estafuncinactivalarepeticinindefinidadelamsica,
detalformaquesisellamaalprocedimientoindicandotrue,lacancinserepite
indefinidamentehastaquelaparemosohastaquedesactivemoselloop.
isLopping() Funcinquedevuelveunbooleano,indicandosiesverdadonoquela
cancinestasonando.
setVolume() Varaelvolumendelsonido,admiteporparmetros(01),conun0
seponeensilencioycon1seponeelvolumenalmximo.
getPosition() Funcinquedevuelveunfloatconlaposicindelacancinen
milisegundos
dispose() Eseldestructordelaclase.Esmuyconvenientellamarlocuandonosea
necesarialamusicayaqueconsumememoriadeldisposivo

Libgdx soportalosformatosMP3,OGGyWAV .EsconvenienteusarOggencasitodoslos


casos.
Sinecesitamscontrolsobreeldispositivodeaudio,puedeutilizarel AudioDevice yclases
Audiorecorder quetambinseobtienedela interfazdeaudio .Estasclasespermitenala
salidadelasmuestrasde PCM paraeldispositivofsicodeaudio,ascomomuestras PCM
registrodeunmicrfonoconectado.

Cargarunamsica
Lasmsicassepuedenalmacenardeformainternaenelproyectoqueestamos
desarrollandooenunarutafija(porejemploparaponercomomsicaunsonidostandarddel
sistema)

ParacargarunamsicaenmemoriadebemosinstanciarunobjetodelaclaseMusic
pasandolecomoparmetrounpunteroalficherodeltipoFileHandle
nativodejava,dela
siguienteforma:

Musicmusic=Gdx. audio
.newMusic(Gdx. files
.getFileHandle(
"data/8.12.mp3"
,
FileType.Internal))

Enesteejemplolacancin8.12.mp3estaguardadadentrodelacarpetadelproyectodata,
porloqueeltipodearchivoleindicamosqueesinterno.FileType.Internal.Enelcasodeno
poderabrirelarchivosegeneraunaexcepcin GdxRuntimeException
LostiposposiblesdeficherossonlosnativosdeJavadetipoFile.FileType,estosson:
ExternalPathrelativoalaraizdelalmacenamientoSDdeandroid.
InternalPathrelativoalarutadelaaplicacionandroidodichodeotromodorelativo
aldirectorioraizdelaaplicacincreada.
ClasspathElpathdelficheroestaenunarutarelativaalaraizdelClashpath
AbsoluteElpathestaindicadodeformaabsoluta,indicandoelfilesystemquelo
contiene.

Reproducirunamsica

Parareproducirunamsicacomohemosmencionadoantesbastaconllamaralmetodo
play()desdeelobjetoinstanciadodetipoMusic.
Vamosaverlomasclaramenteconunpequeoejemplodecomodejarunamsica
reproducindoseenunbucleinfinito
dondelamsicaesunarchivomp3almacenadoenunacarpetaquehemosllamadodata

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

Descargarunamsica
Unavezquenoqueramoshacerusodelsonidosernecesariodescargarlodememoria.
Paradescargardememoriaunsonidotanslosernecesariollamaralmtodo dispose del
objeto.Estopodemoshacerloennuestroapartadodestinadoaladescargadedatosobien
enelmtodo dispose
delaaplicacin,comoyahemosvistoenelapartadodeciclodevida
delaaplicacin.
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,selepasaporparametrolavelocidadconlaquesemueveelframeyel
vectordeimgenes.
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,deestaformasetieneunaccesorpidoa
esavariableysabemosdeunsimplevistazoqueatributostiene.

Respetarlasreglasdenomenclaturadeloslenguajestalescomolossiguientes:
Losnombresdelasvariablescomienzanconletrasminsculas,yencasode
contenervariaspalabrasselepondrmaysculaalaprimeraletradecadapalabraapartir
delasegundapalabra.
Losnombresdelosmtodosseescribirnenminsculasiguiendolamismaregla
queelnombradodelasvariables.Porlogeneral,elnombredeestossuelenserverbos.
Lasvariablesfinalesseescribirnintegramenteenmayscula,separando,sifuera
necesario,diferentespalabraspormediodelcarcterguinbajo_
Elnombredelospaquetesserealizarintegramenteenminscula,aunque
contengavariaspalabras.
Elnombredelasclasescomenzarconlaprimeraletraenmaysculaylas
siguientesenminscula.Encasodecontenervariaspalabrasselasdistingirponiendo
maysculalaprimeraletradecadapalabra.

Tabularelcdigoparaunamayorcompresindelmismo.Enjava,adiferenciadeotros
lenguajesdeprogramacincomopuedeserpython,noesnecesarioquelaslineasdecdigo
estntabuladasparaperteneceraunmtodo/funcin/claseyaqueparaestoseutilizanlas
llaves,perodeestaformasehaceelcdigomslegible.

Realizarunestudioquerelacioneeltiempodeprocesamientovsalmacenamiento.En
ocasionesunalistapuedeestarmuybienparaalmacenardatos,perounarraytieneun
accesoinmediatoaldatocontenido.

Sivesqueprogramandoescribesvariasveceslomismo,creacionesdeobjetoquevaran
muypoco,comprobacindeunobjeto,cambiarunobjeto,lomasprobableesquepuedas
cambiarloporunafuncinounmtodo.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,estonosueleaparecermuchoperohayquetenercuidadoalahora
demeterforwhileodo,unodentrodeotrosyaquepuededarproblemas

Otradelascosasquehayquetenerencuentaalahoradeprogramaresserlimpioyno
escribircomosenosvanocurriendolascosasydejarloas,yaquesidespusalguienquiere
usarnuestroocdigoosimplementesabercomofuncionaleseraimposible,poresocuando
estemosprogramandohayqueintentardejarlineassimples,oexplicarconcomentarios
cuandoveamosquealgopuedequenoseentienda.
Loquetambinayudaraalahoradelalimpiezaydelaclaridadseranlaclases,lomas
importanteenelcasodelaprogramacinorientadaaobjetos.Siemprequevallasautilizar
unobjetoquevayaatenermasdeunapropiedadseutilizanclases.Algunosejemplos:
Pelotaenunespacio:Ademsdesunombretendrunxeyindicandosuposicin.
Personaje:Ademsdesunombrepuedetenersuposicinindicadaconxey,un
inventarioguardadoenunarray,ocualquiercosa.
Enestosyenmuchosmaslacreacindeunaclaseeslomejor,cuandoveasqueestas
creandodosvariablesparaguardarinformacinsobreunobjetodentrodeunaclase
seguramentepodrsinstanciareseobjetodesdeotraclaseyseramasclaroqueponiendo
tantosatributos.

Separarlalgicadelapresentacin

Conlgicanosreferimosatodaslascomprobaciones,modificacionesocreacionesquese
hacenantesderenderizar,yaqueelprocesoderenderizadosoloyaeslentosimetes
tambintodalalogicaaraqueeljuegosealento,porestoesrecomendablehacerloenuna
claseaparte.

Parahacerlapartelgicabastaconcrearunclaseapartedelrenderizadodonde
comprobemosloquehagafaltaantesdepintarenpantalla.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,notiene
porquesersolodeuna.

ParausarelWorldhayquellamarlodesdeelrender,peroantestienequehaberunobjeto
desdeelquellamarlo,queseracreadoenlaclasedelapantalla,aquiunejemplo:

publicclassGameScreenimplementsScreen{

Worldworld
//Atributos

publicGameScreen(){

this.world=newWorld()//estollamaalcontructor,quealavezllamaal
inizialite.

//inicializaciondeatributos.

}

@Override
publicvoiddispose(){
}


@Override
publicvoidhide(){
}

@Override
publicvoidpau
http://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.

Potrebbero piacerti anche