PSP xvi

PSPプログラミングを教えるブログ(本気で頑張る人アクセス大歓迎サイト)

PSP-X.gif

記事の間違いを報告  新アップローダー
記事修正情報 PSPプログラミング資料 自作ゲーム PSP用エミュレータ リンク

公認リンク
公式PSP専科 公式PSVita専科 はじめるPSPSDK PSP EXEC GAME M@STER PSP 猫山のYouTubeチャンネル

TAG
全記事にタグをつけています  http://nekoyama2gillien.blog36.fc2.com/?tag=タグ
PSP PSPプログラミング DXライブラリPortable OSLib ショートプログラム ハローワールド
PSP自作ゲーム PSP自作ソフト エミュレータ ゲームアーカイブス PSP動画
動画 初音ミク ミクミクダンス MMDドラマ ゲーム 魔法少女まどか☆マギカ 侵略!イカ娘
アイドルマスター

このブログについて

このブログでは、非公式のPSPソフト、いわゆる自作ソフト( PSP Homebrew )を作る事を目的とします。

著作権などの こまかい利用規約については、こちらを開いてお読み下さい

このブログについて知りたい方、初めて来訪された方はこちらを開いてお読みください
お問い合わせは 猫山猫宗(nekomune@gmail.com)までどうぞ


当ブログはリンクフリーです。ブログ名は、アルファベットで「PSP xvi」と書いて『ピーエスピー・エクシビ』とお読みください。
相互リンクを希望されるブログ運営者様は、ココで申請して下さい。


このブログで全記事から探し物の方は、ここをクリックして下さい。
http://nekoyama2gillien.blog36.fc2.com/?all

スポンサーサイト 

--/--/--
--. --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[edit]

CM: --
TB: --

page top

はい、解説です

素材は 標準PSPで表示・再生できるフォルダに入れてますでしょうか。
このRPGはまだ開発中なので、素材は EBOOT.PBP と別フォルダが良いと判断してます。

【 今回は、勇者の描画方法についてだけ解説 】
勇者は、上下左右の4方向に3パターンで合計12枚のキャラ絵を使用しています。
配布素材はDXライブラリPortable でも扱いやすい構成になっていましたので、勇者の絵は 背景を透過させただけで殆ど弄っていません。

勇者の絵は、308行目で読み込んでいます。
> LoadDivGraph( GRPH_HERO ,12,3,4,32,48,&HDL_Graph_Hero[0][0]);
↑これです。画像の分割格納読み込みをやっています。
これは、全部で画像を12個に分割し、横3列、縦4行、横幅32ピクセル、縦幅48ピクセルにして、その分割した画像のハンドルを、二次元配列HDL_Graph_Hero に順番に格納させる命令です。

&HDL_Graph_Hero[0][0] は配列の先頭のポインタですよ

注意:画像の分割数は最低でも1です。うっかり0にすると実行時に挙動がおかしくなります。コンパイルエラーにはならないので十分気を付けて下さい。

    

配布されているこの絵ですが、どう扱えば良いか?
縦は「向き」ですね。向きの定義はこれです。32行目からの部分。

#define MUKI_SHITA   0 // 下向き
#define MUKI_HIDARI  1 // 左向き
#define MUKI_MIGI   2 // 右向き
#define MUKI_UE    3 // 上向き


横は「パターン絵」とでも言いましょうか。どこで「モーション絵」になるように定義をしているかと言うと、59行目です。
> int PIC_Walk_Step[4] = { 1,0,1,2 };
↑この数値は、モーション絵のパターン番号の定義です。「Hero_Step」という変数を1ずつカウントして足踏みを実現しています。
「0,1,2,3,0,1,2,3,…」に対応させて「1,0,1,2,1,0,1,2,…」という数値を導けるようにしています。こういうのは変数に入れて定義しておけば簡単に処理できます。

