You are on page 1of 88

Programacin de un Space Invaders en Java

ndice:
0 - Introduccin 1 - La ventana 2 - Cierre debido 3 - Primeros pegotes sobre a ventana ! - Primeras im"genes # - $ptimi%ando a carga de im"genes & - $ptimi%ando todav'a m"s a carga de im"genes ( - )uc e principa * - Limpiando a basura + - Contro ando e caos 10 - ,"s ento -ue e o.o 11 - /ob e )01er autom"tico 12 - ,edicin de rendimiento 13 - 2eorgani%acin de cdigo Java 1! - 3otogramas 1# - 3otogramas - II 1& - 4 Jugador 1( - Contro ando e .ugador 1* - /isparos 1+ - ,"s disparos - )ombas de 1ragmentacin 20 - /eteccin de co isiones 21 - )arra de estado 22 - Puntuacin 23 - ,uriendo 2! - La vengan%a de os monstruos 2# - 3ondo con scro 2& - 2eaparicin de monstruos 2( - Sonido senci o 2* - Corrigiendo os 1a os de sonido 2+ - Pe-ue5as optimi%aciones

0. Introduccin: 4ste tutoria tiene como ob.etivo mostrar cmo es posib e desarro ar un .uego en .ava con un rendimiento m"s -ue aceptab e6 7dem"s8 e curso i ustra a gunas t9cnicas de Java2/ para conseguir ace eracin gr"1ica -ue no se cubren :abitua mente en muc:os curricu ums 1ormativos ni en ibros o manua es de .ava ;est"ndar; 6 4n ugar de sistema tradiciona de p antear un cdigo 1uente < e=p icar o8 :emos seguido e sistema -ue uti i%amos en os propios cursos internos de P aneta ia8 consistente en desarro ar e programa paso a paso8 como o :ar'a cua -uier programador: desde as primeras 'neas de Java :asta comp etar o8 a o argo de una serie de versiones6 /e esta 1orma -ueda muc:o m"s c aro e por -u9 de cada 'nea de cdigo < su pape dentro de programa6 Sin embargo8 no pretendemos -ue este sistema sea un enga5o para presentar como se constru<e paso a paso < supuestamente sin ninguna tribu acin por e camino un programa idea 8 <a -ue en a rea idad este tipo de 1antas'as no ocurren6 4n ugar de esto :emos pre1erido conservar os errores -ue se pudieran cometer por e camino8 as' como no aspirar a un dise5o per1ecto desde e principio8 sino ir :aciendo e programa < ver cmo podr'amos a1rontar e cambio de ob.etivos o de re-uisitos -ue se puedan p antear en un momento dado6 >e recomendamos -ue sigas este tipo de 1i oso1'a cuando a1rontes tus desarro os6 ?na ve% -ue tengas :ec:o e correspondiente an" isis < mode ado @-ue en este curso vamos a obviarA8 es recomendab e tener o antes posib e a go -ue 1uncione6 Bo esperes a tener 2006000 'neas de cdigo para dar e a ;2un; < ver si a-ue o tiene sentido o se comporta como es debido6 4 tener a go -ue 1unciona te proporciona una base s ida a a -ue vo ver si a g0n cambio -ue :agas estropea as cosas6 4 ob.etivo de curso es desarro ar un .uego en Java de tipo ;Space Invaders; - marcianos por arriba8 nave por aba.o6 4 ob.etivo ir" cambiando8 <a -ue una ve% -ue :emos egado a ese 'mite8 es mu< 1"ci a5adir m"s e ementos interesantes6 3ina mente8 antes de comen%ar es necesario indicar -ue no se trata de un curso de java 8 sino un curso con un ob.etivo espec'1ico6 Si no sabes o -ue es a :erencia8 e po imor1ismo8 o -ue es Crap:ics2/ o J3rame8 entonces este no es tu curso6 Para poder seguir este tutoria son necesarios os siguientes conocimientos b"sicos: Lengua.e Java Conocimientos b"sicos de SDing o 7E> < a .erar-u'a de componentes Co ecciones de Java Librer'a de gr"1icos de Java @Crap:ics2/A

1. La ventana: Lgicamente e primer paso en cua -uier programa de Java es a c ase principa con e punto de entrada a programa6 4 programa crea una ventana SDing @J3rameA < arbitrariamente decidimos -ue e tama5o de a ventana ser" *00 = &006 4 tama5o en s' es irre evante < es buena costumbre dec arar os n0meros como constantes6 Los -ue :a<an estado en nuestros cursos <a saben o mani"ticos -ue somos en cuanto a as reg as de esti o < en particu ar con os itera es desparramados por todo e programa6 Si se dec aran as dimensiones de a panta a como constantes < se programa uti i%ando esas constantes8 posteriormente modi1icar e tama5o es pr"cticamente trivia 4 cdigo 1uente de este primer paso no deber'a suponer ning0n prob ema de entendimiento:

pacFage version01G

Invaders6.ava

11 12 import .ava=6sDing6J3rameG 13 1! pub ic c ass Invaders H 1# pub ic static 1ina int EI/>I J *00G 1& pub ic static 1ina int I4ICI> J &00G 1( 1* pub ic Invaders@A H 1+ J3rame ventana J neD J3rame@;Invaders;AG 20 ventana6set)ounds@0808EI/>I8I4ICI>AG 21 ventana6setKisib e@trueAG 23 L 2# pub ic static void main@StringMN argsA H 2& Invaders inv J neD Invaders@AG 2( L 2+ L
OPu9 tenemos con estoQ ?na simp e ventana -ue adem"s a cerrarse no :ace -ue e programa termine:

2. Cierre debido: 4 siguiente paso consiste en :acer -ue a ventana se comporte como es debido: terminando e programa cuando es cerrada6 La 1orma de :acer o es a tradiciona mediante un gestor de evento EindoDC osing8 con e correspondiente S<stem6e=it@0A en su interior:

Invaders6.ava 1 pacFage version02G 11 12 import .ava6aDt6event6EindoD7dapterG 13 import .ava6aDt6event6EindoD4ventG 1! import .ava=6sDing6J3rameG 1# 1& pub ic c ass Invaders H 1( pub ic static 1ina int EI/>I J *00G 1* pub ic static 1ina int I4ICI> J &00G 1+

20 21 22 23 24 2! 2% 2+ 230 32 33 3! 3#

