CientoSeis

Comunidad CientoSeis => Tecnología => Mensaje iniciado por: Bill en 13 de Mayo de 2009, 15:08

Título: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 13 de Mayo de 2009, 15:08
Índice

Introducción (http://www.cientoseis.es/index.php?topic=14400.msg217026#msg217026)

Libro I: Aprendiendo a pensar

1. Los problemas decrecen. División en subproblemas y algoritmos. (http://www.cientoseis.es/index.php?topic=14400.msg217936#msg217936)
2. Los robots son un invento satánico. Formalizar el lenguaje. Bucles. (http://www.cientoseis.es/index.php?topic=14400.msg218971#msg218971)
3. La verdad, la mentira, el yogur griego y YoYo jugando a la xbox. Condicionales y más bucles. Lógica proposicional. (http://www.cientoseis.es/index.php?topic=14400.msg219895#msg219895)
4. Dibujando lo que pensamos. Diagramas de Flujo I: lo básico. (http://www.cientoseis.es/index.php?topic=14400.msg225454#msg225454)
5. Las funciones son tus amigas. Diagramas de Flujo II: funciones. (http://www.cientoseis.es/index.php?topic=14400.msg230243#msg230243)
6. De vectores, matrices y otros monstruos multidimensionales. Diagramas de Flujo III: arrays. (http://www.cientoseis.es/index.php?topic=14400.msg231303#msg231303)
7. La vaquita hace "muuuuu", el patito hace "cua cua". TDA y Orientación a Objetos. Abstracción, Encapsulación, Herencia, Poliformismo. (http://www.cientoseis.es/index.php?topic=14400.msg236625#msg236625)

Libro II: Aprendiendo C#

0. Introducción a la plataforma .NET¿Qué es? Definición de: CLS, MSIL, CLI, CLR, CTS, BCL (http://www.cientoseis.es/index.php?topic=14400.msg306582#msg306582)
1. Hola Mundo Introducción al entorno; creando soluciones y proyectos; hola mundo en consola, windows forms, wpf, asp y compact (http://www.cientoseis.es/index.php?topic=14400.msg308686#msg308686)
2. Sistema de tipos (Parte I : Definición y Clasificación) Tipos de datos y su clasificación (http://www.cientoseis.es/index.php?topic=14400.msg314939#msg314939)
3. Scroll horizontal 2D multicapa Como crear un scroll 2D horizontal multicapa con sensación de profundidad en el movimiento (http://www.cientoseis.es/index.php?topic=14400.msg372363#msg372363)
4. Añadiendo un personaje a la escena Cómo añadir un personaje a nuestra escena con scroll y animar su movimiento a izquierda y derecha (http://www.cientoseis.es/index.php?topic=14400.msg372418#msg372418)
5. Dando más vida al personaje (I). Como hacer un personaje con más vida, separación y ordenación en clases, clase de input y de personaje, concepto de Timer. (http://www.cientoseis.es/index.php?topic=14400.msg372608#msg372608)
6. Dando más vida al personaje (II). Corriendo, saltando, vector velocidad, flip horizontal de bitmaps. (http://www.cientoseis.es/index.php?topic=14400.msg372652#msg372652)
7. Creando un tetris: Análisis La importancia de un análisis correcto antes de comenzar a programar. (http://www.cientoseis.es/index.php?topic=14400.msg374809#msg374809)
8. Creando un tetris: TetrisSprite Más análisis, conceptos de todo un poco, dibujado. (http://www.cientoseis.es/index.php?topic=14400.msg375183#msg375183)
9. Creando un tetris: TetrisPiece Reanálisis, azar, operador ? y mostrando las piezas. (http://www.cientoseis.es/index.php?topic=14400.msg375740#msg375740)
10. Creando un tetris: Espacio de juego Montando el espacio de juego con la pieza, posibilidad de movimiento, acciones e input. (http://www.cientoseis.es/index.php?topic=14400.msg376328#msg376328)
11. Creando un tetris: Motor de juego Montando todo junto y haciendo que funcione (http://www.cientoseis.es/index.php?topic=14400.msg376344#msg376344)
12. Creando un tetris: Música y sonidos (http://www.cientoseis.es/index.php?topic=14400.msg765870#msg765870)
13. Creando un Tetris: Mostrar la siguiente pieza (http://www.cientoseis.es/index.php?topic=14400.msg766121#msg766121)

14. Creando un Tetris: Marcador de puntos y toques finales
(http://www.cientoseis.es/index.php?topic=14400.msg766259#msg766259)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 13 de Mayo de 2009, 15:09
Me parece una idea cojonuda y desde luego, si se hace, me apunto de cabeza aunque las fechas son un poco malas para empezar con esto no?

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 13 de Mayo de 2009, 15:13
Introducción

El curso será largo, sí, pero lo que se pretende es que cualquiera que se apunte, incluso con ningún conocimiento de programación, pueda aprender desde cero a programar (independientemente del lenguaje de programación), emplee sus conocimientos para aprender un lenguaje (en este caso C#) y que una vez tenga fluidez con el lenguaje pueda utilizarlo para programar juegos para Windows y Xbox 360, y no me estoy refiriendo a mariconadas de juegos (que se apenderán también claro) sino a avanzar hasta realizar juegos como los del mercado, incluyendo 3D.

La estructura será en tres bloques:

- Metodología: La metodología de programación consiste en entender cómo funciona un ordenador, qué es un lenguaje de programación, qué herramientas existen, qué formas de trabajar hay, y cómo comenzar a abordar un problema. En la metodología NO se toca un pc, se hace con lápiz y papel, y básicamente es aprender a pensar de manera ordenada y estructurada. En ella se aprende el análisis de un problema cualquiera (puede ser incluso de la vida real y no de programación), cómo separarlo en problemas más pequeños y manejables, e identificar que partes del problema se repiten en otros sitios. Además se aprende a "dibujar" diagramas para representar el conocimiento y el análisis, y un metalenguaje para representar lo que serían las instrucciones equivalentes al dibujo. No solamente se aprende a pensar, sino a pensar mejor, y de forma óptima. El que piense que ya sabe pensar, que obvie esta parte del curso hasta que en el título del hilo se notifique que se comienza con el lenguaje.

- Lenguaje C#: Algunos dirán "pero por qué no con RPG Maker?". Esos, me cago en sus bocas. Otros dirán de aprender Java... pero como el curso lo doy yo, y ya dí un curso de programación orientada a videjuegos de móviles en java, pues no me sale de mis peludas pelotitas (el curso de videojuegos para móviles es recuperable para aquí si es necesario). Otros dirán cualquier otro lenguaje... y aquí mi respuesta: pene. Las ofertas de java son más numerosas pero peor pagadas que las de C#, es decir, un programador de java siempre podrá encontrar trabajo para no morirse de hambre, pero lo que cobre le dará para comprar mortadela y pan. Las de C# son más excasas pero mejor pagadas, así que podrá comprar jamón york, queso y pan bimbo. Facilidad, porque el C# es simple hasta límites insospechados. Aparte con Visual Studio y C# se pueden hacer virguerías, desde un programa profesional, webs (asp.net y silverlight), juegos (XNA), aplicaciones para móviles... ¡De todo y sencillote oiga!

- Juegos en XNA: una maravillosa framework que nos permitirá hacer creaciones para Windows, Xbox 360 y Zune. Y sin cambiar de lenguaje, usando siempre el mismo, con una facilidad asombrosa. Eso sí, no nos equivoquemos, el curso dará conocimientos como para crear juegos todo lo profesionales que podamos, pero no hay que pensar que hacer un juego comercial es llegar y besar el santo. Para empzar hace falta una idea, plasmarla, parametrizarla,... A partir de ella se hacen los bocetos, se discuten, se aprueban, se hacen los gráficos y modelos 3D, se compone la música de ambiente, los efectos, se programa el motor del juego, se integra, se hacen las pruebas de calidad... Es decir, crear un Gears of Wars no es un juego de niños ni de una sola persona, pero dará para crear casuals u otro tipo de juegos siempre y cuando dispongamos del resto de material y la idea.


La velocidad del curso será de mínimo una clase por semana. Habrá deberes, el que no los quiera hacer que no los haga, pero que no se extrañe de que si hace una pregunta tonta mire su post con desdén y de medio lado y pase de él. No pasaré de absolutamente nadie que quiera aprender realmente, y la condición de que el curso se lleve a cabo es que haya al menos un alumno con voluntad. Este curso no es de coña, realmente se enseñará a programar como un profesional, comenzando por formar la mente antes de comenzar a teclear, cosa que no se hace en otros lugares que sueltan el lenguaje y ale a picar... y luego sale lo que sale. Será duro... así que si nadie se apunta, mejor para mí, así no me enterneceré viendo sudor y lágrimas.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 13 de Mayo de 2009, 15:15
Apúntome
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: raul_isl en 13 de Mayo de 2009, 15:30
Me mola, aunque mi tiempo es reducido y no tengo ni zorra de ningun lenguaje de programacion, me apunto.
Eso si, soy muy de preguntas estupidas, asi que temo que me daras de lado :(
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 13 de Mayo de 2009, 15:46
Me alegro de que al final te hayas decidido y yo me voy a apuntar también.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Umi en 13 de Mayo de 2009, 15:49
me apunto *O* me tendrás que sufrir con preguntas mas estupidas que las de raul
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: raul_isl en 13 de Mayo de 2009, 15:52
Te reto a un duelo :gñe:



















Perdon :(

Pd: Cuando lo empieces te lo subo.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 13 de Mayo de 2009, 15:52
Cita de: MiGUi en 13 de Mayo de 2009, 15:46
Me alegro de que al final te hayas decidido y yo me voy a apuntar también.

Creo que tú viste lo que se puede hacer... pero va a ser un camino largo.

En cuanto a los de las preguntas estúpidas, leed lo que puse: cualquiera que muestre interés tiene mi respeto y mi eterna paciencia. El aviso iba para los que no muestran interés y un día entran y sueltan "hoygaaaaa, komosenchufa la kosechadora al mepe3?"
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Umi en 13 de Mayo de 2009, 15:56
Entonces me vas a poner un 10? *O*
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Aliena en 13 de Mayo de 2009, 15:56
Me apunto (seg)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: dragon.dragon en 13 de Mayo de 2009, 16:28
Mira por lo general te diria que aunque tiene muy buena pinta, voy a estar muy liado para poder dedicarle el tiempo que realmente mereceria, pero es probable que disponga de bastante tiempo libre, asi que...

Me apunto, soy genial haciendo preguntas imbeciles.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Shadark en 13 de Mayo de 2009, 16:37
Yo también me apunto, que creo que aprender C puede venirme bien...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 13 de Mayo de 2009, 16:41
Cita de: Shadark en 13 de Mayo de 2009, 16:37
Yo también me apunto, que creo que aprender C puede venirme bien...

Pues que mala suerte, porque C no voy a dar, aunque me gustaría. Es C#.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Shadark en 13 de Mayo de 2009, 16:47
Tenía que haber puesto C?, porque no recordaba si habías puesto C, C+, C++ o Cwut :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 13 de Mayo de 2009, 16:51
Puso C sharp ... Claramente además. Estás ciego.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Canon en 13 de Mayo de 2009, 16:53
Me apunto, pero ojala se empiece de cero que no tengo ni puta idea.  :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 13 de Mayo de 2009, 17:00
Creo que incluso va a empezar antes de

¡Hola, mundo!
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: dragon.dragon en 13 de Mayo de 2009, 17:04
Empezara por el clasico:

for (i=0; i<500; i++)
{
    System.out.println("No volvere a hacer gracias sobre informáticos en clase.");
}
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: raul_isl en 13 de Mayo de 2009, 17:17
Cita de: MiGUi en 13 de Mayo de 2009, 17:00
Creo que incluso va a empezar antes de

class MainClass
{
     public static void Main()
     {
         System.Console.WriteLine("¡Hola, mundo!");
     }
}


Eso que es?
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 13 de Mayo de 2009, 17:23
Yo estudio informática y de programación se lo básico (nada) ademas ahora estoy de exámenes pero bueno, apúntame a ver si te dedico algún aprobado. Solo dos preguntas:

Daremos algo de linux?

Las recuperaciones cuando serán? :unsure:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 13 de Mayo de 2009, 17:25
Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Daremos algo de linux?

No. Si algún voluntario quiere explicar Mono, adelante. Pero Microsoft es lo que tiene.

Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Las recuperaciones cuando serán? :unsure:

Al ser los hilos atemporales, cada cual es cada cual, tiene sus cadacualadas y sus horarios y fechas. Eso significa que yo pondré a un ritmo constante, y cada uno envía sus deberes cuando quiera y se los valido.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 13 de Mayo de 2009, 17:29
Cita de: Peluche en 13 de Mayo de 2009, 17:25
Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Daremos algo de linux?

No. Si algún voluntario quiere explicar Mono, adelante. Pero Microsoft es lo que tiene.

Algún voluntario entonces? Que el tema linux me interesaría bastante darlo a mi :( (o si sabéis de algún buen manual donde toque el tema de programar en linux que me lo diga)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 13 de Mayo de 2009, 18:06
¿Yo ya estoy apuntado no?
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Calabria en 13 de Mayo de 2009, 18:40
Yo me japunto que para diseño gráfico no me viene mal una base de programación, pero iré a mi ritmo (lentito)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 13 de Mayo de 2009, 19:07
Me apunto. Pelu se cagaría en mi pecho si no lo hiciese, pero es que además me interesa.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 13 de Mayo de 2009, 19:08
Cita de: ElCoCo en 13 de Mayo de 2009, 17:29
Cita de: Peluche en 13 de Mayo de 2009, 17:25
Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Daremos algo de linux?

No. Si algún voluntario quiere explicar Mono, adelante. Pero Microsoft es lo que tiene.

Algún voluntario entonces? Que el tema linux me interesaría bastante darlo a mi :( (o si sabéis de algún buen manual donde toque el tema de programar en linux que me lo diga)

Linux es muy de Juan Palomo. Acostúmbrate o dedícate a otra cosa.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 13 de Mayo de 2009, 19:48
Cita de: ElCoCo en 13 de Mayo de 2009, 17:29
Cita de: Peluche en 13 de Mayo de 2009, 17:25
Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Daremos algo de linux?

No. Si algún voluntario quiere explicar Mono, adelante. Pero Microsoft es lo que tiene.

Algún voluntario entonces? Que el tema linux me interesaría bastante darlo a mi :( (o si sabéis de algún buen manual donde toque el tema de programar en linux que me lo diga)

http://mundogeek.net/tutorial-python/

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Des en 13 de Mayo de 2009, 19:59
Me apunto!
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Genki en 13 de Mayo de 2009, 20:06
yo me apunto... puede que no sea muy listo(XD) pero creo que le pondré ganas, al menos cuando pueda... :)

y estoy con risl acerca de lo de las preguntas tontas jajjaa

Ábrenos la mente pelu
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 13 de Mayo de 2009, 21:22
Cita de: MiGUi en 13 de Mayo de 2009, 19:08
Cita de: ElCoCo en 13 de Mayo de 2009, 17:29
Cita de: Peluche en 13 de Mayo de 2009, 17:25
Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Daremos algo de linux?

No. Si algún voluntario quiere explicar Mono, adelante. Pero Microsoft es lo que tiene.

Algún voluntario entonces? Que el tema linux me interesaría bastante darlo a mi :( (o si sabéis de algún buen manual donde toque el tema de programar en linux que me lo diga)

Linux es muy de Juan Palomo. Acostúmbrate o dedícate a otra cosa.

En interneten hay vídeos de gente comiendo mierda, de gente copulando con animales, tiene que haber algo de linux a la fuerza


Mergsi brujo ^^
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 13 de Mayo de 2009, 21:59
El sábado subiré la primera lección y comenzamos. Cada vez que suba un capítulo, lo subiré en texto y además un pdf con todo lo que se lleva hasta el momento.

Para curiosos, el objetivo del curso es conseguir que hagais esto:
http://www.screencast.com/t/sluTGTO3

Para los más curiosos todavía, y aunque algunos ya lo habíais visto, este era el conato de primera lección pero el audio me quedó como el culo:
http://www.screencast.com/t/KkDIuNrI

Al final decidí no ir directamente al XNA, dado que no todo el mundo sabe programar ni todo el mundo sabe C#, así que empezando de cero pero a buen ritmo. Con ese vídeo os haréis una idea de cómo serán las lecciones con videotutos.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 13 de Mayo de 2009, 22:03
Cita de: Peluche en 13 de Mayo de 2009, 21:59
El sábado subiré la primera lección y comenzamos. Cada vez que suba un capítulo, lo subiré en texto y además un pdf con todo lo que se lleva hasta el momento.

Para curiosos, el objetivo del curso es conseguir que hagais esto:
http://www.screencast.com/t/sluTGTO3

Todo se llevara en este hilo no?


P.d- Recuerdame que nunca acepte subir a tu coche.

Edito: Me acabo de leer el post inicial (si, soy algo lento) y he caído en una cosa. Peluche tu no te llamaras por casualidad Miguel Aranega no? Joder es que lo de "y mi respuesta: pene. Lo dijo nada mas presentarse y con un contexto algo similar.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 13 de Mayo de 2009, 22:12
Cita de: ElCoCo en 13 de Mayo de 2009, 21:22
Cita de: MiGUi en 13 de Mayo de 2009, 19:08
Cita de: ElCoCo en 13 de Mayo de 2009, 17:29
Cita de: Peluche en 13 de Mayo de 2009, 17:25
Cita de: ElCoCo en 13 de Mayo de 2009, 17:23
Daremos algo de linux?

No. Si algún voluntario quiere explicar Mono, adelante. Pero Microsoft es lo que tiene.

Algún voluntario entonces? Que el tema linux me interesaría bastante darlo a mi :( (o si sabéis de algún buen manual donde toque el tema de programar en linux que me lo diga)

Linux es muy de Juan Palomo. Acostúmbrate o dedícate a otra cosa.

En interneten hay vídeos de gente comiendo mierda, de gente copulando con animales, tiene que haber algo de linux a la fuerza


Mergsi brujo ^^

Cuando empecé hace 10 años había ya bastante material, hoy mucho más.

Por eso digo que tiene delito andar pidiendo manuales existiendo Google y un volumen de documentación cuasi infinito.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 13 de Mayo de 2009, 22:16
Cita de: ElCoCo en 13 de Mayo de 2009, 22:03
Todo se llevara en este hilo no?

Texto y charla en este hilo, pdfs a megaupload, videotutos a screencast.


Cita de: ElCoCo en 13 de Mayo de 2009, 22:03
P.d- Recuerdame que nunca acepte subir a tu coche.

Gilivainas, que esto es un portátil sin aceleradora, y va a saltos. En la xbox va de puta madre, y en un pc normal también. Por eso conduzco como el culo (sumado a que el freno no sé qué es)

Cita de: ElCoCo en 13 de Mayo de 2009, 22:03
Edito: Me acabo de leer el post inicial (si, soy algo lento) y he caído en una cosa. Peluche tu no te llamaras por casualidad Miguel Aranega no? Joder es que lo de "y mi respuesta: pene. Lo dijo nada mas presentarse y con un contexto algo similar.

¿Miguel Aranega? No me suena. Mi nombre es Jesús, como el hippy ese del libro de fantasía.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: neoprogram en 13 de Mayo de 2009, 22:19
Me gusta el cursillo ^^:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 14 de Mayo de 2009, 01:47
Estoooo... Me apunto, que el RPG Maker es una basura y yo quiero revivir el espíritu de Lucas... *.*
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Aliena en 14 de Mayo de 2009, 01:50
Cita de: Penguin Boy en 14 de Mayo de 2009, 01:47
Estoooo... Me apunto, que el RPG Maker es una basura y yo quiero revivir el espíritu de Lucas... *.*

Hahahá! Envidrioso : D
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: jug0n en 14 de Mayo de 2009, 01:56
Yo juego, pero un poco a mi ritmo vale? :oops:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Canon en 14 de Mayo de 2009, 03:09
C+ es diferente a C# ?  Pelu dinos que putos programas hay que conseguir para ir buscandolos.  :amo:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 14 de Mayo de 2009, 09:31
Cita de: canon en 14 de Mayo de 2009, 03:09
C+ es diferente a C# ?  Pelu dinos que putos programas hay que conseguir para ir buscandolos.  :amo:

RTFW http://es.wikipedia.org/wiki/C_Sharp
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 14 de Mayo de 2009, 10:17
Cita de: canon en 14 de Mayo de 2009, 03:09
C+ es diferente a C# ?  Pelu dinos que putos programas hay que conseguir para ir buscandolos.  :amo:

C++ y C# son totalmente diferentes, al igual que C++ y Ansi C son totalmente diferentes. No es que C++ sea C mejorado y C# sea C++ mejorado, sino que son lenguajes distintos basados en una misma estructura inicial (la forma de definir constantes, variables, funciones, nombres de tipos básicos, carácter de fin de sentencia...).

C++ nació para estructurar el Ansi C existente y para ofrecer la orientación a objetos. C# nació para sustituir el lenguaje C++ por uno más intuitivo, así como para poder trabajar sobre la plataforma .net.

Veamos como sería el hola mundo en C, C++ y C#:

#include <stdio.h>

int main()
{
    printf("Hola Mundo en Ansi C");
    return 0;
}


#include <iostream>

using namespace std;
int main() {

    cout << "Hola Mundo en C++" << endl;
    return 0;
}


usign System;

class HolaMundo
{
     public static void Main(String[] args)
     {
         System.Console.WriteLine("Hola, mundo en C#");
     }
}


Pero vamos, te hago un análisis por encima de las diferencias entre C++ y C#:
- El C++ se compila a lenguaje máquina, mientras que C# compila a código intermedio (IL) que será interpretado por la máquina JIT de la plataforma .net.
- El C# tiene un gestor de memoria no referenciada (recolector de basura...) esto significa que si en C++ creas un objeto y te olvidas de liberarlo la memoria se pierde y puede generar memory leaks, mientras que en C# cuando un objeto no es referenciado por nadie y por tanto no utilizado se autolibera.
- En C++ los punteros son el pan nuestro de cada día, mientras que en C#, si bien se pueden utilizar, son prescindibles y solamente se pueden usar en ciertas circunstancias.
- Las librerías en C++ se basan en librerías estándar y con plantilla (fichero .h) mientras que C# se basa en las clases base de .net.
- C++ no ofrece mucha ayuda para realizar las interfaces gráficas, y normalmente hay que bajarse al pilón de la API, mientras que C# sí está ligado a una interfaz gráfica fácilmente definible.
- C# incluye nuevos conceptos de la programación orientada a objetos que C++ no incluía: delegados (para sustutuir los punteros a funciones), propiedades, eventos, interfaces, atributos...

Así por encima oiga.

¿Lo que te tienes que bajar? En la primera parte del curso, tienes que bajar tú mismo al súper y comprar papel (el cuadriculado va muy bien para estas cosas), lápices, afilalápiz y goma de borrar. No se va a terminar pronto dado que mucha gente de la apuntada jamás ha programado, así que hay que empezar desde lo más sencillo, que es el concepto de problema, solución a un problema y algoritmo (en su significado amplio y no informático, es decir, una receta de cocina es un algoritmo).

En la segunda parte ya se utilizará un entorno de programación para acostumbrarse a él y se aprenderán las bases del lenguaje C#, así que para la segunda parte deberías bajarte el Visual Studio 2008 (la versión Express es de gratís, y si eres estudiante hay sitios dónde conseguir licencias... claro que seguro que eres piratón y consigues una versión megachachi).

En la tercera parte se instalará la framework del XNA en el Visual Studio, y me temo que también hará que instalar programas (los que quieran) para toquetear gráficos (adobe photoshop CS3 es un buen ejemplo), para toquetear música electrónica (fruity loops o el melodyne studio...) o incluso para diseñar modelos 3D y sus texturas (Poser, 3D Studio, Rhinoceros 3D).

Si quieres hacer un juego 3D que incluya personajes, necesitarás que sus caras sean expresivas, así que también necesitarías software de modelado de caras. Hay algunos muy chulos que incluso pillan información directamente de una foto de tu cara, por ejemplo: http://www.facegen.com/modeller.htm
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 14 de Mayo de 2009, 10:43
Yo creo que esto

Citar
- El C# tiene un gestor de memoria no referenciada (recolector de basura...) esto significa que si en C++ creas un objeto y te olvidas de liberarlo la memoria se pierde y puede generar memory leaks, mientras que en C# cuando un objeto no es referenciado por nadie y por tanto no utilizado se autolibera.

es una de las cosas más interesantes que tiene C#.

ElCoco tienes un hilo de dudas sobre Linux para preguntar lo que quieras
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 14 de Mayo de 2009, 14:33
¡Recolector de basura! ¡No hay que estar con punteros arriba y abajo! :wiiiiii:

C# me ha convencido ya. :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 14 de Mayo de 2009, 18:06
Yo no sé de lo que habláis, pero tiene pinta de interesante. Aún así, veo que los textos y los paréntesis van a ser el problema de este lenguaje...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 14 de Mayo de 2009, 18:36
Los paréntesis se usan de forma similar a como se usan en expresiones matemáticas (por no decir igual).
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Nachowsky en 14 de Mayo de 2009, 19:07
Venga va, yo también me apuntaré. A pesar de que en el cursillo de Visual Basic que hice en mi escuela no logré pasar del 3 en raya, estoy seguro de que el profesor ésta vez no será un incompetente.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 14 de Mayo de 2009, 19:40
Cita de: Nachowsky en 14 de Mayo de 2009, 19:07
Venga va, yo también me apuntaré. A pesar de que en el cursillo de Visual Basic que hice en mi escuela no logré pasar del 3 en raya, estoy seguro de que el profesor ésta vez no será un incompetente.

lol de eso tengo yo un examen mañana, pero en C.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 14 de Mayo de 2009, 20:19
Cita de: Faerindel en 14 de Mayo de 2009, 18:36
Los paréntesis se usan de forma similar a como se usan en expresiones matemáticas (por no decir igual).

Ya imaginaba, algo así como en sql... pero siempre se te olvida un paréntesis por cerrar...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 14 de Mayo de 2009, 21:43
Suele pasar. Suerte que está el IDE y su corrector sintáctico de serie que te lo canta.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: raul_isl en 14 de Mayo de 2009, 23:02
Mola el video tuto, pero me he empapado muy poco.
Empezaras programacion a ese ritmo? :llori:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 14 de Mayo de 2009, 23:36
Libro I, aprendiendo a pensar

1. Los problemas decrecen

Cuando alguien piensa en un "programador" piensa en un tío tecleando. Eso es tan cierto como que un neurobiólogo está siempre al microscopio, un astrofísico mirando por un telescopio y un arquitecto poniendo estructuras de hormigón. El ordenador es tan solo una herramienta, el paso final, los lenguajes de programación son igual que los idiomas que se usan para hablar, lo importante de las frases es pensarlas, y si no que le pregunten a un mudo.

La mente es la mayor y única herramienta que no se puede oxidar de un programador. Los lenguajes de programación cambian y evolucionan a velocidades increíbles, la tecnología también, pero hay una constante: el que tiene una mente analítica le sirve para cualquier situación.

Comenzar a programar directamente con el lenguaje es tan inútil como enseñar a hablar a un niño ciego. Un bebé observa el mundo, intenta tocar los objetos por curiosidad y para medir la distancia, se chupa un pie porque le mola.... bueno, y porque cuando lo chupa siente cosquillas y puede contarse los dedos. Solamente cuando su cerebro ya tiene suficiente información sobre el mundo es cuando comienza a poner nombres a las cosas: papá, mamá, butanero,... Así que desde aquí un bechi a todos los profesores de programación del mundo que comienzan explicando los comandos de un lenguaje, porque son máquinas de cagar ineptos.

Así que hablemos del análisis. Cuando se programa algo es porque existe una necesidad que conlleva asociada un problema. Esto es lo mismo en la vida real para todos los problemas, por ejemplo llegar a fin de mes es una necesidad que conlleva un problema bastante serio, pero que puede llevarse mejor con un cierto análisis. Lo que caracteriza a un buen analista es que sabe ver el problema en su globalidad, pero también descomponerlo en componentes sin agobiarse por el tamaño. Imaginad que un problema es una gran burbuja ante la que nos sentimos pequeños. Un analista comienza a pinchar la burbuja con su alfiler mágico +5 matadragones, y convertirla en pequeñas burbujas que dependen unas de otras. Llegar a fin de mes, por ejemplo, es una burbuja que puede descomponerse en calcular el dinero entrante, calcular el dinero fijo saliente, estimar los gastos no fijos, dividir las cifras en pequeñas necesidades... Y cada problema nuevo se puede subdividir. ¿De qué nos sirve esto? Pues bueno, la burbuja inicial era inabordable, un monstrenco que nos asustaba. En cambio ahora tenemos muchos pequeños problemas. ¿A qué preferías enfrentaros, a un gran dragón o a 1000 pequeñas hormigas?

También un analista debe ser capaz de ver los subproblemas con un patrón repetitivo. Por ejemplo, supongamos que tenemos que preparar cena para varios comensales, con entrantes, cena fuerte y postre. En los problemas de "cocina" hay patrones comunes como "cortar" o "calentar". No todos los cortes son iguales, por ejemplo si hacemos una sopa podemos cortar verduras en juliana, si hacemos sushi cortamos pepino en tiras, si hacemos patatas fritas las cortamos en.... patatas fritas. Podríamos hacer un problema cortar específico para cada cosa, como por ejemplo cortarPatatasFritas, cortarPepino.... pero pensad en cuántas cosas existen que se pueden cortar para cocinar. Así que al final el subproblema "cortar" tendrá 3 parámetros que serán: qué cortamos, cuánto cortamos y cómo lo cortamos. Para empezar sin liarnos, se puede usar el lenguaje natural, de esta forma para prepar sushi tendríamos el algoritmo:


Cortar pepino, 30 gramos por comensal, en tiras
Cortar salmón, 40 gramos por comensal, en tiras
Calentar arroz, media taza por comensal
Mezclar arroz con vinagre de sushi
Poner alga sobre esterilla
Cubrir alga con arroz
Poner pepino al principio
Poner salmón al principio
Enrollar
Cortar canuto de sushi, 2 cms, en cilindritos


¿Lo bonito de todo esto? Que los verbos, el algoritmo, la profundidad de vuestros subproblemas, los parámetros... todo, absolutamente todo, sale de vuestra mente y a vuestro gusto. Y algunos subproblemas son divisibles a su vez, por ejemplo calentar arroz puede dividirse en lavar el arroz, sacar la olla del armario, echar un vaso de agua por cada medio de arroz, echar el arroz, poner a fuego medio, esperar a que se evapore el agua.

Fácil, por ahora.

Pues ahora los deberes:

De un plato con el que estéis familiarizados a cocinar ( o forma de subsistencia vital ) diseñad un algoritmo de forma que cualquiera al que paséis dicho algoritmo pueda repetir vuestro plato de forma exacta, y explicad por qué escogéis esa subdivisión en problemas pequeños y no otra
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 15 de Mayo de 2009, 00:32
Me ha quedado claro que ser programador es como jugar al Pang: revientas burbujas haciendo que se partan por la mitad hasta que por fin desaparecen del todo.

Después de tirarme media hora jugando a susodicho juego y recordar lo mal que se me da, espero que no me pase lo mismo con esto y planteo un par de dudas: ¿lo colgamos aquí o te lo enviamos?¿cómo lo justificamos?

Lo último lo digo porque habrá cosas que sea absurdo explicar: cuezo el arroz porque, si no, me lo tomo crudo y eso es inmasticable, entre otras cosas. Y lo cuezo echándolo en una cazuela de agua hirviendo porque la experiencia me ha dicho que así se hace el arroz. No le veo más explicación. Así que eso, a ver si me aclaras cómo quieres que te lo justifiquemos y eso.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 00:47
Cita de: Penguin Boy en 15 de Mayo de 2009, 00:32
Después de tirarme media hora jugando a susodicho juego y recordar lo mal que se me da, espero que no me pase lo mismo con esto y planteo un par de dudas: ¿lo colgamos aquí o te lo enviamos?¿cómo lo justificamos?

Como prefirais. Está claro que enviado es secreto, colgado aquí lo ven todos, y si tienes miedo a la crítica en público... pues MP, y si no a darle vidilla al hilo. En cuanto a lo de justificar, cada cerebro es único, cada persona también. En este ejercicio no hay solución o justificación incorrecta, todos los ejercicios estarán bien, claro que con mejor o menor estilo. Los que subdividan poco tendrán poco estilo, porque no tendrán problemas suficientemente pequeños o reaprovechables. Los que subdividan mucho tendrán demasiados problemas como para ser manejables.

Cita de: Penguin Boy en 15 de Mayo de 2009, 00:32
Lo último lo digo porque habrá cosas que sea absurdo explicar: cuezo el arroz porque, si no, me lo tomo crudo y eso es inmasticable, entre otras cosas. Y lo cuezo echándolo en una cazuela de agua hirviendo porque la experiencia me ha dicho que así se hace el arroz. No le veo más explicación. Así que eso, a ver si me aclaras cómo quieres que te lo justifiquemos y eso.

Verás, lo de que hay que cocer el arroz lo sabe una persona porque lo ha aprendido. Aquí el objetivo es que sea la receta sea reproducible por cualquier persona, incluso si jamás ha cocinado... ¡o incluso si jamás ha comido! ¿Qué diferencia cocer, de hornear, de hervir, de freir...? Todos son verbos diferentes ;)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 15 de Mayo de 2009, 10:41
Ea, pues mandado xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 15 de Mayo de 2009, 11:36
¿Tiene que ser un plato de cocina o vale un protocolo de laboratorio? Básicamente, tienden a ser lo mismo.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 11:37
Cita de: Khram Cuervo Errante en 15 de Mayo de 2009, 11:36
¿Tiene que ser un plato de cocina o vale un protocolo de laboratorio? Básicamente, tienden a ser lo mismo.

Un protocolo de laboratorio no deja de tener el mismo espíritu que una receta. Vamos, la última vez que miré cómo se sintetizaba LSD, incluso había que hornearlo. Claro que vale.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 15 de Mayo de 2009, 14:55
Antes de presentar el ejercicio un par de explicaciones:


Lo presento en publico para ver los fallos y tal, si os apetece insultar apretaros un huevo hasta que se os pase las ganas, (o en el caso que hagan plof también parar). Esto no quiere decir que no acepte criticas constructivas.

Yo no se de medidas justas, así que uso cucharones (la medida mas exacta es lo que te quepa en la dos manos) y latas (latas normales y corrientes de atún y maíz).

Lo que vamos a preparar hoy es "Sustento de clave para 6 días de la semana"


Echar aceite en el cazo hasta cubrir finamente el fondo, junto a un par de ajos cortados.
Añadir un cucharon de arroz por persona.
Sofreír con el mínimo fuego "mareando" el arroz durante 5 minutos..
Verter 2 cucharones de agua por cada 1 de arroz, y una pizca de sal.
Mantener 20 minutos al fuego mínimo desde el momento en el que empiece a hervir.
En las raciones individuales añadir atún (1 lata estándar), maíz(1/4 de lata estándar).
Comer con la boca preferentemente.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 15:10
Cita de: ElCoCo en 15 de Mayo de 2009, 14:55

Echar aceite en el cazo hasta cubrir finamente el fondo, junto a un par de ajos cortados.
Añadir un cucharon de arroz por persona.
Sofreír con el mínimo fuego "mareando" el arroz durante 5 minutos..
Verter 2 cucharones de agua por cada 1 de arroz, y una pizca de sal.
Mantener 20 minutos al fuego mínimo desde el momento en el que empiece a hervir.
En las raciones individuales añadir atún (1 lata estándar), maíz(1/4 de lata estándar).
Comer con la boca preferentemente.


Bueno, está bien, separaras en subproblemas. Sin embargo, lo de reutilizar "no mola" en informática. Por ejemplo, pones "Echar aceite en el cazo hasta cubrir finamente el fondo, junto a un par de ajos cortados.", ¿por qué no poner "Echar aceite en el cazo hasta cubrir finamente el fondo, junto a un par de ajos cortados y un cucharón de arroz por persona"?

Seria más correcto:
Echar aceite en el cazo hasta cubrir finamente el fondo.
Echar un par de ajos cortados.


Cubrir finamente el fondo de un cazo son como dos cucharadas, y para echar ajos cortados hay que cortarlos... y no me has especificado el corte (¿¿¿¿estás seguro de que son dos ajos enteros y no dos dientes?????? ¿Cortados? Yo los picaría). Supongamos que efectivamente son dos ajos y cortados:
Echar dos cucharadas de aceite en el cazo.
Cortar dos ajos.
Echar los ajos cortados en el cazo.


Y seguiríamos, porque no has dicho que el cazo se ponga a fuego, con lo cual al que le pasaras la receta echaría el ajo en aceite frío, que suele ser como epic fail.

No te preocupes, el ejercicio solamente era para aprender a subdividir problemas. En informática existen las instrucciones (es decir, comandos que posee el lenguaje de programación). Con las instrucciones se construyen funciones, que sería el equivalente a nuestros "subproblemas", y las funciones las inventa cada programador siguiendo su propia lógica. Si no existieran, los programas tendrían miles de líneas no separables, y leerlos sería el infierno robot. Por eso lo de subdividir y tal, y jamás dar por sentado que el ordenador tiene imaginación como para suponer "bueno, el programador ha escrito esto, supongo que quiere decir esto otro". Hay que darle todo mascadito.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 15 de Mayo de 2009, 15:11
Me pone tu rollo, peluche, quería apuntarme pero prefería ver antes de qué iba la mandanga. Me apunto, capaz que me sirva en un futuro para hacer una presentación guapa para la uni or something like that.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 15 de Mayo de 2009, 15:25
uhm a ver si para el próximo no la cago tanto xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 15 de Mayo de 2009, 15:29
Algoritmo para preparar Macarrones con atún y champiñones. Ración individual

Abrir paquete de macarrones
Abrir lata de atún
Abrir lata de champiñones
Calentar 200g macarrones
Escurrir macarrones
Sofreir champiñones y atún
Añadir tomate frito
Echar macarrones
Calentar el conjunto



Qué pasa con las demás variables? Qué tipo de olla, cuánta agua para calentar, cuánto tiempo calentando, etc, etc? Por ejemplo, yo quería poner que mientras se escurren los macarrones, en la misma olla, ir echando los champiónes y el atun, después el tomate, y pasados unos minutos los macarrones ya escurridos.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 15:32
Pues el resto de variables son como las quieras poner. Por ejemplo cuando calientas algo puedes especificar a qué temperatura. Lo del tiempo lo podrías decir también como parámetro de calentar, o invertarte un subproblema que se llame "Esperar".

En tu problema veo fallos también:

"Calentar 200g macarrones"

Espero por tu bien que lo que calientes sea una olla con agua, porque poner los macarrones directamente al fuego... no quedan bien.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 15 de Mayo de 2009, 15:37
CitarCortar salmón, 40 gramos por comensal, en tiras
Calentar arroz, media taza por comensal

Me he copiado de ti, no sabía si se tenía que poner, tampoco sabía si se podían poner frases largas para explicar las sucesiones temporales, como todo lo que he visto es escueto cual telegrama xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 15:39
Cita de: Rohi en 15 de Mayo de 2009, 15:37
CitarCortar salmón, 40 gramos por comensal, en tiras
Calentar arroz, media taza por comensal

Me he copiado de ti, no sabía si se tenía que poner, tampoco sabía si se podían poner frases largas para explicar las sucesiones temporales, como todo lo que he visto es escueto cual telegrama xD

Que yo lo ponga de ejemplo no quiere decir que esté óptimo del todo :D Más que nada, yo también cometo errores, si no los cometiese qué aburrimiento. Mea culpa!
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 15 de Mayo de 2009, 15:40
Joder parece un curso de cocina mas que de programación ahora xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 15:41
Cita de: ElCoCo en 15 de Mayo de 2009, 15:40
Joder parece un curso de cocina mas que de programación ahora xD


¿A que sí? Pues ya verás el choteo que va a haber en el siguiente capítulo con el robot satánico.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 15 de Mayo de 2009, 15:42
No pero no quería resaltar tu error coño, quería decirte que me he copiado porque no tengo ni la más mínima puta idea, si me dices que puedo hacer frases largas, y especificar todo eso, pues lo repito y a ver qué tal queda.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 15 de Mayo de 2009, 15:48
El problema, rohi, es que sin terminar una tarea, empiezas otra. Algo así:


Abrir paquete de macarrones.
Poner agua en olla, 2l.
Encender fuego, intensidad media.
Calentar agua en olla, 20 min, 100ºC.
Añadir macarrones, 200g.
Calentar macarrones en agua en olla, 10 min.
Remover para que no se pegue.
Apagar fuego.
Quitar olla de fogón.
Separar macarrones de agua.


Simplificando las tareas y los datos a introducir se gana tiempo de programación y al compilador se lo pondrás también más fácil. Pues esto es igual: no es lo mismo una receta del Arguiñano que una para un curso de programación...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: jug0n en 15 de Mayo de 2009, 15:52

Llenar media olla de agua.
Lavar (lentejas)
Lavar(laurel)
Lavar(ajo)
Pelar(cebolla)
Lavar(cebolla)
Pelar(patatas)
Cortar(patatas)
Introducir en la olla(lentejas, ajo, laurel, cebolla, patatas, pimentón, aceite, sal)
Encender gas
Encender fuego
Dejarlas hervir
Remover de vez en cuando
Esperar 45 minutos aproximadamente
Servir y comerse la sosería de lentejas que se hacer yo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 15:55
Que hijoputa el jug0n, lo ha bordao.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: jug0n en 15 de Mayo de 2009, 15:56
Hombre, como cocinero no me ganaré la vida, porque la receta es sosa, todo hay que decirlo, pero como programador algo tengo :oops:

Me ha dicho mi madre que me faltaba declarar las variables > _ <
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 16:00
Cita de: jug0n en 15 de Mayo de 2009, 15:56
Me ha dicho mi madre que me faltaba declarar las variables > _ <

Jajjaaj, no hacían falta. Pero bueno, has incluído la parte de formato de las oraciones, que se supone que es el siguiente capítulo :D
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: jug0n en 15 de Mayo de 2009, 16:01
Soy un adelantado a mis tiempos :$

y ya, ya me voy y dejo de forochatear :D
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 15 de Mayo de 2009, 16:02
A la salida te esperas, maldito empollón :O


:lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 15 de Mayo de 2009, 16:09
Tortilla de patatas a la vasca v.0.3 (Sin cebolla) 4 personas.

Abrir saco de patatas.
Abrir huevera.
Sacar pan.
Pelar y trozear 200g de patatas.
Freir durante 2 minutos en la freidora a 220º.
Dejarlas escurrir.
Abrir y Batir media docena de huevos.
Calentar aceite en sartén.
Volcar mezcla de huevo y trozos de patata semi-hecha en sarten.
Calentar durante unos minutos.
Vuelta y Calentar por el otro lado.
Retirar sartén.
Trozear 1 barra de pan en rodajas.
Montar un cacho de tortilla por cada rodaja de pan.
Servir en plato grande y llano.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Aliena en 15 de Mayo de 2009, 16:27
Creo que ya quedó claro hace tiempo que la tortilla sin cebolla es para lusers :O
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: YoYo en 15 de Mayo de 2009, 16:29
Como que a la vasca? X(
La tortilla sin cebolla es la tortilla normal uhm
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 15 de Mayo de 2009, 16:35
Ensalada de pasta:

Poner agua en una olla, hasta la mitad
Echar aceite en el agua, un chorrito
Poner la olla en la vitrocerámica.
Encender la vitrocerámica, nivel 5
Echar sal a la olla
Esperar a que hierva el agua
Echar la pasta
Bajar el nivel de la vitrocerámica al 3
Esperar a que se cueza
Retirar la olla de la vitrocerámica
Abrir grifo de la fregadera, agua fría
Escurrir la pasta en la fregadera
Cerrar grifo
Verter la pasta en un bol
Añadir al bol maíz, atún, aceitunas y mahonesa
Mezclar los ingredientes del bol
Servir
Comer


El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 15 de Mayo de 2009, 16:44

Previo:
MaterialBizcocho(
  1 bol grande,
  1 batidor manual,
  1 cazo,
  1 horno,
  1 bandeja del horno,
  1 molde para bizcochos circular,
  1 palillo largo que hace de sonda,
  1 plato grande)

IngredientesBizcocho(
  3 huevos,
  300 gr de mantequilla,
  300 gr de azúcar,
  300 gr de harina de trigo para repostería,
  50 ml de leche)

Acciones a realizar:

esperar(tiempo)
No hacer nada durante tiempo
Fin de esperar

verter(ingrediente, peso, recipiente)
si el ingrediente es un huevo entonces
  fracturar cáscara
  separar contenido de la cáscara
  deshechar cáscara
verter ingrediente en recipiente
Fin de verter

derretir(ingrediente, peso, recipiente, nivel de fuego, estado)
verter ingrediente en recipiente
poner ingrediente en el fuego al nivel de fuego indicado
esperar a que estado sea derretido
Fin de derretir

batir(herramienta, recipiente)
introducir herramienta en recipiente
usar herramienta para que los ingredientes queden completamente mezclados
Fin de batir


hornear(temperatura, tiempo de precalentamiento, tiempo de coccion, tiempo de espera)
dejar una bandeja en el horno a media altura
programar horno a temperatura durante tiempo de precalentamiento
introducir molde con el contenido en su interior
esperar tiempo de cocción
introducir sonda(estado)
  si el estado de la sonda es manchado entonces
  esperar(tiempo de espera)
  si no
   apagar horno
   esperar(tiempo de espera)
   abrir horno
   retirar molde de la bandeja del horno
Fin de hornear


elaboracionBizcocho

mezclarIngredientes:
verter(huevo, 300 gr, bol grande)

verter(azucar, 300 gr, bol grande)

verter(harina, 300 gr, bol grande)
  si estado derretirMantequilla es derretido
   verter(mantequilla, 300gr, bol grande)
  si no
   esperar hasta que estado sea derretido.

verter(leche, 50 ml, bol grande)
Fin de mezclarIngredientes

amasar(huevos, azucar, harina, mantequilla, leche, bol grande)
si estan todos los ingredientes en el bol grande entonces
  batir(manos, bol grande)
si no, mezclarIngredientes
Fin de amasar

hornear(180º, 15 minutos, 25 minutos, 5 minutos)

esperar(1 hora)

Separar bizcocho del molde

Servir en plato grande

Fin de elaboracionBizcocho
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 15 de Mayo de 2009, 16:46
Cita de: Aliena en 15 de Mayo de 2009, 16:27
Creo que ya quedó claro hace tiempo que la tortilla sin cebolla es para lusers :O

+1000
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 15 de Mayo de 2009, 17:10
MiGUi, trampas... ¡tú ya sabías!
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 15 de Mayo de 2009, 17:16
Es parametrizar un problema, ni siquiera es pseudocódigo.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 15 de Mayo de 2009, 17:21
Pollo a la cerveza by yo. Lo he hecho en plan campechano porque no quiero copiarme y saltarme la próxima lección (además así es más fácil y no tengo que pensar valores exactos).

Nos preocupamos de tener una casa.
Nos preocupamos de que esa casa tenga cocina.
Nos preocupamos de que en esa cocina haya fogones o vitrocerámica.
Nos preocupamos de que en esa cocina haya gas o electricidad que nos permita hacer funcionar los anteriores.
Nos preocupamos de que en esa cocina haya agua corriente.
Compramos cazuela.
Compramos tijeras.
Compramos cuchillo.
Compramos el pollo (pechugas o contramuslos, sin hueso / cantidad lo que estés dispuesto a comer)
Compramos cebollas (mínimo 1 grande por cada 2 personas, en mi opinión).
Compramos cerveza.
Compramos sal.
Compramos aceite.
Si hace falta, compramos cerillas o encendedor.
En caso de tener fogones:
          Sacamos una cerilla.
          Giramos la llave del gas.
          Encendemos la cerilla.
          Acercamos la cerilla encendida al fogón para prender el gas.
          Apagamos la cerilla.
En caso de tener vitrocerámica:
          Le damos al botón para que se encienda.
Colocamos la cazuela sobre el fogón o la vitrocerámica que hayamos encendido.
Echamos aceite en la cazuela, hasta cubrir el fondo pero que el pollo no vaya a nadar en ella.
Sacamos el pollo.
Si tiene piel, le quitamos la piel (A TIRAS!).
Troceamos el pollo con la tijera en trozos que seamos capaces de meternos en la boca sin asfixiarnos.
Echamos el pollo en la cazuela.
Echamos sal sobre el pollo.
Dejamos que el pollo se dore, para esto el fuego debe estar bajo.
Sacamos las cebollas pertinentes.
Pelamos las cebollas pertinentes.
Cortamos las cebollas, ya sea en anillos o en juliana (anillos en mi caso).
Echamos las cebollas cortadas en la cazuela.
Cuando tanto el pollo como la cebolla estén bien dorados, añadimos una lata de cerveza de 33 cl.
          Si queremos, podemos añadir algo de agua a la cazuela para suavizar el sabor (¬_¬).
          Si somos muchos, podemos añadir otra cerveza a la cazuela. Siempre en función de nuestras necesidades y gustos.
Se deja cocer durante unos 40 minutos a fin de que se evapore el alochol y tanto el pollo como la cebolla tomen sabor.
Apagamos el fogón o la vitrocerámica.

Cómo servir no estaba en los deberes, así que me lo ahorro (además no he comprado platos).
Mientras hacemos esta receta no es raro que nos dé por bebernos la cerveza. Para evitar hacernos un lío con las medidas, procurad tener a mano una cerveza para la comida y otra para nosotros.


Os adjunto un video que explica cómo preparar otro plato con bastante estilazo, aunque no sé hasta que punto resultará analítico... :huh:

zXEyPwU9VjE
http://www.youtube.com/watch?v=zXEyPwU9VjE
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 15 de Mayo de 2009, 17:44
Aquí el curso lo da Migui.

¿Qué, vais de pro?
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 15 de Mayo de 2009, 18:08
Cita de: [Y]arot~ en 15 de Mayo de 2009, 17:44
Aquí el curso lo da Migui.

¿Qué, vais de pro?

¿Vienes a joder el curso o algo así?
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 15 de Mayo de 2009, 21:55
Cita de: MiGUi en 15 de Mayo de 2009, 18:08
Cita de: [Y]arot~ en 15 de Mayo de 2009, 17:44
Aquí el curso lo da Migui.

¿Qué, vais de pro?

¿Vienes a joder el curso o algo así?

au contraire. Tienes tu detector de sarcasmos roto.

Podrías (podriais) empezar y seguir el curso con las pautas que vaya marcando pelu, sin avanzar temas, puesto que la gente que no tiene ni idea va a querer reflejar algo parecido y va a meter la pata. Además de mostrar humildad, demuestrar tener sentido común.

Es que siempre he odiado a los que ivan de listos en clase.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 22:32
A ver, el fallo fue mío por no decir que todo el mundo mandase las cosas por MP. Los que ya saben programar algo, véase migui o jug0n, está claro que tienen conceptos más avanzados y tal, y cuando ya se tienen cuesta volver hacia atrás (no hay más que ver que mi receta llevaba errores...). No os peguéis, que mañana pongo la lección 2, y será divertida y frustrante a la vez.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Nachowsky en 15 de Mayo de 2009, 22:58
¡Profe! Exijo castigo para los superdotados que interrumpen la clase, no me dejan aprender tranquilo. uhm

Éso de "comprar cuchillos", "comprar tijeras", ¿no es un poco exagerado? Es que me da la sensación de que ya entraría en subdividir tanto que te creas más problemas de los necesarios.



Receta de una amiga, pastel de carne:

"Primer paso: crear la masa"
Limpiar las manos a conciencia, paso especial para guarr@s.
Verter 250 gramos harina sobre superfície de trabajo.
Añadir 25 gramos de mantequilla sobre harina.
Añadir una pizca de sal.
Mezclar cuidadosamente la harina con la mantequilla.
Cuando la harina tome un color amarillento, añadir poco a poco agua templada.
Amasar y añadir agua hasta que deje de pegarse.
Seguir amasando hasta que esté preparada.
Hacer pelota con la masa.
Reservar la masa en un plato.
Humedecer un paño.
Cubrir el plato y la masa con el paño.
Dejar reposar.

"Segundo paso: el relleno"
Poner una sartén con dos cucharadas de aceite a calentar.
Pelar: una cebolla, un diente de ajo.
Picar: cebolla, diente de ajo.
Picar un poco de perejil (en caso de no tener ya picado).
Cuando el aceite esté caliente,
     verter la cebolla picada, el diente de ajo y el perejil.
     añadir salsa de tomate frita.
     añadir medio kg. de carne picada.
Saltear y sofreír todo junto.
(OPCIONAL) Cuando esté todo sofrito,
     picar olivas negras y alcaparras, y añadir al sofrito.

"Tercer paso: a por el pastel"
Empezar a calentar el horno, 160º-180º.
Dividir la bola de masa en dos partes.
Reservar la mitad pequeña.
Estirar la mitad grande.
Engrasar un molde con aceite o mantequilla.
Insertar la masa estirada de forma que recubra el molde por el interior, haciendo asomar los bordes.
Cubrir el fondo con queso avarti en lonchas.
Cubrir el queso con una capa de sofrito.
Cubrir el sofrito con lonchas de queso avarti.
Repetir los dos anterior procesos hasta llenar el molde.
Recuperar la mitad pequeña de masa reservada.
Estirar hasta que tenga el tamaño del molde.
Cubrir el molde con ésta masa, a modo de tapa.
Completar el cerrado y sellado haciendo un trenzado con los bordes que asoman.
Pinchar la masa con un tenedor.
Meter el pastel dentro del horno, mantener la temperatura, 40 minutos aprox.

Engordar.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 15 de Mayo de 2009, 23:01
Tu último paso me inquieta mucho  :llori:

Joé, que últimamente solamente como ensaladitas y pescado (salvo un helado que me zampé...)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 15 de Mayo de 2009, 23:14
Cita de: Peluche en 15 de Mayo de 2009, 23:01
Tu último paso me inquieta mucho  :llori:

Joé, que últimamente solamente como ensaladitas y pescado (salvo un helado que me zampé...)

Ay tú cómo te cuidas!!

Sorry but you are not allowed to view spoiler contents.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Genki en 15 de Mayo de 2009, 23:19
peluche, el mío te lo envié por MP(por si no te diste cuenta xDD)

bueno, pues si es una lección por día, no irá a mal ritmo :P
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Nachowsky en 15 de Mayo de 2009, 23:36
Me lo tomo como "deberes bien hechos", gordito mio :3
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 15 de Mayo de 2009, 23:49
Cita de: [Y]arot~ en 15 de Mayo de 2009, 21:55

Es que siempre he odiado a los que ivan de listos en clase.

Eso es porque tú eres más tonto que una uva.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 16 de Mayo de 2009, 00:00
Se me da fatal fingir que no sé algo que sé.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 16 de Mayo de 2009, 00:59
Cita de: Khram Cuervo Errante en 15 de Mayo de 2009, 23:49
Cita de: [Y]arot~ en 15 de Mayo de 2009, 21:55

Es que siempre he odiado a los que ivan de listos en clase.

Eso es porque tú eres más tonto que una uva.

Mentira.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 16 de Mayo de 2009, 09:05
Joder, y supuestamente era hoy cuando posteabas la primera lección. :lol:


Hacerse un bocata:

-Cortar pan:
   Coger cuchillo adecuado para cortar pan y el pan.
   Cortar el pan longitudinalmente.
   Poner las dos tapas del pan miga arriba en una superficie limpia.
   Soltar el cuchillo.

-Poner ingrediente (ingrediente):
   Coger ingrediente.
   Ponerlo encima del último ingrediente o sobre la tapa de abajo en su defecto.

-Rellenar:
   Para cada ingrediente que se le quiera poner:
       Poner ingrediente(ingrediente)

-Cerrar:
   Poner ingrediente(la otra tapa del pan, miga abajo)


Me ha quedado un poco raruno, creo. ô.o
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: raul_isl en 16 de Mayo de 2009, 17:33
!up
Aunque ya hay tantas cosas ahi arriba que me da hasta noseque. A ver si les hago limpieza.
Lo mio te lo mandare por mp algun dia que tenga tiempo ^^
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: neoprogram en 16 de Mayo de 2009, 18:07
Cita de: risl en 16 de Mayo de 2009, 17:33
!up
Aunque ya hay tantas cosas ahi arriba que me da hasta noseque. A ver si les hago limpieza.
Lo mio te lo mandare por mp algun dia que tenga tiempo ^^

Si tienes muchos cursillos en la sección se podría montar una subsección  ^^:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: raul_isl en 16 de Mayo de 2009, 18:17
Cursillos son solo 2, creo, pero hay demasiados importantes.
Ya he sacado dos que no se estaban actualizando, asi que por el momento arreglado.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 17 de Mayo de 2009, 02:27
Cabrones, me subís el curso y casi no lo encuentro  :lol:

Capítulo 2. Los robots son un invento satánico

La gran mayoría habéis hecho una receta. Y además habéis visto las de los demás. ¿Qué conclusiones sacais? Pues que el lenguaje castellano hace que la misma frase la digamos todos de formas distintas y de forma que para entenderlas hay que tener una cierta subjetividad. Sin ir más lejos en la misma frase podemos decir muchas cosas, y el número de cosas que podemos decir no es un número concreto y dependiente del verbo. Pues bien, en informática SÍ. Un verbo siempre llevará el mismo número de parámetros (esto es mentira, pero no os hablaré de funciones sobrecargadas hasta muuuuuuuuuuuuuy avanzados en el lenguaje). Y lo más importante, es que hay que escribir todos igual.

Por ejemplo para cortar, unos dicen "cortar 2 zanahorias en rodajas" y otros "cortar en rodajas 2 zanahorias" y otros "cortar 50 gramos de zanahoria en finas rodajas"....
Pues bien, en informática cuando se pone un comando (verbo o función), los cuales ya sabéis escribir con su mayúscula inicial y tal, detrás del verbo se ponen paréntesis y entre ellos los parámetros ordenados.

Así, el verbo cortar podría admitir los parámetros "el qué", "cuánto" y "cómo", siendo la cantidad en gramos. De esta forma todos escribiríamos:
Cortar(zanahoria, 50, rodajas);

Como véis, es un lenguaje menos rico que el castellano, pero sí más objetivo, más cuadriculado. Imaginad las grandes ventajas sobre todo para ligar...
Copular(tú, conmigo, ahora, hasta sangrar);

Por cierto, véis que pongo un punto y coma al final. Ese punto y coma es el que informa de que ahí termina ese comando en concreto. Es como si todos cuando terminamos una frase dijésemos "grunt" para saber que terminó, o el stop de los telegramas, o el cambio y corto de los radioaficionados. Grunt.

Por último, y no menos importante, ¿qué sucede si un comando no tiene parámetros? Pues que por decencia, se ponen los parénteis igualmente aunque no vaya nada en medio. Eso es porque a los comandos les mola destacar y que se sepa "hey tíos, mirad, soy un puto comando, ¡¡llevo paréntesis!! Soy más molón que vosotras, sucias variables". Son así de clasistas. (De nuevo, esto es cierto a medias, algunos lenguajes no los necesitan, por ejemplo Pascal).

Y pasemos al ejercicio. El tema es que hay un monje satánico, que tiene un problema muy grave: tiene Parkinson. Y claro, cuando quiere invocar al Diablo y estas cosas, al pintar el pentáculo con la sangre de vírgenes (no veais lo complicada que es de conseguir), le quedan las líneas como el culo, y Satán no se digna aparecer por la mierda de dibujo. Así que consultando en la Gaceta Infernal, en artículos de venta por correo, se pilla unas velas negras, un cuchillo de sacrificios, un grimorio, y el pequeño Robot Secuaz, ¡el mejor robot para misas negras! Consiste en un pequeño robot en el cual se puede cargar un litro de sangre, y programar unas órdenes para que nos joda el parquet pintándolo. El monje abre el libro de instrucciones y encuentra que posee los siguientes comandos:

LimpiarSuelo();   : Limpia el suelo no dejando ni rastro de sangre
GuardarSangre();   : Cierra el conducto del depósito de sangre para que al caminar no pinte el suelo
SacarSangre();   : Reabre el conducto del depósito de sangre para que al caminar vaya pintando
GirarDerecha(angulo);   : Gira a la derecha ese ángulo (especificado en grados)
GirarIzquierda(angulo);  : Como GirarDerecha, pero para el otro lado, garrulos.
Caminar(distancia);    : Camina esa distancia
ActivarRohi();     :   el robot se transforma en un pene
DesactivarRohi();   : el robot abandona su fantástica forma de pene para volver a la normal.
Repetir n veces { .... }  : el robot repite n veces los comandos que vayan dentro, incluyendo los repetir, es decir, se puede meter un Repetir dentro de otro Repetir y así sucesivamente (esto se llama anidar).

Y este último comando es el más peculiar, el repetir. El satánico prueba el robot para pintar un cuadrado de sangre (para las pruebas no usa sangre de virgen). Para las pruebas coloca siempre al robot en el centro del parquet, que es un suelo cuadrado de 500 por 500.

Caminar(100);
GirarDerecha(90);
Caminar(100);
GirarDerecha(90);
Caminar(100);
GirarDerecha(90);
Caminar(100);
GirarDerecha(90);


Sorry but you are not allowed to view spoiler contents.

Claro, es un cuadrado, así que copypastea lo simple.... pero claro, eso sería un coñazo si quiere pintar un dodecágono...

GuardarSangre();
GirarIzquierda(90);
Caminar(150);
GirarDerecha(90);
Caminar(100);
SacarSangre();
Repetir 12 veces {
GirarDerecha(30);
Caminar(100);
}


Sorry but you are not allowed to view spoiler contents.


Fijaos en la importancia del Repetir. Esto en informática se llama bucle. Imaginad que tenéis una base de datos de 5 millones de usuarios que queréis actualizar, y no existen los bucles... ¡Tendríais que escribir el proceso 5 millones de veces!

Pues bien, la prueba de hoy es juguetear con el robo secuaz, y enviarme vuestras creaciones. Pero la verdadera prueba es conseguir programarlo para que dibuje un pentáculo, es decir, un pentágono que contiene una estrella de 5 puntas.

¿Podrá el satánico traer el mal a la Tierra?  *.*

Si sabéis hacerlo sin ayuda de programas, cojonudo. Para los que no sepais, he desarrollado un "simulador" del robot, descargable en este link (es para juindous, pero funciona en Wine):

http://www.megaupload.com/?d=U0ID0G4G

P.D.: Ninguna virgen ha sido maltratatado para la elaboración de este post... todavía.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 17 de Mayo de 2009, 02:36
Esto en la alpha

http://img199.imageshack.us/img199/1652/dibujor.jpg

Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 17 de Mayo de 2009, 02:38
Esa es la versión antigua del robot  :lol:

Prueba la nueva, que tiene bucles y penes.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Canon en 17 de Mayo de 2009, 02:54
Salsa.

Agregar dos y media tasas de agua en una olla
Calentar olla a nivel alto de calor (tiempo máximo 5 min, tiempo minimo 3 min)
Cortar champiñones en rodajas
Cortar 7 gr de cebolla de huevo en cubos pequeños
Cortar 8 gr de cebolla de rama en cilindros pequeños
Revolver 2gr de pimienta con 2gr de sal, ---> sazón
Bajar  el nivel del calor a bajo.
Agregar a la olla ( cebolla en cubos pequeños,  cebolla en cilindros pequeños,champiñones en rodajas, dos cucharadas de harina,sazón,media copa de vino tinto)
Dejar 19 min
Bajar nivel de calor a cero

Se acepta cualquier critica tanto de pelu como de los dos sobrados >_>

PD2: Ya estoy leyendo lo de arriba.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Umi en 17 de Mayo de 2009, 03:33
Lo conseeeguiiiiii :D se lo mando al profe y si me da permiso os lo pongo *O*

Me siento muy filis ^^
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 17 de Mayo de 2009, 03:53
(http://img41.imageshack.us/img41/9128/penesatanico.png)

Hala, ésto supongo que debe ser el resultado. No se puede ver (al subirlo debió pasar por un servidor londinense y pilló algo de niebla, si Pelu me deja la quito), pero al final hace una vueltecita de alegría el pene. :106:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: MiGUi en 17 de Mayo de 2009, 03:59
1. Paste this code into RoboSecuaz.
Sorry but you are not allowed to view spoiler contents.


2. Shit bricks.
3. Profit.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Canon en 17 de Mayo de 2009, 04:34
(http://img268.imageshack.us/img268/9767/estrella.jpg)



Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Canon en 17 de Mayo de 2009, 04:35
Que porque lo hice en un circulo? Por que mola más.  :lol:

Me voy a tomar después si quieres pelu pongo la otra verción
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 17 de Mayo de 2009, 05:47
Si lo haces del tamaño del pentaculo de fae, entonces te alabaré.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 17 de Mayo de 2009, 08:07
canon eso es una estrella de david, no un pentáculo...

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 17 de Mayo de 2009, 10:44
CitarActivarRohi();     :   el robot se transforma en un pene
DesactivarRohi();   : el robot abandona su fantástica forma de pene para volver a la normal.

Hijo de Puta!!!!


Ahora acabo de leer, tenía que decirlo :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 17 de Mayo de 2009, 10:56
Canon como coño has hecho el circulo?
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 17 de Mayo de 2009, 11:26
Repetir 360 veces {
        Caminar(1);
        GirarDerecha(1);
}


Si lo quieres más grande como pedía yarot

Repetir 720 veces {
        Caminar(1);
        GirarDerecha(0.5);
}


(tarda un rato...)

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 17 de Mayo de 2009, 11:28
Por ahora la respuesta de El Brujo es para enmarcarla. No solamente dibujó bien el pentáculo, sino que el cabronazo escribió "EL BRUJO" debajo  :gñe:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 17 de Mayo de 2009, 11:36
Gracias ElBrujo!
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Calabria en 17 de Mayo de 2009, 11:54
Yo voy a mi ritmo, como avisé.
Perritos calientes completos:

Cojer pan de perrito, dos por persona
Partir pan de perrito, longitudinalmente

Cojer cazo
Echar aceite en cazo
Calentar cazo con aceite
Coger cebolla, al gusto
Echar cebolla en cazo con aceite
Calentar cebolla, hasta que se dore

Cojer tomate frito, abundante
Cojer salchichas, dos por persona
Echar tomate frito y salchichas en cazo con cebolla y aceite
Calentar cazo con salchichas y salsa, hasta que se hagan las salchichas

Cojer sartén
Echar aceite en sartén
Calentar sartén con aceite
Coger huevos, uno por persona
Abrir huevos
Echar contenido del huevo en sartén con aceite
Calentar huevos, hasta que se cuajen, removiendo

Coger salchichas, salsa, huevos revueltos
Echar salchichas, salsa, huevo revuelto en pan de perrito, salchichas una por pan, el resto al gusto
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 17 de Mayo de 2009, 12:07
Cita de: Peluche en 17 de Mayo de 2009, 11:28
Por ahora la respuesta de El Brujo es para enmarcarla. No solamente dibujó bien el pentáculo, sino que el cabronazo escribió "EL BRUJO" debajo  :gñe:
Es que la firma es sagrada... xD

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 17 de Mayo de 2009, 12:19
Solamente como nota. Las funciones GirarDerecha(), GirarIzquierda() y Caminar() admiten que el parámetro sea un número decimal (utilizando de separador decimal el punto). Lo digo porque por ahora todos usan al menos 2 bucles, uno para dibujar el pentágono y otro para dibujar la estrella, pero con un poco de conocimiento de matemáticas se puede dibujar en un solo bucle, dibujando ambos a la vez.

Las matemáticas necesarias para los cálculos son las siguientes:

- El ángulo interior de un polígono regular de n lados es (n-2)*180/n, por ejemplo para un polígono de 6 lados el ángulo interior es 120.

- Si de un triángulo rectángulo tienes la hipotenusa y un ángulo que no es el recto, el cateto opuesto a ese ángulo es hipotenusa*seno(ángulo) y el cateto contiguo es hipotenusa*coseno(ángulo)

Además hay que tener en cuenta que media circunferencia son 180 grados, así que en el caso del polígono de 6 lados, si acabas de pintar uno, la cantidad de grados a girar no es 120, sino 180-120 = 60.

Las matemáticas junto con la física son la base de los juegos de ordenador. En realidad cuando los juegos nacieron, lo hicieron de la mano de la física. El primer juego fue el Pong, es decir, dos raquetas y una pelotita, pero la pelotita tenía que rebotar por ahí, y para eso hay que usar trigonometría. El Tetrix sin ir más lejos tiene que girar sus piezas, y eso es una rotación.  El Mario Bros, cuando mario salta hay que calcular la parábola con la que se desplaza en el salto, y cuando dispara, su disparo tendrá un vector dirección y velocidad. Los juegos de coches son todavía mucho más complejos, y usan físicas más avanzadas.

En las lecciones intentaré meter matemáticas y física "poquito a poquito". Hoy ha tocado trigonometría, pero se irán tocando más cosas.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 17 de Mayo de 2009, 12:31
Mierda Mierda y más Mierda... Me estaba currando un mega cimbrel con piercing y todo incluído, me ha aparecido un mensaje que faltaba memoria o no sé qué... Ya me había pasado antes y lo que he hecho ha sido copiar todo el codigo al bog y reiniciar el programa. El caso es que he hecho un Epic Fail y solo he copiado la mitad del codigo, así que a la mierda xD ARFFFF 1 hora y pico de curro para nada xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 17 de Mayo de 2009, 12:34
Coño, el programita es de apoyo, no pensaríais que iba a funcionar bien a la primera  :gñe:

La verdad es que el problema es la pausa que le metí para que se viese como pinta, que se me pasó recordarle que procesara el resto de eventos mientras tanto.

Lo de que se te vaya de memoria, me puede sonar a Repeats enlazados con muchas vueltas de bucle, o yo qué sé.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Rohi en 17 de Mayo de 2009, 12:38
Si eso me da igual, lo que me jode es ser tan burro de no copiar todo el código... Me estaba costando bastante xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Genki en 17 de Mayo de 2009, 14:31
Sorry but you are not allowed to view spoiler contents.


Bueno, no quedó mal del todo ^^ :P
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 17 de Mayo de 2009, 16:58
Aquí, el mío:

(http://i203.photobucket.com/albums/aa21/KCEO/Pentculo.jpg)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 17 de Mayo de 2009, 19:29
Qué bien te ha salido Khram.

A mi es que el parqué se me queda pequeño.

Sorry but you are not allowed to view spoiler contents.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 17 de Mayo de 2009, 20:00
xDDD

a mi me ha salido chulo con el pentagono.

Peluche ya me dices si puedo mejorar algo.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 17 de Mayo de 2009, 20:04
Cita de: [Y]arot~ en 17 de Mayo de 2009, 19:29
Qué bien te ha salido Khram.

A mi es que el parqué se me queda pequeño.

Sorry but you are not allowed to view spoiler contents.


Tengo una pregunta:

UgRguIZ0dR8

Sorry but you are not allowed to view spoiler contents.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 17 de Mayo de 2009, 21:08
Bueno, pues ya lo he hecho.

Sorry but you are not allowed to view spoiler contents.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Aliena en 17 de Mayo de 2009, 21:11
El Fail no lo has centrado bien :O
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 17 de Mayo de 2009, 21:14
Cita de: Aliena en 17 de Mayo de 2009, 21:11
El Fail no lo has centrado bien :O

Ni interés que tengo: Si lo hiciera, no sería un FAIL.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 17 de Mayo de 2009, 21:24
Venga va, pues pongo yo también una captura del mio

(http://img245.imageshack.us/img245/2158/pentaculo.png)

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 17 de Mayo de 2009, 23:21
 :prey:(http://s3.subirimagenes.com/otros/2554685dibujo.jpg)

Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 18 de Mayo de 2009, 10:40
3. La verdad, la mentira, el yogur griego y YoYo jugando a la xbox

En la primera lección aprendíamos lo importante que es saber dividir un problema en subproblemas más pequeñitos, y de esta forma se definía un algoritmo como una lista finita, ordenada y definida de pasos para llegar a la resolución de un problema.

En la segunda lección veíamos la importancia de la unificación del lenguaje, el uso de comandos e introducíamos una estructura preciosa y útil que es el "Repetir". Algunos de los que han solucionado el problema incluso han dibujado un círculo, llegando a utilizar un "Repetir 720 veces". En ese caso si la estructura Repetir no existiese, habría que repetir las instrucciones 720 veces, vamos, un coñazo.

Pues llegados a este punto conocemos dos estructuras: la secuencia (los comandos se ejecutan uno detrás de otro) y el bucle (una secuencia se repite). Pero nos falta algo, está claro que con esto no nos vale. Por ejemplo, en el robot satánico queremos que sepa pintar tanto un pentáculo como una estrella de David, y que nos pregunte al principio qué queremos que pinte, no podríamos porque no hemos visto nada que nos permita decir "si tal cosa se cumple haz esto y si no haz esto otro".

A esa cosa que se tiene que cumplir se le llama condición, y debe cumplir una premisa importantísima, que es que una condición solamente puede tomar dos valores: o es cierto o es falso. Un ordenador no tiene moral ni ética ni nada por el estilo, si un ordenador es padre y su hija de 16 años llega dándo tumbos a las 7 de la mañana de un sábado, el ordenador le preguntará "Amparo, ¿vienes borracha?" y la hija le podría contestar "bueno padre, si es que mis amigas bla bla bla..." y el ordenador (padre amantísimo) le contestará "A mí me la pelan tus amigas ¿vienes borracha sí o no?". Vaya, ahora que lo pienso, tampoco se aleja demasiado del comportamiento de un padre humano.

Así podríamos definir lo que se llama una condicional:
Si (condición) entonces {...} [y si no {...}];

Los corchetes significan que esa parte es opcional, es decir, podemos decir "Si se cumple la condición haz esto, pero si no se cumple sigue normalmente" o podemos decir "Si se cumple la condición haz esto y si no se cumple haz esto otro".

Para verlo con el ejemplo del padre ordenador y la hija dando tumbos, el código sería:
Si (hija dice estar borracha) entonces { castigar 1 semana por borracha }
si no { castigar 2 semanas por borracha y mentirosa};


¿Las condiciones solamente se utilizan en las condicionales? La respuesta es: no. También se usan en los bucles. ¿Recordáis el bucle Repetir n veces? Pues solamente nos vale para repetir algo un número finito de veces predefinido. Pero, ¿y si no sabemos cuántas veces se tiene que repetir?. Imaginad que YoYo está jugando con unos amigos a la Xbox a un juego de lucha. El avanzado método de pelea que utiliza YoYo consiste en una antigua técnica aprendida de un monje shaolin y perfeccionada a base de sangre y sudor: "mueve el mando y pulsa todos los botones al azar". De partida, ¿cuántas veces tendrá que pulsar YoYo los botones? Pues ni puta idea, porque no sabemos cuántos golpes esquivará el contrincante ni cuántos hacen falta para tumbarle, ni cuantos acertará YoYo... así que no nos vale un "Repetir n veces", sino que el bucle sería:
Mientras (estés jugando) haz
  {
    MoverMando();
    PulsarTodoALaVez();
    EmitirGruñidos();
  }


Ahí lo tenéis, un bucle basado en una condición:
Mientras (condición) haz {...};
En este caso el programa entraría, comprobaría la condición del bucle, si se cumple entra en el bucle y lo repite mientras se cumpla y cuando deja de cumplirse sale. Este tipo de bucle tiene una característica: si la condición no se cumple desde el principio, el contenido del bucle jamás se realiza. Pero podemos tener situaciones dónde queramos que el contenido se ejecute al menos una vez, y para eso existe otro tipo de bucle:
haz { ... } Mientras (estés jugando);

Volvamos a lo de YoYo y supongamos que su contrincante es un cheto (un tío que hace trampas) y que conoce una combinación mágica de botones para vencer al contrincante. En este caso, con el bucle de juego que definimos antes, YoYo jamás pulsaría las teclas porque perdería desde el principio. Pero todos sabemos que YoYo mueve el mando, pulsa las teclas y emite quejidos al menos una vez por partida (incluso cuando no está jugando), con lo cual el código quedaría:
haz
  {
    MoverMando();
    PulsarTodoALaVez();
    EmitirGruñidos();
  } Mientras (estés jugando)


Y estas son todas las estructuras de código que existen en programación estructurada:
- Secuencia
- Condicional
- Bucle

Os pongo un gráfico resumen:

(http://img51.imageshack.us/img51/8333/secuencia.jpg)

Y ahora veamos el título de la lección... hemos aprendido sobre la verdad y la mentira (únicos valores que puede tomar una condición) y sobre YoYo jugando a una xbox. ¿Pero qué cojones es el yogur griego? Pues atentos que ahí vamos.

Hace muchos, muchos años, existía una polis griega llamada Orcómeno dónde desarrollaron una receta para hacer el yogur más rico del mundo conocido. Se pusieron manos a la obra y consiguieron realizar 4000 unidades de yogur pagadas con dinero ciudadano y destinadas al comercio y a ser distribuidas entre ciertos sectores ciudadanos. ¡Se iban a hacer ricos! Pero he aquí que comenzaron los problemas, ¿con quién se comerciaría? ¿a qué precio? ¿a quién le corresponderían unidades gratis? Y se hizo una reunión, a la que invitaron a los más prestigiosos pensadores de la zona, tales como Proctágoras de Culeto. La reunión era presidida por el honorable Erginos moderando el debate, que era emitido en directo por la 2. El acta de reunión fue la siguiente:
- Yo con los pijos de Tebas no pienso comerciar. ¡Que se hagan su propio yogur y así revienten de cagalera! Bueno no... si me lo pagan a 100 dracmas entonces sí que les vendo algo y escupo al suelo.
- Pues si con los de Tebas comerciamos a ese precio, ¿con Megara qué hacemos? Porque fijo que si les vendemos yogures, se los revenderán a los de Tebas
- Pues a los de Megara se lo vendemos a 5 dracmas la unidad, y que se jodan, es un precio caro... pero tampoco nos vamos a tirar de la moto.
- ¿Y aquí en la península? ¿Lo vamos a vender a todos igual?
- A mí los de Heraia me caen bien, yo se lo vendería a 1 dracma.
- Los de Messena son tontos del haba, con esos podemos hacer negocio, se lo vendemos a 4 dracmas y fijo que pican
- Y a los espartanos a 2... ¡AHÚ!
- Ok, anotado, y al resto de polis de la península se lo vendemos a 3, lo cual incluye a Elis, Olimpia, Corinto, Sición, Megalípolis...
- Vale, y a los de fuera de la península a 4 dracmas, menos a Megara que ya dijimos que a 5 y a Tebas que no les vamos a vender nada.
- Vayamos con las unidades que se regalarán a los ciudadanos de Orcómeno... vamos a regalar 1000 unidades, pero claro, hay mucho ciudadano.
- Está claro que hay que repartirlo por igual a hombres, mujeres, niños...
- No, a los menores de 10 años no, ni a los mayores de 50, porque les puede causar malestar estomacal.
- Y a las mujeres... bueno, siempre y cuando estén casadas con un ciudadano de Orcómeno que merezca un yogur.
- ¿Los hombres? Pues aquellos que al menos un padre sea de Orcómeno, si son hijos de extranjeros nada.
- Bueno, y a los ciudadanos de Orcómeno que no se les regale, siempre lo pueden comprar a un dracma.
- Joder, la que hemos liado... ¿y ahora cómo sabemos el precio y a quién se regala?

Porctágoras tomó notas de la reunión en un papiro, y anotó mentalmente que había que utilizar la lógica proposicional. Sabíamos que una condición puede ser cierta o falsa. Y las condiciones es lo que los filósofos llaman proposiciones, y las proposiciones pueden estar compuestas a su vez por otras proposiciones unidas por conectores. Existen varios conectores, el primero de ellos es unario, es decir, que afecta tan solo a una proposición, y se llama la negación (NOT): negar cierto implica falso y negar falso implica cierto. El segundo de ellos es binario, afecta a dos proposición, y es la conjunción (AND): la conjunción de dos predicados es cierta cuando ambos predicados son ciertos. El tercero de ellos es la disyunción (OR): la disyunción de dos predicados es cierta cuando al menos uno de ellos es cierto.

(http://img40.imageshack.us/img40/290/tablasverdad.jpg)

Estas operaciones y unos buenos paréntesis nos permiten componer cualquier condicional necesaria para un bucle o para un if. En ocasiones como la del problema del yogur griego el if es anidado, es decir, tendremos combinaciones como "Si (es ciudadano de tebas) entonces { } si no si (es ciudadano de Megara) entonces {   }  si no si es ....".

Pues he aquí los deberes. En nuestro programa nos entra un ciudadano, del cual sabemos los siguientes datos:
- ciudad
- sexo (hombre o mujer)
- edad
- ciudadPadre
- ciudadMadre
- ciudadCónyuge

Del ciudadano queremos saber lo que le vamos a cobrar por el yogur, que será el dato "precio". El Precio será el único dato asignable, y el operador para asignar es el igual (=), por ejemplo "precio = 10".
Para las comparaciones podemos usar los comparadores matemáticos, es decir: igual (==), distinto (!=), menor que (<), mayor que (>), menor o igual que (<=) y mayor o igual que (>=). Pero con una cosa especial sobre el signo igual: si es un solo igual es asignación de valor y si son dos iguales es una comparación, es decir:
precio = 15 <==== esto significa que el nuevo valor de precio será 15
precio == 15 <==== esta es una comparativa que nos devuelve Cierto o Falso indicando si el precio vale 15.

Además contamos con una función que dada una ciudad nos dice si es de la Península o de fuera: EsPeninsular(ciudad), que devuelve cierto o falso. Y por último el operador NOT es la exclamación (!) de forma que !EsPeninsular(ciudad) nos devuelve cierto cuando la ciudad no es peninsular.

Una nota sobre los paréntesis: hay que tener cuidado con ellos y mucho ojito.

Entonces tendríamos cosas similares a esta:
Si ((ciudad == Tebas) AND (edad >= 10) AND (sexo = mujer)) entonces { precio=7; }
si no Si (!EsPeninsular(ciudad) AND (ciudad != Megara)) entonces { precio = 4; }
si no Si (((edad < 10) OR (sexo = hombre)) AND (ciudad == Orcómeno)) entonces {precio = 0; };


Esto es solo un ejemplo que no tiene sentido con los datos del problema. Y aquí vienen los deberes: construir el programita que a partir de los datos de entrada de un ciudadano cualquiera nos diga el precio que debemos cobrarle, teniendo en cuenta que cobrar 0 es regalar.

Suerte majetes.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 18 de Mayo de 2009, 13:54
Me mola cómo explicas
Cita de: Peluche en 18 de Mayo de 2009, 10:40
precio == 10 <==== esta es una comparativa que nos devuelve Cierto o Falso indicando si el precio vale 15.
Por qué en este caso no sería que nos devuelve Cierto o Falso indicando si el precio vale 10?

EDIT: y por qué en los Si usas () y en los entonces {}? Porque el lenguaje es así, para diferenciarlos o...

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 18 de Mayo de 2009, 14:06
Cita de: El Brujo en 18 de Mayo de 2009, 13:54
Me mola cómo explicas
Cita de: Peluche en 18 de Mayo de 2009, 10:40
precio == 10 <==== esta es una comparativa que nos devuelve Cierto o Falso indicando si el precio vale 15.
Por qué en este caso no sería que nos devuelve Cierto o Falso indicando si el precio vale 10?

EDIT: y por qué en los Si usas () y en los entonces {}? Porque el lenguaje es así, para diferenciarlos o...

El Brujo

Porque me equivoqué :D
Fixed.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 18 de Mayo de 2009, 14:28
y lo de los corchetes? Y otra duda.Los ciudadanos a los que se les puede regalar pueden ser de cualquier ciudad o sólo de la península? Alguien de Tebas podría llegar a llevárselo gratis?

El Brujo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 18 de Mayo de 2009, 16:53
Cita de: El Brujo en 18 de Mayo de 2009, 14:28
y lo de los corchetes? Y otra duda.Los ciudadanos a los que se les puede regalar pueden ser de cualquier ciudad o sólo de la península? Alguien de Tebas podría llegar a llevárselo gratis?

El Brujo

Solamente habitantes de Orcómeno.

Lo de los corchetes significa que la segunda parte de un es opcional. Es decir, tu puedes decir "Si llueve me quedo en casa y si no salgo de juerga" y tiene las dos partes, lo que haces en un caso y en el otro, pero también hay situaciones dónde solamente te interesa lo que sucede si se cumple la condición, un ejemplo: "Si gana españa en la eurovisión me depilo los huevos me la pinto del joker y subo la foto al foro".
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: YoYo en 18 de Mayo de 2009, 17:03
Me tienes rencor porque os gané a todos con Sakura
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 18 de Mayo de 2009, 17:22
Cita de: Peluche en 18 de Mayo de 2009, 16:53
Cita de: El Brujo en 18 de Mayo de 2009, 14:28
y lo de los corchetes? Y otra duda.Los ciudadanos a los que se les puede regalar pueden ser de cualquier ciudad o sólo de la península? Alguien de Tebas podría llegar a llevárselo gratis?

El Brujo

Solamente habitantes de Orcómeno.

Lo de los corchetes significa que la segunda parte de un es opcional. Es decir, tu puedes decir "Si llueve me quedo en casa y si no salgo de juerga" y tiene las dos partes, lo que haces en un caso y en el otro, pero también hay situaciones dónde solamente te interesa lo que sucede si se cumple la condición, un ejemplo: "Si gana españa en la eurovisión me depilo los huevos me la pinto del joker y subo la foto al foro".

La madre que me parió... Había hecho todo pensando que podrían ser de cualquier ciudad -.-'. En fin, ahora te lo envío
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 18 de Mayo de 2009, 19:06
Bien bien bien, ya me he hecho la picha un lió.

Peluche puedes poner un ejemplo con el NOT que soy bastante cortito?
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 18 de Mayo de 2009, 19:14
Cita de: ElCoCo en 18 de Mayo de 2009, 19:06
Bien bien bien, ya me he hecho la picha un lió.

Peluche puedes poner un ejemplo con el NOT que soy bastante cortito?
Si te sirvo yo...
Imaginamos que viene un tío de fuera de la península a por un yogur y a los de fuera se los vendemos a 10. Habría que hacer

Si (!EsPeninsular(ciudad)) entonces {precio = 10}

Esto lo que hace es comprobar si NO es peninsular y como es cierto (true) que NO es peninsular se da el resultado que es que el precio va a ser 10.

Si a los de la península se los vendemos a 1 todo junto quedaría así:

Si (!EsPeninsular(ciudad)) entonces {precio = 10}
si no Si (EsPeninsular(ciudad)) entonces {precio = 1}

esto primer comprueba si no es peninsular y si resulta que no es no peninsular (vamos, que sí que es de la península) pasa a la siguiente línea que comprueba si es peninsular y como sí lo es, le da un precio de 1
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 18 de Mayo de 2009, 20:34
Bueno a ver que ya he acabado la clase y ya puedo hacer esto tranquilamente.


Yo empiezo asi

"Miro a ver la edad por si se le puede regalar el yogur y pregunto si tienes <10 o >50 y vives en orconemo entonces es 1 chapa"

si ((edad<10) or (edad>50) AND (Ciudad=Orcónemo)) entonces {precio=1}


Ahora que tendría que preguntar todas las posibilidades que podría haber en ciudadanos? o hay alguna forma mas rápida (he pensado con el bucle [repetir] pero no se me ocurre nada).

Y ahora lo que yo no entiendo es el "==" para que sirve si (ya se que compara precios pero no le veo la utilidad, ya que los precios le pones tu es tanto por cojones y ya.)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 18 de Mayo de 2009, 20:44
Cita de: ElCoCo en 18 de Mayo de 2009, 20:34
Bueno a ver que ya he acabado la clase y ya puedo hacer esto tranquilamente.


Yo empiezo asi

"Miro a ver la edad por si se le puede regalar el yogur y pregunto si tienes <10 o >50 y vives en orconemo entonces es 1 chapa"

si ((edad<10) or (edad>50) AND (Ciudad=Orcónemo)) entonces {precio=1}


Ahora que tendría que preguntar todas las posibilidades que podría haber en ciudadanos? o hay alguna forma mas rápida (he pensado con el bucle [repetir] pero no se me ocurre nada).

Y ahora lo que yo no entiendo es el "==" para que sirve si (ya se que compara precios pero no le veo la utilidad, ya que los precios le pones tu es tanto por cojones y ya.)


Tanto como más rápida... Los "Si" son anidables, es decir, sabes que para Orcómeno hay un tratamiento especial, asi que puedes comenzar con:

Si ( ciudad == Orcómeno ) entonces { ... } si no { ... }


(por cierto, en tu condición has puesto (ciudad=Orcómeno) cuando el = solo es una asignación no una comparación).

Ahora dentro de las primeras llaves sabemos que la ciudad es Orcómeno, con lo cual esa variable solamente se copararía una vez para lo de dentro, ganando en velocidad. Y dentro podríamos comenzar a escribir....

Si ( ciudad == Orcómeno ) entonces
    {
        Si ((edad<10) OR (edad>50))
        {
          precio = 1;
        }
        si no
        {
          ...
        }
     }
     si no
    {
      ...
    }



Pero iré más allá. Para Orcómeno hay más condiciones que implican un precio igual a uno, solamente es ir pensando poco a poco.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 18 de Mayo de 2009, 20:48
uff...

Demasiada información  xDDD

Voy a ver como me sale y te mando, igual pregunto mas cosas que no me entran.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 18 de Mayo de 2009, 20:53
Si me deja peluche, te digo el método que he seguido yo
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 18 de Mayo de 2009, 21:57
Cita de: Brujo en 18 de Mayo de 2009, 20:53
Si me deja peluche, te digo el método que he seguido yo

Coño claro, como si en clase no se ayudasen los compañeros. Se aprende más de los compañeros que del profesor.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 18 de Mayo de 2009, 22:16
Pues yo en lugar de ir por hombre o mujer he ido por ciudades.
Si es de tal ciudad-> precio
Otra ciudad -> otro precio
Y luego cuando además de esa ciudad tienes condiciones de edad y tal pues
Si es de tal ciudad AND >10 AND hombre... -> tal precio

A mí me ha parecido la solución más fácil de plantear
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 19 de Mayo de 2009, 18:02
Enviado a ver que tal esta.

Brujo si que me has quitado dolores de cabeza con tu metodo xD ya me estaba montando un cacao mental que no era normal.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Canon en 20 de Mayo de 2009, 02:26
Bueno ya se que hacer ahora preparo el dolor de cabeza y mando algo.
Como o mejor dicho como puedo dar a entender al programa que ciertas ciudades les voy a dar el valor de una misma variable, osea que yo en el programa haga referencia a "W" y el programa entienda que si el (dato==W)  entonces (dato==Galicia,Madrid,Barcelona)

If ( ciudad== W ) then ( ciudad== Galicia,Madrid,Barcelona );

¿? Asi puedo nombrar a la variable? me imagino que esto lo debo de hacer antes que cualquier proceso eh iria en la primera linea?

Alguno me corrige?
Tengo un problema con Tebas, primero das un condicional para venderles después das una negación para venderles, la condición es 100 dracmas después dices que no vendes así que no se que tomar.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 20 de Mayo de 2009, 03:18
Yo a tebas les he puesto 100.

Y lo de poner ya un dato predefinido creo que no se puede hacer (que me corriga peluche si fallo) yo lo que he hecho para nombrar a los que pertenecian a un grupo
Si (!EsPeninsula) entonces (precio=tal))"(fuera peninsula y mismo precio)"


Yo lo he hecho asi suponiendo que el que lo lea lo haga de arriba abajo y esa orden la pongo al final ya que si no acepta ninguno de los anteriores requisitos quiere decir que el ultimo es el bueno (he puesto abajo del todo las ordenes de "Si ((!EsPeninsula)...".

No se si me explico
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 20 de Mayo de 2009, 09:06
Una cosa antes que nada. Ya he recibido respuestas, y son más o menos correctas. El enunciado llevaba un fallo (el del precio de Tebas) que hizo que cambiase su precio a 100 dracmas dado que no hay forma de indicar que el precio sea "a ti no te vendo na". Aparte llevaba una incongruencia metida a protósito y con maldad: si una mujer de Orcómeno recibe un yogur gratis cuando su marido merece un yogur gratis, ¿podemos con los datos que tenemos asegurar cuándo una mujer merece un yogur? La respuesta es NO, porque para que el marido merezca el yogur gratis tendría que ser de Orcómeno (que se puede presuponer porque salvo que estén separados supongo que dormirán juntos, por eso de la cópula y tal...) y alguno de sus padres tendría que ser de Orcómeno, pero no hay dato que nos indique si marido es descendiente de alguien de Orcómeno, tenemos los datos de los padres de la mujer. Algunos, como Faerindel, lo han visto rápido y se han inventado una subfunción que diría el precio al que compra los yogures el marido, y si es 0 es que es gratis. Como solución admitía o bien no programar la parte de la mujer por considerar imposible por no haber datos, o bien una solución creativa como la de Faerindel. Sin embargo dar por hecho que el marido merece un yogur, o contrastar los padres de ella, es la solución que considero errónea. ¿Por qué puse esta situación? Cuando haces especificaciones con un cliente, estas especificaciones son las que se firman y pagan, y se deben cumplir al dedillo, y si alguna es incongruente no se puede dar una solución que es errónea, sino abrir lo que se llama un CR (Change Request) para hacer una posible solución (bien sea no programar esa parte o bien sea inventar una solución). Jamás se debe programar una solución errónea con respecto a lo que plantea el problema.

Cita de: canon en 20 de Mayo de 2009, 02:26
Como o mejor dicho como puedo dar a entender al programa que ciertas ciudades les voy a dar el valor de una misma variable, osea que yo en el programa haga referencia a "W" y el programa entienda que si el (dato==W)  entonces (dato==Galicia,Madrid,Barcelona)

If ( ciudad== W ) then ( ciudad== Galicia,Madrid,Barcelona );

Jundiox, vaya lío. El operador '==' es el de igualdad, lo que hace es "mira lo de la izquierda, mira lo de la derecha, si son iguales devuelve Cierto y si son distintos devuelve falso". El operador '=' es el de asignación, lo que hace es "mira lo de la derecha y lo pone en lo de la izquierda". De esta forma tu trozo de código está diciendo "Si la ciudad es igual a 'W' entonces mira si la ciudad es 'Galicia,Madrid,Barcelona'". Sabemos que ninguna ciudad se llama 'W' con lo cual el primer trozo nunca se cumpliría y no entraría en la segunda parte. Pero si hubiese alguna ciudad llamada 'W', no podría valer 'Galicia,Madrid,Barcelona' de la misma forma que si te llamas 'Juan' a la vez no puedes llamarte 'Honorato' (y vale, que puedes llamarte 'Juan Honorato Rodríguez de Medinaceli-Fuenrabina', pero en informática 'Juan' no es lo mismo que 'Juan Honorato').

Sí podrías hacer que si la ciudad se llama 'Galicia', 'Madrid' o 'Barcelona', ciudad pase a llamarse 'W'. Lo primero es comprobar si la ciudad se llama 'Galicia', 'Madrid' o 'Barcelona', y sabemos que el operador '==' nos compara una a una, y que el operador OR vale Cierto si alguno de los dos operandos es cierto, con lo cual la primera parte quedaría:

Si ((ciudad == Galicia) OR (ciudad == Madrid) OR (ciudad == Barcelona)) entonces {...}

Eso comprueba si la ciudad se llama alguno de los tres nombres, en cuyo caso hace lo que manden los puntos suspensivos. ¿Qué poner? El operador de asignación era el '=' a secas, entonces quedaría:

Si ((ciudad == Galicia) OR (ciudad == Madrid) OR (ciudad == Barcelona)) entonces { ciudad = W }

Si la ciudad vale Galicia, Madrid o Barcelona, entonces la ciudad pasaría a valer W. Ojo, eso significa que ya no sería su anterior valor.




Cita de: canon en 20 de Mayo de 2009, 02:26
Tengo un problema con Tebas, primero das un condicional para venderles después das una negación para venderles, la condición es 100 dracmas después dices que no vendes así que no se que tomar.

En un principio quería que a Tebas no se pudise vender. Pero con lo que hemos visto eso no se podría hacer, dado que precio tiene que tomar algún valor, el que sea. Por eso puse el valor de 100, que es un valor exagerado para un yogur, vamos, lo equivalente a "no te vendo pero te pongo un precio simbólico que sé que no pagarás... y si me lo pagas, me dará igual que seas un cabrón al que odio, porque la pela es la pela".


Aprovecho para poner lo que sería la solución del Robo Secuaz, de una forma analítica. Lo primero de todo es conocer los ángulos con los que se está jugando, y analizar la figura. Lo mejor es pintarla en una libreta y hacerlos cálculos. Sí, la libreta es la mejor herramienta de un analista o programador, el ordenador es secundario.

(http://img40.imageshack.us/img40/1875/pentaculo.jpg)

El primer ángulo a conocer es el interior de un pentágono, que por la fórmula de ángulos interiores de polígonos regulares, sabemos que es 108 (ángulo a). Al principio llevaremos al robot a la parte de abajo, y quedará mirando hacia abajo, así que hay que calcular el ángulo que tendría que girar para que se quedase paralelo a uno de los lados del pentáculo. Este es el ángulo b, y se corresponde con girar los 180 grados menos la mitad del ángulo a, con lo cual se queda en 126 grados. En este momento tendríamos el robot orientado perfectamente para comenzar a pintar. Vemos que hay 5 diagonales interiores, igual que hay 5 lados exteriores, así que sin pensar mucho sabemos que se puede pintar un lado y una diagonal de una tirada y hacer esto 5 veces para obtener la figura entera. Para eso primero decidimos una longitud del lado del pentágo (por ejemplo 250) y calcular cual sería la longitud de la diagonal, para lo cual calculamos el ángulo d y con el coseno calculamos la mitad de la diagonal. Si de lado escogimos 250, entonces la diagonal medirá 2.B = 2.250.cos(36) = 404,508. Por último, si acabamos de pintar un lado del pentáculo, el ángulo a girar para colocarnos para pintar una diagonal es el e, que vale 108 también. Ahora ya podemos hacer el algoritmo:

GuardarSangre();
GirarDerecha(90);
Caminar(220);
GirarDerecha(126);
SacarSangre();
Repetir 5 veces {
  Caminar(250);
  GirarDerecha(108);
  Caminar(404.51);
  GirarDerecha(108);
}
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 21 de Mayo de 2009, 10:52
Bueno ahora yo planteo una duda que parecera una gilipollez pero yo no la veo asi.

Yo no acabe secundaria, acabe asqueado del colegio de los curas y aparte soy un perro de aquí a la china popular y es por eso que no he dado el coseno y ahora que lo veo en una de las formulas de la estrella de 5 puntas pues quiero ver que es eso del coseno. Alguien se ofrece para explicarme como se calcula? o algun sitio donde lo explique decentemente.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 21 de Mayo de 2009, 10:54
http://es.wikipedia.org/wiki/Trigonometria
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 21 de Mayo de 2009, 11:36
Bueno ElCoCo, intentaré explicártelo, aunque te han puesto el link a la Wiki. Como en la Wiki ya lo explican en plan chungo, yo voy a hacerlo con billar, que creo que se entenderá mejor.
Mira esta mesa de billar:

(http://img194.imageshack.us/img194/778/billark.jpg)

Las líneas rojas largas que se cruzan en el medio son lo que se llaman "ejes de coordenadas". La mesa de billar es un plano, y en él el punto medio será el punto de origen, es decir, el centro. Son "ejes" porque son 2 (al estar en 2 dimensiones). El horizontal se define como eje X, y el vertical como eje Y, comunmente. Al punto de origen le llamaremos (0,0) y cualquier otro punto será (x,y), dónde x es la distancia que hay en horizontal al punto de origen e y la distancia que hay en vertical. ¿Ves la flecha azul? Eso es un vector. Va del punto central (0,0) al punto que queremos (x,y). La longitud que tiene esa flecha es la distancia que hay del centro a la bola en línea recta. Ahí es dónde jugaría la trigonometría, que como es un triángulo rectángulo entonces el cuadrado de la hipotenusa es igual a la suma de los cuadrados de los catetos, con lo cual la longitud del vector (a la cual llamaremos módulo a partir de ahora) se puede calcular como raíz cuadrada de x al cuadrado más y al cuadrado.

Ahora bien, a partir de los catetos hemos determinado la longitud del vector. Ahora supón que pasa lo contrario, que te dan la longitud del vector y el ángulo que tiene con respecto al eje x positivo.... ¿Cómo calculas x e y? Ahí es dónde entran en juego el seno y el coseno. El seno y el coseno de un ángulo son los valores de los catetos si la distancia es 1. Para entenderlo:

(http://img29.imageshack.us/img29/9175/circulito.jpg)

Si la distancia de la bola al centro es 1, el coseno del ángulo sería la x, y el seno la y. ¿Y si la distancia de la bola al centro no es 1? Pues entonces solamente hay que multipicar el seno o el coseno por la consiguiente longitud.

¿Son útiles? Pues volvamos al símil del billar. Cuando en el billar apuntas, cada vez te colocas de una forma diferente y le das a la bola de una forma diferente, y mentalmente aunque no te lo creas haces unos cálculos cojonudos de "si le doy así y rebota allí entonces viene para este otro lado, le da y entra". Además haces un cálculo mental de "le tengo que dar con tanta fuerza porque si no meto la blanca, y si le doy más despacito no entra". Vamos, unos logros titánicos. Si hicieses eso mismo en un programa tendrías que saber todo esto:
- La posiciones de las bolas, en sus correspondientes coordenadas (x,y).
- El ángulo con el que se coloca el palo para golpear a la bola blanca.
- La fuerza con la que se va a dar.

Eso aparte de muchas cosas (dimensiones de los tapetes, rozamiento, lugar dónde se da a la blanca para calcular el efecto....). Cuando simulases que se golpea a la blanca (supongamos en el centro para que no tenga efecto) significaría que la blanca pasaría a moverse con una velocidad en la dirección en la que iba el palo, y para todos esos cálculos venga a usar seno y coseno para ver dónde vas a pintar la vola en el siguiente paso.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 21 de Mayo de 2009, 14:05
Bueno una cosa menos xD

Ahora me comprare cuadernillos rubio para la caligrafía y solo me quedara no hablar en plan gangoso xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Blood en 26 de Mayo de 2009, 16:58
Hola, me gustaría apuntarme (ahora que no va muy avanzado jeje).

La pregunta sería, mando las tareas anteriores antes de ponerme con esta última, o (ya me he leído más o menos las anteriores) comienzo por la última.

Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 26 de Mayo de 2009, 20:25
Cita de: Blood en 26 de Mayo de 2009, 16:58
Hola, me gustaría apuntarme (ahora que no va muy avanzado jeje).

La pregunta sería, mando las tareas anteriores antes de ponerme con esta última, o (ya me he leído más o menos las anteriores) comienzo por la última.



Pues el orden no tiene porque importar pero lo lógico seria que empezaras por el principio y acabaras por el final. Te lo digo por que la de la cocina aunque parezca una gilipollez te ayuda con la del ritual satánico y la del mercadillo de de yogures.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 27 de Mayo de 2009, 11:34
4. Dibujando lo que pensamos

Revisemos. Sabéis lo que es un algoritmo, sabéis cómo escribirlo, sabéis los tipos de bucle, sabéis lo que es una condicional. Solamente os falta aprender a "dibujar" los algoritmos, es decir, cuando los ponéis en texto es complicado de ver y analizar, en cambio hay formas de hacer gráficos para representar los algoritmos que hace que sean fáciles de ver. Este tipo de gráficos se llaman Diagramas de Flujo de Datos, o en siglas, DFD.

Para esta lección, que será ardua, larga y dura como el pene de Rohi cuando se transforma en supersayan de nivel 3, vamos a utilizar un software muy pocholo llamado FreeDFD, que os he subido aquí:

http://www.megaupload.com/?d=MUZDOBH2

Y ahora comenzamos.

Inicio y Fin

Todo algoritmo es finito, es decir, que tendrá un número finito de pasos y por tanto un inicio y un final. La representación gráfica para ambos es un circulito, pero en uno pone inicio y en el otro pone fin (originalidad ante todo).

(http://img265.imageshack.us/img265/6899/inicioyfine.jpg)

El programa los pone por defecto, dado que siempre existirán en todo algoritmo.

Asignación

El elemento más importante después del inicio y del fin. Sirve para asignar valores a variables. ¿Qué es una variable? Es una cajita dónde puedo meter valores. Imaginad que tenéis un cajón, y dentro de él podéis meter objetos, pues el cajón sería la variable y lo que metéis dentro es el valor. A lo largo del tiempo los objetos de dentro del cajón pueden ir cambiando, pero el cajón seguirá ahí, amándoos, queriéndoos, soñando con vosotros cada noche esperando a ser rellenados de nuevos y maravillosos objetos. En la lección 3 ya las vimos, cuando dijimos la diferencia entre el operador de comparar (==) y el de asignar (=).

La asignación se representa con un rectángulo en el cual se escriben las asignaciones en el siguiente formato: nombre de variable <- valor nuevo. Por ejemplo, si tenemos una variable x y queremos que valga 5 pondríamos x <- 5. En el mismo rectángulo se pueden asignar valores a varias variables, el programa en cuestión permite asignar hasta 3 de una tacada. Para poner una cajita de asignación basta con pincharla en la barra de herramientas del programa, y pinchar después de que instrucción del programa queremos que la ponga. Para ver las variables y poder asignarlas es hacerle doble click:

(http://img39.imageshack.us/img39/3223/asignacion.jpg)

Veréis que hay 3 variables, y que la primera se le asigna un número pero a las demás no. Creo que es buen momento para contaros lo que son los tipos de variables. ¿Cuál es la raíz cuadrada de Juan? No tiene, porque no es un número. ¿Y la primera letra de 7? No tiene porque no es una palabra, sino un número. En los lenguajes de programación existen diferentes tipos de variables, cada uno tiene la definición de los suyos, pero casi todos poseen los mismos. En este caso tenemos tres tipos de variables:

- Números: valores numéricos
- Lógicos: Cuando el valor es "Verdadero" o "Falso", en este caso se representan como .V. y .F. respectivamente (la letra V o F entre dos puntos). Estos los dimos en el capítulo 3.
- Texto: Valores alfanuméricos, es decir, cualquier cosa que podáis teclear. Para representarlas siempre se ponen entre comillas simples, por eso pone 'Pepe'.


Salida o Escritura

Se llama salida a cualquier cosa que sea salida de un programa: escribir en fichero, en base de datos, sacar por pantalla... En este caso la salida será siempre por pantalla, dado que no es un lenguaje de programación en sí, sino simplemente para diseñar algoritmos. El símbolo es un cucurucho de castañas asadas tumbado. Dentro de él pondremos lo que queremos que salga, separado por comas, como en la asignación ya teníamos variables podemos probar a poner lo siguiente:

'El nombre es ',nombre,' llueve vale ', llueve, ' y x es ',x

Aquí tenéis captura de pantalla de cómo se ve el símbolo y lo que mostraría la salida con las variables asignadas (arriba del todo tenéis un botón de "play" para ejecutar los algoritmos).

(http://img41.imageshack.us/img41/7421/salidac.jpg)

Entrada o lectura

Se corresponde con la entrada de datos desde algún medio, es decir, la asignación de valores de variables desde un medio externo, bien sea un fichero, base de datos, petición a usuario por pantalla... El programa pide los datos al usuario por pantalla.
Al hacer doble click podemos escribir los nombres de variables que queremos solicitar, separados por comas. Supongamos que tras asignar nuestras variables iniciales pedimos "x,nombre" al usuario, entonces le aparecerá una ventana pidiendo el valor de x y luego una ventana pidiendo el valor de nombre. Recordad que los textos hay que meterlos entre comillas simples.

(http://img132.imageshack.us/img132/5273/entradaz.jpg)

Condicional o Decisión (el if de toda la vida)

Es un precioso rombito sirve para contrastar si una condición es verdadera o falsa(de nuevo al capítulo 3 me remito, que en serio era importante), y toma un camino diferente dependiendo de dicha condición. Vamos a ver un programa sencillito:

(http://img36.imageshack.us/img36/3614/condicional.jpg)

El programa pide dos valores llamados x e y, los compara, y decide si x es mayor que y, x es menor que y o si x es igual a y. Este programa lo he metido junto con el FreeDFD en el directorio "Curso" con el nombre "Programa1.dfd".

Bucle "for" o "para"

Este es un bucle peculiar. Básicamente tiene tres partes, la primera la asignación de una variable, la segunda la condición de final del bucle, y la tercera el incremento que se realiza en cada paso. Por ejemplo, supongamos que queremos repetir algo 7 veces, desde la vez 1 hasta la vez 7, entonces en el bucle inventaríamos o usaríamos una variable que se inicializaria a 1, la condición de final sería que esa variable valiese 7 y el incremento en cada paso sería 1. Supongamos sin embargo que queremos sumar todos los números pares del 1 al 100, la variable la inicializaríamos a 2, la condición de final sería el valor 100 y el incremento sería 2 en lugar de 1. Los bucles tienen una peculiaridad, y es que además del símbolo del bucle existe un símbolo de fin de bucle para indicar dónde se termina (todo lo que vaya entre ambos es lo que se ejecuta en el bucle).

Vamos a ver un ejemplo, hagamos un programita que nos pida dos números ("x" e "y") y que nos muestre la suma de todos los números que van de uno al otro (ambos inclusive). Para ello primero ponemos un símbolo de entrada de datos solicitando los valores de "x" e "y". Ahora declaramos una asignación para la variable "suma" inicializándola a 0, y que se corresponderá con nuestra suma de números para mostrar al final. Ahora echamos un bucle para y en las cuatro cajitas que nos salen pondremos "z <- x, y, 1". Esto significa que nos cree una variable "z" que será la que recorrerá el bucle (los valores de "x" a "y"), esta variable z la inicializa al valor "x", el bucle finalizará cuando valga "y" y el incremento es 1. Dentro del bucle arrastramos una asignación y ponemos "suma <- suma+z", es decir, en cada paso del bucle a nuestra suma le añadimos el valor actual. Finalmente, fuera del bucle, mostramos el resultado. ¿Qué hará este bucle?
Supongamos que a x le ponemos el valor 7 y a y le ponemos el valor 10. Inicialmente z valdrá 7 y ejecuta el bucle, con lo cual suma pasa a valer 7... ahora suma el incremento a z que pasa a valer 8. Como 8 no es mayor que 10, continúa, y suma pasa a valer 15, incrementa z que pasa a valer 9. Como 9 no es mayor que 10, continúa y suma pasa a valer 24, incrementa z que pasa a valer 10. Como 10 no es mayor que 10, continúa y suma pasa a valer 34, incrementa z que pasa a valer 11. Como 11 sí es mayor que 10, sale del bucle.

(http://img20.imageshack.us/img20/3684/buclefor.jpg)

Este programa lo he metido junto con el FreeDFD en el directorio "Curso" con el nombre "Programa2.dfd".


Bucle "while" o "mientras"

El famoso bucle que comprueba una condición y mientras se cumpla ejecuta lo de dentro. Vamos a ver un programa sencillito: el programa inicializa una variable a un valor (por ejemplo 7) y va pidiendo números al usuario hasta que acierta el número. Para ello inicializamos x a 7, mostramos un mensajito al usuario pidiendo un número, pedimos el valor de y que será el número del usuario, y ejecutamos un bucle "mientras" cuya condición será "x!=y", es decir, mientras "x sea distinto de y". Dentro del bucle mostramos el mensajito de "ese no es" y pedimos de nuevo el valor de "y".

(http://img37.imageshack.us/img37/6875/buclemientras.jpg)

Este programa lo he metido junto con el FreeDFD en el directorio "Curso" con el nombre "Programa3.dfd".

Terminando que es gerundio

Con esto ya tenéis bastante que aprender en esta lección. No os preocupeis, a caminar se aprende caminando. En la siguiente lección daremos más cositas acerca de esto, como los operadores aplicables, algunos ya los conocéis, como multiplicar (*), dividir (/), sumar (+), restar (-), o los booleanos que vimos en el capítulo 3 (AND, OR...). Otros son funciones matemáticas, como el seno o el coseno. Hay un poquito de todo.

Como tarea os mandaré hacer tres programas:
- El primero es para calcular la potencia de un número elevado a otro. En este caso el programa debe solicitar dos números al usuario ("x" e "y" por ejemplo) y mostrar de resultado la potencia "x elevado a y", es decir, si x es 4 e y es 6, devuelve el valor de 4*4*4*4*4*4.
- El segundo es para calcular el factorial de un número. El programa ahora solamente pide un número "x" y calcula "x!", es decir, "x factorial". El factorial de un número x es el producto de todos los números naturales desde 1 hasta x, usea, si x vale 5, el factorial valdrá 5*4*3*2*1.
- El tercero es para calcular el término "n" de la sucesión de fibonacci. Lo explicaré fácil, es aquella en la que el término cero de la sucesión vale 0, el primer término de la sucesión vale 1, y cada término vale la suma de sus dos anteriores. Es decir, la sucesión sería: 0,1,1,2,3,5,8,13,21,34,55. En este caso el programa os pedirá el número del término que queréis dar, de esta forma si ingresan un 0 debéis devolver 0, si ingresan un 1 devuelve 1, si ingresan un 2 devuelve 1, si ingresan un 3 devuelve 2, si ingresan un 4 devuelve 3, si ingresan un 5 devuelve 5, si ingresan un 6 devuelve 8, si ingresan un 7 devuelve 13....

Algún día os explicaré por qué la función de Fibonacci es tan importante, simplemente como dato sabed que cuando Leonardo de Pisa (Fibonacci) la estudió lo hizo para saber cual era la cantidad de conejos que se tendrían en un cierto tiempo sabiendo que se comienza con una pareja fértil.

Eso es todo por hoy, creo que tenéis un tiempo para juguetear, y yo para solucionar dudas  :amo:

Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 27 de Mayo de 2009, 19:52
Enviado. Un programita simpático el FreeDFD este.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 28 de Mayo de 2009, 10:27
Ok Fae, recibido y comprobado. Son correctos... o al menos lo que se ve lo parece :P
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 28 de Mayo de 2009, 20:04
¿Preferías descargarte un rar de 602 bytes de MU? :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 01 de Junio de 2009, 18:48
Como se nota que estáis de exámenes y que esto es un coñazo :D

Mañana espero poder postear (de noche) la segunda parte de los DFDs, explicando funciones. Lo siguiente ya será descargarse el Visual Studio para empezar a programar, que creo que Fae lo agradecerá.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Ningüino CDR-lar en 01 de Junio de 2009, 18:49
Me vas a hacer flagelarme al acabar los exámenes...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 01 de Junio de 2009, 19:00
Cita de: Penguin Boy en 01 de Junio de 2009, 18:49
Me vas a hacer flagelarme al acabar los exámenes...

Tranqui... aprender C# da para mucho mucho xD
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 01 de Junio de 2009, 19:12
Yo acabaré con suerte el miercoles.

Luego, tienes todo el verano para explotarme cuanto desees.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: neoprogram en 01 de Junio de 2009, 20:50
Cita de: Emilles en 01 de Junio de 2009, 18:48
Como se nota que estáis de exámenes y que esto es un coñazo :D

El curso no es un coñazo, solo son los exámenes.... y ni se te ocurra dejarlo a medias  uhm  ^^:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 01 de Junio de 2009, 21:28
Cita de: neoprogram en 01 de Junio de 2009, 20:50
Cita de: Emilles en 01 de Junio de 2009, 18:48
Como se nota que estáis de exámenes y que esto es un coñazo :D

El curso no es un coñazo, solo son los exámenes.... y ni se te ocurra dejarlo a medias  uhm  ^^:

Dije que mientras hubiese al menos un alumno continuaría. Y ahí tenéis a Fae, como un machote :D
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 01 de Junio de 2009, 21:41
Yo sigo también...

... no saco el Fibonacci de los cojones, pero sigo...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 01 de Junio de 2009, 22:05
acum=acum+cont hijo de mi vida.

Si, pelu, ya se, pero tal vez asi le venga la inspiración.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Faerindel en 01 de Junio de 2009, 22:08
Cita de: [Y]arot~ en 01 de Junio de 2009, 22:05
acum=acum+cont hijo de mi vida.
Le has aclarado absolutamente todo con eso, includo el inicio del Universo. :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 01 de Junio de 2009, 22:09
Qué piense coño, si es un ejercicio de lógica simplérrimo. :lol:
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: neoprogram en 01 de Junio de 2009, 23:45
En cuanto acabe los exámenes sigo con el temita más en condiciones...  *.*
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 02 de Junio de 2009, 09:24
Sí, será simplérrimo para tí, Yarot, pero yo soy biólogo y todas mis matemáticas se reducen a p > 0.05 = n. s. Y la serie de Fibonacci me la trae al pairo, como podrás deducir. Todo lo que tú me dices ya está pensado, pero simplemente, soy incapaz de dar con la solución.

Ilumíname tú, que eres todo un prohombre de la matemática y la lógica y todo lo sabes.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 02 de Junio de 2009, 11:18
Veamos... Serie de fibonacci.
Sabemos que la función viene definida por:
f(0) = 0
f(1) = 1
f(n) = f(n-1)+f(n-2)

Así que lo primero de lo que nos damos cuenta es de que hacen falta al menos dos variables:
Una para almacenar el término f(n-2) y otra para almacenar el término f(n-1). Las llamamos como queramos, por ejemplo, termMenosDos y termMenosUno. Las inicializamos:
termMenosDos = 0
termMenosUno = 1

Lo siguiene es que si nos piden el término 0 o el término 1 ya conocemos la respuesta directamente y la devolvemos. En caso contrario tenemos que ir avanzando términos hasta dar con el nuestro. ¿Cómo se avanza un término? 
Pues sabemos que f(n) = f(n-1)+f(n-2), y que termMenosUno es f(n-1) y termMenosDos es f(n-2), y que vamos a avanzar un término, con lo cual f(n-2) pasará a valer f(n-1) y f(n-1) pasará a valer f(n).

Necesitamos una variable auxiliar para almacenar el antiguo valor de termMenosDos:

termAux = termMenosDos
termMenosDos = termMenosUno
termMenosUno = termAux + termMenosUno

De esta forma cuando avancemos el primer paso (hacia el término 2) tendremos:
termAux = 0
termMenosDos = 1
termMenosUno = 1+0 = 1

Un paso más tendríamos (hacia el término 3) :
termAux = 1
termMenosDos = 1
termmenosUno = 1+1 = 2

Un paso más tendríamos (hacia el término 4) :
termAux = 1
termMenosDos = 2
termmenosUno = 2+1 = 3

Un paso más tendríamos (hacia el término 5) :
termAux = 2
termMenosDos = 3
termmenosUno = 3+2 = 5

Un paso más tendríamos (hacia el término 6) :
termAux = 3
termMenosDos = 5
termmenosUno = 5+3 = 8

Y así sucesivamente.

Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: elbe en 02 de Junio de 2009, 17:15
Ueeee!! No sé si iréis muy avanzados, pero yo me apunto al curso!! Tengo algo de idea ya de programación y tal, y el tema de los videojuegos me interesa, así que ya tienes una nueva alumna xD Me pondré al día poco a poco (que también estoy de exámenesss), en la sombra, y cuando os alcance ya marearé :D
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 02 de Junio de 2009, 17:36
Peluche yo me tengo que ausentar también que tengo que entregar un proyecto el 15 de junio cuando lo acabe me pongo con esto donde lo deje.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 02 de Junio de 2009, 21:20
No te preocupes Clave, o seguiré al ritmo que pueda...
Por cierto, hoy iba a subir curso, pero al final no, que me he ido de cervezas. Qué profesor más irresponsable soy :)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Khram Cuervo Errante en 02 de Junio de 2009, 21:45
Vaya... yo también me he ido hoy de cervezas después del examen...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Clave en 02 de Junio de 2009, 23:26
Cabrones controlaos un poco que hace 3 semanas que este cuerpo serrano no toca el alcohol!!!

AHAHAHAHHAHAH MI GOZO EN UN POZO


mierda empiezo a recuperar neuronas eso ya es jodidamente malvado
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 03 de Junio de 2009, 12:35
5. Las funciones son tus amigas.

Antes de comenzar la lección voy a dejar unas tablitas explicando todos los operadores y funciones del FreeDFD, para el que lo quiera utilizar a posteriori.

Sorry but you are not allowed to view spoiler contents.


Sorry but you are not allowed to view spoiler contents.


¿Qué es una función? Las vimos en el capítulo 1 y en el capítulo dos. Las funciones son como cajas negras que aceptan unos parámetros de entrada y dan un valor de salida, y por dentro pueden hacer de todo. Supongamos por ejemplo que estamos haciendo un programa de contabilidad, y sabemos que en nuestro programa vamos a estar continuamente calculando el IVA para facturas. Entonces un tipo listo diría, "ah, pues me hago una función DevolverIVA". Ese tipo listo se pone a pensar, ¿qué le paso de parámetro y qué me tiene que devolver? Está claro que como mínimo hay que pasarle de parámetro un precio sobre el cual calcular el IVA, así tendríamos DevolverIVA(precio). La función devolvería el IVA para ese precio. Pero el mismo tipo listo sabe que no siempre es el 16%, sino que hay tres tipos de IVA (General 16%, Reducido 7% y Superreducido 4%), así que decide pasar el tipo como parámetro, una letra que puede ser G, R o S. Así la función ahora sería DevolverIVA(precio,tipoIVA). ¿Qué hace por dentro la función? Está claro que dentro debe devolver precio*porcentajeIVA/100. Pero resulta que no va a usar porcentajes solamente ahí, y poner siempre la operación completa no ayuda a la vista, así que crea la función CalcularPorcentaje(valor,porcentaje) que lo que hace es devolver valor*porcentaje/100.

Este tipo de abstracción de funciones es la que se hizo en el capítulo 1, con la receta. Fijáos que hay verbos que repetís continuamente, esos son las funciones a invocar, y por dentro pues se puede uno extender más.

Vamos al FreeDFD a aprender a definir subprogramas. Un subprograma en realidad es una función incapaz de devolver valores, en otros lenguajes se llaman procedimientos. En estos casos si queremos que devuelvan un valor lo normal es pasarles uno dónde puedan escribir. Vamos a hacer un programa que le puedas decir un número de dados y caras de los dados y realice la tirada (lo equivalente a decirle 1D100, 5D10, etc. en rol). Lo primero es identificar el botón para hacer subprogramas:

(http://img198.imageshack.us/img198/2476/botonsubprograma.jpg)

Al pincharlo nos aparece una cajita extraña y un retornar. Al hacer doble click en la cajita es dónde definimos la función: nombre, parámetros y descripción. A nuestra función la vamos a llamar LanzarDados, y los parámetros que le pasaremos serán dados (número de dados a lanzar), caras (cantidad de caras de cada dado) y resultado (que será dónde nos guarde el resultado de la tirada).

En el cuerpo de la función lo primero que haremos será inicializar resultado a 0. Luego añadimos un bucle for dónde la variable será x, desde 1 hasta dados y el incremento 1. En cada paso del bucle haremos "resultado <- resultado+RANDOM(caras)+1".

Explicación:
El bucle for es para repetir la cantidad de tiradas de dados que hay que hacer. En cada paso del bucle sabemos que tenemos que sumar a lo que llevamos el resultado de lanzar un dado nuevo, y para lanzar un dado al azar usamos la función RANDOM(x) que nos devuelve un número entre 0 y x-1. A esto le sumamos uno porque un dado de 10 caras no va de 0 a 9, sino de 1 a 10.

Tendríamos el siguiente subprograma:
(http://img190.imageshack.us/img190/7348/subprogramadados.jpg)

Ahora habría que usarlo. Justo a la izquierda del botón de añadir subprograma tenéis dos botones para navegar entre ellos. Id al programa principal de toda la vida. En él meted una lectura para preguntar al usuario los valores de dados y de caras. Ahora añadís una llamada dónde invocáis al subprograma LanzarDados pasándole de parámetros dados, caras, resultado. Por último mostráis el resultado al usuario:

(http://img268.imageshack.us/img268/931/subprogramallamada.jpg)

Bueno, ya sabemos crear funciones. Ahora viene lo curioso: la recursividad. Las funciones se pueden llamar unas a otras, e incluso se pueden llamar a sí mismas. ¿Qué es esto de llamarse a sí mismas? Lo que se conoce como recursividad. Consideremos por ejemplo el cálculo del factorial. Sabemos que 7! = 7*6!, que a su vez 6! = 6*5! y así hasta el 2! que sabemos que es 2*1. Podríamos definir por tanto una función Factorial(x) tal que dentro de su cuerpo tengamos que si x vale 1 devuelve 1, en caso contrario devuelve x*Factorial(x). Aplicado a nuestros subprogramas sería definir un subprograma Factorial que admite dos parámetros x, resultado. En el cuerpo del programa ponemos un IF, si x es 1 entonces no hace nda, si x es distinto de 1 entonces resultado es igual a x*resultado y llamamos a Factorial(x-1,resultado). Como prerrequisito, cuando se llama por primera vez a la función factorial, resultado tiene que estar inicializado a 1.

Veamos cómo queda:

(http://img189.imageshack.us/img189/710/factorial.jpg)

Pues nada, deberes de hoy.

1. Sin recursividad: Hacer un programa con el DFD tal que pida al usuario un precio de un artículo y su tipo de IVA en forma de letra ('G' => 16%, 'R' => 7%, 'S' => 4%, si la letra que introduce el usuario no es válida devuelve el error). El programa debe devolver el precio final del artículo, es decir, sumarle el IVA. Para calcular el IVA usará una función DevolverIVA, que a su vez llamará a una función CalcularPorcentaje. Nota: cuando se pide al usuario un valor, para pasarle una cadena de caracteres se deben de usar las comillas, así que cuando nos pida la letra tenemos que meter 'G' en lugar de G.

2. Con recursividad: Hacer un programa que devuelva el término n de la serie de fibonacci usando un subprograma recursivo.



Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 04 de Junio de 2009, 12:15
6. De vectores, matrices y otros monstruos multidimensionales

Hemos visto que existen variables con diferentes tipos, al menos hemos visto numéricas (en este caso números reales), cadenas de caracteres (strings) y booleanas (lógicas que valen cierto o falso). Pues ahora vamos a ver los vectores.

Los vectores o arrays, aunque en sudamérica los llaman arreglos (arreglo el que le iba a hacer yo en la cara al traductor...), son en realidad listas ordenadas de cualquier cosa. En nuestro FreeDFD esto se hace usando un nombre de variable, como siempre, y una posición entre paréntesis. Por ejemplo:
lista(1) <- 3
lista(2) <- 7
lista(3) <- 12

Las ventajas que nos dan es que podemos usar grupos de valores y usarlos todos a la vez en bucles o con un índice, es decir, el índice que va entre paréntesis puede invocarse mediante una variable. Por ejemplo supongamos que tenemos una videoteca en nuestro salón con varios títulos, y queremos preguntar al usuario cuántas películas tiene y luego ir preguntándole los títulos de forma ordenada, para más tarde preguntarle por un número de película y decirle el título. La forma de hacerlo sería:
- Pedir la cantidad de películas (numPeliculas)
- Un bucle (variable i por ejemplo) desde 1 hasta la cantidad de películas pidiendo el título y almacenándolo en la posición actual del vector (peliculas(i)).
- Pedir el número de película que se quiere conocer (iPelicula)
- Si iPelicula es mayor que 0 (dado que el vector comienza en 1) e iPelicula es menor o igual que numPeliculas, entonces se muestra peliculas(iPelicula) en caso contrario se informa de que no existe ninguna con esa numeración.

El diagrama de flujo quedaría más o menos así:

(http://img193.imageshack.us/img193/1693/pedirpeliculas.jpg)

Pero los vectores estos son maravillosos porque no están limitado a una sola dimensión. Es decir, supongamos que de las películas queremos tener también una referencia de localización, entonces alguien diría "ah, pues otro vector para las referencias". Pues no hace falta, porque los vectores pueden tener más de una dimensión. En este caso haría falta dos dimensiones, una nos diría el campo que queremos mirar y otra la película, es decir, si hay 5 películas en nuestra base de datos podríamos decir que:

peliculas(1,1) <- 'ID2038'
peliculas(1,2) <- 'Heat'
peliculas(2,1) <- 'ID2085'
peliculas(2,2) <- 'Una historia del Bronx'
peliculas(3,1) <- 'ID1039'
peliculas(3,2) <- 'Cristal Oscuro'
peliculas(4,1) <- 'ID1045'
peliculas(4,2) <- 'Dentro del laberinto'
peliculas(5,1) <- 'ID3017'
peliculas(5,2) <- 'El último mohicano'

Como veis, al vector se le pasan dos índices en lugar de uno. El primero es la posición de la película, el segundo es el campo que queremos consultar (1 para el localizador, 2 para el título).

No hay límite para las dimensiones que podéis especificar para un vector, así que podéis tener monstruos multidimensionales. En matemáticas, cuando son dos las dimensiones, se llama "Matriz" y son muy útiles e interesantes para multitud de cosas, entre ellas solucionar sistemas de ecuaciones lineales.

No voy a poner un ejercicio complicado de esto... bah venga, soy un mentiroso, sí lo voy a poner :)

Deberes:
- Hacer una aplicación que nos pida la cantidad de películas, y de cada una pida el identificador, título y temática (thriller, melodrama, infantil, anime...). Luego debe pedir un número de película y debe decir todos los datos conocidos de ella.

- Hacer una aplicación que pregunte un número y calcule todos los números primos existentes hasta ese número, conociendo únicamente que los números 2 y 3 son primos. Notas sobre este ejercicio:
+ Se considera que un número es primo cuando no es divisible entre ningún número primo, es decir, cuando el resto de dividir dicho número entre los primos menores que él jamás es 0. Para esto necesitáis el operador "MOD". Para saber si un número es divisible entre otro sería: "(numero MOD otroNumero) =0" (esto es cierto cuando numero es divisible entre otroNumero).
+ Seguramente necesitéis usar una variable booleana (yo la he llamado esPrimo) que nos indica si un número es primo o no (inicializada a .V.). Recordad que podéis usar operadores lógicos, el AND debería ser muy útil en este ejercicio.
+ Si no queréis usar una variable auxiliar para saber cuántas posiciones del vector lleváis (esto es, cuántos números primos lleváis calculados...) siempre podéis aprovecharos del propio vector y hacer que primos(0) en lugar de contener un número primo contenta la cantidad de términos del vector.

Suerte :)


Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: El Brujo en 04 de Junio de 2009, 13:10
Frena el carro nene que a este ritmo para finales de junio que acabo exámenes vas a haberte pulido el curso entero...
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 04 de Junio de 2009, 14:03
Cita de: Brujo en 04 de Junio de 2009, 13:10
Frena el carro nene que a este ritmo para finales de junio que acabo exámenes vas a haberte pulido el curso entero...

Estoy puliendo el primer libro, que es el teórico, para que cuando termines tus exámenes estemos ya programando en c# :P

Además, el curso es en diferido, cada uno que lo siga a su velocidad, estoy subiendo el ritmillo por los que ya saben algo de filosofía de programación.
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Skiles en 04 de Junio de 2009, 14:34
Cita de: Emilles en 04 de Junio de 2009, 14:03
Cita de: Brujo en 04 de Junio de 2009, 13:10
Frena el carro nene que a este ritmo para finales de junio que acabo exámenes vas a haberte pulido el curso entero...

Estoy puliendo el primer libro, que es el teórico, para que cuando termines tus exámenes estemos ya programando en c# :P

Además, el curso es en diferido, cada uno que lo siga a su velocidad, estoy subiendo el ritmillo por los que ya saben algo de filosofía de programación.

Yo me amputo, pero a mi velocidad, cuando termine los exámenes que me quedan ya me meteré más a fondo ;)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Maik en 04 de Junio de 2009, 17:58
Cita de: Emilles en 04 de Junio de 2009, 14:03
Cita de: Brujo en 04 de Junio de 2009, 13:10
Frena el carro nene que a este ritmo para finales de junio que acabo exámenes vas a haberte pulido el curso entero...

Estoy puliendo el primer libro, que es el teórico, para que cuando termines tus exámenes estemos ya programando en c# :P

Además, el curso es en diferido, cada uno que lo siga a su velocidad, estoy subiendo el ritmillo por los que ya saben algo de filosofía de programación.

(seg)
Título: Re: Curso de Programación Lúdica: Introducción
Publicado por: Bill en 10 de Junio de 2009, 11:27
7. La vaquita hace "muuuuu", el patito hace "cua cua"

Esta lección es teórica totalmente, así que no habrá ejercicio final más allá de que cada uno se quede pensando. La pretensión de esta lección es ver cual es la filosofía de la OOP (Object Oriented Programming), y sus puntos fundamentales. Para ello hay que entender 4 conceptos básicos: abstracción, encapsulamiento, herencia y polimorfismo. Suena chungo de cojones, ¿eh? Pues poco a poco.

El primer término que se empleó fue el de abstracción. Antes de existir la programación orientada a objetos, existía la ténica llamada "TDA" (Tipo de Dato Abstracto). Esta técnica consistía en agrupar las cosas por afinidad y conseguir que el programador que las fuera a utilizar no tuviese que entender su funcionamiento interno. Por ejemplo, supongamos que estamos haciendo un programa que usa conjuntos de datos obtenidos en un laboratorio, y lo estamos haciendo dos personas. Una de las personas se encargará de definir los conjuntos, y la otra persona usará dichas definiciones para las labores que realmente necesita hacer el programa. Entonces el primero comienza a programar y decide definir los conjuntos con las siguientes reglas:
Citar- Un conjunto contiene elementos, así que voy a definir un tipo TElemento que será el adecuado para el laboratorio. Un TElemento será el tipo de variable para cualquier elemento que necesite usar.
- También definiré el tipo TConjunto, y usaré herramientas de programación de tal forma que un TConjunto sea una lista no necesariamente ordenada de variables de tipo TElemento.
- Necesitaré una función InicializarConjunto(conjunto) tal que inicializa el conjunto que le pase a conjunto vacío.
- Necesitaré una función EsConjuntoVacío(conjunto) que me indica si un conjunto está vacío
- Necesitaré una función AñadirElemento(conjunto, elemento) que añade un elemento a un conjunto (siempre y cuando el elemento no pertenezca ya al conjunto)
- Necesitaré una función QuitarElemento(conjunto, elemento) que quita un elemento de un conjunto (siempre y cuando el elemento pertenezca al conjunto)
- Necesitaré una función PerteneceElemento(conjunto, elemento) que me indica si un elemento pertenece a un conjunto
- Necesitaré una función Intersección(conjuntoA, conjuntoB) que me devuelve un tercer conjunto fruto de la intersección de dos conjuntos.
- Necesitaré una función Unión(conjuntoA, conjuntoB) que me devuelve un tercer conjunto fruto de la unión de dos conjuntos.
- Necesitaré una función Diferencia(conjuntoA, conjuntoB) que me devuelve un tercer conjunto fruto de la diferencia del conjuntoA con el conjuntoB.
- Necesitaré una función Cardinalidad(conjunto) que me devuelve la cantidad de elementos del conjunto.

Si el segundo programador conoce la existencia de estos tipos y estas funciones, no necesita saber para nada cómo funcionan los tipos o las funciones por dentro, o cómo está programado. Para ello en las unidades (cada uno de los ficheros dónde se programa...) hay dos secciónes: la sección de interfaz y la sección de implementación. La sección de interfaz es dónde se declara "mira tío, esta unidad te da para usar estos tipos, estas constantes, estas variables y estas funciones", la sección de implementación es la zona de la unidad que no es visible desde fuera, y que contiene la programación interna de ese TDA. ¿Necesita el segundo programador saber si conjunto es un vector, un yogur, una lista de objetos o un enano con buena memoria? ¿Necesita el segundo programador conocer cómo funciona por dentro la función de Intersección? La respuesta es no, no lo necesita. Eso es la abstracción, y base de los TDA.

Vayamos ahora con objetos. Hay quien dice que la programación orientada a objetos es lo mismo que el TDA, esos que lo dicen no tienen ni puta idea, y me quedo así de pancho afirmándolo. La filosofía del objeto es más compleja y completa.

Lo primero es entender la base, ¿qué se supone que es un objeto? Para ello tenéis que saber que existen dos conceptos básicos: clase e instancia. Clase es la definición básica de un objeto, e instancia es cada uno de los objetos "reales" que creamos a partir de esa definición. Por ejemplo, pensad en "Coche". El concepto "Coche" nos dice que debe tener unas 4 ruedas, motor, puertas, un cierto color, salpicadero... pero no me puedo montar en un concepto y conducirlo hasta murcia, para eso necesito un coche real, y este coche real es una instancia de la clase Coche.

De un objeto también hay que entender que contiene propiedades, métodos y eventos en su definición. Volviendo al coche, el color es una propiedad, su velocidad máxima también, dimensiones, tipo de ruedas... Es cada uno de los "adjetivos" o "calificativos" que se puedan aplicar al objeto. Métodos de un coche serían Acelerar(), Frenar(), CambiarDeMarcha(), es decir, cada una de las funciones que podemos aplicar sobre el coche para modificar su estado, o incluso sus propiedades (si el coche tiene una propiedad velocidadActual o revolucionesActuales, cambian según lo estamos usando). Por último evento es un informador de un suceso, por ejemplo cuando cambiamos la marcha se nos puede lanzar un evento "MarchaCambiada" informándonos de la nueva marcha, pero para entenderlo mejor los eventos no tienen por qué estar ligados a métodos, un coche nos puede lanzar un evento "GasolinaBaja", "RevisarAceite"... cualquier lucecita o indicador que podamos ver en el panel.

Visto esto, vayamos a entender herencia, encapsulación y polimorfismo.
- Herencia: Los objetos pueden descender unos de otros, y cada descendiente puede modificar o añadir propiedades, métodos o eventos de su padre. De esta forma Coche descenderá de Vehículo, y Vehículo no necesariamente tendrá CambiarDeMarcha(), dado que un patinete también es un vehículo. Los árboles de descendencia serán tan complicados o completos como queramos hacer, pensad en el árbol de los seres vivos si para cada tipo definiéramos una clase, comenzando por las autótrofas...

- Encapsulación: A veces lo confunden con la abstracción, pero técnicamente no es así. La encapsulación es la capacidad de hacer que ciertas propiedades, métodos o eventos no sean visibles para todo el mundo. De esta forma suele haber tres visibilidades básicas (pueden ser más): privada, protegida y pública. Privada significa que solamente la propia clase tiene acceso a esos datos, protegida significa que tiene acceso la clase y sus descendientes, pública significa que el acceso es público incluso para clases externas.

- Polimorfismo: Y aquí es dónde llegamos al título de la lección. Suponed la clase Animal, de la cual tenemos descendencias en plan Ave, Mamífero, Pez, Insecto... y ahí se va complicando la cosa hasta llegar a las clases de especies animales concretas, como la Vaca (que será un mamífero) hasta el Pato (que será un Ave). Suponed ahora que en la clase Animal hemos definido el método EmitirSonido(), es decir, un perro ladra, un gato maúlla. Ese EmitirSonido() hará cosas distintas dependiendo del descendiente de Animal que lo utilice. De hecho, el EmitirSonido() de Animal no hará nada, dado que no hay un sonido genérico para todos. Si tenemos un objeto de la clase Vaca, EmitirSonido() devolverá "muuuuuu", si tenemos un objeto de la clase Pato, EmitirSonido() devolverá "cuá cuá". Cada descendiente puede redefinir el funcionamiento interno de un miembro de su padre, incluso reaprovechando lo que estaba programado en el padre.


Pues ahí queda eso, pero a caminar se aprende poniéndose en pie y dando unos pasos... así que aquí doy por finalizado el primer bloque de aprender a pensar, dado que a partir de aquí se seguirá aprendiendo a ello, pero con el lenguaje de programación delante de las narices.

El siguiente libro ya será de C#, y comenzaremos explicando la instalación del Visual Studio. Los que sean piratones, que se pillen un Visual Studio 2008, los que no, que consigan el Visual Studio 2008 Express, que se baja de la propia web de microsoft.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Thylzos en 10 de Junio de 2009, 20:33
Pues acabo de leerlo todo. No le tengo mucha esperanza a .net (lo reconozco, lo más que usé fue Visual Basic y poco más), pero por ahora pinta interesante. Atrasado, pero me apunto.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Maik en 11 de Junio de 2009, 18:06
Cita de: Peluche en 10 de Junio de 2009, 11:27
Los que sean piratones, que se pillen un Visual Studio 2008, los que no, que consigan el Visual Studio 2008 Express, que se baja de la propia web de microsoft.

Yo me ocupo.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 12 de Junio de 2009, 10:32
Cita de: Yarot en 11 de Junio de 2009, 18:06
Cita de: Peluche en 10 de Junio de 2009, 11:27
Los que sean piratones, que se pillen un Visual Studio 2008, los que no, que consigan el Visual Studio 2008 Express, que se baja de la propia web de microsoft.

Yo me ocupo.

Ok. Si tienes problemas para localizar la medicina avísame, que la tengo muy a mano ;)
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Clave en 12 de Junio de 2009, 11:30
a partir de el lunes sigo con el curso donde lo deje ^^
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 15 de Junio de 2009, 21:02
El curso queda discontinuado por falta de profesor. Si alguien lo quiere continuar, tiene mi visto bueno, en caso contrario lo siento mucho.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: El Brujo en 15 de Junio de 2009, 22:47
Definitivamente o temporalmente por vacaciones o algo así?
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 15 de Junio de 2009, 22:55
Cita de: El Brujo en 15 de Junio de 2009, 22:47
Definitivamente o temporalmente por vacaciones o algo así?

No se sabe... se ha despedido de todas las secciones del :106: en las que estaba haciendo algo (Ej: partidas que jugaba)  :allid:
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Junio de 2009, 16:28
Cita de: neoprogram en 15 de Junio de 2009, 22:55
Cita de: El Brujo en 15 de Junio de 2009, 22:47
Definitivamente o temporalmente por vacaciones o algo así?

No se sabe... se ha despedido de todas las secciones del :106: en las que estaba haciendo algo (Ej: partidas que jugaba)  :allid:

Dadme unos días para cagarme en mi puta madre, felicitarme a mí mismo por unas cosas del curro, seguir cagándome en mi puta madre, y tomarme unas litronas.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: El Brujo en 25 de Junio de 2009, 16:59
Perfecto, es lo que tardo yo en acabar los exams. A partir del día 30 me haré el curso del tirón y te lo iré enviando.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 25 de Junio de 2009, 18:59
Cita de: Peluche en 25 de Junio de 2009, 16:28
Dadme unos días para cagarme en mi puta madre, felicitarme a mí mismo por unas cosas del curro, seguir cagándome en mi puta madre, y tomarme unas litronas.

¿Eso es que seguirá el curso?  *.*
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Calabria en 26 de Junio de 2009, 01:33
Güi lof llu
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 12 de Julio de 2009, 01:22
Cita de: Peluche en 25 de Junio de 2009, 16:28
Dadme unos días para cagarme en mi puta madre, felicitarme a mí mismo por unas cosas del curro, seguir cagándome en mi puta madre, y tomarme unas litronas.

Si te falta lo de las litronas o lo de felicitarte, hacemos fondo común o algo para ayudarte....  :cool:
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 13 de Julio de 2009, 00:14
Cita de: neoprogram en 12 de Julio de 2009, 01:22
Cita de: Peluche en 25 de Junio de 2009, 16:28
Dadme unos días para cagarme en mi puta madre, felicitarme a mí mismo por unas cosas del curro, seguir cagándome en mi puta madre, y tomarme unas litronas.

Si te falta lo de las litronas o lo de felicitarte, hacemos fondo común o algo para ayudarte....  :cool:

Paciencia plis... que todavía me estoy desintoxicando. Prometo que en breve sigo ;) Y bueno, si quieres traerme unas litronas, ya sabes que a ti te daría el curso en "privado", pichurri :*
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Tz en 30 de Agosto de 2009, 14:17
Desde el 13 de julio a ya septiembre, sin noticias, yo me apunto si se retoma, pero tiene muy mala pinta, a pesar de lo que se dijo.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 30 de Agosto de 2009, 14:22
La pereza es la madre de todos los males... y a las madres hay que respetarlas. Me piro dos semanas a Holanda a currar, a mi vuelta ya estaré "liberado".
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Maik en 11 de Septiembre de 2009, 03:15
Cita de: Gambit en 12 de Junio de 2009, 10:32
Cita de: Yarot en 11 de Junio de 2009, 18:06
Cita de: Peluche en 10 de Junio de 2009, 11:27
Los que sean piratones, que se pillen un Visual Studio 2008, los que no, que consigan el Visual Studio 2008 Express, que se baja de la propia web de microsoft.

Yo me ocupo.

Ok. Si tienes problemas para localizar la medicina avísame, que la tengo muy a mano ;)

A ver si mañana consigo sustraer de clase uno, que con el caos inicial de formateos y apaños de hardware, desaparecen memorias RAM, gráficas y Discos Duros como una party llena de looters ninja.

Le tengo echado el ojo a un 2008, pero me gustaría arriesgarme a preguntar si serviría con un 2005 o 2006, que están asi como fuera de la zona visual.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Maik en 11 de Septiembre de 2009, 21:51
Success. :lol:
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Tz en 21 de Septiembre de 2009, 21:24
No sale nada, verdad? andaré al loro por si tal, pero esto tiene pinta de estar muerto
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 21 de Septiembre de 2009, 21:26
Cita de: Tz en 21 de Septiembre de 2009, 21:24
No sale nada, verdad? andaré al loro por si tal, pero esto tiene pinta de estar muerto

Viernes día 25 se reabre.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 21 de Septiembre de 2009, 22:28
Cita de: Gambit en 21 de Septiembre de 2009, 21:26
Cita de: Tz en 21 de Septiembre de 2009, 21:24
No sale nada, verdad? andaré al loro por si tal, pero esto tiene pinta de estar muerto

Viernes día 25 se reabre.
:wiiiiii: :wiiiiii: :wiiiiii: :wiiiiii: :wiiiiii: :wiiiiii:  :pelotita: :pelotita: :columpio:  :pelotita: :pelotita:   :wiiiiii: :wiiiiii: :wiiiiii: :wiiiiii: :wiiiiii: :wiiiiii::
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Lictea en 22 de Septiembre de 2009, 04:04
¿Un viernes? No me fiaria yo mucho.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 25 de Septiembre de 2009, 16:14
Cita de: Lictea en 22 de Septiembre de 2009, 04:04
¿Un viernes? No me fiaria yo mucho.

Bueno... todavía quedan unas 8 horas de este viernes, así que no todo está perdido :P
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Lictea en 25 de Septiembre de 2009, 16:48
Pero es que son las 8 horas que esta fuera del curro.

¡Abandonar toda esperanza...! :P
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 17:38
Libro II: Aprendiendo C#

Introducción a la plataforma .NET

Este capítulo es el coñazo de teoría que todo curso de .NET tiene al principio y ninguno de los alumnos se entera de nada, menos los que ya sabían de qué iba la cosa. No pretendo que lo entendáis, simplemente que os suenen algunos conceptos y que así con el tiempo digáis "anda coño, esto me suena..." y podais regresar a este capítulo y consultarlo para ir entendiendo cosas.

¿Qué es .NET?
Pero, ¿qué es esto de .NET? Comencemos por el principio de todo. Antiguamente había dos tipos de lenguajes: los interpretados y los compilados. Los interpretados, por ejemplo hoy en día el javascript o en sus viejos tiempos el basic, consisten en que hay un programita al que le pasas el código fuente y él lo va ejecutando línea a línea, y haciendo sus cosas. El principal problema es que son lentos, pero la ventaja está en que son multiplataforma per se, es decir, el javascript se ejecuta igual de bien en un navegador en windows que en linux que en mac. Luego están los lenguajes compilados, que son los más clásicos. El programador escribe su código fuente, y luego lo compila para esa máquina, generando un ejecutable que está en código máquina. La ventaja es que son más eficientes, pero la desventaja es que no son multiplataforma.

Y entonces llegó Sun y reaprovechó una idea que existía hacía tiempo, pero de la que sacaron provecho: la máquina virtual y los bytecodes. Básicamente, en java los programas están como "a caballo" entre interpretados y compilados. En java compilas, pero no generas un ejecutable en código máquina, sino un bytecode en código de su máquina virtual, de forma que se ejecuta en plataformas que tengan la máquina virtual instalada. Por eso los programas en Java llegan desde windows, linux hasta incluso dispositivos móviles, lavadoras y neveras.

Microsoft gustó de esta idea y desarrolló el Framework de .NET. Es un componente software que puede ser instalado o viene por defecto con sistemas operativos de Microsoft. Es el que se encarga de proveer las librerías necesarias para ejecutar una aplicación .NET. Por eso podemos programar algo en nuestro visual studio del pc, y que se ejecute en la xbox 360, en el móvil o en un navegador, porque nos permite trabajar en los frameworks adecuados (XNA, mobile, silverlight...) para cada dispositivo.

CLS: Common Language Specification
El Framework de .NET es independiente del lenguaje de programación de origen: cualquier lenguaje puede ser compilado hacia algo ejecutable en .NET siempre que cumpla una especificación llamada CLS (Common Language Specification). Comunmente se suele programar en C# dado que es el lenguaje más evolucionado y de alto nivel existente hasta el momento, pero otros entornos y lenguajes generan aplicaciones en .NET: Visual Basic, Delphi...

MSIL: Microsoft Intermediate Language
Un lenguaje que cumple la CLS genera de salida una compilación intermedia en un lenguaje llamado MSIL (Microsoft Intermediate Language) que vendría a ser "similar" al bytecode de java. De esta forma dos aplicaciones que hagan lo mismo realizadas en lenguajes diferentes pero que cumplen el CLS, generarán un código MSIL muy parecido.

CLI: Common Language Infraestructure
Hasta aquí bien, ya sabemos que el entorno de programación al final genera un MSIL. Pero, ¿y cómo se ejecuta? Para eso Microsoft creó otro estándar: el CLI (Common Language Infraestructure). Este estándar viene a decir lo que tiene que cumplir un componente software para poder interpretar un MSIL. En realidad lo que define es un entorno de ejecución virtual independiente dentro del software en el que trabajan las aplicaciones escritas para .NET, y dicho entorno se ocupa de todo lo necesario para la correcta ejecución de todas las aplicaciones .NET: gestión de memoria, ciclo de vida de objetos, seguridad, recolector de basura, hilos, procesos...

CLR: Common Language Runtime
Si el CLI era un estándar, el CLR es la implementación que ofrece Microsoft de dicho estándar. Son las librerías y el entorno virtual en si, no el concepto abstracto en papel, sino algo ya funcionando, que recibe el MSIL y lo ejecuta. Cada tipo de Sistema Operativo tiene su CLR, así hay CLR de windows 32 bits, de windos 64 bits, de windows mobile o de xbox 360.

CTS: Common Type System
Una de las partes del CLS es el CTS (Common Type System). El CTS define el conjunto de tipos de datos que se pueden manejar y cómo se deben usar. Por ejemplo, el CTS define que existen números enteros de 32 bits (System.Int32), pero estos se llamarán diferente en un programa en Visual Basic (Integer) que en un programa en C# (int)

BCL: Basic Class Library
La BCL (Basic Class Library) es la biblioteca básica de clases de la que nos provee .NET. Son todas las diferentes clases, funciones, constantes y tipos que vienen de forma básica para no tener que comenzar a programar desde cero. Toda biblioteca de clases de .NET se estructurará en bibliotecas DLL (Dynamic Link Library)

Un gráfico para ver como encajaría todo esto así por encima, repito que no tenéis que entenderlo todo ahora, es simplemente ir cazando conceptos:

(http://img33.imageshack.us/img33/8928/arqnet.jpg)


Videotutorial de esta lección:
http://www.screencast.com/t/jgDsEtfM5D1
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 17:51
Por cierto, los que no tenga Visual Studio 2008 instalado, tenéis varias opciones:

1. Instalar la versión Express, que Microsoft la ofrece de gratis, pero no es tan completa como podría ser: http://msdn.microsoft.com/es-es/express/default.aspx
2. Buscar por ahí
3. Apretar a Yarot para que termine de subirlo
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 25 de Septiembre de 2009, 18:04
¿El Visual Studio 2008 Professional Edition también valdría? (supongo que sí, pero por asegurar...)
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 18:06
Cita de: neoprogram en 25 de Septiembre de 2009, 18:04
¿El Visual Studio 2008 Professional Edition también valdría? (supongo que sí, pero por asegurar...)

De sobra, es el que uso yo. Dentro de poco sale la versión 2010 (hay una beta) y ya por fin la .NET 4.0
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 25 de Septiembre de 2009, 18:07
Cita de: Gambit en 25 de Septiembre de 2009, 18:06
Cita de: neoprogram en 25 de Septiembre de 2009, 18:04
¿El Visual Studio 2008 Professional Edition también valdría? (supongo que sí, pero por asegurar...)

De sobra, es el que uso yo. Dentro de poco sale la versión 2010 (hay una beta) y ya por fin la .NET 4.0

Comprobaré el e-academy por si acaso, pero la última que ví era esa: Visual Studio 2008 Professional Edition (x86 and x64 WoW) - DVD (English)

Si, han salido 2 nuevos... la versión en castellano y la beta del 2010, cierto
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 18:09
Cita de: neoprogram en 25 de Septiembre de 2009, 18:07
Cita de: Gambit en 25 de Septiembre de 2009, 18:06
Cita de: neoprogram en 25 de Septiembre de 2009, 18:04
¿El Visual Studio 2008 Professional Edition también valdría? (supongo que sí, pero por asegurar...)

De sobra, es el que uso yo. Dentro de poco sale la versión 2010 (hay una beta) y ya por fin la .NET 4.0

Comprobaré el e-academy por si acaso, pero la última que ví era esa: Visual Studio 2008 Professional Edition (x86 and x64 WoW) - DVD (English)

Yo tengo uno, son dos dvds y su correspondiente medicina, me da cosita subirlo... pero no vives lejos, todavía funcionan las grabadoras o los pendrives.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 25 de Septiembre de 2009, 18:12
Cita de: Gambit en 25 de Septiembre de 2009, 18:09
Yo tengo uno, son dos dvds y su correspondiente medicina, me da cosita subirlo... pero no vives lejos, todavía funcionan las grabadoras o los pendrives.

Probaré a instalar este a ver si se deja... según lo que dicen los de e-academy, debería poder instalarlo alegremente
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Faerindel en 25 de Septiembre de 2009, 18:32
MOAR.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Thylzos en 25 de Septiembre de 2009, 21:17
Cita de: Gambit en 25 de Septiembre de 2009, 17:51
Por cierto, los que no tenga Visual Studio 2008 instalado, tenéis varias opciones:

1. Instalar la versión Express, que Microsoft la ofrece de gratis, pero no es tan completa como podría ser: http://msdn.microsoft.com/es-es/express/default.aspx
2. Buscar por ahí
3. Apretar a Yarot para que termine de subirlo

¿Con mono crees que podré seguir el curso o tendré que hacer malabares?
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Maik en 25 de Septiembre de 2009, 21:45
Se me olvidó. Este finde estará finalizada y posteada.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 21:47
Cita de: Thylzos en 25 de Septiembre de 2009, 21:17
Cita de: Gambit en 25 de Septiembre de 2009, 17:51
Por cierto, los que no tenga Visual Studio 2008 instalado, tenéis varias opciones:

1. Instalar la versión Express, que Microsoft la ofrece de gratis, pero no es tan completa como podría ser: http://msdn.microsoft.com/es-es/express/default.aspx
2. Buscar por ahí
3. Apretar a Yarot para que termine de subirlo

¿Con mono crees que podré seguir el curso o tendré que hacer malabares?

Con mono lo más que podrás hacer es ir de los Apeninos a los Andes buscando a mamá. El Mono no permite juguetear con XNA ni con la mitad de las cosas que vamos a ver. Sorry. Pero siempre puedes ver los videotutoriales para escuchar mi dulce y aterciopelada voz.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Thylzos en 25 de Septiembre de 2009, 21:49
Pues nada, me conformaré con tu aterciopelada voz y mis múltiples intentos de que wine me haga me haga caso. Algún día me haré una partición con Windows.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 21:53
Cita de: Thylzos en 25 de Septiembre de 2009, 21:49
Pues nada, me conformaré con tu aterciopelada voz y mis múltiples intentos de que wine me haga me haga caso. Algún día me haré una partición con Windows.

Hay una opción, si no te funciona wine, te puedo crear una máquina virtua con un XP, Visual Studio 2008 y las frameworks de windows mobile, xna y silverlight montadas. Investiga y dime qué versiones te funcionan de vmWare o VirtualBox (preferiblemente el primero, que me encantan los snapshots). Eso sí, ocupará unos 4 gigas, te la subo a megaupload con la premium desde el curro y te la bajas tú con la premium desde donde quieras. Otra opción es dártela en mano, finales de octubre subo a valencia, noviembre a barcelona. Ale.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Thylzos en 25 de Septiembre de 2009, 21:58
Pueeees... la versión 6.5.3 (la última, vamos) de vmWare me va bien. Si no te es mucho curro, mejor por megaupload, que no creo que pueda esperar hasta finales de octubre para empezar a tocar xD

Gracias *.*
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 25 de Septiembre de 2009, 21:59
Cita de: Thylzos en 25 de Septiembre de 2009, 21:58
Pueeees... la versión 6.5.3 (la última, vamos) de vmWare me va bien. Si no te es mucho curro, mejor por megaupload, que no creo que pueda esperar hasta finales de octubre para empezar a tocar xD

Gracias *.*

No me es mucho curro. Ok. Pero te esperas al lunes, que necesito el ancho de banda del curro para no morirme xD
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Thylzos en 25 de Septiembre de 2009, 22:00
Hasta el lunes sí creo que podré esperar xD
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 26 de Septiembre de 2009, 00:29
Cita de: Gambit en 25 de Septiembre de 2009, 18:09
Cita de: neoprogram en 25 de Septiembre de 2009, 18:07
Cita de: Gambit en 25 de Septiembre de 2009, 18:06
Cita de: neoprogram en 25 de Septiembre de 2009, 18:04
¿El Visual Studio 2008 Professional Edition también valdría? (supongo que sí, pero por asegurar...)

De sobra, es el que uso yo. Dentro de poco sale la versión 2010 (hay una beta) y ya por fin la .NET 4.0

Comprobaré el e-academy por si acaso, pero la última que ví era esa: Visual Studio 2008 Professional Edition (x86 and x64 WoW) - DVD (English)

Yo tengo uno, son dos dvds y su correspondiente medicina, me da cosita subirlo... pero no vives lejos, todavía funcionan las grabadoras o los pendrives.

Creo que no va a hacer falta. Parece que se han instalado bien y funcionan correctamente tanto el VS como la MSDN Library (aunque no podré estar seguro del todo hasta que programe algo que funcione)
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 26 de Septiembre de 2009, 00:30
Cita de: neoprogram en 26 de Septiembre de 2009, 00:29
Cita de: Gambit en 25 de Septiembre de 2009, 18:09
Cita de: neoprogram en 25 de Septiembre de 2009, 18:07
Cita de: Gambit en 25 de Septiembre de 2009, 18:06
Cita de: neoprogram en 25 de Septiembre de 2009, 18:04
¿El Visual Studio 2008 Professional Edition también valdría? (supongo que sí, pero por asegurar...)

De sobra, es el que uso yo. Dentro de poco sale la versión 2010 (hay una beta) y ya por fin la .NET 4.0

Comprobaré el e-academy por si acaso, pero la última que ví era esa: Visual Studio 2008 Professional Edition (x86 and x64 WoW) - DVD (English)

Yo tengo uno, son dos dvds y su correspondiente medicina, me da cosita subirlo... pero no vives lejos, todavía funcionan las grabadoras o los pendrives.

Creo que no va a hacer falta. Parece que se han instalado bien y funcionan correctamente tanto el VS como la MSDN Library (aunque no podré estar seguro del todo hasta que programe algo que funcione)

Prueba algo sencillo, el ejemplo del videotutorial sirve. Y si no, directamente una aplicación windows forms, y arrastras un label o un botón, y pruebas a jugar.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 26 de Septiembre de 2009, 00:57
Anda, si el entorno este es como el del Visual Basic  :cool: ...
parece que mi etiqueta que informa del número de veces que pulsas un botón (gran programa  :wiiiiii:) funciona correctamente  ^^:
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Maik en 26 de Septiembre de 2009, 12:28
Yo para el día 7 tengo que entregar una lista de 35 ejercicios chorras de ese pelo:

Pulsar un bóton y salga un mensaje por pantalla,
Introducir un Nombre y los Apellidos en dos cajas de texto separadas y se visualicen en un label o en otra caja de texto sin permiso de escritura,
Un formulario con la lista de los jugadores del Athletic, del Barcelona, del Madrid, del Villareal y del Valencia y mediante el DoubleClick, se vayan añadiendo a otra lista de nombre Selección, controlando que no se repitan y no supere el contador de 11.

Ahora precisamente estaba liado con un formulario para una "Tienda de Animales" donde se venden Monos, Burros, Tortugas y Palomas, las unidades que desees, al precio ubicado en una lista sin visibilidad en tiempo de ejecución. Hace Arqueo de Caja y hay una ImgBox que cambia según el animal que tengas seleccionado en ese momento.
Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: Bill en 28 de Septiembre de 2009, 21:28
1. Hola Mundo

En este capítulo vamos a ver el Hola Mundo, dado que no hacerlo sería tacharme de hereje. Sin embargo, lo he hecho en forma de un videotutorial de 18 minutos. ¿Por qué tanto tiempo para un simple Hola Mundo? Porque he aprovechado para explicar un poco el entorno, lo que es una solución como conjunto de proyectos, agregar proyectos a una solución, explorador de soluciones, explorador de propiedades... Y lo más importante, para ver las posibilidades de .NET. En esta lección veréis no uno, sino hasta 5 Hola Mundos diferentes:

- En modo consola
- En interfaz gráfica con Windows Forms
- En interfaz gráfica con WPF
- En web con ASP.NET
- Dispositivos móviles con la Compact Framework

Y bueno, esta lección es de ver y escuchar, no hay nada más, así que no me alargo... Aquí la tenéis:

http://www.screencast.com/t/uxO6CLV3iCN

Analizando la estructura de un programa

Si nos fijamos en el programa básico de Hola Mundo que hemos hecho para modo consola, deberíamos tener el entorno con el siguiente aspecto:

(http://img39.imageshack.us/img39/1894/holamundoconsola.th.jpg) (http://img39.imageshack.us/img39/1894/holamundoconsola.jpg)

El código que tenemos será:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HolaMundoConsola
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hola Mundo");
            Console.ReadLine();
        }
    }
}


Vamos a analizarlo por partes.

En primer lugar nos encontramos con varias directivas "Using". Dicha directiva se utiliza para que nuestro programa pueda utilizar el contenido de un espacio de nombres. ¿Qué es un espacio de nombres? Es un sistema de organización jerárquica y en forma de árbol de las clases, tipos y constantes que podemos emplear en un programa. Por ejemplo la primera que vemos es "Using System", indicando al programa que utilice el espacio de nombres System. El espacio de nombres System contiene clases fundamentales y clases base que definen tipos de datos de referencia y de valor de uso frecuente, eventos y controladores de eventos, interfaces, atributos y excepciones de procesamiento. En nuestro programa lo necesitamos explícitamente porque contiene a la clase Console, que es la que representa a las secuencias de entrada, salida y error estándar de las aplicaciones de consola.

Vemos que además nos incluye automáticamente tres espacios de nombres más: "System.Collections.Generic", "System.Linq" y "System.Text". Como dije, la estructura es en forma de árbol, de forma que System contiene otros espacios de nombres que pueden ser invocados. Por defecto se nos añaden aparte estos tres porque contienen clases de uso bastante común (aunque en el caso de Linq es discutible...). En realidad en nuestro programa son prescindibles dado que no se usan para nada.

Tras definir los espacios de nombres que utilizamos, vemos que la siguiente línea es "namespace HolaMundoConsola". Esta línea indica en qué espacio de nombres se incluirá todo lo que declaremos, para meterlo en esa estructura jerárquica y poder reutilizarlo en un futuro. De esta forma indicamos que el espacio de nombres de nuestras clases se llamará HolaMundoConsola. Esta instrucción también es opcional, podríamos desarrollar nuestra clase sin incluirla en un espacio de nombres.

Ahora es cuando comienza nuestra clase, dónde la definimos. El código de la clase es:

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hola Mundo");
            Console.ReadLine();
        }
    }


Vemos que lo primero que se hace es definir el nombre de la clase con "class Program". Esto indica que estamos creando una clase y que se llamará Program. Siempre irán sus llaves de inicio y fin para indicar el contenido de la clase. Por defecto al crear una aplicación de consola nos genera automáticamente un método llamado Main que recibe como parámetro un vector de argumentos de texto:

        static void Main(string[] args)
        {
        }


Es el punto de entrada de la clase, que indica que es lo que se debe ejecutar cuando se ejecuta la aplicación.
Toda aplicación C# debe contener una clase que posea un método Main. No importa cual sea la clase que lo contenga, por ejemplo podemos tener un millón de clases en un programa pero al menos una de ellas debe poseer este método para que al ejecutar el programa se sepa por dónde empezar a ejecutar. Dicho método siempre será público y estático, que son cosas que daremos más adelante pero que algunos ya entenderéis lo que significa: lo primero es que la visibilidad del método debe ser pública para que se vea desde fuera de la clase y que sea estático significa que la clase no necesita ser instanciada para poder invocar al método. Vemos que hay una palabra llamada "void", eso significa que el método no devuelve nada (los que vengáis de pascal significa que es un procedimiento en lugar de una función, después de todo un procedimiento es simplemente una función que no devuelve nada). Y además vemos que recibe "string[] args", eso significa que recibe un vector o lista de argumentos de texto, representando que en una aplicación de consola el usuario puede especificar parámetros cuando la ejecuta, y así pueden ser capturados e interpretados.

Por último el contenido del método Main:
    Console.WriteLine("Hola Mundo");
            Console.ReadLine();


Es lo que verdaderamente hace el programa. Invoca al método WriteLine() de la clase Console, que es el método para escribir una línea en pantalla de consola con un retorno de carro al final. Luego el método ReadLine() que lo que hace es leer una línea que introduzcamos y que en este caso sirve para esperar a que el usuario pulse intro. Los paréntesis son necesarios porque indican que se trata de un método y no de una propiedad de la clase.

Título: Re: Curso de Programación Lúdica: Primer Libro Finalizado
Publicado por: neoprogram en 28 de Septiembre de 2009, 22:06
Que dulce y melodiosa voz....  *.*

Gracias por la lección ^^:
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Bill en 29 de Septiembre de 2009, 14:13
En fin... Thylzos, lo de subirte la máquina virtual está jodido  :gñe:
Con lo que estamos dando ahora puedes tirar con Mono, o bien puedes instalar vmWare, montar un XP y sobre él montas el Visual Studio. Eso sí, cuando lleguemos a lo de XNA te va a ir como el culo en vmWare... si fuese tú me plantearía crear una partición con juindous.
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Thylzos en 29 de Septiembre de 2009, 16:24
Lo estuvo posponiendo mucho tiempo, ya ha llegado la hora de hacerlo.

Tendré que crear una partición con Windows :llori:
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Maik en 29 de Septiembre de 2009, 21:07
Para los interesados.

http://www.cientoseis.es/index.php?topic=16805.0
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Bill en 29 de Septiembre de 2009, 21:18
Eres un crack  :gñe:

(ahora habrá que subir la beta del visual studio 2010  :lol:)
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Bill en 09 de Octubre de 2009, 14:33
2. Sistema de tipos (Parte I : Definición y Clasificación)

Lo primero es entender lo que es un tipo. Cualquier cosa que en nuestro programa queremos que tenga un valor, debe tener un tipo. Ya está explicado en el libro anterior, pero repetimos.

Suponed que queremos una variable para almacenar la cantidad de alumnos de una aula del colegio. Sabemos que en una aula del colegio no habrán más de 100 alumnos, y además que es un número natural (entero sin signo), dado que no vamos a tener nunca 32 alumnos y medio o similares. Entonces podríamos guardar la cantidad de alumnos en un tipo Byte, que es un número natural de 0 a 255. Pero, ¿y para el total de alumnos de un colegio? Un colegio tiene muchas aulas y en cada una alumnos, pero el total será mayor de 255 así que el Byte no nos sirve... De nuevo sabemos que es un número natural, pero en este caso mayor, y el siguiente mayor al byte es el tipo que posee dos bytes, entero y sin signo, que es el ushort (unsigned short) que puede valer desde 0 hasta 65535.

Eso serían tipos simples, pero existen más tipos que definen los usuarios. Por ejemplo podríamos definir enumerados, que son tipos que contienen un número finito y conocido de opciones, por ejemplo los meses del año sería un enumerado que contiene enero, febrero, marzo, abril, mayo, junio, julio, agosto, septiembre, octubre, noviembre y diciembre. De esta forma si definimos un enumerado para los meses cualquier variable que sea de ese tipo tendrá que valer forzosamente uno de los valores permitidos.

Para estructurar la lección he realizado un pequeño árbol de tipos, con su clasificación, que procederé a explicar.

(http://img83.imageshack.us/img83/8710/arboltipos.jpg)

La primera distinción que vemos es en tres grupos: tipos valor, tipos referencia y punteros.
Los tipos valor son aquellos en los que el contenido es tal cual el valor de lo que se quiere, es decir, cuando se declara una variable de dicho tipo ya se sabe cuánto ocupará físicamente.
Los tipos referencia son aquellos que no contienen el valor, sino una referencia a dónde se encuentra, y sirven para variables cuyo gasto de memoria no es mesurable desde el momento de la compilación, como por ejemplo una cadena de caracteres (string) que puede valer desde "hola" hasta un libro entero si queremos. Los objetos son tipos referencia también.
Los punteros son direcciones a una posición de memoria, y no se pueden emplear directamente en .NET, sino que se usan en su modo inseguro (unsafe mode) que no daremos hasta el final del curso, así que por ahora no les daremos la más mínima importancia.

Tipos Valor

Como dijimos, son aquellos que contienen directamente el valor. Se subdividen en tipos estructurados y enumerados.

Tipos Estructurados

Son los tipos más básicos y más empleados del lenguaje, y se subdividen en numéricos (contienen valores numerables), booleanos (tipo bool, valor lógico que puede valer cierto o falso) y definidos por el usuario.

En el caso de los definidos por el usuario son los llamados tipos "struct" de C o los "record" de Pascal. Básicamente el usuario puede definir una estructura que contiene a otros tipos. De esta forma un usuario podría declarar una estructura para almacenar varios datos de una misma cosa, un ejemplo sería un hilo del foro, del cual podemos almacenar datos como número de posts, número de visitas, fecha de creación, fecha de último post, nombre del creador, nombre del hilo, link y sección.

Los booleanos, a pesar de poseer dos valores diferenciados que solemos asociar a 0 y 1, no son numéricos como tal debido a su función lógica que los hace totalmente distintos.

Dentro de los numéricos existen los enteros (poseen un valor entero o natural), los de coma flotante (contienen un valor decimal de coma flotante) y los decimal que poseen un trato especial a pesar de que la lógica nos dice que corresponderían a la sección de coma flotante. Sin embargo esto no es así porque los decimales están diseñados para ser terriblemente precisos en sus valores. Mientras en los de coma flotante se produce un redondeo si se excede su precisión, los decimales son exactos, es decir, de cada valor podemos conocer el siguiente y no hay redondeo. Cuando se define un número decimal y se le quiere asignar un valor con decimales se debe poner una letra "m" detrás para indicar que ese valor es decimal y no de coma flotante. Esto es importante, porque existe el casteo directo entre tipos enteros y decimales, pero no entre tipos de coma flotante y decimales.

Como nota, los char son enteros a pesar de que representen letras, dado que sus valores internos son numerables.

Tipos Enumerados

Como vimos, sirven para definir un tipo en el cual hay una cantidad finita y conocida de posibles valores (ya puse el ejemplo de los meses del año, también serviría para los días de la semana).

Tipos Referencia

En el espacio de nombres System nos vienen definidos varios tipos referencia importantes. El más importante de ellos es la clase Object. Cualquier clase que definamos en nuestros programas tiene como ancestro más lejano a Object, es decir, es el padre de toda la estructura de objetos, se podría decir que es el Adán de las clases.
De Object desciende otra clase de gran importancia: String. String sirve para representar a una cadena de caracteres, y también es muy usada.
Vemos que hay varios subtipos de tipos referencia. El primero es el array, que es una lista de objetos (hay que tener en cuenta que todo es un objeto en .NET).
Luego la clase, que nos sirve para definir los objetos.
Luego los interfaces, que dan un esqueleto abstracto que los objetos que implementan dicho interfaz deben cumplir. Pongamos un ejemplo, todos los reproductores de media que conocemos poseen unos ciertas funcionalidades en forma de botonera: play/pause, stop, ir hacia delante, ir hacia atrás, anterior y siguiente. Esto es independiente de si lo que reproducimos es un sonido o un vídeo, pero está claro que la funcionalidad interna no es la misma. Esas funciones pertenecerían al interfaz, y las clases que implementásemos para reproducir sonidos y vídeos implementarían dicho interfaz rellenando la funcionalidad.
Y por último los delegados, que son una forma de utilizar métodos como si fuesen variables.

Valores de los tipos básicos

(http://img266.imageshack.us/img266/7584/tiposvalores.jpg)


Luego grabaré el resto de la lección y la podéis ver y oír ;) Esto es para abrir boca.


Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: neoprogram en 21 de Octubre de 2009, 17:32
 *.* queremos más....  *.*
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Faerindel en 22 de Octubre de 2009, 01:48
Esperamos al vídeo. Si eso cuando te puedas salir del monasterio mocosofístico y eso... Y algo de tarea vendría bien.
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Bill en 22 de Octubre de 2009, 09:12
Cita de: Faerindel en 22 de Octubre de 2009, 01:48
Esperamos al vídeo. Si eso cuando te puedas salir del monasterio mocosofístico y eso... Y algo de tarea vendría bien.

Lo sé :( Pero la transformación a siervo de Microsoft me está consumiendo.
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: cokycastillo en 29 de Octubre de 2009, 14:04
Hola a tod@s!

aunque no se si hay muchas chicas en este hilo...

Me presento y espero poder cogeros en poco tiempo ya que empiezo el curso un poco tarde :lol:

Saludos!

cokycastillo
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: danyof en 12 de Noviembre de 2009, 15:35
Creo que hablo en nombre de todos/as cuando digo....

Gambit vuelve!! pero que sea antes de navidad!! :)
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: neoprogram en 12 de Noviembre de 2009, 20:34
Es verdad, que ahora que en cierta clase me dicen que no se C ni java, me vendría bien aprender C#...  :llori:
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: neoprogram en 27 de Noviembre de 2009, 02:07
Cita de: neoprogram en 12 de Noviembre de 2009, 20:34
Es verdad, que ahora que en cierta clase me dicen que no se C ni java, me vendría bien aprender C#...  :llori:
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: danyof en 27 de Noviembre de 2009, 15:35
¿¿??
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Bill en 27 de Noviembre de 2009, 16:42
Ah, perdón... lo siento. Mi nivel de informática no es suficiente para estos menesteres. Eso es algo que he aprendido de grandes maestros como El Brujo, por tanto en una "charla" con él en otro hilo prometí que no volvería por la sección de informática. Dado que él es tan bueno y tan listo, veo conveniente que sea él quien prosiga el curso, dado que a su lado no soy más que un mero gusano. Las lecciones las he seguido haciendo, pero existiendo por aquí gente tan pro como él no veo adecuado el lugar, en cualquier caso si a alguien le interesa el curso dado por un inepto en desarrollo informática como yo, que me lo haga saber y lo continúo en un foro alternativo que no sea este.

Un saludo: Gambit.
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Superjorge en 27 de Noviembre de 2009, 17:23
Cita de: Gambit en 27 de Noviembre de 2009, 16:42
Ah, perdón... lo siento. Mi nivel de informática no es suficiente para estos menesteres. Eso es algo que he aprendido de grandes maestros como El Brujo, por tanto en una "charla" con él en otro hilo prometí que no volvería por la sección de informática. Dado que él es tan bueno y tan listo, veo conveniente que sea él quien prosiga el curso, dado que a su lado no soy más que un mero gusano. Las lecciones las he seguido haciendo, pero existiendo por aquí gente tan pro como él no veo adecuado el lugar, en cualquier caso si a alguien le interesa el curso dado por un inepto en desarrollo informática como yo, que me lo haga saber y lo continúo en un foro alternativo que no sea este.

Un saludo: Gambit.

Vamos hombre no me jodas Peluche
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Genki en 29 de Noviembre de 2009, 15:17
Peluche, sé racional y piensa... eres mayorcito para pasar de lo que te diga El Brujo...
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: danyof en 29 de Noviembre de 2009, 18:42
Eso mismo pienso yo. No se que movidas habreis tenido... pero eso de ahora no hago el curso porque me enfado me suena a niño de parbulario, sin animo de ofender por supuesto!

A mi me gustaria que el curso continuara, fuese aqui o en algun otro sitio.
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: neoprogram en 30 de Noviembre de 2009, 04:41
Cita de: danyof en 29 de Noviembre de 2009, 18:42
A mi me gustaria que el curso continuara, fuese aqui o en algun otro sitio.

Si... además, echo de menos la voz de enseñar en los cursos de Peluche  *.*
Título: Re: Curso de Programación Lúdica: Libro II, Aprendiendo C#, Capítulo 2: Hola Mundo
Publicado por: Bill en 12 de Abril de 2010, 14:56
3. Scroll horizontal 2D multicapa

A ver si se entera Penguin, que no me quedé muy convencido  :gñe:

Vamos con algo fácil de digerir y muy utilizado en juegos 2D. En este caso se trata del scroll horizontal 2D multicapa, es decir, que exista una localización "larga" en la que nos podemos desplazar en horizontal y que existan varias capas en el fondo que se desplacen a velocidades diferentes para dar la sensación de profundidad.

Lo primero que hay que entender es el concepto de profundidad y su relación con la transparencia. Las capas serán gráficos independientes (en nuestro caso en png) que contendrán información de transparencia. De no utilizar un formato de gráfico con transparencias, existen opciones alternativas como decidir un color como transparente el cual no se pintará o utilizar otro gráfico como capa alpha que llevará información binaria de lo que se pintará y lo que no. En nuestro caso, al utilizar png como formato gráfico, la transparencia va incluída en el gráfico así que no necesitamos nada más. ¿En qué orden hay que pintar las capas? Siempre las más alejadas se pintan primero, para que las más cercanas se superpongan. Sencillo y para todos los públicos.

Además hay que entender lo que es el punto de vista, lo que sería la zona de proyección. Vamos a verlo con un ejemplo gráfico:

(http://img710.imageshack.us/img710/6097/viewport.jpg)

Vamos a explicarlo. Por una parte tenemos el escenario, que mide 400px de altura y 4000px de ancho. Por otra parte tenemos el punto de vista, que es lo que se pinta en pantalla, y que en este caso tendrá la misma altura que el escenario (dado que es un scroll horizontal puro, si no tuviesen la misma altura existiría también scroll vertical) y de ancho 500px. Entonces en cada momento se pintará solamente un trozo del escenario. El punto inicial es en el que x=0, con lo que estamos mostrando el trozo desde la x=0 hasta la x=499 del escenario. El punto máximo es en el que x=3500 dado que estaremos mostrando el trozo desde la x=3500 hasta la x=3999 del escenario, el cual es de 4000px de ancho, con lo cual si nos fuésemos un poco más hacia la derecha se mostraría vacío.

Ahora mismo sabemos (funcionalmente) cómo mostrar un trozo de un escenario estático. ¿Cómo se hace para tener varias capas y que den sensación de profundidad?. Vamos a pensar en 4 capas:
- La más cercana es el suelo
- Luego vienen unas montañas
- Luego unas nubes
- Por último unas nubes más alejadas y el cielo.

Todas las capas deben tener la misma altura (dado que no tenemos scroll vertical), pero... ¿deben tener el mismo ancho? Si todas tuviesen el mismo ancho no existiría sensación de profundidad, todas se moverían a la misma velocidad y a la par, así que habría sensación de movimiento horizontal pero con un fondo estático, que sería lo mismo que tener una única imagen con las 4 capas superpuestas. La capa que se debe mover a mayor velocidad es la más cercana al punto de vista, con lo cual el suelo, las montañas deben moverse un poco más lento pero más rápido que las nubes, y las nubes un poco más rápido que las nubes alejadas. Para conseguir este efecto las capas más alejadas tendrán un ancho menor.

Para nuestro ejemplo utilizaremos los siguientes gráficos:

Sorry but you are not allowed to view spoiler contents.


Así que tenemos:
- Suelo.png: 400x4000px
- Montana.png: 400x3000px
- Nubesfrente.png: 400x2000px
- Nubesfondo.png: 400x1500px

Ahora es cuando llega la formulación matemática: dada una posición x en la que estamos, ¿qué posición x tenemos en cada una de las capas? Con suelo.png lo tenemos solucionado porque es la capa más cercana, con lo cual es la de referencia. Para todas las demás se usará una regla de 3, pero ¡ojo! ¡No una regla de tres con la longitud total! Es decir, en el punto 0 todas las capas tendrán desplazamiento 0, pero el punto máximo no es 3999px sino 3500px, dado que de desplazarnos más a la derecha se verían vacíos. Entonces:

Dado un ancho refWidth de la capa de referencia, un ancho viewWidth del punto de vista, un ancho layerWidth de la capa que queremos calcular el desplazamiento, y una posición actual actualX, el cálculo del desplazamiento de la capa en cuestión será:

despX = actualX*(layerWidth-viewWidth)/(refWidth-viewWidth);

Esta fórmula, como podemos comprobar, para la capa de referencia siempre nos da que despX = actualX.

Programando el scroll con Visual Studio C# en WindowsForms

1. Vamos a crear el proyecto. Abrimos Visual Studio y seleccionamos Archivo -> Nuevo -> Proyecto. Seleccionaremos Aplicación de Windows Forms y pondremos el nombre del proyecto y solución (en nuestro caso, TestScroll2D). Y hacemos click en Aceptar

(http://img231.imageshack.us/img231/7687/captura1nw.jpg)

Esto lo que hace es crearnos el código inicial de la solución y el proyecto, además del formulario por defecto.

2. Hacemos click en el formulario que nos ha creado para ver la paleta de propiedades. En el caso de que no nos aparezca la ventana de propiedades, hacer click en Ver -> Ventana Propiedades. Aquí es dónde vemos las propiedades de nuestra ventana, que será lo que se muestre al usuario. Nos vamos a la propiedad Text y la cambiamos por Test Scroll 2D, y a la propiedad Size y la cambiamos por 500; 400. Esto hará que la ventana tenga las proporciones que le hemos marcado.

(http://img169.imageshack.us/img169/4051/captura2x.jpg)

Si ahora pulsamos F5 (compilará y ejecutará el programa) veremos lo siguiente:

(http://img10.imageshack.us/img10/2764/captura3j.jpg)

3. El programa se ha compilado en el path en el que tengamos el proyecto, y bin/debug. En ese mismo path, en el que veremos el ejecutable de nuestro programa al que podemos hacer doble click y ejecutarlo desde ahí para comprobar, copiamos las imágenes con los nombres correctos (ojo, no es montanau.png, sino montana.png, aseguraos de que los nombres son correctos).

(http://img22.imageshack.us/img22/3179/captura4g.jpg)

4. Vamos a comenzar a programar. En el explorador de soluciones, dónde vemos Form1.cs, damos click con el botón derecho del ratón y elegimos Ver Código. Se nos abrirá una pestaña en la que veremos el código profabricado de nuestra aplicación. Lo primero que se ve son los using, que son las bibliotecas a las que se hacen referencia.

(http://img341.imageshack.us/img341/6598/captura5a.jpg)

Por ahora vamos a dejar los using como están. Luego vemos la declaración del namespace, que es el nombre de la biblioteca en el que incluímos nuestro código. Y debajo la declaración de la clase Form1 como heredera de la clase Form y además indicando que es parcial (partial). ¿Qué significa esto de parcial? Pues que lo que vemos no es todo el código de la ventana, se nos está mostrando solamente parte del código para no liarnos. El resto del código está en Form1.Designer.cs, y contiene información visual de los componentes. Dentro de la clase vemos el constructor:

Citarpublic Form1()
        {
            InitializeComponent();
        }

Toda clase tiene un constructor, que es lo primero a lo que se invoca cuando se crea una instancia de dicha clase. Ya os iréis acostumbrado a los conceptos de clase e instancia con su uso.

5. Vamos a cargar las imágenes. Para ello tenemos la clase Bitmap. Toda clase se instancia con la palabra "new" y el constructor de la clase. Ponemos este código dentro de la clase Form1 y antes de su constructor:

Citarprivate Bitmap btmNubesFondo = new Bitmap("nubesfondo.png");
        private Bitmap btmNubesFrente = new Bitmap("nubesfrente.png");
        private Bitmap btmMontana = new Bitmap("montana.png");
        private Bitmap btmSuelo = new Bitmap("Suelo.png");

Analicemos una de ellas:
Sorry but you are not allowed to view spoiler contents.


La primera palabra, private, indica la visibilidad que tiene lo que estemos declarando, en este caso private indica que solamente será visible para la clase en la que está declarada. Otros tipos comunes de visibilidad son protected, que indica que lo puede ver la clase y sus descendientes, y public que indica que el acceso no está restringido. En nuestro caso son campos que solamente utilizará nuestra clase, con lo que el acceso privado es el recomendado.
La segunda palabra, Bitmap, es una clase que se encuentra en la biblioteca System.Drawing y que representa a una imagen.
La tercera palabra, en este caso btmNubesFondo, es el nombre que le damos a nuestro campo (un equivalente a las variables).
Luego tenemos un signo igual seguido de la palabra new que indica la creación de clase, y Bitmap("nubesfondo.png") que es el constructor de la clase en el que le indicamos que cargue el fichero "nubesfondo.png" alojado en el mismo sitio que el ejecutable que se genere.

6. Declaramos el rectángulo visible que se pinta en la pantalla, el rectángulo correspondiente a la capa de referencia completa y la X actual en la que nos encontramos con respecto a la capa de referencia:

Citarprivate Rectangle viewRect;
        private Rectangle referenceRect;
        private int actualX;

Como vemos, no los estamos inicializando. Eso lo hacemos en el constructor de la clase, en el cual ya tendremos todos los datos necesarios:

Citarpublic Form1()
        {
            InitializeComponent();
            DoubleBuffered = true;
            viewRect = new Rectangle(0, 0, Width, Height);
            referenceRect = new Rectangle(0, 0, btmSuelo.Width, btmSuelo.Height);
            actualX = 0;
        }

La primera sentencia, la del DoubleBuffered=true, es para indicarle a la ventana que a la hora de pintar tenga doble buffer, es decir, que no haya parpadeos gordos desagradables, sino que pinta en una segunda versión duplicada en la memoria de vídeo y cuando termina de pintar en esa versión es cuando lo pasa a la zona de memoria visible de pantalla.
Luego creamos el viewRect, nuestro rectángulo de vista, iniciando en el punto 0,0 de la ventana, y con ancho el ancho de la ventana (Width) y alto el alto de la ventana (Height). Así tendremos definido un rectángulo en el punto (0,0) con ancho 500 y altura 400 en nuestro caso.
Luego creamos el referenceRect, el rectángulo de la capa de referencia, iniciado en el punto 0,0 de la imagen de referencia y con su mismo ancho y alto.
Por último indicamos que estamos en la x=0.

Todavía nuestra aplicación no está haciendo nada adicional, simplemente carga los gráficos e inicializa cosas.

7. Vamos a declarar un método (una función de clase) que se encargue de pintar una capa calculando su desplazamiento con respecto a las fórmulas que vimos antes. A este método le llamaremos PaintLayer, y aquí está su implementación:

Citarprivate void PaintLayer(Graphics graphics, Bitmap layer)
        {
            int layerX = actualX * (layer.Width - viewRect.Width) / (referenceRect.Width - viewRect.Width);
            Rectangle layerRect = new Rectangle(layerX, 0, viewRect.Width, viewRect.Height);
            graphics.DrawImage(layer, viewRect, layerRect, GraphicsUnit.Pixel);
        }

Los parámetros que se pasan a este método son un graphics y un layer, graphics es dónde pintamos y layer es la imagen que vamos a pintar (la capa).
Como vemos, calculamos layerX con respecto a la fórmula que vimos antes, y definimos un rectángulo, que será el que se pintará de la capa en cuestión, con el desplazamiento en las x de layerX, ningún desplazamiento en el eje Y, y con el alto y ancho de la vista.
Al final se invoca al DrawImage del graphics que se le está pasando, que por ahora no hace falta que lo entendais, pero se le pasa una imagen a pintar, un rectángulo de destino, un rectángulo de origen de la imagen y el modo de pintado.

8. Muy bien, tenemos los gráficos cargados, las vistas inicializadas, tenemos un método para pintar una capa en concreto... ¿y dónde pintamos? Hemos visto propiedades, hemos visto métodos, nos quedan los eventos. Los eventos son métodos que se autoinvocan cuando sucede algo. En este caso queremos reaccionar al evento Paint del formulario. Para ello hacemos click en el formulario para que se nos muestren sus propiedades, y hacemos click en el icono del rayo, que es el de eventos, buscamos el Paint y le hacemos doble click. Eso nos creará un método asociado al evento.

(http://img411.imageshack.us/img411/1811/captura6g.jpg)

Dentro del método que nos ha creado automáticamente tenemos que hacer que llame a nuestro método para pintar capas para cada capa, y que los pinte en la región de gráficos que se nos pasa al evento en sus argumentos de evento como e.Graphics:

Citarprivate void Form1_Paint(object sender, PaintEventArgs e)
        {
            PaintLayer(e.Graphics, btmNubesFondo);
            PaintLayer(e.Graphics, btmNubesFrente);
            PaintLayer(e.Graphics, btmMontana);
            PaintLayer(e.Graphics, btmSuelo);
        }

Ahora ya tenemos algo, cuando arrancamos la aplicación se llamará al evento Paint, con lo que se nos pintará lo que sería el punto de vista para la x = 0.

(http://img17.imageshack.us/img17/4513/captura7q.jpg)

9. Vamos a añadir movimiento. Primeramente vamos a definir una función que dada una representación de una tecla, haga algo si dicha tecla se corresponde con la flecha derecha, algo si se corresponde con la flecha izquierda y además responda si se trataba de una de dichas teclas.

Citarprivate bool ProcessKeyDown(Keys keyCode)
        {
            switch (keyCode)
            {
                case Keys.Left:
                    {
                        if (actualX > 5)
                        {
                            actualX -= 5;
                            Invalidate();
                        }
                        return true;
                    }
                case Keys.Right:
                    {
                        if (actualX < referenceRect.Width - viewRect.Width-5)
                        {
                            actualX += 5;
                            Invalidate();
                        }
                        return true;
                    }
            }
            return false;
        }

Aquí vemos la introducción al Switch, un tipo de sentencia que nos permite comprobar los distintos valores que puede tomar un campo y ejecutar código diferente según el valor. En nuestro caso vamos a mover con incrementos de 5 píxeles, que aunque aquí está puesto a "fuego" debería ir en un campo o una constante externa definible. Por tanto podemos movernos a la izquierda siempre que existan 5 pixeles de holgura, y podremos movernos a la derecha siempre que no se exceda el máximo de visualización de la capa base según definimos antes (si la capa mide 4000px y el rectángulo de vista 500px, el máximo punto será el 3500). En caso de que sea una de dichas teclas, se devuelve true y se sale del método, en caso contrario se devuelve false.

Pero, ¿cómo interceptamos las teclas? De nuevo es un evento, en este caso el KeyDown del formulario.

(http://img28.imageshack.us/img28/5472/captura8l.jpg)

En ella debemos invocar al método que hemos definido:

Citarprivate void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = ProcessKeyDown(e.KeyCode);
        }

Conclusión
Con esto queda terminada una aplicación que permite utilizar las teclas direccionales izquierda y derecha para movernos por el scroll, y en el que vemos la sensación de profundidad en base a 4 capas, quedando además suficientemente genérico como para que dichas capas puedan ser sustituidas por otras cualesquiera. Un ejemplo del scroll cuando x = 300:

(http://img34.imageshack.us/img34/384/captura9q.jpg)

Espero que haya quedado claro el concepto de scroll horizontal, en realidad el vertical funciona exactamente de la misma manera, y el mixto (scroll horizontal y vertical a la vez) también. Todo es entender el rectángulo de vista y las capas, y como la velocidad a las que las desplazamos no es la misma, y así con las transparencias se consigue el efecto deseado.

Subiría el código fuente y ejecutable y todo, pero no tengo acceso a megaupload.
Título: Re: Curso de Programación Lúdica. Actualmente: Scroll horizontal 2D multicapa
Publicado por: Bill en 12 de Abril de 2010, 17:23
El código fuente, imágenes y compilado subido a megaupload por cortesía de Clave:

http://www.megaupload.com/?d=TU5T0B6C

Lo siguiente que vamos a hacer va a ser poner un personaje que se mueva, con animación para simular los pasos.
Título: Re: Curso de Programación Lúdica. Actualmente: Scroll horizontal 2D multicapa
Publicado por: Bill en 12 de Abril de 2010, 20:08
4. Añadiendo un personaje a la escena.

Para este capítulo meteremos un personaje con animación. Como el scroll lo estamos haciendo en ambas direcciones, meteremos dos animaciones del personaje: una caminando hacia la izquierda y otra caminando hacia la derecha. En este caso las siguientes:

(http://img215.imageshack.us/img215/5140/char1walkright.png)
(http://img251.imageshack.us/img251/2340/char1walkleft.png)

Ambos son pngs con transparencia que contienen una animación en 10 frames del personaje caminando, cada png en un sentido. Cada frame ocupa un ancho de 60px, aquí es dónde los diseñadores gráficos tienen el papelón gordo de diseñar un personaje, sus posibles movimientos, gestos, etc. y guardarlos bien guardaditos en pngs de forma que se pueda extraer un frame en concreto de ellos sabiendo el cuadrado que debemos cortar mediante fórmulas matemáticas. En nuestro caso tendremos una animación del frame 0 al frame 9 en la que el corte de cada frame se iniciará en la x = 60*frame con un ancho de 60px.

Comenzamos definiendo los campos que utilizaremos y cargando los dos pngs:

Citarprivate Bitmap btmChar1WalkR = new Bitmap("Char1_walk_right.png");
        private Bitmap btmChar1WalkL = new Bitmap("Char1_walk_left.png");
        private Bitmap btmActualChar;
        private int widthCharFrame = 60;
        private int numFramesChar;
        private int actualCharFrame;

Como en el punto anterior, estamos cargando las dos animaciones en bitmaps llamados btmChar1WalkR y btmChar1WalkL, definimos un campo btmActualChar que indicará cual de los dos estamos utilizando en este momento para saber de cual de los dos pintar según la dirección hacia la que se vaya, widthCharFrame indica el ancho en píxeles de cada frame dentro del png, numFramesChar se calculará en función del ancho de los pngs y el ancho de cada frame, y actualCharFrame nos indica el número de frame en el que nos encontramos ahora mismo, que irá desde 0 hasta numFramesChar-1.

Hacemos las inicializaciones en el constructor de Form1 de acuerdo con esto último que hemos dicho, inicializando la dirección del personaje hacia la derecha:

CitarnumFramesChar = btmChar1WalkR.Width / widthCharFrame;
            actualCharFrame = 0;
            btmActualChar = btmChar1WalkR;

Igual que tenemos un método para pintar una capa definiremos un método para pintar un frame del personaje, en el que utilizaremos un rectángulo para cortar el trozo que nos interesa del png del personaje y otro rectángulo para saber dónde ponerlo:

Citarprivate void PaintChar(Graphics graphics, Bitmap layer)
        {
            Rectangle layerRect = new Rectangle(actualCharFrame * widthCharFrame, 0, widthCharFrame, layer.Height);
            Rectangle outputRect = new Rectangle(60, viewRect.Height-layerRect.Height-60, layerRect.Width, layerRect.Height);
            graphics.DrawImage(layer, outputRect, layerRect, GraphicsUnit.Pixel);
        }

El primer rectángulo, el de la capa, se inicia en la x = frameActual*anchoDeFrame, con y=0, con ancho = anchoDeFrame y con altura el del png.
El segundo rectángulo es dónde pintamos, y hacemos que sea en la x = 60 (desplazarlo un poco desde el borde), calculamos una y adecuada con respecto al alto de la vista menos el alto del personaje y menos un poco para que se vea bien en el suelo,y el ancho y alto será el del trozo que cortamos del personaje, es decir, el de un frame, y dibujamos igual que hacíamos con la capa.

En el evento Paint del Form1, donde pintamos las capas, al final añadimos que pinte al personaje:

CitarPaintChar(e.Graphics, btmActualChar);

Ahora vamos a por las teclas. Ahora cuando se pulsa la tecla izquierda, si el personaje no mira hacia la izqueirda tenemos que hacer que mire, es decir, asignar btmActualChar = btmChar1WalkL. Recíproco para la derecha. Además debemos incrementar el número de frame y si nos pasamos regresar al frame 0 para hacer el loop de la animación:

Citarprivate bool ProcessKeyDown(Keys keyCode)
        {
            switch (keyCode)
            {
                case Keys.Left:
                    {
                        if (actualX > 5)
                        {
                            if (btmActualChar != btmChar1WalkL)
                            {
                                btmActualChar = btmChar1WalkL;
                            }
                            actualCharFrame++;
                            if (actualCharFrame >= numFramesChar)
                            {
                                actualCharFrame = 0;
                            }
                            actualX -= 5;
                            Invalidate();
                        }
                        return true;
                    }
                case Keys.Right:
                    {
                        if (actualX < referenceRect.Width - viewRect.Width-5)
                        {
                            if (btmActualChar != btmChar1WalkR)
                            {
                                btmActualChar = btmChar1WalkR;
                            }
                            actualCharFrame++;
                            if (actualCharFrame >= numFramesChar)
                            {
                                actualCharFrame = 0;
                            }
                            actualX += 5;
                            Invalidate();
                        }
                        return true;
                    }
            }
            return false;
        }

Y ya estaría. Es una animación muy primitiva debido a dos motivos:
1) No estamos comprobando los ciclos de procesador ni FPS, así que va a su bola.
2) No soy diseñador gráfico, así que el sprite no es todo lo bueno que debería. Este siempre será el mayor problema: los programadores no son lo mismo que los diseñadores gráficos, y un juego es un gran tanto por ciento visual.

(http://img263.imageshack.us/img263/9108/captura1f.jpg)

Código, gráficos y ejecutable de esta lección:

http://www.megaupload.com/?d=V5605202
Título: Re: Curso de Programación Lúdica. Actualmente: Añadiendo un personaje
Publicado por: neoprogram en 12 de Abril de 2010, 20:46
 *.* Muchas gracias.
Título: Re: Curso de Programación Lúdica. Actualmente: Añadiendo un personaje
Publicado por: Thylzos en 12 de Abril de 2010, 20:49
¡Ah!, ¡mola!, ¡sigue!

A ver si encuentro el disco de mi máquina virtual.
Título: Re: Curso de Programación Lúdica. Actualmente: Añadiendo un personaje
Publicado por: Clave en 12 de Abril de 2010, 23:33
Que mamonazo por culpa de eso me ha entrado curiosidad xD

Voy a volver a intentarlo en tener un segundo fale? *.*
Título: Re: Curso de Programación Lúdica. Actualmente: Añadiendo un personaje
Publicado por: Bill en 13 de Abril de 2010, 20:26
5. Dando más vida al personaje (I).

En este capítulo vamos a tratar de hacer un personaje con algo más de vida. En lugar de hacer un programa de scroll horizontal vamos a hacer lo que sería un plataformas, pero en habitación negra, es decir, solamente estará el personaje y un fondo negro. En el siguiente, que complementará a este, meteremos un poquito de los conceptos de tiro parabólico, inercia y velocidad. Vamos, que va a ser completita.

De nuevo, creamos una solución con un proyecto de aplicación Windows Forms, y la llamamos DarkRoom. Al formulario que nos crea por defecto le cambiamos el texto a "Dark Room" y el tamaño a 800;600.

Vamos a utilizar el siguiente fondo:
http://img140.imageshack.us/img140/6480/backgroundps.png

Ahora de nuevo cargar el gráfico e inicializar los rects básicos, con lo que la clase Form1 quedaría así:

Citarpublic partial class Form1 : Form
    {
        private Bitmap btmBackground = new Bitmap("background.png");
        private Rectangle viewRect;
        private Rectangle bgRect;

        public Form1()
        {
            InitializeComponent();
            viewRect = new Rectangle(0, 0, Width, Height);
            bgRect = new Rectangle(0, 0, btmBackground.Width, btmBackground.Height);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            PaintBackground(e.Graphics);   
        }

        private void PaintBackground(Graphics graphics)
        {
            graphics.DrawImage(btmBackground, viewRect, bgRect, GraphicsUnit.Pixel);
        }
    }

Ahora es cuando llega la labor del diseñador gráfico. En este caso escoger un personaje, dibujarlo y hacer el png, como dijimos, con transparencia, y de forma que podamos saber con alguna fórmula qué frame coger en cada momento. Para hacer un juego, el personaje tiene montones de acciones que puede realizar o estados, y para cada acción o estado tiene varios frames, y termina por convertirse en un pequeño infierno  :gñe:

Vamos a poner un ejemplo, os presento a Lucas, y Lucas puede hacer todo esto:

http://img10.imageshack.us/img10/9651/lucaskl.png

Ahí podemos ver que Lucas puede hacer muchas cosas, que el png no es transparente, que no cumple unas distancias fijas sino variables, y que además contiene errores en el sentido de que hay frames que pertenecen a otro personaje. Os paso también al otro personaje:

http://img255.imageshack.us/img255/2130/nessi.png

A partir del png que tenemos de lucas vamos a hacer un png nuevo que contenga solamente las acciones que queremos, cada fila será una acción diferente, y que cumpla las distancias y la transparencia para que sea más sencillo de tratar. Vamos a escoger tres de las acciones: old stance, run y jump. Como veis ninguno tiene el mismo número de frames, y además en jump el último frame sobra porque es el mismo que el primero. El Jump es el que tiene más frames, tiene 9, así que tendremos una rejilla de 9x3, con altura 48px y ancho 40px. Así que la imagen resultante será de 360x144. Así que con photoshop creamos la imagen, fondo transparente, le creamos una rejilla de referencia para diferenciar los rectángulos en los que se sitúa cada frame, y llevamos los frames para cada casilla. Al final guardamos el png, sin la rejilla de referencia. Así es como lo veríamos en el photoshop, con un fondo añadido en negro para saber cómo quedará en el resultado, y la rejilla:

(http://img72.imageshack.us/img72/7489/captura1xx.jpg)

Y aquí está el resultado guardado a png sin la rejilla y con fondo transparente:

(http://img576.imageshack.us/img576/5259/lucas.png)

Ahora vamos a hacer algo diferente a lo de la última vez: el personaje va a tener su propia clase. Es decir, la funcionalidad del personaje no estará en el formulario, sino que será independiente. Damos click con el botón derecho del ratón en el proyecto y escogemos Agregar -> Clase y la llamamos Character.cs. Eso nos creará automáticamente código con el namespace del formulario y una clase llamada Character. Cambiamos la visibilidad de la clase a pública añadiendo la palabra clave public antes de la definición de la clase:

Citarpublic class Character
    {
    }

En esta clase definimos el campo Bitmap en el que vamos a cargar su correspondiente png, y lo llamamos btmCharacter. Pero no lo vamos a cargar a las bravas, sino que haremos que el personaje pueda cargar diferentes pngs, así la misma clase nos servirá para diferentes pngs de personaje siempre y cuando sus pngs sean compatibles. Cuando añadimos el campo nos dice que no encuentra la clase Bitmap, porque nos falta poner el using de System.Drawing, sin embargo si te colocas en la palabra Bitmap sale un cursor con una notita que si la pinchas te sugiere agregarla automáticamente.

Creamos un método LoadBitmap que acepte como parámetro un nombre de fichero y lo que haga sea crear un nuevo bitmap con ese fichero desechando el anterior. También creamos un constructor de la clase que acepte como parámetro el nombre de fichero inicial e invoque a LoadBitmap:

Citarpublic class Character
    {
        private Bitmap btmCharacter = null;

        public Character(string pngName)
        {
            LoadBitmap(pngName);
        }

        public void LoadBitmap(string pngName)
        {
            btmCharacter = new Bitmap(pngName);
        }
    }

Añadimos otra clase y la llamamos KeyController. Esta clase nos servirá para llevar el control de las teclas pulsadas y su estado, dado que vamos a controllar si hay más de una tecla pulsada en un determinado instante. En este KeyController, por ahora, llevaremos control de únicamente 4 teclas, correspondientes a las direccionales. Definimos un tipo enumerado público para dichas 4 teclas fuera de la clase y un campo privado de tipo array booleano y cardinalidad 4, inicializando todos los valores a false, que será el que indique las teclas pulsadas. De este último lo encapsulamos a una propiedad pública de solo lectura. Además añadimos dos métodos para reaccionar al KeyDown y al KeyUp que serán invocados desde la ventana principal:

Citarpublic enum DirectionKeys
    {
        up,
        down,
        left,
        right
    }

    public class KeyController
    {
        private bool[] keysPressed = new bool[4] { false, false, false, false };

        public bool[] KeysPressed
        {
            get { return keysPressed; }
        }

        public bool KeyDown(Keys key)
        {
            switch (key)
            {
                case Keys.Up:
                    keysPressed[(int)DirectionKeys.up] = true;
                    return true;
                case Keys.Down:
                    keysPressed[(int)DirectionKeys.down] = true;
                    return true;
                case Keys.Left:
                    keysPressed[(int)DirectionKeys.left] = true;
                    return true;
                case Keys.Right:
                    keysPressed[(int)DirectionKeys.right] = true;
                    return true;
            }
            return false;
        }

        public bool KeyUp(Keys key)
        {
            switch (key)
            {
                case Keys.Up:
                    keysPressed[(int)DirectionKeys.up] = false;
                    return true;
                case Keys.Down:
                    keysPressed[(int)DirectionKeys.down] = false;
                    return true;
                case Keys.Left:
                    keysPressed[(int)DirectionKeys.left] = false;
                    return true;
                case Keys.Right:
                    keysPressed[(int)DirectionKeys.right] = false;
                    return true;
            }
            return false;
        }
    }

Hay que entender que si bien no es la forma más rápida de hacer las cosas, sí es la más ordenada y reutilizable. Así estamos separando la zona de interfaz con el usuario, la reacción al Input y el personaje. Los enemigos y objetos, por ejemplo, también llevarían su propia clase. Además en el form añadimos un campo que sea una instancia de este keycontroller y añadimos los eventos de respuesta a KeyDown y KeyUp:

Citarprivate KeyController keyController = new KeyController();

Citarprivate void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = keyController.KeyDown(e.KeyCode);
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = keyController.KeyUp(e.KeyCode);
        }

Volvemos al personaje. Hay que añadirle campos para llevar el control de varias cosas:
- El rectángulo definitorio de un frame, que será (0,0,40,48).
- Un enumerado para los diferentes estados en los que puede estar el personaje
- Un array de enteros que nos dirá los frames que contiene cada estado
- El estado actual del personaje
- El número de frame actual del personaje dentro de su estado
- Un rectángulo que lleve el control de las dimensiones del mundo en el que se puede mover el personaje
- La posición x del personaje
- La posición y del personaje (altura para cuando salta)

Citarprivate enum CharState
        {
            stand,
            run,
            jump
        }
        private Rectangle charRect = new Rectangle(0, 0, 40, 48);
        private int[] stateFrames = new int[3] { 4, 8, 9 };
        private CharState state = CharState.stand;
        private int actualFrameNumber = 0;
        private Rectangle worldRect;
        private int x = 0;
        private int y = 0;

Hay que modificar su constructor para que acepte como parámetro el rectángulo de las dimensiones del mundo:

Citarpublic Character(string pngName, Rectangle worldRect)
        {
            this.worldRect = worldRect;
            LoadBitmap(pngName);
        }

La cláusula "this" sirve para indicar que se trata de la clase. Es útil para casos como este: el parámetro que se pasa al constructor se llama exactamente igual que un campo de la clase.

Ahora hay que hacer que en la instanciación del personaje se le pase un rectángulo con las dimensiones del mundo:

CitarcharLucas = new Character("lucas.png", new Rectangle(0,0,800,426));

Además hay que añadirle un método privado para pasar al siguiente frame, un método para coger el Bitmap del frame actual y que además avanza al siguiente frame, y por último un método que dado unos gráficos, pinte al personaje:

Citarprivate void NextFrame()
        {
            actualFrameNumber++;
            if (actualFrameNumber >= stateFrames[(int)state])
            {
                actualFrameNumber = 0;
            }
        }

        private Bitmap ActualBitmap()
        {
            Bitmap result = new Bitmap(charRect.Width, charRect.Height);
            Rectangle srcRect = new Rectangle(actualFrameNumber * charRect.Width, (int)state * charRect.Height, charRect.Width, charRect.Height);
            Graphics g = Graphics.FromImage(result);
            g.DrawImage(btmCharacter, charRect, srcRect, GraphicsUnit.Pixel);
            NextFrame();
            return result;
        }

        public void Paint(Graphics g)
        {
            Bitmap actualBitmap = ActualBitmap();
            Rectangle destRect = new Rectangle(x, worldRect.Height-actualBitmap.Height-y, charRect.Width, charRect.Height);
            g.DrawImage(actualBitmap, destRect, charRect, GraphicsUnit.Pixel);
        }

En el paint del form1, dónde pintábamos el background, hay que hacer que además pinte al personaje:

Citarprivate void Form1_Paint(object sender, PaintEventArgs e)
        {
            PaintBackground(e.Graphics);
            charLucas.Paint(e.Graphics);
        }

Ahora mismo, si ejecutamos, ya veremos a nuestro lucas situado al principio del todo:

(http://img686.imageshack.us/img686/5946/captura2m.jpg)

Pero está muerto  :'(

Ahora es cuando entra el concepto de tiempo. En el capítulo anterior repintábamos a petición del usuario cuando pulsaba una tecla. Ahora no lo vamos a hacer así. Vamos a meter una instancia de una clase llamada Timer que nos permite definir un intervalo de tiempo y que al habilitarlo nos llame a métodos que estén suscritos a su evento Tick. En el Form1 definimos el timer:

Citarprivate Timer frameTimer;

Añadimos un método DoOnFrameTimer que será el que se dispare. Ojo, los parámetros tienen que ser los que son porque son los definidos en el delegado de Timer.Tick. En cada tick lo que hacemos es pintar de nuevo la escena.

Citarprivate void DoOnFrameTimer(object sender, EventArgs e)
        {
            Invalidate();
        }

Ahora es cuando tenemos que crear el timer y darle un intervalo, y llega el concepto de FPS. Según el tiempo que definamos tendrá más FPS, aunque todavía no llevaremos un control de repintado según demanda de procesador que sí tendremos cuando veamos XNA. En este caso vamos a definir 20 FPS, como un segundo tiene 1000 ms entonces el timer se tiene que llamar cada 1000/20 = 50ms:

CitarframeTimer = new Timer();
            frameTimer.Interval = 50;
            frameTimer.Tick += DoOnFrameTimer;
            frameTimer.Enabled = false;

Ahora ya tendríamos a Lucas haciendo cosas, estando vivo. Como además queremos comprobar el resto de estados, añadimos el siguiente método de test a la clase Character:

Citarpublic void NextState()
        {
            if ((int)state < 2)
            {
                state++;
            }
            else
            {
                state = 0;
            }
        }

Y en el evento KeyUp del Form1 añadimos que se llame al NextState de charLucas:

Citarprivate void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = keyController.KeyUp(e.KeyCode);
            charLucas.NextState();
        }

Ahora cuando pulsamos una tecla cualqueira lucas cambia a su siguiente estado, así podremos ver la animación de stand, run y jump.

(http://img64.imageshack.us/img64/9105/captura3l.jpg)
(http://img215.imageshack.us/img215/1928/captura4f.jpg)

Adjunto el código fuente, en la carpeta bin/Debug encontraréis además un ejecutable generado, los gráficos necesarios y el psd del personaje por si queréis tocar.

http://www.megaupload.com/?d=8TF32SM7


Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje
Publicado por: Bill en 13 de Abril de 2010, 20:32
Avisados estais de que si este era "duro", en el siguiente entran lo conceptos de vector velocidad, inercia, tiro parabólico... si no os gusta la matemática o física ni un poquito, abandonad ahora  :amo:

O preguntad mucho, que contesto  :gñe:
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje
Publicado por: Khram Cuervo Errante en 13 de Abril de 2010, 20:33
Joder, me encantaría hacer una movida de estas para una conferencia que tengo que dar, pero no tengo tiempo de programar nada...

Pelu, no los asustes tanto, que esa física es de la facilita...
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje
Publicado por: Bill en 13 de Abril de 2010, 21:38
Un pequeño anexo para "juguetear". Dado que tenemos el personaje en una clase, se puede instanciar varias veces, así que hay un pequeño ejercicio divertido que se puede hacer, y es que salgan varios luquitas haciendo lo mismo por la pantalla. Para ello modificamos el constructor del personaje para que acepte una x, que será la posición de ese lucas:

Citarpublic Character(string pngName, Rectangle worldRect,int x)
        {
            this.worldRect = worldRect;
            LoadBitmap(pngName);
            this.x = x;
        }

En el Form1 cambiamos la declaración del Character por un array de 10 elementos:

Citarprivate Character[] charLucas = new Character[10];

En la inicialización del Character hacemos que se pase una x apropiada dentro de un for:

Citarfor (int i = 0; i<10; i++)
            {
                charLucas = new Character("lucas.png", new Rectangle(0, 0, 800, 426),i*80);
            }

El for tiene 3 parámetros: inicialización, condición e incremento. La inicialización es para iniciar la variable del for, que hemos declarado ahí mismo, así que comienza en i=0. La condición es lo que se debe cumplir para continuar ejecutando el for, en este caso que i sea menor que 10 para que recorra de 0 hasta 9. Y por último el incremento que se hace cada vez que se ejecuta una vuelta del for, en este caso i++ que significa i=i+1.

En todos los sitios en los que usábamos charLucas hay que sustituirlo ahora por el for haciendo la acción que se llevaba a cabo:

Citarprivate void Form1_Paint(object sender, PaintEventArgs e)
        {
            PaintBackground(e.Graphics);
            for (int i = 0; i < 10; i++)
            {
                charLucas.Paint(e.Graphics);
            }
        }

Citarprivate void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            e.Handled = keyController.KeyUp(e.KeyCode);
            for (int i = 0; i < 10; i++)
            {
                charLucas.NextState();
            }
        }

Y aquí el resultado: 10 luquitas haciendo lo mismo

(http://img169.imageshack.us/img169/5587/captura1w.jpg)

¿Alguien es capaz de hacer que aparezcan 3 filas de luquitas?  :gñe:

Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje
Publicado por: Bill en 13 de Abril de 2010, 23:50
6. Dando más vida al personaje (II).

Lo primero que vamos a hacer es modificar el tipo de los campos x e y de la clase Character para que en lugar de enteros sean double (un número real, con sus decimales). ¿Por qué? Porque cuando se trabaja con una física de un juego, aunque sea inventada, normalmente termina habiendo incrementos y localizaciones no enteras. En nuestro caso sí lo van a ser porque la física que vamos a implementar en el juego es terriblemente sencilla, y con números enteros, pero más vale prevenir... Con lo cual no solamente modificamos la declaración sino que a la hora de pintar el bitmap tendremos que hacerles un casteo a entero. De esta forma la declaración es:

Citarprivate double x = 0;
       private double y = 0;

Y el pintado:

Citarpublic void Paint(Graphics g)
       {
           Bitmap actualBitmap = ActualBitmap();
           Rectangle destRect = new Rectangle((int)x, worldRect.Height-actualBitmap.Height-(int)y, charRect.Width, charRect.Height);
           g.DrawImage(actualBitmap, destRect, charRect, GraphicsUnit.Pixel);
       }

Definimos un vector para la velocidad, al ser un mundo plano este vector será de dos dimensiones representando a x e y:

Citarprivate double[] speedVector = new double[2]{0.0f, 0.0f};

Lo de 0.0f es la manera de expresar que es 0.0 decimal (float), podríamos haber puesto un 0 normal.

Necesitaremos dos métodos auxiliares, uno para incrementar la velocidad que aceptará en qué dimensión aumentamos la velocidad (si es para correr, la x que es el 0, si es para saltar la y que es el 1) y el incremento de la velocidad en dicha dimensión. El segundo método será para relajar la velocidad en el eje x. Además, definimos una constante para la velocidad máxima, que será de 12 píxeles por frame:

Citarconst double maxSpeed = 12.0f;

El método de incrementar la velocidad sería:

Citarprivate void IncreaseSpeed(int i, double k)
       {
           speedVector += k;
           if (speedVector > maxSpeed)
           {
               speedVector = maxSpeed;
           }
           else if (speedVector < -maxSpeed)
           {
               speedVector = -maxSpeed;
           }
       }

Y el de relajar la velocidad (hace que la velocidad tienda a 0, para la inercia):

Citarprivate void RelaxSpeed(double k)
       {
               if (speedVector[0] < 0)
               {
                   speedVector[0] += k;
                   if ((speedVector[0]) > 0)
                   {
                       speedVector[0] = 0.0f;
                   }
               }
               else if (speedVector[0] > 0)
               {
                   speedVector[0] -= k;
                   if ((speedVector[0]) > 0)
                   {
                       speedVector[0] = 0.0f;
                   }
               }
       }

Ahora definimos un método Move que será el encargado de calcular las nuevas coordenadas de nuestro personaje con respecto a su velocidad y posición, además de calcular en qué estado está y pasar de frame:

Citarprivate void Move()
       {
           x = x + speedVector[0];
           if (x < 0)
           {
               x = 0;
               speedVector[0] = 0.0f;
           }
           else if (x > worldRect.Width - charRect.Width-10)
           {
               x = worldRect.Width - charRect.Width-10;
               speedVector[0] = 0.0f;
           }
           y = y + speedVector[1];
           if (y < 0)
           {
               y = 0;
               speedVector[1] = 0.0f;
           }
           else if (y > worldRect.Height - charRect.Height)
           {
               y = worldRect.Height - charRect.Height;
               speedVector[1] = 0.0f;
           }
           if (y > 0)
           {
               state = CharState.jump;
           }
           else if (speedVector[0] != 0)
           {
               state = CharState.run;
           }
           else
           {
               state = CharState.stand;
           }
           NextFrame();
       }

Como vemos hay una comprobación de que no se salga de los límites del mundo, considera que el personaje está saltando si y>0, si no está saltando y tiene velocidad en las x entonces está corriendo, y si no está saltando ni corriendo es que está parado.

Y ahora necesitamos un método para procesar el input del teclado, calcular el siguiente movimiento y pintar el personaje, que se llamará ProcessMovement. Este método debe hacer varias cosas:
- Si la y>0 entonces frenar la velocidad en Y en 1 punto.
- Si están pulsando la tecla hacia arriba y no la de abajo, y el personaje está en el suelo, aumentar la velocidad en Y en 12 puntos para representar el impulso inicial.
- Si están pulsando la tecla derecha y no la izquierda incrementa su velocidad en 1 punto y mira hacia la derecha
- Si están pulsando la tecla izquierda y no la derecha decrementa su velocidad en 1 punto y mira hacia la izquierda
- Si no pulsan ni derecha ni izquierda por separado, relaja la velocidad.
- Realiza el movimiento
- Pinta.

Citarpublic void ProcessMovement(KeyController controller, Graphics g)
       {
           if (y > 0)
           {
               IncreaseSpeed(1, -1);
           }
           if ((controller.UpPressed) && (!controller.DownPressed) && (y == 0))
           {
               IncreaseSpeed(1, 12);
           }
           if ((controller.RightPressed) && (!controller.LeftPressed))
           {
               IncreaseSpeed(0, 1);
               direction = CharDirection.right;
           }
           else if ((!controller.RightPressed) && (controller.LeftPressed))
           {
               IncreaseSpeed(0, -1);
               direction = CharDirection.left;
           }
           else
           {
               RelaxSpeed(1);
           }
           Move();
           Paint(g);
       }

Cambiamos el evento Paint de Form1 para invocar a este nuevo método en lugar del Paint (al cual cambiamos la visibilidad a privada):

Citarprivate void Form1_Paint(object sender, PaintEventArgs e)
       {
           PaintBackground(e.Graphics);
           charLucas.ProcessMovement(keyController, e.Graphics);
       }

Y nos queda un último toque mágico: si el personaje mira hacia la izquierda hay que hacer un flip horizontal del bitmap, y eso se hace en ActualBitmap() con el método RotateFlip de la clase Bitmap:

Citarprivate Bitmap ActualBitmap()
       {
           Bitmap result = new Bitmap(charRect.Width, charRect.Height);
           Rectangle srcRect = new Rectangle(actualFrameNumber * charRect.Width, (int)state * charRect.Height, charRect.Width, charRect.Height);
           Graphics g = Graphics.FromImage(result);
           g.DrawImage(btmCharacter, charRect, srcRect, GraphicsUnit.Pixel);
           if (direction != CharDirection.right)
           {
               result.RotateFlip(RotateFlipType.RotateNoneFlipX);
           }
           return result;
       }

El resultado es que nuestro muñeco ya corre, salta, se para, y tiene una física que aunque no es real es la lógica para un juego de plataformas. Os recomiendo juguetear con el código y hacerle perrerías, como por ejemplo probar a implementar un doble salto o un efecto kirby.

(http://img210.imageshack.us/img210/2527/captura1xw.png)

Código con gráficos y ejecutable:

http://www.megaupload.com/?d=WO7WXJXA


Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Bill en 14 de Abril de 2010, 00:12
El vídeo de cómo queda (y haciendo un poco el payaso):

http://www.screencast.com/t/MzMzZTJjY

:gñe:
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Khram Cuervo Errante en 14 de Abril de 2010, 09:49
Peluche, yo sé que tú eres niño como yo, por eso te qu... este... Yo sé que estás ocupadísimo, pero si te pidiera que me programaras una animación de una diapedesis para ponerla en un congreso, ¿te animarías? (Por supuesto, tu nombre iría en el congreso).
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Rohi en 14 de Abril de 2010, 09:51
Has descubierto el mecanismo de la diapedesis? :O

edit: la cara esa quiere ser una cara sorprendida, no sobrada.
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Khram Cuervo Errante en 14 de Abril de 2010, 09:54
¿El mecanismo? No, qué va. Pero quiero que un linfocito T atraviese la barrera hematoencefálica. Y eso lo hacen por diapédesis. Se sabe más o menos qué es lo que ocurre, por mucho que no se sepa como.

Además, soy neuro no inmunólogo...
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Bill en 14 de Abril de 2010, 10:50
Cita de: Khram Cuervo Errante en 14 de Abril de 2010, 09:49
Peluche, yo sé que tú eres niño como yo, por eso te qu... este... Yo sé que estás ocupadísimo, pero si te pidiera que me programaras una animación de una diapedesis para ponerla en un congreso, ¿te animarías? (Por supuesto, tu nombre iría en el congreso).

Si me mandas un MP con explicado lo que quieres (pa tontos, porque yo de biología bastante pez...) se puede mirar. Pero para animaciones, mejor Penguin, es decir, una animación es simplemente algo que sucede no hay interactividad ni cálculos, es un vídeo. Lo que se puede hacer con programación que te pudiese interesar serían cálculos y simulación en tiempo real, algo interactivo que el usuario pueda meter parámetros... Tengo por ejemplo simulaciones de colonias de hormigas utilizando algoritmos genéticos para calcular mutaciones en el comportamiento. Básicamente defines una colonia de individuos, cantidad de comida y los situa al azar, la frecuencia de mutaciones, capacidad de portear comida, fuerza de seguimiento de las feromonas y velocidad de un individuo,... Te paso una captura:

Los triángulos son individuos (hormigas) con su correspondiente numeración de individuo y la cantidad de comida que portan. Los puntos azules son comida.

(http://img404.imageshack.us/img404/9721/captura1xb.jpg)

En la carrera saqué matrícula en biomédica, pero lo que hacíamos era tratamiento de señales biológicas, en mi caso la matrícula vino porque de práctica hice un dispositivo con dos electrodos que se conectaban a la pierna izquierda y brazo derecho de un individuo (2ª derivación) y que con un amplificador operacional en modo instrumental pasaba los datos de diferencia de potencial a través de un puerto serie, y un programa que tomaba los datos, mostraba el electrocardiograma, y calculaba las ondas, complejos, frecuencia, energía... incluso te decía si el usuario tenía algún problema cardíaco (no muy complicados, identificaba paradas cardíacas, infartos e isquemias).

Pero eso, que para simulaciones la programación está bien, para animaciones... Penguin.
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Khram Cuervo Errante en 14 de Abril de 2010, 11:04
Vale, ahora me entra una duda: ¿Penguin es pingüino/power overgüino/ningüino o es una plataforma para animaciones?

Básicamente, lo que debería hacer el linfocito es pegarse a la barrera hematoencefálica, encontrar un lugar en el que dos células epiteliales contactan, estrecharse para pasar por un agujero muy pequeño y atravesar dicho agujero. Esto es lo complejo, porque el linfocito debe pasar por ese punto de contacto como si fuera una ameba, es decir, moviendo su citoplasma de un lado a otro, lo que significa que el linfocito debería tener el culo muy gordo y una cabeza muy fina en un primer momento, esa cabeza tan fina atravesar la barrera y salir por el otro lado. Y una vez sale por el otro lado, el culo debe ir adelgazando mientras engorda la cabeza hasta invertir la situación, dejando al linfocito totalmente dentro del sistema nervioso. Esquema ridículo:


  (        (       (        (        (
O     ->  C>   ->  C><D  ->  <D  ->    O
  (        (       (        (        (
 
 

Donde "O", "C>", "C><D" y "<D" son los distintos estados del linfocito y los paréntesis la barrera que debe atravesar.
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Bill en 14 de Abril de 2010, 11:18
Penguin es nuestro Ningüino de toda la vida, se llame como se llame ahora. Hace vídeos y animaciones, o al menos eso me dice, aunque no sé si creerle porque todavía no he visto nada de él y es totalmente reticente a enseñar nada.

Lo que tú necesitas es una animación, yo para eso... fatal. Mi capacidad creativa o de diseño es -10. Si en cambio fuese una simulación, que le puedas definir parámetros, número de linfocitos, etc etc... se podría hacer una simulación en 3D, aunque si las formas que poseen no son básicas (esferas, discos, conos...) yo no sé diseñarlas, con lo que volvemos a Penguin.
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Khram Cuervo Errante en 14 de Abril de 2010, 11:30
Pues acudiré al señor ningüino. Gracias por todo Gambit.
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Ningüino CDR-lar en 20 de Abril de 2010, 01:26
Cita de: Gambit en 14 de Abril de 2010, 11:18
Penguin es nuestro Ningüino de toda la vida, se llame como se llame ahora. Hace vídeos y animaciones, o al menos eso me dice, aunque no sé si creerle porque todavía no he visto nada de él y es totalmente reticente a enseñar nada.

Lo que tú necesitas es una animación, yo para eso... fatal. Mi capacidad creativa o de diseño es -10. Si en cambio fuese una simulación, que le puedas definir parámetros, número de linfocitos, etc etc... se podría hacer una simulación en 3D, aunque si las formas que poseen no son básicas (esferas, discos, conos...) yo no sé diseñarlas, con lo que volvemos a Penguin.

O.o

¿Cuándo te he dicho yo eso? En cualquier caso una cosa es saber y otra hacer: generalmente soy muy vago. Si no te corre prisa, podría hacerlo, Khram; pero en las próximas semanas no (hasta la segunda mitad de mayo, me temo).

Aunque no lo creas, Pelu, estoy modelando para darte cosas que desarrollar y eso y que me salves el culo. Mi planing es pasártelo todo como en 10 días y que tengas entre 2 y 3 semanas (es probable que me den una prórroga por guay) para desarrollar y mientras yo haga los videos pertinentes. La semana que viene un día me paso a verte y te explico en profundidad (y sigo rallándome con los escenarios, porque no quiero algo rollo metal slug y no sé cómo se hacen los espacios intermedios -es decir, cómo cortar los niveles- xDDD). Si tienes alguna queja, avisa. :*
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Calabria en 20 de Abril de 2010, 01:32
Cita de: Khram Cuervo Errante en 14 de Abril de 2010, 11:04
Vale, ahora me entra una duda: ¿Penguin es pingüino/power overgüino/ningüino o es una plataforma para animaciones?

Básicamente, lo que debería hacer el linfocito es pegarse a la barrera hematoencefálica, encontrar un lugar en el que dos células epiteliales contactan, estrecharse para pasar por un agujero muy pequeño y atravesar dicho agujero. Esto es lo complejo, porque el linfocito debe pasar por ese punto de contacto como si fuera una ameba, es decir, moviendo su citoplasma de un lado a otro, lo que significa que el linfocito debería tener el culo muy gordo y una cabeza muy fina en un primer momento, esa cabeza tan fina atravesar la barrera y salir por el otro lado. Y una vez sale por el otro lado, el culo debe ir adelgazando mientras engorda la cabeza hasta invertir la situación, dejando al linfocito totalmente dentro del sistema nervioso. Esquema ridículo:


   (        (       (        (        (
O     ->  C>   ->  C><D  ->  <D  ->    O
   (        (       (        (        (
 
 

Donde "O", "C>", "C><D" y "<D" son los distintos estados del linfocito y los paréntesis la barrera que debe atravesar.
Vaaaaaaa...lo quieres hecho en flash o en 3D? pa cuando? qué pinta tiene todo eso? Quicir...cómo es un linfocito, una barrera hematoencefálica y el liquidito en que flotan?
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Khram Cuervo Errante en 21 de Abril de 2010, 16:26
Si me pasas una dirección de mail, puedo mandarte la imagen estática para que te hagas una idea. Si aceptas el trabajo, ya te pasaría una chuleta para que se viera el orden en el que tienen que ocurrir las cosas.
Título: Re: Curso de Programación Lúdica. Actualmente: Dando más vida al personaje (II)
Publicado por: Bill en 27 de Abril de 2010, 15:58
7. Creando un Tetris: Análisis

Lo que hemos experimentado hasta ahora era de forma caótica, es decir, se programaba para lo que se necesitaba en cada momento. Esto, que es un error en el que suelen caer todos los que empiezan y muchos de los que ya no son novatos, es pan hoy y hambre mañana. Por ejemplo, suponed el diseño de enemigos, tendríamos que repetir código, como mínimo el de recorte de gráficos.

Lo normal antes de comenzar un programa es el análisis, de forma que que obtengamos una idea de lo que vamos a tener que programar, qué estructuras utilizar, cómo programarlo, o incluso una estimación del coste y el esfuerzo. En juegos, más allá del análisis para un programa, está el análisis para un motor, que básicamente responde a la pregunta "¿éste será el único juego que voy a programar?". Toda compañía de juegos trabaja contra un motor, no parten de cero, de forma que gran parte del trabajo gráfico o lógico está ya automatizado.

En nuestro caso vamos a hacer un análisis de programa para el tetris, y una vez terminado el desarrollo se comenzará con XNA, dónde veremos lo báisico para luego adentrarnos en el desarrollo de un simple motor gráfico 2D y más tarde 3D.

El Tetris

En el tetris poseemos un espacio de juego cuadriculado de unas dimensiones determinadas en el que caen de la parte superior figuras geométricas que se denominan "tetriminos". El jugador puede girar dichas fichas en ángulos de 90º, moverlas a izquierda y derecha o acelerar su caída. Cuando alguna parte del tetrimino topa con un bloque estacional (por ejemplo una pieza que ya había sido colocada), queda colocada y se obtiene un tetrimino nuevo al azar. Cuando una fila del espacio de juego está repleta por bloques de tetriminos, dicha fila desaparece y las superiores a ella bajan una posición.

Las piezas originales son 7, que se denotan con las letras que mejor las definen: O, I, S, Z, J, L y T.
Si representamos dichas piezas en cuadrículas de 4x4, podremos representar también sus diferentes posiciones rotándolas a partir de un cuadrado escogido como pivote, en nuestro caso el (1,1):

(http://img265.imageshack.us/img265/6428/guiaf.png)

Se puede observar que la pieza O solamente tiene una posibilidad, dado que aunque se rote se queda igual (por eso para ella su caso es especial y no se utiliza el pivote de giro, que daría un resultado desagradable). Las piezas I, S y Z tienen dos posiciones, y las piezas J, L y T tienen 4 posiciones.
A cada una de las piezas le hemos dado un color correspondiente para diferenciarlas.

En nuestro caso, por darle un aspecto más moderno, las piezas se mostrarán en una perspectiva isométrica, y el tablero se representará relleno de piezas blancas en el inicio. Además, no se utilizará un ancho y alto fijo del espacio de juego, sino que será definible. Necesitaremos una imagen para los sprites de los cubos que contendrá 8 cubos (uno blanco y los 7 de cada color):

(http://img227.imageshack.us/img227/6651/cubos.png)

Cada cubo tiene un ancho de 21px y un alto de 21px. Sin embargo, a la hora de mostrarlos apilados, hay que tener en cuenta que un cubo encima de otro está en su misma x pero en el incremento en y no es de 21px sino de 10px, cuando un cubo está a la derecha de otro el incremento en x es de 10px y además debe bajar 5px de altura para la emulación de la isométrica.

(http://img230.imageshack.us/img230/281/cotash.jpg)

A la hora de pintar también hay que tener algo importante en cuenta: el orden de pintado. Los sprites de los cubos se van a superponer así que hay que contemplar el orden de pintado para que no pasen cosas extrañas. Las posibilidades son 4:

(http://img185.imageshack.us/img185/852/ordenpintado.jpg)

Como vemos, la forma correcta es pintar comenzando por abajo y hacia arriba.

Ahora hay que analizar las estructuras que se utilizarán para la aplicación y datos básicos que necesitaremos:

1. Necesitaremos cargar al inicio la imagen con los cubos de colores y partirla en sus diferentes Bitmaps.
2. Necesitaremos información sobre cada pieza y sus diferentes giros. Para esto utilizaremos una matriz de 4 dimensiones:
- la primera dimensión se corresponderá con la pieza, es decir, la pieza 0 será la O, la 1 será la I, la 2 será la S y así sucesivamente
- la segunda dimensión se corresponderá con la posición de la pieza, con lo cual la posición 0 será rotación de 0º, posición 1 será 90º, posición 2 será 180º y posición 3 será 270º.
- la tercerá dimensión será el y de la pieza
- la cuarta dimensión será el x de la pieza.
De esta forma, dada una pieza y posición, obtendremos una matriz de 2 dimensiones 4x4 que nos dirá para cada casilla qué hay que pintar, significando el 0 que la casilla está vacía (lo cual no origina colisiones), el 1 el cubo de color rojo, el 2 el cubo de color verde, el 3 el cubo de color azul y así sucesivamente.
3. Necesitamos el número de piezas, cantidad de estados de pieza, ancho en casillas de la pieza y alto en casillas de la pieza como constantes, dado que será fijo.
4. Necesitamos el ancho y alto de cada pieza para cargar sus sprites, y será definible.
5. Necesitamos el incremento de ancho, incremento de alto e incremento de alto cuando hay cambio de x, que es lo que hemos definido antes con las cotas, y que será también definible dado que lleva relación con el ancho y alto de la pieza.
6. Además necesitaremos la posición izquierda y de alto en las que comenzar a pintar dentro del canvas de la aplicación.
7. Hace falta llevar control del espacio de juego, que será una matriz.
8. También hace falta llevar control de la pieza y detección de colisiones para calcular si hay giros posibles o si hay que posicionarla y sacar una pieza nueva.
9. Control de finalización de juego cuando no es posible sacar pieza nueva.
10. Cálculo de si en el espacio de juego hay filas completas para eliminarlas y bajar las superiores.

A partir de estos datos construiremos una clase TetrisEngine que será la encargada de representar al motor del tetris, y que será llamada por el formulario principal el cual le proporciona en el evento OnPaint su canvas para que pinte. Además sabemos que hay un cambio con respecto al ejercicio anterior: en el ejercicio anterior había un timer para los FPS y estaba definido en el formulario, el cual forzaba al repintado cada cierto tiempo. En este caso es el propio TetrisEngine el que tendrá un timer que será menor cuanto mayor sea la dificultad, con lo cual lanzará un evento que será leído por el formulario principal para producir su repintado, y que además comprueba si hay líneas conseguidas o si hay que sacar una pieza nueva. Además, el formulario principal informa al TetrisEngine de los movimientos del jugador (flecha arriba => girar, flecha izquierda, flecha derecha, flecha abajo => bajar una posición, barra espaciadora => tirar pieza), y el TetrisEngine procesará si es un movimiento válido, y en caso de serlo lanzará el evento para el repintado.

Además hay que pensar en el futuro, se planean los siguientes datos para el tetris:
- Visión previa de la siguiente pieza.
- Número de líneas conseguidas.
- Nivel de dificultad actual.
- Puntuación.
- Menú de juego.
- Música y efectos de sonido.
- Multijugador on-site (por decidir).
- Multijugador on-line (por decidir).

Un ejemplo de cómo quedaría el juego inicializado mostrando el espacio de juego vacío, que será lo primero a conseguir en el desarrollo:

(http://img689.imageshack.us/img689/175/primeraventana.jpg)

Ahora que tenemos las ideas un poquito más claras se puede comenzar a programar.
Título: Re: Curso de Programación Lúdica. Actualmente: Creando un Tetris
Publicado por: Bill en 30 de Abril de 2010, 00:40
8. Creando un Tetris: Sprites

8. Creando un Tetris: Sprites

Vamos a crear la aplicación y la dividiremos en 5 trozos diferenciados:
1- El formulario principal, que incluirá la interacción con el usuario y nos dará el canvas para pintar.
2- Una clase para cargar, manejar y pintar los sprites del tetris, que además incluya cálculos para la isométrica (TetrisSprite)
3- Una clase para representar a una pieza de tetris (TetrisPiece)
4- Una clase para representar a un espacio de juego del tetris (TetrisSpace)
5- El motor del tetris que se encarga de unirlo y moverlo todo (TetrisEngine)

Por definición, el formulario principal incluirá una instancia de TetrisEngine, que a su vez incluirá una instancia de TetrisSpace, la cual incluye una instancia de TetrisPiece. La clase TetrisSprite, por el contrario, necesita ser utilizada tanto por el Engine, Space y Piece, dado que en ella centralizaremos todo el pintado gráfico. A su vez, TetrisEngine informará al formulario principal de cuándo debe ser repintado mediante un evento.

Lo primero de todo es crear nuestra solución escogiendo de tipo de proyecto aplicación de Windows Forms.

La clase TetrisSprite

La clase TetrisSprite vamos a diseñarla según los siguientes datos:
1. Debe poder ser utilizada por diversas clases, pero solamente debemos permitir una instancia. Para eso utilizaremos el patrón de diseño singleton que nos asegurará que existe una única instancia de la clase TetrisSprite.
2. Debe permitir cargar los sprites de una única imagen sabiendo que dicha imagen los contiene en horizontal uno detrás de otro y pasándole la cantidad de sprites que contiene la imagen como parámetro.
3. Debe permitir que se especifique si es perspectiva isométrica o no, y hacer los correspondientes cálculos de los incrementos de X e Y que debe de utilizar en cada caso.
4. Debe contemplar que existen 3 clases de zonas en el juego: casillas ocupadas por una pieza, casillas no ocupadas y que se corresponden a la zona de juego, casillas que no están ocupadas y que se corresponden a la zona de drop por dónde caen las piezas.
5. Para cada zona debe poderse especificar la transparencia en Alpha Blend de lo que vaya a pintar.
6. Debe contener métodos para el pintado que hagan el desarrollo futuro más sencillo.

Patrón de diseño singleton
En desarrollo informático los patrones de diseño son una parte importantísima, sobre todo a la hora de elaborar el diseño técnico de una aplicación. Son soluciones a problemas comunes que deben ser efectivas y reusables, y existen unos cuantos de ellos. Uno de los más comunes es el patrón singleton, que nos asegura que una determinada clase se instanciará una única vez, y nos permitirá acceder a esa instancia. En principio puede parecer tarea sencilla, pero se complica cuando pensamos que una aplicación puede tratar de acceder desde dos puntos diferentes de un mismo hilo cuando todavía no está creada la instancia y generar problemas, y todavía peor, en aplicaciones multihilo hay que proteger todavía más esta primera invocación.

En C# para elaborar una solución óptima al problema del singleton tenemos que seguir varios pasos:
1º) El constructor debe estar protegido, así que cambiaremos su visibilidad a privada
2º) Necesitamos un campo estático, inicializado a null, para almacenar la instancia.
3º) Necesitamos una propiedad estática de solo lectura y pública que nos dé acceso a esta instancia, pero que en caso de ser null la cree nueva.
4º) La creación debe estar protegida en una sección crítica. En c# es utilizando la instrucción lock(obj) dónde obj es un objeto cualquiera para la sincronización, y claramente debe ser declarado estático.
5º) Además de protegida por una sección crítica, estará protegida del acceso simultáneo desde hilos diferentes, y esto nos lo asegura el atributo  [MethodImpl(MethodImplOptions.Synchronized)], contenido en System.Runtime.CompilerServices. Este atributo es aplicable a métodos, así que la verdadera creación de la instancia estará en un método privado.

Veamos cómo quedaría nuestra clase TetrisSprite con el singleton implementado:

Citarpublic class TetrisSprite
    {
        private static Object syncObject = new Object();

        private static TetrisSprite instance = null;

        public static TetrisSprite Instance
        {
            get { return GetInstance(); }
        }

        private TetrisSprite()
        {
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        private static TetrisSprite GetInstance()
        {
            lock (syncObject)
            {
                if (instance == null)
                {
                    instance = new TetrisSprite();
                }
                return instance;
            }
        }
    }

Cualquiera que quiera utilizar la instancia de TetrisSprite solamente tiene que utlizar la propiedad pública y estática TetrisSprite.Instance

Uso de regiones

Hay algo muy útil en C# que son las regiones. Las regiones no es código que se compile, sino que es una ayuda para organizar y visualizar el código. Lo que hace una región es que lo de dentro de ella se pueda "plegar", por ejemplo:

Citar#region Prueba
(aquí el código)
#endregion

Podríamos plegarlo o desplegarlo para que solamente muestre la palabra "Prueba" o todo el código. En ese sentido, es bueno ser muy organizado con el código y utilizar regiones, aseguro que son muy útiles.

(http://img52.imageshack.us/img52/1238/curso1n.jpg)

Recorte y uso de los sprites

Para el uso de los sprites necesitaremos diversos campos, y sus respectivas propiedades de solo lectura:
1- Un array con los Bitmaps recortados
2- Un Rectangle con el área ya calculada de esos Bitmaps
3- El incremento en X cuando nos desplazamos horizontalmente (la mitad del ancho si es isométrica o el ancho entero si es plano)
4- El incremento en Y cuando nos desplazamos verticalmente (la mitad de la altura si es isométrica o la altura entera si es plano)
5- El incremento en Y cuando nos desplazamos horizontalmente (un cuarto de la altura si es isométrica o 0 si es plano)

Citarprivate Bitmap[] sprites;

        private Rectangle spriteRect;

        private int xIncrement;

        private int yIncrement;

        private int yIncrementForX;

        public Bitmap[] Sprites
        {
            get { return sprites; }
        }

        public Rectangle SpriteRect
        {
            get { return spriteRect; }
        }

        public int XIncrement
        {
            get { return xIncrement; }
        }

        public int YIncrement
        {
            get { return yIncrement; }
        }

        public int YIncrementForX
        {
            get { return yIncrementForX; }
        }

Además necesitamos un método público con el que pasarle el Bitmap que contiene los sprites, la cantidad de sprites que contiene y una booleana para indicar si es isométrica:

Citarpublic void Initialize(Bitmap srcBitmap, int numSprites, bool isIsometric)
        {
            // Calculamos el Rectangle de cada sprite. El ancho será el ancho total del bitmap que entra
            // dividido entre el número de sprites que contiene
            spriteRect = new Rectangle(0, 0, srcBitmap.Width / numSprites, srcBitmap.Height);
            // Inicializamos nuestros campos de desplazamiento dependiendo de la perspectiva
            if (isIsometric)
            {
                xIncrement = spriteRect.Width / 2;
                yIncrement = spriteRect.Height / 2;
                yIncrementForX = -spriteRect.Height / 4;
            }
            else
            {
                xIncrement = spriteRect.Width;
                yIncrement = spriteRect.Height;
                yIncrementForX = 0;
            }
            // Creamos el array para almacenar los bitmaps
            sprites = new Bitmap[numSprites];
            // Creamos un rect que será para recorrer el bitmap que nos ha llegado y partirlo en trozos.
            Rectangle srcRect = new Rectangle(0, 0, spriteRect.Width, spriteRect.Height);
            // Recorremos cada uno de los sprites y lo pintamos en el bitmap de la posición del array.
            for (int i = 0; i < numSprites; i++)
            {
                sprites = new Bitmap(spriteRect.Width, spriteRect.Height);
                Draw(sprites, srcBitmap, spriteRect, srcRect);
                srcRect.X += srcRect.Width;
            }
        }

        public void Draw(Bitmap target, Bitmap source, Rectangle destRect, Rectangle srcRect)
        {
            Graphics bitmapGraphics = Graphics.FromImage(target);
            bitmapGraphics.DrawImage(source, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel);
        }

Como vemos, hemos creado un método público adicional que nos ayudará en el pintado de un bitmap a otro.

Transparencia Alpha Blending

Vimos ya varias veces que la clase Graphics tiene un método Draw con muchísimas sobrecargas. Varias de ellas aceptan un tipo de parámetro que es una instancia de ImageAttributes. Este ImageAttributes contiene diversas modificaciones que se pueden realizar sobre una imagen y una de ellas es que puede poseer una matriz de colores (ColorMatrix) que es una matriz de transformación de colores en el plano RGB.

El proceso, básicamente, consiste en crear una instancia de ColorMatrix, una instancia de ImageAttributes y usar el método SetColorMatrix de ImageAttributes para pasar la matriz. Pero, ¿cómo cambio la opacidad usando esa matriz? No entraré a explicarla en profundidad porque tiene muchísima miga, pero básicamente en su propiedad Matrix33 podemos modificar una diagonal que afecta a la opacidad de cada color, y en la que pondremos un número desde 0.0 a 1.0, significando el 0.0 que es transparente y el 1.0 que es totalmente opaco.

Lo primero que haremos será crear un enumerado que defina el tipo de zona que pintamos:

Citarpublic enum SpriteZone
    {
        game,
        drop,
        piece
    }

Ahora creamos una matriz de 3 elementos float para almacenar las opacidades y otra de 3 elementos ImageAttributes para almacenar los tres tipos de ImageAttributes que vamos a tener. La matriz de opacidades la inicializamos, la posición 0 es game, la posición 1 es drop y la posición 2 es piece. Como vemos, el juego y las piezas las mostramos opacas, la zona de drop bastante transparente (20%).

Citarprivate float[] opacities = new float[3] { 1.0f, 0.2f, 1.0f };

        private ImageAttributes[] imageAttributes;

Creamos un método privado que pasándole una posición aplique la transparencia de opacities en imageAttributes:

Citarprivate void ApplyOpacity(int i)
        {
            ColorMatrix cm = new ColorMatrix();
            cm.Matrix33 = opacities;
            imageAttributes.SetColorMatrix(cm);
        }

Creamos una propiedad para poder leer y modificar la opacidad de cada una de las zonas. Casteando un enumerado a entero obtenemos su valor entero y así podemos utilizarlo en las matrices:

Citarpublic float GameZoneOpacity
        {
            get { return opacities[(int)SpriteZone.game]; }
            set
            {
                opacities[(int)SpriteZone.game] = value;
                ApplyOpacity((int)SpriteZone.game);
            }
        }

        public float DropZoneOpacity
        {
            get { return opacities[(int)SpriteZone.drop]; }
            set
            {
                opacities[(int)SpriteZone.drop] = value;
                ApplyOpacity((int)SpriteZone.drop);
            }
        }

        public float PieceOpacity
        {
            get { return opacities[(int)SpriteZone.piece]; }
            set
            {
                opacities[(int)SpriteZone.piece] = value;
                ApplyOpacity((int)SpriteZone.piece);
            }
        }

Y por último, necesitamos modificar el constructor para que cree el array de ImageAttributes y además inicialice:

Citarprivate TetrisSprite()
        {
            imageAttributes = new ImageAttributes[3];
            for (int i = 0; i < 3; i++)
            {
                imageAttributes = new ImageAttributes();
                ApplyOpacity(i);
            }
        }

2 métodos auxiliares de pintado más con vistas al futuro

Añadiremos 2 métodos más de pintado, uno de ellos será bastante típico pero aceptando un enumerado de la zona para poner la transparencia, y el otro será especificando el número de sprite a pintar:

Citarpublic void Draw(Graphics target, Bitmap source, Rectangle destRect, Rectangle srcRect, SpriteZone zone)
        {
            target.DrawImage(source, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, imageAttributes[(int)zone]);
        }

        public void Draw(Graphics target, int spriteNumber, int left, int top, SpriteZone zone)
        {
            Rectangle destRect = new Rectangle(left, top, spriteRect.Width, spriteRect.Height);
            Draw(target, sprites[spriteNumber], destRect, spriteRect, zone);
        }

Probando el invento

Lo primero que haremos será añadir nuestro cubos.png al proyecto, pero lo vamos a hacer de una forma diferente. En lugar de cargarla directamente de disco duro hemos decidido que eso induce mucho a los malvados rippers de sprites, y que es mejor que vaya incrustado en el ejecutable. Es tan fácil como seguir estos pasos:
1) Crear una carpeta en el proyecto, la llamamos Resources
(http://img188.imageshack.us/img188/1299/curso2x.jpg)
2) En esa carpeta dar a añadir elemento existente y seleccionar nuestro cubos.png
3) Seleccionamos el fichero de la imagen y en propiedades en Acción de compilación seleccionamos Recurso Incrustado

(http://img188.imageshack.us/img188/5821/curso3y.jpg)

El proceso para cargar una imagen de un archivo de recursos incrustado es el siguiente:

CitarStream inputStream = GetType().Assembly.GetManifestResourceStream("aquí el nombre");
            Bitmap inputBitmap = new Bitmap(inputStream);
            inputStream.Close();
            // aquí va tu uso del bitmap....
            inputBitmap.Dispose();

Dónde pone "aquí el nombre" hay que colocar el nombre del recurso. ¿Y cuál es? Pues el nombre del proyecto y su estructura de carpetas y por último el nombre del fichero. Por ejemplo en nuestro caso el proyecto se llama "Tetris", la estructura de carpetas es "Resources" y el fichero es "cubos.png" así que el nombre del recurso será "Tetris.Resources.cubos.png".
Dónde pone "aquí va tu uso del bitmap" es dónde metemos el codigo para usarlo.

Vamos a nuestro Formulario principal y vamos a cambiarlo un poco:

CitarTetrisSprite sprite = TetrisSprite.Instance;

        public MainForm()
        {
            InitializeComponent();
            DoubleBuffered = true;
            Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos.png");
            Bitmap inputBitmap = new Bitmap(inputStream);
            inputStream.Close();
            sprite.Initialize(inputBitmap, 8, true);
            inputBitmap.Dispose();
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            for (int i = 0; i < 8; i++)
            {
                sprite.Draw(e.Graphics, i, 30 + (i * sprite.SpriteRect.Width + 10), 30, SpriteZone.piece);
            }
            for (int i = 0; i < 8; i++)
            {
                sprite.Draw(e.Graphics, i, 30 + (i * sprite.SpriteRect.Width + 10), 80, SpriteZone.drop);
            }
        }

Hemos añadido un campo para la instancia de TetrisSprite, hemos hecho que TetrisSprite cargue los sprites del fichero, y en el evento Paint del formulario hacemos que pinte los 8 bitmaps, tanto con opacidad de pieza como con opacidad de drop.

El resultado:

(http://img408.imageshack.us/img408/7906/curso4w.jpg)

El código fuente:
http://www.megaupload.com/?d=OPNP2K8X
Título: Re: Curso de Programación Lúdica. Actualmente: Creando un Tetris
Publicado por: Bill en 03 de Mayo de 2010, 16:27
9. Creando un Tetris: Piezas

Lo siguiente es definir las piezas del tetris, con la clase TetrisPiece. Esta clase nos debe asegurar que podamos hacer lo siguiente:

1- Tener todos los datos de pintado de una pieza, con lo que para cada pieza se guardarán sus posibles representaciones según el tipo de pieza y ángulo.
2- Guardar el identificador de pieza, rotación y posición en x e y dentro del espacio de juego.
3- Obtener una nueva pieza al azar y asignarle una posición inicial en función del ancho del espacio de juego, el alto del espacio de juego y el alto de la zona de drop.
4- Obtener el valor de la pieza en una determinada celda del espacio de juego, indicando para ello la posición de la pieza y la rotación
5- Obtener el valor de la pieza en una determinada celda en función de la rotación y posición actual.
6- Obtener la rotación siguiente de la pieza.

Constantes
Hacen falta 4 constantes que representarán al número de piezas existentes, la cantidad de rotaciones posibles de cada pieza, el ancho y el alto en celdas de cada pieza:

Citar#region · Constants ·

        public const int NumPieces = 7;

        public const int NumRotations = 4;

        public const int CellWidth = 4;

        public const int CellHeight = 4;

        #endregion

En nuestro caso hay 7 piezas, 4 rotaciones (0º, 90º, 180º y 270º) y las representamos en matrices de 4x4.

Definición de las piezas

Hay que definir las piezas, en formas de matrices 4x4, de las cuales sabemos que hay 7 piezas y 4 rotaciones, con lo cual hay un total de 7x4 = 28 matrices de las piezas. Además hay que saber lo que representa el valor de cada casilla:
- Un 0 representa que la pieza no tiene ningún cubo en esa casilla.
- Un valor distinto de 0 representa al número de sprite que hay que pintar.

En esta representación además tendremos en cuenta otra cosa: la altura de la zona de drop. Vamos a tener una zona de drop de 2 casillas de altura, así que vamos a intentar que la posición inicial de cada una de nuestras piezas quepa en 2 casillas de altura, así que hacemos revisión de nuestra hoja de piezas:

(http://img402.imageshack.us/img402/3850/tetrise.jpg)

Vamos con la definición, sabemos que será una matriz de enteros de 4 dimensiones:

Citarpublic static int[,,,] PieceDefinition = new int[NumPieces,NumRotations,CellHeight,CellWidth] {
                {{{0, 0, 0, 0},{0, 1, 1, 0},{0, 1, 1, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{0, 1, 1, 0},{0, 1, 1, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{0, 1, 1, 0},{0, 1, 1, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{0, 1, 1, 0},{0, 1, 1, 0},{0, 0, 0, 0}}},
                {{{0, 0, 0, 0},{2, 2, 2, 2},{0, 0, 0, 0},{0, 0, 0, 0}},
                 {{0, 2, 0, 0},{0, 2, 0, 0},{0, 2, 0, 0},{0, 2, 0, 0}},
                 {{0, 0, 0, 0},{2, 2, 2, 2},{0, 0, 0, 0},{0, 0, 0, 0}},
                 {{0, 2, 0, 0},{0, 2, 0, 0},{0, 2, 0, 0},{0, 2, 0, 0}}},
                {{{0, 0, 0, 0},{0, 3, 3, 0},{3, 3, 0, 0},{0, 0, 0, 0}},
                 {{3, 0, 0, 0},{3, 3, 0, 0},{0, 3, 0, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{0, 3, 3, 0},{3, 3, 0, 0},{0, 0, 0, 0}},
                 {{3, 0, 0, 0},{3, 3, 0, 0},{0, 3, 0, 0},{0, 0, 0, 0}}},
                {{{0, 0, 0, 0},{4, 4, 0, 0},{0, 4, 4, 0},{0, 0, 0, 0}},
                 {{0, 4, 0, 0},{4, 4, 0, 0},{4, 0, 0, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{4, 4, 0, 0},{0, 4, 4, 0},{0, 0, 0, 0}},
                 {{0, 4, 0, 0},{4, 4, 0, 0},{4, 0, 0, 0},{0, 0, 0, 0}}},
                {{{5, 0, 0, 0},{5, 5, 5, 0},{0, 0, 0, 0},{0, 0, 0, 0}},
                 {{0, 5, 5, 0},{0, 5, 0, 0},{0, 5, 0, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{5, 5, 5, 0},{0, 0, 5, 0},{0, 0, 0, 0}},
                 {{0, 5, 0, 0},{0, 5, 0, 0},{5, 5, 0, 0},{0, 0, 0, 0}}},
                {{{0, 0, 6, 0},{6, 6, 6, 0},{0, 0, 0, 0},{0, 0, 0, 0}},
                 {{0, 6, 0, 0},{0, 6, 0, 0},{0, 6, 6, 0},{0, 0, 0, 0}},
                 {{0, 0, 0, 0},{6, 6, 6, 0},{6, 0, 0, 0},{0, 0, 0, 0}},
                 {{6, 6, 0, 0},{0, 6, 0, 0},{0, 6, 0, 0},{0, 0, 0, 0}}},
                {{{0, 0, 0, 0},{7, 7, 7, 0},{0, 7, 0, 0},{0, 0, 0, 0}},
                 {{0, 7, 0, 0},{7, 7, 0, 0},{0, 7, 0, 0},{0, 0, 0, 0}},
                 {{0, 7, 0, 0},{7, 7, 7, 0},{0, 0, 0, 0},{0, 0, 0, 0}},
                 {{0, 7, 0, 0},{0, 7, 7, 0},{0, 7, 0, 0},{0, 0, 0, 0}}}};

Cada fila representa a una de las posiciones de una pieza. Si colocamos una fila en vertical podremos entrever la pieza. Un ejemplo, vamos a pillar la pieza 6, y vamos a colocar cada fila en vertical con la anterior:

Citar{{{0, 0, 6, 0},
                  {6, 6, 6, 0},
                  {0, 0, 0, 0},
                  {0, 0, 0, 0}},
                 {{0, 6, 0, 0},
                  {0, 6, 0, 0},
                  {0, 6, 6, 0},
                  {0, 0, 0, 0}},
                 {{0, 0, 0, 0},
                  {6, 6, 6, 0},
                  {6, 0, 0, 0},
                  {0, 0, 0, 0}},
                 {{6, 6, 0, 0},
                  {0, 6, 0, 0},
                  {0, 6, 0, 0},
                  {0, 0, 0, 0}}},

Como vemos, son las 4 rotaciones de la pieza L.

Además de esas definiciones tendremos un array para indicarnos cuántas casillas en el eje Y empezando por abajo están vacías, para saber cómo colocarla en la zona de drop:

Citarprivate static readonly int[] PieceY = {1, 2, 1, 1, 2, 2, 1};


Propiedades

Necesitamos 4 propiedades para almacenar el Id, la rotación, la X y la Y actual de la pieza. En lugar de definir campos privados, y dado que solamente vamos a leer y escribir en ellos de forma convencional como si fuesen variables, vamos a utilizar una característica de C# muy útil que es que poniendo simplemente { get; set; } nos ahorramos el campo privado, y el compilador cuando genera el IL lo autocrea, de forma transparente para el programador. Así que la definición de propiedades nos quedaría:

Citar#region · Properties ·

        public int Id { get; set; }

        public int Rotation { get; set; }

        public int X { get; set; }

        public int Y { get; set; }

        #endregion

El azar

El azar en C# se maneja instanciando a la clase Random. La clase random permite dos constructores, uno de ellos sin pasar parámetros que crea azar total, y otro pasando una semilla que crea números pseudoaleatorios. En el caso de nuestra pieza nos vendrá mejor el segundo constructor. ¿Por qué? Porque tenemos intención de hacer el juego multijugador, y queremos que a ambos jugadores les vayan saliendo las mismas piezas, entonces lo mejor es obtener una semilla aleatoria al principio y utilizar la misma semilla para las piezas de ambos jugadores, así se obtendrán las mismas en el mismo orden, y la semilla se la pasaremos al constructor de la pieza. En el constructor, además, inicializaremos la pieza a vacía:

Citar#region · Fields ·

        private readonly Random _randomizer;

        #endregion

Citar#region · Constructor ·

        public TetrisPiece(int seed)
        {
            Id = -1;
            Rotation = 0;
            X = 0;
            Y = 0;
            _randomizer = (seed > 0 ? new Random(seed) : new Random());
        }

        #endregion


El operador ?

En el código del constructor hemos visto una línea un tanto peculiar. Me refiero a la siguiente:

Citar_randomizer = (seed > 0 ? new Random(seed) : new Random());

Se ha utilizado el operador ?. ¿Para qué sirve? El código anterior es equivalente al siguiente:

Citarif (seed >0)
            {
                _randomizer = new Random(seed);
            } else
            {
                _randomizer = new Random();
            }

La estructura del operador ? es la siguiente:

Citarcampo = (condición)?(valor true):(valor false);

y equivale a:

Citarif (condicion)
{
campo = (valor true);
}
else
{
campo = (valor false);
}

Es una manera de ahorrar tiempo y esfuerzo.

Calcular rotación siguiente

La rotación es un número del 0 al 3. El siguiente al 0 es el 1, el siguiente al 1 el 2, el siguiente al 2 el 3 y el siguiente al 3 es de nuevo el 0. En nuestro código hemos definido la constante NumRotations de forma que para calcular el siguiente valor sabemos que si la rotación actual es menor que la cantidad de rotaciones -1 entonces devuelve la rotación actual +1, en caso contrario devuelve 0.
Un ejemplo claro, sabemos que la cantidad de rotaciones es 4, entonces si la rotación actual es menor de (4-1 = 3) entonces devuelve la rotación actual+1, pero si vale 3 o superior devuelve 0. Esto se traduce en:

Citarpublic int NextRotation()
        {
            return (Rotation < (NumRotations - 1) ? Rotation + 1 : 0);
        }

Coger una pieza nueva

Tan sencillo como coger un número aleatorio entre 0 y NumPieces como Id de la pieza e inicializar la rotación a 0... si no fuese por el cálculo de la posición. En el eje X sabemos que tenemos que colocarla centrada, y para eso la tenemos que colocar el centro de la pieza en el centro del espacio de juego, así que dividimos el ancho del espacio de juego entre 2 y le restamos el ancho de la pieza entre 2. Además tenemos que hacer que quede bien situada en la zona de drop, en función de la altura del espacio de juego, la altura del drop, la altura de las piezas y las líneas vacías de la pieza por abajo:

Citarpublic void NewPiece(int spaceWidth, int spaceHeight, int spaceDropHeight)
        {
            Id = _randomizer.Next(NumPieces);
            Rotation = 0;
            X = spaceWidth / 2 - CellWidth / 2;
            Y = spaceHeight - spaceDropHeight - 1 + CellHeight - PieceY[Id];
        }

Calcular el valor de una celda de la pieza en una determinada posición del espacio de juego:

Dada una posición del espacio de juego (x,y), una posición de la pieza (pieceX, pieceY) y una rotación de la pieza. Si la pieza está recién inicializada y por tanto su identificador es -1, se devuelve 0.
En caso contrario se calcula la celda dentro de la matriz, y si la celda cae en los límites de la matriz de la pieza se devuelve su valor, en caso contrario 0:


Citarpublic int PieceValueAt(int x, int y, int rotation, int pieceX, int pieceY)
        {
            if (Id <= -1)
            {
                return 0;
            }
            int cellX = x - pieceX;
            int cellY = pieceY - y;

            if ((cellX >= 0) && (cellX < CellWidth) && (cellY >= 0) && (cellY < CellHeight))
            {
                return PieceDefinition[Id, rotation, cellY, cellX];
            }
            return 0;
        }

Hacemos una sobrecarga del método para contemplar el caso de una pieza con su propia rotación y posición:

Citarpublic int PieceValueAt(int x, int y)
        {
            return PieceValueAt(x, y, Rotation, X, Y);
        }

Mostrar algo en el principal:

En el MainForm vamos a tratar de que muestre todas las piezas posibles, para ello este será el código del MainForm:

Citarpublic partial class MainForm : Form
    {
        private readonly TetrisSprite _sprite = TetrisSprite.Instance;
        private readonly TetrisPiece _piece;

        public MainForm()
        {
            Random seedGenerator = new Random();
            InitializeComponent();
            DoubleBuffered = true;
            Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos.png");
            if (inputStream != null)
            {
                Bitmap inputBitmap = new Bitmap(inputStream);
                inputStream.Close();
                _sprite.Initialize(inputBitmap, 8, true);
                inputBitmap.Dispose();
            }
            _piece = new TetrisPiece(seedGenerator.Next());
        }

        private void DrawPiece(Graphics graphics, int id, int rotation, int x, int y)
        {
            _piece.Id = id;
            _piece.Rotation = rotation;
            _piece.X = 0;
            _piece.Y = 3;
            for (int cellY = TetrisPiece.CellHeight-1; cellY >=0; cellY--)
            {
                for (int cellX = 0; cellX < TetrisPiece.CellWidth; cellX++)
                {
                    _sprite.Draw(graphics, _piece.PieceValueAt(cellX, TetrisPiece.CellHeight -1 - cellY),
                        x+cellX*_sprite.XIncrement, y+cellY*_sprite.YIncrement-cellX*_sprite.YIncrementForX, SpriteZone.Piece);
                }
            }
        }

        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            int y = 10;
            for (int id = 0; id < TetrisPiece.NumPieces; id++)
            {
                int x = 10;
                for (int rotation = 0; rotation < TetrisPiece.NumRotations; rotation++)
                {
                    DrawPiece(e.Graphics,id, rotation, x, y);
                    x += _sprite.XIncrement * TetrisPiece.CellWidth + TetrisPiece.CellWidth+10;
                }
                y += _sprite.YIncrement * TetrisPiece.CellHeight + TetrisPiece.CellHeight + 10;
            }
        }
    }

El resultado que veríamos sería este:
(http://img706.imageshack.us/img706/1918/piezas.jpg)

Pero además vamos a probar con piezas que no sean en isométrica. Para ello añadir el siguiente archivo de recursos igual que hicimos con el primero:
(http://img688.imageshack.us/img688/1783/cubos3.png)

Dónde se carga el archivo de recursos cambiarlo para adecuarlo al nuevo nombre:

CitarStream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos3.png");

Y en la inicialización del _sprite indicar que se trata de sprites planos y no en isométrica:

Citar_sprite.Initialize(inputBitmap, 8, false);

El resultado es el siguiente:
(http://img696.imageshack.us/img696/7996/piezas2k.jpg)

Código fuente pendiente de subida.
Título: Re: Curso de Programación Lúdica. Actualmente: Creando un Tetris
Publicado por: Bill en 05 de Mayo de 2010, 10:58
10. Creando un Tetris: Espacio de juego

Introducción

Tenemos la forma de pintar en pantalla y las diferentes casillas que hay para los diferentes colores de pieza, también tenemos la representación de una pieza en concreto, solamente falta el espacio en el que se pinta. El espacio de juego se verá de la siguiente forma:

(http://img62.imageshack.us/img62/1006/cotas.jpg)

La zona que hay con transparencia es el drop, por el que caen las piezas. Si una pieza no puede bajar más, y alguna de sus casillas ocupadas (no las transparentes) está en la zona de drop, entonces se termina el juego.

El espacio de juego nos implicará la creación de la clase TetrisSpace.

Campos

Si atendemos a la figura anterior, vemos que al menos necesitamos 5 campos para guardar características numéricas del espacio de juego:
- left : posición izquierda en pixels en el canvas a pintar
- top : posición de altura en pixels con respecto al más inferior de los cubos del espacio de juego.
- width: ancho en casillas del espacio de juego
- height: altura en casillas del espacio de juego
- dropHeight: altura en casillas de la zona de drop

Además necesitaremos:
- Una matriz de enteros para representar a las casillas del espacio, un 0 representa una casilla vacía, en caso contrario el valor se corresponde al índice del sprite.
- La instancia de TetrisSprite para poder pintar. Como es un singleton, la podemos coger directamente.
- Una instancia de TetrisPiece para representar a la pieza flotante actual en el espacio de juego.

Citar#region · Fields ·

       private readonly int[,] _space;

       private readonly TetrisSprite _sprites = TetrisSprite.Instance;

       private readonly TetrisPiece _piece;

       private readonly int _left;

       private readonly int _top;

       private readonly int _width;

       private readonly int _height;

       private readonly int _dropHeight;

       #endregion

Constructor

En el constructor simplemente se inicializarán los campos con los valores pasados como parámetro (left, top, width, height y dropHeight) y además existirá un parámetro para la semilla aleatoria para la instanciación de TetrisPiece. Se instanciará TetrisPiece y la matriz.

Citarpublic TetrisSpace(int left, int top, int width, int height, int dropHeight, int seed)
       {
           _piece = new TetrisPiece(seed);
           _left = left;
           _top = top;
           _width = width;
           _height = height;
           _dropHeight = dropHeight;
           _space = new int[_width, _height];
       }

Iniciando TetrisSpace
Para iniciar la instancia de TetrisSpace hacen falta dos cosas:
- Limpiar la matriz de casillas
- Sacar una pieza nueva

Para ello creamos métodos privados para limpiar (Clear) y para sacar una pieza nueva (NewPiece) y un método público para iniciar la instancia (Start).

El Clear es sencillo: recorrer cada casilla e inicializarla a 0, y para eso utilizamos dos for anidados.

Citarprivate void Clear()
       {
           for (int y = 0; y < _height; y++)
           {
               for (int x = 0; x < _width; x++)
               {
                   _space[x, y] = 0;
               }
           }
       }

El NewPiece consiste en invocar al método NewPiece de la instancia de TetrisPiece dándole como parámetros el ancho, el alto y el alto de la zona de drop de nuestro espacio de juego:

Citarprivate void NewPiece()
       {
           _piece.NewPiece(_width, _height, _dropHeight);
       }

Por último el Start es sencillamente la invocación de los dos anteriores:

Citarpublic void Start()
       {
           Clear();
           NewPiece();
       }

Métodos auxiliares para saber dónde cae una casilla
Una casilla (x,y) puede caer fuera del espacio de juego o dentro del espacio de juego. Además, si está dentro del espacio de juego, puede que esté o no en la zona de drop. Vamos a necesitar conocer dónde cae una casilla, y para ello necesitaremos dos métodos privados, uno para decirnos si una casilla cae en el espacio de juego o si cae en la zona de drop:

Para saber si cae en la zona de juego simplemente hay que comprobar que la coordenada (x,y) caiga entre el punto (0,0) y el punto (width,height). Para saber si cae en zona de drop es comprobar si cae en el espacio de juego y además que su coordenada y sea mayor o igual que la altura menos la altura de drop.

Citarprivate bool IsSpaceZone(int x, int y)
       {
           return ((x >= 0) && (x < _width) && (y >= 0) && (y < _height));
       }

       private bool IsDropZone(int x, int y)
       {
           return (IsSpaceZone(x, y) && (y >= (_height - _dropHeight)));
       }

Transformando la coordenada de celda a rectángulo de pintado del sprite
Nos hace falta un Método que dada una coordenada (x,y) de una celda nos diga el Rect de pintado de esa celda, que se saca a partir del left, el top y los siguientes datos de sprite: ancho de sprite, alto de sprite, incremento en x, incremento en y, incremento en y por x.

Citarprivate Rectangle CellRectangle(int x, int y)
       {
           if (IsSpaceZone(x, y))
           {
               return new Rectangle(_left + x * _sprites.XIncrement, _top - y * _sprites.YIncrement
                   - x * _sprites.YIncrementForX, _sprites.SpriteRect.Width, _sprites.SpriteRect.Height);
           }
           return new Rectangle(0, 0, 0, 0);
       }

Pintando el espacio de juego

Ya tenemos todos los métodos auxiliares que necesitamos para el pintado. Para el pintado utilizaremos un método Draw que aceptará como parámetro el canvas como instancia de Graphics. El pintado será tan sencillo como recorrer cada una de las casillas del espacio de juego en el orden inidicado previamente (de abajo a arriba y de izquierda a derecha), y para cada casilla ver si está ocupada por un trozo de nuestra pieza actual, en cuyo caso pintaremos su valor y la zona de pitando será SpriteZone.Piece. Si no está ocupada por un trozo de nuestra pieza actual, pintaremos lo que haya en la matriz del espacio de juego, y además si es zona de de Drop la zona será SpriteZone.Drop, y si no lo es será SpriteZone.Game. Por último calcularemos el rectángulo en el que debemos pintar e invocaremos al método Draw de nuestra instancia de TetrisSprite:

Citarpublic void Draw(Graphics drawZone)
       {
           for (int y = 0; y < _height; y++)
           {
               for (int x = 0; x < _width; x++)
               {
                   int actualValue = _piece.PieceValueAt(x, y);
                   if (actualValue <= 0)
                   {
                       actualValue = _space[x, y];
                   }
                   SpriteZone zone;
                   if (actualValue == 0)
                   {
                       zone = IsDropZone(x, y) ? SpriteZone.Drop : SpriteZone.Game;
                   }
                   else
                   {
                       zone = SpriteZone.Piece;
                   }
                   Rectangle cellRect = CellRectangle(x, y);
                   _sprites.Draw(drawZone, actualValue, cellRect.X, cellRect.Y, zone);
               }
           }
       }

Probando lo que hay hasta ahora

En el MainForm utilizaremos la siguiente implementación:

Citarprivate readonly TetrisSprite _sprite = TetrisSprite.Instance;
       private readonly TetrisSpace _space;

       public MainForm()
       {
           Random seedGenerator = new Random();
           InitializeComponent();
           DoubleBuffered = true;
           Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos.png");
           if (inputStream != null)
           {
               Bitmap inputBitmap = new Bitmap(inputStream);
               inputStream.Close();
               _sprite.Initialize(inputBitmap, 8, true);
               inputBitmap.Dispose();
           }
           _space = new TetrisSpace(30,250,10,22,2,seedGenerator.Next());
           _space.Start();
       }

       private void MainForm_Paint(object sender, PaintEventArgs e)
       {
           _space.Draw(e.Graphics);
       }

Esto nos pintará el espacio de juego iniciado, con la primera pieza sacada:

(http://img687.imageshack.us/img687/9718/captura1hb.jpg)

Comprobando que una pieza se puede mover
Una de las partes importantes es calcular si una pieza se puede mover a la izquierda, derecha, abajo o  rotar. Para esto necesitaremos un método en el que le demos una rotación de la pieza y una posición (x,y) y compruebe si la pieza se puede poner en esa rotación y posición. Consideremos que una pieza se puede poner en una posición y rotación si cumple las siguientes condiciones:
- Ninguna de sus casillas no transparentes cae fuera del espacio de juego, excepto si es por encima de la zona de drop.
- Ninguna de sus casillas no transparentes cae encima de una casilla ocupada del espacio de juego.

Citarprivate bool TestPiece(int rotation, int left, int top)
       {
           for (int y = -1; y < _height; y++)
           {
               for (int x = -1; x <= _width; x++)
               {
                   if (_piece.PieceValueAt(x, y, rotation, left, top) == 0) continue;
                   if ((y <0 ) || (x <0) || (x >= _width))
                   {
                       return false;
                   }
                   if (_space[x, y] != 0)
                   {
                       return false;
                   }
               }
           }
           return true;
       }

Aplicando una pieza al espacio de juego

Cuando una pieza llega al tope de bajada y no puede bajar más, se aplica al espacio de juego, es decir, sus casillas se graban en la matriz del espacio de juego para poder pedir otra pieza. Además, al aplicar, debemos borrar las líneas que se hayan completado, para lo que necesitaremos métodos auxiliares para comprobar si una línea está completa, para elimitar una línea y para eliminar todas las líneas completas:

Citarprivate bool IsCompleteLine(int line)
       {
           for (int x = 0; x < _width; x++)
           {
               if (_space[x, line] == 0)
               {
                   return false;
               }
           }
           return true;
       }

       private void RemoveLine(int line)
       {
           for (int y = line; y < _height - _dropHeight; y++)
           {
               for (int x = 0; x < _width; x++)
               {
                   _space[x, y] = _space[x, y + 1];
               }
           }
       }

       private void RemoveCompleteLines()
       {
           int i = 0;
           while (i < (_height - _dropHeight))
           {
               if (IsCompleteLine(i))
               {
                   RemoveLine(i);
               }
               else
               {
                   i++;
               }
           }
       }

Para aplicar la pieza al espacio de juego se recorren las casillas del espacio de juego y si hay alguna que tenga un trozo de la pieza se aplica a la matriz:

Citarprivate void ApplyPiece()
       {
           for (int y = 0; y < _height; y++)
           {
               for (int x = 0; x < _width; x++)
               {
                   int actualValue = _piece.PieceValueAt(x, y);
                   if (actualValue != 0)
                   {
                       _space[x, y] = actualValue;
                   }
               }
           }
           RemoveCompleteLines();
       }

Realizando acciones sobre el espacio de juego

Hay 5 acciones que se pueden realizar sobre el espacio de juego con respecto a su pieza:
- Rotar la pieza
- Mover la pieza a la izquierda
- Mover la pieza a la derecha
- Mover la pieza hacia abajo
- Dejar caer la pieza.

Para representar a estas 5 acciones utilizaremos un tipo enumerado:

Citarpublic enum TetrisAction
   {
       Down,
       Rotate,
       Right,
       Left,
       Drop
   }

Además estas acciones darán un resultado entre los siguientes:
- La pieza se movió correctamente
- La pieza no se movió, sino que se aplicó al espacio de juego, se limpiaron las líneas completas y se pidió una pieza nueva
- La pieza no se pudo mover
- La pieza no se pudo mover y además alguna de sus casillas está en la drop zone.

De nuevo emplearemos un tipo enumerado:

Citarpublic enum PieceMoveResult
   {
       Moved,
       Applied,
       NotMoved,
       DropZone
   }

Las acciones de mover a la derecha, mover a la izquierda y rotar son sencillas, simplemente se prueba si se puede colocar la pieza en la nueva posición, si hay éxito se cambia la posición o rotación de la pieza y se devuelve PieceMoveResult.Moved, en caso contrario se devuelve PieceMoveResult.NotMoved.

La acción de bajar es más complicada, si se pudo mover se devuelve PieceMoveResult.Moved, en caso contrario si está en la zona de drop se devuelve PieceMoveResult.DropZone, y si no está en la DropZone se aplica la pieza al espacio de juego, se pide una nueva pieza y se devuelve PieceMoveResult.Applied.

Por último está la acción de dejar caer, que nos llevará a hacer la función recursiva porque lo que haremos será que mientras se pueda mover la pieza hacia abajo, se haga, y devuelve el último resultado que devuelva utilizar la acción TetrisAction.Down que no devuelva PieceMoveResult.Moved.

Al grano:

Citarpublic PieceMoveResult DoAction(TetrisAction action)
       {
           if (action == TetrisAction.Drop)
           {
               PieceMoveResult result = DoAction(TetrisAction.Down);
               while (result == PieceMoveResult.Moved)
               {
                   result = DoAction(TetrisAction.Down);
               }
               return result;
           }
           int rotation = _piece.Rotation;
           int x = _piece.X;
           int y = _piece.Y;
           switch (action)
           {
               case TetrisAction.Down:
                   y -= 1;
                   break;
               case TetrisAction.Left:
                   x -= 1;
                   break;
               case TetrisAction.Right:
                   x += 1;
                   break;
               case TetrisAction.Rotate:
                   rotation = _piece.NextRotation();
                   break;
           }
           if (TestPiece(rotation, x, y))
           {
               _piece.Rotation = rotation;
               _piece.X = x;
               _piece.Y = y;
               return PieceMoveResult.Moved;
           }
           if (action == TetrisAction.Down)
           {
               if (IsDropZone(_piece.X, _piece.Y))
               {
                   return PieceMoveResult.DropZone;
               }
               ApplyPiece();
               NewPiece();
               return PieceMoveResult.Applied;
           }
           return PieceMoveResult.NotMoved;
       }

Input con el usuario en el MainForm para probarlo

En el formulario principal responderemos a eventos de teclado (KeyDown) de forma que realicemos acciones sobre el TetrisSpace. Para ello añadimos el evento KeyDown del formulario con la siguiente implementación:

Citarprivate void MainForm_KeyDown(object sender, KeyEventArgs e)
       {
           switch (e.KeyCode)
           {
               case Keys.Space:
                   _space.DoAction(TetrisAction.Drop);
                   break;
               case Keys.Up:
                   _space.DoAction(TetrisAction.Rotate);
                   break;
               case Keys.Down:
                   _space.DoAction(TetrisAction.Down);
                   break;
               case Keys.Left:
                   _space.DoAction(TetrisAction.Left);
                   break;
               case Keys.Right:
                   _space.DoAction(TetrisAction.Right);
                   break;
           }
           Invalidate();
       }


Ahora ya podremos mover las piezas y ver el resultado.

Pendiente de subida de vídeo.
Pendiente de subida de código.
Título: Re: Curso de Programación Lúdica. Actualmente: Creando un Tetris
Publicado por: Bill en 05 de Mayo de 2010, 12:19
11. Creando un Tetris: Motor del juego

Introducción
Ya tenemos todo lo necesario para construir nuestro tetris. Solamente nos falta el motor, que para un sólo jugador, sin puntos ni música ni nada, es bastante sencillo porque casi toda su funcionalidad nos la da TetrisSpace.

Campos

Hacen falta tres campos para el motor:
- Un SolidBrush con un color para pintar el fondo de la pantalla.
- Una instancia de TetrisSpace.
- Un timer para cada cierto tiempo efectuar la acción de mover la pieza hacia abajo.

Citar#region · Fields ·

       private readonly SolidBrush _backgroundBrush = new SolidBrush(Color.White);

       private TetrisSpace _space;

       private readonly Timer _tetrisTimer = new Timer();

       #endregion

Constructor
En el constructor de la clase cambiaremos el color del SolidBrush al que nos pasen por parámetro. También cogerá como parámetro el Bitmap con los sprites, el número de sprites y si es isométrica, inicializando la instancia de TetrisSprite con dichos parámetros. Por último, hará que el timer invoque a DoOnTimer en su evento Elapsed, para lo que necesitamos declarar un método DoOnTimer que por ahora dejaremos vacío:

Citarprivate void DoOnTimer(Object sender, EventArgs e)
       {
       }

Citar#region · Constructor ·

       public TetrisEngine(Color backgroundColor, Bitmap srcCubeBitmap, int numCubes, bool isIsometric)
       {
           _backgroundBrush.Color = backgroundColor;
           TetrisSprite.Instance.Initialize(srcCubeBitmap, numCubes, isIsometric);
           _tetrisTimer.Elapsed += DoOnTimer;
       }

       #endregion

Inicialización
Aparte de la creación está la inicialización del espacio de juego:

Citarpublic void Initialize(int left, int top, int width, int height, int dropHeight)
       {
           Random seedRandomize = new Random();
           _space = new TetrisSpace(left, top, width, height, dropHeight, seedRandomize.Next());

       }

Declarando un evento para actualizaciones

El motor del juego necesitará informar de cuándo se ha producido un cambio en el juego y necesita ser repintado. Para ello declararemos un evento OnUpdate:

Citar#region · Events ·

       public event EventHandler OnUpdate;

       #endregion

Iniciando y parando el juego
Habrá dos métodos públicos para iniciar y para parar el juego (Start y Stop). El Start llama al Start de TetrisSpace, invoca al evento OnUpdate e inicia el timer de juego. El stop simplemente para el timer de juego:

Citarpublic void Start()
       {
           _space.Start();
           if (OnUpdate != null)
           {
               OnUpdate(this, null);
           }
           _tetrisTimer.Interval = 500;
           _tetrisTimer.Start();
       }

       public void Stop()
       {
           _tetrisTimer.Stop();
       }

El dibujado

Ahora necesitamos dibujar, además del espacio de juego, el fondo, para lo que utilizamos el método FillRectangle. Definimos nuestro método de pintado:

Citarpublic void Draw(Graphics graphicSpace)
       {
           graphicSpace.FillRectangle(_backgroundBrush, graphicSpace.ClipBounds);
           _space.Draw(graphicSpace);
       }

Realizando acciones

Ahora hay que realizar acciones, igual que hacíamos en el TetrisSpace. Para ello tenemos un método privado genérico para realizar cualquier acción, y métodos independientes para cada acción que invocan a este:

Citarprivate void DoAction(TetrisAction action)
       {
           if (_space.DoAction(action) == PieceMoveResult.DropZone)
           {
               Stop();
           }
           if (OnUpdate != null)
           {
               OnUpdate(this, null);
           }
       }
       public void MoveDown()
       {
           DoAction(TetrisAction.Down);
       }

       public void MoveLeft()
       {
           DoAction(TetrisAction.Left);
       }
       
       public void MoveRight()
       {
           DoAction(TetrisAction.Right);
       }

       public void Rotate()
       {
           DoAction(TetrisAction.Rotate);
       }

       public void Drop()
       {
           DoAction(TetrisAction.Drop);
       }

Solamente nos queda un último detalle con esto: que cuando el Timer salte, se llame a MoveDown():

       private void DoOnTimer(Object sender, EventArgs e)
       {
           MoveDown();  
       }

Adaptación del Formulario Principal

En el formulario principal ya no hará falta ni TetrisSpace ni TetrisSprite, simplemente el TetrisEngine, en el cual nos vamos a suscribir a su evento OnUpdate mediante un método DoOnUpdate que llamará al Invalidate() para repintar el canvas:
Citar
       private readonly TetrisEngine _engine;

       public MainForm()
       {
           InitializeComponent();
           DoubleBuffered = true;
           Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos.png");
           if (inputStream != null)
           {
               Bitmap inputBitmap = new Bitmap(inputStream);
               inputStream.Close();
               _engine = new TetrisEngine(Color.Wheat,inputBitmap,8,true);
               inputBitmap.Dispose();
               _engine.OnUpdate += DoOnUpdate;
               _engine.Initialize(30, 250, 10, 22, 2);
           }
       }

       private void DoOnUpdate(object sender, EventArgs e)
       {
           Invalidate();
       }

       private void MainForm_Paint(object sender, PaintEventArgs e)
       {
           _engine.Draw(e.Graphics);
       }

En el OnKeyDown responderemos a los eventos de teclado invocando a los métodos de movimiento de la instancia del engine:

Citarprivate void MainForm_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Enter:
                    _engine.Start();
                    break;
                case Keys.Space:
                    _engine.Drop();
                    break;
                case Keys.Up:
                    _engine.Rotate();
                    break;
                case Keys.Down:
                    _engine.MoveDown();
                    break;
                case Keys.Left:
                    _engine.MoveLeft();
                    break;
                case Keys.Right:
                    _engine.MoveRight();
                    break;
            }
        }

Conclusión

Ahora mismo ya tendríamos el juego funcionando. Cuando arrancamos aparece el tablero vacío, con la tecla Enter iniciamos una nueva partida. ¿Qué nos queda? Los detalles: sonido, menú, puntuación, contador de líneas, imagen de pieza siguiente, dos jugadores hot-site y dos jugadores on-line.

Iremos "tuneando" el juego poco a poco, pero en principio ya funciona ;)
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Thylzos en 05 de Mayo de 2010, 18:32
Mola o.o.

¡Más!
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 05 de Mayo de 2010, 18:35
Cita de: Thylzos en 05 de Mayo de 2010, 18:32
Mola o.o.

¡Más!

Tranqui, que ahora subo el código y vídeo ;)
De hecho, me lo has recordado. ¡Voy!
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: maikolf en 18 de Octubre de 2010, 07:23
Cita de: Gambit en 05 de Mayo de 2010, 18:35
Cita de: Thylzos en 05 de Mayo de 2010, 18:32
Mola o.o.

¡Más!

Tranqui, que ahora subo el código y vídeo ;)
De hecho, me lo has recordado. ¡Voy!

podrias subir el codigo...por favor????
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Crosher en 17 de Julio de 2011, 12:53
Esto no va a seguir? :huh:
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Genki en 17 de Julio de 2011, 12:57
pues tiene toda la pinta que no... gambit hace meses que no se pasa por aquí
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Crosher en 17 de Julio de 2011, 13:03
¿Y nadie que le conozca puede llamarle?
o alguien hacerse cargo?
Es que he empezado con muchas ganas y me acabo de dar cuenta que está parado...
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Orestes en 17 de Julio de 2011, 13:08
Pelu abandonó el foro. La última vez que hablé con él no tenía intención de volver. Despídete del curso.
Título: Re: Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Crosher en 17 de Julio de 2011, 13:09
Pues me quedo con el tetris...  :(
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 26 de Julio de 2012, 13:35
Como megaupload ha petado un poco, he perdido todo el código. Pero he vuelto a hacer el Tetris hasta dónde se había quedado la última lección, como también se habían perdido las imágenes de los cubos las he hecho en tres patadas con el paint, aunque no se ven igual, suficiente es.

El código hasta la última lección, completo, en dropbox:

http://dl.dropbox.com/u/11320362/Cientris.zip (http://dl.dropbox.com/u/11320362/Cientris.zip)

Continuaré con la forma de añadir el contador de puntos y los sonidos. Y pasaremos a otro tipo de juego.
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: raul_isl en 26 de Julio de 2012, 14:42
Y yo pensando que esto habia muerto!
Siempre he tenido la ilusion de intentarlo, pero como te piraste pues... :(
Y tampoco tengo el tiempo suficiente. A ver si algun dia consigo un trabajo con horario de personas y puedo ponerme.
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Index en 26 de Julio de 2012, 16:16
Ahí te veo. Yo también ando ocupadillo gran parte del tiempo, pero una hora diaría mínimo puedo dedicarle sin problemas, a base de constancia tiramos. Voy a volver con el tetris desde el principio mientras vas haciendo lo nuevo.
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 30 de Julio de 2012, 21:36
12. Creando un Tetris: Música y sonidos

[Introducción]
Lo primero es identificar lo que queremos hacer. Queremos poner una música de fondo mientras se está jugando, y además los siguientes sonidos:
- Cuando cae la pieza.
- Cuando se realiza línea.
- Cuando se pierde la partida.

Hacerlo con .wav es muy sencillo, pero vamos a hacerlo con sonidos .mp3 y .wma para ver cómo añadir clases que están en componentes COM. En este caso queremos añadir el componente COM del Windows Media Player, y utilizarlo. Para eso hay que ir a referencias y agregar una nueva referencia, y pinchar en la pestaña COM. Veremos que hay cientos de ellos. Vamos directamente a Windows Media Player y seleccionamos el que es wmp.dll:

(http://img51.imageshack.us/img51/7456/captura1if.png)

Ahora añadimos a resources los recursos musicales. En este caso en lugar de recursos embebidos, los marcaremos como Content, y marcaremos la opción "Copy if newer".

(http://img21.imageshack.us/img21/3403/captura2rg.png)

Y por último creamos la clase TetrisSounds para ayudarnos a utilizarlos:


using System.IO;
using System.Windows.Forms;
using WMPLib;

namespace Tetris
{
    public class TetrisSounds
    {
        #region - Fields -

        private WindowsMediaPlayer backgroundPlayer = new WindowsMediaPlayer();

        private WindowsMediaPlayer eventPlayer = new WindowsMediaPlayer();

        #endregion

        #region - Constructor -

        public TetrisSounds()
        {
            this.backgroundPlayer.URL = Path.GetDirectoryName(Application.ExecutablePath) + "\\Resources\\theme_song.wma";
            this.backgroundPlayer.settings.setMode("loop", true);
            this.backgroundPlayer.controls.stop();
        }

        #endregion

        #region - Methods -

        public void StartBackground()
        {
            this.backgroundPlayer.controls.play();
        }

        public void StopBackground()
        {
            this.backgroundPlayer.controls.stop();
        }

        public void PlaySound(string fileName)
        {
            this.eventPlayer.URL = fileName;
            this.eventPlayer.controls.play();
        }

        public void PlayDrop()
        {
            PlaySound(Path.GetDirectoryName(Application.ExecutablePath) + "\\Resources\\splat3a.wma");
        }

        public void PlayLinesRemove()
        {
            PlaySound(Path.GetDirectoryName(Application.ExecutablePath) + "\\Resources\\explosion.mp3");
        }

        public void PlayLost()
        {
            PlaySound(Path.GetDirectoryName(Application.ExecutablePath) + "\\Resources\\ohh.mp3");
        }

        #endregion
    }
}


Ahora solamente falta hacer algunas modificaciones en los lugares en los que el sonido debe comenzar.

Lo primero es en TetrisEngine añadir el field para almacenar una instancia de TetrisSounds:


        private TetrisSounds sounds = new TetrisSounds();


En el métido Start() the TetrisEngine hacer que la música comience a sonar:


        public void Start()
        {
            sounds.StartBackground();
...


Y en el Stop() que deje de sonar:


        public void Stop()
        {
            tetrisTimer.Stop();
            sounds.StopBackground();
        }


Y también modificamos su DoAction() para que si se para el juego porque se ha perdido, suene el sonido de que se ha perdido:


        private void DoAction(TetrisAction action)
        {
            if (space.DoAction(action) == PieceMoveResult.DropZone)
            {
                Stop();
                sounds.PlayLost();
            }
            if (OnUpdate != null)
            {
                OnUpdate(this, null);
            }
        }


¿Qué pasa con los otros dos sonidos? ¿El de drop y el de línea? Pues que veremos más adelante cómo introducirlos, porque para identificar cuál de los dos hay que hacer sonar, hay que saber si se han eliminado líneas, y eso se va a hacer aprovechando el contador de puntos en el siguiente capítulo.

El fichero para descargar:

http://dl.dropbox.com/u/11320362/Cientris2.zip (http://dl.dropbox.com/u/11320362/Cientris2.zip)

Este el tetris tal y como funciona en esta lección:

Tetris, lección 12 (http://www.youtube.com/watch?v=WQ84_0FpAo8#ws)

Y este es el producto casi final (le falta algún debug) para el que faltan dos lecciones:

Tetris, lección final (http://www.youtube.com/watch?v=j6FE3VINxTU#ws)



Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 01 de Agosto de 2012, 10:51
13. Creando un Tetris: Mostrar la siguiente pieza

Introducción
Para mostrar la siguiente pieza lo primero que tenemos que hacer es "ordenar" las cosas que pintamos. Es decir, ahora mismo estamos pintando en el Canvas de la ventana principal, y poniendo las coordenadas en las que queremos pintar. Pero existen componentes contenedores que sirven para agrupar otros componentes.

Pintando en un panel
Primero redimensionamos nuestra ventana principal a 510;335.
Ahora colocamos un Panel en la ventana (está en el toolbox, en la categoría containers). Lo renombramos a pnlMain.
Redimensionamos nuestro Panel a 111;277 y lo colocamos por la izquierda de la ventana:

(http://img859.imageshack.us/img859/4318/captura3j.png)

Ahora nos vamos al código del MainForm.cs y nos vamos al método DoOnUpdate, que es el que dispara el evento Update de nuestro TetrisEngine. Vemos que actualmente llama al Invalidte() del formulario, que fuerza a su repintado. Lo que queremos es que llame al Invalidate() de nuestro panel, así que lo cambiamos:


        private void DoOnUpdate(object sender, EventArgs e)
        {
            pnlMain.Invalidate();
        }


Pero claro, en el evento Paint del panel no tenemos nada, tenemos respuesta al Paint del formulario. Tenemos que quitar el evento Paint del formulario (borrar el código y sus referencias), y añadir un evento Paint del panel (pinchar en el panel, seleccionar eventos en lugar de propiedades, y doble click en Paint):


        private void pnlMain_Paint(object sender, PaintEventArgs e)
        {
            engine.Draw(e.Graphics);
        }


Y por último, cuando inicializamos nuestro engine, le pasamos coordenadas para su pintado, y hay que ajustarlas al nuevo medio:

engine.Initialize(0, 210, 10, 22, 2);

Ejecutamos y vemos un efecto extraño al jugar: se ve el refresco. Esto es por algo que ya habíamos comentado antes, el flicker. Y para evitar el flicker, lo que hay que hacer es utilizar el double buffering. El problema viene de que si bien los formularios tienen double buffer como propiedad, y es pública, el resto de componentes contenedores no, es una propiedad protegida así que no la podemos cambiar, no tenemos acceso a ella.

La solución es crear nuestra propia clase BufferedPanel que descienda de Panel y que en su constructor modifique este double buffering, dado que al descender de Panel tiene acceso a sus propiedades protegidas. Así que añadimos un BufferedPanel.cs con el siguiente código:

using System.Windows.Forms;

namespace Tetris
{
    public class BufferedPanel : Panel
    {
        public BufferedPanel()
            : base()
        {
            this.DoubleBuffered = true;
            this.UpdateStyles();
        }
    }
}


Ahora mostramos el código de MainForm.Designer.cs, que es dónde se crean las clases visuales del formulario principal, y buscamos dónde se crea nuestro pnlMain y sustituimos la clase Panel por BufferedPanel

        private void InitializeComponent()
        {
            this.pnlMain = new BufferedPanel();
            this.SuspendLayout();


Ejecutamos y ya funciona. Ya estamos listos para continuar y mostrar la pieza siguiente.

Mostrar la pieza siguiente
Lo primero es decidir en qué zona la vamos a mostrar. Así que ponemos un panel pequeñito de 78x78 en nuestro formulario principal. De nuevo, tenemos que ir al código del designer y cambiar la clase Panel por BufferedPanel para que no tenga flicker. Además le ponemos un label para indicar que se trata de la pieza siguiente:

(http://img801.imageshack.us/img801/1081/captura4l.png)

¿Dónde almacenábamos la pieza? En la instancia de TetrisSpace. Pues bien, ahí ahora además de almacenar la pieza actual hay que almacenar la siguiente, y la añadimos a sus fields:


        /// <summary>
        /// Instance of the next piece.
        /// </summary>
        private readonly TetrisPiece nextPiece;


Además modificamos el constructor de TetrisSpace para que cree esta pieza siguiente:


            nextPiece = new TetrisPiece(seed);


Ahora vamos a modificar TetrisPiece para tener dos métodos NewPiece más:
- Uno para construir una pieza siguiente, sin necesidad de más información.
- Otro para construir una pieza recibiendo además la pieza siguiente, para asignar su Id.

        /// <summary>
        /// Calculates a new piece, from a existing next piece .
        /// </summary>
        /// <param name="spaceWidth">Width of the space.</param>
        /// <param name="spaceHeight">Height of the space.</param>
        /// <param name="spaceDropHeight">Height of the space drop.</param>
        /// <param name="nextPiece">The next piece.</param>
        public void NewPiece(int spaceWidth, int spaceHeight, int spaceDropHeight, TetrisPiece nextPiece)
        {
            Id = nextPiece.Id;
            Rotation = 0;
            X = spaceWidth / 2 - CellWidth / 2;
            Y = spaceHeight - spaceDropHeight - 1 + CellHeight - PieceY[Id];
        }

        /// <summary>
        /// Calculates a new Next Piece.
        /// </summary>
        public void NewPiece()
        {
            NewPiece(CellWidth, CellHeight, 0);
            Y = 3;
        }


Volvemos al constructor de TetrisSpace y añadimos que inmediatamente después de instanciar nextPiece, además calcule su pieza siguiente con NewPiece():


        public TetrisSpace(int left, int top, int width, int height, int dropHeight, int seed)
        {
            piece = new TetrisPiece(seed);
            nextPiece = new TetrisPiece(seed);
            nextPiece.NewPiece();
       
            this.left = left;
            this.top = top;
            this.width = width;
            this.height = height;
            this.dropHeight = dropHeight;
            space = new int[width, height];
        }


Y ahora modificamos el método NewPiece de TetrisSpace para tener en cuenta que tenemos ya calculada la pieza siguiente:


        private void NewPiece()
        {
            piece.NewPiece(width, height, dropHeight, nextPiece);
            nextPiece.NewPiece();
        }


Si ejecutamos ahora, estará funcionando perfectamente, pero todavía no está pintando la pieza siguiente en su sitio. Necesitamos un método DrawNext en TetrisSpace que nos sirva para dibujar la pieza siguiente. Para ello además necesitaremos acceso a las constantes CellHeight y CellWidth de TetrisPiece, que debemos cambiarlas a visibilidad pública, y añadir el código para dibujar la pieza:


        /// <summary>
        /// Draws the next piece in a canvas.
        /// </summary>
        /// <param name="drawZone">The canvas draw zone.</param>
        public void DrawNext(Graphics drawZone)
        {
            for (int y = 0; y < TetrisPiece.CellHeight; y++)
            {
                for (int x = 0; x < TetrisPiece.CellWidth; x++)
                {
                    int actualValue = nextPiece.PieceValueAt(x, y);
                    if (actualValue <= 0)
                    {
                        actualValue = 0;
                    }
                    SpriteZone zone;
                    if (actualValue == 0)
                    {
                        zone = SpriteZone.Game;
                    }
                    else
                    {
                        zone = SpriteZone.Piece;
                    }

                    Rectangle cellRect = new Rectangle(x*sprites.XIncrement, 40-y*sprites.YIncrement-x*sprites.YIncrementForX,
                        sprites.SpriteRect.Width, sprites.SpriteRect.Height);
                    sprites.Draw(drawZone, actualValue, cellRect.X, cellRect.Y, zone);
                }
            }
        }


También necesitamos subir este DrawNext hacia TetrisEngine para permitir que se pueda pintar desde dicha clase a más alto nivel:


        /// <summary>
        /// Draws the next piece.
        /// </summary>
        /// <param name="graphicSpace">The graphic space.</param>
        public void DrawNext(Graphics graphicSpace)
        {
            graphicSpace.FillRectangle(backgroundBrush, graphicSpace.ClipBounds);
            space.DrawNext(graphicSpace);
        }


Ahora solamente queda que el MainForm sepa repintar este panel. Para ello añadimos en el DoOnUpdate el Invalidate() del panel de la pieza:


        private void DoOnUpdate(object sender, EventArgs e)
        {
            pnlMain.Invalidate();
            pnlNext.Invalidate();
        }


Y añadimos el evento Paint del pnlNext de forma que pinte la pieza siguiente:

        private void pnlNext_Paint(object sender, PaintEventArgs e)
        {
            engine.DrawNext(e.Graphics);
        }


El resultado:

(http://img62.imageshack.us/img62/3383/captura5q.png)

Aprovechamos además para cambiar el BackColor del MainForm al color Wheat, para que no se vea gris.

Y el código para descargar:

http://dl.dropbox.com/u/11320362/Cientris3.zip (http://dl.dropbox.com/u/11320362/Cientris3.zip)
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 01 de Agosto de 2012, 19:37
14. Creando un Tetris: Marcador de puntos y toques finales

Llega el momento de finiquitar nuestro Tetris. Solamente le falta el marcador de puntos, marcador de líneas conseguidas, los sonidos que habíamos dejado pendientes hasta este momento, y algún toquecito. Comencemos con los marcadores.

Marcador de puntos y líneas

Lo primero es crear los cuatro labels para los marcadores, 2 indicativos (el título) y 2 para presentar los números. Así que creamos los 4 labels, a uno lo llamaremos lblActualPoints y a otro lblActualLines, los otros dos como queráis. Además ponedlos de color diferente:

(http://img850.imageshack.us/img850/9594/captura6j.png)

En TetrisEngine creamos los Fields para almacenar los puntos y líneas de la partida actual:


        /// <summary>
        /// Actual points of the player.
        /// </summary>
        private int actualPoints = 0;

        /// <summary>
        /// Total lines removed in the actual game.
        /// </summary>
        private int totalLinesRemoved = 0;


Y creamos también sus propiedades:


        /// <summary>
        /// Gets or sets the actual points.
        /// </summary>
        /// <value>
        /// The actual points.
        /// </value>
        public int ActualPoints
        {
            get { return actualPoints; }
            set { actualPoints = value; }
        }

        /// <summary>
        /// Gets or sets the total lines removed.
        /// </summary>
        /// <value>
        /// The total lines removed.
        /// </value>
        public int TotalLinesRemoved
        {
            get { return totalLinesRemoved; }
            set { totalLinesRemoved = value; }
        }


En el método Start() de TetrisEngine deben inicializarse a 0, porque la partida empieza con los marcadores limpios:


        public void Start()
        {
            sounds.StartBackground();
            actualPoints = 0;
            totalLinesRemoved = 0;
...


Pero claro, el engine no es consciente de cuántas líneas se borran, porque lo hace la instancia de TetrisSpace. Así que vamos a modificar TetrisSpace para que devuelva el número de líneas eliminadas por la última acción.

Primero, añadirle el campo para las líneas borradas:


        /// <summary>
        /// Lines removed in the last move.
        /// </summary>
        private int linesRemoved = 0;


Y la propiedad para dicho campo:


        /// <summary>
        /// Gets or sets the lines removed in the last move.
        /// </summary>
        /// <value>
        /// The lines removed.
        /// </value>
        public int LinesRemoved
        {
            get { return linesRemoved; }
            set { linesRemoved = value; }
        }


El método DoAction de TetrisSpace es la entrada principal de las acciones, con lo cual ahí inicializaremos linesRemoved a 0:

        public PieceMoveResult DoAction(TetrisAction action)
        {
            linesRemoved = 0;
            if (action == TetrisAction.Drop)
...


Y el lugar exacto en el que TetrisSpace puede saber cuántas líneas borra, es en RemoveCompleteLines():


        private void RemoveCompleteLines()
        {
            int i = 0;
            while (i < (height - dropHeight))
            {
                if (IsCompleteLine(i))
                {
                    RemoveLine(i);
                    linesRemoved++;
                }
                else
                {


Ahora en el Engine hay que hacer que como respuesta a la realización de una acción, incremente su total de puntos y de líneas. Así que nos vamos al DoAction de TetrisSpace:


        private void DoAction(TetrisAction action)
        {
            if (space.DoAction(action) == PieceMoveResult.DropZone)
            {
                Stop();
                sounds.PlayLost();
            }
            else
            {
                totalLinesRemoved += space.LinesRemoved;
                actualPoints += space.LinesRemoved * space.LinesRemoved;
            }


Ahora el Engine ya tiene conocimiento de sus puntos y de la cantidad de líneas borradas. Nos queda que se muestren en el interfaz. ¿Dónde actualizarlo? Primero al crear la aplicación para que se pongan a 0 o lo que quiera el Engine que sea la puntuación inicial. Y luego tras la reacción a las teclas pulsadas en el evento KeyDown:


        public MainForm()
        {
            InitializeComponent();
            DoubleBuffered = true;
            Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos.png");
            if (inputStream != null)
            {
                Bitmap inputBitmap = new Bitmap(inputStream);
                inputStream.Close();
                engine = new TetrisEngine(Color.Wheat, inputBitmap, 8, true);
                inputBitmap.Dispose();
                engine.OnUpdate += DoOnUpdate;
                engine.Initialize(0, 210, 10, 22, 2);
            }
            lblActualLines.Text = engine.TotalLinesRemoved.ToString();
            lblActualPoints.Text = engine.ActualPoints.ToString();
        }


Y en el MainForm_KeyDown al final lo mismo:


                 case Keys.Left:
                    engine.MoveLeft();
                    break;
                case Keys.Right:
                    engine.MoveRight();
                    break;
            }
            lblActualLines.Text = engine.TotalLinesRemoved.ToString();
            lblActualPoints.Text = engine.ActualPoints.ToString();
        }


(http://img560.imageshack.us/img560/9916/captura7s.png)

Sonidos para el drop y línea conseguida
Hemos visto que quien se entera a la vez de la acción realizada y si la acción conlleva eliminar líneas, es el TetrisSpace. Así que tenemos dos opciones, o pasarle el sounds a TetrisSpace o que genere eventos hacia arriba. En nuestro caso vamos a hacer lo primero, modifiquemos DoAction para que pase el TetrisSounds de TetrisEngine a TetrisSpace:


        public PieceMoveResult DoAction(TetrisAction action, TetrisSounds sounds)


Dentro de ese DoAction buscamos la acción TetrisAction.Down, y justo después del ApplyPiece() reaccionamos tocando el sonido:


                if (linesRemoved > 0)
                {
                    sounds.PlayLinesRemove();
                }
                else
                {
                    sounds.PlayDrop();
                }


Ahora el propio compilador nos avisa de que en tres lugares la llamada al DoAction está mal porque falta un argumento. En esos tres lugares hay que añadir el parámetro sounds a la llamada, y listo.

Toques finales

Primero el título. Lo de Form1 no queda bien. Así que lo cambiamos por Tetris.

Segundo añadir una imagen con instrucciones, porque queda estiloso:

Añadimos al mainForm un objeto image y le cargamos esta (botón derecho, choose image):
(http://img337.imageshack.us/img337/4732/instruccioneso.png)

Y por último hacer que se pueda cambiar de vista 2D a 3D pulsando la letra c. Creamos los métodos Set2D() y Set3D() que cargan los recursos correspondientes a cada uno, así:


        private void Set3D()
        {
            isometric = true;
            Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos.png");
            if (inputStream != null)
            {
                Bitmap inputBitmap = new Bitmap(inputStream);
                inputStream.Close();
                engine.InitSprites(inputBitmap, 8, true);
                inputBitmap.Dispose();
            }
        }

        private void Set2D()
        {
            isometric = false;
            Stream inputStream = GetType().Assembly.GetManifestResourceStream("Tetris.Resources.cubos3.png");
            if (inputStream != null)
            {
                Bitmap inputBitmap = new Bitmap(inputStream);
                inputStream.Close();
                engine.InitSprites(inputBitmap, 8, false);
                inputBitmap.Dispose();
            }
        }


El campo isometric debe ser un booleano dentro del propio mainForm:


        private bool isometric = false;


Y ahora modificamos TetrisEngine para tener el método InitSprites:


        public void InitSprites(Bitmap srcCubeBitmap, int numCubes, bool isIsometric)
        {
            TetrisSprite.Instance.Initialize(srcCubeBitmap, numCubes, isIsometric);
        }


Y por último modificamos el MainForm_KeyDown para que reaccione al pulsar la "c", cambiando de 2D a 3D y viceversa:


                case Keys.C:
                    if (isometric)
                    {
                        Set2D();
                    }
                    else
                    {
                        Set3D();
                    }
                    break;


Y como la aplicación comienza en isométrica, hacer que en el constructor del MainForm inicialice la variable isometric a true.

¡Y hecho! ¡Terminado!

Código final de descarga:
http://dl.dropbox.com/u/11320362/Cientris4.zip (http://dl.dropbox.com/u/11320362/Cientris4.zip)
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 01 de Agosto de 2012, 19:47
¿Y ahora qué?

Pues si no hay nadie interesado, paro, y aquí se queda.
Si alguien quiere seguir, lo siguiente serían tres posiblidades, que se pueden abordar por orden:
1. Un arcade tipo arcanoid o 1941.
2. Aprovechando que hemos visto el tetris, ver cómo hacer un Puyo Pop, y que además se pueda combatir a través de internet con otros jugadores (1v1)
3. Aprovechando que es un foro que le gusta la estrategia y juegos similares, abordar la creación de un servidor de juegos y realizar un Zombies!, un Bang! o el que se pida.

En vuestras manos.
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Genki en 01 de Agosto de 2012, 19:51
Yo he estado rehaciendo el libro I y en unos días me meteré con el libro II

si mi opinión cuenta, diría la opción 2 o si no la 3
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 01 de Agosto de 2012, 19:56
Sí, es buena idea hacer un Puyo Pop (u otro juego que conozcas que sea 1vs1) para ver cómo afrontar las comunicaciones por internet sin servidor, es decir uno de los dos hace de hosting y el otro de cliente, así que el que hace de hosting debe tener el puerto abierto en el router. Además el Puyo Pop es similar al tetris, se puede partir de una base buena, solamente meter mejores gráficos y un motor de animaciones para que las fichas tengan ojitos o se muevan.

A partir de ahí ver cómo hacer un servidor de partidas para varios jugadores, y un estratégico, porque necesitas escalado de imagen, y otros conceptos.
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Faerindel en 01 de Agosto de 2012, 20:03
Las opciones 2 y 3 me afilan los dientes cosa mala.

¿Alguien ha hecho ya un pack con tus posts en pdf y los archivos?
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 01 de Agosto de 2012, 20:17
No que yo sepa.

Sobre lo de por dónde continuar, decidid vosotros. Yo me voy 20 días de vacaciones. Si cuando vuelva habéis decidido, mejor. Y si tenéis el material gráfico, mejor todavía.

Ya tengo Sprites base para Puyo, una colección con 1960 imágenes con los sprites. Unos ejemplos:

(http://img860.imageshack.us/img860/2259/1377o.png)
(http://img857.imageshack.us/img857/7449/1255.png)
(http://img806.imageshack.us/img806/444/1254c.png)

Para los que no conozcan el juego:

Puyo Puyo 15 th Anniversary -Arle VS Schezo (http://www.youtube.com/watch?v=v_b5TlkuncE#)
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Macsnow en 02 de Agosto de 2012, 04:58
Aquí os dejo el Libro I en Pdf maquetado, la fé de erratas os la dejo a vosotros que yo no me lo he leído todo  >_< (prometo que lo haré, de ahí que haga esto también)

Falta la imagen del capi 5

y los enlaces esos de megaupload.

Bill, no he puesto la autoria, porque no sé si quieres o que, ni que pongo :-P

Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Bill en 02 de Agosto de 2012, 06:52
Gracias Mac!!!!

En cuanto a la autoría, tampoco es que me importe mucho, no hago esto por CV  :vergu:
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Macsnow en 02 de Agosto de 2012, 07:48
De nada hombre, a mí si que me da igual lo de la autoría, y ya sé que no lo haces por CV monercio, pero a futuras generaciones les interesará la fuente digo yo :lol:

pero vamos lo que sí estaría bien es que me repusieras la imagen y los enlaces  :amo:
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Index en 02 de Agosto de 2012, 11:27
Yo voto 1 y 2, el arcade a lo 1941 molaría tela.
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Thylzos en 02 de Agosto de 2012, 14:12
Vengo desde el exilio a decir que a mí el tres me mola y además se podría usar para partidas por skype. Aunque al dos tampoco le hago ascos.

¿Falta mucho para empezar con 3D? *.*
Título: Re:Curso de Programación Lúdica. Actualmente: Tetris funcionando
Publicado por: Ydrojen en 04 de Agosto de 2012, 19:50
Cita de: Bill en 01 de Agosto de 2012, 19:56
Sí, es buena idea hacer un Puyo Pop (u otro juego que conozcas que sea 1vs1) para ver cómo afrontar las comunicaciones por internet sin servidor, es decir uno de los dos hace de hosting y el otro de cliente, así que el que hace de hosting debe tener el puerto abierto en el router. Además el Puyo Pop es similar al tetris, se puede partir de una base buena, solamente meter mejores gráficos y un motor de animaciones para que las fichas tengan ojitos o se muevan.

A partir de ahí ver cómo hacer un servidor de partidas para varios jugadores, y un estratégico, porque necesitas escalado de imagen, y otros conceptos.

Me interesa el tema de las comunicaciones, sockets y todo eso que es ahora mismo de lo que tengo menos idea porque no lo he practicado nunca y la asignatura donde se daba pude aprobarla sin estudiarme esa parte (cosa que ahora me arrepiento).

Le voy a meter un repaso al hilo para asegurarme de que no has dado nada que no sepa.
EhPortal 1.39.2 © 2024, WebDev