Gamer_Xtremo
Usuario (México)
Navenando por taringa, y la Internet en general, encontre que a los otakus les dicen depravados sociales, pervertidos, que es una enfermedad mental, etc. A lo largo de mi investigacion por el pensamiento occidental de la palabra "Otaku" y su interpretacion llegue a comentarios como estos: En el comentario que podre proximamente, lo más ridiculo es que es en un post relacionado con el tema, lo ridiculo es la cantidad de likes: Si bien la ultima parte es más que respetable, su forma de decir el significado de "Otaku esta muy mal empleada. ¿Que significa realmente esta palabra? Otaku proviene de la palabra fanatismo, es decir, ser fan de algo. Luego de leer esto, caeras en cuenta de que toda la gente del mundo es Otaku ya que es fan de algo, desde fans de los insectos hasta fans del twitter.{ La manifestacion más famos de ser "Otaku" es por el anime, cosa que ha hecho que los amantes del anime queden mal etiquetados como "Los otakus" en ves de como "Un tipo de otaku" entre todos los fantaismos del mundo. Desde fanaticos del cine de terror hasta los de comedia, desde fanaticos de música orquestal hasta pop, desde fanaticos de taringa hasta twitter, todos son Otakus por el fanatismo. ¿Por que discriminan a los Anime Otaku? Es algo que no entiendo, ¿Es muy distinto usar un traje de tu marca favorita, marca de la que seas fanatico y toda tu ropa de esa marca a usar un cosplay? ¿Es distinto desfilparrar dinero en coleccionar coches cuando solo necesitas uno a desfilparrarlo en tomos de un texto japones? ¿Es distinto pagar 10 dolares por ver una pelicula de Tarantino que pagar 10 dolares por ver la nueva pelicula de dragon ball? Todo fanatico tiende a buscar tener lo mayor posible de objetos de los cuales es fanatico, desde el autografo de su cantautor favorito hasta una camisa identica a la que uso en el concierto X. No me parece en lo absoluto justo que a alguien que use un traje, perfume y lentes Hugo Boss sea conciderado alguien con estilo, clase y nivel socioeconomico alto y que alguien que usa un cosplay de Vegeta le tachen de raro y sin vida. Varios "anti-otaku" (que ya vimos mal empleado este termino) dicen que a chuck norris se le puede conciderar un dios pero a Goku no, cuando en realidad, es lo mismo, eres fan de una figura que no existe, fans de justin bieber, fans de madona, fans de john lennon, fans de luchadores, etc. todos ellos son otaku. ¿Es respetable el cosplay? Si, totalmente, así como es respetable llevar la mascara de tu luchador favorito, así como es respetable hacerte un tatuaje de tu musico favorito, así como es respetable saberse de memoria todas las peliculas de tu director favorito, así como USAR LA CAMISA Y PINTURA FACIAL DE TU EQUIPO FAVORITO DE FOOTBALL. Así como todo eso es respetable, es respetable vestirte como tu personaje favorito de anime. Conclucion La tolerancia es lo más importante, si pides respeto, respeta, si pides amor, ama, si pides odio, odia, pero ante todo, como ser humano, ya odies, ames o respetes, tolera, por más que odies algo, toleralo, ya que todos tenemos libertad, y podemos hacer con nuestras vidas lo que queramos, mientras no afectemos libertad e integridad de los otros.

