Archive for programación

lotu — Un framework para desarrollo de juegos en Ruby

// Marzo 5th, 2010 // No Comments » // game development, programación

ruby.jpg Pues aquí estoy con un nuevo proyecto. :)

Un framework para desarrollar juegos en Ruby.

Los antecedentes

Después de terminar mi clon de Tetris llamado rubytris, decidí darme a la tarea de implementar otro clon de los juegos de antaño —¡y uno de mis favoritos!: Missile Command.

Debo comentar que a medio camino se me ocurrió utilizar comportamientos de direccíón (steering behaviors) para modelar el movimiento de los misiles —y algunos otras entidades— para una experiencia más envolvente.

Así, le puse pausa al Missile Command y comencé a desarrollar otro proyecto llamado ruby_steering_behaviors que cuenta ya con los comportamientos necesarios para utilizarlo en mi juego nuevo).

Durante la implementación de esos dos proyectos comencé a desarrollar abstracciones y clases útiles que no tenía en rubytris (mi primer juego):

  • Estados de juego
    Auxiliado por una máquina de estados es mucho más sencillo implementar las diversas pantallas de juego, entradas (splash screens) y menús.
  • Manejador de recursos
    Para un fácil acceso a las imágenes, fuentes y sonidos.
  • Manejador de eventos
    Un sistema de disparo y captación de eventos.
  • Funciones auxiliares
    Para facilitar el despliegue de texto, imágenes, sonidos.
  • Clases útiles
    Un contador de cuadros por segundo (FPS counter).
    Un visor (viewport) para poder tener espacios virtuales de tamaños arbitrarios, con acercamientos, alejamientos y control de entrada.

Desgraciadamente el trabajo y otras actividades de mi vida cotidiana me absorbieron demasiado y dejé ambos proyectos abandonados por un rato.

Pero, ahora que logré hacerme de un tiempecito decidí retomarlos y me pregunté:
¿por qué no desarrollar un framework que incluya todo eso (más lo que salga)? ¿podría ser provechoso para alguien más? Creo que sí.

Y así nació lotu.

lotu

lotu es un framework naciente que está basado en gosu, una biblioteca para creación de juegos en 2D.

Siendo gosu una biblioteca, te provee únicamente con las funciones básicas para crear un juego y nada más.

lotu, por otro lado se encargará de hacer el proceso de creación de juegos simple e intuitivo. gosu provee las herramientas y lotu los medios. gosu da el con qué y lotu provee el cómo.

Sin un marco de trabajo (framework), eres totalmente libre de organizar tu código de la forma que más te plazca, pero corres el riesgo de caer en el caos completo.

Un framework impone ciertas convenciones, te enseña un estilo de trabajo. Si las convenciones ayudan a desarrollar de una manera más rápida y menos compleja tu proyecto, entonces podemos decir que el framework es exitoso.

Como experimento he decidido desarrollar a la par mi juego nuevo y lotu. Espero que de esta manera ambos se retroalimenten y así obtener un mejor resultado.

lotu gem

Nunca antes había hecho una gema en Ruby. Se me hacía un proceso esotérico y extraño (lotu es mi primera gema ¡que emoción!). :D

Pero jeweler realmente te la pone fácil, demasiado diría yo jeje. Si no me crees, checa este video:
Gemcutter & Jeweler

La gema la puedes instalar con:

1
sudo gem install lotu

Sin embargo si quieres ir al día con el desarrollo te aconsejo que lo cheques en github.

Otros frameworks

¿Por qué no usar un framework existente como chingu?

La razón principal es aprendizaje. ;)

¡Es hora de programar! :D

Artículos relacionados:

Cómo mostrar las sentencias SQL en la consola de Rails

// Noviembre 17th, 2009 // No Comments » // programación, tips

Al operar la consola de Rails, muchas veces quisieramos que al usar nuestros modelos se nos mostrara el SQL que se está generando.

Sólo agrega las siguientes líneas a tu archivo ~/.irbrc

1
2
3
4
5
6
7
8
if ENV['RAILS_ENV']
  # Called after the irb session is initialized and Rails has been loaded
  IRB.conf[:IRB_RC] = Proc.new do
    logger = Logger.new(STDOUT)
    ActiveRecord::Base.logger = logger
    ActiveResource::Base.logger = logger
  end
end

Ahora, cuando interactúes con la base de datos verás algo como esto:

