tag:blogger.com,1999:blog-51007347266655462202024-03-05T00:33:05.874-08:00Programar para Nintendo DS y WiiProgramación de la Nintendo DS y la WiiUnknownnoreply@blogger.comBlogger50125tag:blogger.com,1999:blog-5100734726665546220.post-89596445142703576002010-06-11T00:01:00.000-07:002010-06-11T00:01:01.371-07:00Instalar DevkitPro en Linux - Ubuntu (2)En este <a href="http://devnintendods.blogspot.com/2009/09/instalar-en-linux-ubuntu.html">entrada del blog</a> ya se hizo referencia a la forma de instalar devkitpro en linux - ubuntu.<br />
<br />
A fecha de hoy la instalación ha cambiado y hemos modificado esa entrada para actualizarla. <br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinh6tc6z-PNT18V1FJA-bR7GuV5jiAxMvbOcFNtEE6p5y92U3a0r5cdZrhJVhZ3BNLQPS8Oib7vUHYJRyjKZWNgcsbHd3-f8KeBJSWcs9AdufxhWHaRlr6-6zLdEQtWZUs0_GzNGjK9ho/s1600/ubuntu-logo.gif" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinh6tc6z-PNT18V1FJA-bR7GuV5jiAxMvbOcFNtEE6p5y92U3a0r5cdZrhJVhZ3BNLQPS8Oib7vUHYJRyjKZWNgcsbHd3-f8KeBJSWcs9AdufxhWHaRlr6-6zLdEQtWZUs0_GzNGjK9ho/s320/ubuntu-logo.gif" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoTdXuhUDq4cxw89KdOSMGisQijat-BMPVfdlUD4ivD4KM3qWNFxj0IJ3QVaiz077O7MhYwYRIzr-oKwwdgvObBdd5UHwXXOM-fmmMBKrRirt6h__Q-kWDLuipfWxIQ_JMpLKuw9mU0mE/s1600/devkitlogo.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoTdXuhUDq4cxw89KdOSMGisQijat-BMPVfdlUD4ivD4KM3qWNFxj0IJ3QVaiz077O7MhYwYRIzr-oKwwdgvObBdd5UHwXXOM-fmmMBKrRirt6h__Q-kWDLuipfWxIQ_JMpLKuw9mU0mE/s320/devkitlogo.gif" /></a></div><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUVojIRKX45alQiMNdhcm8F3L5hU0aoq-4UwGJcvFV2VEE3XLWqqnMLc7xmB2_vqVymGQ52_pOXtyNuysMVU2bd7pgRbR-eJGse0-uBqlc8PljyuodWS9yE06EtP3eqkY8OelV4qBZwTs/s1600/nintendods_logo1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUVojIRKX45alQiMNdhcm8F3L5hU0aoq-4UwGJcvFV2VEE3XLWqqnMLc7xmB2_vqVymGQ52_pOXtyNuysMVU2bd7pgRbR-eJGse0-uBqlc8PljyuodWS9yE06EtP3eqkY8OelV4qBZwTs/s320/nintendods_logo1.jpg" /></a></div>SaludosUnknownnoreply@blogger.com1tag:blogger.com,1999:blog-5100734726665546220.post-53675973860398655802010-05-27T02:46:00.000-07:002010-05-27T02:47:21.173-07:00Una breve explicaciónYa siento no haber escrito en estos cuatro meses. Siempre me he estado quejando del poco tiempo que tenía, y ahora como podéis ver, ya ni siquiera actualizo el blog.<br />
<br />
<br />
La verdad es que he emprendido una aventura empresarial y ya no tengo nada de tiempo. Desde hace un par de años llevaba colaborando con un amigo en una serie de proyectos informáticos y este año ya nos hemos decidido a dar el salto.<br />
<br />
He dejado mi trabajo y nos estamos poniendo por nuestra cuenta. Como comprenderéis estoy bastante liado.<br />
<br />
En cuanto tenga algo de tiempo seguiré con el blog, ya que tengo alguna que otra idea y me gustaría poder desarrollarla en el blog.<br />
<br />
Saludos a todos y muchas graciasUnknownnoreply@blogger.com3tag:blogger.com,1999:blog-5100734726665546220.post-91115507538618712512010-01-22T00:00:00.000-08:002010-01-22T00:00:06.901-08:00Tetris para la WiiComo ya comentamos en una entrada <a href="http://devnintendods.blogspot.com/2009/11/programar-para-la-wii.html">anterior</a> vamos a ver como pasar el Tetris de la DS a la Wii.<br />
<br />
Lo primero de todo es bajar el <a href="http://sites.google.com/site/devnintendods/Home/tetris">Tetris para la DS</a>, y ponernos a cambiar las llamadas a la librería PAlib por las de la Wii. Para la Wii hay varias librerías disponibles, en nuestro caso hemos usado las librerías libwiisprite, para la parte gráfica, fat, para le acceso al disco y wpad para manejar el wiimote.<br />
<br />
Por ejemplo el #include <pa9.h> se debe cambiar por #include <wiiuse/wpad.h="">, #include <wiisprite.h> y #include <fat.h>.<br />
<br />
Por ejemplo las llamadas de tipo PA_Init, PA_InitVBL() y PA_InitText por gwd.InitVideo, donde se ha definido gwd de tipo GameWindow, fatInitDefault y WPAD_Init();.<br />
<br />
Otra cosa, las librería del Wii que he usado están en C++, por lo que hay que pasar de tetris.c a tetris.cpp. He utilizado la nomenclatura de objetos con . en vez de con ->. Esto es debido a que todos los ejemplo venían con . y como he hecho Copy/Paste pues así es como ha quedado.<br />
<br />
Este es el código para cargar el fondo:<br />
</fat.h></wiisprite.h></wiiuse/wpad.h=""></pa9.h><br />
<pre class="cpp" name="code">Image img_fondo;
if (img_fondo.LoadImage("fondo.png") != IMG_LOAD_ERROR_NONE) exit(0);
Sprite fondo;
fondo.SetImage(&img_fondo);
fondo.SetPosition(0, 0);
</pre><br />
La explicación del código sería muy fácil: primero definimos la variable img_fondo de tipo Imagen y cargamos el fondo en este objeto, con la función LoadImage. Se crea un objeto de tipo Sprite y se le asocia la imagen. Finalmente lo colocamos en la posición 0, 0 y Ya tenemos el fondo.<br />
<br />
Ahora toca cargar los tilset para las fichas y el tablero. Esto, si se ha seguido la programación del tetris de la DS, no sería necesario explicarlo mucho. Sólo comentaremos que un tileset es una zona gráfica que se puede rellenar con pequeñas imágenes para crear la imagen completa, a modo de ladrillos.<br />
<br />
Para crear una zona de tilesets (el tablero del tetris y la fichas siguiente) usaremos<br />
el objeto TiledLayer:<br />
<br />
<pre class="cpp" name="code">TiledLayer tablero_layer(TABLERO_ANCHO, TABLERO_ALTO, 8);
TiledLayer ficha_siguiente_layer(FICHA_ANCHO, FICHA_ALTO, 8);
Image tiles;
if (tiles.LoadImage("tiles16.png") != IMG_LOAD_ERROR_NONE) exit(0);
tablero_layer.SetStaticTileset(&tiles, 16, 16);
tablero_layer.SetPosition(160, 50);
ficha_siguiente_layer.SetStaticTileset(&tiles, 16, 16);
ficha_siguiente_layer.SetPosition(350, 50);
</pre><br />
La explicación sería muy parecida a la de cargar el fondo. Se han creado dos objetos de tipo TiledLayer y a ambos se les asocia una imagen como StaticTileset. Esta será la que contendrá los ladrillos. Finalmente posicionamos los dos tilesets en la pantalla.<br />
<br />
Ahora vamos a cargar todo en pantalla. Para esto se usa un LayerManager, al cual hay que asignarle los tres componentes que queremos que muestre:<br />
<br />
<pre class="cpp" name="code">LayerManager tablero_manager(3);
tablero_manager.Append(&tablero_layer);
tablero_manager.Append(&ficha_siguiente_layer);
tablero_manager.Append(&fondo);
</pre>El orden es importante, el fondo debe ir al final.<br />
<br />
En el próximo post veremos como utilizar el mando el wiimote como un mando clásico.<br />
<br />
Saludos y feliz año.<br />
<br />
P.D. Este es el primer y único desarrollo que he hecho para la Wii, así que no puedo decir si como se ha hecho es la mejor forma posible. Cargar un fondo en un objeto de tipo Sprite no parece muy correcto, pero es que no he encontrado otra forma de hacerlo. Me gustaría estudiar más a fondo la librería libogc pero, como siempre, la falta de tiempo...Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-72918082902736494952009-12-18T00:00:00.000-08:002009-12-18T00:00:11.196-08:00MegaMan ya disparaPara ver a nuestro nuevo héroe disparando he creado un nuevo proyecto.<br />
<br />
El código que he escrito lo he metido dentro de la librería devnintendods, pero no tiene que ser difícil ponerlo en otro proyecto. Por supuesto el juego está en 2D.<br />
<br />
Se ha creado un vector en la clase ScreenManager que se denomina m_dynamicSprite. Este es el vector donde se irán añadiendo los distintos elementos dinámicos del juego. En este caso son disparos, pero podrían ser otras cosas, por ejemplo los enemigos, o las casas que se van construyendo en un juego tipo Age of Empire. Los objetos que se asocian a este array deben implementar el interface DyamicSprite. De esta forma todos tendrán la función Next.<br />
<br />
Desde el bucle del juego, en GameManager se llama a la función Next de ScreenManager. Se hacen dos llamadas, una para la pantalla de arriba y otra para la pantalla de abajo:<br />
<br />
<pre class="cpp" name="code">void GameManager::Run() {
bool exit = 1;
while (exit) {
if (m_KeypadManager) {
if (Pad.Newpress.Up) {
exit = m_KeypadManager->NewpressUp();
} else if (Pad.Newpress.Left) {
exit = m_KeypadManager->NewpressLeft();
} else if (Pad.Newpress.Right) {
exit = m_KeypadManager->NewpressRight();
} else if (Pad.Newpress.Down) {
exit = m_KeypadManager->NewpressDown();
} else if (Pad.Held.Up) {
exit = m_KeypadManager->HeldUp();
} else if (Pad.Held.Left) {
exit = m_KeypadManager->HeldLeft();
} else if (Pad.Held.Right) {
exit = m_KeypadManager->HeldRight();
} else if (Pad.Held.Down) {
exit = m_KeypadManager->HeldDown();
} else {
exit = m_KeypadManager->NoKey();
}
}
m_TopScreenManager->Next();
m_BottomScreenManager->Next();
exit = exit && m_KeypadManager->BeforeVBL();
PA_WaitForVBL();
}
}
</pre><br />
ScreenManager es la que recorre el array y llama a todas las funciones Next, independientemente del tipo de objeto que sea. En nuestro caso es siempre un objeto de tipo Disparo.<br />
<br />
<pre class="cpp" name="code">void ScreenManager::Next() {
unsigned int i;
for (i = 0; i < m_dynamicSprites->size(); i++) {
DynamicSprite *dynamicSprite = m_dynamicSprites->at(i);
dynamicSprite->Next(this);
}
}
void ScreenManager::EraseDynamicSprite(DynamicSprite *dynamicSprite) {
unsigned int i;
for (i = 0; i < m_dynamicSprites->size(); i++) {
DynamicSprite *dynamic = m_dynamicSprites->at(i);
if (dynamic == dynamicSprite) {
m_dynamicSprites->erase(m_dynamicSprites->begin() + i);
delete dynamicSprite;
}
}
}
</pre><br />
Al pulsar la tecla de disparar (he puesto la flecha para arriba porque en mi emulador no funciona la A) se crea un disparo y se añade al array. La función Next del disparo es la que se encargará de mover la bala en la dirección correcta y cuando llegue al final de la pantalla destruir el propio objeto.<br />
<br />
<pre class="cpp" name="code">bool Disparo::Next(void *screenManager) {
if (m_direccion == DIRECCION_IZQUIERDA) {
int x = this->MoveLeft(VELOCIDAD);
if (x < 0) this->Stop(screenManager);
} else if (m_direccion == DIRECCION_DERECHA) {
int x = this->MoveRight(VELOCIDAD);
if (x > 256) this->Stop(screenManager);
}
return 1;
}
void Disparo::Stop(void *screenManager) {
ScreenManager *sm = (ScreenManager *)screenManager;
sm->EraseDynamicSprite(this);
}
</pre><br />
Y esto es todo. Si disparáis más de 100 veces deja de disparar. He probado y todos los destructores de las clases se ejecutan y la función PA_DeleteSprite también, pero como se ha comentado en algún post anterior, este tema parece que no va bien.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmSugkI2r34VP6urT9MFU9xq8W6CoGMnRLJM3l7DiFVTmDzM2RdPqUVxMnxk24KcRWjNgWmhz4bcByyxKuUg9uoDWXbTKyBb4JvG8gCW8OWG54Wjf9T2BWi4xAi0hx84LoRyYlHu2RFtc/s1600-h/mm_frame.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmSugkI2r34VP6urT9MFU9xq8W6CoGMnRLJM3l7DiFVTmDzM2RdPqUVxMnxk24KcRWjNgWmhz4bcByyxKuUg9uoDWXbTKyBb4JvG8gCW8OWG54Wjf9T2BWi4xAi0hx84LoRyYlHu2RFtc/s320/mm_frame.png" /></a><br />
</div><br />
En el próximo post veremos como disparar un sólo proyectil. El proyecto se puede descargar de <a href="http://sites.google.com/site/devnintendods/Home/megaman/MegaManDS_1.0.zip">aquí</a>.<br />
<br />
SaludosUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-5100734726665546220.post-4034001204011828032009-12-11T00:01:00.000-08:002009-12-11T00:01:01.785-08:00Cogiendo las monedasPor fin, Mario puede coger sus monedas y ya empieza esto a parecerse más al New Super Mario Bross de la Nintendo DS.<br />
<br />
Está quedando chulo, parece algo:<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEireY4ZrbJhYkhsVyqi9rJOzudeZbuiRIeRBEBytTLhu1hhHvSjbYSapciQxukpitxaTkb2ReVZpLj1S6w_qfnvzz0tB-dBtvRDzKuoRth-NnzobYY5-mPv4Dk_bROY_he-PNueanzFh_Y/s1600-h/cogiendo_monedas.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5402427109634729618" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEireY4ZrbJhYkhsVyqi9rJOzudeZbuiRIeRBEBytTLhu1hhHvSjbYSapciQxukpitxaTkb2ReVZpLj1S6w_qfnvzz0tB-dBtvRDzKuoRth-NnzobYY5-mPv4Dk_bROY_he-PNueanzFh_Y/s320/cogiendo_monedas.png" style="cursor: pointer; display: block; height: 320px; margin: 0px auto 10px; text-align: center; width: 213px;" /></a><br />
<br />
Se ha tenido que cambiar alguna cosilla de las librerías, pero nada demasiado raro.<br />
<br />
Para coger las monedas lo primero es saber donde están y cuanto abultan. Es por esto que se ha tenido que introducir las variables width y height dentro de la clase Sprite. De paso hemos aprovechado para limpiar un poco los constructores y dejarlo todo más fino.<br />
<br />
Dentro de la clase Sprite se han modificado e introducido las siguientes funciones:<br />
<br />
<pre class="cpp" name="code">Sprite(unsigned int screen, unsigned int background, unsigned int size, int x, int y, int width, int height);
Sprite(unsigned int screen, unsigned int background, unsigned int shape, unsigned int size, void *palette, void *sprite, int x, int y, int width, int height, int hflip);
void SetWidth(int width);
void SetHeight(int height);
void SetWidthHeight(int width, int height);
int GetWidth();
int GetHeight();
bool InSprite(int x, int y);
</pre><br />
Esta última función, InSprite mira que el punto x,y esté dentro del Sprite. En nuestro caso será dentro de la moneda y se ha codificado de la siguiente manera:<br />
<br />
<pre class="cpp" name="code">bool Sprite::InSprite(int x, int y) {
return (x >= m_x && x <= m_x + m_width && y >= m_y && y <= m_y + m_height);
}</pre><br />
<pre class="cpp" name="code"></pre><pre class="cpp" name="code">No está fino del todo, pero ya lo iremos mejorando.</pre><pre class="cpp" name="code"></pre>También hemos codificado el destructor de la clase: <br />
<br />
<pre class="cpp" name="code">Sprite::~Sprite() {
PA_StopSpriteAnim(m_screen, m_index_sprite);
PA_DeleteSprite(m_screen, m_index_sprite);
}</pre><br />
De esta forma al coger la moneda destruimos el sprite. Ahora la clase ScreenManager. En las funciones para crear Sprites y sprites de fondo se ha introducido el width y el height: <br />
<pre class="cpp" name="code">Sprite *CreateSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y, int width, int height, int hflip = 0);
Sprite *CreateBackgroundSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y, int width, int height, int hflip = 0);
</pre>Y hemos introducido más funciones para trabajar con los Sprites de fondo: <br />
<pre class="cpp" name="code">int ScreenManager::GetBackgroundSpriteIndex(int x, int y) {
unsigned int i;
for (i = 0; i < m_backgroundSprites->size(); i++) {
Sprite *sprite = m_backgroundSprites->at(i);
if (sprite->InSprite(x, y)) return i;
}
return -1;
}
Sprite *ScreenManager::GetBackgroundSprite(unsigned int i) {
return m_backgroundSprites->at(i);
}
void ScreenManager::EraseBackgroundSprite(unsigned int i) {
Sprite *sprite = m_backgroundSprites->at(i);
delete sprite;
m_backgroundSprites->erase(m_backgroundSprites->begin() + i);
}
</pre>La primera obtiene el índice de un Sprite de fondo a partir de unas coordenadas. Devolverá el primer sprite de fondo que contenga esas coordenadas. La segunda devuelve el Sprite de fondo a partir de un índice. La tercera borra un Sprite de fondo a partir de un índice. Esta última destruye el Sprite. En cuanto a código PAlib hemos usado por primera vez, creo, la función que sirve para borrar un Sprite: PA_DeleteSprite(m_screen, m_index_sprite); Se le pasa la pantalla donde está el sprite asignado y el indice que se le asoció al crearlo (no confundir con el índice de los Sprites de fondo). Para adaptar todas estas nuevas funciones a nuestro propósito, que es coger monedas al pasar sobre ellas, he introducido las siguientes líneas al final de la función BeforeVBL de la clase NSMB.cpp: <br />
<pre class="cpp" name="code">int i = topScreen->GetBackgroundSpriteIndex(mario->GetX() + 8, mario->GetY() + 8);
if (i > -1) { //hemos pillado moneda
topScreen->EraseBackgroundSprite(i);
puntuacion_monedas++;
PA_OutputText(SCREEN_BOTTOM, 1, 1, "monedas = %d ", puntuacion_monedas); // para debugear
}
</pre><br />
El código lo podéis encontrar en esta <a href="http://sites.google.com/site/devnintendods/Home/nsmb/SuperMarioDS_0.8.zip">dirección</a>.<br />
<br />
Esto es todo por ahora.<br />
<br />
SaludosUnknownnoreply@blogger.com1tag:blogger.com,1999:blog-5100734726665546220.post-36012268285354252222009-12-04T00:00:00.000-08:002010-05-31T01:39:44.832-07:00Cargamos las monedas (II)Hemos encontrado un problema a la hora de cargar las monedas. La función de clonar tiene la peculiaridad de que clona incluso el comportamiento del Sprite, en este caso la animación.<br />
<br />
Eso nos venía muy bien hasta ahora, porque todas la monedas se ponían a girar alegremente. Pero ahora, al coger las monedas, las borramos y las paramos (si no se hace esto aparecen efectos raros en la pantalla).<br />
<br />
Al parar la primera moneda (la de más arriba), de la que hemos clonado todas, se paraban todas. Así que hemos modificado la función de clonar añadiendo nuevos parámetros (opcionales):<br />
<br />
<pre class="cpp" name="code">//en ScreenManager.h
void LoadBackgroundSprites(Sprite *sprite, int *map, int map_columns, int map_rows, unsigned int firstframe = 0, unsigned int lastframe = 0, unsigned int speed = 0);
//en ScreenManager.cpp
void ScreenManager::LoadBackgroundSprites(Sprite *sprite, int *map, int map_columns, int map_rows, unsigned int firstframe, unsigned int lastframe, unsigned int speed) {
unsigned int i;
unsigned int length = map_columns * map_rows;
bool primero = true;
for (i = 0; i < length; i++)
if (map[i] > 0) {
int y = i / map_columns;
int x = i - (y * map_columns);
if (primero) {
sprite->SetXY(x * 16, y * 16);
primero = false;
} else {
Sprite *newSprite = CloneBackgroundSprite(sprite, x * 16, y * 16);
if (speed > 0) {
newSprite->SetAnim(firstframe, lastframe, speed);
newSprite->StartAnim();
}
}
}
}
</pre><br />
Lo nuevo de la función está al final:<br />
<br />
Si la velocidad de la animación es mayor de cero entonces preparamos el sprite para animarlo y comenzamos la animación. De esta forma cada sprite es animado de forma independiente y no depende del primer sprite.<br />
<br />
Ya se pode descargar <a href="http://sites.google.com/site/devnintendods/Home/nsmb/NSMB_mapas_0.4.zip">el editor de mapas</a>.<br />
<br />
Saludos<br />
<br />
P.D: Es importante parar el Sprite a la hora de borrarlo, por lo que estas dos líneas deben ir juntas, si no darán problemas el resto de sprites. En el destructor de la clase Sprite hemos escrito el siguiente código:<br />
<pre class="cpp" name="code">Sprite::~Sprite() {
PA_StopSpriteAnim(m_screen, m_index_sprite);
PA_DeleteSprite(m_screen, m_index_sprite);
}
</pre><br />
y se invoca de esta forma:<br />
<pre class="cpp" name="code">delete sprite;
</pre><br />
Borra el objeto sprite, y de esta forma se ejecuta el destructor de la clase Sprite.<br />
<br />
Aún así el tema no va bien. Si creas y destruyes muchos Sprites al final el sistema no permite crear más o aunque los cree no se ven correctamente, parece un problema de PAlib.<br />
<br />
SaludosUnknownnoreply@blogger.com1tag:blogger.com,1999:blog-5100734726665546220.post-53501230203775089252009-12-02T00:12:00.000-08:002017-02-17T00:04:21.099-08:00Un juego tipo ShooterO lo que es lo mismo uno de disparar.<br />
<br />
Hace un par de semanas respondimos a un comentario de como hacer un juego de disparos. Hemos preparado una nueva versión de la librería devnintendods para que permita a nuestros héroes disparar.<br />
<br />
En su momento se respondió con una explicación técnica de como es posible hacerlo. Esta era más o menos la explicación que se dio: se crea un array o vector y ahí se van acumulando todos los disparos que se vayan efectuando. El motor del juego recorrería ese array en cada ciclo del bucle del juego y moverá los disparos a su siguiente posición.<br />
<br />
Hemos diferenciado dos tipos de juegos, los que puede hacer un disparo cada vez (no se puede hacer otro hasta que no acabe el anterior) y otro con disparos ilimitados.<br />
<br />
Hemos preparado un nuevo desarrollo basado en el popular personaje de Megaman y nos hemos puesto a pegar tiros como locos por la pantalla.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://upload.wikimedia.org/wikipedia/en/f/f7/Mega_Man_(Mega_Man_9).png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://upload.wikimedia.org/wikipedia/en/f/f7/Mega_Man_(Mega_Man_9).png" width="279" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
Las próximas semanas iremos publicando el código y la explicación de como se ha hecho.<br />
<br />
Saludos<br />
<br />
P.D. En cuanto a la programación en C++ es interesante ver como se ha preparado un Interface. Para los que trabajen en Java parece algo trivial pero a la hora de trabajar en C++ no me ha parecido tan sencillo. Lo veremos en los próximos post.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-7475409862609053252009-11-27T00:01:00.000-08:002009-11-27T00:01:00.801-08:00Qué se necesita para programar en WiiO mejor dicho que he usado yo. En primer lugar, deciros que hay un emulador para Wii o gamecube que se llama dolphin-emu. Pero parece ser que necesita un montón de recursos. Yo lo he intentado ejecutar y me ha sido imposible.<br /><br />Así que una vez más os voy a mostrar la forma 'chapucera' que tengo de trabajar con la Wii. En primer lugar vemos mi 'laboratorio'. Tengo un router wifi, un ordenador (en mi caso un portátil con ubuntu) y la Wii, estos dos últimos conectados al router, que es por él por donde salgo a Internet.<br /><br />Me he bajado el <a href="http://ftpii.googlecode.com/files/ftpii_0.0.19.zip">ftpii</a> que es un servidor de ftp para la Wii. Lo he copiado a la tarjeta SD de la Wii (dentro de apps) en una carpeta que he llama ftpii_clave, donde clave será nuestra contraseña de entrada.<br /><br />En el Homebrew channel saldrá el ftpii como un programa a ejecutar. Lo hacemos y nos mostrará la IP con la que sirve los ficheros. Pues nada cogemos nuestro cliente de ftp (en mi caso el filezilla) que estará instalado en el portátil y nos conectamos a esa IP. Si la carpeta la hemos llamado ftpii_clave habrá que usar 'clave' como la contraseña de la cuenta.<br /><br />Y ya está, tenemos acceso a la tarjeta SD de la Wii, sin tener que estar manipulándola todo el rato. Dentro de apps creo la carpeta del juego que estoy compilando y, eso sí, cambio el nombre del archivo ejecutable mi_programa.dol por boot.dol.<br /><br />Para probar yo os animaría a instalar de esta forma cualquier otro programa homebrew que bajéis de Internet.<br /><br />SaludosUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-5100734726665546220.post-18668984374994286272009-11-20T00:01:00.000-08:002009-11-20T00:01:00.882-08:00Cargamos las monedasVamos a cargar las monedas en el mundo de New Super Mario Bros, y para hacer esto utilizaremos el programa que nos genera los mapas.<br /><br />Se ha agregado una nueva opción al generador de mapas para que permita editar una capa denominada coins (monedas). En la siguinete imagen se puede ver al editor a pleno rendimiento:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs14QrboFQltT-yCLndDKgbYwWsJIZjKACf1R7bonQGdiUYrPeB08u5rNynZvmkvP5-673A0RadPMbGa_Ojx3q9cqhAE0v-voxVWbdoHWqew7HrUH2Sl3_AeMLk5IeV7Acllgj1LBa3mE/s1600-h/java.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 167px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjs14QrboFQltT-yCLndDKgbYwWsJIZjKACf1R7bonQGdiUYrPeB08u5rNynZvmkvP5-673A0RadPMbGa_Ojx3q9cqhAE0v-voxVWbdoHWqew7HrUH2Sl3_AeMLk5IeV7Acllgj1LBa3mE/s320/java.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5402041267437983938" /></a><br /><br />El editor al guardar generará un nuevo fichero que se llamará coins_mapa_8_nombre del txt) y coins_mapa_16_nombre del txt). Este último será el que utilizaremos. <br /><br />ahora veamos los cambios en el código del juego.<br /><br />En primer lugar seguimos añadiendo funcionalidades a las librerías:<br />En la clase ScreenManager.h se ha añadido una función para cargar <a href="http://devnintendods.blogspot.com/2009/04/las-monedas.html">sprites de fondo</a> a partir de una array (el que genera el editor de mapas):<br /><pre name="code" class="cpp"><br /> /**<br /> * Carga una serie de sprites de tipo background a partir de un mapa y de un primer sprite de tipo background<br /> * ya cargado.<br /> * Este primwr sprite será reubicado a la priemra posición indicada por el mapa.<br /> *<br /> * @param sprite El sprite a cargar<br /> * @param map mapa que indica donde colocar cada sprite<br /> * @param mapCols número de columnas del mapa<br /> */<br /> void LoadBackgroundSprites(Sprite *sprite, int *map, int map_columns, int map_rows);<br /></pre><br /><br />En ScreenManager.cpp hemos codificado la funcion de la siguiente forma:<br /><br /><pre name="code" class="cpp"><br />void ScreenManager::LoadBackgroundSprites(Sprite *sprite, int *map, int map_columns, int map_rows) {<br /> unsigned int i;<br /> unsigned int length = map_columns * map_rows;<br /> bool primero = true;<br /> for (i = 0; i < length; i++)<br /> if (map[i] > 0) {<br /> int y = i / map_columns;<br /> int x = i - (y * map_columns);<br /> if (primero) {<br /> sprite->SetXY(x * 16, y * 16);<br /> primero = false;<br /> } else CloneBackgroundSprite(sprite, x * 16, y * 16);<br /> }<br />}<br /></pre><br />Lo que hace esta función es coger un sprite de fondo y un array y donde el array le indique coloca un copia del sprite de fondo, que en este caso serán modenas.<br /><br />Vamos a ver como se usa esta nueva función en nuestro juego:<br /><br /><pre name="code" class="cpp"><br />int coins_map[48 * 12] = {<br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 56, 0, 56, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, <br /> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0<br />};<br />#define COINS_MAPA coins_map, 48, 12<br /><br />....<br /><br />Sprite *coin = topScreen->CreateBackgroundSprite(BACKGROUND_THREE, COIN, 0, 0);<br />coin->SetAnim(0, 3, 4);<br />coin->StartAnim();<br />topScreen->LoadBackgroundSprites(coin, COINS_MAPA); <br /></pre><br /><br />La explicación sería algo así: <br />Carga una primera moneda (las coordenadas dan igual, en este caso se ha puesto 0, 0),<br />Se anima el sprite,<br />y finalmente se cargan tantas monedas como diga el mapa.<br /><br />Los números que aparecen en el mapa no es importante (por ahora). Sólo es importante que sea cero donde no va moneda y distinto de cero donde queremos una moneda.<br /><br />Nos falta coger las dichosas monedas!!<br /><br />En el próximo post intentaremos cogerlas y de paso publicaremos código.<br /><br />SaludosUnknownnoreply@blogger.com3tag:blogger.com,1999:blog-5100734726665546220.post-11230136819110855642009-11-13T00:01:00.000-08:002009-11-13T00:01:03.686-08:00Programar para la WiiYa desde el <a href="http://devnintendods.blogspot.com/2008/03/bienvenido-al-blog.html">primer post</a> teníamos intención de programar algo para la Wii, y no ha sido hasta el pasado mes de Octubre que tuvimos un par de tardes libre y pudimos hacer las primeras pruebas.<br />
<br />
En este post vamos a mostrar como preparar la instalación de devkitpro para poder compilar juegos para la Wii. En su día preparamos una instalación sobre <a href="http://devnintendods.blogspot.com/2009/09/instalar-en-linux-ubuntu.html">ubuntu</a> y ahora vamos a hacer que esa misma instalación soporte a la Wii, y a la Game Cube que es lo mismo.<br />
<br />
En resumen podemos decir que es lo mismo que el otro día pero instalando las librerías libogc en vez de libnds. Vamos a ver paso a paso:<br />
<br />
Lo primero será bajar todo lo necesario:<br />
<br />
Bajar devkitPPC de http://sourceforge.net/projects/devkitpro/files/ (si no lo tenemos instalado ya)<br />
libogc -> http://sourceforge.net/projects/devkitpro/files/libogc/ (libogc-1.7.1.tar.bz2)<br />
libfat-ogc -> http://sourceforge.net/projects/devkitpro/files/libfat/ (libfat-ogc-1.0.4.tar.bz2)<br />
Wii examples (optional) -> http://sourceforge.net/projects/devkitpro/files/examples/ (wii-examples-20090509.tar.bz2)<br />
<br />
En segundo lugar todos estos comandos:<br />
$ cd Escritorio<br />
<br />
(Si no tenemos instalado devkitpro)<br />
$ sudo mkdir /usr/local/devkitpro 'si ni existiera ya<br />
$ sudo chmod 777 /usr/local/devkitpro 'si ni existiera ya<br />
$ sudo bunzip2 devkitARM_r26-i686-linux.tar.bz2<br />
$ sudo tar xvf devkitARM_r26-i686-linux.tar -C /usr/local/devkitpro<br />
<br />
(Seguimos)<br />
$ sudo bunzip2 devkitPPC_r17-i686-linux.tar.bz2<br />
$ sudo tar xvf devkitPPC_r17-i686-linux.tar -C /usr/local/devkitpro<br />
$ sudo mkdir /usr/local/devkitpro/libogc<br />
$ sudo chmod 777 /usr/local/devkitpro/libogc<br />
$ sudo bunzip2 libogc-1.7.1.tar.bz2<br />
$ sudo tar xvf libogc-1.7.1.tar -C /usr/local/devkitpro/libogc<br />
$ sudo bunzip2 libfat-ogc-1.0.4.tar.bz2<br />
$ sudo tar xvf libfat-ogc-1.0.4.tar -C /usr/local/devkitpro/libogc<br />
<br />
Ahora añadimos unas variables de contexto:<br />
<br />
$ gksudo gedit /etc/environment<br />
<br />
y añadimos al final las siguientes líneas:<br />
<br />
DEVKITPRO="/usr/local/devkitpro"<br />
DEVKITARM="/usr/local/devkitpro/devkitARM"<br />
DEVKITPPC="/usr/local/devkitpro/devkitPPC"<br />
<br />
Reiniciando la máquina ya podremos compilar los ejemplos.<br />
<br />
Instalar libwiisprite:<br />
<br />
Descargar de http://chaosteil.googlepages.com/libwiisprite-0.3.0b.tar.gz<br />
<br />
Lo descomprimos en el mismo lugar donde lo descargamos y realizamos los siguientes pasos:<br />
<br />
De la carpeta libwiisprite/libwiisprite/include copiamos todos los archivos a /usr/local/devkitpro/libogc/include<br />
(en mi caso he ejecutado la siguiente acción desde un terminal: sudo cp /home/inigo/Escritorio/libwiisprite/libwiisprite/include/*.h /usr/local/devkitpro/libogc/include)<br />
Ahora sudo cp /home/inigo/Escritorio/libwiisprite/libwiisprite/lib/*.a /usr/local/devkitpro/libogc/lib/wii<br />
<br />
Lo mismo con la carpeta libwiisprite/libpng:<br />
sudo cp /home/inigo/Escritorio/libwiisprite/libpng/include/*.h /usr/local/devkitpro/libogc/include<br />
sudo cp /home/inigo/Escritorio/libwiisprite/libpng/lib/*.a /usr/local/devkitpro/libogc/lib/wii<br />
<br />
Yo en este punto tuve un problema con libwiisprite y realicé los siguientes pasos:<br />
<br />
Bajar una nueva compilación de http://www.mediafire.com/download.php?wwycxmg0j0x<br />
y ejecutar: sudo cp /home/inigo/Escritorio/libwiisprite.a /usr/local/devkitpro/libogc/lib/wii<br />
<br />
Descargar con Synaptic la librería libfreeimage<br />
<br />
Si todo ha ido bien ya se podrá compilar los ejemplos que vienen con la librería.<br />
<br />
Hemos instalado la librería libwiisprite, hay más librerías pero nosotros sólo vamos a usar esta, por ahora.<br />
<br />
Y que vamos a hacer nosotros en este blog, pues algo muy sencillo, vamos a pasar el <a href="http://devnintendods.blogspot.com/2009/03/nueva-version-del-tetris.html">Tetris </a>que hicimos para la DS a la Wii!!!<br />
<br />
Para ir abriendo boca os dejo un video para que veáis como ha quedado el juego, si os fijaís bien es el mismo que el de la nintendo DS (sólo hemos cambiado el fondo).<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/QuxucfJIGNE&hl=es&fs=1&"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/QuxucfJIGNE&hl=es&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object><br />
<br />
Saludos<br />
<br />
P.D. En los siguientes post sobre Wii veremos como trabajo con ella, pero lo que no puedo explicar bien es como crear el Homebrew channel. Lo hice hace un año y ahora hay nuevas formas de hacerlo y no tengo ni idea.<br />
<br />
P.D. Seguimos con el tema del New Super Mario Bros. El próximo post será para él.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5100734726665546220.post-21481265453569135822009-11-10T03:08:00.001-08:002009-11-10T04:04:40.042-08:00RetomamosHa habido un cierre temporal del blog estos meses, que espero que sea eso, temporal.<br />
<br />
Como penitencia voy a crear unos post hablando de la Wii y de como programar para ella. Ya tengo portado el tetris (por ahora usando el mando como un pad) y no hemos pasado el New Super Mario Bros, porque lo van a hacer los de Nintendo este mes y no era cuestión de adelantarnos a ellos :D<br />
<br />
Por supuesto, seguiremos con el New Super Mario Bros para la Nintendo DS.<br />
<br />
Este viernes posteamos fijo!!!<br />
<br />
Saludos<br />
<br />
P.D. Hemos cambiado el título del blog, ahora es Programar para la Nintendo DS y Wii, la url por supuesto sigue igual!!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-5100734726665546220.post-46027173552516697182009-09-18T00:00:00.000-07:002009-11-09T08:55:53.642-08:00La aventura de MarioPor fin ponemos a Mario en su sitio. Mario se hace dueño y señor de su mundo. Un juego que se llama New Super Mario Bros y que no saliera él por ningún sitio era algo extraño. Pues nada un poco de photoshop para ponerle guapo y ya está. Quitamos a koopa y ponemos a Mario.<br /><br />Nos ha hecho cambiar alguna cosa más, como por ejemplo el mario_collision_map. Es que este Mario es un poco más bajito que Koopa. También cambia el número de frames que forman la animación (el número de imágenes que representan el movimiento).<br /><br />El aspecto de nuestro juego DS es el siguient:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl1ALYi-nVMEnlH2QIxqVzHlD1alcF6den04HzCJFJLBpxjzUf8hV7xq-SrpHc7TIe58RMp7AflHhixu_JN17-D-dU8sC9VB2TLA3QYzF4Ikfji-iuOszsAq9qGslIH8u7lCzGQr-4r_M/s1600-h/mario.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 256px; height: 192px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgl1ALYi-nVMEnlH2QIxqVzHlD1alcF6den04HzCJFJLBpxjzUf8hV7xq-SrpHc7TIe58RMp7AflHhixu_JN17-D-dU8sC9VB2TLA3QYzF4Ikfji-iuOszsAq9qGslIH8u7lCzGQr-4r_M/s320/mario.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5376020741033912402" /></a><br /><br />Es el Mario pequeñito. Ya pondremos al intermedio, porque el grande es otra historia.<br /><br />SaludosUnknownnoreply@blogger.com1tag:blogger.com,1999:blog-5100734726665546220.post-72071122972103729492009-09-11T00:00:00.000-07:002010-06-10T00:56:08.740-07:00Instalar DevkitPro en linux - UbuntuHemos instalado devkitpro y PAlib en una distribución de Ubuntu.<br />
<br />
Hemos seguido los siguientes pasos:<br />
<br />
Hemos descargado de la red los siguientes ficheros:<br />
<br />
devkitarm, libNds, DSwifi, libfat de <a href="http://sourceforge.net/project/showfiles.php?group_id=114505" target="_blank">http://sourceforge.net/project/showfiles.php?group_id=114505</a><br />
y PAlib: <a href="http://www.palib.info/wiki/doku.php" target="_blank">http://www.palib.info/wiki/doku.php</a><br />
<br />
Se han descargado en el Escritorio. Abrimos un terminal y ejecutamos los siguientes comandos:<br />
<br />
$ cd Escritorio<br />
$ sudo mkdir /usr/local/devkitpro<br />
$ sudo chmod 777 /usr/local/devkitpro<br />
$ sudo bunzip2 devkitARM_r26-i686-linux.tar.bz2<br />
$ sudo tar xvf devkitARM_r26-i686-linux.tar -C /usr/local/devkitpro<br />
$ sudo mkdir /usr/local/devkitpro/libnds<br />
$ sudo chmod 777 /usr/local/devkitpro/libnds<br />
$ sudo bunzip2 libnds-1.3.6.tar.bz2<br />
$ sudo tar xvf libnds-1.3.6.tar -C /usr/local/devkitpro/libnds<br />
$ sudo bunzip2 dswifi-0.3.9.tar.bz2<br />
$ sudo tar xvf dswifi-0.3.9.tar -C /usr/local/devkitpro/libnds<br />
$ sudo bunzip2 libfat-nds-20070127.tar.bz2<br />
$ sudo tar xvf libfat-nds-20070127.tar -C /usr/local/devkitpro/libnds<br />
$ sudo mkdir /usr/local/devkitpro/PAlib<br />
$ sudo chmod 777 /usr/local/devkitpro/PAlib<br />
<br />
Aquí me cansé de lanzar tantos comandos y lo que hice fue copiar con el explorador de archivos el <br />
fichero PAlib99999.7z a devkitpro y con el ratón ejecutar descomprimir aquí.<br />
<br />
Para acabar lanzamos el siguiente comando:<br />
$ gksudo gedit /etc/environment<br />
<br />
y añadimos al final las siguientes líneas:<br />
<br />
DEVKITPRO="/usr/local/devkitpro"<br />
DEVKITARM="/usr/local/devkitpro/devkitARM"<br />
PAPATH="/usr/local/devkitpro/PAlib"<br />
<br />
Para instalar un emulador realizamos los siguientes pasos:<br />
<br />
En el menú principal: Sistema/administración/gestor de paquetes synaptic<br />
buscamos 'Desmume' y lo bajamos. Son dos paquetes.<br />
<br />
Y ya está todo.<br />
<br />
He creado la carpeta devDS en /home/inigo/devDS (donde inigo es mi usuario) y ahí he copiado el proyecto. Dentro de SuperMarioDS se puede ejecutar (desde el terminal) la sentencia make. Una vez compilado para ejecutarlo escribimos desmume SuperMarioDS.nds y ...<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGHfBabMoZK0tt58jH0WHhvEwh-JopWQjAZQcxLxL1HsRknXkAJTnNGx0bNVZAxu1_VCBwP3LkTTF2Aj69Wq59266sHKRC9r4glXumjSchRaW0IjeJOWwy93JgRMAdLU4bnhdLSIvwzw/s1600-h/Pantallazo.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5376610063073138370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiGHfBabMoZK0tt58jH0WHhvEwh-JopWQjAZQcxLxL1HsRknXkAJTnNGx0bNVZAxu1_VCBwP3LkTTF2Aj69Wq59266sHKRC9r4glXumjSchRaW0IjeJOWwy93JgRMAdLU4bnhdLSIvwzw/s320/Pantallazo.png" style="cursor: pointer; display: block; height: 240px; margin: 0px auto 10px; text-align: center; width: 320px;" /></a><br />
<br />
Es Mario y no Koopa!!.....la semana que viene lo vemos.<br />
<br />
Saludos<br />
<br />
NOTA:<br />
A fecha de <b>Junio de 2010</b> esta ayuda ya no va bien. Además de los ficheros que se han instalado es necesario bajarse otros más como son maxmod_ns, libfilesystem y default arm7. Todos estos ficheros los hemos instalado en la carpeta libnds.<br />
Os pongo el link a la wiki de devkitpro donde explica todo: <a href="http://wiki.devkitpro.org/index.php/Getting_Started/devkitARM">http://wiki.devkitpro.org/index.php/Getting_Started/devkitARM</a><br />
<br />
Existe otro forma de instalarlo y es ejecutando un script (devkitpro.sh) que puedes bajar de la página <a href="http://lmn.mooo.com/projects/devkitpro-sh/">http://lmn.mooo.com/projects/devkitpro-sh/</a>. Este script se pueden modificar las primeras líneas para que no instale lo que no se quiera:<br />
INSTALL_PALIB="yes"<br />
INSTALL_ULIB="yes"<br />
INSTALL_NOCASHGBA="yes"<br />
<br />
Se cambia el 'yes' por otra cosa y esa librería o programa no se instala. Te pide tener instalado el 7zr y el unrar. estos se instalan escribiendo en la consola: sudo apt-get install p7zip y sudo apt-get install unrar.<br />
<br />
Acordarse de dar permisos de ejecución al script: chmod a+x devkitpro.sh<br />
<br />
Aunque todo esto lo explican más o menos en la página web.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-5100734726665546220.post-91253241749464746832009-09-04T00:10:00.000-07:002009-12-10T01:15:32.663-08:00Nueva versión del entorno de desarrolloTenemos nueva versión de devkitPro y parece que muchos de los problemas de instalación han desaparecido. Ya no hace falta cambiar algunas de las librerías que vienen por defecto con el devkitPro para que PAlib funcione.<br />
<br />
Pero sí que va a ser necesario cambiar algo de nuestro código. Pero eso lo veremos más adelante.<br />
<br />
Ahora mismo los pasos para instalar el entorno de homebrew de la nintendo DS son los siguientes:<br />
<br />
Para instalar devkitPro en windows:<br />
<br />
1. Bajar devkitPro Updater 1.5.0 de esta <a href="http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitProUpdater-1.5.0.exe" target="_blank">dirección</a>.<br />
2. En una de las pantallas nos muestra esta opción 'Download and install/install from downloaded files' la dejamos pulsada y seguimos<br />
3. La siguiente nos preunta que hacer con los ficheros que ha bajado. Por defecto está seleccionada Keep downloaded files, que lo único que hace es dejar todos los ficheros en la carpeta de descargas. Yo lo dejé por si tenía algún problema. Cada uno... Seguimos.<br />
4. Seleccionamos devkitARM -> para trabajar con la DS (la que usamos en este blog)<br />
devkitPPC -> para gamecube/wii <br />
devkitPSP -> para la PSP <br />
2. A la hora de instalarlo Lo instalaremos en c:\devkitPro (Instalarlo donde queráis pero que la ruta no tenga espacios en blanco)<br />
6. Se tirará un ratito bajando e instalando cosas...<br />
<br />
Y ya está, ahora le toca el turno a PAlib.<br />
<br />
7. Bajamos la última <a href="http://forum.palib.info/index.php?topic=7048.0" target="_blank">versión</a> (es una beta).<br />
8. Creamos la carpeta c:\devkitPro\PAlib y descomprimimos el zip PAlib090801.7z ahí.<br />
<br />
Y ya está todo!!!!.<br />
<br />
Ahora un emulador. Yo he bajado no$gba y lo he instalado en C:\devkitPro\emulators\no$gba.<br />
<br />
Ahora le toca el turno a nuestro programa, el SuperMarioDS. <br />
<br />
Hay que cambiar una serie de cosas en el código, así que crearemos un proyecto nuevo y trasladaremos las cosas del antiguo a este. Lo primero que hacemos es copiar la carpeta C:\devkitPro\PAlib\template a c:\devDS o donde trabajemos. Cambiamos el nombre template por SuperMarioDS y borramos el fichero main.c de source. Yo para hecer esto renombre el antiguo SuperMarioDS por SuperMarioDS_old<br />
<br />
Si nos fijamos las carpetas han cambiado un poco. El mayor cambio es la carpeta gfx, que pasa de source a estar al nivel de todas las demás. El programa ha cambiado un poco así que únicamente copiaremos los ficheros PNG a la nueva carpeta. El ini ha cambiado, también, así que lanzamos el programa PAGfxFrontend.exe (se necesita tener instalado .net) y se cargan como sprites lo siguientes ficheros: coin.png, goomba.png y koopa.png<br />
Como backgrounds se cargarán estos otros: fondo_azul.png, newImage_0.png, newImage_1.png<br />
<br />
Salvamos y generamos, ningún problema. Sólo que únicamente crea all_gfx.h y NO all_gfx.c. Tendremos que quitar esa referencia.<br />
<br />
En el make file hacemos una pequeña modificamos en la línea 46:<br />
<br />
Antes: SOURCES := source data gfx/bin <br />
Ahora: SOURCES := source data gfx/bin source/devnintendods<br />
<br />
De esta forma podemos usar las fuentes que hay en source/devnintendods.<br />
<br />
Ahora el resto de cosas. Los ficheros que estaban en data (dos .raw) siguen en la nueva data.<br />
<br />
El fichero devnintendods.h de include se va al nuevo include y source sigue igual quitando el gfx antiguo, claro.<br />
<br />
Ahora, si compilamos, saldrán una serie de errores. En mi caso bastantes. Lo primero, quitar all_gfx.c de NSMB.cpp.<br />
<br />
Otra cosa, en ScreenManager.cpp cambia la línea 45 y en el .h correspondiente la línea 137:<br />
Lo que antes era:<br />
SetBackground(unsigned int background, int *info, void * pal, const unsigned char *tiles, u32 tiles_size, const unsigned short *mapa) <br />
ahora es:<br />
SetBackground(unsigned int background, int *info, void * pal, const unsigned char *tiles, unsigned int tiles_size, const unsigned int *mapa)<br />
<br />
El array Blank, que era un array a blanco ha desaparecido, así que da error la línea 16 del TileSet.cpp, la he comentado. Ahora no se usa, pero...<br />
<br />
Y no recuerdo más cambios.<br />
<br />
El juego ya compila y se puede ejecutar.<br />
<br />
La semana que viene veremos como instalar en ubuntu, que es un poco más largo, pero no da ningún tipo de problema.<br />
<br />
Saludos<br />
<br />
P.D. Tras el descanso veraniego, en que le blog no ha sido actualizado, vamos a intentar seguir con el blog. No sé de cuanto tiempo dispondré pero bueno...<br />
<br />
Enlaces paqtrocinadosUnknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-11733187922978980882009-07-17T00:01:00.000-07:002009-07-17T00:10:15.324-07:00Dejamos el salto finoHasta ahora a la hora de caer de un salto nuestro personaje realizaba una misteriosa maniobra. Justo antes de caer al suelo frenaba de forma misteriosa. Lo que ocurría era que el código al obtener una colisión con el suelo reseteaba todos los valores del salto y empezaba a caer de nuevo.<br /><br />Eso hay que cambiarlo.<br /><br />Lo único que se necesita es que al obtener una colisión, como estamos cayendo con una 'fuerza' de más de un pixel, debemos encontrar la primera posición libre antes de las plataformas. Un sencillo for realizará este trabajo (NSMB.cpp):<br /><br /><pre name="code" class="cpp"><br />bool NSMB::BeforeVBL() {<br /> if (tiempoSalto-- < 0) { <br /><br /> tiempoSalto = MOVIMIENTO_VELOCIDAD_INTERMEDIA;<br /> int y = koopa->GetY();<br /> koopa->SetY(y + fuerzaSalto);<br /> if (topScreen->IsCollision(koopa, topScreen->GetBackgroundsX() / 8, topScreen->GetBackgroundsY() / 8)) {<br /> if (fuerzaSalto > 0) { <br /> int i = 0;<br /> for (i = 0; i < MAXIMA_FUERZA_CAIDA; i++) {<br /> koopa->MoveUp();<br /> if (!topScreen->IsCollision(koopa, topScreen->GetBackgroundsX() / 8, topScreen->GetBackgroundsY() / 8)) break;<br /> }<br /> } else {<br /> koopa->SetY(y);<br /> }<br /> fuerzaSalto = 0;<br /> volando = false;<br /> } else {<br /> if (fuerzaSalto < MAXIMA_FUERZA_CAIDA) fuerzaSalto++;<br /> volando = true;<br /> }<br /> }<br /> return 1;<br />}<br /></pre><br /><br />El aspecto del juego no ha cambido demasiado:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTzq_Is8XuQAMBNcLDrVkjqeKssf39MDVJDlNYT0zRToMW_015UmKwsFbJKsaqPpCktbRqEWG7WdsTUwuYD6eU__sGFpVCq79jnuIJpLPI8C0i4sWYY_FHBDzjEebQ8HrD9rHEwLW4bdE/s1600-h/screen.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 256px; height: 193px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTzq_Is8XuQAMBNcLDrVkjqeKssf39MDVJDlNYT0zRToMW_015UmKwsFbJKsaqPpCktbRqEWG7WdsTUwuYD6eU__sGFpVCq79jnuIJpLPI8C0i4sWYY_FHBDzjEebQ8HrD9rHEwLW4bdE/s320/screen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5357978376020720610" /></a><br />Otras cosas que hemos hecho es seguir 'mejorando' la librería. Por ejemplo, las funciones de mover un sprite, MoveLeft, MoveUp que tengan el parámetro opcional y así realizar un movimiento de 1 por defecto, preparando el código para coger las monedas, etc.<br /><br />Esta semana si vamos a colgar el <a href="http://sites.google.com/site/devnintendods/Home/nsmb/SuperMarioDS_0.7.zip?attredirects=0">proyecto</a>, tal cual está.<br /><br />Saludos<br /><br />P.D. Otra cosa, estamos en verano y los post no serán tan fluidos, pero supongo que tampoco las visitas.Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-5100734726665546220.post-63797554228932609822009-06-19T00:00:00.000-07:002009-09-08T01:35:40.340-07:00Mejoramos el movimientoTodas estas semanas atrás hemos estado programando el juego utilizando las funcionalidades de los Tiles que nos brinda PALib. Esto está muy bien para juegos tipo Tetris, de tablero, etc. Pero para el New Super Mario Bros, o para los Pokemon no es totalmente válido.<br /><br />El programar con tiles permite dibujar la pantalla con 'azulejos' de 8x8 pixeles, por lo que el movimiento del fondo (necesario en este tipo de juegos) ha de ser de 8 en 8 pixeles y eso no puede ser. Necesitamos unas transiciones más suaves.<br /><br />PALib permite crear tiles y mover el fondo como de si una imagen se tratara. Así que hemos realizado los siguientes cambios en nuestra librería y en el editor de mapas.<br /><br />Con respecto a la nueva librería hemos creado nuevas funciones para tratar los fondos. Estas funciones estarán en ScreenManager:<br /><br /><pre name="code" class="cpp"><br /> /**<br /> * Asigna una imagen de fondo<br /> *<br /> * @param background Cada pantalla de la consola permite cuatro niveles de<br /> * fondos. Los valores posibles son: BACKGROUND_ZERO, BACKGROUND_ONE,<br /> * BACKGROUND_TWO, BACKGROUND_THREE (de mayor a menor prioridad)<br /> */<br /> void SetBackground(unsigned int background, int *info, void * pal, const unsigned char *tiles, u32 tiles_size, const unsigned short *mapa);<br /><br /> /**<br /> * Devuelve la coordenada X única a todos los fondos.<br /> */<br /> int GetBackgroundsX();<br /><br /> /**<br /> * Devuelve la coordenada Y única a todos los fondos.<br /> */<br /> int GetBackgroundsY();<br /><br /> /**<br /> * Asigna la coordenada X única a todos los fondos.<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param y coordenada x<br /> */<br /> void SetBackgroundsX(int x);<br /><br /> /**<br /> * Asigna la coordenada Y única a todos los fondos.<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param y coordenada Y<br /> */<br /> void SetBackgroundsY(int y);<br /><br /> /**<br /> * Asigna las coordenadas X, Y única a todos los fondos.<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param y coordenada x<br /> * @param y coordenada Y<br /> */<br /> void SetBackgroundsXY(int x, int y);<br /><br /> /**<br /> * Desplaza a la izquierda todos los fondos una cantidad dada<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param offset desplazamiento<br /> * @return la nueva coordenada x<br /> */<br /> int MoveBackgroundsLeft(int offset);<br /><br /> /**<br /> * Desplaza a la derecha todos los fondos una cantidad dada<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param offset desplazamiento<br /> * @return la nueva coordenada x<br /> */<br /> int MoveBackgroundsRight(int offset);<br /><br /> /**<br /> * Desplaza arriba todos los fondos una cantidad dada<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param offset desplazamiento<br /> * @return la nueva coordenada y<br /> */<br /> int MoveBackgroundsUp(int offset);<br /><br /> /**<br /> * Desplaza abajo todos los fondos una cantidad dada<br /> * Se utiliza para mover todos los fondos a la vez<br /> *<br /> * @param offset desplazamiento<br /> * @return la nueva coordenada y<br /> */<br /> int MoveBackgroundsBottom(int offset);<br /></pre><br /><br />De esta forma podemos asignar una serie de imágenes a los distintos fondos y moverlos sin problema los pixeles que se desean. En nuestro caso los fondos se moverán de izquierda a derecha.<br /><br />Las funciones utilizadas hasta hoy, <span style="font-style:italic;">CreateTileSet</span>, y la clase <span style="font-style:italic;">TileSet </span>se dejarán para los proyectos que lo necesiten.<br /><br />En cuanto al programa de edición de mapas se han cambiado los ficheros de salida. Ahora genera un png con el dibujo que se ha editado. Este dibujo debe pasar por PAGfx para generar los ficheros de salida. A continuación publicamos las dos imágenes de salida del programa de edición:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpemyFPFN321e4ZaU6Z8cASdBlQIvAYShDkSogJH-waikYpfXdBzIZJNUxuL94fw60EqFkXneA5GNdOv79zJupuHRAZcAWMy5fWs9stQLah5ykKkHwcMBKTU-1aDuR_Uz7lgTUhlSvIjs/s1600-h/newImage_0.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 80px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpemyFPFN321e4ZaU6Z8cASdBlQIvAYShDkSogJH-waikYpfXdBzIZJNUxuL94fw60EqFkXneA5GNdOv79zJupuHRAZcAWMy5fWs9stQLah5ykKkHwcMBKTU-1aDuR_Uz7lgTUhlSvIjs/s320/newImage_0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5342615106391516786" /></a><br />Fondo cero<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyqtcUl1NR64m-Ovmh8wavrVS5hyOMGrSPMBngSvqrb0h_qGwrX1ETwDGyiiDtPBv3W8i3-1l9oy9KZxuBCdpEQxrAiN_huN60H-5R_KgAKy-GBtOycCzv5ir_yIYE9S7FJi64CdxvPGk/s1600-h/newImage_1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 80px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyqtcUl1NR64m-Ovmh8wavrVS5hyOMGrSPMBngSvqrb0h_qGwrX1ETwDGyiiDtPBv3W8i3-1l9oy9KZxuBCdpEQxrAiN_huN60H-5R_KgAKy-GBtOycCzv5ir_yIYE9S7FJi64CdxvPGk/s320/newImage_1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5342618097277702434" /></a><br />Fondo uno<br /><br />El código en NSMB.cpp quedará así:<br /><br /><pre name="code" class="cpp"><br /> topScreen->SetBackground(BACKGROUND_ZERO, FONDO_CERO);<br /> topScreen->SetBackground(BACKGROUND_ONE, FONDO_UNO);<br /> topScreen->SetBackground(BACKGROUND_THREE, FONDO_TRES);<br /> topScreen->SetCollisionMap8x8((void *)newImage_0_Map, newImage_0_Info[1] / 8, newImage_0_Info[2] / 8);<br /></pre><br /><br />Esta semana no voy a publicar código. Son demasiados cambios de un solo golpe y no puedo mantener bien las versiones. Además de que el código estará lleno de errores.<br /><br />Ahora mi objetivo es dejar el salto fino y coger las monedas.<br /><br />Espero tener para la semana que viene cosas nuevas que ofrecer, aunque el verano me va a quitar tiempo. <br /><br />SaludosUnknownnoreply@blogger.com0tag:blogger.com,1999:blog-5100734726665546220.post-39377509324882886442009-06-12T00:00:00.000-07:002009-06-12T00:00:26.720-07:00Los sonidosA partir del <a href="http://devnintendods.blogspot.com/2009/04/sonidos-en-la-nintendo-ds.html">post</a> de como programar los sonidos en la Nintendo DS, con el código de David que publicamos hace ya un tiempo, vamos a implementar los sonidos de nuestro juego.<br /><br />Como ya explicamos en aquel post, las librerías PALib leen los ficheros de audio en formato raw.<br /><br />Para pasar de mp3 a raw lo he hecho con 'Switch Sound File Converter'. Para editar los ficheros hemos usado Audacity.<br /><br />Los ficheros de sonido se dejan en la carpeta data de SuperMarioDS. <br /><br />La Instrucción PA_InitSound la hemos puesto en el constructor de GameManager.cpp. Ahora en la instalación que tengo de PALib ha empezado a dar problemas y he tenido que cambiar el código, que ha quedad de esta forma: <br /><br /><pre name="code" class="cpp"><br />GameManager::GameManager() {<br /> PA_Init();<br /> PA_InitVBL();<br /> <br /> //PA_InitSound();<br /> AS_Init(AS_MODE_SURROUND | AS_MODE_16CH );<br /> AS_SetDefaultSettings(AS_PCM_8BIT, 11025, AS_SURROUND);<br /></pre><br /><br />El código a cambiar en NSMB.cpp es el siguiente:<br /><br /><pre name="code" class="cpp"><br />#include <PA9.h><br />#include "salto.h"<br /><br />....<br /><br />bool NSMB::HeldUp() {<br /> if (!volando) { //Si no estamos volando podremos saltar<br /> //PA_PlaySimpleSound(0, salto);<br /> PA_PlaySimpleSound(salto);<br /> tiempoSalto = TIEMPO_SALTO;<br /> volando = true;<br /> fuerzaSalto = FUERZA_SALTO_INICIAL;<br /> }<br /> return 1;<br />}<br /></pre><br />El error que aparecía al compilar era<span style="font-style:italic;"><br />'PA_InitSound' was not declared in this scope</span>, y ahí me he quedado, he cambiado PA_InitSound y PA_PlaySimpleSound(0, salto) por las otras instrucciones y ya funciona (¿?¿?¿?¿?).<br /><br />Ahora habrá que ir poniendo sonidos a las distintas acciones...<br /><br />SaludosUnknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-80315730304782290532009-06-05T00:01:00.000-07:002009-07-07T01:49:03.050-07:00La gravedad y el saltoBueno, aquí no vamos a explicar lo que es la gravedad, pero si que es necesario ponerla en nuestro juego.<br /><br />Vamos a programar la gravedad en nuestro juego.<br /><br />El tema está en que al saltar, Mario no sube y después baja, no....si no que al saltar Mario sube, el bajar es cosa de la gravedad, no del salto. Por lo que habrá que programar primero el tema de la gravedad.<br /><br />Lo primero será hacer un mapa con una zona elevada y poner ahí a nuestro héroe. Y que al salir de dicha zona la gravedad le haga caer y que lo haga hasta que ocurra una colisión.<br /><br />he creado varias variables, una para saber que estamos cayendo, ya que en esos momentos no podemos saltar. Sólo se salta desde el suelo.<br />Otra es para el tema de la fuerza al caer, es decir, cada vez se cae más deprisa y el retardo del salto para que no caiga demasiado deprisa.<br /><br /><pre name="code" class="cpp"><br />bool NSMB::BeforeVBL() {<br /> if (tiempoSalto-- < 0) { <br /> tiempoSalto = MOVIMIENTO_VELOCIDAD;<br /> int y = koopa->GetY();<br /> koopa->SetY(y + fuerzaSalto);<br /> if (topScreen->IsCollision(koopa, mundo_plataformas_cero->GetX(), mundo_plataformas_cero->GetY())) {<br /> koopa->SetY(y);<br /> fuerzaSalto = 1;//inicializar<br /> volando = false;<br /> } else {<br /> if (fuerzaSalto < MAXIMA_FUERZA_CAIDA) fuerzaSalto++;<br /> volando = true;<br /> }<br /> }<br /> return 1;<br />}<br /></pre><br /><br />El código lo hemos colocado en la función <span style="font-style:italic;">BeforeVBL</span> que se ejecuta en cada vuelta del bucle y antes del refresco de la pantalla. Esto se ha hecho así porque la gravedad actua continuamente.<br /><br />Lo que realmente hace nuestro código es coger la coordenada 'Y' de nuestro héroe y sumarle la fuerza. La hemos llamado fuerzaSalto porque sirve igualmente para saltar que para caer, ya hemos dicho que saltar y caer es lo mismo.<br /><br />Una vez sumados los valores vemos si hay colisión, si no es el caso aumentamos la fuerza, cada vez caemos más fuerte (hasta un límite 'MAXIMA_FUERZA_CAIDA'). Este algoritmo se ejecutará hasta llegar a un suelo.<br /><br />Y ahora que pasa si fuerzaSalto es negativo. Pues que tenemos a nuestro héroe saltando. Por lo que necesitamos este código para comenzar a saltar:<br /><br /><pre name="code" class="cpp"><br />bool NSMB::HeldUp() {<br /> if (!volando) { //Si no estamos volando podremos saltar<br /> tiempoSalto = TIEMPO_SALTO;<br /> volando = true;<br /> fuerzaSalto = FUERZA_SALTO_INICIAL;<br /> }<br /> return 1;<br />}<br /></pre><br /><br />Y ya está, programando la gravedad nos ha salido gratis el salto. Así da gusto!<br /><br />El juego tiene este aspecto ahora mismo:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC_KTUKLyXhZ_kMpN4zrMwu7BWyXzVEcKLQZLFektVIherjh351uZpAgLFxpBBaiSeIu04KBs1E3wv0KKEOhZZx_Wl9Mx4b31ncY9_DUjbYf0I559TshAkY64jaOVG2RBCZr9OS69LnBQ/s1600-h/juego.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 256px; height: 192px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgC_KTUKLyXhZ_kMpN4zrMwu7BWyXzVEcKLQZLFektVIherjh351uZpAgLFxpBBaiSeIu04KBs1E3wv0KKEOhZZx_Wl9Mx4b31ncY9_DUjbYf0I559TshAkY64jaOVG2RBCZr9OS69LnBQ/s320/juego.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5338215921271589938" /></a><br /><br />Aún así queda un efecto feo al aterrizar. Ya lo trabajaremos más adelate.<br /><br />Ahora sólo queda coger las monedas, meter los sonidos, los efectos de fondo, más plataformas,... esto no acaba nunca.<br /><br />Saludos, nos vemos en los comentarios.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-5100734726665546220.post-75735767913657535992009-05-29T00:01:00.000-07:002009-05-29T00:01:03.374-07:00Las monedasEl tema de las monedas nos va a permitir crear un nuevo tipo de Sprite, los Sprites de fondo. Esto no es algo de PALib, si no que es algo implementado por nuestra pequeña librería. <br /><br />Los sprites de fondo o 'background sprite' se moverán con el fondo, por lo que habrá que hacer también funciones que muevan el fondo.<br /><br />Se ha implementado casi todo dentro de ScreenManager. La función para crear un Sprite de fondo es 'CreateBackgroundSprite'. Tiene los mismos parámetros que 'CreateSprite', lo único que el Sprite queda en una lista de sprites de fondo. También se ha preparado 'CloneBackgroundSprite' que crea un sprite idéntico ahorrando espacio en memoria.<br /><br />Antes de ver las funciones, conviene resaltar que se ha usado por primera vez una clase de C++ denominada Vector. Esta clase permite tener una especie de 'array' que se puede ir cargando de forma dinámica. En este caso se ha usado de esta forma:<br /><br /><pre name="code" class="cpp"><br />//ScreenManager.h<br />std::vector <Sprite *> *m_backgroundSprites;<br /></pre><br /><br />Esta es la forma de crear un vector de clases de Sprite. Más delante se ve como recorrerlo, en 'MoveRightBackgroundSprites' y en 'MoveLeftBackgroundSprites'.<br /><br />Las funciones nuevas son las siguientes:<br /><br /><pre name="code" class="cpp"><br />Sprite *ScreenManager::CreateBackgroundSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y) {<br /> return CreateBackgroundSprite(background, shape, sizes, palette, sprite, x, y, 0);<br />}<br /><br />Sprite *ScreenManager::CreateBackgroundSprite(unsigned int background, unsigned int shape, unsigned int sizes, void *palette, void *sprite, int x, int y, int hflip) {<br /> Sprite *newSprite = new Sprite(m_screen, background, shape, sizes, palette, sprite, x, y, hflip);<br /> if (!m_backgroundSprites) m_backgroundSprites = new std::vector<Sprite *>();<br /> m_backgroundSprites->push_back(newSprite);<br /> return newSprite;<br />}<br /><br />Sprite *ScreenManager::CloneBackgroundSprite(Sprite *sprite) {<br /> return CloneBackgroundSprite(sprite, sprite->GetX(), sprite->GetY());<br />}<br /><br />Sprite *ScreenManager::CloneBackgroundSprite(Sprite *sprite, int x, int y) {<br /> Sprite *clone = sprite->Clone(x, y);<br /> m_backgroundSprites->push_back(clone);<br /> return clone;<br />}<br /></pre><br /><br />Y, finalmente, las funciones encargadas de mover todos los sprites de fondo de un golpe son:<br /><br /><pre name="code" class="cpp"><br />void ScreenManager::MoveRightBackgroundSprites(int offset) {<br /> unsigned int i;<br /> for(i = 0; i < m_backgroundSprites->size(); i++) {<br /> Sprite *sprite = (Sprite *)m_backgroundSprites->at(i);<br /> sprite->MoveRight(offset);<br /> }<br />}<br /><br />void ScreenManager::MoveLeftBackgroundSprites(int offset) {<br /> unsigned int i;<br /> for(i = 0; i < m_backgroundSprites->size(); i++) {<br /> Sprite *sprite = (Sprite *)m_backgroundSprites->at(i);<br /> sprite->MoveLeft(offset);<br /> }<br />}<br /></pre><br /><br />En este punto surgió un problema y es que cuando la x se hacía negativa o mayor de 256 aparecían los sprites por el otro lado. Este tema se ha corregido creando una función nueva que permite ocultar los sprites:<br /><br /><pre name="code" class="cpp"><br />void Sprite::SetVisible(int visible) {<br /> if (!visible) {<br /> if (PA_GetSpriteMode(m_screen, m_index_sprite) != 1) {<br /> PA_SetSpriteMode(m_screen, m_index_sprite, 1);<br /> PA_EnableSpecialFx(m_screen, SFX_ALPHA, 0, SFX_BG0 | SFX_BG1 | SFX_BG2 | SFX_BG3 | SFX_BD);<br /> PA_SetSFXAlpha(m_screen, 0, 0);<br /> }<br /> } else if (PA_GetSpriteMode(m_screen, m_index_sprite) != 0) {<br /> PA_SetSpriteMode(m_screen, m_index_sprite, 0);<br /> }<br />}<br /></pre> <br /><br />Esta función pone el sprite totalmente transparente (Esto no es cierto del todo, Existen dos modos y en uno de ellos serán todos los sprites transparentes). Se puede utilizar desde nuestros programas y además lo utilizan las funciones SetX, SetY y SetXY si las coordenadas están fuera de la pantalla:<br /><pre name="code" class="cpp"><br />void Sprite::SetX(int x) {<br /> m_x = x;<br /> PA_SetSpriteX(m_screen, m_index_sprite, m_x);<br /> if (m_x < 0 || m_x > 256) SetVisible(0);<br /> else SetVisible(1);<br />}<br /><br />void Sprite::SetY(int y) {<br /> m_y = y;<br /> PA_SetSpriteY(m_screen, m_index_sprite, m_y);<br /> if (m_y < 0 || m_y > 192) SetVisible(0);<br /> else SetVisible(1);<br />}<br /><br />void Sprite::SetXY(int x, int y) {<br /> m_x = x;<br /> m_y = y;<br /> PA_SetSpriteXY(m_screen, m_index_sprite, m_x, m_y);<br /> if (m_x < 0 || m_x > 256) SetVisible(0);<br /> else SetVisible(1);<br />}<br /></pre><br /><br />Las monedas las hemos creado en NSMB.cpp de la siguiente manera:<br /><pre name="code" class="cpp"><br />Sprite *coin = topScreen->CreateBackgroundSprite(BACKGROUND_TWO, COIN, 192, 80);<br />coin->SetAnim(0, 3, 4);<br />coin->StartAnim();<br />topScreen->CloneBackgroundSprite(coin, 224, 88);<br />topScreen->CloneBackgroundSprite(coin, 248, 96);<br />topScreen->CloneBackgroundSprite(coin, 548, 104);<br /></pre><br /><br />La primera línea crea una moneda (un sprite de fondo).<br />La segunda define los frames para la animación.<br />La tercera pone a girar la moneda.<br />Y las otras tres crean tres monedas más.<br /><br />Este es el aspecto del juego en estos momentos:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp6qFn5Y9b-xf6gCwsLuhWSRm7pDPfHewoxxmQ3wJX8bOgowHer4hW-AZxc99w8WGiYudQaykslNfoYwDUw-ySPkpI4mJDsYRNkidfEi7tW9rHqf932aMA8YebCnH_20iaKsMBF6hyomE/s1600-h/nsmb_6.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 286px; height: 268px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgp6qFn5Y9b-xf6gCwsLuhWSRm7pDPfHewoxxmQ3wJX8bOgowHer4hW-AZxc99w8WGiYudQaykslNfoYwDUw-ySPkpI4mJDsYRNkidfEi7tW9rHqf932aMA8YebCnH_20iaKsMBF6hyomE/s320/nsmb_6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5332450015999602514" /></a><br /><br />¡¡Ahora solo nos falta saltar para coger esas monedas!!<br /><br />Tenemos que hacer el tema de la gravedad y lo de saltar.<br /><br />El código correspondiente a esta última entrega lo podéis descargar desde <a href="http://sites.google.com/site/devnintendods/Home/nsmb/SuperMarioDS_0.6.zip?attredirects=0">aquí</a>.<br /><br />Nos vemos en los comentarios.<br /><br />SaludosUnknownnoreply@blogger.com5tag:blogger.com,1999:blog-5100734726665546220.post-73889629141172005642009-05-22T00:01:00.000-07:002009-05-22T00:01:08.896-07:00Creación de mapas para el Juego (II)Hemos seguido desarrollando el programa de Java para crear mapas. Se ha detectado un error a la hora de generar los mapas de 8 pixeles y se ha añadido la posibilidad de crear más niveles (hasta los cuatro que permite la Nintendo DS).<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKDltSxKgvr1qZw3Izh8F65RGf8eRiWtdSi7kN-a2NNG1uzlUiI-VyPrIUB8Knr3WxoxrpEn7uNIIKPQC5VEJbU__L3i4IMLTMwzKAj6J4u1rKygIPVL7hjmNuDdE8ehsTB3sfrq6EuHw/s1600-h/mapas.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 148px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKDltSxKgvr1qZw3Izh8F65RGf8eRiWtdSi7kN-a2NNG1uzlUiI-VyPrIUB8Knr3WxoxrpEn7uNIIKPQC5VEJbU__L3i4IMLTMwzKAj6J4u1rKygIPVL7hjmNuDdE8ehsTB3sfrq6EuHw/s320/mapas.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5334464311207249810" /></a><br /><br />En la foto se puede ver que se ha añadido una lista de opciones con el nombre 'cero', 'one', 'two' y 'three'. Al añadir dibujos a la pantalla se añadirán al mapa que esté seleccionado. tener en cuenta que el mapa 'cero' es de de mayor prioridad, y así hasta el 'three'. (Por supuesto, mayor prioridad es que sale encima).<br /><br />En la foto las plantas están en la pantalla 'one', y los ladrillos en la 'two'.<br /><br />A la hora de cargar un mapa se ha de cargar el cero_mapa_16.txt, con la opción abrir mapa 16. A la hora de guardar se pondrá, únicamente, el nombre de un txt. <br />Si por ejemplo se pone casa.txt el programa generará:<br />cero_mapa_16_casa.txt, (este es el que habrá que cargar la próxima vez para editar todos los mapas)<br />cero_mapa_8_casa.txt,<br />cero_collision_8_casa.txt,<br />one_mapa_16_casa.txt,<br />one_mapa_8_casa.txt,<br />one_collision_8_casa.txt,<br />two_mapa_16_casa.txt,<br />two_mapa_8_casa.txt,<br />two_collision_8_casa.txt,<br />three_mapa_16_casa.txt,<br />three_mapa_8_casa.txt y<br />three_collision_8_casa.txt<br /><br />Los ficheros de colisión serán los que utilizaremos para el tema de las colisiones. En nuestro caso sólo usaremos el cero_collision_8_...<br /><br />La última versión la encontraréis <a href="http://sites.google.com/site/devnintendods/Home/nsmb/NSMB_mapas_0.3.zip?attredirects=0">aquí</a>.<br /><br />Con todo esto creo que tenemos toda la información necesaria para poder programar nuestro juego. Otra cosa que se puede hacer en el futuro es cargar estos txt directamente desde el juego. Tiempo al tiempo.<br /><br />SaludosUnknownnoreply@blogger.com4tag:blogger.com,1999:blog-5100734726665546220.post-24516374320685685922009-05-15T00:01:00.000-07:002009-05-15T00:01:04.090-07:00El movimientoOtra característica del Mario Bros es que Mario no está siempre en el centro de la pantalla. Si no que cuando se acaban las plataformas, tanto a un lado como a otro, llega hasta el borde de la pantalla.<br /><br />Esta característica hay que programarla dentro del juego y no de las librerías, es decir, lo pondremos en NSMB.cpp.<br /><br />El código fuente de la función avanzar será el siguiente:<br /><pre name="code" class="cpp"><br />int NSMB::avanzar() {<br /> velocidad--;<br /> if (velocidad == 0) {<br /> velocidad = MOVIMIENTO_VELOCIDAD;<br /> if (movimiento == MOVIMIENTO_DERECHA) {<br /> if (koopa->GetX() < 128) {//128 = pixeles mitad pantalla<br /> koopa->MoveRight(MOVIMIENTO_VELOCIDAD);<br /> if (topScreen->IsCollision(koopa, mundo_plataformas->GetX(), mundo_plataformas->GetY()))<br /> koopa->MoveLeft(MOVIMIENTO_VELOCIDAD);//deshacemos el avance<br /> } else {<br /> int x = mundo_plataformas->GetX() + 1;<br /> if (x < COLUMNAS_MAPA - COLUMNAS_PANTALLA) {<br /> if (!topScreen->IsCollision(koopa, x, mundo_plataformas->GetY())) {<br /> mundo_plataformas->SetX(x);<br /> mundo_plataformas->PrintMap8x8(MAPA_PLATAFORMAS);<br /> }<br /> } else if (koopa->GetX() < 256) {<br /> koopa->MoveRight(MOVIMIENTO_VELOCIDAD);<br /> if (topScreen->IsCollision(koopa, mundo_plataformas->GetX(), mundo_plataformas->GetY()))<br /> koopa->MoveLeft(MOVIMIENTO_VELOCIDAD);//deshacemos el avance<br /> }<br /> }<br /> } else {//MOVIMIENTO_IZQUIERDA<br /> if (koopa->GetX() > 128) {//128 = pixeles mitad pantalla<br /> koopa->MoveLeft(MOVIMIENTO_VELOCIDAD);<br /> if (topScreen->IsCollision(koopa, mundo_plataformas->GetX(), mundo_plataformas->GetY()))<br /> koopa->MoveRight(MOVIMIENTO_VELOCIDAD);//deshacemos el avance<br /> } else if (mundo_plataformas->GetX() > 0) {<br /> int x = mundo_plataformas->GetX() - 1;<br /> if (!topScreen->IsCollision(koopa, x, mundo_plataformas->GetY())) {<br /> mundo_plataformas->SetX(x);<br /> mundo_plataformas->PrintMap8x8(MAPA_PLATAFORMAS);<br /> }<br /> } else if (koopa->GetX() > 0) {<br /> koopa->MoveLeft(MOVIMIENTO_VELOCIDAD);<br /> if (topScreen->IsCollision(koopa, mundo_plataformas->GetX(), mundo_plataformas->GetY()))<br /> koopa->MoveRight(MOVIMIENTO_VELOCIDAD);//deshacemos el avance<br /> }<br /> }<br /> }<br /> return 1;<br />}<br /></pre><br /><br />Hoy no voy a poner una versión del código porque está cambiando bastante por lo que lo dejaré para futuros post. Sólo os puedo decir que las funciones Print de ScreenManager están ahora a nivel de TileSet. La clase Sprite está cambiando y mantener varias versiones no me es posible.<br /><br />SaludosUnknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-47699522365846607922009-05-08T00:01:00.000-07:002009-06-09T00:25:13.839-07:00Las colisionesQuizás es uno de los temas más importantes de nuestro juego: no demos salirnos de nuestro mundo, ni atravesar las paredes. La intención de este post es de dotar a las librerías que estamos creando, y de paso al NSMB, de esta cualidad tan necesaria.<br /><br />Vamos a ver cosas que hemos tenido en cuenta a la hora de programar el tema de las colisiones:<ol><br /><li>Veamos cómo está definido Koopa, nuestro héroe:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcrKomd6_WBP-57iHszzdINAZslYDTf4bX7tKdbLbZPawzgTincyP5CAYH57bZciIBb255HzDFB3hr6MUftL1-0m_8ZaVoHk5YpbDc6WqYf57vua2psDM7w0E1AOuofzGSbfkFb64GBcI/s1600-h/colisiones.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 35px; height: 35px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcrKomd6_WBP-57iHszzdINAZslYDTf4bX7tKdbLbZPawzgTincyP5CAYH57bZciIBb255HzDFB3hr6MUftL1-0m_8ZaVoHk5YpbDc6WqYf57vua2psDM7w0E1AOuofzGSbfkFb64GBcI/s320/colisiones.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5316312898998879682" /></a><br />Está dentro de un array de 4x4, pero en el fondo sólo ocupa 2x4 (2 columnas y 4 filas). Es decir, una colisión se dará en el caso en que un objeto entrase en las coordenadas (x+1, y) o (x+1, y+1) o (x+1, y+2) o (x+1, y+3) o (x+2, y) o (x+2, y+1) o (x+2, y+2) o (x+2, y+3). El resto de coordenadas no causan colisión.</li><br /><br /><li>Otro tema a tener en cuenta. Nuestro juego es de plataformas y Koopa está siempre en las mismas coordenadas, son las plataformas las que se mueven, por lo que habrá que calcular en que casillas del mapa está nuestra tortuga.<br /><br />En el código que tenemos hecho hasta la fecha estamos trabajando con formas de 16x16 pixeles,<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1FiymGDEeytn6BaPYUm-E-WpyIgtQ_8SoAwTC4_NNPRPa9eOUSgn3yNTzUURILZ-7QXpW2_MUhoDgkzWwnw6PHSbv3M18_lARyRpoJLZRlbHyOuBI3I94leKx3F-awj0C1R9Q1-B5jrU/s1600-h/plataformas.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 256px; height: 32px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1FiymGDEeytn6BaPYUm-E-WpyIgtQ_8SoAwTC4_NNPRPa9eOUSgn3yNTzUURILZ-7QXpW2_MUhoDgkzWwnw6PHSbv3M18_lARyRpoJLZRlbHyOuBI3I94leKx3F-awj0C1R9Q1-B5jrU/s320/plataformas.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5309658612990880258" /></a><br />y esto nos va a dar problemas. Hay que cambiar las cosas, tenemos que pasar a que nuestro mapa vuelva a ser de 8x8. Dejaremos las funciones de 16x16 por si otro proyecto las necesitase.</li><br /><li>El mapa de colisiones, es decir un array parecido al que define la forma de nuestro mundo pero de colisiones.</li><br /></ol><br /><br />En definitiva hemos añadido el siguiente código:<ul><br /><br /><li>Se ha creado una función que nos permite asignar un array donde definir los obstáculos de nuestro mundo:<br />void ScreenManager::SetCollisionMap8x8(void *collisionMap, unsigned int cols, unsigned int rows).</li><br /><li>Y una que nos permita preguntar por una posible colisión:<br />int ScreenManager::IsCollision(Sprite *sprite, int x, int y). Ambas funciones se han implementado en la clase ScreenManager.</li><br /><li>En la clase Sprite se han definido las siguientes funciones:<br />void SetCollisionMap(void *collisionMap, unsigned int cols, unsigned int rows);<br />void *GetCollisionMap();<br />unsigned int GetCollisionCols();<br />unsigned int GetCollisionRows();<br />Que son las que sirven para definir el mapa de colisiones del Sprite.<br /></li><br /><li>En NSMB.cpp hemos añadido el control de colisiones. Para hacer pruebas hemos dejado el código de subir y bajar, que no son del juego de NSMB, pero nos sirven, en este momento, para probar la funcionalidad. Este control lo encontraréis en la función int NSMB::avanzar() que es invocada desde HeldRight y HeldLeft.</li><br /><li>El editor de pantallas tiene nuevas opciones como son la de grabar mapas de 8x8 y uno de colisiones.</li><br /></ul><br /><br />Para ver la versión que corresponde a este post pinchar <a href="http://sites.google.com/site/devnintendods/Home/nsmb/SuperMarioDS_0.5.zip?attredirects=0">aquí</a>.<br />La nueva versión del editor de mapas está <a href="http://sites.google.com/site/devnintendods/Home/nsmb/NSMB_mapas_0.2.zip?attredirects=0">aquí</a>.<br /><br />Esto empieza a tener algo de forma. Nos falta que nuestro héroe, que tiene que ser Mario y no koopa, empiece a saltar. Lo dejaremos para próximos post. Y las monedas, tenemos que llenar nuestro mundo de monedas!!!<br /><br />Nos vemos en los comentarios.<br /><br />SaludosUnknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-74189503785231397132009-04-24T00:01:00.000-07:002009-05-05T01:43:05.070-07:00Creación de mapas para el JuegoDespués del paréntesis de la semana santa volvemos al proyecto en que estamos metidos, hacer el New Super Mario Bros para la Nintendo DS.<br /><br />En esta entrada vamos a presentar un programa que sirve para hacer los mapas del juego. Es un poco cutre, pero el tiempo no da para más. Aquí os dejo un pantallazo del programa.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigKaaripj6IN6NqfGAHGozD6jYFnDWIyEBUfEA3hMUSbXMQZCOtc2li1OvP3O8lwjrWtR7-SQymoioHvnSU5s0Gzn4n9jI1NslxqGpu83TMZK3glYjPBDleqJLq2MzfMnOUxdqT4sjs7U/s1600-h/mapas.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 132px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigKaaripj6IN6NqfGAHGozD6jYFnDWIyEBUfEA3hMUSbXMQZCOtc2li1OvP3O8lwjrWtR7-SQymoioHvnSU5s0Gzn4n9jI1NslxqGpu83TMZK3glYjPBDleqJLq2MzfMnOUxdqT4sjs7U/s320/mapas.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5327821295614317458" /></a><br /><br />Su uso es muy sencillo:<ul><li>Primero, se debe cargar el tileset con el que queremos dibujar el mapa (fichero/abrir tileset...),</li><br /><li>Segundo, si queremos modificar un mapa ya hecho lo cargamos con la opción fichero/abrir mapa 16,</li><br /><li>Tercero, seleccionamos el tile que queremos dibujar en la parte superior,</li><br /><li>Cuarto, vamos 'clickando' por la pantalla para ir poniendo los cuadraditos y</li><br /><li>Finalmente guardamos el mapa con la opción 'guardar 16'.</li></ul><br />Si os fijáis, al cargar se carga con la opción de cargar mapa 16. Esto es que el programa trabaja con tiles de 16x16 pixeles, así que el mapa a cargar sera de 16.<br /><br />La opción de 'grabar 16' graba el mapa con tiles de 16x16 pixeles (salida_16.txt).<br />La opción de 'grabar 8' graba con tiles de 8x8 pixeles (salida_8.txt).<br /><br />El proyecto java lo encontrareis <a href="http://sites.google.com/site/devnintendods/Home/nsmb/NSMB_mapas.zip?attredirects=0">aquí</a>.<br /><br />No he explicado nada de java, no es tema de este blog, pero si alguien quiere saber algo, que lo diga. Por otra parte, <span style="font-weight:bold;">¡¡¡he comentado bastante el código!!!<span style="font-style:italic;"></span></span><br /><br /><br />Para ver el mapa dentro de nuestro juego, únicamente, tendremos que copiar el contenido del fichero a NSMB.cpp. Es el array denominado mapa8.<br /><br />El último código lo encontraréis <a href="http://sites.google.com/site/devnintendods/Home/nsmb/SuperMarioDS_0.4.zip?attredirects=0">aquí</a>.<br /><br />Hay un cambio con respecto a la anterior versión y es que antes dibujábamos casillas de 16x16 y ahora de 8x8. Dejaremos la anterior funcionalidad en las librerías por si a algún otro proyecto le pueda interesar.<br /><br />Ahora ya podemos ir a por el tema de las colisiones y, después, a por el tema de la gravedad.<br /><br />Ya siento no poder avanzar más pero de donde no hay no se puede sacar, y no tengo nada de tiempo.<br /><br />Nos vemos en los comentarios, saludosUnknownnoreply@blogger.com2tag:blogger.com,1999:blog-5100734726665546220.post-36609337876907440812009-04-10T00:01:00.000-07:002009-04-23T03:17:57.182-07:00Doxygen :: Comentar el códigoHe estado hablando con David y estamos viendo la posibilidad de comentar el código de una forma más extensa que hasta ahora. O mejor dicho, hasta ahora no se comentaba casi nada en las fuentes.<br /><br />Hemos estado mirando las distintas herramientas que hay en Internet para documentar un proyecto y parece que <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a> es la que nos parece más potente y fácil de usar. Posee una opción para utilizar los comentarios JavaDoc por lo que el que conozca esta forma de comentar ya lo tiene todo hecho, y ese es más o menos mi caso.<br /><br />El resultado es algo parecido a esto:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOcNoSi2h7OLIGtOx-0GrDOhmHG0V8QgnBVeLtHglySzV51FCpruvWRlchaFfIXWtsmdgUJtMfeB6GK98FEUoKur9A50IoMPFzkdnv45Xcbsv00iObDq3dFTs0IHvQnWFkEIYMk1azT_E/s1600-h/doxygen.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 180px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOcNoSi2h7OLIGtOx-0GrDOhmHG0V8QgnBVeLtHglySzV51FCpruvWRlchaFfIXWtsmdgUJtMfeB6GK98FEUoKur9A50IoMPFzkdnv45Xcbsv00iObDq3dFTs0IHvQnWFkEIYMk1azT_E/s320/doxygen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5321498324833505778" /></a><br /><br />¡Ahora sólo queda comentar el código!<br /><br />SaludosUnknownnoreply@blogger.com1tag:blogger.com,1999:blog-5100734726665546220.post-39177143309838633792009-04-03T00:10:00.000-07:002009-05-21T23:49:51.460-07:00Sonidos en la Nintendo DSEsta semana vamos a tocar un tema que hasta el momento no habíamos hecho nada, el sonido.<br /><br />Para ilustrar el tema tenemos código que ha mandado David. David es un crack de la programación de la nintendo DS, además de ser quien aporta más comentarios al Blog.<br /><br />El código es el siguiente:<br /><br /><pre name="code" class="cpp"><br />#include &lh;PA9.h><br /><br />#include "intro.h"<br />#include "uno.h" // Include the sound (found in the data folder in .raw format)<br />#include "dos.h"<br />#include "tres.h"<br />#include "cuatro.h"<br /><br />#include "constantes.h"<br /><br />int main(void)<br />{<br /> PA_Init(); // Initializes PA_Lib<br /> PA_InitVBL(); // Initializes a standard VBL<br /><br /> PA_InitSound();<br /> <br /> PA_InitText(SCREEN_TOP, BACKGROUND_ZERO); // Initialise the text system on the top screen<br /> PA_InitText(SCREEN_BOTTOM, BACKGROUND_ZERO); // Initialise the text system on the top screen<br /><br /> PA_OutputSimpleText(SCREEN_TOP, 0, 1, "Prueba raw,pulsa Arriba para escuchar");<br /> PA_OutputSimpleText(SCREEN_TOP, 0, 3, "--------------------------------");<br /> <br /> PA_WaitForVBL();<br /> <br /> s32 sonido = 1;<br /> while (1)<br /> {<br /> if (Pad.Newpress.Up)<br /> {<br /> switch (sonido)<br /> {<br /> case 1:<br /> PA_PlaySimpleSound(0, uno);<br /> sonido ++;<br /> break;<br /> case 2:<br /> PA_PlaySimpleSound(0, dos);<br /> sonido ++;<br /> break;<br /> case 3:<br /> PA_PlaySimpleSound(0, tres);<br /> sonido ++;<br /> break;<br /> case 4:<br /> PA_PlaySimpleSound(0, cuatro);<br /> sonido = 1;<br /> break;<br /> default:<br /> PA_PlaySimpleSound(0, intro);<br /> break;<br /> }<br /> }<br /> <br /> PA_OutputText(SCREEN_BOTTOM, 1, 3, "sonido %d ", sonido);<br /> <br /> PA_WaitForVBL();<br /> }<br /> <br /> return 0;<br />}<br /></pre><br /><br />Para realizar este proyecto se han de seguir los siguientes pasos:<br /><br />1. Copiar los ficheros de sonido .raw a la carpeta data<br />2. realizar los includes de los sonidos<br />3. constants.h se encuentra en la carpeta 'include'. Como ya nos enseñó David, en esa carpeta puedes dejar cosas comunes y el compilador va a buscarlas ahí por defecto. constants.h hace las veces de devnintendods.h en los proyectos mios.<br />4. PA_InitSound(); Esta función de PALib no la habíamos usado nunca hasta ahora. Inicializa el sistema de sonido de la consola.<br />5.PA_PlaySimpleSound(0, uno); Hace sonar el fichero de sonido uno, por el canal 0. Tenemos hasta 8 canales disponibles, lo que permite tener varios sonidos sonando a la vez. En este ejemplo sólo falta una música de fondo, como si fuera la melodía de un juego.<br /><br />El programa mantiene una variable, sonido, que va pasando de 1 a 4 para que suenen los distintos ficheros.<br /><br />Un código sencillo y elegante.<br /><br /><a href="http://sites.google.com/site/devnintendods/Home/sonidos/Sonido.zip?attredirects=0">El proyecto lo dejo donde siempre</a>.<br /><br />Saludos y gracias David.<br /><br />P.D. En estos momentos estoy sin tiempo, y con la proximidad de semana santa quizás no consiga llegar a mi cita semanal...Unknownnoreply@blogger.com1