pub ic Invaders@A H J3rame ventana J neD J3rame@;Invaders;AG ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana.addWindowListener( new WindowAdapter() pub"ic void windowC"osin#(Window$vent e) &'ste(.e)it(0)* , ,)* L pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG L

.. /ri(eros pe#otes sobre "a ventana: 4 siguiente paso -ue necesitamos de 1orma imprescindib e es poder pintar cosas encima de a ventana6 4sto nos genera un prob ema6 Para pintar8 seg0n o -ue conocemos :asta a:ora8 necesitamos sobreescribir e m9todo paint de ;a guien; - de a guna ventana8 o de a g0n pane -6 Sin embargo8 ni a c ase Invaders es una ventana ni tampoco podr'amos :acer nada si o 1uese8 <a -ue a ventana -ue se muestra es otra -ue creamos dentro de constructor de Invaders6 ?na posib e so ucin es :acer descender nuestra c ase Invaders de a c ase Canvas - a c ase ancestro por e=ce encia para os componentes visua es6 Siendo un Canvas8 :eredamos e m9todo paint@A -ue podemos sobreescribir6 OR cmo :acer a asociacin entre nuestra c ase < a ventana -ue estamos mane.andoQ Senci o: siendo Canvas un descendiente de Component8 podemos a5adirnos a pane de a ventana como un componente m"s:

1 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 222 .0

pacFage version03G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J *00G pub ic static 1ina int I4ICI> J &00G pub ic Invaders@A H J3rame ventana J neD J3rame@;Invaders;AG 0/ane" pane" 1 (0/ane")ventana.#etContent/ane()* pane".set3ounds(0404WI56747$I876)* pane".set/re9erred&i:e(new 5i(ension(WI56747$I876))*

.1 .2 33 3! 3# 3& 3( 3* 3+ !0 !1 42 4. 44 4! 4% !( !* !+ #0 #1

pane".setLa'out(nu"")*;;error poner"a co(o co(entario. pane".add(t<is)* ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG

pub"ic void paint(8rap<ics #) #.setCo"or(Co"or.red)* #.9i""=va"( WI567;2>104 7$I876;2>10420420)* , pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG L

4. /ri(eras i(?#enes: Como pretendemos dar a .uego un aspecto a go vistoso8 est" c aro -ue no vamos a poder con1ormarnos con pintar os gr"1icos mediante as :erramientas de Crap:ics2/ de Java6 Por e o os gr"1icos deben ser im"genes e=ternas -ue iremos cargando seg0n va<amos necesitando 4 siguiente paso consistir" en cargar una imagen < mostrar a sobre a ventana6 Para poder tener transparencias sin comp icaciones vamos a uti i%ar para os bic:os im"genes en 1ormato 6gi16 Para cargar a imagen uti i%aremos a c ase ImageI$ 8 e=istente desde e J/S 16! La imagen a cargar se amar" bic:o6gi1 < debe estar en un subdirectorio amado ;res; @recursos en ing 9sA -ue debe co gar de directorio de pro<ecto @pero no de directorio de pa-ueteA6 4s decir8 si a c ase est" en c:Tp aneta iaTcursoT.avaTversion0!TInvaders6c ass8 entonces e subdirectorio de recursos debe estar en c:Tp aneta iaTcursoT.avaTresTA: 4 gr"1ico en concreto es este:

1 11 12 13 1! 1# 1& 1( 1* 20 21

pacFage version0!G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava=6imageio6ImageI$G import .ava=6sDing6J3rameG

22 23 2! 2# 2& 2* 2+ 30 31 32 33 3! 3# 3& 3( 3* 3+ !0 !1 !2 !3 !# 4% 4+ 442 !0 !1

import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J *00G pub ic static 1ina int I4ICI> J &00G pub ic Invaders@A H J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808EI/>I8I4ICI>AG pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG L pub ic )u11eredImage oadImage@String nombreA H @AL ur"1nu""* tr' ur" 1 #etC"ass().#etC"assLoader().#etAesource(no(bre)* return I(a#eI=.read(ur")* , catc< ($)ception e) &'ste(.out.print"n(BCo se pudo car#ar "a i(a#en B D no(bre DB de BDur")* !2 &'ste(.out.print"n(B$" error 9ue : BDe.#etC"ass().#etCa(e()DB BDe.#etEessa#e())* &'ste(.e)it(0)* return nu""* , , pub ic void paint@Crap:ics gA H )u11eredImage bic:o J oadImage@;resUbic:o6gi1;AG #.drawI(a#e(bic<o4 404 404t<is)* L pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG L

!. !4 !! !% !#+ &0 &1 &2 &! &# && &(

Se puede ver -ue a gestin de errores es ine=istente: cua -uier 1a o en a carga de a imagen :ace -ue e programa se cierre6 Intentaremos me.orar esto posteriormente6 >ambi9n es interesante se5a ar -ue en ugar de poner una ruta de arc:ivo ;a peda ; uti i%amos getC ass@A6getC assLoader@A6get2esource@666A8 -ue permite obtener una ?2L apuntando a un subdirectorio re ativo a sitio de cua 1ue cargada a c ase6 4sto permite -ue nuestro

programa 1uncione de 1orma transparente si uego decidimos convertir o en app et o en programa autoe.ecutab e de Java uti i%ando EebStart6 4 resu tado de este programa es e siguiente:

!. =pti(i:ando "a car#a de i(?#enes: Si <a :as programado en Java8 te :abr"s dado cuenta -ue a 1orma de cargar a imagen es rea mente pat9tica - a :acer o dentro de propio paint8 o -ue estamos :aciendo es cargar a imagen cada ve% -ue se redibu.a a ventana8 a go no mu< :"bi precisamente6 Se podr'a pensar -ue o idea es :acer o es cargar a imagen en e constructor8 pero pensemos por un momento -u9 ocurrir'a si por e.emp o nuestro .uego es un app et < tenemos un centenar de im"genes de distintos bic:os < nive es6 7 descargar e usuario as c ases Java de .uego8 se -uedar'a esperando una eternidad a -ue e programa descargase todas as im"genes8 -ue rea mente a o me.or no se egan a uti i%ar por-ue e usuario nunca ega a a can%ar e nive en e -ue aparecen6 Por este motivo se sue e uti i%ar una t9cnica amada carga tard'a8 -ue consiste en cargar a imagen una 0nica ve%8 pero ap a%ar este instante :asta e momento en -ue rea mente se :ace necesario visua i%ar esa imagen Invaders6.ava 1 pacFage version0#G 11 12 import .ava6aDt6CanvasG 13 import .ava6aDt6/imensionG 1! import .ava6aDt6Crap:icsG 1# import .ava6aDt6event6EindoD7dapterG 1& import .ava6aDt6event6EindoD4ventG 1( import .ava6aDt6image6)u11eredImageG 1* import .ava6net6?2LG 1+ 20 import .ava=6imageio6ImageI$G 21 import .ava=6sDing6J3rameG 22 import .ava=6sDing6JPane G 23 2! pub ic c ass Invaders e=tends Canvas H 2# pub ic static 1ina int EI/>I J *00G 2& pub ic static 1ina int I4ICI> J &00G 2pub"ic 3u99eredI(a#e bic<o 1 nu""* 30

31 32 33 3! 3# 3& 3( 3* 3+ !0 !1 !2 !3 !! !# !( !* !+ #0 #1 #2 #3 #! ## #& #( #* &1 %2 %. &! &# &( &* &+ (0

pub ic Invaders@A H J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808EI/>I8I4ICI>AG pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG L pub ic )u11eredImage oadImage@String nombreA H ?2L ur Jnu G tr< H ur J getC ass@A6getC assLoader@A6get2esource@nombreAG return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G L L pub ic void paint@Crap:ics gA H i9 (bic<o11nu"") bic<o 1 "oadI(a#e(Bres;bic<o.#i9B)* g6draDImage@bic:o8 !08 !08t:isAG L pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG L

%. =pti(i:ando todavFa (?s "a car#a de i(?#enes: 4 paso anterior reso v'a e prob ema de a carga de im"genes8 pero tiene una pinta bastante 1ea <a -ue es un engorro tener -ue estar comprobando todo e rato en todas as posib es situaciones donde nos pueda surgir a necesidad de uti i%ar una imagen si est" cargada o no6 Para evitar esto8 vamos a encapsu ar esto en una rutina a a -ue amaremos getSprite@A8 -ue recibir" como par"metro un nombre de sprite -ue necesitemos < devo ver" a imagen8 carg"ndo a si es necesario6 Puesto -ue puede :aber muc:as im"genes8 a rutina tendr" -ue recordar -u9 sprites est"n cargados < cu" es no6 Para e o nada me.or -ue una Ias:,ap -ue asocie e nombre de cada sprite con su imagen en memoria6

Invaders6.ava

1 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 22 30 31 .2 33 3! 3# 3& 3( 3* 3+ !0 !1 !2 !3 !! !# !& !( !+ #0 #1 #2 #3 #! ## #& #( #* #+ &0

pacFage version0&G import .ava6aDt6CanvasG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava6uti 6Ias:,apG import .ava=6imageio6ImageI$G import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J *00G pub ic static 1ina int I4ICI> J &00G pub"ic 7as<Eap sprites* pub ic Invaders@A H sprites 1 new 7as<Eap()* J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808EI/>I8I4ICI>AG pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG

L pub ic )u11eredImage oadImage@String nombreA H ?2L ur Jnu G tr< H ur J getC ass@A6getC assLoader@A6get2esource@nombreAG return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G L L

%2 %. %4 %! %% %+ %%2 (2 +. (! (& (( (* (+

pub"ic 3u99eredI(a#e #et&prite(&trin# no(bre) 3u99eredI(a#e i(# 1 (3u99eredI(a#e)sprites.#et(no(bre)* i9 (i(# 11 nu"") i(# 1 "oadI(a#e(Bres;BDno(bre)* sprites.put(no(bre4i(#)* , return i(#* , pub ic void paint@Crap:ics gA H #.drawI(a#e(#et&prite(Bbic<o.#i9B)4 404 404t<is)* L pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG L

+. 3uc"e principa": 7:ora -ue <a tenemos un sistema -ue nos permite cargar im"genes de 1orma cmoda8 es :ora de ver cmo :acer -ue as cosas en nuestro .uego de Java cambien6 /e a misma 1orma en -ue todas as ap icaciones de EindoDs tienen un n0c eo amado ;buc e de proceso de mensa.es; o ,essage Loop8 a go mu< simi ar sucede con os .uegos6 ?n .uego b"sicamente de 1orma continua est" :aciendo o siguiente: 16 7ctua i%ar e ;estado de mundo; o e ;escenario; 26 Si es preciso8 re1rescar a panta a 36 Ko ver a punto 1 4n e primer paso es donde ocurren todos os movimientos de monstruos8 as acciones de .ugador8 a aparicin o desaparicin de e ementos8 os cambios de nive 8 a comprobacin de si se :a terminado e .uego8 etc6 Por supuesto todo esto no se :ace en a misma rutina8 pero s' se puede pensar -ue constitu<e una etapa c aramente di1erenciada de a siguiente8 en a -ue si :a :abido cambios en o -ue e .ugador est" viendo8 entonces se dibu.a de nuevo6 Kamos a imp ementar este sistema en nuestro .uego Java6 4 buc e principa estar" en una rutina a a -ue amaremos game@A6 La rutina -ue actua i%a e estado de mundo ser" updateEor d@A < 1ina mente a -ue dibu.a a panta a de momento seguir" siendo paint@A6 4n este paso8 a ;actua i%acin de mundo; consistir" en -ue e bic:o cambiar" de posicin a eatoriamente6 Por eso necesitaremos dos variab es g oba es amadas posW < posR -ue guardar"n su posicin8 de 1orma -ue e m9todo updateEor d@A pueda modi1icar as < e m9todo paint@A pueda uti i%ar as para pintar a bic:o en su posicin: Con esta idea8 e cdigo -ueda como sigue:

1 11 12 13 1! 1# 1& 1(

pacFage version0(G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11eredImageG

10

1* import .ava6net6?2LG 1+ import .ava6uti 6Ias:,apG 21 import .ava=6imageio6ImageI$G 22 import .ava=6sDing6J3rameG 23 import .ava=6sDing6JPane G 2! 2# pub ic c ass Invaders e=tends Canvas H 2& pub ic static 1ina int EI/>I J &!0G 2( pub ic static 1ina int I4ICI> J !*0G 2* 2+ pub ic Ias:,ap spritesG 30 pub ic int posW8posRG 31 32 pub ic Invaders@A H 33 sprites J neD Ias:,ap@AG 3! posW J EI/>IU2G 3# posR J I4ICI>U2G 3& 3( J3rame ventana J neD J3rame@;Invaders;AG 3* JPane pane J @JPane Aventana6getContentPane@AG 3+ set)ounds@0808EI/>I8I4ICI>AG !0 pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG !1 pane 6setLa<out@nu AG !2 pane 6add@t:isAG !3 ventana6set)ounds@0808EI/>I8I4ICI>AG !! ventana6setKisib e@trueAG !# ventana6addEindoDListener@ neD EindoD7dapter@A H !& pub ic void DindoDC osing@EindoD4vent eA H !( S<stem6e=it@0AG !* L !+ LAG !0 ventana.setAesi:ab"e(9a"se)* #1 L #3 pub ic )u11eredImage oadImage@String nombreA H #! ?2L ur Jnu G ## tr< H #& ur J getC ass@A6getC assLoader@A6get2esource@nombreAG #( return ImageI$6read@ur AG #* L catc: @4=ception eA H #+ S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG &0 S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG &1 S<stem6e=it@0AG &2 return nu G &3 L &! L && pub ic )u11eredImage getSprite@String nombreA H &( )u11eredImage img J @)u11eredImageAsprites6get@nombreAG &* i1 @img JJ nu A H &+ img J oadImage@;resU;VnombreAG

11

(0 (1 (2 (3 (& ++ (* -0 -1 -2 -. -! -% -+ --2 20 +2 +3 24 +# +&

L pub ic void paint@Crap:ics gA H #.drawI(a#e(#et&prite(Bbic<o.#i9B)4 posG4 posH4t<is)* L pub"ic void updateWor"d() posG 1 (int)(Eat<.rando(()IWI567)* posH 1 (int)(Eat<.rando(()I7$I876)* , pub"ic void #a(e() w<i"e (isJisib"e()) updateWor"d()* paint(#et8rap<ics())* , , pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG inv.#a(e()* L

sprites6put@nombre8imgAG L return imgG

Iemos aprovec:ado tambi9n a inc uir e m9todo set2esi%ab e@1a seA en e constructor para -ue e usuario no pueda redimensionar e tama5o de a ventana6 Si e.ecutamos este programa8 nos encontraremos con una sorpresa < es -ue a ventana se ena inmediatamente de bic:os:

C aramente tenemos un prob ema: como somos nosotros os -ue manua mente estamos amando a m9todo paint@A8 no estamos borrando o -ue :ab'a antes en a panta a8 con o -ue e bic:o se pinta en a nueva posicin pero sin -ue sea e iminado de a antigua6 -. Li(piando "a basura: 4 paso anterior nos de. con una saturacin de bic:os -ue :ab'a -ue so ucionar6 Para e o8 vamos a probar inicia mente una estrategia consistente en borrar a mano toda a

12

ventana antes de pintar e bic:o correspondiente6 4 0nico cambio consiste en as siguientes 'neas dentro de paint@A6

666 (& (( ++2 *0 666

Invaders6.ava

pub ic void paint@Crap:ics gA H #.setCo"or(#et3acK#round())* #.9i""Aect(0404#etWidt<()4#et7ei#<t())* g6draDImage@getSprite@;bic:o6gi1;A8 posW8 posR8t:isAG

Si e.ecutamos a:ora e programa8 veremos -ue e bic:o cambia de posicin tan r"pidamente -ue apenas da tiempo a ver o6 4st" c aro -ue :a< -ue insertar arti1icia mente una pausa en e buc e de programa8 para -ue e usuario tenga tiempo de ver a go en panta a: 16 26 36 !6 7ctua i%ar e ;estado de mundo; o e ;escenario;X Si es preciso8 re1rescar a panta a 4sperar un interva o de tiempo Ko ver a punto 1

4 interva o de tiempo - como no podr'a ser de otra manera - ser" una constante -ue de1iniremos a nive g oba e inicia mente 1i.aremos en #0 ms :

2! 2# 2& 2( 22+ *( ** *+ +0 +1 22 2. 24 +# +&

666

Invaders6.ava

pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J &!0G pub ic static 1ina int I4ICI> J !*0G pub"ic static 9ina" int &/$$5 1 !0* 666 pub ic void game@A H D:i e @isKisib e@AA H updateEor d@AG paint@getCrap:ics@AAG tr' 6<read.s"eep(&/$$5)* , catc< (Interrupted$)ception e) , L L 666

2. Contro"ando e" caos: 7un-ue no o parece8 e sistema anterior de impiar a basura tiene un prob ema de -ue nos percataremos en seguida6 Para e o8 primero vamos a :acer -ue e monstruo se mueva

13

de 1orma m"s o menos contro ada6 4n este caso :aremos -ue se mueva de 1orma :ori%onta 8 < -ue ;rebote; contra os 'mites de a ventana6 Iabitua mente este tipo de movimientos se imp ementan de1iniendo una variab e vW -ue servir" como ;ve ocidad; e indicar" a cantidad -ue :a< -ue sumar en cada ;turno; @cada iteracin de buc e de .uegoA a a variab e posW -ue contro a a posicin de bic:o6 Si a variab e -ue representa a ve ocidad es positiva8 @ vW X 0A8 entonces a posicin W ir" aumentando < por o tanto e bic:o se mover" a a derec:a6 Si a variab e vW es negativa8 a posicin W ir" disminu<endo < e bic:o se mover" a a i%-uierda6 La 1orma de contro ar os rebotes es comprobando a posicin de bic:o despu9s de cada movimiento6 Si se sa e por a i%-uierda @posW Y 0 A o por a derec:a @posW X EI/>IA8 entonces :a< -ue cambiar a direccin de movimiento6 Pero ta como o tenemos p anteado8 cambiar a direccin de movimiento es simp emente cambiar e signo de a ve ocidad6 Si antes de rebotar vW va 'a #8 despu9s de rebotar pasar" a va er -# < viceversa6 Con todo esto8 e paso + -ueda como sigue:

1 11 12 13 1! 1# 1& 1( 1* 1+ 21 22 23 2! 2# 2& 2( 2* 30 .1 32 3! 3# .% .+ .!0 !1 !2 !3 !! !# !& !(

pacFage version0+G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava6uti 6Ias:,apG import .ava=6imageio6ImageI$G import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J &!0G pub ic static 1ina int I4ICI> J !*0G pub ic static 1ina int SP44/ J 10G pub ic Ias:,ap spritesG pub"ic int posG4posH4vG* pub ic Invaders@A H sprites J neD Ias:,ap@AG posG 1 WI567;2* posH 1 7$I876;2* vG 1 2* J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808EI/>I8I4ICI>AG pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808EI/>I8I4ICI>AG

14

!* !+ #0 #1 #2 #3 ## #& #* #+ &0 &1 &2 &3 &! &# && &( &* &+ (1 (2 (3 (! (# (& (( (* (+ *0 *1 *2 2. 24 2! 2% +* ++ 100 102 103 10! 10# 10& 10( 10+ 110 111

L pub ic )u11eredImage oadImage@String nombreA H ?2L ur Jnu G tr< H ur J getC ass@A6getC assLoader@A6get2esource@nombreAG return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G L L pub ic )u11eredImage getSprite@String nombreA H )u11eredImage img J @)u11eredImageAsprites6get@nombreAG i1 @img JJ nu A H img J oadImage@;resU;VnombreAG sprites6put@nombre8imgAG L return imgG L pub ic void paint@Crap:ics gA H g6setCo or@get)acFground@AAG g61i 2ect@08 08 getEidt:@A8 getIeig:t@AAG g6draDImage@getSprite@;bic:o6gi1;A8 posW8 posR8 t:isAG L pub"ic void updateWor"d() posG D1 vG* i9 (posG L 0 MM posG N WI567) vG 1 >vG* , pub ic void game@A H D:i e @isKisib e@AA H updateEor d@AG paint@getCrap:ics@AAG tr< H >:read6s eep@SP44/AG L catc: @Interrupted4=ception eA HL L L pub ic static void main@StringMN argsA H Invaders inv J neD Invaders@AG inv6game@AG

ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG

15

112 L 113 L

10. E?s "ento Oue e" ojo: Sa vo -ue tengamos un ordenador e=cepciona mente r"pido8 nos :abremos percatado -ue e programa anterior tiene un de1ecto e=tremadamente mo esto < es un parpadeo en e bic:o6 4 parpadeo ocurre por-ue durante unos instantes e o.o est" viendo a panta a reci9n borrada en a -ue todav'a no se :a pintado ning0n bic:o6 Si e ordenador -ue tenemos es mu< r"pido < no podemos apreciar o8 basta en genera con aumentar e tama5o de a ventana o uti i%ar gr"1icos m"s grandes para -ue e e1ecto pase a ser apreciab e6 Para reso ver esta situacin uti i%aremos una t9cnica amada doub"e bu99erin#6 4sta t9cnica consiste en tener una imagen en memoria de mismo tama5o -ue e escenario en a cua se :acen todas as operaciones gr"1icas6 ?na ve% -ue e escenario :a sido pintado ;1uera de a panta a; @o11-screenA8 esa imagen en memoria es vo cada encima de a ventana6 7 esta imagen en memoria se a sue e amar bu99er.

1 11 12 13 1! 1# 1& 1( 1* 1+ 21 22 23 2! 2# 2& 2( 2* 30 31 .2 33 3! 3# 3& 3( 3* .2 !0 !1 42 !!

pacFage version10G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava6uti 6Ias:,apG import .ava=6imageio6ImageI$G import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J &!0G pub ic static 1ina int I4ICI> J !*0G pub ic static 1ina int SP44/ J 10G pub ic Ias:,ap spritesG pub ic int posW8posR8vWG pub"ic 3u99eredI(a#e bu99er* pub ic Invaders@A H sprites J neD Ias:,ap@AG posW J EI/>IU2G posR J I4ICI>U2G vW J 2G bu99er 1 new bu99eredI(a#e(WI56747$I87643u99eredI(a#e.6H/$PIC6PA83)* J3rame ventana J neD J3rame@;Invaders;AG ventana.create3u99er&trate#'(2)*

16

!# !& !( !* !+ #0 #1 #2 #3 #! ## #& !+ #* #+ &1 &2 &3 &! &# && &( &* &+ (0 (1 (2 (! (# (& (( (* (+ *0 *1 -. -4 -! -% -+ -21 22 2. +# +& +( +* 100

L pub ic )u11eredImage oadImage@String nombreA H ?2L ur Jnu G tr< H ur J getC ass@A6getC assLoader@A6get2esource@nombreAG return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G L L pub ic )u11eredImage getSprite@String nombreA H )u11eredImage img J @)u11eredImageAsprites6get@nombreAG i1 @img JJ nu A H img J oadImage@;resU;VnombreAG sprites6put@nombre8imgAG L return imgG L pub"ic void paintWor"d() 8rap<ics # 1 bu99er.#et8rap<ics()* #.setCo"or(#et3acK#round())* #.9i""Aect(0404#etWidt<()4#et7ei#<t())* #.drawI(a#e(#et&prite(Bbic<o.#i9B)4 posG4 posH4t<is)* , pub"ic void paint(8rap<ics #) #.drawI(a#e(bu99er40404t<is)* , pub ic void updateEor d@A H posW VJ vWG i1 @posW Y 0 ZZ posW X EI/>IA vW J -vWG L pub ic void game@A H

JPane pane J @JPane Aventana6getContentPane@AG pane 6set)ounds@0808EI/>I8I4ICI>AG pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana.setI#noreAepaint(true)* ventana6set2esi%ab e@1a seAG

17

101 D:i e @isKisib e@AA H 102 updateEor d@AG 103 paintEor d@AG 10! paint@getCrap:ics@AAG 10# tr< H 10& >:read6s eep@SP44/AG 10( L catc: @Interrupted4=ception eA HL 10* L 10+ L 111 pub ic static void main@StringMN argsA H 112 Invaders inv J neD Invaders@AG 113 inv6game@AG 11! L 11# L
11. 5ob"e 3Q9er auto(?tico: La t9cnica de dob e bu11er es tan e=tendida -ue en e J/S 16! se inc u< un mecanismo autom"tico para rea i%ar este tipo de operaciones8 permitiendo adem"s -ue a visua i%acin de bu11er se :aga mediante mecanismos m"s ace erados dependientes de a p ata1orma @como por e.emp o8 mover e puntero de memoria de a tar.eta gr"1ica -ue indica dnde comien%a e bu11er de v'deo en ugar de copiar ese bu11er a otra %ona de memoriaA6 La c ase -ue permite imp ementar este tipo de operaciones se ama )u11erStrateg< < se encuentra en e pa-uete .ava6aDt6image6 La 1orma de uti i%ar a es e=tremadamente senci a: 16 4n primer ugar8 se decide -u9 ventana o componente es a -ue presentar" este tipo de comportamiento6 Se :a de escoger a-ue componente sobre e -ue vamos a pintar @en nuestro caso es a propia c ase InvadersA6 Se ama a m9todo create)u11erStratg<@nA de esa ventana8 pasando como par"metro e n0mero de bu11ers -ue -ueremos tener6 ?ti i%amos e m9todo get)u11erStrateg<@A de a ventana para obtener un ob.eto de tipo )u11erStrateg<8 -ue representa b"sicamente una ristra de bu11ers de memoria - tantos como 1ue e par"metro -ue pasamos a create)u11erStrateg<@A 4n todo momento :a< un ;bu11er de dibu.o; < un ;bu11er visib e;6 Para poder pintar encima de bu11er de dibu.o8 amamos a m9todo get/raDCrap:ics@A de ob.eto )u11erStrateg< obtenido anteriormente6 Cuando :emos terminado de pintar8 amamos a m9todo s:oD@A de ob.eto )u11erStrateg< para indicar -ue e bu11er est" isto < -ue -ueremos mostrar e siguiente bu11er6

26 36

!6

#6

Con esta t9cnica8 e programa -uedar'a de a siguiente 1orma: observar -ue e m9todo paint@A :a desaparecido6

1 pacFage version11G 11 12 import .ava6aDt6CanvasG 13 import .ava6aDt6Co orG 1! import .ava6aDt6/imensionG 1# import .ava6aDt6Crap:icsG 1& import .ava6aDt6event6EindoD7dapterG

Invaders6.ava

18

1( import .ava6aDt6event6EindoD4ventG 1i(port java.awt.i(a#e.3u99er&trate#'* 1+ import .ava6aDt6image6)u11eredImageG 20 import .ava6net6?2LG 21 import .ava6uti 6Ias:,apG 23 import .ava=6imageio6ImageI$G 2! import .ava=6sDing6J3rameG 2# import .ava=6sDing6JPane G 2& 2( pub ic c ass Invaders e=tends Canvas H 2* pub ic static 1ina int EI/>I J &!0G 2+ pub ic static 1ina int I4ICI> J !*0G 30 pub ic static 1ina int SP44/ J 10G .2 pub"ic 3u99er&trate#' strate#'* 33 pub ic Ias:,ap spritesG 3! pub ic int posW8posR8vWG 3# 3& pub ic Invaders@A H 3( sprites J neD Ias:,ap@AG 3* posW J EI/>IU2G 3+ posR J I4ICI>U2G !0 vW J 2G !2 J3rame ventana J neD J3rame@;Invaders;AG !3 JPane pane J @JPane Aventana6getContentPane@AG !! set)ounds@0808EI/>I8I4ICI>AG !# pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG !& pane 6setLa<out@nu AG !( pane 6add@t:isAG !* ventana6set)ounds@0808EI/>I8I4ICI>AG !+ ventana6setKisib e@trueAG #0 ventana6addEindoDListener@ neD EindoD7dapter@A H #1 pub ic void DindoDC osing@EindoD4vent eA H #2 S<stem6e=it@0AG #3 L #! LAG ## ventana6set2esi%ab e@1a seAG !% create3u99er&trate#'(2)* !+ strate#' 1 #et3u99er&trate#'()* #* re-uest3ocus@AG #+ L &1 pub ic )u11eredImage oadImage@String nombreA H &2 ?2L ur Jnu G &3 tr< H &! ur J getC ass@A6getC assLoader@A6get2esource@nombreAG &# return ImageI$6read@ur AG && L catc: @4=ception eA H &( S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG &* S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG &+ S<stem6e=it@0AG

19

(0 return nu G (1 L (2 L (! pub ic )u11eredImage getSprite@String nombreA H (# )u11eredImage img J @)u11eredImageAsprites6get@nombreAG (& i1 @img JJ nu A H (( img J oadImage@;resU;VnombreAG (* sprites6put@nombre8imgAG (+ L *0 return imgG *1 L *3 pub ic void paintEor d@A H -4 8rap<ics # 1 strate#'.#et5raw8rap<ics()* -! #.setCo"or(Co"or.b"acK)* *& g61i 2ect@0808getEidt:@A8getIeig:t@AAG *( g6draDImage@getSprite@;bic:o6gi1;A8 posW8 posR8t:isAG -strate#'.s<ow()* *+ L +3 pub ic void updateEor d@A H +! posW VJ vWG +# i1 @posW Y 0 ZZ posW X EI/>IA vW J -vWG +& L +* pub ic void game@A H ++ D:i e @isKisib e@AA H 100 updateEor d@AG 101 paintEor d@AG 102 tr< H 103 >:read6s eep@SP44/AG 10! L catc: @Interrupted4=ception eA HL 10# L 10& L 10* pub ic static void main@StringMN argsA H 10+ Invaders inv J neD Invaders@AG 110 inv6game@AG 111 L 112 L
12. Eedicin de" rendi(iento: ?no de os aspectos 1undamenta es de cua -uier .uego es a ve ocidad con a -ue es capa% de dibu.ar e escenario6 /e nada sirve -ue e .uego sea maravi oso si e dibu.o de a ma%morra tarda 2 segundos @aun-ue siempre cabe a opcin de cambiar a denominacin de "rcade a ;.uego de estrategia por turnos;A6 4s mu< 1"ci a principio de.arse evar por e entusiasmo < comen%ar a a5adir opciones < m"s opciones a nuestro .uego8 con gr"1icos cada ve% m"s comp icados < grandes < a 1ina encontrarse con -ue e redibu.o de escenario se :a convertido en a go tan ento -ue <a no es .ugab e6 Por este motivo es 1undamenta -ue o antes posib e imp ementemos en nuestro .uego un contador de ;1otogramas por segundo; - os 1amosos 1rames per second @1psA -ue nos diga cu"ntas veces por segundo somos capaces de dibu.ar e escenario6 Sin embargo8 no tenemos tampoco -ue obsesionarnos con e va or de este contador6

20

Kisua mente8 un .uego a +0 1ps es e=actamente igua de suave -ue uno de 1200 1ps6 4 motivo es mu< senci o < es -ue si e monitor es de 100 I% - en e me.or de os casos - eso signi1icar" -ue en un segundo :ace cien barridos de a panta a6 /a igua si en ese tiempo nuestro programa :a actua i%ado e escenario mi veces8 por-ue a monitor s o e :a dado tiempo a presentar uno6 Ia< una gran ma<or'a de monitores -ue 1uncionan a #08 &0 < (# I%8 < en cua -uier caso a o.o e es su1iciente con #0 1ps8 con o cua si nuestro contador no ba.a de esa ci1ra8 no deber'amos preocuparnos en e=ceso6 Sin embargo8 debemos ser conscientes de -ue e n0mero de 1otogramas por segundo imita seriamente as amp iaciones -ue seremos capaces de :acer en e 1uturo6 Si tenemos mi bic:os movi9ndose simu t"neamente en a panta a < e o nos eva a (( 1ps8 entonces es poco probab e -ue consigamos a5adir te=turas desp a%"ndose en e 1ondo sin -ue caigamos por deba.o de umbra de usabi idad6 OCmo ca cu ar os 1psQ Simp emente miramos e buc e principa de .uego < e=aminamos cuanto tiempo tarda en rea i%arse un turno - con todos sus cambios8 actua i%aciones8 dibu.os8 etc666 Supongamos -ue obtenemos una cierta cantidad de mi isegundos6 7:ora dividimos 1000 @1 segundoA por a cantidad ca cu ada < obtenemos os 1ps6 Por e.emp o8 si e cuerpo de nuestro buc e tarda 1! ms @sin contar con a pausa8 -ue es tota mente arti1icia < se puede reducir o inc uso e iminarA8 entonces estar'amos proporcionando (1 1ps6 Con nuestro contador 1ps8 e programa -ueda as':

1 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 31 32 33 3! .! 3& 3( 3* 3+

pacFage version12G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt6Crap:icsG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11erStrateg<G import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava6uti 6Ias:,apG import .ava=6imageio6ImageI$G import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas H pub ic static 1ina int EI/>I J &!0G pub ic static 1ina int I4ICI> J !*0G pub ic static 1ina int SP44/ J 10G pub ic pub ic pub ic pub"ic )u11erStrateg< strateg<G Ias:,ap spritesG int posW8posR8vWG "on# used6i(e*

pub ic Invaders@A H sprites J neD Ias:,ap@AG posW J EI/>IU2G

21

!0 !1 !2 !3 !! !# !& !( !* !+ #0 #1 #2 #3 #! ## #& #( #* #+ &0 &2 &3 &! &# && &( &* &+ (0 (1 (2 (3 (# (& (( (* (+ *0 *1 *2 *! *# *& *( ** *+ 20 21

posR J I4ICI>U2G vW J 2G J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808EI/>I8I4ICI>AG pane 6setPre1erredSi%e@neD /imension@EI/>I8I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808EI/>I8I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG

L pub ic )u11eredImage oadImage@String nombreA H ?2L ur Jnu G tr< H ur J getC ass@A6getC assLoader@A6get2esource@nombreAG return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G L L pub ic )u11eredImage getSprite@String nombreA H )u11eredImage img J @)u11eredImageAsprites6get@nombreAG i1 @img JJ nu A H img J oadImage@;resU;VnombreAG sprites6put@nombre8imgAG L return imgG L pub ic void paintEor d@A H Crap:ics g J strateg<6get/raDCrap:ics@AG g6setCo or@Co or6b acFAG g61i 2ect@0808getEidt:@A8getIeig:t@AAG g6draDImage@getSprite@;bic:o6gi1;A8 posW8 posR8t:isAG #.setCo"or(Co"or.w<ite)* i9 (used6i(e N 0)

22

22 #.draw&trin#(&trin#.va"ue=9(1000;used6i(e)DB 9psB4047$I876>!0)* 2. e"se 24 #.draw&trin#(B>>> 9psB4047$I876>!0)* +# strateg<6s:oD@AG +& L 100 pub ic void updateEor d@A H 101 posW VJ vWG 102 i1 @posW Y 0 ZZ posW X EI/>IA vW J -vWG 103 L 10# pub ic void game@A H 10% used6i(e11000* 10( D:i e @isKisib e@AA H 10"on# start6i(e 1 &'ste(.current6i(eEi""is()* 10+ updateEor d@AG 110 paintEor d@AG 111 used6i(e 1 &'ste(.current6i(eEi""is()>start6i(e* 112 tr< H 113 >:read6s eep@SP44/AG 11! L catc: @Interrupted4=ception eA HL 11# L 11& L 11* pub ic static void main@StringMN argsA H 11+ Invaders inv J neD Invaders@AG 120 inv6game@AG 121 L 122 L

Inicia mente e cuerpo tarda tan poco @menos de 1 msA8 as' -ue podemos estar tran-ui os6 Sin embargo8 esto no debe :acer -ue nos con1iemos puesto -ue en seguida veremos -ue as cosas se van a ir comp icando a medida -ue a5adamos m"s 1unciona idad a nuestro .uego6

1.. Aeor#ani:acin de" cdi#o 0ava:

23

4n este punto e programa Invaders6.ava est" convirti9ndose en una masa de cdigo entreme%c adaG nada -ue ver con a programacin orientada a ob.etos o con un buen esti o de programacin6 Si no se tiene e=periencia8 es norma :aber recorrido este camino < egar a esta situacin6 Lo importante es saber detenerse8 como vamos a :acer nosotros a-u'8 < ver si e=iste a guna me.or 1orma de organi%ar e cdigo6 Con e tiempo < seg0n se va<a acumu ando e=periencia en a programacin en Java o cua -uier otro engua.e orientado a ob.etos8 as decisiones -ue vamos a tomar a-u' as :abr'amos tomado a principio en base a os comportamientos < tipos de ;cosas; -ue preveamos -ue :abr" en e programa 1ina 6 Inicia mente vamos a pensar -ue ;cosas; @entidadesA distintas tenemos en e programa: >enemos una parte de programa - re ativamente independiente de as dem"s - -ue se dedica a gestionar un ;cac:9 de sprites;6 4sa parte de programa8 -ue tiene una serie de datos propios @ os sprites cargadosA < comportamientos propios @ eer < proporcionar spritesA es candidata t'pica para convertirse en una c ase independiente6 Cuando se de1ine una c ase nueva8 es buena idea pensar -u9 responsabi idades o interacciones tendr" esa c ase con e resto de sistema6 4n este caso a c ase es mu< senci a < su 0nica interaccin es ;dar gr"1icos; a -uien o necesite6 Por o tanto su 0nico m9todo p0b ico ser" e siguiente:

pub ic )u11eredImage getSprite@String nombreA H


?na ve% -ue tenemos c aros os servicios -ue proporcionar" a c ase8 debemos preguntarnos -u9 necesitar" internamente para evar a cabo su cometido6 4n este caso8 gicamente a c ase necesitar" e mapa de sprites < e m9todo para cargar una imagen en memoria6 Con todo esto8 a c ase SpriteCac:e -uedar'a como sigue:

+ 10 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 2! 2# 2& 2( 2* 2+ 30 31 32 33

pacFage version13G

SpriteCac:e6.ava

import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava6uti 6Ias:,apG import .ava=6imageio6ImageI$G pub ic c ass SpriteCac:e H private Ias:,ap spritesG pub ic SpriteCac:e@A H sprites J neD Ias:,ap@AG L private )u11eredImage oadImage@String nombreA H ?2L ur Jnu G tr< H ur J getC ass@A6getC assLoader@A6get2esource@nombreAG return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen ; V nombre V; de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G

24

3! 3# 3( 3* 3+ !0 !1 !2 !3 !! !#

L L pub ic )u11eredImage getSprite@String nombreA H )u11eredImage img J @)u11eredImageAsprites6get@nombreAG i1 @img JJ nu A H img J oadImage@;resU;VnombreAG sprites6put@nombre8imgAG L return imgG L

4n segundo ugar tenemos e sitio donde se desarro a a accin6 Kamos a amar a este sitio ;e escenario; @Stage en ing 9sA6 4 escenario es e -ue de a guna 1orma ;coordina; as cosas -ue ocurren en e .uego - e escenario es e -ue sabe cu"ntos monstruos :a<8 cuantas ba as8 en -u9 nive estamos8 etc666 ?na caracter'stica mu< importante de escenario es -ue es precisamente 9 e -ue tiene a re1erencia a 0nico ob.eto SpriteCac:e -ue e=iste en e programa6 Podr'amos pensar -ue <a tenemos una c ase ;escenario; -ue es a propia Invaders6.ava8 pero o cierto es -ue si -ueremos tener una serie de 1unciona idades -ue nos sirvan para otros .uegos8 ser" me.or separar as en una c ase o en una inter1a% distinta6 4n este caso :emos optado por crear una inter1a% -ue indi-ue as caracter'sticas -ue tiene e escenario6 Kamos a de1inir a inter1a% Stage de a siguiente 1orma:

Stage6.ava + pacFage version13G 10 11 import .ava6aDt6image6Image$bserverG 12 13 pub ic inter1ace Stage e=tends Image$bserver H 1! pub ic static 1ina int EI/>IJ&!0G 1# pub ic static 1ina int I4ICI>J!*0G 1& pub ic static 1ina int SP44/J10G 1( pub ic SpriteCac:e getSpriteCac:e@AG 1+ L
Como se puede ver8 de momento esta inter1a% o 0nico -ue contiene son as constantes genera es de .uego < un m9todo para acceder a cac:9 de sprites6 7diciona mente tenemos e monstruo6 4st" c aro -ue si en e 1uturo vamos a a5adir m"s8 todos e os ser"n en esencia o mismo8 si acaso en distintas posiciones8 o con distintas ve ocidades6 Pensemos por un momento -u9 caracter'sticas comunes van a tener nuestros monstruos en e .uego para poder de1inir una c ase apropiada6 Por un ado8 todos os monstruos van a tener una posicin sobre a panta a6 7dem"s8 todos van a tener un gr"1ico -ue peridicamente van a tener -ue pintar sobre e a6 /ado -ue es posib e -ue -ueramos de1inir monstruos di1erentes8 cada uno tendr" un tama5o -ue no ser" necesariamente e mismo para todos6 Por 0 timo8 todos van a ;:acer a go; cuando es to-ue e turno6 Puede ser -ue e i.an moverse8 disparar8 desaparecer8 te e transportarse8 atacar a .ugador8 o cua -uier cosa -ue se nos ocurra m"s ade ante6 Como a:ora mismo no sabemos -u9 va a ser esa cua -uier cosa8 vamos a de1inir un m9todo gen9rico amado act@A en e -ue cada monstruo e egir" o -ue -uiere :acer6 Lo bonito

25

de este sistema es -ue e programa principa se imitar" a amar a monstruo6act@A < cada uno actuar" seg0n e comportamiento programado8 sin -ue e programa principa tenga -ue saber nada a respecto6 Por o tanto < resumiendo8 os monstruos: 16 26 36 !6 >ienen una posicin sobre a panta a >ienen un tama5o @una anc:ura < una a turaA Son capaces de pintarse sobre a panta a Peridicamente e.ecutan un comportamiento

Pensemos a:ora un poco m"s < veremos -ue rea mente estas caracter'sticas as tienen no so o os monstruos sino e propio .ugador @su naveA o os disparos de a misma6 Por o tanto :emos egado a una c ase -ue es capa% de encapsu ar pr"cticamente cua -uier cosa ;activa; o ;viva; sobre e escenario < a esta c ase a vamos a amar 7ctor6 Por supuesto8 podr'amos :aber :ec:o este ra%onamiento a principio de curso8 pero e ob.etivo era egar :asta 9 de 1orma natura 8 como o :ar'a una persona sin muc:a e=periencia < -ue est" aprendiendo6 Con o dic:o :asta a:ora8 a c ase 7ctor -uedar'a como sigue:

+ 10 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 31 32 33 3! 3# 3& 3( 3* 3+

pacFage version13G

7ctor6.ava

import .ava6aDt6Crap:ics2/G import .ava6aDt6image6)u11eredImageG pub ic c ass 7ctor H protected int =8<G protected int Didt:8 :eig:tG protected String spriteBameG protected Stage stageG protected SpriteCac:e spriteCac:eG pub ic 7ctor@Stage stageA H t:is6stage J stageG spriteCac:e J stage6getSpriteCac:e@AG L pub ic void paint@Crap:ics2/ gAH g6draDImage@ spriteCac:e6getSprite@spriteBameA8 =8<8 stage AG L pub ic int getW@A H return =G L pub ic void setW@int iA H = J iG L pub ic int getR@A H return <G L pub ic void setR@int iA H < J iG L pub ic String getSpriteBame@A H return spriteBameG L pub ic void setSpriteBame@String stringA H spriteBame J stringG )u11eredImage image J spriteCac:e6getSprite@spriteBameAG

26

!0 !1 !2 !! !# !& !( !* !+ #0

L pub ic pub ic pub ic pub ic

:eig:t J image6getIeig:t@AG Didt: J image6getEidt:@AG int getIeig:t@A H return :eig:tG L int getEidt:@A H return Didt:G L void setIeig:t@int iA H:eig:t J iG L void setEidt:@int iA H Didt: J iG L

pub ic void act@A H L

4sta es a c ase gen9rica8 < a:ora vamos a de1inir una c ase descendiente de e a amada ,onster -ue se imitar" a moverse < a actuar como :asta a:ora o :ac'a nuestro 0nico monstruo:

10 pacFage version13G 11 pub ic c ass ,onster e=tends 7ctor H 12 protected int v=G 13 1! pub ic ,onster@Stage stageA H 1# super@stageAG 1& setSpriteBame@;bic:o6gi1;AG 1( L 1* 1+ pub ic void act@A H 20 =VJv=G 21 i1 @= Y 0 ZZ = X Stage6EI/>IA 22 v= J -v=G 23 L 2# pub ic int getK=@A H return v=G L 2& pub ic void setK=@int iA Hv= J iG L 2* L R 1ina mente nos toca reescribir a c ase origina - Invaders < aprovec:aremos para a5adir a posibi idad de -ue e=istan muc:os monstruos6 >odos e os os a macenaremos en una ista amada ;actors;: Invaders6.ava

,onster6.ava

1 10 11 12 13 1! 1# 1& 1( 1* 20 21

pacFage version13G

import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt6Crap:ics2/G import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11erStrateg<G import .ava6uti 67rra<ListG import .ava=6sDing6J3rameG import .ava=6sDing6JPane G

27

22 23 2! 2# 2& 2* 2+ 30 31 32 33 3! 3# 3& 3( 3* 3+ !0 !1 !2 !3 !! !# !& !( !* !+ #0 #1 #3 #! ## #& #( #* #+ &0 &1 &2 &! &# && &( &* &+ (0 (1 (2 (3 (!

pub ic c ass Invaders e=tends Canvas imp ements Stage H private )u11erStrateg< strateg<G private ong used>imeG private SpriteCac:e spriteCac:eG private 7rra<List actorsG pub ic Invaders@A H spriteCac:e J neD SpriteCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG

L pub ic void initEor d@A H actors J neD 7rra<List@AG 1or @int i J 0G i Y 10G iVVAH ,onster m J neD ,onster@t:isAG m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG m6setR@ i[20 AG m6setK=@ @intA@,at:6random@A[20-10A AG actors6add@mAG L L pub ic void updateEor d@A H 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6act@AG L L

pub ic void paintEor d@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG g6setCo or@Co or6b acFAG g61i 2ect@0808getEidt:@A8getIeig:t@AAG

28

(# 1or @int i J 0G i Y actors6si%e@AG iVVA H (& 7ctor m J @7ctorAactors6get@iAG (( m6paint@gAG (* L *0 g6setCo or@Co or6D:iteAG *1 i1 @used>ime X 0A *2 g6draDString@String6va ue$1@1000Uused>imeAV; 1ps;808Stage6I4ICI>-#0AG *3 e se *! g6draDString@;--- 1ps;808Stage6I4ICI>-#0AG *# strateg<6s:oD@AG *& L ** pub ic SpriteCac:e getSpriteCac:e@A H *+ return spriteCac:eG +0 L +2 pub ic void game@A H +3 used>imeJ1000G +! initEor d@AG +# D:i e @isKisib e@AA H +& ong start>ime J S<stem6current>ime,i is@AG +( updateEor d@AG +* paintEor d@AG ++ used>ime J S<stem6current>ime,i is@A-start>imeG 100 tr< H 101 >:read6s eep@SP44/AG 102 L catc: @Interrupted4=ception eA HL 103 L 10! L 10& pub ic static void main@StringMN argsA H 10( Invaders inv J neD Invaders@AG 10* inv6game@AG 10+ L 110 L
3i.9monos especia mente en os m9todos initEor d@A8 updateEor d@A < paintEor d@A6 4 primero de e os es nuevo < su propsito es inicia i%ar e escenario6 4n este caso8 se constru<en distintos monstruos < se a5aden a a ista de actores e=istentes6 Los m9todos updateEor d@A < paintEor d@A tienen os mismos pape es -ue antes8 pero a:ora son muc:o m"s impios < no dependen para nada de tipo de actores con os -ue est"n tratando6 Cada uno de estos m9todos se imita a recorrer a ista de actores dici9ndo es ;p'ntate\;8 ;act0a;8 etc666 < cada actor concreto8 dependiendo de cmo est"n sobreescritos sus m9todos8 act0a en consecuencia6

29

14. Roto#ra(as: 7:ora -ue tenemos un montn de bic:os movi9ndose por todas partes8 vamos a dotar es de animacin6 4n este tipo de video.uegos8 as' como en muc:os otros como por e.emp o de estrategia8 de aventura o de ro con perspectiva isom9trica8 de p ata1orma8 etc6 a animacin de os monigotes sue e ser sinnimo de 1otogramas: a imagen de actor va recorriendo una serie sucesiva de imagenes amadas ;1otogramas;6 Cuantos m"s 1otogramas :a<8 m"s suave es a animacin de propio bic:o6 4n este caso vamos a uti i%ar os siguientes dos 1otogramas8 amados ;bic:o06gi1; < ;bic:o16gi1;:

/ado -ue os 1otogramas es a go -ue podemos -uerer -ue tenga cua -uier ob.eto de nuestro .uego - disparos8 bonus8 monstruos8 etc8 a5adiremos esa 1unciona idad a a c ase 7ctor en ugar de a a c ase ,onster6 La propiedad spriteBame desaparece < es sustituida por a propiedad spriteBames8 -ue es una matri% de nombres de gr"1icos en ugar de un 0nico gr"1ico6 7diciona mente8 e m9todo act@A se encarga de incrementar e n0mero de 1otograma cada ve%:

+ 10 11 12 13 1! 1# 1& 1+ 11+ 20

pacFage version1!G

7ctor6.ava

import .ava6aDt6Crap:ics2/G import .ava6aDt6image6)u11eredImageG pub ic c ass 7ctor H protected int =8<G protected int Didt:8 :eig:tG protected &trin#ST spriteCa(es* protected int currentRra(e* protected Stage stageG protected SpriteCac:e spriteCac:eG

30

22 pub ic 7ctor@Stage stageA H 23 t:is6stage J stageG 2! spriteCac:e J stage6getSpriteCac:e@AG 2# current3rame J 0G 2& L 2- pub"ic void paint(8rap<ics25 #) 22 #.drawI(a#e( spriteCac<e.#et&prite(spriteCa(esScurrentRra(eT)4 )4'4 sta#e )* .0 , 31 32 pub ic int getW@A H return =G L 33 pub ic void setW@int iA H = J iG L 3! 3# pub ic int getR@A H return <G L 3& pub ic void setR@int iA H < J iG L 3( .pub"ic void set&priteCa(es(&trin#ST na(es) .2 spriteCa(es 1 na(es* 40 <ei#<t 1 0* 41 widt< 1 0* 42 9or (int i 1 0* i L na(es."en#t<* iDD ) 4. 3u99eredI(a#e i(a#e 1 spriteCac<e.#et&prite(spriteCa(esSiT)* 44 <ei#<t 1 Eat<.(a)(<ei#<t4i(a#e.#et7ei#<t())* 4! widt< 1 Eat<.(a)(widt<4i(a#e.#etWidt<())* 4% , 4+ , !+ pub ic int getIeig:t@A H return :eig:tG L #0 pub ic int getEidt:@A H return Didt:G L #1 pub ic void setIeig:t@int iA H:eig:t J iG L #2 pub ic void setEidt:@int iA H Didt: J iG L #3 !4 pub"ic void act() !! currentRra(e 1 (currentRra(e D 1) U spriteCa(es."en#t<* !% , #( L
4s interesante -ue nos 1i.emos en a 1orma en -ue se aumenta e contador de 1otogramas: se uti i%a un ] spriteBames6 engt: para asegurarse -ue su va or siempre est9 entre 0 < e n0mero de 1otogramas ^ 16 Puesto -ue a:ora tenemos 1unciona idad en e m9todo act@A de 7ctor8 os :i.os no pueden sobreescribir ese m9todo sin m"s8 sino -ue deben acordarse de amar a m9todo ancestro antes de comen%ar a rea i%ar sus propias acciones particu ares6 4sto :ace -ue a c ase ,onster -uede modi1icada de a siguiente 1orma:

,onster6.ava + pacFage version1!G 10 11 pub ic c ass ,onster e=tends 7ctor H 12 protected int v=G 13 1! pub ic ,onster@Stage stageA H

31

1# 1% 1( 1+ 20 21 22 23 2! 2& 2(

L pub ic void act@A H super.act()* =VJv=G i1 @= Y 0 ZZ = X Stage6EI/>IA v= J -v=G L pub ic int getK=@A H return v=G L pub ic void setK=@int iA Hv= J iG LL

super@stageAG set&priteCa(es( new &trin#ST Bbic<o0.#i9B4Bbic<o1.#i9B,)*

1!. Roto#ra(as V II: Si tenemos un ordenador su1icientemente r"pido8 os 1otogramas de programa anterior avan%an a una ve ocidad e=cesiva < apenas da tiempo a ver os como 1otogramas di1erenciados6 Sin embargo8 a 1recuencia con a -ue se ama a m9todo act@A es a go -ue es genera para todo e .uego < no podemos variar o para cada caso individua 6 La so ucin a tomamos prestada de a e ectrnica mediante o -ue se ama una base de tiempos6 4 buc e principa duerme durante un tiempo -ue -ueda determinado por e m"=imo com0n divisor de os tiempos de resto de ob.etos6 Por e.emp o imaginemos -ue estamos :aciendo un video.uego en e cua os monstruos se act0an a a ve ocidad de una ve% por segundo8 mientras -ue e .ugador act0a a una ve ocidad de 2 veces por segundo @o dic:o de otra 1orma8 -ueremos -ue tenga un ;turno; para :acer cosas dos veces por segundo8 o una ve% cada medio segundoA6 >enemos tambi9n un vo c"n -ue :ace erupcin cada 10 segundos6 4 m"=imo com0n divisor entre 18 06# < 10 es 06#6 4ste ,C/ recibe e nombre de unidad de tiempo o base de tiempos < es e tiempo -ue dormir" en genera e buc e principa 6 /entro de buc e principa 8 cada ve% -ue sa gamos de >:read6s eep8 se incrementa un contador secuencia -ue :ace as veces de ;instante de tiempo;6 Cuando este contador sea divisib e por a cantidad apropiada8 entonces es cuando se rea i%a a actua i%acin de ob.eto en cuestin6 4sta ;cantidad apropiada; es e resu tado de dividir e interva o en segundos entre dos movimientos sucesivos de ob.eto por e ,C/ ca cu ado anteriormente6 Como en nuestro e.emp o a unidad de tiempo es de 06# segundos8 e es-uema ser'a: Jugador - Se actua i%a siempre @ 06# U 06# J 1 A ,onstruo - Se mueve cada 2 unidades de tiempo8 por o tanto se actua i%a cada ve% -ue e contador sea divisib e por 26 Ko c"n - 4ntra en erupcin cada 10 segundos8 o cada 20 unidades de tiempo8 por o -ue se actua i%a cada ve% -ue e contador sea divisib e por 206

4 mismo criterio podemos ap icar a os 1otogramas: Podemos mantener dentro de a c ase 7ctor un contador de tiempos < actua i%ar e 1otograma s o cuando este contador sea divisib e por una cantidad -ue amaremos ;ve ocidad de os 1otogramas;6 Con este ra%onamiento8 a c ase ;7ctor; -uedar'a como sigue: 7ctor6.ava + pacFage version1#G 10 11 import .ava6aDt6Crap:ics2/G 12 import .ava6aDt6image6)u11eredImageG

32

1! pub ic c ass 7ctor H 1# protected int =8<G 1& protected int Didt:8 :eig:tG 1( protected StringMN spriteBamesG 1* protected int current3rameG 12 protected int 9ra(e&peed* 20 protected int t* 21 protected Stage stageG 22 protected SpriteCac:e spriteCac:eG 23 2! pub ic 7ctor@Stage stageA H 2# t:is6stage J stageG 2& spriteCac:e J stage6getSpriteCac:e@AG 2( current3rame J 0G 2* 1rameSpeed J 1G 2+ tJ0G 30 L 32 pub ic void paint@Crap:ics2/ gAH 33 g6draDImage@ spriteCac:e6getSprite@spriteBamesMcurrent3rameNA8 =8<8 stage AG 3! L 3& pub ic int getW@A H return =G L 3( pub ic void setW@int iA H = J iG L 3* 3+ pub ic int getR@A H return <G L !0 pub ic void setR@int iA H < J iG L !1 !2 pub ic int get3rameSpeed@A Hreturn 1rameSpeedG L !3 pub ic void set3rameSpeed@int iA H1rameSpeed J iG L !# !& pub ic void setSpriteBames@StringMN namesA H !( spriteBames J namesG !* :eig:t J 0G !+ Didt: J 0G #0 1or @int i J 0G i Y names6 engt:G iVV A H #1 )u11eredImage image J spriteCac:e6getSprite@spriteBamesMiNAG #2 :eig:t J ,at:6ma=@:eig:t8image6getIeig:t@AAG #3 Didt: J ,at:6ma=@Didt:8image6getEidt:@AAG #! L ## L #( pub ic int getIeig:t@A H return :eig:tG L #* pub ic int getEidt:@A H return Didt:G L #+ pub ic void setIeig:t@int iA H:eig:t J iG L &0 pub ic void setEidt:@int iA H Didt: J iG L &1 %2 pub"ic void act() %. tDD* %4 i9 (t U 9ra(e&peed 11 0) %! t10* %% currentRra(e 1 (currentRra(e D 1) U spriteCa(es."en#t<* %+ ,

33

%%2

Los descendientes de esta c ase tendr'an -ue preocuparse cada uno de estab ecer su propia ve ocidad de 1otogramas6 Por e.emp o a c ase ,onster -uedar'a as': ,onster6.ava 13 _66 1! pub ic ,onster@Stage stageA H 1# super@stageAG 1& setSpriteBames@ neD StringMN H;bic:o06gi1;8;bic:o16gi1;LAG 1+ setRra(e&peed(.!)* 1* L 1+ _6 Iaber dec arado a variab e `ta como protegida permitir" a os descendientes uti i%ar a misma variab e para :acer otros c" cu os basados en a base de tiempos com0n @por e.emp o8 determinar cuando :a< -ue disparar8 cuando debe ;mutar; un monstruo8 etc666

1%. $" 0u#ador: 4 .ugador no es m"s -ue un actor -ue adem"s puede ser contro ado por e usuario mediante e tec ado o e ratn6 Kamos a :acer o descender de 7ctor < adem"s vamos a adoptar as siguientes premisas en cuanto a su comportamiento8 para poder mode ar a c ase de 1orma correcta: La nave de .ugador se puede mover en todas as direcciones posib es6 La ve ocidad de movimiento de .ugador es siempre a misma8 aun-ue var'e a direccin6 Para -ue a nave se mueva en una direccin dada8 ser" necesario -ue a tec a correspondiente est9 pu sada6

/e estas tres premisas -ueda c aro -ue a nave de .ugador es simi ar a un monstruo8 con a 0nica e=cepcin de -ue tiene una ve ocidad = < una ve ocidad <6 Para e gr"1ico vamos a

uti i%ar e siguiente - -ue ser" adem"s e 0nico 1otograma: /ic:o esto8 a c ase -uedar'a como sigue @todav'a no :emos incorporado e contro de movimientoA:

+ pacFage version1&G 10 11 pub ic c ass P a<er e=tends 7ctor H 12 protected int v=G 13 protected int v<G 1! 1# 1& pub ic P a<er@Stage stageA H

P a<er6.ava

34

1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 31 32 33 3! 3# 3&

super@stageAG setSpriteBames@ neD StringMN H;nave6gi1;LAG

pub ic void act@A H super6act@AG =VJv=G <VJv<G i1 @= Y 0 ZZ = X Stage6EI/>IA v= J -v=G i1 @< Y 0 ZZ < X Stage6I4ICI>A v< J -v<G L pub ic int getK=@A H return v=G L pub ic void setK=@int iA Hv= J iG L pub ic int getK<@A H return v<G L pub ic void setK<@int iA Hv< J iG L

Lgicamente tendremos -ue modi1icar a c ase principa para dar acomodo a .ugador6 Bo a5adiremos e .ugador a a ista de actores de escenario por-ue e .ugador es un actor -ue va a tener un tratamiento tota mente especia 8 a di1erencia de todos os dem"s6 Sin embargo8 as cosas -ue se :acen con 9 en principio ser"n as mismas - pintar o8 decir e -ue act0e8 etc666

1 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 .1 32

pacFage version1&G import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt6Crap:ics2/G import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11erStrateg<G import .ava6uti 67rra<ListG import .ava=6sDing6J3rameG import .ava=6sDing6JPane G

Invaders6.ava

pub ic c ass Invaders e=tends Canvas imp ements Stage H private )u11erStrateg< strateg<G private ong used>imeG private SpriteCac:e spriteCac:eG private 7rra<List actorsG private /"a'er p"a'er*

35

33 3! 3# 3( 3* 3+ !0 !1 !2 !3 !! !# !& !( !* !+ #0 #1 #2 #3 #! ## #& #( #* #+ &0 &1 &2 &3 &! &# %+ %%2 +0 (1 (3 (! (# (& (( +(+ *0 *1 *2 *3 *! *#

pub ic Invaders@A H spriteCac:e J neD SpriteCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG

pub ic void initEor d@A H actors J neD 7rra<List@AG 1or @int i J 0G i Y 10G iVVAH ,onster m J neD ,onster@t:isAG m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG m6setR@ i[20 AG m6setK=@ @intA@,at:6random@A[20-10A AG actors6add@mAG p"a'er 1 new /"a'er(t<is)* p"a'er.setG(&ta#e.WI567;2)* p"a'er.setH(&ta#e.7$I876 > 2Ip"a'er.#et7ei#<t())* p"a'er.setJ)(!)*

L pub ic void updateEor d@A H 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6act@AG L p"a'er.act()* L

pub ic void paintEor d@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG g6setCo or@Co or6b acFAG g61i 2ect@0808getEidt:@A8getIeig:t@AAG 1or @int i J 0G i Y actors6si%e@AG iVVA H

36

*& 7ctor m J @7ctorAactors6get@iAG *( m6paint@gAG ** L -2 p"a'er.paint(#)* +0 +1 g6setCo or@Co or6D:iteAG +2 i1 @used>ime X 0A +3 g6draDString@String6va ue$1@1000Uused>imeAV; 1ps;808Stage6I4ICI>-#0AG +! e se +# g6draDString@;--- 1ps;808Stage6I4ICI>-#0AG +& strateg<6s:oD@AG +( L +* ++ pub ic SpriteCac:e getSpriteCac:e@A H 100 return spriteCac:eG 101 L 102 103 pub ic void game@A H 10! used>imeJ1000G 10# initEor d@AG 10& D:i e @isKisib e@AA H 10( ong start>ime J S<stem6current>ime,i is@AG 10* updateEor d@AG 10+ paintEor d@AG 110 used>ime J S<stem6current>ime,i is@A-start>imeG 111 tr< H 112 >:read6s eep@Stage6SP44/AG 113 L catc: @Interrupted4=ception eA HL 11! L 11# L 11( pub ic static void main@StringMN argsA H 11* Invaders inv J neD Invaders@AG 11+ inv6game@AG 120 L 121 L

37

1+. Contro"ando e" ju#ador: La versin anterior de programa mostraba e .ugador pero no permit'a -ue e mismo pudiera ser contro ador por e usuario6 4n esta versin a5adiremos a posibi idad de contro ar a nave de .ugador con e tec ado8 uti i%ando para e o todas as tec as de cursor6 7un-ue podr'amos gestionar esto en a c ase Invaders8 o m"s correcto ser'a de egar a gestin de evento a a c ase P a<er8 de 1orma -ue e p anteamiento -ue seguiremos es: 16 La c ase Invaders recibir" todos os eventos de tec ado6 26 Cuando ocurra un evento8 a c ase primero procesar" as tec as -ue tengan -ue ver con e .uego en genera @en e caso de :aber asA8 como por e.emp o ;pausar;8 ;sa ir; o simi ares @de momento no tenemos ninguna de estas8 pero -ueremos mantener a 1 e=ibi idad de poder a5adir as en e 1uturoA6 36 Cuando :a<amos determinado -ue a tec a pu sada no interesa a .uego en genera 8 e pasaremos os datos de esta tec a a p a<er para -ue act0e como buenamente crea oportuno6 /e1iniremos dos nuevos m9todo en a c ase P a<er amados Fe<Pressed@666A < Fe<2e eased@666A8 -ue ser"n os encargados de recibir as noti1icaciones de -ue :a sido pu sadaUso tada una tec a6 Con a descripcin anterior8 a c ase Invaders -ueda como sigue:

1 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 31 32 33 3! 3#

pacFage version1(G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt6Crap:ics2/G import .ava6aDt6event6Se<4ventG import .ava6aDt6event6Se<ListenerG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11erStrateg<G import .ava6uti 67rra<ListG import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas imp ements Stage8 We'Listener H private )u11erStrateg< strateg<G private ong used>imeG private SpriteCac:e spriteCac:eG private 7rra<List actorsG private P a<er p a<erG pub ic Invaders@A H

38

3& 3* 3+ !0 !1 !2 !3 !! !# !& !( !* !+ #0 #1 #2 #3 #! ## !% #( #+ &0 &1 &2 &3 &! &# && &( &* (0 (1 (2 (3 (( (* (+ *0 *1 *2 *3 *# *& *( ** *+ +0 +1 +2

spriteCac:e J neD SpriteCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG addWe'Listener(t<is)*

L pub ic void initEor d@A H actors J neD 7rra<List@AG 1or @int i J 0G i Y 10G iVVAH ,onster m J neD ,onster@t:isAG m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG m6setR@ i[20 AG m6setK=@ @intA@,at:6random@A[20-10A AG actors6add@mAG

L pub ic void updateEor d@A H 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6act@AG L p a<er6act@AG L pub ic void paintEor d@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG g6setCo or@Co or6b acFAG g61i 2ect@0808getEidt:@A8getIeig:t@AAG 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6paint@gAG L

L p a<er J neD P a<er@t:isAG p a<er6setW@Stage6EI/>IU2AG p a<er6setR@Stage6I4ICI> - 2[p a<er6getIeig:t@AAG

39

+3 p a<er6paint@gAG +# g6setCo or@Co or6D:iteAG +& i1 @used>ime X 0A +( g6draDString@String6va ue$1@1000Uused>imeAV; 1ps;808Stage6I4ICI>-#0AG +* e se ++ g6draDString@;--- 1ps;808Stage6I4ICI>-#0AG 100 strateg<6s:oD@AG 101 L 103 pub ic SpriteCac:e getSpriteCac:e@A H 10! return spriteCac:eG 10# L 10+ pub"ic void Ke'/ressed(We'$vent e) 10p"a'er.Ke'/ressed(e)* 102 , 111 pub"ic void Ke'Ae"eased(We'$vent e) 112 p"a'er.Ke'Ae"eased(e)* 11. , 114 pub"ic void Ke'6'ped(We'$vent e) , 11# 11& pub ic void game@A H 11( used>imeJ1000G 11* initEor d@AG 11+ D:i e @isKisib e@AA H 120 ong start>ime J S<stem6current>ime,i is@AG 121 updateEor d@AG 122 paintEor d@AG 123 used>ime J S<stem6current>ime,i is@A-start>imeG 12! tr< H 12# >:read6s eep@SP44/AG 12& L catc: @Interrupted4=ception eA HL 12( L 12* L 130 pub ic static void main@StringMN argsA H 131 Invaders inv J neD Invaders@AG 132 inv6game@AG 133 L 13! L
R a c ase de .ugador pasa a ser:

+ pacFage version1(G 10 11 i(port java.awt.event.We'$vent* 12 13 pub ic c ass P a<er e=tends 7ctor H 14 protected static 9ina" int /LAH$AP&/$$5 1 4* 1# protected int v=G 1& protected int v<G 1+ private boo"ean up4down4"e9t4ri#<t*

P a<er6.ava

40

20 21 22 23 2# 2& 2( 2* 2+ 30 31 32 33 3! 3# 3& 3( 3* 3+ 41 42 4. 44 4! 4% 4+ 42 !0 !1 !2 !. !4 !! !% !+ !2 %0 %1 %2 %. %4 %! %% %+ %2

pub ic P a<er@Stage stageA H super@stageAG setSpriteBames@ neD StringMN H;nave6gi1;LAG L pub ic void act@A H super6act@AG =VJv=G <VJv<G i1 @= Y 0 ZZ = X Stage6EI/>IA v= J -v=G i1 @< Y 0 ZZ < X Stage6I4ICI>A v< J -v<G L pub ic pub ic pub ic pub ic int getK=@A H return v=G L void setK=@int iA Hv= J iG L int getK<@A H return v<G L void setK<@int iA Hv< J iG L

protected void update&peed() v)10*v'10* i9 (down) v' 1 /LAH$AP&/$$5* i9 (up) v' 1 >/LAH$AP&/$$5* i9 ("e9t) v) 1 >/LAH$AP&/$$5* i9 (ri#<t) v) 1 /LAH$AP&/$$5* , pub"ic void Ke'Ae"eased(We'$vent e) switc< (e.#etWe'Code()) case We'$vent.JWP5=WC : down 1 9a"se*breaK* case We'$vent.JWP@/ : up 1 9a"se* breaK* case We'$vent.JWPL$R6 : "e9t 1 9a"se* breaK* case We'$vent.JWPAI876 : ri#<t 1 9a"se*breaK* , update&peed()* , pub"ic void Ke'/ressed(We'$vent e) switc< (e.#etWe'Code()) case We'$vent.JWP@/ : up 1 true* breaK* case We'$vent.JWPL$R6 : "e9t 1 true* breaK* case We'$vent.JWPAI876 : ri#<t 1 true* breaK* case We'$vent.JWP5=WC : down 1 true*breaK* , update&peed()* ,

Se puede ver -ue :emos de1inido tambi9n una constante amada PL7R42bSP44/ -ue determina a ve ocidad de .ugador8 de 1orma -ue as tec as 0nicamente cambian a direccin de movimiento8 pero no a ve ocidad6

41

1-. 5isparos: Ia egado e momento de a5adir a go de vio encia a nuestro pac'1ico .uego - a posibi idad de -ue e .ugador dispare6 Bos con1ormaremos inicia mente con poder disparar < de momento de.aremos e e1ecto -ue os disparos producen sobre e entorno @en particu ar os monstruosA para m"s ade ante6 Buestros disparos tendr"n as siguientes premisas: 16 4 disparo aparece .usto encima de a nave de .ugador 26 Los disparos se mueven :acia arriba8 siempre a a misma ve ocidad 36 4 .ugador s o puede disparar cinco misi es cada ve% /esde e punto de vista de programa8 os disparos son simp emente actores6 Lo novedoso es -ue os disparos aparecen < desaparecen sobre a marc:a < dependiendo de circunstancias -ue e buc e principa de programa no contro a6 Por e.emp o8 cuando se pu sa a barra espaciadora8 aparece un disparo6 4ste actor debe ser a5adido a a ista8 pero a gestin de as tec as a :ace a c ase P a<er8 < no ser'a correcto -ue esta c ase ;metiera a mano; dentro de a ista de actores8 <a -ue esta ista es una estructura de datos propia de a c ase Invaders6 ?na so ucin es dotar a escenario de m9todos -ue permitan a5adir < -uitar actores sobre a marc:a6 Con esta idea8 a inter1a% Stage -uedar'a de a siguiente 1orma:

+ 10 11 12 13 1! 1# 1& 1( 11+

pacFage version1*G

Stage6.ava

import .ava6aDt6image6Image$bserverG pub ic inter1ace Stage e=tends Image$bserver H pub ic static 1ina int EI/>IJ&!0G pub ic static 1ina int I4ICI>J!*0G pub ic static 1ina int SP44/J10G pub ic SpriteCac:e getSpriteCac:e@AG pub"ic void addActor(Actor a)* L

7:ora bien8 :a< un prob ema importante -ue no es obvio a primera vista: O-ui9n borra os actoresQ Lo primero -ue se nos podr'a ocurrir es a5adir un m9todo remove7ctor@666A igua -ue e otro6 Pero surge un prob ema < es -ue es posib e -ue e borrado de un actor se :aga como respuesta a a pu sacin de una tec a8 o bien como consecuencia de un m9todo act@A de otro actor @caso de os disparosA6 4n e primer caso8 e borrado se estar'a produciendo desde un :i o distinto a principa @nada bueno <a -ue estar'amos manipu ando una estructura de datos desde un :i o8 mientras -ue desde e principa ta ve% a estemos recorriendoA6 4n e segundo caso8 estar'amos en una situacin simi ar - podr'a producirse un desa.uste en e buc e < -ue e m9todo act@A de a g0n actor no 1uese amado6 Para evitar ambas situaciones8 en ugar de borrar un actor directamente de1iniremos una marca -ue indi-ue -ue un actor determinado est" ;marcado para ser borrado;6 Posteriormente ser" e buc e principa e 0nico -ue comprobar" dic:a marca < e iminar" e actor si procede: 4sto re-uiere una modi1icacin a a c ase 7ctor de a siguiente 1orma:

42

+ 10 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 2. 2! 2# 2& 2( 2* 2+ 30 31 32 .. .4 .! 3& .+ ..2 !0 !1 !2 !3 !! !# !& !( !* !+ #0 #1 #2 #3 #! ## #&

pacFage version1*G

7ctor6.ava

import .ava6aDt6Crap:ics2/G import .ava6aDt6image6)u11eredImageG pub ic c ass 7ctor H protected int =8<G protected int Didt:8 :eig:tG protected StringMN spriteBamesG protected int current3rameG protected int 1rameSpeedG protected int tG protected Stage stageG protected SpriteCac:e spriteCac:eG protected boo"ean (arKedRorAe(ova"* pub ic 7ctor@Stage stageA H t:is6stage J stageG spriteCac:e J stage6getSpriteCac:e@AG current3rame J 0G 1rameSpeed J 1G tJ0G L pub"ic void re(ove() (arKedRorAe(ova" 1 true* , pub"ic boo"ean isEarKedRorAe(ova"() return (arKedRorAe(ova"* , pub ic void paint@Crap:ics2/ gAH g6draDImage@ spriteCac:e6getSprite@spriteBamesMcurrent3rameNA8 =8<8 stage AG L pub ic int getW@A H return =G L pub ic void setW@int iA H = J iG L pub ic int getR@A H return <G L pub ic void setR@int iA H < J iG L pub ic int get3rameSpeed@A Hreturn 1rameSpeedG L pub ic void set3rameSpeed@int iA H1rameSpeed J iG L

pub ic void setSpriteBames@StringMN namesA H spriteBames J namesG

43

#( #* #+ &0 &1 &2 &3 &! && &( &* &+ (0 (1 (2 (3 (! (# (& (( (*

L pub ic pub ic pub ic pub ic

:eig:t J 0G Didt: J 0G 1or @int i J 0G i Y names6 engt:G iVV A H )u11eredImage image J spriteCac:e6getSprite@spriteBamesMiNAG :eig:t J ,at:6ma=@:eig:t8image6getIeig:t@AAG Didt: J ,at:6ma=@Didt:8image6getEidt:@AAG L int getIeig:t@A H return :eig:tG L int getEidt:@A H return Didt:G L void setIeig:t@int iA H:eig:t J iG L void setEidt:@int iA H Didt: J iG L

pub ic void act@A H tVVG i1 @t ] 1rameSpeed JJ 0AH tJ0G current3rame J @current3rame V 1A ] spriteBames6 engt:G L L

Los m9todos updateEor d@A < add7ctor@A de a c ase Invaders6.ava -uedar'an de a siguiente 1orma:

(# (& (( (+ -0 -1 -2 -. -4 -! -% -+ --2 20 21

666 pub ic void add7ctor@7ctor aA H actors6add@aAG L pub ic void updateEor d@A H int i 1 0* w<i"e (i L actors.si:e()) Actor ( 1 (Actor)actors.#et(i)* i9 ((.isEarKedRorAe(ova"()) actors.re(ove(i)* , e"se (.act()* iDD* , , p"a'er.act()* , . . .

Invaders6.ava

?na ve% -ue :emos resue to os prob emas de adicin < e iminacin de actores8 podemos comen%ar a a5adir a gestin de os disparos6 Para e disparo uti i%aremos e siguiente gr"1ico8 amado ;disparo6gi1;:

44

Los disparos8 a tener su propio comportamiento8 van a estar representados por una nueva c ase amada )u et:

+ pacFage version1*G 10 12 pub ic c ass )u et e=tends 7ctor H 13 protected static 1ina int )?LL4>bSP44/J10G 1! 1# pub ic )u et@Stage stageA H 1& super@stageAG 1( setSpriteBames@ neD StringMN H;misi 6gi1;LAG 1* L 20 pub ic void act@A H 21 super6act@AG 22 <-J)?LL4>bSP44/G 23 i1 @< Y 0A 2! remove@AG 2# L 2& L
Se puede ver -ue e metodo act@A borra autom"ticamente e disparo cuando detecta -ue :a sa ido por a parte superior de a panta a6 Por 0 timo8 -ueda a5adir a gestin de a tec a de disparo a a c ase P a<er:

/isparos6.ava

+ pacFage version1*G 10 11 import .ava6aDt6event6Se<4ventG 12 13 pub ic c ass P a<er e=tends 7ctor H 1! protected static 1ina int PL7R42bSP44/ J !G 1# protected int v=G 1& protected int v<G 1( private boo ean up8doDn8 e1t8rig:tG 1* 20 pub ic P a<er@Stage stageA H 21 super@stageAG 22 setSpriteBames@ neD StringMN H;nave6gi1;LAG 23 L 2# pub ic void act@A H 2& super6act@AG 2( =VJv=G 2* <VJv<G 2+ i1 @= Y 0 ZZ = X Stage6EI/>IA 30 v= J -v=G 31 i1 @< Y 0 ZZ < X Stage6I4ICI>A 32 v< J -v<G 33 L 3# pub ic int getK=@A H return v=G L

7ctor6.ava

45

3& 3( 3* 3+ !1 !2 !3 !! !# !& !( !+ #0 #1 #2 #3 #! ## #& #( #+ &0 &1 &2 &3 &! %! && &( &* +0 +1 +2 +. +4 +! ((

pub ic void setK=@int iA Hv= J iG L pub ic int getK<@A H return v<G L pub ic void setK<@int iA Hv< J iG L protected void updateSpeed@A H v=J0Gv<J0G i1 @doDnA v< J PL7R42bSP44/G i1 @upA v< J -PL7R42bSP44/G i1 @ e1tA v= J -PL7R42bSP44/G i1 @rig:tA v= J PL7R42bSP44/G L pub ic void Fe<2e eased@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb/$EB : doDn J 1a seGbreaFG case Se<4vent6KSb?P : up J 1a seG breaFG case Se<4vent6KSbL43> : e1t J 1a seG breaFG case Se<4vent6KSb2ICI> : rig:t J 1a seGbreaFG L updateSpeed@AG L pub ic void Fe<Pressed@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb?P : up J trueG breaFG case Se<4vent6KSbL43> : e1t J trueG breaFG case Se<4vent6KSb2ICI> : rig:t J trueG breaFG case Se<4vent6KSb/$EB : doDn J trueGbreaFG case We'$vent.JWP&/AC$ : 9ire()* breaK* L updateSpeed@AG L pub"ic void 9ire() 3u""et b 1 new 3u""et(sta#e)* b.setG())* b.setH(' > b.#et7ei#<t())* sta#e.addActor(b)* ,

46

12. E?s disparos > 3o(bas de 9ra#(entacin: Kamos a comprobar as de icias de a programacin orientada a ob.etos a5adiendo un nuevo tipo de disparo - a ;bomba de 1ragmentacin;6 4 usuario tendr" un n0mero imitado de estas bombas @supongamos inicia mente #A < cada ve% -ue dispare una8 aparecer"n oc:o bo as de 1uego -ue sa dr"n despedidas en as oc:o direcciones posib es6 Para este propsito uti i%aremos os siguientes gr"1icos:

bomb?L6gi1 bombL6gi1 bomb/L6gi1

bomb?6gi1

bomb?26gi1 bomb26gi1 bomb/26gi1

bomb/6gi1

La bo a de 1uego tendr" su propia c ase8 amada )omb8 con e siguiente aspecto:

+ pacFage version1+G 11 12 pub ic c ass )omb e=tends 7ctor H 13 pub ic static 1ina int ?PbL43> J 0G 1! pub ic static 1ina int ?P J 1G 1# pub ic static 1ina int ?Pb2ICI> J 2G 1& pub ic static 1ina int L43> J 3G 1( pub ic static 1ina int 2ICI> J !G 1* pub ic static 1ina int /$EBbL43> J #G 1+ pub ic static 1ina int /$EB J &G 20 pub ic static 1ina int /$EBb2ICI> J (G 21 22 protected static 1ina int )$,)bSP44/ J #G 23 protected int v=G 2! protected int v<G 2# 2& pub ic )omb@Stage stage8 int :eading8 int =8 int <A H 2( super@stageAG 2* t:is6= J =G 2+ t:is6< J <G 30 String sprite J;;G 31 sDitc: @:eadingA H 32 case ?PbL43>: v= J -)$,)bSP44/G v< J -)$,)bSP44/G spriteJ;bomb?L6gi1;GbreaFG 33 case ?P : v= J 0G v< J -)$,)bSP44/G spriteJ;bomb?6gi1;GbreaFG 3! case ?Pb2ICI>: v= J )$,)bSP44/G v< J -)$,)bSP44/G spriteJ;bomb?26gi1;GbreaFG 3# case L43> : v= J -)$,)bSP44/G v< J 0G sprite J ;bombL6gi1;GbreaFG 3& case 2ICI> : v= J )$,)bSP44/G v< J 0G sprite J ;bomb26gi1;GbreaFG

)omb6.ava

47

3( 3* 3+ !0 !1 !2 !3 !! !# !& !( !* !+ #0 #1 L

case /$EBbL43> : v= J -)$,)bSP44/G v< J )$,)bSP44/G spriteJ;bomb/L6gi1;GbreaFG case /$EB : v= J 0G v< J )$,)bSP44/G sprite J ;bomb/6gi1;GbreaFG case /$EBb2ICI> : v= J )$,)bSP44/G v< J )$,)bSP44/G sprite J ;bomb/26gi1;GbreaFG L setSpriteBames@ neD StringMN HspriteLAG L pub ic void act@A H super6act@AG <VJv<G =VJv=G i1 @< Y 0 ZZ < X Stage6I4ICI> ZZ = Y 0 ZZ = X Stage6EI/>IA remove@AG L

2especto a os otros actores8 a novedad de este es -ue e aspecto visua cambia seg0n a direccin en a -ue se mueve6 7dem"s podemos ver -ue e m9todo act@A se imita a mover a bomba < borrar a si se sa e de a panta a en a g0n momento La c ase P a<er debe ser modi1icada para evar e contador de as bombas de as -ue disponemos < para :acer -ue a pu sar una tec a especia @en nuestro e.emp o ser" ;);A se disparen as oc:o bo as de 1uego:

+ pacFage version1+G 10 11 import .ava6aDt6event6Se<4ventG 12 13 pub ic c ass P a<er e=tends 7ctor H 1! protected static 1ina int PL7R42bSP44/ J !G 1# protected int v=G 1& protected int v<G 1( private boo ean up8doDn8 e1t8rig:tG 1private int c"uster3o(bs* 20 21 pub ic P a<er@Stage stageA H 22 super@stageAG 23 setSpriteBames@ neD StringMN H;nave6gi1;LAG 24 c"uster3o(bs 1 !* 2# L 2( pub ic void act@A H 2* super6act@AG 2+ =VJv=G 30 <VJv<G 31 i1 @= Y 0 ZZ = X Stage6EI/>IA 32 v= J -v=G 33 i1 @< Y 0 ZZ < X Stage6I4ICI>A 3! v< J -v<G

P a<er6.ava

48

3# 3( 3* 3+ !0 !2 !3 !! !# !& !( !* !+ #1 #2 #3 #! ## #& #( #* #+ &1 &2 &3 &! &# && &( %&+ (0 (1 (3 (! (# (& (( (* -0 -1 -2 -. -4 -! -% -+ --2 20

L pub ic pub ic pub ic pub ic

int getK=@A H return v=G L void setK=@int iA Hv= J iG L int getK<@A H return v<G L void setK<@int iA Hv< J iG L

protected void updateSpeed@A H v=J0Gv<J0G i1 @doDnA v< J PL7R42bSP44/G i1 @upA v< J -PL7R42bSP44/G i1 @ e1tA v= J -PL7R42bSP44/G i1 @rig:tA v= J PL7R42bSP44/G L pub ic void Fe<2e eased@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb/$EB : doDn J 1a seGbreaFG case Se<4vent6KSb?P : up J 1a seG breaFG case Se<4vent6KSbL43> : e1t J 1a seG breaFG case Se<4vent6KSb2ICI> : rig:t J 1a seGbreaFG L updateSpeed@AG L pub ic void Fe<Pressed@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb?P : up J trueG breaFG case Se<4vent6KSbL43> : e1t J trueG breaFG case Se<4vent6KSb2ICI> : rig:t J trueG breaFG case Se<4vent6KSb/$EB : doDn J trueGbreaFG case Se<4vent6KSbSP7C4 : 1ire@AG breaFG case We'$vent.JWP3 : 9ireC"uster()* breaK* L updateSpeed@AG L pub ic void 1ire@A H )u et b J neD )u et@stageAG b6setW@=AG b6setR@< - b6getIeig:t@AAG stage6add7ctor@bAG L pub"ic void 9ireC"uster() i9 (c"uster3o(bs 11 0) return* c"uster3o(bs>>* sta#e.addActor( sta#e.addActor( sta#e.addActor( sta#e.addActor( sta#e.addActor( sta#e.addActor(

new new new new new new

3o(b(sta#e4 3o(b(sta#e4 3o(b(sta#e4 3o(b(sta#e4 3o(b(sta#e4 3o(b(sta#e4

3o(b.@/PL$R64 )4'))* 3o(b.@/4)4'))* 3o(b.@/PAI8764)4'))* 3o(b.L$R64)4'))* 3o(b.AI8764)4'))* 3o(b.5=WCPL$R64)4'))*

49

21 22 2. 2!

sta#e.addActor( new 3o(b(sta#e4 3o(b.5=WC4)4'))* sta#e.addActor( new 3o(b(sta#e4 3o(b.5=WCPAI8764)4'))*

20. 5eteccin de co"isiones: Iasta a:ora os monstruos se :ab'an reido en nuestra cara de nuestros disparos por-ue ninguno de e os es a1ectaba o m"s m'nimo6 Ia egado a :ora de a5adir a deteccin de co isiones a nuestro programa6 4n genera es errneo p antearse a deteccin de co isiones como un asunto de ob.etos puntua es8 <a -ue nuestros sprites tienen tanto anc:uras como a turas6 /e esta 1orma8 :abr" una co isin cuando os rect"ngu os -ue encierran cada sprite se intersecten:

4sta comprobacin :abr" -ue :acer a para todas as posib es pare.as de actores 8 < adem"s :abr" -ue :acer a para cada actor con e .ugador6 4sta comprobacin puesto -ue invo ucra mane.ar a ista g oba de actores8 a debe :acer a c ase Invaders6 71ortunadamente8 a c ase 2ectang e de Java incorpora e m9todo intersects@A -ue permite comprobar si un rect"ngu o intersecta con otro6 Como necesitaremos saber os rect"ngu os -ue eng oban cada sprite8 podemos a5adir un m9todo @por e.emp o get)ounds@AA en a c ase 7ctor -ue <a devue va e ob.eto 2ectang e construido6 Cuando detectamos una co isin8 O-u9 es o -ue :a< -ue :acerQ6 /e nuevo ec:amos mano de po imor1ismo < de a de egacin de responsabi idades < o -ue :aremos ser" imitarnos a noti1icar a cada actor -ue se :a producido una co isin con otro actor8 < -ue e os decidan o -ue :acer en consecuencia6 4sto signi1ica -ue aparece un nuevo m9todo en a c ase 7ctor amado co ision@666A6 Por de1ecto este m9todo no :ace nada8 siendo as c ases :i.as as responsab es de sobreescribir o como buenamente crean oportuno:

(+ *0

666

7ctor6.ava

pub ic 2ectang e get)ounds@A H

50

*1 *2 *! *& *(

L pub ic void co ision@7ctor aAH L

return neD 2ectang e@=8<8Didt:8:eig:tAG;;&i no <asces t<is.)4 t<is.' ;; (co(pi"ador 1.%.0) tienes resu"tados inesperados

Lgicamente8 -ueremos -ue os monstruos mueran cuando ocurre una co isin con un misi o una bomba6 4sto se rea i%a de a siguiente 1orma en a c ase ,onster:

,osnter6.ava 11 pub ic c ass ,onster e=tends 7ctor H 12 protected int v=G 13 1! pub ic ,onster@Stage stageA H 1# super@stageAG 1& setSpriteBames@ neD StringMN H;bic:o06gi1;8;bic:o16gi1;LAG 1( set3rameSpeed@3#AG 1* L 20 pub ic void act@A H 21 super6act@AG 22 =VJv=G 23 i1 @= Y 0 ZZ = X Stage6EI/>IA 2! v= J -v=G 2# L 2( pub ic int getK=@A H return v=G L 2* pub ic void setK=@int iA Hv= J iG L 2+ .0 pub"ic void co""ision(Actor a) .1 i9 (a instanceo9 3u""et MM a instanceo9 3o(b) .2 re(ove()* .. , 3! L
R 1ina mente -ueda a propia deteccin de co isiones8 -ue se rea i%a en a c ase principa 8 en un nuevo m9todo a -ue :emos amado c:ecFCo isions@A:

Invaders6.ava 1 pacFage version20G 11 12 import .ava6aDt6CanvasG 13 import .ava6aDt6Co orG 1! import .ava6aDt6/imensionG 1# import .ava6aDt6Crap:ics2/G 1& import .ava6aDt62ectang eG 1( import .ava6aDt6event6Se<4ventG 1* import .ava6aDt6event6Se<ListenerG 1+ import .ava6aDt6event6EindoD7dapterG

51

20 import .ava6aDt6event6EindoD4ventG 21 import .ava6aDt6image6)u11erStrateg<G 22 import .ava6uti 67rra<ListG 23 2! import .ava=6sDing6J3rameG 2# import .ava=6sDing6JPane G 2& 2( pub ic c ass Invaders e=tends Canvas imp ements Stage8 Se<Listener H 2* 2+ private )u11erStrateg< strateg<G 30 private ong used>imeG 31 32 private SpriteCac:e spriteCac:eG 33 private 7rra<List actorsG 3! private P a<er p a<erG 3# 3& pub ic Invaders@A H 3( spriteCac:e J neD SpriteCac:e@AG 3* !0 J3rame ventana J neD J3rame@;Invaders;AG !1 JPane pane J @JPane Aventana6getContentPane@AG !2 set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG !3 pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG !! pane 6setLa<out@nu AG !# pane 6add@t:isAG !& ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG !( ventana6setKisib e@trueAG !* ventana6addEindoDListener@ neD EindoD7dapter@A H !+ pub ic void DindoDC osing@EindoD4vent eA H #0 S<stem6e=it@0AG #1 L #2 LAG #3 ventana6set2esi%ab e@1a seAG #! create)u11erStrateg<@2AG ## strateg< J get)u11erStrateg<@AG #& re-uest3ocus@AG #( addSe<Listener@t:isAG #* L #+ &0 pub ic void initEor d@A H &1 actors J neD 7rra<List@AG &2 1or @int i J 0G i Y 10G iVVAH &3 ,onster m J neD ,onster@t:isAG &! m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG &# m6setR@ i[20 AG && m6setK=@ @intA@,at:6random@A[20-10A AG &( &* actors6add@mAG &+ L (0

52

(1 (2 (3 (! (# (& (( (* (+ *0 *1 *2 *3 *! *# *& *( ** *+ +0 +1 +2 +3 24 2! 2% 2+ 222 100 101 102 10. 104 10! 10% 10+ 10102 110 111 112 11! 11# 11& 11( 11* 11+ 120 121

p a<er J neD P a<er@t:isAG p a<er6setW@Stage6EI/>IU2AG p a<er6setR@Stage6I4ICI> - 2[p a<er6getIeig:t@AAG

pub ic void add7ctor@7ctor aA H actors6add@aAG L pub ic void updateEor d@A H int i J 0G D:i e @i Y actors6si%e@AA H 7ctor m J @7ctorAactors6get@iAG i1 @m6is,arFed3or2emova @AA H actors6remove@iAG L e se H m6act@AG iVVG L L p a<er6act@AG L pub"ic void c<ecKCo""isions() Aectan#"e p"a'er3ounds 1 p"a'er.#et3ounds()* 9or (int i 1 0* i L actors.si:e()* iDD) Actor a1 1 (Actor)actors.#et(i)* Aectan#"e r1 1 a1.#et3ounds()* i9 (r1.intersects(p"a'er3ounds)) p"a'er.co""ision(a1)* a1.co""ision(p"a'er)* , 9or (int j 1 iD1* j L actors.si:e()* jDD) Actor a2 1 (Actor)actors.#et(j)* Aectan#"e r2 1 a2.#et3ounds()* i9 (r1.intersects(r2)) a1.co""ision(a2)* a2.co""ision(a1)* , , , , pub ic void paintEor d@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG g6setCo or@Co or6b acFAG g61i 2ect@0808getEidt:@A8getIeig:t@AAG 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6paint@gAG L

53

122 p a<er6paint@gAG 12! g6setCo or@Co or6D:iteAG 12# i1 @used>ime X 0A 12& g6draDString@String6va ue$1@1000Uused>imeAV; 1ps;808Stage6I4ICI>-#0AG 12( e se 12* g6draDString@;--- 1ps;808Stage6I4ICI>-#0AG 12+ strateg<6s:oD@AG 130 L 132 pub ic SpriteCac:e getSpriteCac:e@A H 133 return spriteCac:eG 13! L 13& pub ic void Fe<Pressed@Se<4vent eA H 13( p a<er6Fe<Pressed@eAG 13* L 1!0 pub ic void Fe<2e eased@Se<4vent eA H 1!1 p a<er6Fe<2e eased@eAG 1!2 L 1!3 pub ic void Fe<><ped@Se<4vent eA HL 1!! 1!# pub ic void game@A H 1!& used>imeJ1000G 1!( initEor d@AG 1!* D:i e @isKisib e@AA H 1!+ ong start>ime J S<stem6current>ime,i is@AG 1#0 updateEor d@AG 1!1 c<ecKCo""isions()* 1#2 paintEor d@AG 1#3 used>ime J S<stem6current>ime,i is@A-start>imeG 1#! tr< H 1## >:read6s eep@SP44/AG 1#& L catc: @Interrupted4=ception eA HL 1#( L 1#* L 1&0 pub ic static void main@StringMN argsA H 1&1 Invaders inv J neD Invaders@AG 1&2 inv6game@AG 1&3 L 1&! L
21. 3arra de estado: 7:ora -ue somos capaces de matar a os bic:os8 ser'a 0ti disponer de a guna c ase de puntuacin para motivarnos en nuestro =enocidio6 4n este paso a5adiremos una barra de estado en a parte in1erior de a panta a6 4sta barra contendr" o siguiente: ?n indicador de puntuacin6 ?n medidor de escudos6 ?na representacin gr"1ica de n0mero de bombas de 1ragmentacin -ue nos -uedan6 Como siempre8 nuestro contador 1ps6

54

Kamos a comen%ar primero por a puntuacin < os escudos6 4stos atributos pertenecen a a c ase de .ugador8 as' -ue os a5adiremos a '8 .unto con sus correspondientes m9todos de acceso6 Por otra parte8 en este punto me :e dado cuenta -ue es bastante mo esto -ue a nave de .ugador ;rebote; cuando ega a os 'mites de a panta a8 as' -ue :emos aprovec:ado para modi1icar este comportamiento < :acer -ue en su ugar si e .ugador trata de sa irse de a panta a8 simp emente se -ueda en e borde6

+ pacFage version21G 10 11 import .ava6aDt6event6Se<4ventG 12 13 pub ic c ass P a<er e=tends 7ctor H 14 pub"ic static 9ina" int EAGP&7I$L5& 1 200* 1! pub"ic static 9ina" int EAGP3=E3& 1 !* 1& protected static 1ina int PL7R42bSP44/ J !G 1( protected int v=G 1* protected int v<G 1+ private boo ean up8doDn8 e1t8rig:tG 20 private int c uster)ombsG 21 private int score* 22 private int s<ie"ds* 2# 2& 2( 222 .0 31 32 33 3! 3# 3& .+ ..2 40 41 42 4. 44 !# !( !* !+ #0 #2 #3 pub ic P a<er@Stage stageA H super@stageAG setSpriteBames@ neD StringMN H;nave6gi1;LAG c"uster3o(bs 1 EAGP3=E3&* s<ie"ds 1 EAGP&7I$L5&* score 1 0* L pub ic void act@A H super6act@AG =VJv=G <VJv<G i9 () L 0 ) ) 1 0* i9 () N &ta#e.WI567 > #etWidt<()) ) 1 &ta#e.WI567 > #etWidt<()* i9 (' L 0 ) ' 1 0* i9 ( ' N &ta#e./LAHP7$I876>#et7ei#<t()) ' 1 &ta#e./LAHP7$I876 > #et7ei#<t()* L pub ic int getK=@A H return v=G L pub ic void setK=@int iA Hv= J iG L pub ic int getK<@A H return v<G L pub ic void setK<@int iA Hv< J iG L protected void updateSpeed@A H

P a<er6.ava

55

#! v=J0Gv<J0G ## i1 @doDnA v< J PL7R42bSP44/G #& i1 @upA v< J -PL7R42bSP44/G #( i1 @ e1tA v= J -PL7R42bSP44/G #* i1 @rig:tA v= J PL7R42bSP44/G #+ L &1 pub ic void Fe<2e eased@Se<4vent eA H &2 sDitc: @e6getSe<Code@AA H &3 case Se<4vent6KSb/$EB : doDn J 1a seGbreaFG &! case Se<4vent6KSb?P : up J 1a seG breaFG &# case Se<4vent6KSbL43> : e1t J 1a seG breaFG && case Se<4vent6KSb2ICI> : rig:t J 1a seGbreaFG &( L &* updateSpeed@AG &+ L (1 pub ic void Fe<Pressed@Se<4vent eA H (2 sDitc: @e6getSe<Code@AA H (3 case Se<4vent6KSb?P : up J trueG breaFG (! case Se<4vent6KSbL43> : e1t J trueG breaFG (# case Se<4vent6KSb2ICI> : rig:t J trueG breaFG (& case Se<4vent6KSb/$EB : doDn J trueGbreaFG (( case Se<4vent6KSbSP7C4 : 1ire@AG breaFG (* case Se<4vent6KSb) : 1ireC uster@AG breaFG (+ L *0 updateSpeed@AG *1 L *3 pub ic void 1ire@A H *! )u et b J neD )u et@stageAG *# b6setW@=AG *& b6setR@< - b6getIeig:t@AAG *( stage6add7ctor@bAG ** L +0 pub ic void 1ireC uster@A H +1 i1 @c uster)ombs JJ 0A +2 returnG +! c uster)ombs--G +# stage6add7ctor@ neD )omb@stage8 )omb6?PbL43>8 =8<AAG +& stage6add7ctor@ neD )omb@stage8 )omb6?P8=8<AAG +( stage6add7ctor@ neD )omb@stage8 )omb6?Pb2ICI>8=8<AAG +* stage6add7ctor@ neD )omb@stage8 )omb6L43>8=8<AAG ++ stage6add7ctor@ neD )omb@stage8 )omb62ICI>8=8<AAG 100 stage6add7ctor@ neD )omb@stage8 )omb6/$EBbL43>8=8<AAG 101 stage6add7ctor@ neD )omb@stage8 )omb6/$EB8=8<AAG 102 stage6add7ctor@ neD )omb@stage8 )omb6/$EBb2ICI>8=8<AAG 103 L 10# pub ic int getScore@A H return scoreG L 10& pub ic void setScore@int iA H score J iG L 10( 10pub"ic int #et&<ie"ds() return s<ie"ds* , 102 pub"ic void set&<ie"ds(int i) s<ie"ds 1 i* ,

56

111 112 11# L

pub"ic int #etC"uster3o(bs() return c"uster3o(bs* , pub"ic void setC"uster3o(bs(int i) c"uster3o(bs 1 i* ,

Lo siguiente -ue debemos :acer es cambiar e tama5o de "rea de .uego8 <a -ue a:ora debemos reservar una parte para e redibu.o de estado actua 6 7s' -ue a5adimos una nueva constante amada PL7RbI4ICI> a a c ase Stage6 4sta constante contendr" e tama5o de "rea de .uego:

+ pacFage version21G 10 11 import .ava6aDt6image6Image$bserverG 12 13 pub ic inter1ace Stage e=tends Image$bserver H 1! pub ic static 1ina int EI/>IJ&!0G 1# pub ic static 1ina int I4ICI>J!*0G 1% pub"ic static 9ina" int /LAHP7$I876 1 400* 1( pub ic static 1ina int SP44/J10G 1* pub ic SpriteCac:e getSpriteCac:e@AG 1+ pub ic void add7ctor@7ctor aAG 20 L
4 ma<or cambio ocurrir" en a c ase Invaders8 donde a:ora tendremos cuatro m9todos para dibu.ar as di1erentes partes de a barra de estado:

Stage6.ava

1 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 31 32

pacFage version21G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt63ontG import .ava6aDt6Crap:ics2/G import .ava6aDt62ectang eG import .ava6aDt6event6Se<4ventG import .ava6aDt6event6Se<ListenerG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11erStrateg<G import .ava6aDt6image6)u11eredImageG import .ava6uti 67rra<ListG import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas imp ements Stage8 Se<Listener H private )u11erStrateg< strateg<G private ong used>imeG

57

3! 3# 3& 3( 3* 3+ !2 !3 !! !# !& !( !* !+ #0 #1 #2 #3 #! ## #& #( #* #+ &0 &2 &3 &! &# && &( &* &+ (0 (1 (3 (! (# (& (* (+ *0 *2 *3 *! *# *& *( ** *+

private SpriteCac:e spriteCac:eG private 7rra<List actorsG private P a<er p a<erG pub ic Invaders@A H spriteCac:e J neD SpriteCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG addSe<Listener@t:isAG L pub ic void initEor d@A H actors J neD 7rra<List@AG 1or @int i J 0G i Y 10G iVVAH ,onster m J neD ,onster@t:isAG m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG m6setR@ i[20 AG m6setK=@ @intA@,at:6random@A[20-10A AG actors6add@mAG

L pub ic void add7ctor@7ctor aA H actors6add@aAG L pub ic void updateEor d@A H int i J 0G D:i e @i Y actors6si%e@AA H 7ctor m J @7ctorAactors6get@iAG i1 @m6is,arFed3or2emova @AA H actors6remove@iAG L e se H m6act@AG

L p a<er J neD P a<er@t:isAG p a<er6setW@Stage6EI/>IU2AG p a<er6setR@Stage6PL7RbI4ICI> - 2[p a<er6getIeig:t@AAG

58

+0 +1 +2 +3 +! +& +( +* ++ 100 101 102 103 10! 10# 10& 10( 10* 10+ 110 111 112 113 11! 11% 11+ 11112 120 121 122 12. 12! 12+ 12122 1.0 1.1 1.2 1.. 1.! 1.% 1.+ 1.1.2 140 141 14. 144

L pub ic void c:ecFCo isions@A H 2ectang e p a<er)ounds J p a<er6get)ounds@AG 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor a1 J @7ctorAactors6get@iAG 2ectang e r1 J a16get)ounds@AG i1 @r16intersects@p a<er)oundsAA H p a<er6co ision@a1AG a16co ision@p a<erAG L 1or @int . J iV1G . Y actors6si%e@AG .VVA H 7ctor a2 J @7ctorAactors6get@.AG 2ectang e r2 J a26get)ounds@AG i1 @r16intersects@r2AA H a16co ision@a2AG a26co ision@a1AG L L L L pub"ic void paint&<ie"ds(8rap<ics25 #) #.set/aint(Co"or.red)* #.9i""Aect(2-04&ta#e./LAHP7$I8764/"a'er.EAGP&7I$L5&4.0)* #.set/aint(Co"or.b"ue)* #.9i""Aect(2-0D/"a'er.EAGP&7I$L5&> /"a'er.#et&<ie"ds()4&ta#e./LAHP7$I8764p"a'er.#et&<ie"ds()4.0)* #.setRont(new Ront(BAria"B4Ront.3=L5420))* #.set/aint(Co"or.#reen)* #.draw&trin#(B&<ie"dsB41+04&ta#e./LAHP7$I876D20)* , pub"ic void paint&core(8rap<ics25 #) #.setRont(new Ront(BAria"B4Ront.3=L5420))* #.set/aint(Co"or.#reen)* #.draw&trin#(B&core:B4204&ta#e./LAHP7$I876 D 20)* #.set/aint(Co"or.red)* #.draw&trin#(p"a'er.#et&core()DBB41004&ta#e./LAHP7$I876 D 20)* , pub"ic void paintA((o(8rap<ics25 #) int )3ase 1 2-0D/"a'er.EAGP&7I$L5&D10* 9or (int i 1 0* i L p"a'er.#etC"uster3o(bs()*iDD) 3u99eredI(a#e bo(b 1 spriteCac<e.#et&prite(Bbo(b@L.#i9B)* #.drawI(a#e( bo(b 4)3aseDiIbo(b.#etWidt<()4&ta#e./LAHP7$I8764t<is)* , , pub"ic void paint9ps(8rap<ics25 #) #.setRont( new Ront(BAria"B4Ront.3=L5412))*

L p a<er6act@AG

iVVG

59

14! 14% 14+ 14142 1!0 1!. 1!4 1!! 1!% 1!+ 1!1&0 1&1 1&2 1&3 1&! 1&# 1&& 1&( 1&* 1+1 1(2 1(3 1(# 1(& 1(( 1(+ 1*0 1*1 1*3 1*! 1*# 1*& 1*( 1** 1*+ 1+0 1+1 1+2 1+3 1+! 1+# 1+& 1+( 1+* 1++ 200 201

, pub"ic void paint&tatus(8rap<ics25 #) paint&core(#)* paint&<ie"ds(#)* paintA((o(#)* paint9ps(#)* , pub ic void paintEor d@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG g6setCo or@Co or6b acFAG g61i 2ect@0808getEidt:@A8getIeig:t@AAG 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6paint@gAG L p a<er6paint@gAG paint&tatus(#)* strateg<6s:oD@AG L pub ic SpriteCac:e getSpriteCac:e@A H return spriteCac:eG L pub ic void Fe<Pressed@Se<4vent eA H p a<er6Fe<Pressed@eAG L pub ic void Fe<2e eased@Se<4vent eA H p a<er6Fe<2e eased@eAG L pub ic void Fe<><ped@Se<4vent eA HL pub ic void game@A H used>imeJ1000G initEor d@AG D:i e @isKisib e@AA H ong start>ime J S<stem6current>ime,i is@AG updateEor d@AG c:ecFCo isions@AG paintEor d@AG used>ime J S<stem6current>ime,i is@A-start>imeG tr< H >:read6s eep@SP44/AG L catc: @Interrupted4=ception eA HL L L

#.setCo"or(Co"or.w<ite)* i9 (used6i(e N 0) #.draw&trin#(&trin#.va"ue=9(1000;used6i(e)DB 9psB4&ta#e.WI567> !04&ta#e./LAHP7$I876)* e"se #.draw&trin#(B>>> 9psB4&ta#e.WI567>!04&ta#e./LAHP7$I876)*

60

203 pub ic static void main@StringMN argsA H 20! Invaders inv J neD Invaders@AG 20# inv6game@AG 20& L 20( L
4 resu tado a:ora es:

22. /untuacin: 4 paso -ue daremos a continuacin es pr"cticamente trivia 6 Cuando matamos a un monstruo8 -ueremos -ue nuestra puntuacin aumente en - por e.emp o - 20 puntos6 4ste cambio o :aremos en e m9todo de a c ase ,onster -ue se ama cuando ocurre una co isin6 Sin embargo :a< un pe-ue5o prob ema < es -ue a puntuacin es un atributo de .ugador8 < a c ase ,onster no tiene acceso a esta variab e6 /ado -ue podemos necesitar acceder a a instancia de .ugador desde mu titud de sitios distintos8 por e.emp o para aumentar e n0mero de bombas8 para disminuir os escudos8 etc68 o -ue :aremos es a5adir un m9todo a a c ase Stage para obtener a a instancia de .ugador desde cua -uier punto de programa

+ pacFage version22G 11 import .ava6aDt6image6Image$bserverG 13 pub ic inter1ace Stage e=tends Image$bserver H 1! pub ic static 1ina int EI/>IJ&!0G 1# pub ic static 1ina int I4ICI>J!*0G 1& pub ic static 1ina int PL7RbI4ICI> J !00G 1( pub ic static 1ina int SP44/J10G 1* pub ic SpriteCac:e getSpriteCac:e@AG 1+ pub ic void add7ctor@7ctor aAG 20 pub"ic /"a'er #et/"a'er()* 21 L Por supuesto este m9todo :a< -ue imp ementar o en a c ase Invaders: Invaders6.ava

Stage6.ava

666 *1 -2 -.

pub"ic /"a'er #et/"a'er() return p"a'er*

61

-4

7:ora -ue podemos obtener una re1erencia a .ugador8 uti i%amos este m9todo para aumentar a puntuacin cada ve% -ue un monstruo es destruido:

+ pacFage version22G 10 11 pub ic c ass ,onster e=tends 7ctor H 12 protected int v=G 13 1! pub ic ,onster@Stage stageA H 1# super@stageAG 1& setSpriteBames@ neD StringMN H;bic:o06gi1;8;bic:o16gi1;LAG 1( set3rameSpeed@3#AG 1* L 20 pub ic void act@A H 21 super6act@AG 22 =VJv=G 23 i1 @= Y 0 ZZ = X Stage6EI/>IA 2! v= J -v=G 2# L 2( pub ic int getK=@A H return v=G L 2* pub ic void setK=@int iA Hv= J iG L 2+ 30 pub ic void co ision@7ctor aA H 31 i1 @a instanceo1 )u et ZZ a instanceo1 )ombA H 32 remove@AG .. sta#e.#et/"a'er().add&core(20)* 3! L 3# L 3& L
2.. Euriendo: ?n .uego en e -ue nunca podemos perder no tiene ninguna gracia8 as' -ue <a es :ora de a1rontar este do oroso momento6 4n este paso :aremos -ue cada ve% -ue un monstruo c:oca con e .ugador8 e nive de escudos disminu<a en cierta cantidad6 Si e nive ega a cero < e .ugador recibe otro go pe8 e .uego termina6 4n primer ugar imp ementaremos un indicador de ;.uego 1ina i%ado; en a c ase principa 6 Cua -uiera puede evantar ese indicador amando a m9todo game$ver@A:

,onster6.ava

666 2+ 30 31 32 33

Invaders6.ava pub ic c ass Invaders e=tends Canvas imp ements Stage8 Se<Listener H private )u11erStrateg< strateg<G private ong used>imeG

62

3! 3# 3& 3( .3+ %4 %! %% 1-! 1-% 1-+ 1-1-2 120 121 20& 20( 20* 202 210 211 212 213 21! 21# 21& 21( 21* 212 220

private SpriteCac:e spriteCac:eG private 7rra<List actorsG private P a<er p a<erG private boo"ean #a(e$nded19a"se* 666 pub"ic void #a(e=ver() #a(e$nded 1 true* , 666 pub"ic void paint8a(e=ver() 8rap<ics25 # 1 (8rap<ics25)strate#'.#et5raw8rap<ics()* #.setCo"or(Co"or.w<ite)* #.setRont(new Ront(BAria"B4Ront.3=L5420))* #.draw&trin#(B8AE$ =J$AB4&ta#e.WI567;2>!04&ta#e.7$I876;2)* strate#'.s<ow()* , 666 pub ic void game@A H used>imeJ1000G initEor d@AG w<i"e (isJisib"e() XX Y#a(e$nded) H ong start>ime J S<stem6current>ime,i is@AG updateEor d@AG c:ecFCo isions@AG paintEor d@AG used>ime J S<stem6current>ime,i is@A-start>imeG tr< H >:read6s eep@SP44/AG L catc: @Interrupted4=ception eA HL L paint8a(e=ver()* L 666

Cuando e .uego termina8 simp emente pintamos ;C7,4 $K42; sobre a panta a < nos -uedamos esperando a -ue e usuario cierre a ventana6 Por supuesto8 en un .uego m"s pro1esiona se supone -ue :ar'amos a guna otra cosa: o1rece a posibi idad de reiniciar e .uego8 vo ver a a g0n men0n inicia 8 apuntar a puntuacin conseguida8 etc666 Keamos a:ora os cambios en a c ase P a<er:

P a<er6.ava + pacFage version23G 10 11 import .ava6aDt6event6Se<4ventG 12 13 pub ic c ass P a<er e=tends 7ctor H 1! pub ic static 1ina int ,7WbSII4L/S J 200G

63

1# 1& 1( 1* 1+ 20 21 22 2! 2# 2& 2( 2* 2+ 30 31 33 3! 3# 3& 3( 3* 3+ !0 !1 !2 !3 !! !# !( !* !+ #0 #2 #3 #! ## #& #( #* #+ &1 &2 &3 &! &# && &( &* &+

pub ic static 1ina int ,7Wb)$,)S J #G protected static 1ina int PL7R42bSP44/ J !G protected int v=G protected int v<G private boo ean up8doDn8 e1t8rig:tG private int c uster)ombsG private int scoreG private int s:ie dsG pub ic P a<er@Stage stageA H super@stageAG setSpriteBames@ neD StringMN H;nave6gi1;LAG c uster)ombs J ,7Wb)$,)SG s:ie ds J ,7WbSII4L/SG score J 0G L pub ic void act@A H super6act@AG =VJv=G <VJv<G i1 @= Y 0 A = J 0G i1 @= X Stage6EI/>I - getEidt:@AA = J Stage6EI/>I - getEidt:@AG i1 @< Y 0 A < J 0G i1 @ < X Stage6PL7RbI4ICI>-getIeig:t@AA < J Stage6PL7RbI4ICI> - getIeig:t@AG L pub ic int getK=@A H return v=G L pub ic void setK=@int iA Hv= J iG L pub ic int getK<@A H return v<G L pub ic void setK<@int iA Hv< J iG L protected void updateSpeed@A H v=J0Gv<J0G i1 @doDnA v< J PL7R42bSP44/G i1 @upA v< J -PL7R42bSP44/G i1 @ e1tA v= J -PL7R42bSP44/G i1 @rig:tA v= J PL7R42bSP44/G L pub ic void Fe<2e eased@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb/$EB : doDn J 1a seGbreaFG case Se<4vent6KSb?P : up J 1a seG breaFG case Se<4vent6KSbL43> : e1t J 1a seG breaFG case Se<4vent6KSb2ICI> : rig:t J 1a seGbreaFG L updateSpeed@AG L

64

(1 (2 (3 (! (# (& (( (* (+ *0 *1 *3 *! *# *& *( ** +0 +1 +2 +3 +! +# +& +( +* ++ 100 101 102 103 10# 10& 10+ 10* 10+ 110 111 112 11. 114 11& 11( 120 121 122 12. 124 12! 12%

pub ic void Fe<Pressed@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb?P : up J trueG breaFG case Se<4vent6KSbL43> : e1t J trueG breaFG case Se<4vent6KSb2ICI> : rig:t J trueG breaFG case Se<4vent6KSb/$EB : doDn J trueGbreaFG case Se<4vent6KSbSP7C4 : 1ire@AG breaFG case Se<4vent6KSb) : 1ireC uster@AG breaFG L updateSpeed@AG L pub ic void 1ire@A H )u et b J neD )u et@stageAG b6setW@=AG b6setR@< - b6getIeig:t@AAG stage6add7ctor@bAG L pub ic void 1ireC uster@A H i1 @c uster)ombs JJ 0A returnG c uster)ombs--G stage6add7ctor@ neD )omb@stage8 )omb6?PbL43>8 =8<AAG stage6add7ctor@ neD )omb@stage8 )omb6?P8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6?Pb2ICI>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6L43>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb62ICI>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6/$EBbL43>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6/$EB8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6/$EBb2ICI>8=8<AAG

L pub ic int getScore@A H return scoreG L pub ic void setScore@int iA H score J iG L pub"ic void add&core(int i) score D1 i* ,

pub ic int getS:ie ds@A H return s:ie dsG L pub ic void setS:ie ds@int iA H s:ie ds J iG L pub"ic void add&<ie"ds(int i) s<ie"ds D1 i* i9 (s<ie"ds N EAGP&7I$L5&) s<ie"ds 1 EAGP&7I$L5&* , pub ic int getC uster)ombs@A H return c uster)ombsG L pub ic void setC uster)ombs@int iA H c uster)ombs J iG L pub"ic void co""ision(Actor a) i9 (a instanceo9 Eonster ) a.re(ove()* add&core(40)* add&<ie"ds(>40)* i9 (#et&<ie"ds() L 0) sta#e.#a(e=ver()*

65

12+ 12130 L

/ado -ue a:ora mismo os monstruos aparecen e.os de nosotros < se mueven en :ori%onta 8 a 0nica posibi idad de probar o -ue acabamos de a5adir es c:oc"ndose adrede contra os bic:os:

24. La ven#an:a de "os (onstruos: Iasta este punto nuestro .uego parec'a m"s un .uego de tiro a pato m"s -ue un Space Invaders6 4n este paso a5adiremos a posibi idad de -ue os monstruos nos paguen con a misma medicina dispar"ndonos6 /e1iniremos un nuevo actor a -ue amaremos ;Laser;8 -ue representar" as cosas -ue os bic:os nos disparar"n6 Para 9 uti i%aremos a siguiente secuencia de gr"1icos8 amados disparo06gi18 disparo16gi1 < disparo26gi1:

La c ase Laser es mu< simi ar a a c ase ,issi e6 Las 0nicas di1erencias son e :ec:o de -ue e Laser tiene varios 1otogramas @< por tanto una ve ocidad de 1otogramasA8 -ue se desp a%a :acia aba.o < -ue es m"s ento -ue e misi :

Laser6.ava + pacFage version2!G 11 12 pub ic c ass Laser e=tends 7ctor H 13 protected static 1ina int )?LL4>bSP44/J3G 1! 1# pub ic Laser@Stage stageA H 1& super@stageAG 1( setSpriteBames@ neD StringMN H;disparo06gi1;8;disparo16gi1;8;disparo26gi1;LAG 1* set3rameSpeed@10AG 1+ L 20

66

21 22 23 2! 2# 2& 2(

pub ic void act@A H super6act@AG <VJ)?LL4>bSP44/G i1 @< X Stage6PL7RbI4ICI>A remove@AG L

7:ora debemos :acer -ue os monstruos puedan disparar a eatoriamente6 /e 1orma un poco arbitraria decidimos -ue en cada turno8 un monstruo tiene una probabi idad de 1] de disparar6 Considerando -ue :a< casi un centenar de turnos por segundo8 esta probabi idad proporciona un ritmo de disparo bastante aceptab e6 /e :ec:o8 cua -uier otra 1recuencia de disparo :ace -ue nos en1rentemos a una uvia de "seres6 4 proceso de disparo es mu< simi ar a de .ugador - se crea un nuevo actor @LaserA < se co oca .usto deba.o de monstruo -ue o :a disparado:

,onster6.ava + pacFage version2!G 10 11 pub ic c ass ,onster e=tends 7ctor H 12 protected int v=G 1. protected static 9ina" doub"e RIAIC8PRA$Z@$CCH 1 0.01* 1! 1# pub ic ,onster@Stage stageA H 1& super@stageAG 1( setSpriteBames@ neD StringMN H;bic:o06gi1;8;bic:o16gi1;LAG 1* set3rameSpeed@3#AG 1+ L 20 21 pub ic void act@A H 22 super6act@AG 23 =VJv=G 2! i1 @= Y 0 ZZ = X Stage6EI/>IA 2# v= J -v=G 2% i9 (Eat<.rando(()LRIAIC8PRA$Z@$CCH) 2+ 9ire()* 2* L 2+ 30 pub ic int getK=@A H return v=G L 31 pub ic void setK=@int iA Hv= J iG L 32 33 pub ic void co ision@7ctor aA H 3! i1 @a instanceo1 )u et ZZ a instanceo1 )ombA H 3# remove@AG 3& stage6getP a<er@A6addScore@20AG 3( L 3* L 40 pub"ic void 9ire() 41 Laser ( 1 new Laser(sta#e)* 42 (.setG()D#etWidt<();2)*

67

4. 44 4! !&

(.setH(' D #et7ei#<t())* sta#e.addActor(()*

3ina mente debemos :acer -ue e .ugador reaccione a as co isiones con os disparos6 Por cada co isin8 disminuiremos e escudo en 10 unidades:

P a<er6.ava + pacFage version2!G 10 11 import .ava6aDt6event6Se<4ventG 12 13 pub ic c ass P a<er e=tends 7ctor H 1! pub ic static 1ina int ,7WbSII4L/S J 200G 1# pub ic static 1ina int ,7Wb)$,)S J #G 1& protected static 1ina int PL7R42bSP44/ J !G 1( protected int v=G 1* protected int v<G 1+ private boo ean up8doDn8 e1t8rig:tG 20 private int c uster)ombsG 21 private int scoreG 22 private int s:ie dsG 2! 2# pub ic P a<er@Stage stageA H 2& super@stageAG 2( setSpriteBames@ neD StringMN H;nave6gi1;LAG 2* c uster)ombs J ,7Wb)$,)SG 2+ s:ie ds J ,7WbSII4L/SG 30 score J 0G 31 L 33 pub ic void act@A H 3! super6act@AG 3# =VJv=G 3& <VJv<G 3( i1 @= Y 0 A 3* = J 0G 3+ i1 @= X Stage6EI/>I - getEidt:@AA !0 = J Stage6EI/>I - getEidt:@AG !1 i1 @< Y 0 A !2 < J 0G !3 i1 @ < X Stage6PL7RbI4ICI>-getIeig:t@AA !! < J Stage6PL7RbI4ICI> - getIeig:t@AG !# L !( pub ic int getK=@A H return v=G L !* pub ic void setK=@int iA Hv= J iG L !+ pub ic int getK<@A H return v<G L #0 pub ic void setK<@int iA Hv< J iG L #2 #3 protected void updateSpeed@A H

68

#! ## #& #( #* #+ &1 &2 &3 &! &# && &( &* &+ (1 (2 (3 (! (# (& (( (* (+ *0 *1 *3 *! *# *& *( ** +0 +1 +2 +! +# +& +( +* ++ 100 101 102 103 10# 10& 10( 10* 10+

L pub ic void Fe<2e eased@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb/$EB : doDn J 1a seGbreaFG case Se<4vent6KSb?P : up J 1a seG breaFG case Se<4vent6KSbL43> : e1t J 1a seG breaFG case Se<4vent6KSb2ICI> : rig:t J 1a seGbreaFG L updateSpeed@AG L pub ic void Fe<Pressed@Se<4vent eA H sDitc: @e6getSe<Code@AA H case Se<4vent6KSb?P : up J trueG breaFG case Se<4vent6KSbL43> : e1t J trueG breaFG case Se<4vent6KSb2ICI> : rig:t J trueG breaFG case Se<4vent6KSb/$EB : doDn J trueGbreaFG case Se<4vent6KSbSP7C4 : 1ire@AG breaFG case Se<4vent6KSb) : 1ireC uster@AG breaFG L updateSpeed@AG L pub ic void 1ire@A H )u et b J neD )u et@stageAG b6setW@=AG b6setR@< - b6getIeig:t@AAG stage6add7ctor@bAG L pub ic void 1ireC uster@A H i1 @c uster)ombs JJ 0A returnG c uster)ombs--G stage6add7ctor@ neD )omb@stage8 )omb6?PbL43>8 =8<AAG stage6add7ctor@ neD )omb@stage8 )omb6?P8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6?Pb2ICI>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6L43>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb62ICI>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6/$EBbL43>8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6/$EB8=8<AAG stage6add7ctor@ neD )omb@stage8 )omb6/$EBb2ICI>8=8<AAG L pub ic int getScore@A H return scoreG L pub ic void setScore@int iA H score J iG L pub ic void addScore@int iA H score VJ iG L pub ic int getS:ie ds@A H return s:ie dsG L