BIENBENIDOS A MI HUMILDE POST DE DROGA-ADICCIONES, O DRAGADICCION Hola compañer@s de Taringa!, hoy les dare un post de las drogas, tanto legales como ilegales. LEGALES Legales dijo: Tabaquismo Tabaquismo dijo:A aquellos que no les gusta leer les dejare unos 6 videos para que quede bien explicado, tanto para adultos como para menores y niños: Videos dijo: Esta es muy buena para niños pequeños: Deacuerdo, ahora una seleccion de imagenes: Imagenes dijo: Bueno, esa fue la seccion para lo que no les agrada leer, ahora para los que no les molesta leer: Tabaquo y Tabaquismo dijo:El tabaquismo es la adicción al tabaco provocado, principalmente, por uno de sus componentes activos, la nicotina; la acción de dicha sustancia acaba condicionando el abuso de su consumo. Según la Organización Mundial de la Salud el tabaco es la primera causa de invalidez y muerte prematura del mundo. En Europa el tabaquismo provoca cada año 1,2 millones de muertes. Está directamente relacionado con la aparición de 29 enfermedades, de las cuales 10 son diferentes tipos de cáncer, y es la principal causa del 95% de los cánceres de pulmón, del 90% de las bronquitis y de más del 50% de las enfermedades cardiovasculares. En España cada año mueren más de 50.000 personas debido al consumo de tabaco, más que por los accidentes de tráfico y el consumo de todas las drogas ilegales juntas. El tabaco tiene poder adictivo[2] debido principalmente a su componente activo, la nicotina, que actúa sobre el sistema nervioso central. El fumador sufre una dependencia física y psicológica que genera un síndrome de abstinencia, denominado tabaquismo. La nicotina genera adicción, pero tiene efectos antidepresivos y de alivio sintomático de la ansiedad. No se utiliza en farmacia, porque en la segunda mitad del siglo XX se descubrieron antidepresivos más eficaces y que no crean adicción. Tampoco se emplea para el alivio sintomático de la ansiedad, salvo en casos excepcionales, porque las benzodiacepinas, que son el tipo de tranquilizantes más utilizado, también crean dependencia, pero se consideran más eficaces y menos nocivas. Es factor de riesgo en enfermedades respiratorias, cardiovasculares, distintos tipos de cáncer, y es especialmente perjudicial durante el embarazo. Además, no sólo perjudica a los fumadores, sino también a los que respiran el mismo aire (fumadores pasivos). El tabaquismo es la principal causa de mortalidad, en la mayoría de los países desarrollados, a principios del siglo XXI, aunque hay otros estudios que indican que estas enfermedades atribuidas al tabaco son en realidad la contaminación industrial y química, los aditivos alimentarios y los pesticidas utilizados en la agricultura[cita requerida]. Además, el tabaco como tal es lo que menos se fuma, pues excepto el poco tabaco natural, todo lo que se comercializa está adulterado con sustancias químicas que le aportan dudosas o preocupantes propiedades como la de ser más adictivo o mejorar su sabor, y otras que no se saben porque también tienen fórmulas secretas.[cita requerida] Las industrias agregan aditivos que el tabaco puro jamás ha tenido, aumentando la toxicidad que de por sí ya tiene. Sin embargo es importante recalcar que el tabaco por muy puro o de "liar" como se conoce, siempre causará daño irremediablemente, por lo que la única opción que minimiza el riesgo de padecer enfermedades respiratorias a edades avanzadas es simplemente no fumar. Debido a las consecuencias, tanto a la repercusión (dependencia) física, psicológica y social que genera en los consumidores, ya desde el último Congreso de Psiquiatría que tuvo lugar en la Habana, fue considerado una enfermedad más, pues requiere tanto tratamiento medicinal como rehabilitación psicológica y re-educación social. Dichas dependencias son las más difíciles de corregir, aunque la dependencia física es la que con mayor facilidad desaparece, después de la abstinencia. Queda constituida desde entonces, como una enfermedad, que genera enfermedades y otras complicaciones. Epidemiología dijo:Según la OMS existen en el mundo más de 1.100 millones de fumadores (2002), lo que representa aproximadamente un tercio de la población mayor de 15 años. Por sexos el 47 % de los hombres y un 11 % de las mujeres en este rango de edad consumen una media de 14 cigarrillos/día, lo que supone un total de 5,827 billones de cigarrillos al año. El 74 % de todos los cigarrillos se consumen en países de bajo-medio nivel de ingresos (Banco Mundial). Tanto para hombres como para mujeres, el segmento de edad en la que fuma mayor proporción es el comprendido entre 30 y 49 años. Las mayores prevalencias mundiales se encuentran en Vietnam, Chile, parte de África y República Dominicana en hombres (73, 68 y 66 %, respectivamente), mientras que Dinamarca y Noruega la presentan en la población femenina (37 y 36 % respectivamente).[cita requerida] Por su elevado volumen poblacional, China, India y la Rusia son las que agrupan la mayor parte de fumadores del mundo. En la Unión Europea existe una reducción progresiva del consumo, se mantiene la mayor prevalencia en hombres que en mujeres, excepto en Suecia, donde el consumo es algo mayor en mujeres (22% hombres, 24% mujeres). La mayor proporción de fumadores se encuentra en los países mediterráneos. La prevalencia en España a todas las edades (2003) es del 36 % de la población. En México se estima que mueren diariamente entre 122 y 165 personas debido a haber consumido tabaco, lo que convierte a esta adicción en un grave problema de salud pública. Composición físico-química del humo del tabaco dijo: Actualmente la forma de consumo más habitual es la inhalación de los productos de combustión del tabaco. En el extremo del cigarrillo que se está quemando se alcanzan temperaturas de hasta 1.000º C. Se han reconocido cerca de 5.000 compuestos químicos en las distintas fases (gaseosa, sólida o de partículas) del humo del tabaco. Entre estos compuestos químicos se han identificado sin dudas al DDT(insecticida, propano(combustible para naves espaciales y propelente de aerosoles como en antitranspirante), benceno, butano, arsénico y, como trágica anécdota, cianuro de hidrógeno, que era nada más y nada menos que el gas utilizado por los nazis en las tristemente célebres cámaras de gas de exterminio de judíos en los campos de concentración. Se consideran ingredientes del tabaco (término aconsejado por la OMS) a todos los componentes del producto, mientras que emisiones de los productos del tabaco a lo que realmente capta el fumador siendo la principal causa de mortalidad y enfermedades atribuidas al tabaco, y exposición a la parte de emisiones que realmente absorbe el fumador. Actualmente las emisiones son el punto principal de la regulación, aunque los ingredientes permisibles también están regulados. Tabaco y salud dijo:El fumar puede ser el causante de varias enfermedades, como el cáncer de pulmón, la bronquitis y el enfisema pulmonar. El tabaquismo es reconocido desde hace varios años como un problema de salud pública, debido a que los daños a la salud asociados al consumo del tabaco causan más de medio millón de muertes en el continente americano. El fumar es la causa más frecuente de muertes que pueden evitarse. Según los últimos informes, cientos de miles de personas mueren anualmente de forma prematura debido al tabaco. Estudios recientes indican que la exposición al humo de los cigarrillos fumados por otra gente y otros productos del tabaco, producen al año la muerte de miles de personas que no fuman Pese a estas estadísticas y a numerosos avisos sobre los peligros de fumar, millones de adultos y adolescentes siguen fumando. De todos modos se están haciendo progresos: cada día son más las personas que dejan de fumar. En el año 2004, la Organización Mundial de la Salud estimaba en 4,9 millones el número de muertes anuales relacionadas con el consumo de tabaco. Pese a existir una probada relación entre tabaco y salud, esto no impide que sea uno de los productos de consumo legal que puede matar al consumidor asiduo. Fumar un sólo cigarrillo da lugar a una elevación del ritmo cardíaco, la frecuencia respiratoria y la tensión arterial. El humo produce una reacción irritante en las vías respiratorias. La producción de moco y la dificultad de eliminarlo es la causa de la tos. Debido a la inflamación continua se produce bronquitis crónica. También produce una disminución de la capacidad pulmonar, produciendo al fumador mayor cansancio y disminución de resistencia en relación a un ejercicio corporal. Alcoholismo Alcoholismo dijo:Otravez, empezando con 6 videos, muy claros, el 3ero es algo fuertesito: Videos dijo: Continuamos con imagenes: Imagenes dijo: Ahora el texto: Evidencia cientifica dijo:· La adolescencia es una etapa muy vulnerable a las adicciones, los efectos nocivos de cualquier sustancia tóxica, son más perjudiciales en un organismo que se encuentra en plena etapa de desarrollo. · Cuanto antes comienza el consumo de alcohol, más pronto aparecerán sus efectos tóxicos además de aumentar la posibilidad de dependencia y adicción. · Las últimas investigaciones señalan que el consumo de alcohol durante la adolescencia es capaz de provocar alteraciones en el crecimiento y en la maduración sexual del adolescente. · El consumo de alcohol puede producir alteraciones hepáticas, digestivas y cardiovasculares. · El consumo de bebidas alcohólicas deteriora el crecimiento cerebral del adolescente, esto está relacionado a la cantidad y frecuencia de las tomas y puede darse con cualquier bebida alcohólica(no hay ninguna “más buena que otra”). · La adolescencia es un período de crecimiento y maduración cerebral importantísima, si ocurre alguna alteración en su desarrollo, el daño provocado es irreversible. · Los efectos perjudiciales en el cerebro son independientes del tipo de bebida alcohólica que se consume. Caracteristicas dijo:Hasta el momento no existe una causa común conocida de esta adicción, aunque varios factores pueden desempeñar un papel importante en su desarrollo y las evidencias muestran que quien tiene un padre o una madre con alcoholismo tiene mayor probabilidad de adquirir esta enfermedad. Ello puede deberse, más que al entorno social, familiar o campañas publicitarias, a la presencia de ciertos genes que podrían aumentar el riesgo de alcoholismo. Algunos otros factores asociados a este padecimiento son la necesidad de aliviar la ansiedad, conflicto en relaciones interpersonales, depresión, baja autoestima, facilidad para conseguir el alcohol y aceptación social del consumo de alcohol. Tratamiento dijo:Los tratamientos contra el alcoholismo incluyen programas de desintoxicación realizados por instituciones médicas. Esto puede suponer la estancia del paciente durante un periodo indeterminado, (quizás varias semanas), bajo tutela en hospitales especializados donde puede que se utilicen determinados medicamentos para evitar el síndrome de abstinencia. Después del período de desintoxicación, puede someterse al paciente a diversos métodos de terapia de grupo o psicoterapia para tratar problemas psicológicos de fondo que hayan podido llevar al paciente a la dependencia. Se puede asimismo apoyar el programa con terapias que inciten al paciente a repugnar el alcohol mediante fármacos como el disulfiram, que provoca fuertes y repentinas resacas siempre que se consuma alcohol. La terapia nutricional es otro tratamiento. Muchos alcohólicos tienen síndrome de resistencia a la insulina, un desorden metabólico debido al cual el cuerpo no regula correctamente el azúcar causando un suministro inestable a la circulación sanguínea.[cita requerida] Aunque este desorden se puede tratar con una dieta hipoglucémica, esto puede afectar a su comportamiento y su estado anímico. Estos síntomas son efectos secundarios que se observan a menudo en alcohólicos sometidos bajo tratamiento de desintoxicación. Los aspectos metabólicos del alcoholismo a menudo se pasan por alto dando como resultado tratamientos de dudosos resultados. En los años 1990, los grupos de consultas de autoayuda fueron adquiriendo notoriedad por sus logros, como lo ha sido el movimiento de Alcohólicos Anónimos. ILEGALES Ilegales dijo:AQUI NO ENCONTRE NINGUN VIDEO RELACIONADO CON LOS DAÑOS, ASI QUE LO SIENTO PARA LOS QUE LES DA FLOJERA LEER. Son todas aquellas que no se mencionan en las legales, y solo son legales si un medico las receta: Marihuana dijo:La marihuana se consume fundamentalmente en forma de cigarrillos y su prevalencia real resulta difícil de apreciar en las encuestas de hogares. Los medios de comunicación ofrecen información contradictoria. De un lado los esfuerzos preventivos y los profesionales especializados la presentan como una droga peligrosa, causante de alteraciones en el rendimiento intelectual, la memoria y la voluntad (síndrome amotivacional), pero de otro hay una campaña millonaria a favor de su uso y no es raro ver escritos de personajes famosos que la propician, o noticias tergiversadas sobre una supuesta utilidad en medicina, confundiendo el uso de su principio activo como medicina el Ä9-Tetrahidrocannabinol, con el de fumar las hojas de cualquier procedencia ilegal. El permiso de uso como medicina controlada en Holanda ha sido presentado como que la marihuana se puede usar libremente y muchos que la probaron en alguna oportunidad ahora aparecen como usuarios. Cocaína dijo:Como droga ilegal la cocaína se consume bajo la forma de pasta básica fumada y como clorhidrato aplicado a las mucosas, pero su uso por inyección se mantiene prácticamente desconocido en nuestro medio. El ofrecimiento de PBC alcanza al 12,6% de la población, mientras con cocaína bordeó el 10% Este es realizado principalmente por un amigo o conocido. En el caso de la cocaína clorhidrato, también resultan importantes los vendedores y la pareja en el ofrecimiento. Extasis dijo:Extasis («Adam» o «XTC») es el nombre que se da a un derivado de la anfetamina, la metilenodioximetanfetamina (MDMA), droga sintética que fue introducida en medicina y luego abandonada por su elevada toxicidad, pero que ha entrado con gran fuerza en la subcultura de las drogas. Los reportes existentes en la literatura peruana acerca del consumo de esta droga muestran que este se realiza habitualmente en ambientes festivos y es frecuente el uso de varias dosis a lo largo de una noche de fiesta. Investigaciones recientes han demostrado el uso del éxtasis en el grupo de escolares de nivel secundario (Zavaleta y Castro 2006) y universitario (Zavaleta y Castro 2006). También se ha reportado periodísticamente la ocurrencia de muertes en usuarios de discotecas, por consumo de esta droga (Zavaleta y Castro 2006). En el Perú comenzó a usarse en las discotecas elegantes del sur de la capital, pero su uso se ha ampliado a todos los grupos sociales. La venta de pastillas estimulantes bajo el nombre de éxtasis hace que cualquiera pueda ser engañado y los niños pueden ser inducidos a probarlas ya que su uso no es detectado por sus padres o profesores como ocurre con el alcohol o el tabaco que dejan olor persistente que se percibe con facilidad. Así, cuando se indica que se ha consumido éxtasis, el consumo puede ser de la droga verdadera o de una falsificación, que puede ser inocua o mucho más peligrosa. Por ello en las encuestas ahora utilizamos preguntas que permitan detectar otros síntomas asociados al uso de estimulantes del grupo de las anfetaminas (taquicardia, sudoración, hipertermia, incremento de la sed, etc). Opio y derivados-heroína dijo:La adormidera está siendo cultivada en forma creciente en el Perú y ya resultan importantes los decomisos que efectúan las fuerzas policiales, indicando una producción de morfina que va en aumento y que representa un rendimiento económico bastante mayor que el de la cocaína para los campesinos y los traficantes. El alto contenido de alcaloides y la facilidad de su extracción y transformación en heroína hacen que estemos frente a un problema que va a ser muy difícil de resolver. (Zavaleta y Castro 2006). La creciente disponibilidad del opio y la heroína ha dado lugar a que se detecten casos de consumo en la encuesta y aunque los porcentajes sean marginales la llamada de atención es clara: ya hay uso de opio y heroína en proporción detectable por las encuestas de hogares. Esto sumado a la creciente disponibilidad, nos debe servir de advertencia para reforzar las acciones preventivas y de control. La presente encuesta de hogares ha detectado el uso de heroína que, como en el caso del éxtasis, no por ser en baja proporción (Prevalencia de vida de 0,46%) deja de ser alarmante frente a un ofrecimiento que llega al 1,3%. Las cifras de incidencia en relación a las variables demográficas también son demasiado bajas para tener significado estadístico. Aún cuando aquellos que informan haber utilizado heroína refieren haberlo usado principalmente en el extranjero o en el Perú y el extranjero, ya se registran casos de consumo y ofrecimiento solo en el Perú En resumen, la drogadiccion es: Gracias por su vicita a mi post, cualquier cosa, comenten.
![Crear un script para Pokémon Essentials[1]](https://storage.posteamelo.com/assets-adonis/assets/2018/06/21/16x16_10-3MJWEQU2ovT.webp)
Hola compañeros de Taringa. Hoy les vengo a enseñar como crear un script para el Pokémon Essentials de RPG Maker XP. Tomo 1: Menú táctil V2.5 Introducción Hoy veremos, como crear un menú Aquí imágenes de como quedara maso menos [Aun esta incompleto] Se llama V2.5 por el script de input, y porque lo de el menú lo he perfeccionado 2 veces, y estoy en la tercera a la mitad de desarrollo. Desarrollo Primero que nada, necesitaremos crear 1 script y editar otro: Primero crean un script llamado Input abajo de RGSS2Compatibility input dijo: # Mouse and Input #------------------------------------------------------------------------------- # Begin SDK Enabled Check #------------------------------------------------------------------------------- module Mouse #-------------------------------------------------------------------------- # * Variable Setup #-------------------------------------------------------------------------- gsm = Win32API.new('user32', 'GetSystemMetrics', 'i', 'i') [email protected]_pos = Win32API.new('user32', 'GetCursorPos', 'p', 'i') module_function #-------------------------------------------------------------------------- # * Mouse Global Position #-------------------------------------------------------------------------- def mouse_global_pos pos = [0, 0].pack('ll') [email protected]_pos.call(pos) != 0 return pos.unpack('ll') else return nil end end #-------------------------------------------------------------------------- # * Mouse Position #-------------------------------------------------------------------------- def mouse_pos(catch_anywhere = false) x, y = screen_to_client(*getMouseGlobalPos) width, height = Win32API.client_size if Input.Anykey == false if catch_anywhere or (x >= 0 and y >= 0 and x < width and y < height) return (x/$ResizeFactor).to_i, (y/$ResizeFactor).to_i else [email protected],[email protected]#nil end else return (x/$ResizeFactor).to_i, (y/$ResizeFactor).to_i end end #-------------------------------------------------------------------------- # * Delete #-------------------------------------------------------------------------- # def del [email protected]== nil # return # else [email protected](handel ,-12,[email protected]) [email protected]= nil # end # end end #-------------------------------------------------------------------------- # * Variable Setup #-------------------------------------------------------------------------- $scr2cli = Win32API.new('user32', 'ScreenToClient', %w(l p), 'i') $client_rect = Win32API.new('user32', 'GetClientRect', %w(l p), 'i') $readini = Win32API.new('kernel32', 'GetPrivateProfileStringA', %w(p p p p l p), 'l') $findwindow = Win32API.new('user32', 'FindWindowA', %w(p p), 'l') #-------------------------------------------------------------------------- # * Screen to Client #-------------------------------------------------------------------------- def screen_to_client(x, y) return nil unless x and y pos = [x, y].pack('ll') if $scr2cli.call(hwnd, pos) != 0 return pos.unpack('ll') else return nil end end #-------------------------------------------------------------------------- # * H Windowed #-------------------------------------------------------------------------- def hwnd game_name = "" * 256 $readini.call('Game','Title','',game_name,255,".Game.ini") game_name.delete!("") return $findwindow.call('RGSS Player',nil) end #-------------------------------------------------------------------------- # * Client Size #-------------------------------------------------------------------------- def client_size rect = [0, 0, 0, 0].pack('l4') $client_rect.call(hwnd, rect) right, bottom = rect.unpack('l4')[2..3] return right, bottom end #------------------------------------------------------------------------------- # Begin SDK Enabled Check #------------------------------------------------------------------------------- cursor = Win32API.new("user32", "ShowCursor", "i", "i" ) cursor.call(0) class Game_Mouse #-------------------------------------------------------------------------- # * Attributes #-------------------------------------------------------------------------- attr_accessor :icon attr_accessor :x attr_accessor :y #-------------------------------------------------------------------------- # * Starts up the class, and creates the cursor icon #-------------------------------------------------------------------------- def initialize [email protected]= 0 [email protected]= 0 [email protected]= RPG::Cache.picture("mouse") [email protected]= Sprite.new [email protected][email protected] [email protected]= 9999999 [email protected]= false [email protected]< 384 [email protected]= 255 else [email protected]= 255 end end #-------------------------------------------------------------------------- # * Reset #-------------------------------------------------------------------------- def reset [email protected]= RPG::Cache.picture("mouse") [email protected]@mouse.bitmap != nil [email protected]= Sprite.new [email protected][email protected] [email protected]= false # Updates the co-ordinates of the icon [email protected],[email protected]= Mouse.mouse_pos [email protected][email protected] [email protected][email protected] [email protected]= 9999999 [email protected]< 384 [email protected]= 255 else [email protected]= 255 end end #-------------------------------------------------------------------------- # * Update #-------------------------------------------------------------------------- def update # Updates the co-ordinates of the icon [email protected][email protected]# prevent the F2 bug [email protected][email protected]# prevent the F2 bug [email protected],[email protected]= Mouse.mouse_pos [email protected][email protected][email protected]==nil # prevent the F2 bug [email protected][email protected][email protected]==nil # Prevent the F2 Bug [email protected][email protected] [email protected][email protected] [email protected]< 384 [email protected]= 255 else [email protected]= 255 end self.reset if $scene.kind_of? Scene_Map end end #-------------------------------------------------------------------------- # * Returns the current y-coordinate of the tile the mouse is over on the map #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- # * Makes the mouse sprite disappear #-------------------------------------------------------------------------- def invisible [email protected]= 0 #Win32API.new('user32', 'ShowCursor', 'l', 'l').call(1) end #-------------------------------------------------------------------------- # * Makes the mouse sprite visible #-------------------------------------------------------------------------- def visible [email protected]= 255 #Win32API.new('user32', 'ShowCursor', 'l', 'l').call(0) end #-------------------------------------------------------------------------- # * Disposes the sprite #-------------------------------------------------------------------------- def dispose [email protected] end end #------------------------------------------------------------------------------- # End SDK Enabled Check #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # Modified by Rafael-animal #------------------------------------------------------------------------------- # Begin SDK Enabled Check #------------------------------------------------------------------------------- module Input #-------------------------------------------------------------------------- # * Variable Setup #-------------------------------------------------------------------------- [email protected]= [] [email protected]= [] Mouse_Left = 1 Mouse_Right = 2 Mouse_Middle = 4 Back= 8 Tab = 9 Enter = 13 Shift = 16 Ctrl = 17 Alt = 18 X = 0x1B LT = 0x25 UPs = 0x26 RT = 0x27 DN = 0x28 Space = 32 Numberpad = {} Numberpad[0] = 45 Numberpad[1] = 35 Numberpad[2] = 40 Numberpad[3] = 34 Numberpad[4] = 37 Numberpad[5] = 12 Numberpad[6] = 39 Numberpad[7] = 36 Numberpad[8] = 38 Numberpad[9] = 33 Equ={} # Shift Value for num US Equ[0]=')' # FR: à Equ[1]='!' # FR: & Equ[2]='@' # FR: é Equ[3]='#' # FR: " Equ[4]='$' # FR: ' Equ[5]='%' # FR: ( Equ[6]='^' # FR: - Equ[7]='&' # FR: è Equ[8]='*' # FR: _ Equ[9]='(' # FR: ç Carac = {} Carac[0] = 48 # => 0 Carac[1] = 49 # => 1 Carac[2] = 50 # => 2 Carac[3] = 51 # => 3 Carac[4] = 52 # => 4 Carac[5] = 53 # => 5 Carac[6] = 54 # => 6 Carac[7] = 55 # => 7 Carac[8] = 56 # => 8 Carac[9] = 57 # => 9 Carac["A"] = 65 Carac["B"] = 66 Carac["C"] = 67 Carac["D"] = 68 Carac["E"] = 69 Carac["F"] = 70 Carac["G"] = 71 Carac["H"] = 72 Carac["I"] = 73 Carac["J"] = 74 Carac["K"] = 75 Carac["L"] = 76 Carac["M"] = 77 Carac["N"] = 78 Carac["O"] = 79 Carac["P"] = 80 Carac["Q"] = 81 Carac["R"] = 82 Carac["S"] = 83 Carac["T"] = 84 Carac["U"] = 85 Carac["V"] = 86 Carac["W"] = 87 Carac["X"] = 88 Carac["Y"] = 89 Carac["Z"] = 90 Fkeys = {} Fkeys[1] = 112 Fkeys[2] = 113 Fkeys[3] = 114 Fkeys[4] = 115 Fkeys[5] = 116 Fkeys[6] = 117 Fkeys[7] = 118 Fkeys[8] = 119 Fkeys[9] = 120 Fkeys[10] = 121 Fkeys[11] = 122 #Fkeys[12] = 123 Collon = 186 # US: ;: Equal = 187 # US: =+ FR: =+ Comma = 188 # US: ,< FR: ,? Underscore = 189 # US: -_ Dot = 190 # US: .> FR: ;. Backslash = 191 # US: /? FR: :/ Quote = 222 # US: '" FR: ² Lb = 219 # US: [{ FR: )° Rb = 221 # US: ]} FR: ^¨ E2 = 226 # FR: <> DC = 220 # US: | FR: *µ DF = 223 # FR: !§ C0 = 192 # US: `~ FR: ù% Test = Carac.values+Numberpad.values+Fkeys.values State = Win32API.new('user32','GetKeyState',['i'],'i') Key = Win32API.new('user32','GetAsyncKeyState',['i'],'i') #------------------------------------------------------------------------------- USED_KEYS = [Mouse_Left, Mouse_Right, Mouse_Middle] #------------------------------------------------------------------------------- module_function #-------------------------------------------------------------------------- def Input.getstate(key) return true unless State.call(key).between?(0, 1) return false end #-------------------------------------------------------------------------- def Input.testkey(key) Win32API.new('user32','GetAsyncKeyState',['i'],'i').call(key) & 1==1 end #-------------------------------------------------------------------------- def Input.update [email protected]= [] [email protected]= [] for key in Test [email protected](key) if testkey(key) [email protected](key) if getstate(key) end [email protected](Back) if testkey(Back) [email protected](Tab) if testkey(Tab) [email protected](Enter) if testkey(Enter) [email protected](Shift) if testkey(Shift) [email protected](Ctrl) if testkey(Ctrl) [email protected](Alt) if testkey(Alt) [email protected](Esc) if testkey(Esc) [email protected](Collon) if testkey(Collon) [email protected](Equal) if testkey(Equal) [email protected](Comma) if testkey(Comma) [email protected](Underscore) if testkey(Underscore) [email protected](Dot) if testkey(Dot) [email protected](Backslash) if testkey(Backslash) [email protected](Lb) if testkey(Lb) [email protected](Rb) if testkey(Rb) [email protected](E2) if testkey(E2) [email protected](DF) if testkey(DF) [email protected](C0) if testkey(C0) [email protected](DC) if testkey(DC) [email protected](Quote) if testkey(Quote) [email protected](Space) if testkey(Space) [email protected](LT) if testkey(LT) [email protected](UPs) if testkey(UPs) [email protected](RT) if testkey(RT) [email protected](DN) if testkey(DN) [email protected](Space) if getstate(Space) [email protected](Back) if getstate(Back) [email protected](Tab) if getstate(Tab) [email protected](Enter) if getstate(Enter) [email protected](Shift) if getstate(Shift) [email protected](Ctrl) if getstate(Ctrl) [email protected](Alt) if getstate(Alt) [email protected](Esc) if getstate(Esc) [email protected](LT) if getstate(LT) [email protected](UPs) if getstate(UPs) [email protected](RT) if getstate(RT) [email protected](DN) if getstate(DN) @pressed.push(Collon) if getstate(Collon) @pressed.push(Equal) if getstate(Equal) @pressed.push(Comma) if getstate(Comma) @pressed.push(Underscore) if getstate(Underscore) @pressed.push(Dot) if getstate(Dot) @pressed.push(Backslash) if getstate(Backslash) @pressed.push(Lb) if getstate(Lb) @pressed.push(Rb) if getstate(Rb) @pressed.push(E2) if getstate(E2) @pressed.push(DF) if getstate(DF) @pressed.push(C0) if getstate(C0) @pressed.push(DC) if getstate(DC) @pressed.push(Quote) if getstate(Quote) end #-------------------------------------------------------------------------- def Input.triggerd?(key) return true if @keys.include?(key) return false end #-------------------------------------------------------------------------- def Input.pressed?(key) return true if @pressed.include?(key) return false end #-------------------------------------------------------------------------- # * 4 Diraction #-------------------------------------------------------------------------- def Input.dir4 return 2 if pressed?(DN) return 4 if pressed?(LT) return 6 if pressed?(RT) return 8 if pressed?(UPs) return 0 end #-------------------------------------------------------------------------- # * Trigger (key) #-------------------------------------------------------------------------- def trigger?(key) keys = [] case key when Input::DOWN keys.push(DN) when Input::UP keys.push(UPs) when Input::LEFT keys.push(LT) when Input::RIGHT keys.push(RT) when Input::C keys.push(Space, Enter) when Input::B keys.push(X, Numberpad[0]) when Input::X keys.push(Carac["A"]) when Input::L keys.push(Carac["Q"]) when Input::R keys.push(Carac["W"]) when Input::Y keys.push(Carac["R"]) when Input::F5 keys.push(Fkeys[5]) when Input::F6 keys.push(Fkeys[6]) when Input::F7 keys.push(Fkeys[7]) when Input::F8 keys.push(Fkeys[8]) when Input::F9 keys.push(Fkeys[9]) when Input::SHIFT keys.push(Shift) when Input::CTRL keys.push(Ctrl) when Input::ALT keys.push(Alt) else keys.push(key) end for k in keys if triggerd?(k) return true end end return false end #-------------------------------------------------------------------------- # * Repeat (key) #-------------------------------------------------------------------------- def repeat?(key) keys = [] case key when Input::DOWN keys.push(DN) when Input::UP keys.push(UPs) when Input::LEFT keys.push(LT) when Input::RIGHT keys.push(RT) when Input::C keys.push(Space, Enter) when Input::B keys.push(X, Numberpad[0]) when Input::X keys.push(Carac["A"]) when Input::L keys.push(Carac["Q"]) when Input::R keys.push(Carac["W"]) when Input::Y keys.push(Carac["R"]) when Input::F5 keys.push(Fkeys[5]) when Input::F6 keys.push(Fkeys[6]) when Input::F7 keys.push(Fkeys[7]) when Input::F8 keys.push(Fkeys[8]) when Input::F9 keys.push(Fkeys[9]) when Input::SHIFT keys.push(Shift) when Input::CTRL keys.push(Ctrl) when Input::ALT keys.push(Alt) else keys.push(key) end for k in keys if Input.triggerd?(k) return true end end return false end #-------------------------------------------------------------------------- # * Check (key) #-------------------------------------------------------------------------- def check(key) Win32API.new("user32","GetAsyncKeyState",['i'],'i').call(key) & 0x01 == 1 # key 0 end #-------------------------------------------------------------------------- # * Mouse Update #-------------------------------------------------------------------------- def mouse_update @used_i = [] for i in USED_KEYS x = check(i) if x == true @used_i.push(i) end end end #-------------------------------------------------------------------------- # * Mouse Triggered ? (key) #-------------------------------------------------------------------------- def trigger(key) return @used_i.include?(key) end #-------------------------------------------------------------------------- # * Mouse Pressed ? (key) #-------------------------------------------------------------------------- def pressed(key) return true unless Win32API.new("user32","GetKeyState",['i'],'i').call(key).between?(0, 1) return false end #-------------------------------------------------------------------------- # * Short Write C #-------------------------------------------------------------------------- def Input.C triggerd?(Space) or triggerd?(Enter) end #-------------------------------------------------------------------------- # * Short Write B #-------------------------------------------------------------------------- def Input.B triggerd?(X) or triggerd?(Numberpad[0]) end #-------------------------------------------------------------------------- # * Short Write A #-------------------------------------------------------------------------- def Input.A trigger?(Input::A) end #-------------------------------------------------------------------------- # * Short Write Down #-------------------------------------------------------------------------- def Input.Down triggerd?(DN) end #-------------------------------------------------------------------------- # * Short Write Up #-------------------------------------------------------------------------- def Input.Up triggerd?(UPs) end #-------------------------------------------------------------------------- # * Short Write Right #-------------------------------------------------------------------------- def Input.Right triggerd?(RT) end #-------------------------------------------------------------------------- # * Short Write Left #-------------------------------------------------------------------------- def Input.Left triggerd?(LT) end #-------------------------------------------------------------------------- # * Anykey pressed? ( A or B or C or Down or Up or Right or Left ) #-------------------------------------------------------------------------- def Input.Anykey if A or B or C or Down or Up or Right or Left return true else return false end end end #------------------------------------------------------------------------------- # End SDK Enabled Check #------------------------------------------------------------------------------- def pbMouseClickImage?(image) if $mouse.x >= image.x && $mouse.x <= (image.x + image.bitmap.width) and $mouse.y >= image.y && $mouse.y <= (image.y + image.bitmap.height) && Input.pressed(Input::Mouse_Left) return true else return false end end def pbMouseClick?(x,y,w,h) if $mouse.x >= x && $mouse.x <= (x + w) and $mouse.y >= y && $mouse.y <= (y + h) && Input.pressed(Input::Mouse_Left) return true else return false end end NOTA: Se necesita una imagen llamada Cursor.png en la carpeta pictures. Ya hecho esto, editamos el script Main, antes de $scene = pbCallTitle main dijo: $mouse = Game_Mouse.new $mouse.visible Ya que tenemos esto, eliminamos el script PokemonPauseMenu, y creamos un nuevo script con el nombre que quieran, en mi caso, este se llamara PokemonTouchMenu, y empezamos con la clase. La clase es lo que distingue el script de los demás. Pueden usar el Class que viene por defecto: class PokemonMenu_Scene Yo usare un class nuevo, le llamare Scene_Map Ahora deben agregar un codigo para que el touch no afecte el mapa, y sean solo los botones: def createSpritesets @spritesets={} for map in $MapFactory.maps @spritesets[map.map_id]=Spriteset_Map.new(map) end $MapFactory.setSceneStarted(self) updateSpritesets menu end def disposeSpritesets return if !@spritesets for i in @spritesets.keys if @spritesets @spritesets.dispose @spritesets=nil end end @spritesets.clear @spritesets={} pbDisposeSpriteHash(@sprites) end Y ahora empezamos lo bueno, el script en si. def main createSpritesets Graphics.transition loop do $mouse.visible $mouse.update Graphics.update Input.update update if $Trainer menutactil if $game_map.map_id != X Ese de arriba sirve para que no aparezca en el mapa de la intro, cambien X por el ID del mapa de introducción, en mi caso es el 51 Ahora agregaremos el código que define si tenemos la Pokedex o no, y si si la tenemos muestra los graficos: if $Trainer.pokedex if !@sprites["X"] @sprites["X"] = Sprite.new(@viewport) @sprites["X"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/Y") @sprites["X"].x=B @sprites["X"].y=A @sprites["overlay"]=BitmapSprite.new(Graphics.width, Graphics.height, @viewport) @sprites["overlay"].z = 9999 overlay= @sprites["overlay"].bitmap overlay.clear baseColor=Color.new(255, 255, 255) shadowColor=Color.new(156,156,156) pbSetSystemFont(@sprites["overlay"].bitmap) end end Cambiamos X por el nombre que queremos que tenga, en mi caso, sera menupokedex [RECUERDEN NO USAR MAYUSCULAS NI ESPACIOS], cambiamos Y por el nombre de la imagen que tendremos en la carpeta pictures, en mi caso es llamada menupokedex, y por ultimo, A y B es la ubicación de la imagen según un plano cartesiano, en mi caso, la resolución del juego es 584 de X y 700 de Y, y como uso media pantalla para touch, todos mis scripts tendrán más de 350 en y. Ahora, hacemos un proceso muy similar if $Trainer.party.length>0 if !@sprites["X"] @sprites["X"] = Sprite.new(@viewport) @sprites["X"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/Y") @sprites["X"].x=B @sprites["X"].y=A @sprites["overlay"]=BitmapSprite.new(Graphics.width, Graphics.height, @viewport) @sprites["overlay"].z = 9999 overlay= @sprites["overlay"].bitmap overlay.clear baseColor=Color.new(255, 255, 255) shadowColor=Color.new(156,156,156) pbSetSystemFont(@sprites["overlay"].bitmap) end end Solo cambio lo que va en IF, todo lo demás se maneja de forma igual. Es opcional agregar esto, solo crea textos: baseColor=Color.new(49,49,49) shadowColor=Color.new(140, 140, 140) baseColor2=Color.new(222,222,222) shadowColor2=Color.new(132,132,132) pbSetSystemFont(@sprites["overlaylol"].bitmap) textos.push([_INTL("TEXTO") Y, hayan o no agregado texto, agregan un end después de estos códigos. Agregan esto: if $scene != self break end end Graphics.freeze disposeSpritesets if $game_temp.to_title Graphics.transition Graphics.freeze end end Sirve para que se congele el juego mientras están los menús abiertos, asi si mueves las flechas, presionas la tecla para interactuar con un evento cercano, se mueve un personaje, etc, no pase ninguna acción, y no se mueva nada, ni siquiera los autotiles. Ahora agregan los gráficos de todos los menús [Cambien solo lo que esta entre comillas y los números a tu gusto]: def menu @sprites= {} if $Trainer @sprites["bg"]=Sprite.new(@viewport) @sprites["bg"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menubg") @sprites["bg"].x=0 @sprites["bg"].y=400 @sprites["menutrainer"] = Sprite.new(@viewport) @sprites["menutrainer"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menutc") @sprites["menutrainer"].x=0 @sprites["menutrainer"].y=0 @sprites["menuguardar"] = Sprite.new(@viewport) @sprites["menuguardar"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuguardar") @sprites["menuguardar"].x=0 @sprites["menuguardar"].y=400 @sprites["menuopciones"] = Sprite.new(@viewport) @sprites["menuopciones"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuopciones") @sprites["menuopciones"].x=0 @sprites["menuopciones"].y=400 @sprites["menumochila"] = Sprite.new(@viewport) @sprites["menumochila"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menumochila") @sprites["menumochila"].x=0 @sprites["menumochila"].y=400 if $Trainer.pokedex @sprites["menupokedex"] = Sprite.new(@viewport) @sprites["menupokedex"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menupokedex") @sprites["menupokedex"].x=0 @sprites["menupokedex"].y=400 end if $Trainer.party.length>0 @sprites["menuball"] = Sprite.new(@viewport) @sprites["menuball"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuball") @sprites["menuball"].x=0 @sprites["menuball"].y=400 end @sprites["overlay"]=BitmapSprite.new(Graphics.width, Graphics.height, @viewport) @sprites["overlay"].z = 9999 overlay= @sprites["overlay"].bitmap overlay.clear baseColor=Color.new(255, 255, 255) shadowColor=Color.new(156,156,156) pbSetSystemFont(@sprites["overlay"].bitmap) end end EXPLICACION: bg: es el fondo del menú, yo cree un fondo transparente de arriba, por eso es de pantalla completa, pero normalmente, si es de media pantalla, pongan el grafico en 350 menutrainer,mochila,opciones,guardar: Son simplemente los menu que hay. menupokedex y menuball: USEN EL NOMBRE QUE TIENEN EN if $Trainer.pokedex COMO X Y EN EL DE Trainer.party.length>0 COMO X Ya vamos acabando el script, solo nos falta definir las zonas táctiles: def menutactil Input.update if $Trainer Con esto le decimos al script que es con cursor, y que tiene el IF TRAINER, lo cual conecta con el IF TRAINER de los codigos anteriores: if @sprites["menuball"] if $mouse.x >= 17 && $mouse.x <= (17 + 87) and $mouse.y >= 450 && $mouse.y <= (450 + 75) @sprites["menuball"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuball-s") if Input.pressed(Input::Mouse_Left) pbPlayDecisionSE() sscene=PokemonScreen_Scene.new sscreen=PokemonScreen.new(sscene,$Trainer.party) hiddenmove=nil pbFadeOutIn(99999) { hiddenmove=sscreen.pbPokemonScreen if hiddenmove @scene.pbEndScene end } end else @sprites["menuball"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuball") end end if @sprites["menupokedex"] if $mouse.x >= 131*2 && $mouse.x <= (131*2 + 246) and $mouse.y >= (272*2 - 48*2) && $mouse.y <= ((272*2 - 48*2) + 86) @sprites["menupokedex"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menupokedex-s") if Input.pressed(Input::Mouse_Left) pbPlayDecisionSE() pbFadeOutIn(99999) { scene=PokemonPokedexScene.new screen=PokemonPokedex.new(scene) screen.pbStartScreen } end else @sprites["menupokedex"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menupokedex") end end if $mouse.x >= 3*2 && $mouse.x <= (3*2 + 246) and $mouse.y >= (320*2 - 48*2) && $mouse.y <= ((320*2 - 48*2) + 86) @sprites["menumochila"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menumochila-s") if Input.pressed(Input::Mouse_Left) pbPlayDecisionSE() item=0 scene=PokemonBag_Scene.new screen=PokemonBagScreen.new(scene,$PokemonBag) pbFadeOutIn(99999) { item=screen.pbStartScreen if item>0 break end } if item>0 Kernel.pbUseKeyItemInField(item) return end end else @sprites["menumochila"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menumochila") end if $mouse.x >= 0 && $mouse.x <= 500 and $mouse.y >= 0 && $mouse.y <= 100 @sprites["menutrainer"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menutc-s") if Input.pressed(Input::Mouse_Left) pbPlayDecisionSE() PBDebug.logonerr { scene=PokemonTrainerCardScene.new screen=PokemonTrainerCard.new(scene) pbFadeOutIn(99999) { screen.pbStartScreen @scene.pbRefresh } } end else @sprites["menutrainer"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menutc") end if $mouse.x >= (700 - 17 -87) && $mouse.x <= (700 - 17) and $mouse.y >= (450) && $mouse.y <= (450 + 75) @sprites["menuguardar"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuguardar-s") if Input.pressed(Input::Mouse_Left) pbPlayDecisionSE() scene=PokemonSaveScene.new screen=PokemonSave.new(scene) if screen.pbSaveScreen end end else @sprites["menuguardar"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuguardar") end if $mouse.x >= (700 - 55) && $mouse.x <= (700) and $mouse.y >= (784 - 40 - 100) && $mouse.y <= (784 - 40) @sprites["menuopciones"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuopciones-s") if Input.pressed(Input::Mouse_Left) pbPlayDecisionSE() pbFadeOutIn(99999){ scene=PokemonOptionScene.new screen=PokemonOption.new(scene) screen.pbStartScreen } end else @sprites["menuopciones"].bitmap=BitmapCache.load_bitmap("Graphics/Pictures/menuopciones") end end end # Menu Táctil end SOLO CAMBIEN LOS "if $mouse.x >= 17 && $mouse.x <= (17 + 87) and $mouse.y >= 450 && $mouse.y <= (450 + 75)" Y LOS "("Graphics/Pictures/menuopciones-s"PORQUE SI CAMBIAN ALGO MÁS, NO LES LLEVARA A LOS MENÚ El menú mencionado en la nota, es el que usare como ejemplo. Tiene que cambiar el numero que va después de >= 17 para decir en que punto de X empieza el gráfico, <= (17 + 87) para decir donde va a acabar el punto de X, y lo mismo con los Y, siempre empiecen por el número menor Ahora, pueden testear el juego, y verán como sus botones cambian al pasar el cursor Conclusión Gracias a esto, podremos crear menús no solo de media pantalla, si no que ahora también de pantalla completa, pero les recomiendo empezar de poco a poco, no busquen todo con su primer script Creditos Rafael-Animal de Wahack por enseñarme lo básico Taringa: Ser una gran comunidad para poder aportar Mi madre por pagar el Internet Los users que comentan por animarme a hacer otra tutorial Próximas Tutoriales Hacer Mapas al estilo BW [Cuando este post tenga 100 puntos] Crear un script de perspectiva [Cuando este y el de mapas tengan 500 puntos en total] Script de vídeos a travez de pictures al estilo la intro de BW [Cuando tenga Mil puntos en mi perfil ]
![Curso de iniciación a la programación con C# [Parte 1]](https://storage.posteamelo.com/assets-adonis/assets/2018/06/19/big2v5-aDPScosNw3r.webp)
Primero quiero aclarar que no es mio, es de una pagina que encontre buscando aprender C#, asi que den los creditos a esta pagina: http://www.elguille.info/NET/cursoCSharpErik/index.htm ______________________________________________________________________________________________________________________ Curso de iniciación a la programación con C# PRIMERA APROXIMACIÓN A C# Antes de nada, quiero que sepas que hasta ahora soy programador de Visual Basic, y la curiosidad me ha llevado a interesarme por el nuevo C#, de modo que, básicamente, me vas a acompañar durante todo mi proceso de aprendizaje. No es que vaya a escribir cosas sin estar seguro de ellas, estoy bien documentado, sino que puede que encuentres algo de código que, con el tiempo, te des cuenta de que se podía haber mejorado. Te diré que, poco a poco, C# ha ido superando con creces todas mis expectativas: es un lenguaje moderno, potente, flexible y orientado a objetos. No te puedo decir nada comparándolo con Java ni con C++, porque, básicamente, tengo muy poquita idea de cómo son estos lenguajes. No obstante, sí te puedo decir que, en una de mis muchas incursiones por la web en busca de información sobre este lenguaje encontré el siguiente párrafo: “Muchos dicen que si Java se puede considerar un C++ mejorado en cuestiones de seguridad y portabilidad, C# debe entenderse como un Java mejorado en todos los sentidos: desde la eficiencia hasta la facilidad de integración con aplicaciones tan habituales como Microsoft Office o Corel Draw.” (El rincón en español de C#, http://manowar.lsi.us.es/~csharp/) Por lo poco que yo sé sobre Java y C++, y lo que he leído en diversa documentación, creo que esta descripción se ajusta bastante a la realidad. Lo que sí te puedo asegurar con toda certeza es que C# combina la rapidez de desarrollo de Visual Basic con la enorme capacidad bruta de C++. MÉTODO A SEGUIR DURANTE TODO EL CURSO Empezaremos con una breve introducción a la programación orientada a objetos y la tecnología .NET, y posteriormente iremos ya con la programación en C# propiamente dicha. Seguramente pienses al principio que todas las excelencias que te cuento de la programación orientada a objetos vienen a ser una patraña, puesto que al final sigues teniendo que programar todo lo que el programa tiene que hacer. Sin embargo te aconsejo que tengas un poco de paciencia: cuando empecemos a desarrollar aplicaciones para Windows verás que no te engañaba, pues al desarrollar programas para Windows es cuando se ve que casi todo está hecho (las ventanas, los botones, las cajas de texto, cuadros de diálogo ...) y solamente hay que usarlo sin más. No obstante he preferido dejar el desarrollo de aplicaciones para Windows al final, puesto que de lo contrario, con tantos objetos, propiedades y eventos hubiera sido mucho más complicado hacer que comprendieras este lenguaje. Por este motivo, empezaremos desarrollando pequeños programas de consola para que puedas irte familiarizando cómodamente con la sintaxis, sin otras distracciones. PROGRAMACIÓN ORIENTADA A OBJETOS Bien, vamos allá. Si conoces bien la programación orientada a objetos, puedes pasar adelante. De lo contrario te recomiendo que hagas una lectura lenta y cuidadosa de lo que viene a continuación, pues es básico para después comprender cómo funciona el lenguaje C#. Los conceptos están ilustrados con código de C#. Si no entiendes dicho código no desesperes, ya que el objetivo de esta introducción es que comprendas dichos conceptos, y no el código. La programación orientada a objetos es algo más que “el último grito en programación”. No se trata de una moda, sino de un modo de trabajo más natural, que te permite centrarte en solucionar el problema que tienes que resolver en lugar de tener que andar pensando en cómo le digo al ordenador que haga esto o lo otro. Si alguna vez utilizaste algún lenguaje de los del “año la polca” me comprenderás enseguida. El 90% del código estaba dedicado a comunicarte con el ordenador (que si diseñar la pantalla, que si reservar memoria, que si el monitor me aguanta esta resolución...), y el otro 10% a resolver el problema. Ya no digamos si alguna vez has hecho, o intentado, algún programa para Windows usando C en bajo nivel. La programación orientada a objetos (POO en adelante) te abstrae de muchas de estas preocupaciones para que puedas dedicarte a escribir realmente el código útil, es decir, resolver el problema y ya está. Veamos un ejemplo muy claro de lo que quiero decir: Imagina hacer un programa que mantenga una base de datos de personas. Simple y llanamente. ¿Cómo era esto antes? ¡JA! ¡JAJA! Recoge los datos, abre el archivo, define la longitud del registro, define la longitud y el tipo de cada campo, pon cada campo en su sitio, guarda el registro en el lugar del archivo donde le corresponde y cierra el archivo. Después, para una búsqueda, recoge los datos a buscar, abre el archivo, busca los datos, cierra el archivo, presenta los resultados. Si además permites modificaciones, recoge los nuevos datos, vuelve a abrir el archivo, guarda los datos modificados en el registro que le corresponde, cierra el archivo... Pesado, ¿eh? Ciertamente. La mayor parte del tiempo la dedicábamos a comunicarnos con el ordenador. ¿Cómo sería esto con un lenguaje orientado a objetos, como C#? Mucho más sencillo. Tenemos un objeto Persona. Para agregar un registro, sencillamente habría que dar los valores a dicho objeto y decirle que los guarde. Ya está. Nos da igual cómo haga el objeto Persona para guardar. Veámoslo: Persona.Nombre = Pepe Persona.Apellido = Pepe (otra vez, hala) Persona.Dirección = la dirección que sea Persona.Guardar ¿Y para buscar? Pues, por ejemplo: Persona.Buscar(Manolo) Si lo encuentra, las propiedades Nombre, Apellido y Dirección ya se habrían rellenado con los datos del tal Manolo. ¿Cómo lo ha hecho el objeto Persona? ¡Qué más da! Esto es lo verdaderamente útil de la POO, ya que no tienes que preocuparte de cómo el objeto hace su trabajo. Si está bien construido y funciona no tienes que preocuparte de nada más, sino simplemente de usarlo según tus necesidades. Si lo piensas un poco, no se trata de un sistema arbitrario, o de una invención particular de algún iluminado. Pongamos por ejemplo que, en lugar de diseñar un programa, estás conduciendo un coche. ¿Qué esperas que suceda cuando pisas el acelerador? Pues esperas que el coche acelere, claro. Ahora bien, cómo haga el coche para decirle al motor que aumente de revoluciones te trae sin cuidado. En realidad, da igual que haya un mecanismo mecánico mediante un cable, o un mecanismo electrónico, o si debajo del capó hay un burro y al pisar el acelerador se introduce una guindilla por el sito que más le pueda escocer al desdichado animal. Además, esto nos lleva a otra gran ventaja: Por mucho que avance la tecnología, el modo de conducir un coche siempre es el mismo, ya que lo único que cambia es el mecanismo interno, no la interfaz que te ofrece. Esto mismo es aplicable a los objetos en programación: por mucho que cambien las versiones de los objetos para hacerlos más eficientes, estos siempre ofrecerán la misma interfaz, de modo que podrás seguir utilizándolos sin necesidad de hacer modificación alguna cuando aparezca una nueva versión del objeto. Clases y objetos Ya hemos visto algunas de las principales ventajas de la POO. Vamos a entrar ahora en más detalles: qué son las clases, qué son los objetos y en qué se diferencian. A menudo es fácil confundir ambos términos. ¿Ambas cosas son iguales? No, ni mucho menos, aunque están íntimamente relacionados. Para que pueda haber un objeto debe existir previamente una clase, pero no al revés. Me explico: la clase es la "plantilla" en la que nos basamos para crear el objeto. Volvamos al ejemplo del coche: todos ellos tienen una serie de características comunes: todos tienen un motor, ruedas, un volante, pedales, chasis, carrocería...; todos funcionan de un modo parecido para acelerar, frenar, meter las marchas, dar las luces...; sin embargo, cada uno de ellos es diferente de los demás, puesto que cada uno es de su marca, modelo, color, número de bastidor..., propiedades que lo diferencian de los demás, aunque una o varias de ellas puedan coincidir en varios coches. Diríamos entonces que todos los coches están basados en una plantilla, o un tipo de objeto, es decir, pertenecen todos a la misma clase: la clase coche. Sin embargo, cada uno de los coches es un objeto de esa clase: todos comparten la "interfaz", pero no tienen por qué compartir los datos (marca, modelo, color, etc). Se dice entonces que cada uno de los objetos es una instancia de la clase a la que pertenece, es decir, un objeto. En resumen, la clase es algo genérico (la idea que todos tenemos sobre lo que es un coche) y el objeto es algo mucho más concreto (el coche del vecino, el nuestro, el papamóvil...). Veamos cómo sería esto en C#. El diseño de la clase Coche sería algo parecido a esto (aunque más ampliado): class Coche { public Coche(string marca, string modelo, string color, string numbastidor) { this.Marca=marca; this.Modelo=modelo; this.Color=color; this.NumBastidor=numbastidor; } public double Velocidad { get { return this.velocidad; } } protected double velocidad=0; public string Marca; public string Modelo; public string Color; public string NumBastidor; public void Acelerar(double cantidad) { // Aquí se le dice al motor que aumente las revoluciones pertinentes, y... Console.WriteLine("Incrementando la velocidad en {0} km/h", cantidad); this.velocidad += cantidad; } public void Girar(double cantidad) { // Aquí iría el código para girar Console.WriteLine("Girando el coche {0} grados", cantidad); } public void Frenar(double cantidad) { // Aquí se le dice a los frenos que actúen, y... Console.WriteLine("Reduciendo la velocidad en {0} km/h", cantidad); this.velocidad -= cantidad; } } Veamos una clase con un método Main para ver cómo se comportaría esta clase: class EjemploCocheApp { static void Main() { Coche MiCoche=new Coche("Peugeot", "306", "Azul","1546876"; Console.WriteLine("Los datos de mi coche son:"; Console.WriteLine("Marca: {0}", MiCoche.Marca); Console.WriteLine("Modelo: {0}", MiCoche.Modelo); Console.WriteLine("Color: {0}", MiCoche.Color); Console.WriteLine("Número de bastidor: {0}", MiCoche.NumBastidor); MiCoche.Acelerar(100); Console.WriteLine("La velocidad actual es de {0} km/h",MiCoche.Velocidad); MiCoche.Frenar(75); Console.WriteLine("La velocidad actual es de {0} km/h",MiCoche.Velocidad); MiCoche.Girar(45); } } El resultado que aparecería en la consola al ejecutar este programa sería este: Los datos de mi coche son los siguientes: Marca: Peugeot Modelo: 306 Color: Azul Número de bastidor: 1546876 Incrementando la velocidad en 100 km/h La velocidad actual es de 100 km/h Reduciendo la velocidad en 75 km/h La velocidad actual es de 25 km/h Girando el coche 45 grados No te preocupes por no entender todo el código todavía, pues ya hablaremos largo y tendido de la sintaxis. Sólo quiero que te fijes en que en la clase es donde se definen todos los datos y se programan todas las acciones que han de manejar los objetos de esta clase. Los datos son Velocidad, Marca, Modelo, Color y NumBastidor, y los métodos son Acelerar, Girar y Frenar. Sin embargo, el objeto, MiCoche (creado en la primera línea del método Main) no define absolutamente nada. Simplemente usa la interfaz diseñada en la clase (la interfaz de una clase es el conjunto de métodos y propiedades que esta ofrece para su manejo). Por lo tanto, Coche es la clase y MiCoche un objeto de esta clase. LOS PILARES DE LA POO: ENCAPSULAMIENTO, HERENCIA Y POLIMORFISMO A partir de aquí leerás constantes referencias al “cliente”. Si no sabes qué es yo te lo aclaro: no, no es todo aquel que va comprar algo. ¡Céntrate, hombre, que estamos en programación! Cuando hable del cliente de una clase me estoy refiriendo al código que está usando esa clase, es decir, instanciándola o invocando métodos de la misma, independientemente de si este código forma parte del mismo programa o de otro distinto, aun escrito en otro lenguaje. Quédate con esto porque te vas a hartar de verlo. ¿Qué es eso del encapsulamiento? Podríamos definirlo como la capacidad que tienen los objetos de ocultar su código al cliente y proteger sus datos, ofreciendo única y exclusivamente una interfaz que garantiza que el uso del objeto es el adecuado. La ocultación del código es algo evidente: cuando se invoca el método Acelerar del objeto MiCoche, lo único que sabemos es que el coche acelerará, pero el cómo lo haga es algo que no podremos ver desde el cliente. En cuanto a la protección de datos, fíjate también en un detalle del ejemplo: no podríamos modificar directamente el valor de la propiedad Velocidad, dado que está definida como propiedad de sólo lectura. La única forma de modificar su valor sería invocar los métodos Acelerar y/o Frenar. Esta importante característica asegura que los datos de los objetos pertenecientes a esta clase se van a manejar del modo adecuado. MiCoche.Velocidad=100; // Esto provocaría un error. Velocidad es de sólo lectura ----------------- MiCoche.Acelerar(100); Console.WriteLine(MiCoche.Velocidad); Si el coche estaba parado antes de invocar el método Acelerar, el programa escribiría 100 en la consola. Además de la gran ventaja de la protección de datos nos encontramos con otra no menos estimable: la portabilidad del código. Una vez diseñada la clase podremos usarla en tantos programas como la necesitemos, sin necesidad de volver a escribirla. Puede que alguno me diga: "bueno, yo ya podía usar procedimientos escritos anteriormente en mis programas hechos en el lenguaje X" (donde pone X póngase C, Pascal, Basic o NISU). Claro que sí, esto podía hacerse ya con la programación procedimiental. No obstante, este modo de programar conlleva una serie de deficiencias intrínsecas: cada función está completamente aislada de los datos que vamos a usar con ella, de modo que, por ejemplo, para acelerar habría que pasarle no sólo cuánto queremos acelerar, sino también la velocidad actual, y dicha función tendría que devolvernos como resultado la nueva velocidad alcanzada. Dicho resultado tendríamos que almacenarlo en una variable que, por decirlo de algún modo, está también completamente aislada y, además, desprotegida, pudiendo esta ser modificada sin intención en otra línea del programa (usando por error el operador de asignación = en lugar del de comparación ==, por ejemplo), generando así errores difíciles de rastrear (puesto que la variable no contiene el valor adecuado), ya que el compilador lo permite y no arroja ningún mensaje de error. Esto sería imposible con la propiedad Velocidad del objeto coche, pues si se intentara modificar directamente en alguna parte el código, el compilador arrojaría un mensaje de error, avisando de que la propiedad no se puede modificar pues es de sólo lectura, error que por otro lado es muy fácil de localizar (de hecho te lo localiza el compilador). Como ves, la POO solventa todas estas deficiencias gracias al encapsulamiento, proporcionándote así un modo natural, seguro y sencillo de trabajar. Otro de los pilares básicos de la POO es la herencia. Gracias a ella podemos definir clases nuevas basadas en clases antiguas, añadiéndoles más datos o más funcionalidad. Para ver esto más claro sigamos con el ejemplo del coche. Imaginemos que la clase Coche ofrece una interfaz básica para cualquier tipo de coche. Sin embargo queremos un coche que, además de todo lo que tienen los demás coches, es capaz de aparcar él solito, sin necesidad de que nosotros andemos haciendo maniobras. ¿Tendríamos que definir otra clase para incorporar esta nueva capacidad? Pues no. Podemos heredar todos los miembros de la clase Coche y después agregarle lo que deseemos en la nueva clase: class CocheAparcador:Coche { public CocheAparcador(string marca, string modelo, string color, string numbastidor): base(marca, modelo, color, numbastidor) {} public void Aparcar() { // Aquí se escribe el código para que el coche aparque solo Console.WriteLine("Aparcando el coche de modo automático"; this.velocidad = 0; } } ¿Qué ha pasado? ¿Dónde están todos los demás miembros de la clase? Aunque parezca mentira, están. La clase CocheAparcador ha heredado todos los miembros de su clase base (Coche). Lo único que ha añadido ha sido el método Aparcar, de modo que cualquier objeto de la clase CocheAparcador (ojo, no de la clase Coche) tendrá todos los miembros de la clase Coche más el método Aparcar incorporado en la clase derivada CocheAparcador. ¿Y cómo se instancian objetos de una clase derivada? Pues exactamente igual que si se instanciara de cualquier otra clase. Veámoslo con el ejemplo anterior, modificando ligeramente el método Main: class EjemploCocheApp { static void Main() { CocheAparcador MiCoche=new CocheAparcador("Peugeot", "306", "Azul","1546876"; Console.WriteLine("Los datos de mi coche son:"; Console.WriteLine("Marca: {0}", MiCoche.Marca); Console.WriteLine("Modelo: {0}", MiCoche.Modelo); Console.WriteLine("Color: {0}", MiCoche.Color); Console.WriteLine("Número de bastidor: {0}", MiCoche.NumBastidor); MiCoche.Acelerar(100); Console.WriteLine("La velocidad actual es de {0} km/h",MiCoche.Velocidad); MiCoche.Frenar(75); Console.WriteLine("La velocidad actual es de {0} km/h",MiCoche.Velocidad); MiCoche.Girar(45); MiCoche.Aparcar(); string a=Console.ReadLine(); } } Las modificaciones sobre el anterior están en negrilla. Ahora, el resultado en la consola sería este: Los datos de mi coche son los siguientes: Marca: Peugeot Modelo: 306 Color: Azul Número de bastidor: 1546876 Incrementando la velocidad en 100 km/h La velocidad actual es de 100 km/h Reduciendo la velocidad en 75 km/h La velocidad actual es de 25 km/h Girando el coche 45 grados Aparcando el coche de modo automático Ahora, el objeto MiCoche tiene los mismos miembros que tenía cuando era de la clase Coche más el método Aparcar implementado por la clase derivada CocheAparcador. Y entonces, ¿podría construir clases más complejas a partir de otras clases más sencillas? Hombre, este es el objetivo principal de la herencia. No obstante, C# soporta la herencia simple, pero no la herencia múltiple. Por lo tanto, en C# podemos construir una clase derivada a partir de otra clase, pero no de varias clases. Sobre este aspecto, lo ideal para construir una clase coche hubiera sido construir clases más sencillas (ruedas, motor, chasis, carrocería, volante, ...), y después construir la clase coche derivándola de todas ellas: class Coche:Ruedas, Motor, Chasis, Carrocería, Volante //Error. C# no soporta herencia múltiple Sin embargo ya digo que esto no es posible en C#. Una clase puede derivarse de otra, pero no de varias. Sí se puede derivar una clase de otra clase y varias interfaces, pero de esto hablaremos más adelante, cuando tratemos las interfaces. El polimorfismo es otra de las maravillas que incorpora la POO. ¿Qué ocurre si, siguiendo con el manido ejemplo de los coches, cada coche ha de comportarse de un modo diferente dependiendo de su marca, esto es, si es un Peugeot, por ejemplo, el acelerador acciona un cable, pero si es un Volkswagen, el acelerador acciona un mecanismo electrónico?. Bien, alguien acostumbrado a la programación procedimental dirá: "Eso está chupao. Basta con un Switch". Bien, veámoslo: class Coche { public Coche(string marca, string modelo, string color, string numbastidor) { this.Marca=marca; this.Modelo=modelo; this.Color=color; this.NumBastidor=numbastidor; } public double Velocidad { get { return this.velocidad; } } protected double velocidad=0; public string Marca; public string Modelo; public string Color; public string NumBastidor; public void Acelerar(double cantidad) { switch this.Marca { case "Peugeot": // Aquí acciona el mecanismo de aceleración de los Peugeot... Console.WriteLine("Accionando el mecanismo de aceleración del Peugeot"; break; case "Volkswagen": // Aquí acciona el mecanismo de aceleración de los Volkswagen... Console.WriteLine("Accionando el mecanismo de aceleración del Volkswagen"; break; case "Seat": // Aquí acciona el mecanismo de aceleración de los Seat... Console.WriteLine("Accionando el mecanismo de aceleración del Seat"; break; default: // Aquí acciona el mecanismo de aceleración por defecto... Console.WriteLine("Accionando el mecanismo de aceleración por defecto"; break; } Console.WriteLine("Incrementando la velocidad en {0} km/h"; this.velocidad += cantidad; } public void Acelerar(double cantidad) { // Aquí se le dice al motor que aumente las revoluciones pertinentes, y... Console.WriteLine("Incrementando la velocidad en {0} km/h", cantidad); this.velocidad += cantidad; } public void Girar(double cantidad) { // Aquí iría el código para girar Console.WriteLine("Girando el coche {0} grados", cantidad); } public void Frenar(double cantidad) { // Aquí se le dice a los frenos que actúen, y... Console.WriteLine("Reduciendo la velocidad en {0} km/h", cantidad); this.velocidad -= cantidad; } } ¡Muy bien! ¿Y si aparece una marca nueva con un mecanismo diferente, machote? -Estoooo, bueno... pueees... se añade al switch y ya está.- ¡Buena respuesta! Entonces, habría que buscar el código fuente de la clase Coche, y hacer las modificaciones oportunas, ¿no? -Pues sí, claro- Bien. Imagínate ahora que la clase Coche no es una clase en programación, sino una clase de verdad, o sea, coches de verdad. Si se crea un nuevo sistema de aceleración, ¿tienen que buscar el manual de reparación del coche, modificarlo para contemplar el nuevo sistema y después redistribuirlo otra vez todo entero a todo el mundo? Claro que no. Lo que se hace es, simplemente, escribir un nuevo manual únicamente con las innovaciones y distribuir esta parte a aquellos que lo vayan a necesitar para que se añada a lo que ya existe, ni más ni menos. Pues esto es, más o menos, lo que proporciona el polimorfismo en la POO. No es necesario modificar el código de la clase original. Si esta está bien diseñada, basta con derivar otra clase de la original y modificar el comportamiento de los métodos necesarios. Claro, para esto la clase Coche debería estar bien construida. Algo como esto: class Coche { public Coche(string marca, string modelo, string color, string numbastidor) { this.Marca=marca; this.Modelo=modelo; this.Color=color; this.NumBastidor=numbastidor; } public double Velocidad { get { return this.velocidad; } } protected double velocidad=0; public string Marca; public string Modelo; public string Color; public string NumBastidor; public virtual void Acelerar(double cantidad) { // Aquí se le dice al motor que aumente las revoluciones pertinentes, y... Console.WriteLine("Accionando el mecanismo de aceleración por defecto"; Console.WriteLine("Incrementando la velocidad en {0} km/h", cantidad); this.velocidad += cantidad; } public virtual void Girar(double cantidad) { // Aquí iría el código para girar Console.WriteLine("Girando el coche {0} grados", cantidad); } public virtual void Frenar(double cantidad) { // Aquí se le dice a los frenos que actúen, y... Console.WriteLine("Reduciendo la velocidad en {0} km/h", cantidad); this.velocidad -= cantidad; } } Fíjate un poquito en los cambios con respecto a la que habíamos escrito en primer lugar: se ha añadido la palabra virtual en las declaraciones de los tres métodos. ¿Para qué? Para que las clases derivadas puedan sobrescribir el código de dichos métodos en caso de que alguna de ellas lo necesite porque haya cambiado el mecanismo. Fíjate bien en cómo lo haría una clase que sobrescribe el método Acelerar porque utiliza un sistema distinto al de la clase Coche: class CocheAceleradorAvanzado:Coche { public CocheAceleradorAvanzado(string marca, string modelo, string color, string numbastidor): base(marca, modelo, color, numbastidor) {} public override void Acelerar(double cantidad) { // Aquí se escribe el nuevo mecanismo de aceleración Console.WriteLine("Accionando el mecanismo avanzado de aceleración"; Console.WriteLine("Incrementando la velocidad en {0} km/h", cantidad); this.velocidad += cantidad; } } Ya está. La clase base queda intacta, es decir, no hay que modificar absolutamente nada. La clase derivada únicamente sobrescribe aquello que no le sirve de la clase base, que es en este caso el método acelerar. Fíjate que para poder hacerlo hemos puesto la palabra override en la declaración del método. Pero puede que alguno piense: "Vamos a ver si yo me aclaro. En ese caso, en la clase derivada habría dos métodos Acelerar: uno el derivado y otro el sobrescrito que, además, tienen los mismos argumentos. ¿Cómo sabrá el compilador cuál de ellos ha de ejecutar?" El compilador siempre ejecuta el método sobrescrito si el objeto pertenece a la clase derivada que lo sobrescribe. Es como si eliminara completamente el método virtual de la clase derivada, sustituyéndolo por el nuevo. Veamos un ejemplo: CocheAceleradorAvanzado MiCoche; ... MiCoche = new CocheAceleradorAvanzado("Peugeot", "306", "Azul", "54668742635"; MiCoche.Acelerar(100); En este caso, está muy claro. El objeto MiCoche está declarado como un objeto de la clase CocheAceleradorAvanzado, de modo que al ejecutar el método acelerar se ejecutará sin problemas el método de la clase derivada. Por lo tanto, la salida por pantalla de este fragmento sería: Accionando el mecanismo avanzado de aceleración Incrementando la velocidad en 100 km/h Sin embargo, este otro ejemplo puede ser más confuso: Coche MiCoche; ... MiCoche = new CocheAceleradorAvanzado("Peugeot", "306", "Azul", "54668742635"; MiCoche.Acelerar(100); Un momento, un momento. Aquí el objeto MiCoche está declarado como un objeto de la clase Coche y, sin embargo, se instancia como objeto de la clase CocheAceleradorAvanzado. ¿Cuál de los dos métodos ejecutará ahora? De nuevo ejecutará el método de la clase derivada, como en el caso anterior. ¿Entonces, para qué diantres has declarado el objeto MiCoche como un objeto de la clase Coche? Sencillo: pudiera ser que yo sepa que voy a necesitar un objeto que será un coche, pero en el momento de declararlo no sé si será un coche normal o uno de acelerador avanzado. Por este motivo, tengo que declararlo como objeto de la clase Coche. Sin embargo, más adelante sabré qué tipo de coche tengo que crear, por lo que instanciaré el que necesite. Gracias al polimorfismo no tendré que preocuparme de decirle que ejecute un método u otro, ya que el compilador ejecutará siempre el que le corresponda según la clase a la que pertenezca. La salida por pantalla en este caso sería, por lo tanto, exactamente la misma que en el caso anterior. El polimorfismo, en resumen, ofrece la posibilidad de que varios objetos que comparten la misma interfaz, es decir, que están formados por los mismos miembros, se comporten de un modo distinto unos de otros. Bueno, creo que ya está bien de conceptos. Aunque parezca mentira, hoy has dado un paso crucial para entender y aprender a utilizar este nuevo lenguaje, dado que en C# todo, hasta los tipos de datos de toda la vida, son objetos (bueno, todo, lo que se dice todo, no: los punteros no son objetos, pero hablaremos de ellos cuando lleguemos al código inseguro... todo se andará). Sigue conmigo. ______________________________________________ Yo he leido hasta aqui, conforme lea, ire posteando, dejen puntos si les sirvio, no tomen en cuenta los emoticon