Hoje iremos aprender como trabalhar com SpriteSheets (folha de sprites) no PSPSDK como esta abaixo:
O PSPSDK possui um biblioteca gráfica que trabalha com imagens png com canais alpha.
Baixe esta classe de graphics :
O que vamos utilizar da Graphics?
– Image*
– blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy);
Apenas isto, sendo o Image* (ponteiro para o arquivo de imagem), e o blitAlphaImageToScreen (função que irá desenhar na tela a imagem)
Vamos ao que interessa:
Arquivo main.c (muito parecido com o hello World)
/*****************************************************\
Exemplo de movimentação PSPSDK
Autor : Nei Estrabelli
site : http://www.neyestrabelli.com
V.0.1 - Versão Beta
\*****************************************************/
#include
#include
#include
#include
#include
#include
#include "graphics.h"
#include "game.h"
PSP_MODULE_INFO("Exemplo de Movimentação", 0, 1, 1);
/**********Thread PSP**********/
int exit_callback(int arg1, int arg2, void *common) {
//THE NEXT LINE IS NEEDED FOR A CLEAN EXIT
sceKernelExitGame();
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0) {
sceKernelStartThread(thid, 0, 0);
}
return thid;
}
/*********FIM Thread PSP**********/
int main(void)
{
pspDebugScreenInit(); // iniciamos o debug
SetupCallbacks(); // executamos a thread
initGraphics(); // inciiamos gráfico
Game(); // executamos o jogo
return 0;
}
Arquivo game.c
/*****************************************************\
Exemplo de movimentação PSPSDK
Autor : Nei Estrabelli
site : http://www.neyestrabelli.com
V.0.1 - Versão Beta
\*****************************************************/
#include
#include
#include
#include
#include
#include "graphics.h"
#define LIMESQ 0 //definimos o inicio do cenario
#define LIMDIR 416 //definimos o final do cenario, sendo 480(fim da tela) - 64(largura do personagem)
void Game()
{
SceCtrlData pad; // varival necessária para os controles
int mUpdateCnt = 0; // variavel para controlar os frames
int PosX = 170; // posicao inicial do personagem
int frameX = 64; // tamanho em pixel da primeira imagem da spriteSheet
int frameY = 73; // inicio da segunda linha da spriteSheet
//carregamos a spriteSheet do Ryu
Image* ryu;
ryu = loadImage("./imagens/ryu.png");
//carregamos a imagem de Fundo (cenario do Akuma)
Image* Fundo;
Fundo = loadImage("./imagens/fundo.png");
//aqui é onde o jogo irá ficar rodando
while(1){
mUpdateCnt++; //incrementamos a variável de controle de frames
sceCtrlReadBufferPositive(&pad, 1); // acionamos o buffer de leitura dos controles
//caso seja pressionado Direcional Esquerda
if (pad.Buttons & PSP_CTRL_LEFT) {
//indicamos que as sprites andando começam do 0 (posição inical da spriteSheet)
frameY = 0;
//verificamos o limite esquerdo
//se a posição X for menor que LIMESQ então dizemos que PosX é igual a LIMESQ
if(PosX < LIMESQ) {
PosX = LIMESQ;
} else {
//caso contrario o personagem anda para a esquera
PosX -= 2;
}
//caso seja pressionado Direcional Esquerda
} else if (pad.Buttons & PSP_CTRL_RIGHT) {
//indicamos que as sprites andando começam do 0 (posição inical da spriteSheet)
frameY = 0;
//verificamos o limite direito
//se a posição X for maior que LIMESQ então dizemos que PosX é igual a LIMESQ
if(PosX > LIMDIR) {
PosX = LIMDIR;
} else {
//caso contrario o personagem anda para a direita
PosX += 2;
}
//caso nenhum direcional seja pressionado
} else {
//indicamos que as sprites de stand começam da altura 73
frameY = 73;
}
//se mUpdateCnt / 10 = 0
if (mUpdateCnt % 10 == 0) {
//somanos frameX ( 64+64) || 64 = 1ª imagem, 128 = 2ª imagem, etc
frameX += frameX;
}
//se frameX for maior que 512 (tamanho máximo de nossa spriteSheet)
if(frameX == 512) {
//reiniciamos o valor para 64
frameX = 64;
}
/*
blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy);
sx - limite do retangulo na posição horizontal
sy - inicio do retangulo na posição vertical
width - largura da imagem
height - altura da imagem
source - imagem alocada com a variavel "Image*"
dx - posição de movimentação horizontal( 0 caso não tenha)
dy - posição de movimentação vertical ( 0 caso não tenha)
*/
blitAlphaImageToScreen(0, 0 , 480, 272, Fundo, 0, 0); //display da imagem de fundo
blitAlphaImageToScreen(frameX, frameY, 64, 73, ryu, PosX, 200); //display do personagem
//funções de refresh
sceDisplayWaitVblankStart();
flipScreen();
}
}
O codigo está bem comentado, sendo assim acho que não é necessário explicação.
Pack completo com o source + arquivo PBP você pode pegar aqui:
Movimentos + SRC
Para rodar o PBP é necessário Custom firmware (SE ou OE), crie uma pasta dentro da GAME150 e copie o EBOOT.PBP + a pasta de imagens, para rodar na versão 1.50 você pode utilizar o PSPBrew para que ele gere a pasta com % em seu devido lugar.
Este exemplo de movimentação ficará desta maneira:
Bom divertimento.
Qualquer dúvida sobre o exemplo comente abaixo.