勇者の表示(描画)は、198行目の
> DrawGraph( 224,104,HDL_Graph_Hero[Hero_MUKI][ PIC_Walk_Step[(Hero_Step>>4)] ],TRUE );
です。
PIC_Walk_Step[(Hero_Step>>4)] の (Hero_Step>>4) は何かと言うと Hero_Step÷16 の商を求める計算式の高速版です。2の4乗16ですから。
16で割っている理由は、足踏みのアニメーション絵の切り替え速度が そのままのHero_Stepの値 では早すぎたからです。
つまり、16/60秒(約 0.3秒)ごとに1枚ずつ、足踏みのアニメーション絵の切り替えをやっているのです。
1モーションに4枚の絵を使っていますので、16/60秒×4倍=64/60秒(約 1.1秒)かかる、という計算になります。

Hero_Step のカウントは 189行目の
> Hero_Step = (++Hero_Step)&(63);
↑これです。増加させたあとの&(63)は、カウンタの周期が1モーション=64フレーム(16フレーム×4パターン絵)だから0~63の範囲になるようにする計算式です。
63(10進数)は、0x3F(16進数)/ 00111111(2進数)です。
つまり、カウンタ値を 00111111(2進数)でマスクして値が63を越えない処理をする均一速度な高速版なのです。
解りやすく書いたら
++Hero_Step;
if(Hero_Step > 63) Hero_Step = 0;

↑こういうことです。if文は、コンパイルすると「条件分岐処理」に機械語翻訳される(アセンブル)ので真の場合と偽の場合とで処理速度が変化します。その為、スピード重視なゲームではif文の羅列はお薦め出来ません。

2進数で考える、左シフト演算や&演算は、ビット演算です。論理ビット演算と算術ビット演算があります。コンピュータが得意な技ですから覚えてくださいね。論理ビット演算は ふつう unsigned数値でやります。算術ビット演算は符号付き数値でやります。

シフト演算については過去記事をおさらいして下さい


背景の描画方法は、解説要らないと判断しましたので省略。

次回は、マップチップを使った背景の実装とスクロール実装をやります。


続きを読むに、RPG_TEST_v0.01 の全ソースコードを貼り付けてあります。以後、必要箇所だけソースコード掲載します。
閲覧推奨ブラウザは、FireFoxです(行番号も表示されるので)。