v=J0Gv<J0G i1 @doDnA v< J PL7R42bSP44/G i1 @upA v< J -PL7R42bSP44/G i1 @ e1tA v= J -PL7R42bSP44/G i1 @rig:tA v= J PL7R42bSP44/G

69

110 pub ic void setS:ie ds@int iA H s:ie ds J iG L 111 pub ic void addS:ie ds@int iA H 112 s:ie ds VJ iG 113 i1 @s:ie ds X ,7WbSII4L/SA s:ie ds J ,7WbSII4L/SG 11! L 11# 11& pub ic void co ision@7ctor aA H 11( i1 @a instanceo1 ,onster A H 11* a6remove@AG 11+ addScore@!0AG 120 addS:ie ds@-!0AG 121 L 122 i9 (a instanceo9 Laser ) 12. a.re(ove()* 124 add&<ie"ds(>10)* 12! , 12& i1 @getS:ie ds@A Y 0A 12( stage6game$ver@AG 12* L 130 pub ic int getC uster)ombs@A H return c uster)ombsG L 131 pub ic void setC uster)ombs@int iA H c uster)ombs J iG L 133 L

2!. Rondo con scro"": ,uc:os .uegos o1recen un aspecto visua mu< e1ectista gracias a un 1ondo con scro sobre e -ue se desarro a a accin6 4ste e1ecto es mu< 1"ci de conseguir si simp emente en ugar de borrar a panta a con un co or s ido a re enamos con una te=tura6 4 scro se consigue modi1icando e rect"ngu o -ue act0a como anc a de a te=tura6 Para entender e proceso8 imaginemos -ue tenemos a siguiente imagen -ue uti i%aremos como te=tura de 1ondo:

70

Si re enamos toda a panta a con esta te=tura uti i%ando un rect"ngu o anc a de @08 08 2#&8 2#&A8 obtenemos o siguiente:

7:ora si uti i%amos un rect"ngu o anc a de @082082#&82#&A8 es decir8 si aumentamos a coordenada `<a de rect"ngu o en 20 unidades8 obtenemos esto otro:

4 e1ecto es como si todo e decorado se :ubiese desp a%ado :acia aba.o 20 unidades6 Precisamente esta es a 1orma en -ue conseguiremos nuestro e1ecto para e 1ondo6 Por supuesto8 dado -ue -ueremos un desp a%amiento suave8 aumentaremos a coordenada en un

71

pi=e cada ve%6 >ambi9n uti i%aremos una imagen m"s apropiada para un 1ondo8 como por e.emp o a siguiente8 amada ;oceano6gi1;:

La 0nica c ase -ue cambiar" en este paso es a c ase Invaders en a -ue e1ectuamos as siguientes modi1icaciones:

1 2 12 13 1! 1# 1& 1( 11+ 20 21 22 23 2! 2# 2& 2( 2* 2+ 30 31 32 33 3! 3# 3& 3( ..2 !1 !3

pacFage version2#G

Invaders6.ava

import .ava6aDt6CanvasG import .ava6aDt6Co orG import .ava6aDt6/imensionG import .ava6aDt63ontG import .ava6aDt6Crap:ics2/G import .ava6aDt62ectang eG i(port java.awt.6e)ture/aint* import .ava6aDt6event6Se<4ventG import .ava6aDt6event6Se<ListenerG import .ava6aDt6event6EindoD7dapterG import .ava6aDt6event6EindoD4ventG import .ava6aDt6image6)u11erStrateg<G import .ava6aDt6image6)u11eredImageG import .ava6uti 67rra<ListG import .ava=6sDing6J3rameG import .ava=6sDing6JPane G pub ic c ass Invaders e=tends Canvas imp ements Stage8 Se<Listener H private )u11erStrateg< strateg<G private ong used>imeG private SpriteCac:e spriteCac:eG private 7rra<List actorsG private P a<er p a<erG private 3u99eredI(a#e ocean* private int t* private boo ean game4ndedJ1a seG pub ic Invaders@A H

72

!! !( !* !+ #0 #1 #2 #3 #! ## #& #( #* #+ &0 &1 &2 &3 &! &# &( &* &+ (1 (2 (3 (! (# (& (( (* (+ *0 *1 *2 *3 *! *# *( ** *+ +1 +2 +3 +# +& +( +* ++ 100

L pub ic void game$ver@A H game4nded J trueG L pub ic void initEor d@A H actors J neD 7rra<List@AG 1or @int i J 0G i Y 10G iVVAH ,onster m J neD ,onster@t:isAG m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG m6setR@ i[20 AG m6setK=@ @intA@,at:6random@A[20-10A AG actors6add@mAG

spriteCac:e J neD SpriteCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG addSe<Listener@t:isAG

L pub ic void add7ctor@7ctor aA H actors6add@aAG L pub ic P a<er getP a<er@A H return p a<erG L pub ic void updateEor d@A H int i J 0G D:i e @i Y actors6si%e@AA H 7ctor m J @7ctorAactors6get@iAG i1 @m6is,arFed3or2emova @AA H actors6remove@iAG

p a<er J neD P a<er@t:isAG p a<er6setW@Stage6EI/>IU2AG p a<er6setR@Stage6PL7RbI4ICI> - 2[p a<er6getIeig:t@AAG

73

101 102 103 10! 10# 10& 10( 10+ 110 111 112 113 11! 11# 11& 11( 11* 11+ 120 121 122 123 12! 12# 12& 12( 12+ 130 131 132 133 13! 13# 13& 13* 1!0 1!1 1!2 1!3 1!! 1!# 1!& 1!* 1!+ 1#0 1#1 1#2 1#3 1#!

L pub ic void c:ecFCo isions@A H 2ectang e p a<er)ounds J p a<er6get)ounds@AG 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor a1 J @7ctorAactors6get@iAG 2ectang e r1 J a16get)ounds@AG i1 @r16intersects@p a<er)oundsAA H p a<er6co ision@a1AG a16co ision@p a<erAG L 1or @int . J iV1G . Y actors6si%e@AG .VVA H 7ctor a2 J @7ctorAactors6get@.AG 2ectang e r2 J a26get)ounds@AG i1 @r16intersects@r2AA H a16co ision@a2AG a26co ision@a1AG L L L L pub ic void paintS:ie ds@Crap:ics2/ gA H g6setPaint@Co or6redAG g61i 2ect@2*08Stage6PL7RbI4ICI>8P a<er6,7WbSII4L/S830AG g6setPaint@Co or6b ueAG g61i 2ect@2*0VP a<er6,7WbSII4L/S p a<er6getS:ie ds@A8Stage6PL7RbI4ICI>8p a<er6getS:ie ds@A830AG g6set3ont@neD 3ont@;7ria ;83ont6)$L/820AAG g6setPaint@Co or6greenAG g6draDString@;S:ie ds;81(08Stage6PL7RbI4ICI>V20AG L pub ic void paintScore@Crap:ics2/ gA H g6set3ont@neD 3ont@;7ria ;83ont6)$L/820AAG g6setPaint@Co or6greenAG g6draDString@;Score:;8208Stage6PL7RbI4ICI> V 20AG g6setPaint@Co or6redAG g6draDString@p a<er6getScore@AV;;81008Stage6PL7RbI4ICI> V 20AG L pub ic void paint7mmo@Crap:ics2/ gA H int =)ase J 2*0VP a<er6,7WbSII4L/SV10G 1or @int i J 0G i Y p a<er6getC uster)ombs@AGiVVA H )u11eredImage bomb J spriteCac:e6getSprite@;bomb?L6gi1;AG g6draDImage@ bomb 8=)aseVi[bomb6getEidt:@A8Stage6PL7RbI4ICI>8t:isAG L L

L p a<er6act@AG

L e se H m6act@AG iVVG L

74

1#& 1#( 1#* 1#+ 1&0 1&1 1&2 1&3 1&& 1&( 1&* 1&+ 1(0 1(1 1(3 1(! 1+! 1+% 1++ 1(* 1(+ 1*0 1*1 1*2 1*# 1*& 1*( 1*+ 1+0 1+1 1+2 1+3 1+! 1+# 1+& 1+( 1+* 1++ 201 202 203 20# 20& 20( 20* 210 211

pub ic void paint1ps@Crap:ics2/ gA H g6set3ont@ neD 3ont@;7ria ;83ont6)$L/812AAG g6setCo or@Co or6D:iteAG i1 @used>ime X 0A g6draDString@String6va ue$1@1000Uused>imeAV; 1ps;8Stage6EI/>I#08Stage6PL7RbI4ICI>AG e se g6draDString@;--- 1ps;8Stage6EI/>I-#08Stage6PL7RbI4ICI>AG L pub ic void paintStatus@Crap:ics2/ gA H paintScore@gAG paintS:ie ds@gAG paint7mmo@gAG paint1ps@gAG L pub ic void paintEor d@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG ocean 1 spriteCac<e.#et&prite(Boceano.#i9B)* #.set/aint(new 6e)ture/aint(ocean4 new Aectan#"e(04t4ocean.#etWidt<()4ocean.#et7ei#<t())))* #.9i""Aect(0404#etWidt<()4#et7ei#<t())* 1or @int i J 0G i Y actors6si%e@AG iVVA H 7ctor m J @7ctorAactors6get@iAG m6paint@gAG L p a<er6paint@gAG paintStatus@gAG strateg<6s:oD@AG L pub ic void paintCame$ver@A H Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG g6setCo or@Co or6D:iteAG g6set3ont@neD 3ont@;7ria ;83ont6)$L/820AAG g6draDString@;C7,4 $K42;8Stage6EI/>IU2-#08Stage6I4ICI>U2AG strateg<6s:oD@AG L pub ic SpriteCac:e getSpriteCac:e@A H return spriteCac:eG L pub ic void Fe<Pressed@Se<4vent eA H p a<er6Fe<Pressed@eAG L pub ic void Fe<2e eased@Se<4vent eA H p a<er6Fe<2e eased@eAG L pub ic void Fe<><ped@Se<4vent eA HL pub ic void game@A H used>imeJ1000G