1
2
3
>> Oficina.find 1
  Oficina Load (1.2ms)   SELECT * FROM "oficinas" WHERE ("oficinas"."id" = 1) 
=> #<Oficina id: 1, nombre: "CAMPECHE BCMR", organizacion_id: 2, activa: true>

Referencia

Showing SQL statements in the Rails console

Artículos relacionados:

Programando un PBBG en Ruby & Rails

// Noviembre 17th, 2009 // 3 Comments » // game development, programación

lobo_tuerto

Después de mi corto regreso a la programación de videojuegos, y de haber visto por ahí y leído acerca de algunos PBBGs, finalmente he decido darme a la tarea de desarrollar uno.

PBBGs

Seguramente se preguntarán ¿qué es y cómo se juega un PBBG?

PBBG == Persistent Browser Based Game
Eso básicamente quiere decir: juego persistente para navegador.

La infraestructura y herramientas necesarias para desarrollar videojuegos en el ámbito del desarrollo web no son ni remotamente cercanas a las que existen para el desarrollo de escritorio.

Así, esto se convierte básicamente en un arte, hay que diseñar y desarrollar un videojuego alrededor de una estructura de operación ya establecida como lo es el protocolo HTTP, el modelo cliente-servidor y los tiempos de respuesta acostumbrados de una página web.

Por esta razón, la gran mayoría de los PBBGs se inclinan por uno de estos dos géneros:

  • Juegos de rol
  • Juegos de estrategia

O alguna mezcla rara entre ellos.

El modelo de participación preferido y más fácil de implementar es por turnos, aunque algunos de los PBBGs más modernos están incorporando un modelo de participación en tiempo real.

Si no conoces aún algún PBBG, aquí te dejo unos enlaces para que te des una idea de cómo son y cómo se juegan:

Los juegos de estrategia tradicionalmente se dividen en: por turno (TBS) [turn based strategy] y en tiempo real (RTS) [real time strategy]. En los PBBG he visto mucho el uso de tiempo instantáneo (ITS) [instant time strategy].

Instant Time Strategy (ITS)

Por lo que he visto la estrategia en tiempo instantáneo es muy popular entre los desarrolladores de PBBGs.

Modelan combates enteros con ecuaciones y obtienen de manera inmediata el resultado de las peleas.

Aunque adecuado a la situación, este nivel de abstracción se me antoja demasiado alto para mi proyecto. Me llama la atención el implementar algo más cercano al tiempo real (o una mezcla de tiempo real y turnos).

Ahora con tecnologías como Ajax, lenguajes como Ruby y frameworks como Rails, no es tan complicado hacer un PBBG.

Ya que andamos hablando de tecnologías, les presento mi stack de desarrollo.

Mi development stack

Aquí pongo la lista de las herramientas que estoy utilizando para llevar a cabo este proyecto:

  • Linux (nada mejor para el desarrollo en general)
  • PostgreSQL (una robusta base de datos)
  • Ruby (sigo enamorado de este lenguaje)
  • Rails (web development framework)
  • jQuery (javascript framework)
  • Formtastic (excelente para lidiar con formas)
  • Authlogic (para implementar la autenticación de usuarios)
  • Haml (lenguaje para escribir las vistas HTML de la aplicación)
  • Sass (lenguaje para escribir el CSS de la aplicación)
  • Compass (framework CSS para hacer el layout de la aplicación)
  • git (version control system)
  • emacs (editor de código)

Tengo grandes planes para este PBBG: misiones, peleas entre clanes, clases variadas, habilidades especiales, mercado, subastas y una vibrante comunidad a su alrededor.

Pero como todo: debe empezar por algún lado.

Modelando los combates

Veamos un elemento que considero fundamental para este PBBG: El sistema de batallas.

En mi caso particular, si algo deseo ver funcionando primero son los combates.

Había comentado antes que quiero mis batallas en tiempo real (o algo que se le acerque). El tiempo real que puedes conseguir en una aplicación web no es el común de 60 fps de los videojuegos tradicionales.

Aquí tienes que pensar en término de peticiones por segundo a tu servidor web. GET, POST, params, sesiones, etc.

A continuación pongo una lista con algunas de las características que me gustaría ver en el sistema de batallas:

Representar y llevar a cabo un combate entre varios participantes

  • Duelos entre jugadores
  • Duelos entre NPC y jugadores
  • Duelos entre grupos de jugadores

