Re: iリブロ
Posted: 2013年1月14日(月) 10:57
by ながもん
返信ありがとうございます。
DXライブラリとBox2Dを使っているプログラムでいじったソースファイルを載せます。
プログラミングは勉強ですのでみずらかったらすみません。
#include "main.h"
//グローバル変数
GameState g_gamestate = GAME_TITLE;
//box2d関連
b2Vec2 gravity(0.0f, GRAVITY_Y); //重力加速度
b2World g_world(gravity, true); //Box2DWorld
//ゲームデータ
Images g_images; //画像データ
Sounds g_sounds; //音声データ
StageInfo g_stage; //ステージデータ
Character ch;
HeroState hstate;
//メインループ
void MyMain(){
//ゲーム開始からの時間を計る
g_stage.gametime = g_lasttime - g_stage.gamestarttime;
//b2bの時間を進める
g_world.Step(g_frametime, VELOCITYITE, POSITIONITE);
//各画面の描画
switch(g_gamestate){
case GAME_TITLE:
DrawGameTitle();
break;
case GAME_MAIN:
DrawGameMain();
break;
case GAME_CLEAR:
DrawGameClear();
break;
case GAME_OVER:
DrawGameOver();
break;
}
}
//ファイルの読み込み
int LoadFiles(){
//主人公
if(LoadDivGraph("私.png",7,7,1,60,80,g_images.hero)==-1)
return -1;
//敵
if(LoadDivGraph("敵.png",5,5,1,60,80,g_images.enemy)==-1)
return -1;
//背景
if(LoadDivGraph("back_cross.png",2,2,1,128,128,g_images.back)==-1)
return -1;
//壁
g_images.wall[WALL_13]=LoadGraph("wall.png");
g_images.wall[WALL_0]=DerivationGraph(0,0,200,300,g_images.wall[WALL_13]);
g_images.wall[WALL_1]=DerivationGraph(0,0,1500,100,g_images.wall[WALL_13]);
g_images.wall[WALL_2]=DerivationGraph(0,0,250,50,g_images.wall[WALL_13]);
g_images.wall[WALL_3]=DerivationGraph(0,0,48,48,LoadGraph("リンゴ.png"));
g_images.wall[WALL_4]=DerivationGraph(0,0,300,500,g_images.wall[WALL_13]);
g_images.wall[WALL_5]=DerivationGraph(0,0,300,50,g_images.wall[WALL_13]);
g_images.wall[WALL_6]=DerivationGraph(0,0,157,50,g_images.wall[WALL_13]);
g_images.wall[WALL_7]=DerivationGraph(0,0,600,50,g_images.wall[WALL_13]);
g_images.wall[WALL_8]=DerivationGraph(0,0,200,200,g_images.wall[WALL_13]);
g_images.wall[WALL_9]=DerivationGraph(0,0,60,20,g_images.wall[WALL_13]);
g_images.wall[WALL_11]=NULL;
g_images.wall[WALL_10]=DerivationGraph(0,0,500,100,g_images.wall[WALL_13]);
g_images.wall[WALL_12]=DerivationGraph(0,0,60,10,g_images.wall[WALL_13]);
g_images.wall[WALL_14]=DerivationGraph(0,0,300,0,g_images.wall[WALL_13]);
//ゴールの旗
g_images.wall[GOAL]=LoadGraph("goal.png");
g_images.wall[MOUNTAIN]=LoadGraph("山.png");
g_images.wall[TREE]=LoadGraph("木.png");
g_images.wall[LEAF]=LoadGraph("木の葉.png");
g_images.wall[FALL]=LoadGraph("川.png");
g_images.wall[ROCK]=LoadGraph("岩.png");
g_images.wall[CLOUD]=LoadGraph("雲.png");
//読み込み成功
return 1;
}
//マップの読み込み
int LoadMapDate(char *filepath){
int f; //ファイルハンドル
char buf[1024]; //テキスト読み込みバッファ
f=FileRead_open(filepath);
if(f==0)return -1; //読み込みエラー
//マップサイズと主人公初期位置読み込み
if(FileRead_gets(buf,1023,f)==-1)return -1;
float w,h,sx,sy;
sscanf_s(buf,"%f,%f,%f,%f",&w,&h,&sx,&sy);
g_stage.mapsize_w=w;
g_stage.mapsize_h=h;
//主人公キャラクター
g_stage.hero=CreateBody(PHS(sx),PHS(sy),PHS(30),PHS(40),0,true,1,1+4,4.0f,0.1f,0.5f);
//地形オブジェクト
if(FileRead_gets(buf,1023,f)==-1)return -1;
int imax;
sscanf_s(buf,"%d",&imax); //行数取得
float x,y,angle;
int id;
for(int i=0;i<imax;i++){
if(FileRead_gets(buf,1023,f)==-1)return -1;
sscanf_s(buf,"%f,%f,%f,%f,%f,%d",&x,&y,&w,&h,&angle,&id);
//ボディ作成
switch(id){
case 0: //床壁
case 1: //抜け床
case 2: //ゴールフラグ
CreateStaticBlock(x,y,w,h,angle,id);
break;
case 3: //はてなボックス
CreateDynamicBlock(x,y,w,h,angle,id);
break;
}
}
FileRead_close(f);
return 0;
}
//ステージ初期化
void InitStage(){
//ゲームデータ全体のゼロ初期化
ZeroMemory(&g_stage, sizeof(g_stage));
ZeroMemory(&ch,sizeof(ch));
//全ボディ・ジョイント削除
DeleteAllBody();
//マウスジョイント用のグランドボディ作成
b2BodyDef bodydef;
g_stage.groundbody = g_world.CreateBody(&bodydef);
//地形読み込み
if(LoadMapDate("stage01.txt")==-1){
MessageBox(NULL,"マップデータ読み込み失敗","DXライブラリ",MB_OK);
}
//ゲーム開始時刻の記録
g_stage.gamestarttime = g_lasttime;
}
//タイトル画面描画
void GoGameTitle(){
g_gamestate = GAME_TITLE;
}
void DrawGameTitle(){
//テキスト表示
DrawStringToHandle(100, 340, "Zキーでゲームスタート",
0x666666, g_middlefont);
//キーをチェックして画面切り替え
int key = GetJoypadInputState( DX_INPUT_KEY_PAD1 );
if(IsAKeyTrigger(key)==true) GoGameMain();
}
//ゲーム本編描画
void GoGameMain(){
g_gamestate=GAME_MAIN;
InitStage(); //ステージデータの初期化
}
void DrawGameMain(){
//スクロール座標調整
b2Vec2 pos=g_stage.hero->GetPosition();
int hx=(int)(pos.x*WLDSC);
int hy=(int)(pos.y*WLDSC);
//画像表示
DrawGraph(-g_stage.screen_x-300,-g_stage.screen_y-70,g_images.back[0],true);
if(hx-(SCROLL_LIMIT+100)<g_stage.screen_x)
g_stage.screen_x=hx-(SCROLL_LIMIT+100);
if(640-(SCROLL_LIMIT+100)<hx-g_stage.screen_x)
g_stage.screen_x=hx+(SCROLL_LIMIT+100)-640;
if(hy-SCROLL_LIMIT<g_stage.screen_y)
g_stage.screen_y=hy-SCROLL_LIMIT;
if(480-SCROLL_LIMIT<hy-g_stage.screen_y)
g_stage.screen_y=hy+SCROLL_LIMIT-480;
g_gamestate = GAME_MAIN;
if(IsOutScreen(pos.x,pos.y)==true)GoGameOver();
//衝突チェック
g_stage.heroontheground=false;
g_stage.enemyontheground=false;
Collision();
int key=GetJoypadInputState(DX_INPUT_KEY_PAD1);
hstate=HERO_STANDING;
//主人公の位置と移動ベクトル
b2Vec2 vec=g_stage.hero->GetLinearVelocity();
float angle=g_stage.hero->GetAngle();
DrawEnemyAndMap(); //地形描
//キーチェック
if(g_stage.heroontheground==true&&(key&PAD_INPUT_C)==false){
//左右移動
if(key&PAD_INPUT_LEFT){
vec.x=-PHS(120.0f);
g_stage.hero->SetLinearVelocity(vec);
hstate=HERO_RUNNING;
g_stage.isheroleft=true;
}
if(key&PAD_INPUT_RIGHT){
vec.x=PHS(120.0f);
g_stage.hero->SetLinearVelocity(vec);
hstate=HERO_RUNNING;
g_stage.isheroleft=false;
}
//ジャンプ
if(IsBKeyTrigger(key)==true){
vec.x=0;
vec.y=-62.0f;
g_stage.hero->ApplyLinearImpulse(vec,pos);
hstate=HERO_JUMP;
g_stage.heroontheground=false;
}
}
//ジャンプ姿勢へ
if(g_stage.heroontheground==false)
{
hstate=HERO_JUMP;
//ヒップドロップ
if(key&PAD_INPUT_C){
vec.x=0;
vec.y=100.0f;
g_stage.hero->ApplyLinearImpulse(vec,pos);
hstate=HERO_SQUAT;
g_stage.isheroleft=false;
}
}
//転倒対策
if(fabs(angle)>0.2f)
g_stage.hero->SetAngularVelocity(-angle*2);
DrawHero(hstate); //主人公描画
}
//主人公の描画
void DrawHero(int hstate){
b2Vec2 pos=g_stage.hero->GetPosition();
float angle=g_stage.hero->GetAngle();
//キャラクター描画
int animpat=(g_lasttime/(1000/12)%4);
switch(hstate){
case HERO_STANDING:
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,angle,g_images.hero[0],TRUE,g_stage.isheroleft);
break;
case HERO_RUNNING:
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,angle,g_images.hero[1+animpat],TRUE,g_stage.isheroleft);
break;
case HERO_JUMP:
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,angle,g_images.hero[5],TRUE,g_stage.isheroleft);
break;
case HERO_SQUAT:
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,angle,g_images.hero[6],TRUE,g_stage.isheroleft);
}
}
//主人公の作成
void CreateHero(float x,float y,float w,float h)
{
g_stage.hero=CreateBody(PHS(x),PHS(y),PHS(w),PHS(h),0,true,1,1+4,4.0f,0.1f,0.5f);
}
//動かない床壁
void CreateStaticBlock(float x,float y,float w,float h,float angle,int id)
{
ch.size=(int)w;
ch.used=true;
switch(id){
case 0: //床壁
ch.body=CreateBody(PHS(x),PHS(y),PHS(w/2),PHS(h/2),angle,false,4,1+4,4.0f,0.2f,0.4f);
break;
case 1: //抜け床
ch.body=CreateBody(PHS(x),PHS(y),PHS(w/2),PHS(h/2),angle,false,2,2,4.0f,0.2f,0.4f);
break;
case 2: //ゴールフラグ
ch.body=CreateBody(PHS(x),PHS(y),PHS(w/2),PHS(h/2),angle,false,4,1,4.0f,0.2f,0.4f);
g_stage.flagbody=ch.body;
break;
}
if((int)h==300&&(int)w==200)ch.ID=WALL_0;
if((int)w==1500)ch.ID=WALL_1;
if((int)w==250&&(int)h==50)ch.ID=WALL_2;
if((int)h==48)ch.ID=WALL_3;
if((int)h==500)ch.ID=WALL_4;
if((int)w==300&&(int)h==50)ch.ID=WALL_5;
if((int)w==300&&(int)h==1)ch.ID=WALL_14;
if((int)w==600&&(int)h==50)ch.ID=WALL_7;
if((int)h==200)ch.ID=WALL_8;
if((int)h==20)ch.ID=WALL_9;
if((int)w==500&&(int)h==10)ch.ID=WALL_11;
if((int)w==500&&(int)h==100)ch.ID=WALL_10;
if((int)w==60&&(int)h==10)ch.ID=WALL_12;
if(id==1)
{
switch((int)w)
{
case 156:ch.ID=WALL_6; //抜け床
break;
case 2159:ch.ID=MOUNTAIN; //山
break;
case 494:ch.ID=TREE; //木
break;
case 650:ch.ID=LEAF; //葉
break;
case 403:ch.ID=FALL; //滝
break;
case 70:ch.ID=ROCK; //岩
break;
case 60:ch.ID=CLOUD; //雲
break;
}
}
if(id==2)ch.ID=GOAL; //ゴールフラグ
g_stage.wall[g_stage.num_mapchara]=ch;
ch.body->SetUserData(&g_stage.wall[g_stage.num_mapchara]);
g_stage.num_mapchara++;
}
//動く床壁
void CreateDynamicBlock(float x,float y,float w,float h,float angle,int id)
{
ch.size=(int)w;
ch.used=true;
b2WeldJointDef wjointdef;
b2PrismaticJointDef pjointdef;
switch(id){
case 3:
ch.body=CreateBody(PHS(x),PHS(y),PHS(w/2),PHS(h/2),angle,true,4,1+4,4.0f,0.2f,0.4f);
pjointdef.Initialize(g_stage.groundbody,ch.body,ch.body->GetPosition(),b2Vec2(0.0f,-1.0f));
pjointdef.enableLimit=true; //制限有効
pjointdef.lowerTranslation=PHS(0); //下限
pjointdef.upperTranslation=PHS(50);//上限
g_world.CreateJoint(&pjointdef);
ch.type=HATENA_BOX;
if((int)h==48)ch.ID=WALL_3;
break;
}
g_stage.wall[g_stage.num_mapchara]=ch;
ch.body->SetUserData(&g_stage.wall[g_stage.num_mapchara]);
g_stage.num_mapchara++;
}
//地形の描画
void DrawEnemyAndMap()
{
int animpat=(g_lasttime/(1000/12)%4);
int kawapat=(g_lasttime/(500/12)%8);
for(int x=0;x<6;x++){
for(int y=0;y<5;y++){
int delta=(g_lasttime/(1000/50))%128;
DrawGraph(x*128-delta,y*128-delta,g_images.back[1],FALSE);
}
}
//地形の描画
for(int i=0;i<g_stage.num_mapchara;i++)
{
//床壁
if(g_stage.wall.used==false)continue;
b2Vec2 pos=g_stage.wall.body->GetPosition();
float angle=g_stage.wall.body->GetAngle();
int id=g_stage.wall.ID;
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,angle,g_images.wall[id],TRUE);
if(g_stage.wall.ID==FALL)
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y+kawapat),1,angle,g_images.wall[FALL],TRUE);
}
EnterEnemy();
for(int i=0;i<MAXENEMYCHARA;i++)
{
if(g_stage.enemy.used==false)continue;
b2Vec2 pos=g_stage.enemy.body->GetPosition();
//画面外に出たら消去
if(g_stage.enemy.damage>0.0f||IsOutScreen(pos.x,pos.y)==true)
{
g_stage.enemy.used=false;
g_world.DestroyBody(g_stage.enemy.body);
continue;
}
b2Vec2 vec=g_stage.enemy[i].body->GetLinearVelocity();
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,0,g_images.enemy[animpat],TRUE);
switch(g_stage.enemy[i].type){
case ENEMY:
vec.x=g_stage.enemy[i].vecx;
g_stage.enemy[i].body->SetLinearVelocity(vec);
break;
}
float angle=g_stage.enemy[i].body->GetAngle();
if(fabs(angle)>0.1f)
g_stage.enemy[i].body->SetAngularVelocity(-angle*20);
}
}
//ゲームクリア画面描画
void GoGameClear(){
g_gamestate = GAME_CLEAR;
g_stage.timerstart = g_lasttime;
}
void DrawGameClear(){
DrawEnemyAndMap();
DrawHero(HERO_STANDING);
DrawGraph(-50,160,LoadGraph("gameclear.png"),TRUE);
//5秒経ったらタイトル画面へ
if(g_lasttime - g_stage.timerstart > 5000) GoGameTitle();
}
//ゲームオーバー画面描画
void GoGameOver(){
g_gamestate = GAME_OVER;
g_stage.timerstart = g_lasttime;
}
void DrawGameOver(){
DrawGraph(20,20,LoadGraph("gameover.png"),TRUE);
//5秒経ったらタイトル画面へ
if(g_lasttime - g_stage.timerstart > 5000) GoGameTitle();
}
b2Body* CreateBody(float x,float y,float w,float h,float angle,bool dynamic,int categoryBits,int maskBits
,float density,float restitution,float friction)
{
//ボディ定義
b2BodyDef bodydef;
if(dynamic)bodydef.type=b2_dynamicBody; //動的ボディ
else bodydef.type=b2_staticBody; //静的ボディ
bodydef.position.Set(x,y);
bodydef.angle=angle;
//ボディ作成
b2Body* body=g_world.CreateBody(&bodydef);
//シェイプ作成
b2PolygonShape staticBox;
staticBox.SetAsBox(w,h);
//フィクスチャ定義
b2FixtureDef fixturedef;
fixturedef.shape=&staticBox;
fixturedef.density=density; //密度
fixturedef.restitution=restitution; //反発力
fixturedef.friction=friction; //摩擦係数
fixturedef.filter.categoryBits=categoryBits;
fixturedef.filter.maskBits=maskBits;
body->CreateFixture(&fixturedef);
return body;
}
//主人公衝突判定
void Collision(){
//接触確認ループ
for(b2Contact* c = g_world.GetContactList(); c!=NULL;
c = c->GetNext())
{
if(c->IsTouching() == false) continue;
//接触しているボディを取り出す
b2Body* bd[2];
b2Fixture* fx[2];
fx[0]=c->GetFixtureA();
fx[1]=c->GetFixtureB();
bd[0]=fx[0]->GetBody();
bd[1]=fx[1]->GetBody();
//ボディチェック
for(int i=0;i<2;i++){
b2Body *obd=bd[(i+1)%2];
Character *ch = (Character *)bd[i]->GetUserData();
Character *och = (Character *)obd->GetUserData();
//接地チェック
if( bd[i]==g_stage.hero )
{
g_stage.heroontheground = true;
if(och->type==ENEMY)
{
b2Vec2 pos1=g_stage.hero->GetPosition();
b2Vec2 pos=och->body->GetPosition();
float hx=(float)(pos1.x*WLDSC);
float hy=(float)(pos1.y*WLDSC);
float ex=(float)(pos.x*WLDSC);
float ey=(float)(pos.y*WLDSC);
if(PHS(hy+40)>=PHS(ey-45)&&PHS(hx+30)>PHS(ex-30)&&PHS(hx-30)<PHS(ex+30))
{
DrawRotaGraph(VIWX(pos.x),VIWY(pos.y),1,0,g_images.enemy[4],TRUE);
och->damage=10.0f;
}
if(PHS(hx+30)>=PHS(ex-31)&&PHS(hy)>=PHS(ey-40))
GoGameOver();
}
if(obd==g_stage.flagbody)
GoGameClear();
}
if(ch!=NULL&&och!=NULL){
//モンスター左右方向転換
if(ch->type>=ENEMY){
g_stage.enemyontheground=true;
b2Manifold *manifold = c->GetManifold();
if(manifold->type >= b2Manifold::e_faceA){
//進行方向で衝突が起きていたら
if( (manifold->localNormal.x < 0.0f && ch->vecx > 0.0f)||
(manifold->localNormal.x > 0.0f && ch->vecx < 0.0f))
ch->vecx =-ch->vecx;
}
}
}
}
}
}
//敵を出現させる
void EnterEnemy()
{
for(int i=0;i<MAXENEMYCHARA;i++){
//空きキャラクターを探す
//位置を決める
float x=(float)GetRand((int)g_stage.mapsize_w);
int blank=FindBlankChara(g_stage.enemy,MAXENEMYCHARA);
if(blank>=0)
{ //ボディ作成
ch.body=CreateBody(PHS(x),0,PHS(30),PHS(40),0,true,4,5,4.0f,0.0f,0.1f);
ch.used=true;
ch.vecx=-PHS(speed);
ch.type=ENEMY;
ch.damage=0.0f;
g_stage.enemy[blank]=ch;
ch.body->SetUserData(&g_stage.enemy[blank]);
}
}
}
//配列から空きキャラクターを探す
int FindBlankChara(Character *arr,int arraymax)
{
for(int i=0;i<arraymax;i++){
if(arr[i].used==false)
return i;
}
//空きが見つからなかった場合
return -1;
}