75

212 t 1 0* 213 initEor d@AG 21! D:i e @isKisib e@A cc \game4ndedA H 21! tDD* 21& ong start>ime J S<stem6current>ime,i is@AG 21( updateEor d@AG 21* c:ecFCo isions@AG 21+ paintEor d@AG 220 used>ime J S<stem6current>ime,i is@A-start>imeG 221 tr< H 222 >:read6s eep@SP44/AG 223 L catc: @Interrupted4=ception eA HL 22! L 22# paintCame$ver@AG 22& L 22* pub ic static void main@StringMN argsA H 22+ Invaders inv J neD Invaders@AG 230 inv6game@AG 231 L 232 L
2%. Aeaparicin de (onstruos: 4n nuestro .uego cuando matamos a un monstruo de momento no ocurre nada especia 8 < os monstruos son e=terminados con bastante rapide%6 Podemos a1rontar esta situacin de distintas 1ormas: Iacer aparecer nuevos monstruso cada ve% -ue un monstruo muere6 Cambiar e ;nive ; de .uego cambiando os decorados < :aciendo -ue apare%can di1erentes bic:os6 Iaciendo -ue apare%can nuevos monstruos de 1orma peridica con independencia de os -ue matamos6

Para i ustrar este proceso8 uti i%aremos e primero de os en1o-ues6 Cada ve% -ue matemos a un monstruo8 aparecer" uno nuevo6 4sto es 1"ci de conseguir a5adiendo o siguiente a nuestra c ase ,onster:

666 33 3! 3# .% 3( 3* 3+ 41 42 4. 44 4!

,onster6.ava pub ic void co ision@7ctor aA H i1 @a instanceo1 )u et ZZ a instanceo1 )ombA H remove@AG spawn()* stage6getP a<er@A6addScore@20AG L L pub"ic void spawn() Eonster ( 1 new Eonster(sta#e)* (.setG( (int)(Eat<.rando(()I&ta#e.WI567) )* (.setH( (int)(Eat<.rando(()I&ta#e./LAHP7$I876;2) )* (.setJ)( (int)(Eat<.rando(()I20>10) )*

