Con este tutorial ya termino lo que seria el "primer bloque", la parte mas basica y aburrida, y pasamos a 2D (EHHH!!!).
Cuando termineis este tutorial tan facil,
sereis perfectamente capaces de crear una aplicacion util y seria.Antes de nada, aviso que para este tutorial lo voy a explicar de otra forma, voy a explicarlo paso a paso, y despues pondré un pequeño ejemplo.Bueno, no me quiero enroyar mas, asi que empiezo.
Menus, algo que mucha gente me ha preguntado como crear... para esto vamos a usar
booleanosY os preguntareis... ¿Que es un booleano?
Muy simple, es una "variable" especial, que solo admite el valor true (verdadero) o el valor false (falso).
Una variable "normal" tambien vale, pero vas a tener que hacer lo mismo que con booleanos y vas a tener mas provavilidades de liarte y confundirte.
Ahora vamos a usar poquitos, como mucho tres, pero en un proyecto grande para esto necesitas tener una capacidad logica y de comprension vastante grande, porque si tienes muchos te haces la picha un lio (o lo que tengas)
.
Y supongo que tendreis otras dudas... ¿Como se crean y usan los booleanos?
Por ejemplo, si queremos hacer un booleano que se llame menu y que al principio este en false seria poner esto:
// lo declaramos
bool menu;
// le damos el valor inicial
menu = false;
Así de facil, muy parecido a una variable.
Ahora vamos a usarlos. ¿Como?
Pues bien simple, con un if.
if (menu == false){
// lo que sea
}
Por supuesto, cuando los compruebas en un if, tienes que decir si el valor es true o false.
Se suelen usar junto a una accion, por ejemplo:
// imaginamos que hemos cargado un fondo, que seria por ejemplo una intro
// si pulsamos la pantalla y el valor del booleano en false
if ((Stylus.Newpress) && menu == false){
// pues por ejemplo, borramos los bg anteriores y cargamos otros nuevos
menu = true; // al cambiar los bg hemos puesto el fondo que seria el menu, y le decimos que ya estamos en el menu.
}
// si pulsamos el boton a y el valor del boleanos (que habiamos cambiado en el anterior if de false a true) es true
else if ((Pad.Newpress.A) && menu == true){
// lo que sea, por ejemplo, vamos a hacer que vuelva a el menu anterior
// pues cargariamos otra vez los bg anteriores (podemos usar una funcion para esto, que veremos mas adelante)
menu == false; // como volvemos al otro menu, volveriamos a decir que es falso
}
Y ya podemos hacer un menu, tan facil como veis.
Ahora, vamos a hacer un ejemplo aver si os habeis enterado:
#include <PA9.h>
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"
int main(int argc, char ** argv)
{
PA_Init();
PA_InitVBL();
bool menu; /* declaramos el booleano y le damos el valor de falso,
si es falso va a ser que esta en el menu 1 y si es verdadero está en el 2*/
// le damos el valor de falso
menu = false;
// cargamos los bg del menu 1
PA_EasyBgLoad(0, 3, bg0_1);
PA_EasyBgLoad(1, 3, bg0_2);
while (1)
{
// si tocamos la pantalla y estamos en el menu 1...
if ((Stylus.Newpress) && (menu == false)){ /*OJO MUY IMPORTANTE, si pones como condicion el
valor de un booleano o una variable en el if, enved de = hay que colocarle ==, sino no lo comprueba*/
// borramos los anteriores bg
PA_DeleteBg(0, 3);
PA_DeleteBg(1, 3);
// cargamos los bg del menu 2
PA_EasyBgLoad(0, 3, bg1_1);
PA_EasyBgLoad(1, 3, bg1_2);
menu = true; // indicamos que estamos en el menu 2
}
// ahora vamos a volver al menu 1
else if ((Stylus.Newpress) && (menu == true)){ // si tocamos la pantalla y estamos en el menu 2...
// borramos los anteriores bg
PA_DeleteBg(0, 3);
PA_DeleteBg(1, 3);
// cargamos los bg del menu 1 otra vez
PA_EasyBgLoad(0, 3, bg0_1);
PA_EasyBgLoad(1, 3, bg0_2);
menu = false; // indicamos que estamos en el menu 1
}
PA_WaitForVBL();
}
return 0;
}
Captura:
Descarga:
http://www.zonahomebrew.com/modules.php ... tit&lid=77Y ya esta, ahora, a por las funciones.
Todos savemos lo que es una funcion. Vamos a usar las de tipo void.
Para el que ande un poco despiestadillo, una libreria, es un conjunto de funciones.
Las funciones se usan para "hacer varias cosas de un tiron", vastante útiles, ya vereis, me cuesta definirlo xD.
Una funcion de palib, por ejemplo, seria <<PA_Init();>>.
Ahora, aprenderemos a crearlas...
Para usar una funcion hay que hacer tres cosas, declararla, "reyenar" esa funcion, y llamarla.
Al declarar una funcion podemos usar dentro de ella variables para facilitarlo aun mas. Es parecido a una variable.
// declaramos la primera funcion(simple)
void textosimple(void);
// declaramos la segunda funcion, esta con variables
void textocustom(u16 x, u16 y, const char *texto);
Hemos declarado dos funciones, una con variables, lo que vamos a hacer es mostrar texto con las dos.
Centrandonos en la que tiene variables. Vamos a usar x para la posicion x del texto, y por la posicion y, y la cadena de caracteres por el texto.
// vamos a "reyenar" nuestra funcion primera
void textosimple(void){
// esta funcion va a hacer que aparezca texto normal y corriente.
PA_OutputSimpleText(0, 5, 5, "Hemos llamado a la funcion primera");
}
// ahora vamos a usar la segunda, la que contiene las variables
void textocustom(u16 x, u16 y, const char *texto){
// sustituimos cada valor por su letra, x por posicion x, y por posicion y, y texto por el texto que escribimos
PA_OutputSimpleText(0, x, y, texto);
}
Así ya estan preparadas para ser usadas nuestras funciones.
Ahora lo ultimo, que es llamarlas:
// si pulsamos A, llamamos a la primera funcion
if (Pad.Newpress.A){
// llamamos a la funcion, lo que hara que aparezca texto
textosimple();
}
if (Pad.Newpress.B){
// llamamos a la funcion, y le damos valores de posición x e y, ademas de escribir el texto que queramos desde ella
textocustom(7, 10, "Carahuevo");
}
Y asi de facil que es. Esa funcion seria una mierda en mayusculas, porque no nos ayuda mucho que digamos, pero es un ejemplo.
Lo bueno de esto, es que podemos modificar esos valores mientras la aplicacion se ejecuta (siempre que este en un blucle la funcion).
Ahora, el ejemplo:
#include <PA9.h>
// declaramos la primera funcion(simple)
void textosimple(void);
// declaramos la segunda funcion, esta con variables
void textocustom(u16 x, u16 y, const char *texto);
int main(int argc, char ** argv)
{
PA_Init();
PA_InitVBL();
PA_InitText(0, 0);
while (1)
{
// vamos a "reyenar" nuestra funcion primera
void textosimple(void){
PA_OutputSimpleText(0, 5, 5, "Hemos llamado a la funcion primera");
}
// ahora vamos a usar la segunda, la que contiene las variables
void textocustom(u16 x, u16 y, const char *texto){
PA_OutputSimpleText(0, x, y, texto);
}
// si pulsamos A, llamamos a la primera funcion
if (Pad.Newpress.A){
// llamamos a la funcion
textosimple();
}
if (Pad.Newpress.B){
// llamamos a la funcion, y le damos valores x e y, ademas de escribir el texto que queramos desde ella
textocustom(7, 10, "Carahuevo");
}
PA_WaitForVBL();
}
return 0;
}
Captura:
Descarga:
http://www.zonahomebrew.com/modules.php ... tit&lid=78Ahora, lo ultimo, vamos a crear un mini-SO MUY BASICO, aplicando las funciones y los booleanos.
Lo que vamos a hacer es un escritorio, un sprite que representaria una sub-aplicacion(tipo un .exe), y poder entrar y salir de la sub-aplicacion.
Va a ser muy tipo "windows", asi que los interesados en hacer SO, les va a ser de gran ayuda.
Vamos a usar también multiarchivo, es tan simple que no me enroyo, solo con que lo veais en el código ya lo entendereis.
Empezamos:
Con nuestro main.c ya de nuestro nuevo proyecto, crearemos un .txt y lo renombramos a main.h. En main.h "llamaremos" a los demas archivos.
Hacemos lo mismo, otro .txt y le llamamos funciones.h y otro llamado aplicacion1.h
Antes de nada, recomiendo descargar este ejemplo para asimilarlo mejorTenemos cuatro archivos:
- main.c
- main.h
- funciones.h
- aplicación1.h
Empezamos con el código de main.c:
#include <PA9.h> // Include for PA_Lib
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"
// incluimos main.h... OJO, hemos de tener cuidado en el orden que se leen los ficheros.
#include "main.h"
int main(int argc, char ** argv)
{
PA_Init();
PA_InitVBL();
// iniciamos el texto
PA_InitText(0, 0);
// cargo la paleta de los sprites
PA_LoadSpritePal(0, 0, (void*)sprite0_Pal);
// cargo el bg de la tactil y el de la de arriba
PA_EasyBgLoad(0, 3, bg0);
PA_EasyBgLoad(1, 3, bg1);
// creo el sprite del programa
PA_CreateSprite(0, 0, (void*)programa_Sprite, OBJ_SIZE_32X32, 1, 0, 10, 10);
// funcion de palib, lo que va a hacer es cambiar la prioridad de los sprites, en este caso para dejarle detras de la ventana cuando se abra
PA_SetSpritePrio(0, // pantalla
0, // sprite
3); //capa
while (1)
{
// damos opcion de mover la aplicacion por el escritorio (como en windows)
PA_MoveSprite(0);
PA_SetTextTileCol(0, 9);
// ponemos la hora y los minutos
PA_OutputText(0, 27, 22,"%02d:%02d ",
PA_RTC.Hour, // igual que si queremos saver la posicion del stylus...
PA_RTC.Minutes);
// cargo mi funcion de aplicación (archivo aplicacion1.h)
App1();
PA_WaitForVBL();
}
return 0;
}
Main.h:
#ifndef MAIN_H
#define MAIN_H
// y entre esto va el codigo que quieras, no es tan dificil...
// VAMOS A INCLUIR LOS DEMAS ARCHIVOS...
//-----------------------------------------------------
//
// Funciones.h, lo incluimos, aqui declararemos las funciones mas "generales"
//
//-----------------------------------------------------
#include "funciones.h"
//-----------------------------------------------------
//-----------------------------------------------------
//
// Aplicacion1.h, aqui meteremos lo que seria la aplicación primera (y unica) que le meteremos
//
//-----------------------------------------------------
#include "aplicacion1.h"
//-----------------------------------------------------
#endif
Funciones.h:
#ifndef FUNCIONES_H
#define FUNCIONES_H
// lo que hace esta función es crear una nueva ventana que despues se reyena
void nuevaventana(const char *nombreventana);
// esta función cierra la ventana de la sub-aplicacion
void cerrar(void);
void nuevaventana(const char *nombreventana){
// el titulo de la aplicacion que aparece en la ventana
PA_SetTextTileCol(0, 9);
PA_OutputSimpleText(0, 3, 1, nombreventana);
// creamos la ventana a partir de sprites
PA_CreateSprite(0, 1, (void*)ventapp1_Sprite, OBJ_SIZE_64X64, 1, 0, 1, 2);
PA_CreateSprite(0, 2, (void*)ventapp2_Sprite, OBJ_SIZE_64X64, 1, 0, 64, 2);
PA_CreateSprite(0, 3, (void*)ventapp3_Sprite, OBJ_SIZE_64X64, 1, 0, 128, 2);
PA_CreateSprite(0, 4, (void*)ventapp4_Sprite, OBJ_SIZE_64X64, 1, 0, 192, 2);
PA_CreateSprite(0, 5, (void*)ventapp5_Sprite, OBJ_SIZE_64X64, 1, 0, 1, 66);
PA_CreateSprite(0, 6, (void*)ventapp6_Sprite, OBJ_SIZE_64X64, 1, 0, 64, 66);
PA_CreateSprite(0, 8, (void*)ventapp8_Sprite, OBJ_SIZE_64X64, 1, 0, 192, 66);
PA_CreateSprite(0, 7, (void*)ventapp7_Sprite, OBJ_SIZE_64X64, 1, 0, 128, 66);
// creo el sprite que cierra la ventana
PA_CreateSprite(0, 9, (void*)cerrar_Sprite, OBJ_SIZE_16X16, 1, 0, 234, 5);
// funcion de palib, lo que va a hacer es cambiar la prioridad de los sprites para que el texto este delante de ellos
PA_SetSpritePrio(0, // pantalla
1, // sprite
2); //capa
PA_SetSpritePrio(0, 2, 2);
PA_SetSpritePrio(0, 3, 2);
PA_SetSpritePrio(0, 4, 2);
PA_SetSpritePrio(0, 5, 2);
PA_SetSpritePrio(0, 6, 2);
PA_SetSpritePrio(0, 7, 2);
PA_SetSpritePrio(0, 8, 2);
}
void cerrar(void){
// borramos los sprites de la ventana
PA_DeleteSprite(0, 1);
PA_DeleteSprite(0, 2);
PA_DeleteSprite(0, 3);
PA_DeleteSprite(0, 4);
PA_DeleteSprite(0, 5);
PA_DeleteSprite(0, 6);
PA_DeleteSprite(0, 7);
PA_DeleteSprite(0, 8);
PA_DeleteSprite(0, 9);
// quitamos el texto y le devolvemos su color normal
// funcion que "limpia" una capa (incluido texto)
PA_ClearBg(0, 0);
PA_SetTextTileCol(0, 0);
}
#endif
Aplicacion1.h:
#ifndef APLICACION1_H
#define APLICACION1_H
/* vamos a hacer una funcion que nos va a indicar el estado en el que
esta el programa (si se mueve, si esta seleccionado, si esta abierto...)
y lo que ocurre cuando se abre*/
void App1(void);
// estado es una variable que usaremos como si fuera un booleano
// abierto un booleano.
u16 estado = 0;
bool abierto = false;
// variables que usaremos dentro de nuestra sub-aplicacion
u8 colL = 1;
u8 colR = 1;
u8 colA = 1;
u8 colB = 1;
u8 colX = 1;
u8 colY = 1;
u8 colAr = 1;
u8 colAb = 1;
u8 colIz = 1;
u8 colDe = 1;
void App1(void){
// si tocamos el sprite y el estado es 0 (0 sin seleccionar, 1 seleccionado) y esta cerrado...
if((Stylus.Newpress) && (PA_SpriteTouched(0)) && (estado == 0) && (abierto == false))
{
// lo animamos
PA_SetSpriteAnim(0,0,1);
// esta seleccionado
estado = 1;
}
// si volvemos a tocarlo se abre
else if((Stylus.Newpress) && (PA_SpriteTouched(0)) && (estado == 1) && (abierto == false))
{
// lo animamos como que ya lo hemos abierto
PA_SetSpriteAnim(0,0,0);
// cramos la ventana y le ponemos el nombre(funciones.h)
nuevaventana("Aplicacion 1");
// esta seleccionado
estado = 0;
// y abierto
abierto = true;
}
// si tocamos la pantalla pero no el sprite y esta seleccionado solo...
else if((Stylus.Newpress) && (estado == 1)){
// le volvemos a animar al frame primero
PA_SetSpriteAnim(0,0,0);
// sin seleccionar
estado = 0;
}
// si esta abierto...
if ((abierto == true)){
//----------------------------------------
// Aquí vamos a meter el codigo de la aplicacion en si
// Mostraremos la posicion del stylus dentro de la ventana, y checkeara si pulsamos algun boton
////----------------------------------------
// ponemos color azul para ese "enunciado"
PA_SetTextTileCol(0, 3);
PA_OutputText(0, 2, 4, "Test stylus:");
// ponemos la posicion del stylus en verde
PA_SetTextTileCol(0, 2);
PA_OutputText(0, 2, 6,"Stylus X: %d ", Stylus.X);
PA_OutputText(0, 2, 7,"Stylus Y: %d ", Stylus.Y);
// otro "enunciado"
PA_SetTextTileCol(0, 3);
PA_OutputText(0, 17, 4, "Test botones:");
// ponemos variables en todos los colores (una para rojo/sinpulsar y otra verde/pulsado)
PA_SetTextTileCol(0, colL);
PA_OutputText(0, 17, 6, "L");
PA_SetTextTileCol(0, colR);
PA_OutputText(0, 25, 6, "R");
PA_SetTextTileCol(0, colA);
PA_OutputText(0, 17, 8, "A");
PA_SetTextTileCol(0, colB);
PA_OutputText(0, 25, 8, "B");
PA_SetTextTileCol(0, colX);
PA_OutputText(0, 17, 9, "X");
PA_SetTextTileCol(0, colY);
PA_OutputText(0, 25, 9, "Y");
PA_SetTextTileCol(0, colAr);
PA_OutputText(0, 17, 11, "Arriba");
PA_SetTextTileCol(0, colAb);
PA_OutputText(0, 25, 11, "Abajo");
PA_SetTextTileCol(0, colIz);
PA_OutputText(0, 17, 13, "Izquierda");
PA_SetTextTileCol(0, colDe);
PA_OutputText(0, 17, 14, "Derecha");
//----------------------------------------
}
//-------------------------------------------------
// AQUI METEREMOS LOS IFS DE NUESTRA SUB_APLICACION
//-------------------------------------------------
//si dejamos pulsado L...
if ((Pad.Held.L)){
colL = 2; // se pone de color verde
}
// si la soltamos...
else if ((Pad.Released.L)){
colL = 1; // se vuelve roja
}
// lo mismo con el R...
if ((Pad.Held.R)){
colR = 2;
}
else if ((Pad.Released.R)){
colR = 1;
}
// lo mismo con la A
if ((Pad.Held.A)){
colA = 2;
}
else if ((Pad.Released.A)){
colA = 1;
}
// lo mismo con el B
if ((Pad.Held.B)){
colB = 2;
}
else if ((Pad.Released.B)){
colB = 1;
}
// lo mismo con el x
if ((Pad.Held.X)){
colX = 2;
}
else if ((Pad.Released.X)){
colX = 1;
}
// lo mismo con la Y
if ((Pad.Held.Y)){
colY = 2;
}
else if ((Pad.Released.Y)){
colY = 1;
}
// lo mismo con Arriba
if ((Pad.Held.Up)){
colAr = 2;
}
else if ((Pad.Released.Up)){
colAr = 1;
}
// lo mismo con Abajo
if ((Pad.Held.Down)){
colAb = 2;
}
else if ((Pad.Released.Down)){
colAb = 1;
}
// lo mismo con Izquierda
if ((Pad.Held.Left)){
colIz = 2;
}
else if ((Pad.Released.Left)){
colIz = 1;
}
// lo mismo con Derecha
if ((Pad.Held.Right)){
colDe = 2;
}
else if ((Pad.Released.Right)){
colDe = 1;
}
//-------------------------------------------------
//-------------------------------------------------
// CERRAMOS LA APLICACION
//-------------------------------------------------
// si cerramos la aplicación...
if ((abierto == true) && PA_SpriteTouched(9)){
// llamamos a la funcion que cierra(funciones.h)
cerrar();
// esta cerrado
abierto = false;
}
//-------------------------------------------------
}
#endif
Captura:
Descarga:
http://www.zonahomebrew.com/modules.php ... tit&lid=79Para añadirle algo tipo inicio de windows, lo mismo que con el archivo del escritorio para crear una ventana, con sprites, un booleanos, y si tocas en la zona que sea, aparecen los sprites y el booleanos pasa a true...
Y con esto hemos terminado ya si todo lo que son las aplicaciones a nivel Facil-Medio.
Ahora vamos a pasar a 2D y aprenderemos todo lo que se puede consegir. Al final sereis capaces de hacer un juego tipo super mario bros o zelda sin problema.
El apartado 2D lo vamos a dividir en dos partes:
1.- Relacionado con los sprites, colisiones, movimientos, scroll, etc...
2.- Aplicar lo anterior junto a leyes fisicas como friccion, aceleracion, gravedad...
Lo que vamos a hacer es como siempre, ejemplo a ejemplo, pero crearemos otro a parte, que sera irle aplicando dia a dia todo lo aprendido a ese ejemplo, como tarea.
Lo podemos orientar hacia juegos tipo zelda, mario bros, etc... Después aremos otro aparte mas chungete que usara leyes fisicas que sera de una moto (o coche si quereis).
Con esto ya podemos hacer el juego que queramos.
Y por ultimo, despues de todo eso, volveremos con las api y daremos un nivel avanzado (escritura y lectura de archivos, mas ejemplos adaptables a SO...)
Y despues ya se vera por el camino...
Antes de terminar el bloque, quiero dar muchisimas gracias a todos los que me an apoyado, an segido mis tutoriales y les an gustado.
Todas las dudas sobre este ultimo ejemplo en el post "general".
Salu2.