Tutorial PSPSDK – Movimentação de Sprites

Hoje iremos aprender como trabalhar com SpriteSheets (folha de sprites) no PSPSDK como esta abaixo:

SpriteSheet Ryu

O PSPSDK possui um biblioteca gráfica que trabalha com imagens png com canais alpha.
Baixe esta classe de graphics :

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:

Movimentação PSPSDK

Bom divertimento.

Qualquer dúvida sobre o exemplo comente abaixo.