Durante el combate los personajes podrán hacer uso de habilidades especiales, objetos y armas

  • Un guerrero puede dar un golpe especial con su arma
  • Un brujo puede hacer uso de alguna magia
  • Un guerrero puede hacer uso de una poción para curarse

En la pelea, los jugadores podrán seleccionar un objetivo para atacar

  • Un guerrero puede seleccionar al enemigo de su preferencia para recibir sus ataques

En el próximo artículo pondré algo de código del sistema de batallas, las decisiones de diseño que se tomaron y una breve explicación de cómo funciona.

Suena bien para comenzar, ¿no?

Artículos relacionados:

Un problema con MySQL 5.0

// Octubre 15th, 2009 // No Comments » // programación

postgresql-pwns-mysql

Recuerdo que hace tiempo tuve un problema en Ubuntu Server, el MySQL no se podía detener.

Después de escribir el comando:
sudo /etc/init.d/mysql stop

Se quedaba trabado en:
* Stopping MySQL database server mysqld

Y de ahí no salía.

1
sudo apt-get remove mysql-server-5.0

Tampoco ofrecía remedio.

Al parecer había un problema en un directorio, porque al tratar de respaldar las bases de datos con una simple copia el comando cp se quedaba trabado también.

Siendo una base de datos de desarrollo, no había mucho que respaldar realmente, así que eliminé el directorio de los datos y santo remedio.

El problema fue causado por un apagón en la oficina. Me pregunto que hubiera pasado si este error hubiese ocurrido en una aplicación en producción…

Artículos relacionados:

Optimizando operaciones sobre vectores en Ruby con memoization

// Julio 29th, 2009 // 1 Comment » // game development, programación

ruby.jpg

Ahora que estaba haciendo el clon del Missile Commander, me dieron ganas de implementar un movimiento más realista en los misiles.

En lugar de que simplemente tuvieran una velocidad lineal desde que salen hasta que explotan al llegar a su destino, quería que aceleraran a la hora de hacer su despegue.

Recordé que tengo un muy buen libro que habla sobre steering behaviors (comportamientos de dirección), y decidí implementarlos en Ruby.

Los steering behaviors usan mucha matemática de vectores, así que me puse a desarrollar una pequeña clase para realizar un par de cálculos comunes: longitud y normalización — conforme las necesite, le iré agregando otras operaciones útiles.

La clase Vector2d

Esta es la clasecita que me ayudará a darle vida a un sinnúmero de entidades virtuales en mis futuros proyectos. :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
require 'benchmark'
 
class Vector2d
  attr_reader :x, :y
 
  def initialize(x=0,y=0)
    clear_length
    @x = x
    @y = y
  end
 
  def clear_length
    @length = nil
    @length_sq = nil
  end
 
  def length
    Math.sqrt(length_sq)
  end
 
  def sub_memoized_length
    Math.sqrt(memoized_length_sq)
  end
 
  def memoized_length
    @length ||= Math.sqrt(length_sq)
  end
 
  def length_sq
    @x*@x + @y*@y
  end
 
  def memoized_length_sq
    @length_sq ||= @x*@x + @y*@y
  end
 
  def normalize
    Vector2d.new(@x/length, @y/length)
  end
 
  def normalize!
    @x = @x/length
    @y = @y/length
    clear_length
    self
  end
 
  def x=(x)
    clear_length
    @x = x
  end
 
  def y=(y)
    clear_length
    @y = y
  end
end
 
Benchmark.bm do |x|
  a = Vector2d.new(23,45)
 
  x.report do
    1.upto(1000000) do
      a.length
    end
  end
 
  x.report do
    1.upto(1000000) do
      a.sub_memoized_length
    end
  end
 
  x.report do
    1.upto(1000000) do
      a.memoized_length
    end
  end
end

Conforme la programaba se me ocurrió hacer unas optimizaciones, lo que dio como resultado los métodos que incluyen la palabra memoized en su nombre.

Hice unas benchmarks (pruebas de tiempo) —¡mi primer benchmark en Ruby! :D — para medir que tanto afectaban mis supuestas optimizaciones, y esto fue lo que descubrí:

1
2
3
4
5
6
7
8
9
10
-*- mode: compilation; default-directory: "~/development/gamedev/steering/" -*-
Compilation started at Wed Jul 29 23:52:19
 