76

4% 4+ !+

sta#e.addActor(()* , pub ic void 1ire@A H 666

2+. &onido senci""o: 75adir un sonido senci o a .uego es re ativamente 1"ci 8 sin embargo puede tener un impacto radica sobre e aspecto 1ina de .uego6 4n rea idad8 muc:os de os .uegos -ue se producen en a actua idad invierten muc:o m"s dinero en gr"1icos < sonido -ue en programacin < dise5o8 con a consecuencia de -ue a veces se obtienen .uegos con unos e=ce entes e1ectos visua es < bandas sonoras pero con escasa .ugabi idad6 ?ti i%aremos di1erentes arc:ivos 6Dav para as distintas situaciones - disparo8 impacto contra un monstruo8 etc8 - as' como un 6Dav -ue uti i%aremos como ;m0sica de ambiente;: 7rc:ivo musica6Dav p:oton6Dav e=p osion6Dav missi e6Dav ?so ,0sica ambiente 7 ien disparando 7 ien destruido Jugador disparando $rigen 2ea mente no recuerdoG descargada de a g0n sitio a-u' a-u' a-u'

Los sonidos son un recurso m"s para nuestro programa de Java8 de 1orma -ue o -ue necesitamos es una c ase -ue gestione un ;cac:9 de sonidos; de 1orma mu< simi ar a cac:9 de sprites -ue <a tenemos6 /ado -ue ambas comparten gran parte de a 1unciona idad8 podemos intentar reorgani%ar e cdigo e=tra<endo una c ase ancestro com0n8 a a -ue amaremos 2esourceCac:e6 Su cdigo ser" e siguiente:

10 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2( 2* 2+

pacFage version2(G import .ava6net6?2LG import .ava6uti 6Ias:,apG

2esourceCac:e6.ava

pub ic abstract c ass 2esourceCac:e H protected Ias:,ap resourcesG pub ic 2esourceCac:e@A H resources J neD Ias:,ap@AG L protected $b.ect oad2esource@String nameA H ?2L ur Jnu G ur J getC ass@A6getC assLoader@A6get2esource@nameAG return oad2esource@ur AG L protected $b.ect get2esource@String nameA H $b.ect res J resources6get@nameAG

77

30 31 32 33 3! 3# 3& 3( 3* 3+

i1 @res JJ nu A H res J oad2esource@;resU;VnameAG resources6put@name8resAG L return resG

protected abstract $b.ect oad2esource@?2L ur AG L

Con este ancestro8 reescribimos a c ase SpriteCac:e de a siguiente manera:

+ 10 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22

pacFage version2(G

SpriteCac:e6.ava

import .ava6aDt6image6)u11eredImageG import .ava6net6?2LG import .ava=6imageio6ImageI$G pub ic c ass SpriteCac:e e=tends 2esourceCac:eH protected $b.ect oad2esource@?2L ur A H tr< H return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen de ;Vur AG S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G L L pub ic )u11eredImage getSprite@String nameA H return @)u11eredImageAget2esource@nameAG L