main.c


  1. /*****************************************************************************
  2. * main.c DXライブラリPortable v0.5.7版                   *
  3. *        RPG TEST v0.01                       *
  4. *                                      *
  5. *     このソースコードはBSDライセンスとします              *
  6. *                                      *
  7. *                  製作:猫山猫三郎猫宗 in 2010.10.24(SUN) *
  8. *****************************************************************************/
  9. #include <dxlibp.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. //#include "mydef.h"
  13.  
  14. /*****************************************************************************
  15. * define
  16. *****************************************************************************/
  17. //#define SCRBUF0     (char*)(0)
  18.  
  19. #define SCREEN_WIDTH    480 // 横幅は 480ピクセル
  20. #define SCREEN_HEIGHT    272 // 縦幅は 272ピクセル
  21.  
  22. #ifndef PSP_MODULE_KERNEL
  23. #define PSP_MODULE_KERNEL  0x1000
  24. #endif
  25. #ifndef PSP_MODULE_USER
  26. #define PSP_MODULE_USER   0
  27. #endif
  28.  
  29. #define MP3_EXIST   1 // BGM.mp3 ファイルがある
  30. #define MP3_NOT_EXIST 0 // BGM.mp3 ファイルが無い
  31.  
  32. #define MUKI_SHITA   0 // 下向き
  33. #define MUKI_HIDARI  1 // 左向き
  34. #define MUKI_MIGI   2 // 右向き
  35. #define MUKI_UE    3 // 上向き
  36.  
  37. #define Hero_STOP   0 // 勇者 止まる
  38. #define Hero_MOVE   1 // 勇者 歩く
  39.  
  40. #define XVI_COLOR_DARKGREEN 0xFF008000 // 深緑色
  41. #define XVI_COLOR_YELLOW   0xFF00FFFF // 黄色
  42. #define XVI_COLOR_LIGHTBLUE 0xFFE6D8AD // 水色
  43.  
  44. #define SND_BGM    "ms0:/MUSIC/RPG/BGM.mp3" // BGM
  45.  
  46. #define GRPH_LOADING  "ms0:/PICTURE/RPG/LOADING.png" // なう・ろーでぃんぐ
  47. #define GRPH_HERO   "ms0:/PICTURE/RPG/勇者.png"   // 勇者 の スプライト
  48. #define GRPH_SIBA   "ms0:/PICTURE/RPG/芝.png"    // 背景 の 芝
  49.  
  50. /*****************************************************************************
  51. * groval
  52. *****************************************************************************/
  53.  
  54. int HDL_Graph_Shiba;   // 芝生の画像ハンドル
  55. int HDL_mp3;       // BGM.mp3 のハンドル
  56. int flag_mp3;       // BGM.mp3 ファイルがあれば MP3_EXIST
  57.  
  58. int HDL_Graph_Hero[4][3]; // 勇者の画像ハンドル(4方向×3パターン)
  59. int PIC_Walk_Step[4] = { 1,0,1,2 }; // 歩きのステップ番号に対するパターン絵の指定
  60.  
  61. int HDL_Graph_BG;     // 背景の画像ハンドル(とりあえず芝生)
  62.  
  63. int Hero_MUKI;      // 勇者の向き( MUKI_***** )
  64. int Hero_Step;      // 勇者の歩きステップ具合( 0~3 )
  65. int Hero_MOVE_flag;    // 勇者が歩くかどうかのフラグ
  66.  
  67. /*****************************************************************************
  68. * Original Functions
  69. *****************************************************************************/
  70. void main(void);
  71. void messages(void);
  72. void action(void);
  73. void Draw_haikei(void);
  74. void ScreenSettings(void);
  75. void mp3checker();
  76. int pic_load(void);
  77. int initton(void);
  78.  
  79. /*****************************************************************************
  80. * もじゅ~る・いんふぉ / メインコードはユーザモード
  81. *****************************************************************************/
  82. PSP_MODULE_INFO("PSP_RPG", PSP_MODULE_USER, 0, 0);
  83. PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
  84. //PSP_HEAP_SIZE_KB(-2048);
  85. //PSP_MAIN_THREAD_STACK_SIZE_KB(512);
  86. /*****************************************************************************
  87. * main
  88. *****************************************************************************/
  89. void main(void)
  90. {
  91.   DxLib_Init();
  92.  
  93.   if(initton() == 0)
  94.     action();    // 初期化成功(正常時)の時だけ action()関数を実行
  95.  
  96.   DxLib_End();
  97. }
  98.  
  99. /*****************************************************************************
  100. * sub1 開始前に表示するメッセージ
  101. *****************************************************************************/
  102. void messages(void)
  103. {
  104.   DrawBox(0,0,480,272,DXP_COLOR_BLUE,TRUE); // 青色画面
  105.   DrawFormatString(120, 40,XVI_COLOR_YELLOW,"『RPG TEST v0.01』");
  106.   if(flag_mp3 == MP3_NOT_EXIST)
  107.     DrawFormatString(80, 80,DXP_COLOR_GRAY,"音楽は鳴りません");
  108.   else
  109.     DrawFormatString(80, 80,DXP_COLOR_WHITE,"音楽が鳴ります(ループします)");
  110.  
  111.   DrawFormatString(80, 120,DXP_COLOR_WHITE,"Lトリガー押しで終了");
  112.   DrawFormatString(80, 180,XVI_COLOR_LIGHTBLUE,"○ボタン押しで始まります");
  113.  
  114.   ScreenFlip();
  115. }
  116.  
  117. /*****************************************************************************
  118. * sub2 勇者が歩くよ、どこまでも!!
  119. *****************************************************************************/
  120. void action(void)
  121. {
  122.   Hero_MUKI   = MUKI_SHITA; // 下向き
  123.   Hero_Step   = 0;     // 足踏みのステップ(最初は0で)
  124.   Hero_MOVE_flag = Hero_STOP; // 最初は止まっている
  125.  
  126.   // 足踏みは、16/60秒単位で行なう作戦
  127.  
  128.  
  129.   messages();
  130.  
  131.   do {
  132.     ProcessMessage();  // パッド読み取り本体
  133.  
  134.     if((GetInputState()) == DXP_INPUT_LTRIGGER) return; // Lトリガー押されたら終了
  135.  
  136.   }while((GetInputState()) != DXP_INPUT_CIRCLE); // ○ボタン押しでアニメーション開始
  137.  
  138.   // BGM.mp3ファイルあれば再生させる
  139.   if(flag_mp3 == MP3_EXIST)
  140.     PlaySoundMem( HDL_mp3, DX_PLAYTYPE_LOOP, TRUE);
  141.  
  142.   // ここからループします ↓↓
  143.   while(1) {
  144.     ProcessMessage();  // パッド読み取り本体
  145.     switch(GetInputState()) {
  146.  
  147.       case DXP_INPUT_LTRIGGER: { // Lトリガー押されたら
  148.         if(flag_mp3 == MP3_EXIST) { // mp3再生終了の為の後片付け
  149.           StopSoundMem( HDL_mp3 );
  150.           DeleteSoundMem( HDL_mp3 );
  151.         }
  152.         return; // Lトリガーで抜ける
  153.       }
  154.  
  155.       case DXP_INPUT_UP:   { // ↑レバー入れたら
  156.         if(Hero_MOVE_flag == Hero_STOP) {
  157.           Hero_MUKI = MUKI_UE;
  158.           Hero_MOVE_flag = Hero_MOVE;
  159.         }
  160.         break;
  161.       }
  162.  
  163.       case DXP_INPUT_DOWN:  { // ↓レバー入れたら
  164.         if(Hero_MOVE_flag == Hero_STOP) {
  165.           Hero_MUKI = MUKI_SHITA;
  166.           Hero_MOVE_flag = Hero_MOVE;
  167.         }
  168.         break;
  169.       }
  170.  
  171.       case DXP_INPUT_LEFT:   { // ←レバー入れたら
  172.         if(Hero_MOVE_flag == Hero_STOP) {
  173.           Hero_MUKI = MUKI_HIDARI;
  174.           Hero_MOVE_flag = Hero_MOVE;
  175.         }
  176.         break;
  177.       }
  178.  
  179.       case DXP_INPUT_RIGHT:   { // →レバー入れたら
  180.         if(Hero_MOVE_flag == Hero_STOP) {
  181.           Hero_MUKI = MUKI_MIGI;
  182.           Hero_MOVE_flag = Hero_MOVE;
  183.         }
  184.         break;
  185.       }
  186.  
  187.     }
  188.  
  189.     Hero_Step = (++Hero_Step)&(63); // 足踏みで絵が変わるよ
  190.  
  191.     if(Hero_Step == 0)
  192.       Hero_MOVE_flag = Hero_STOP;
  193.  
  194.     // 背景を描画
  195.     Draw_haikei();
  196.  
  197.     // 勇者を表示
  198.     DrawGraph( 224,104,HDL_Graph_Hero[Hero_MUKI][ PIC_Walk_Step[(Hero_Step>>4)] ],TRUE );
  199.  
  200.     DrawFormatString(240, 220,DXP_COLOR_WHITE,"Lトリガー押しで終了");
  201.     ScreenFlip(); // 垂直同期信号を待つ(1/60秒)1回目
  202.   }
  203. }
  204.  
  205. /*****************************************************************************
  206. * sub3 背景グラフィックの描画関数
  207. *****************************************************************************/
  208. void Draw_haikei()
  209. {
  210.   unsigned int x,y;
  211.  
  212.   for(x=0; x<12; x++)  {
  213.     for(y=0; y<8; y++) {
  214.       DrawGraph( (x<<5)+48,(y<<5)+8,HDL_Graph_BG,FALSE ); // 芝生を表示
  215.     }
  216.   }
  217.  
  218.   DrawBox( 0, 0, 48,272,DXP_COLOR_BLACK,TRUE);   // 左側の黒い帯
  219.   DrawBox(432, 0,480,272,DXP_COLOR_BLACK,TRUE);   // 右側の黒い帯
  220.   DrawBox( 48, 0,432, 8,DXP_COLOR_BLACK,TRUE);   // 上側の黒い帯
  221.   DrawBox( 48,264,432,272,DXP_COLOR_BLACK,TRUE);   // 下側の黒い帯
  222. }
  223.  
  224. /*****************************************************************************
  225. * sub3 グラフィック画面の設定などの関数
  226. *****************************************************************************/
  227. void ScreenSettings()
  228. {
  229.   SetDisplayFormat(DXP_FMT_8888); // 画面のピクセルフォーマットを32Bit色モードに
  230.   SetWaitVSyncFlag(TRUE); // 画面更新の際、垂直同期待ちをしてから行なう様に
  231.   SetDrawArea(0,0,480,272); // 描画可能領域を全領域に設定
  232. // SetDrawMode(DX_DRAWMODE_NEAREST); // 描画モードを高速なNEARESTにセットする
  233. // SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);// 描画の際のブレンドモードを、標準モードに
  234.   SetDrawBright(255,255,255); // 描画する色の輝度を最大に
  235.   SetGraphMode(480, 272, DXP_FMT_8888); // フル画面サイズ & 32Bit色モード
  236.   ClearDrawScreen(); // 描画先のグラフィックスをクリアする
  237.  
  238.   ChangeFontType(DX_FONTTYPE_NORMAL);   // エッジ無しノーマル文字にする(IntraFont)
  239. }
  240.  
  241. /*****************************************************************************
  242. * sub4 mp3ファイル・チェッカー関数
  243. *****************************************************************************/
  244. void mp3checker()
  245. {
  246.   // まずは 全てのサウンドハンドルを削除します
  247.   InitSoundMem();
  248.  
  249.   // ストリーミング再生モードに設定します(チョイ読みしながら再生)
  250.   SetCreateSoundDataType(DX_SOUNDDATATYPE_FILE);
  251.  
  252.   // 再生させる音声ファイルを指定します(mp3ファイルを用意してね)
  253.   if((HDL_mp3 = LoadSoundMem(SND_BGM)) == -1) // もしエラーが発生したら
  254.     flag_mp3 = MP3_NOT_EXIST; // ないよ
  255.   else
  256.     flag_mp3 = MP3_EXIST;   // あるよ
  257.  
  258.   // パンを中央に設定します
  259.   if(flag_mp3 == MP3_EXIST)
  260.     SetPanSoundMem( 0, HDL_mp3);
  261. }
  262.  
  263. /*****************************************************************************
  264. * sub5 画像データ・ローダー関数
  265. *****************************************************************************/
  266. int pic_load(void)
  267. {
  268. const char *pic_filename[]={
  269.   GRPH_SIBA,  // 背景 の 芝
  270.   GRPH_HERO,  // 勇者 の スプライト
  271.   "おわる"
  272. };
  273.  
  274.   FILE *fp;
  275.   int i;
  276.  
  277.   // なう・ろーでぃんぐ画像を表示
  278.   if((LoadGraphScreen(0,0,GRPH_LOADING, FALSE)) == -1) {
  279.     // ↓↓ なう・ろーでぃんぐ画像が無いなら文字で
  280.     DrawBox(0,0,480,272,XVI_COLOR_DARKGREEN,TRUE);
  281.     DrawFormatString(150, 120,DXP_COLOR_WHITE,"なう・ろーでぃんぐ!!");
  282.   }
  283.   ScreenFlip();
  284.  
  285.   i=0; // インデックス( i=0 は背景画像を含む場合 )
  286.  
  287.   while(strcmp(pic_filename[i],(const char *)"おわる") != 0) {
  288.     fp=fopen(pic_filename[i],"r");
  289.     if(fp==NULL)  {
  290.       fclose(fp);
  291.       DrawBox(0,0,480,272,DXP_COLOR_RED,TRUE); // 赤色画面
  292.       DrawFormatString(100, 90,DXP_COLOR_WHITE,"ファイル %s が無いよ",pic_filename[i]);
  293.       DrawFormatString(100,140,DXP_COLOR_WHITE,"終了します。何か押して!");
  294.       ScreenFlip();
  295.  
  296.       do  { // 何か押されるまで待つ do ~ while
  297.         ProcessMessage();
  298.       }while(CheckHitKeyAll() == 0);
  299.  
  300.       return(-1); // 終了
  301.     }
  302.     fclose(fp);
  303.     i++;
  304.   }
  305.  
  306.   // 画像ファイル全部読み込み
  307.   HDL_Graph_BG = LoadGraph(GRPH_SIBA);
  308.   if(LoadDivGraph( GRPH_HERO ,12,3,4,32,48,&HDL_Graph_Hero[0][0]) == -1) {
  309.     // 画像データの読み込みがおかしい場合の処理
  310.     DrawBox(0,0,480,272,DXP_COLOR_RED,TRUE); // 画面を真っ赤にする
  311.     DrawFormatString(10,100,DXP_COLOR_WHITE,"%sの読み込みに失敗しました",GRPH_HERO);
  312.     DrawFormatString(10,180,DXP_COLOR_WHITE,"終了します。何かキーを押して下さい。");
  313.     ScreenFlip();
  314.     // WaitKey();      // キーの入力待ち
  315.     do  {
  316.       ProcessMessage();
  317.     }while(CheckHitKeyAll() == 0);
  318.     return(-1); // エラーで抜けます
  319.   }
  320.  
  321.  
  322.   DrawBox(0,0,480,272,DXP_COLOR_BLACK,TRUE); // 画面を真っ黒にする
  323.   ScreenFlip();
  324.   Sleep(800); // 800ミリ秒だけ停止(黒い画面でチョイ待ち)
  325.  
  326.   return(0);
  327. }
  328.  
  329. ///////////////////////////////////////////////////////////////
  330. // sub6 初期化専門
  331. ///////////////////////////////////////////////////////////////
  332. int initton(void)
  333. {
  334.   ScreenSettings();
  335.  
  336.   // mp3音楽チェッカー
  337.   mp3checker();
  338.  
  339.   // 画像データ読み込み
  340.   return( pic_load() );
  341. }