/usr/bin/ruby -w /home/lobo/development/gamedev/steering/vehicle.rb 
      user     system      total        real
  1.460000   0.000000   1.460000 (  1.480273)
  1.310000   0.000000   1.310000 (  1.352205)
  0.270000   0.000000   0.270000 (  0.276391)
 
Compilation finished at Wed Jul 29 23:52:22

Una breve explicación

La prueba consistió en calcular la longitud de un vector determinado, un millón de veces.

La técnica de optimización usada se llama: Memoization.

En computación, memoization es una técnica de optimización que se usa principalmente para incrementar la velocidad de los programas de computadora al evitar que las llamadas repetidas a una función recalculen los resultados de entradas previamente procesadas.

El primer método medido:

1
2
3
  def length
    Math.sqrt(length_sq)
  end

Calcula calcula la raíz cuadrada cada vez que es llamado, además calcula la suma de los cuadrados de X y Y.
Tarda: 1.480273 segundos

El segundo método:

1
2
3
  def sub_memoized_length
    Math.sqrt(memoized_length_sq)
  end

Se ahorra el cálculo de los cuadrados de X y Y al guardar en una variable de instancia el cálculo realizado previamente.
Tarda: 1.352205 segundos

El tercer método:

1
2
3
  def memoized_length
    @length ||= Math.sqrt(length_sq)
  end

Se ahorra el cálculo de la raíz cuadrada mientras X y Y no cambien.
Tarda: 0.276391 segundos

¿Qué tal? :)

En los juegos es necesario hacer todas las optimizaciones posibles, ya que las operaciones se están realizando una y otra vez en cada ciclo del game loop.

Creo que estás me vendrán muy bien. :D

P.D. Estas pruebas fueron hechas con Ruby 1.9.

Artículos relacionados:

SHDH9 — SuperSizedNerdCore Edition

// Julio 25th, 2009 // 3 Comments » // andanzas, eventos, programación

shdh9-logo

¿Tienes una mente inquieta, te encanta programar y aprender por el sólo gusto de hacerlo? ¿Te apasiona la tecnología y conocer como funcionan las cosas?

¿Si? También a mí.

Siempre me pregunté si no existiría un lugar donde se reuniera gente afín a mi. Gente curiosa respecto a la tecnología, código, cables y arte. Hackers, geeks y nerds que pusieran sus conocimientos en acción.

Ser un lobo solitario es bueno, pero nada como andar y sentirse en manada. Se aprende más rápido si tienes una fuente dispuesta de donde aprender. Y que mejor si puedes compartir y enseñar también.

Zed Shaw ilustró muy bien en un ensayo lo que sería el lugar ideal para ir a pasar mis fines de semana. Hmph, y recién me entero de que hay algo que se le parece mucho, aquí, ¡en México! :D

Esta es la página del evento: SHDH 9 – SuperSizedNerdcore Edition (Sábado 25 de Julio de 10am a 10pm). En la wiki pueden consultar las personas que asistirán y leer sobre lo que planean hacer este día.

Realmente lamento no haber podido publicar esto con tiempo, apenas ayer en la noche (muy noche) me enteré de ello. Pero, según leí, se realiza cada seis semanas, y ahí me tendrán. :)

En concreto, el SHDH es un evento en el que varias personas se reúnen para desarrollar sus proyectos personales, compartir conocimiento, evangelizar nuevas tecnologías y en general para pasársela bien en compañía de otros geeks.

Si extrañabas un lugar como este, pues bienvenido a casa. ;)

P.D. Por cierto, le doy las gracias a mi buen ex-compañero de la ESCOM Nation84 por pasarme el dato.

Artículos relacionados:

Aprendiendo un nuevo lenguaje con ayuda del Proyecto Euler

// Julio 13th, 2009 // No Comments » // programación

lobo_tuerto

¿Cuál es la mejor manera de aprender un nuevo lenguaje de programación?

La mejor idea que he leído al respecto la ví en este artículo.

El autor sugiere resolver problemas sencillos, que poco a poco te ayuden a ir entendiendo (y a poner en práctica) las características del nuevo lenguaje. Podrías por ejemplo, entrarle a resolver los problemas que aparecen en el Proyecto Euler.

El Proyecto Euler es un conjunto de desafíos matemáticos y de programación que requieren algo más que conocimientos matemáticos para resolverse. Aunque las matemáticas pueden ayudarte a encontrar un método elegante y eficiente, el uso de una computadora y algunas habilidades de programación son requeridos para resolver la mayoría de los problemas.

