Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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.
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.
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.
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
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
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.
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
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.