Makefire

TARGET = PSP_RPG
OBJS = main.o

PSPSDK=$(shell psp-config --pspsdk-path)
INCS = $(PSPSDK)/include $(PSPSDK)/DXP_v0.5.7/include
INCDIR = $(INCS)

CFLAGS = -Wall -G0 -O3 -fomit-frame-pointer -mgp32 -mlong32

CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LIBDIR = $(PSPSDK)/DXP_v0.5.7/lib
LDFLAGS =
LIBS = $(PSPSDK)/DXP_v0.5.7/lib/dxlibp.a
LIBS += -lpspgu -lz -lm -lpsprtc -lpspaudio -lpspaudiocodec\
-lpsputility -lpspvalloc -lpsppower

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = PSP_RPG TEST v0.01
PSP_EBOOT_ICON = ICON0.png
PSP_EBOOT_ICON1 = NULL
PSP_EBOOT_UNKPNG= NULL
PSP_EBOOT_PIC1 = NULL
PSP_EBOOT_SND0 = NULL

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

# 以下、任意で(開発しているソースに依存)
main.o : main.c




関連記事
スポンサーサイト

[edit]

CM: 0
TB: 0

page top

この記事に対するコメント

page top

コメントの投稿

Secret

page top

トラックバック

トラックバックURL
→http://nekoyama2gillien.blog36.fc2.com/tb.php/372-9690478e
この記事にトラックバックする(FC2ブログユーザー)

page top


h o m e |


 

2017-04