La motivación para iniciar el Proyecto Euler, es el proveer una plataforma para que las mentes inquisitivas puedan entrar a áreas desconocidas y aprender nuevos conceptos en un contexto divertido y recreativo.

El ver las soluciones escritas por otras personas en el lenguaje que estamos tratando de aprender, puede ser de gran ayuda. Así podemos darnos cuenta de si no estamos escribiendo código estilo Java, en Ruby.

Recursos

Project Euler
Learning Scala With Project Euler
Practice Your Code-Fu: Programming Contests and Puzzles Online

Artículos relacionados:

Ruby 1.9 — invalid multibyte char (US-ASCII)

// Julio 13th, 2009 // No Comments » // programación

ruby.jpg

Ahora que instalé Ruby 1.9, me puse a hacer algunas pruebas. En una de esas, utilicé caracteres con acento en mis cadenas y al correr el programa, ¡bam! que me sale esto:

invalid multibyte char (US-ASCII)

Y yo con mi cara de WTF?!
Al cabo de un rato de investigar, entendí por qué sucedía esto.

El problema

Ruby 1.9 trae ya soporte para múltiples codificaciones de caracteres (character encodings). Pero —siempre hay un pero— hay que indicarle cúal es el que va a utilizar.

Esta forma de trabajar se creó para resolver el problema en el que yo escribo mi código en UTF-8, y un japonés escribe su código en Shift JIS. Ruby debería soportar eso, de hecho, la versión 1.9 lo hace. Vamos a complicar las cosas un poco más: imagina que pongo el código que escribí en UTF-8 en una gema y luego el programador japonés la utiliza en su código escrito en Shift JIS. ¿Cómo podemos hacer que trabajen ambos sin problemas?

La estrategia de Ruby 1.8 de usar una variable global para especificar la codificación no sobreviviría a una prueba como esa, era momento de un cambio de estrategia. La respuesta de Ruby 1.9 a este problema es la codificación (encoding) del código fuente.

Todo código fuente en Ruby tiene cierta codificación. Cuando creas una cadena en tu código, automáticamente le es asignada esa codificación. Esa sencilla regla resuelve adecuadamente los problemas que he descrito. Mientras la codificación de mi código fuente sea UTF-8 y la del programador japonés sea Shift JIS, mis cadenas de texto trabajarán como es debido y las de él también. Obviamente si compartimos datos, tendremos que establecer algunas reglas acerca de los formatos que compartiremos usando documentación o código que pueda adaptarse a las diferentes codificaciones, pero eso es algo que se debió estar haciendo ya de cualquier manera.

La razón por la que aparece el error mencionado arriba es que la codificación por defecto es US-ASCII.

No se por qué usaron US-ASCII en lugar de UTF-8 ¿será por rendimiento?

La solución

Debes indicar la codificación que usas en cada uno de tus archivos.

Agrega una línea como esta al principio de tus archivos (ambas formas funcionan, pero la primera fue agregada por Emacs de manera automática):

1
# -*- coding: utf-8 -*-
1
# encoding: UTF-8

Recursos

Puedes obtener más información en: Ruby 1.9’s Three Default Encodings

Artículos relacionados:

Instalando el soporte de OpenGL en Ruby

// Julio 7th, 2009 // No Comments » // programación

ruby.jpg

Si al tratar de ejecutar un programa en Ruby que requiere OpenGL te marca un error parecido a este:

/usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require’: no such file to load — gl (LoadError)

Lo puedes solucionar fácilmente con:

1
sudo gem install ruby-opengl

Artículos relacionados:

Scrum — Una metodología ágil para el desarrollo y administración de proyectos de software

// Julio 7th, 2009 // No Comments » // programación

Andando la senda de Ruby y las metodologías ágiles, me encontré con Scrum.

Directo de la Wikipedia:

Scrum es un proceso de desarrollo de software iterativo y creciente utilizado comúnmente en entornos basados en el desarrollo ágil de software.

He escuchado muchas cosas buenas acerca de Scrum, así que decidí investigar y aprender de que se trata. Este artículo fue especialmente revelador: Explicando Scrum a mi abuela.
Espero les sea igual de útil. :)

Como apoyo a la lectura, aquí les presento unos diagramas que ilustran claramente el proceso:
scrum3 scrum2 scrum1

Artículos relacionados:

FireStats icon Con la potencia de FireStats