23 2! 2# 2& 2* 2+ 30 31 L

R 1ina mente a5adimos una nueva c ase SoundCac:e -ue ser" a encargada de oca i%ar < cargar os arc:ivos de sonido6 Su cdigo es mu< simi ar a SpriteCac:e8 pero devue ve 7udioC ips en ugar de )u11eredImages6 >ambi9n proporciona dos m9todos adiciona es -ue son p a<Sound@A - para reproducir un sonido una 0nica ve% < oopSound@A para reproducir un sonido c'c icamente6

+ pacFage version2(G 10 11 import .ava6app et67pp etG 12 import .ava6app et67udioC ipG 13 import .ava6net6?2LG

SoundCac:e6.ava

78

1! 1# pub ic c ass SoundCac:e e=tends 2esourceCac:eH 1& protected $b.ect oad2esource@?2L ur A H 1( return 7pp et6neD7udioC ip@ur AG 1+ L 20 pub ic 7udioC ip get7udioC ip@String nameA H 21 return @7udioC ipAget2esource@nameAG 22 L 2! pub ic void p a<Sound@1ina String nameA H 2# get7udioC ip@nameA6p a<@AG 2& L 2* pub ic void oopSound@1ina String nameA H 2+ get7udioC ip@nameA6 oop@AG 30 L 32 L
Puesto -ue cua -uier c ase puede so icitar en un momento dado -ue se to-ue un sonido8 cua -uier c ase debe ser capa% de obtener una re1erencia a cac:9 de sonidos6 Como siempre8 este tipo de m9todos g oba es os a5adimos a a inter1a% Stage6

Stage6.ava + pacFage version2(G 10 11 import .ava6aDt6image6Image$bserverG 12 13 pub ic inter1ace Stage e=tends Image$bserver H 1! pub ic static 1ina int EI/>IJ&!0G 1# pub ic static 1ina int I4ICI>J!*0G 1& pub ic static 1ina int PL7RbI4ICI> J !00G 1( pub ic static 1ina int SP44/J10G 1* pub ic SpriteCac:e getSpriteCac:e@AG 12 pub"ic &oundCac<e #et&oundCac<e()* 20 pub ic void add7ctor@7ctor aAG 21 pub ic P a<er getP a<er@AG 22 pub ic void game$ver@AG 23 L
4n a c ase principa 8 debemos construir e cac:9 de sonidos8 imp ementar e m9todo getSoundCac:e@A < :acer -ue se inicie a m0sica ambiente nada m"s a comen%ar e .uego:

666 30 31 32 33 3# .% 3( 3*

Invaders6.ava pub ic c ass Invaders e=tends Canvas imp ements Stage8 Se<Listener H private )u11erStrateg< strateg<G private ong used>imeG private SpriteCac:e spriteCac:eG private &oundCac<e soundCac<e* private 7rra<List actorsG private P a<er p a<erG

79

3+ !0 !2 !3 !! !# 4% !* !+ #0 #1 #2 #3 #! ## #& #( #* #+ &0 &1 (2 (3 (! (# (& (( (* (+ *0 *1 *2 *3 *! *# *& -+ ** 204 20! 20% 20( 20*

private )u11eredImage oceanG private int tG private boo ean game4ndedJ1a seG pub ic Invaders@A H spriteCac:e J neD SpriteCac:e@AG soundCac<e 1 new &oundCac<e()* J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG 666 pub ic void initEor d@A H actors J neD 7rra<List@AG 1or @int i J 0G i Y 10G iVVAH ,onster m J neD ,onster@t:isAG m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG m6setR@ i[20 AG m6setK=@ @intA@,at:6random@A[20-10A AG actors6add@mAG

p a<er J neD P a<er@t:isAG p a<er6setW@Stage6EI/>IU2AG p a<er6setR@Stage6PL7RbI4ICI> - 2[p a<er6getIeig:t@AAG soundCac<e."oop&ound(B(usica.wavB)*

L 666 pub"ic &oundCac<e #et&oundCac<e() return soundCac<e* , pub ic void Fe<Pressed@Se<4vent eA H 666

Por 0 timo8 debemos modi1icar as c ases P a<er < ,onster de 1orma -ue en as situaciones apropiadas @disparo8 impacto8 etc6A se to-ue e sonido correspondiente6 2ea mente en esta

80

ocasin os cambios son trivia es <a -ue o 0nico -ue necesitamos es insertar una amada a m9todo p a<Sound@A con e sonido -ue necesitemos: P a<er6.ava 666 *3 pub ic void 1ire@A H *! )u et b J neD )u et@stageAG *# b6setW@=AG *& b6setR@< - b6getIeig:t@AAG *( stage6add7ctor@bAG -sta#e.#et&oundCac<e().p"a'&ound(B(issi"e.wavB)* *+ L +0 666

+ pacFage version2(G 10 11 pub ic c ass ,onster e=tends 7ctor H 12 protected int v=G 13 protected static 1ina doub e 3I2IBCb324P?4BCR J 0601G 1! 1# pub ic ,onster@Stage stageA H 1& super@stageAG 1( setSpriteBames@ neD StringMN H;bic:o06gi1;8;bic:o16gi1;LAG 1* set3rameSpeed@3#AG 1+ L 21 pub ic void act@A H 22 super6act@AG 23 =VJv=G 2! i1 @= Y 0 ZZ = X Stage6EI/>IA 2# v= J -v=G 2& i1 @,at:6random@AY3I2IBCb324P?4BCRA 2( 1ire@AG 2* L 30 pub ic int getK=@A H return v=G L 31 pub ic void setK=@int iA Hv= J iG L 32 33 pub ic void co ision@7ctor aA H 3! i1 @a instanceo1 )u et ZZ a instanceo1 )ombA H 3# remove@AG .% sta#e.#et&oundCac<e().p"a'&ound(Be)p"osion.wavB)* 3( spaDn@AG 3* stage6getP a<er@A6addScore@20AG 3+ L !0 L !2 pub ic void spaDn@A H !3 ,onster m J neD ,onster@stageAG !! m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG !# m6setR@ @intA@,at:6random@A[Stage6PL7RbI4ICI>U2A AG !& m6setK=@ @intA@,at:6random@A[20-10A AG !( stage6add7ctor@mAG

,onster6.ava

81

!* #0 #1 #2 #3 #! !! #( #*

L pub ic void 1ire@A H Laser m J neD Laser@stageAG m6setW@=VgetEidt:@AU2AG m6setR@< V getIeig:t@AAG stage6add7ctor@mAG sta#e.#et&oundCac<e().p"a'&ound(Bp<oton.wavB)* L

2-. /eOue[as opti(i:aciones: 4n nuestra 0 tima versin8 rea i%aremos a gunas pe-ue5as optimi%aciones -ue nos a<udar"n a incrementar nuestros 1otogramas por segundo8 da5adas desde -ue imp ementamos e sonido < as te=turas6 La primera optimi%acin consiste en uti i%ar im"genes en 1ormato ;compatib e;6 OPu9 signi1ica estoQ ?na imagen ;compatib e; es una imagen en memoria -ue tiene as mismas caracter'sticas @o a menos mu< simi aresA a modo de v'deo nativo -ue se est" mostrando en ese momento - en t9rminos de bits por pi=e 8 transparencia8 etc6 Las im"genes compatib es son muc:o m"s r"pidas de dibu.ar -ue cua -uier otro 1ormato6 7:ora mismo o -ue estamos :aciendo es uti i%ar e 1ormato -ue a ImageI$ e apete%ca devo vernos6 Podemos optimi%ar esto de a siguiente 1orma: 16 Leemos a imagen de disco uti i%ando ImageI$6 26 Creamos una imagen compatib e de mismo tama5o -ue a imagen e'da6 36 Pintamos a imagen reci9n cargada encima de a imagen compatib e6 /e esta 1orma obtenemos una ;versin compatib e; de una imagen situada en e disco Iaremos todo esto en a c ase SpriteCac:e8 -ue es a -ue centra i%a e acceso a as im"genes:

+ 10 11 12 13 1! 1# 1& 1( 1* 1+ 20 21 22 23 2! 2# 2& 2(

pacFage version2+G

SpriteCac:e6.ava

import .ava6aDt6Crap:icsG import .ava6aDt6Crap:icsCon1igurationG import .ava6aDt6Crap:ics4nvironmentG import .ava6aDt6ImageG import .ava6aDt6>ransparenc<G import .ava6aDt6image6)u11eredImageG import .ava6aDt6image6Image$bserverG import .ava6net6?2LG import .ava=6imageio6ImageI$G pub ic c ass SpriteCac:e e=tends 2esourceCac:e imp ements Image$bserverH protected $b.ect oad2esource@?2L ur A H tr< H return ImageI$6read@ur AG L catc: @4=ception eA H S<stem6out6print n@;Bo se pudo cargar a imagen de ;Vur AG

82

2*

2+ 30 31 L 32 L .4 pub"ic 3u99eredI(a#e createCo(patib"e(int widt<4 int <ei#<t4 int transparenc') .! 8rap<icsCon9i#uration #c 1 8rap<ics$nviron(ent.#etLoca"8rap<ics$nviron(ent().#et5e9au"t&creen5e vice().#et5e9au"tCon9i#uration()* .+ 3u99eredI(a#e co(patib"e 1 #c.createCo(patib"eI(a#e(widt<4<ei#<t4transparenc')* .return co(patib"e* .2 , 41 pub"ic 3u99eredI(a#e #et&prite(&trin# na(e) 42 3u99eredI(a#e "oaded 1 (3u99eredI(a#e)#etAesource(na(e)* 4. 3u99eredI(a#e co(patib"e 1 createCo(patib"e("oaded.#etWidt<()4"oaded.#et7ei#<t()46ransparenc'.3 I6EA&W)* 44 8rap<ics # 1 co(patib"e.#et8rap<ics()* 4! #.drawI(a#e("oaded40404t<is)* 4% return co(patib"e* 4+ , 42 pub"ic boo"ean i(a#e@pdate(I(a#e i(#4 int in9o9"a#s4int )4 int '4 int w4 int <) !0 return (in9o9"a#s X (ALL3I6&MA3=A6)) 11 0* !1 , #2 L
La segunda optimi%acin consiste en ibrarnos de dibu.o repetitivo de te=turas dentro de buc e principa 6 4n su ugar8 procederemos de a siguiente 1orma: Bada m"s a arrancar e .uego8 creamos una imagen en memoria -ue tiene a misma anc:ura -ue a panta a8 pero con una a tura igua a a de a panta a m"s e tama5o de a te=tura6 2e enamos esta imagen con e 1ondo -ue -ueremos uti i%ar6 /urante e .uego8 simp emente copiamos una sub-imagen de esta imagen en memoria a a panta a6 4 e1ecto de scro se consigue variando a coordenada R de inicio de a sub-imagen -ue pintamos6 4sto nos permite imitar e uso de >e=turePaint - -ue siempre es mu< ento- a una 0nica ve%8 < adem"s 1uera de buc e principa de .uego:

S<stem6out6print n@;4 error 1ue : ;Ve6getC ass@A6getBame@AV; ;Ve6get,essage@AAG S<stem6e=it@0AG return nu G

1 32 33 3! 3# 3& 3* 3+

pacFage version2+G

Invaders6.ava

_6 pub ic c ass Invaders e=tends Canvas imp ements Stage8 Se<Listener H private )u11erStrateg< strateg<G private ong used>imeG private SpriteCac:e spriteCac:eG private SoundCac:e soundCac:eG

83

!0 !1 42 4. !#

private 7rra<List actorsG private P a<er p a<erG private 3u99eredI(a#e bacK#round4 bacK#round6i"e* private int bacK#roundH* private boo ean game4ndedJ1a seG

*2 __ *3 pub ic void initEor d@A H *! actors J neD 7rra<List@AG *# 1or @int i J 0G i Y 10G iVVAH *& ,onster m J neD ,onster@t:isAG *( m6setW@ @intA@,at:6random@A[Stage6EI/>IA AG ** m6setR@ i[20 AG *+ m6setK=@ @intA@,at:6random@A[20-10A AG +1 actors6add@mAG +2 L +! p a<er J neD P a<er@t:isAG +# p a<er6setW@Stage6EI/>IU2AG +& p a<er6setR@Stage6PL7RbI4ICI> - 2[p a<er6getIeig:t@AAG +( +* soundCac:e6 oopSound@;musica6Dav;AG ++ 100 bacK#round6i"e 1 spriteCac<e.#et&prite(Boceano.#i9B)* 101 bacK#round 1 spriteCac<e.createCo(patib"e( 102 &ta#e.WI5674 10. &ta#e.7$I876DbacK#round6i"e.#et7ei#<t()4 104 6ransparenc'.=/AZ@$)* 10! 8rap<ics25 # 1 (8rap<ics25)bacK#round.#et8rap<ics()* 10% #.set/aint( new 6e)ture/aint( bacK#round6i"e4 10+ new Aectan#"e(0404bacK#round6i"e.#etWidt<()4bacK#round6i"e.#et7ei#<t())))* 10#.9i""Aect(0404bacK#round.#etWidt<()4bacK#round.#et7ei#<t())* 102 bacK#roundH 1 bacK#round6i"e.#et7ei#<t()* UU>ambi9n UUbacFground J neD )u11eredImage@Stage6EI/>I8 Stage6I4ICI> V UUoceano6getIeig:t@A8 UU>ransparenc<6$P7P?4AG UUCrap:ics2/ gra1ico J bacFground6createCrap:ics@AG UUgra1ico6setPaint@neD >e=turePaint@oceano8 neD 2ectang e@08 08 oceano6getEidt:@A8 UUoceano6getIeig:t@AAAAG UUgra1ico61i 2ect@08 08 bacFground6getEidt:@A8 bacFground6getIeig:t@AAG 111 L 1+* __6 1++ pub ic void paintEor d@A H 200 Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG 201 #.drawI(a#e( bacK#round4 202 04 04 &ta#e.WI5674 &ta#e.7$I87640 20. bacK#roundH4 &ta#e.WI5674 bacK#roundHD&ta#e.7$I8764 t<is)* 20! 1or @int i J 0G i Y actors6si%e@AG iVVA H 20# 7ctor m J @7ctorAactors6get@iAG

84

20& m6paint@gAG 20( L 20* p a<er6paint@gAG 211 paintStatus@gAG 212 strateg<6s:oD@AG 213 L 21# pub ic void paintCame$ver@A H 21& Crap:ics2/ g J @Crap:ics2/Astrateg<6get/raDCrap:ics@AG 21( g6setCo or@Co or6D:iteAG 21* g6set3ont@neD 3ont@;7ria ;83ont6)$L/820AAG 21+ g6draDString@;C7,4 $K42;8Stage6EI/>IU2-#08Stage6I4ICI>U2AG 220 strateg<6s:oD@AG 221 L 2!0 pub ic void game@A H 2!1 used>imeJ1000G 2!2 initEor d@AG 2!3 D:i e @isKisib e@A cc \game4ndedA H 2!! ong start>ime J S<stem6current>ime,i is@AG 24! bacK#roundH>>* 24% i9 (bacK#roundH L 0) 24+ bacK#roundH 1 bacK#round6i"e.#et7ei#<t()* 2!* updateEor d@AG 2!+ c:ecFCo isions@AG 2#0 paintEor d@AG 2#1 used>ime J S<stem6current>ime,i is@A-start>imeG 2#2 do H 2#3 >:read6<ie d@AG 2#! L D:i e @S<stem6current>ime,i is@A-start>imeY 1(AG 2## L 2#& paintCame$ver@AG 2#( L 2#+ pub ic static void main@StringMN argsA H 2&0 Invaders inv J neD Invaders@AG 2&1 inv6game@AG 2&2 L 2&3 L
La tercera optimi%acin consiste en ibrarnos de cursor de ratn:

!( !* !+ #1 #2 #3 #! ## #&

Invaders6.ava 666 pub ic Invaders@A H spriteCac:e J neD SpriteCac:e@AG soundCac:e J neD SoundCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG

85

#( #* #+ &0 &1 &2 &3 &! &# && &( &* &+ (1 +. +4 +! +% ((

pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG addSe<Listener@t:isAG setIgnore2epaint@trueAG 3u99eredI(a#e cursor 1 spriteCac<e.createCo(patib"e(1041046ransparenc'.3I6EA&W)* 6oo"Kit t 1 6oo"Kit.#et5e9au"t6oo"Kit()* Cursor c 1 t.createCusto(Cursor(cursor4new /oint(!4!)4Bnu""B)* setCursor(c)*

La siguiente optimi%acin trata con un prob ema -ue es posib e -ue nos :a<amos encontrado durante e .uego6 Si movemos a ventana a un segundo p ano < a vo vemos a poner en primer p ano8 veremos un parpadeo gris por unos instantes6 Bo es mu< prob em"tico8 pero es mu< poco pro1esiona 6 Lo -ue est" ocurriendo es -ue e 7E> est" an%ando un evento de redibu.o desde su propio :i o8 mientras nosotros estamos :aciendo otra cosa6 /ado -ue 7E> no uti i%a un dob e b01er8 por unos instantes vemos una panta a gris comp etamente borrada - a misma situacin -ue ten'amos nosotros a comen%ar6 Para evitar esto8 debemos indicar e a 7E> -ue ignore as peticiones de redibu.o -ue provengan de sistema operativo8 <a -ue nosotros mismos nos estamos :aciendo cargo de dibu.o de a panta a6 4sto se consigue amando a m9todo setIgnore2epaint6

!( !* !+ #2 #3 #! ## #& #( #* #+ &0 &1 &2 &3

666 pub ic Invaders@A H spriteCac:e J neD SpriteCac:e@AG soundCac:e J neD SoundCac:e@AG J3rame ventana J neD J3rame@;Invaders;AG JPane pane J @JPane Aventana6getContentPane@AG set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG pane 6setPre1erredSi%e@neD /imension@Stage6EI/>I8Stage6I4ICI>AAG pane 6setLa<out@nu AG pane 6add@t:isAG ventana6set)ounds@0808Stage6EI/>I8Stage6I4ICI>AG ventana6setKisib e@trueAG ventana6addEindoDListener@ neD EindoD7dapter@A H pub ic void DindoDC osing@EindoD4vent eA H S<stem6e=it@0AG L

Invaders6.ava

86

&! &# && &( &* &+ (0 +1 (2 (3 (! (# (& ((

LAG ventana6set2esi%ab e@1a seAG create)u11erStrateg<@2AG strateg< J get)u11erStrateg<@AG re-uest3ocus@AG addSe<Listener@t:isAG setI#noreAepaint(true)* )u11eredImage cursor J spriteCac:e6createCompatib e@108108>ransparenc<6)I>,7SSAG >oo Fit t J >oo Fit6get/e1au t>oo Fit@AG Cursor c J t6createCustomCursor@cursor8neD Point@#8#A8;nu ;AG setCursor@cAG __66

3ina mente8 tenemos un prob ema con e .uego < es -ue su ve ocidad var'a un poco dependiendo de a ve ocidad de ordenador6 /ado -ue a pausa -ue :acemos es siempre a misma8 si e ordenador es r"pido a actua i%acin de escenario ser" r"pida < e .uego ir" r"pido6 Sin embargo8 si e ordenador es ento8 consumir" muc:o tiempo en a actua i%acin de escenario < a0n as' estamos esperando a misma cantidad de tiempo en e buc e principa 8 con o cua e .uego va m"s ento6 Como esto no es mu< agradab e o corregiremos e=igiendo -ue cada turno dure cierta cantidad 1i.a de tiempo6 4sta cantidad depender" de n0mero de 1otogramas -ue -ueremos a can%ar6 Por e.emp o si -ueremos &0 1ts8 cada turno debe durar 1000U&0 J 1&8&& mi isegundos6 /e 1orma -ue en ugar de dormir siempre a misma cantidad de tiempo @10msA8 en cada turno ca cu aremos cu"nto :emos invertido en a actua i%acin < redibu.o de a panta a < dormiremos e tiempo -ue nos -ueda6

2!0 2!1 2!2 2!3 2!! 2!# 2!& 2!( 2!* 2!+ 2#0 2#1 2!2 2!. 2!4 2## 2#& 2#(

666 pub ic void game@A H used>imeJ1000G initEor d@AG D:i e @isKisib e@A cc \game4ndedA H ong start>ime J S<stem6current>ime,i is@AG bacFgroundR--G i1 @bacFgroundR Y 0A bacFgroundR J bacFground>i e6getIeig:t@AG updateEor d@AG c:ecFCo isions@AG paintEor d@AG used>ime J S<stem6current>ime,i is@A-start>imeG do 6<read.'ie"d()* , w<i"e (&'ste(.current6i(eEi""is()>start6i(eL 1+)* L paintCame$ver@AG L

Invaders6.ava

87

)ien8 :emos egado a 1ina de este tutoria de Java6 7:ora es tu turno para comen%ar a :acer .uegos6

88

You might also like