Aquí tenemos la segunda entrega de cómo programar para nuestra PSP, después del
primer post donde se explicaba como instalar el entorno de programación y compilar el “Hello World”, en esta segunda entrega vamos a programar una pequeña demo de estrellas en moviemiento.
Empezamos viendo todos los ficheros y cual es su cometido:
- font.c: Fuente para los textos
- stars.c y stars.h: Estrellas, crear y mostrar
- main.c: Fichero principal
- types.h: Definición de algunos tipos
- pad.c y pad.h: Control del Pad
- pg.c y pg.h: Primitivas
- mtrand.c y mtrand.h: Números aleatorios
- colors.h: Definición de colores
- image_psp.c: Imagen
Los ficheros font.c, types.h, pad.c, pad.h, pg.c, pg.h y colors.h estan extraidos de varios emuladores o demos open source para PSP así que no hace falta que expliquemos que hacen.
Los ficheros mtrand.c y mtrand.h no los he visto por ahí, pero son una pequeña implementación de “Mersenne Twister” que es un generador de números aleatorios programado por Makoto Matsumoto y Takuji Nishimura.
El fichero image_psp.c es un array con el contenido de la imagen que queremos mostrar, para generar este array he usado “ConvImage” que por desgracia solo funciona para Windows.
Y por fin nos quedan main.c, stars.c y stars.h que son los ficheros que nos interesan, vamos a ver por encima los tres ficheros:
stars.h: Creamos una estructura muy sencilla para cada estrella, creamos un array de la estructura estrella para todas las estrellas, definimos tres funciones, “stars_new” para crear una estrella es una posición aleatoria, “stars_init” para inicializar todas las estrellas y “stars_draw” para imprimirlas.
/*
_____ ___ ____
____| | ____| MrSiir / SiirLabs
| ___| | (C)2005, MrSiir (mrsiir@gmail.com)
------------------------------------------------------------------------
stars.h
Stars
------------------------------------------------------------------------
*/
#ifndef STARS_H
#define STARS_H
#define MAX_STARS 200 // Numero de estrellas
#define SCREEN_WIDTH 480 // Ancho de la pantalla
#define SCREEN_HEIGHT 272 // Alto de la pantalla
// Las estrellas se mueve hacia la:
#define STARS_LEFT 0 // Izquierda
#define STARS_RIGHT 1 // Derecha
#define STARS_UP 2 // Arriba
#define STARS_DOWN 3 // Abajo
// Estructura para las estrellas
typedef struct _star
{
int x; // Posicion X
int y; // Posicion Y
int speed; // Velocidad de la estrella
unsigned short color; // Color
} star;
star stars[MAX_STARS]; // Array con las estrellas
void stars_new(int n); // Inicializamos una estrella en la posicion n
void stars_init(void); // Inicializamos todas las estrellas de 0 a MAX_STARS
void stars_draw(int stars_dir); // Pintamos todas las estrellas
#endif
stars.c: Evidentemente es la implementación de stars.h, es muy muy sencillo, evidentemente se puede mejorar mucho, pero para una primera toma de contacto con la PSP no esta mal.
/*
_____ ___ ____
____| | ____| MrSiir / SiirLabs
| ___| | (C)2005, MrSiir (mrsiir@gmail.com)
------------------------------------------------------------------------
stars.c
Stars
------------------------------------------------------------------------
*/
#include "stars.h"
#include "mtrand.h"
/*
* Inicializamos una estrella en la posicion n
*/
void stars_new(int n)
{
stars[n].x = rand() % SCREEN_WIDTH; // Posicion X inicial entre 0 y SCREEN_WIDTH
stars[n].y = rand() % SCREEN_HEIGHT; // Posicion Y inicial entre 0 y SCREEN_HEIGHT
stars[n].speed = (rand() % 4) + 1; // Velocidad de la estrella entre 1 y 4
stars[n].color = rgb2col(0,0,0); // Color inicial negro
// Cambiamos el color segun la velocidad
if(stars[n].speed == 1) stars[n].color = rgb2col(255,255,255); // Blanco
if(stars[n].speed == 2) stars[n].color = rgb2col(211,211,211); // Gris claro
if(stars[n].speed == 3) stars[n].color = rgb2col(128,128,128); // Gris
if(stars[n].speed == 4) stars[n].color = rgb2col(255,255,0); // Amarillo
}
/*
* Inicializamos todas las estrellas de 0 a MAX_STARS
*/
void stars_init(void)
{
int n;
// Inicializamos el generador de numeros aleatorios
srand(SCREEN_WIDTH);
// Inicializamos todas las estrellas
for(n=0; n<MAX_STARS; n++)
{
stars_new(n);
}
}
/*
* Pintamos todas las estrellas
*/
void stars_draw(int stars_dir)
{
int n;
// Recorremos todas las estrellas para moverlas y pintarlas
for(n=0; n<MAX_STARS; n++)
{
// Las estrellas pueden hacia la izquierda, derecha, arriba o abajo
switch(stars_dir)
{
case STARS_LEFT:
// Decrementamos la posicion X
stars[n].x -= stars[n].speed;
if(stars[n].x <= 0) stars_new(n);
break;
case STARS_RIGHT:
// Incrementamos la posicion X
stars[n].x += stars[n].speed;
if(stars[n].x >= SCREEN_WIDTH) stars_new(n);
break;
case STARS_UP:
// Decrementamos la posicion Y
stars[n].y -= stars[n].speed;
if(stars[n].y <= 0) stars_new(n);
break;
case STARS_DOWN:
// Incrementamos la posicion Y
stars[n].y += stars[n].speed;
if(stars[n].y >= SCREEN_HEIGHT) stars_new(n);
break;
}
// Pintamos la estrella en su posicion X,Y con su color
pgDrawFrame(stars[n].x, stars[n].y, stars[n].x, stars[n].y, stars[n].color);
}
}
main.c: El código esta todo comentado, así que no creo que tenga que apuntar nada más.
/*
_____ ___ ____
____| | ____| MrSiir / SiirLabs
| ___| | (C)2005, MrSiir (mrsiir@gmail.com)
------------------------------------------------------------------------
main.c
Stars
------------------------------------------------------------------------
*/
#include "pad.h"
#include "pg.h"
#include "colors.h"
#include "mtrand.h"
#include "stars.h"
#include "image_psp.c"
/*
* Punto de entrada del programa establecido por startup.s
*/
int xmain(int argc, char *argv)
{
pgInit(); // Iniciamos el modo grafico
pgScreenFrame(2,0);
CtrlInit(0); // Iniciamos el PAD
pgFillvram(0); // Vaciamos
pgScreenFlipV(); // Pintamos
int stars_dir = STARS_LEFT; // Inicialmente hacia la izquierda
stars_init(); // Iniciamos las estrellas
// Bucle infinito
while(1)
{
// Leemos el PAD
readpad();
// Si presionan cambiamos la direccion
if(new_pad & CTRL_UP) stars_dir = STARS_UP; // Arriba
if(new_pad & CTRL_DOWN) stars_dir = STARS_DOWN; // Abajo
if(new_pad & CTRL_LEFT) stars_dir = STARS_LEFT; // Izquierda
if(new_pad & CTRL_RIGHT) stars_dir = STARS_RIGHT; // Derecha
pgFillvram(0); // Vaciamos
stars_draw(stars_dir); // Printamos las estrellas
pgPrint2(10, 15, white, "PSP Stars By"); // Printamos el texto 1 en blanco
pgPrint2(23, 15, bluepsp, "MrSiir"); // Printamos el texto 2 en azul
pgBitBlt(10, 10, 131, 42, 1, image_pspData); // Printamos la imagen
pgScreenFlipV(); // Printamos
}
// Nunca llegaremos a este punto ;-)
return 0;
}
Y para finalizar os dejo una imagen de las estrellitas y el código completo.
Código fuente:
http://www.siirlabs.com/psp/pspstars.tar.gz
1ª ACTUALIZACIÓN:
Tal y como comentaba por ahí, el "ConvImage" solo me funcionaba en Windows así que lo he reprogramado usando las SDL para que funcione en Linux, requiere de SDL y SDL_image.
Código fuente y binario para Linux:
http://www.siirlabs.com/psp/ConvImage16SDL.tar.gz