いまのところ当たり判定までだいたい出来上がったのでアニメーションで
主人公のソロモンを動かしたいと思っているのですがなかなかうまく動いてくれません。
アニメーション関連の座標はあってると思うのですが、何がいけないのでしょうか?
//--------------------------------------------------------------------------------------
// File: EmptyProject.cpp
//
// Empty starting point for new Direct3D applications
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include <tchar.h>
#include "dxstdafx.h"
#include "resource.h"
LPDIRECT3DTEXTURE9 pTexture; // スタート画面
LPDIRECT3DTEXTURE9 pTex_clear; // クリア画面
LPDIRECT3DTEXTURE9 pTex_map; // マップ1面
LPDIRECT3DTEXTURE9 pTex_soro; // ソロモン
LPD3DXSPRITE pSprite;
D3DXVECTOR3 gPos = D3DXVECTOR3(-9,-9,0); // スタート画面座標
D3DXVECTOR3 gPos2 = D3DXVECTOR3(-9,-9,0); // クリア画面座標
D3DXVECTOR3 gPos1; // 主人公座標
D3DXVECTOR3 gPos_key; // 鍵の座標
D3DXVECTOR3 gPos_door; // 扉の座標
int gamemode = 0; // ゲームモード 0:タイトル 1:1面
int key = 1; // 0:鍵がない状態 1:ある状態
int door = 0; // 0:扉が閉まっている状態 1:開いてる状態
// あたり判定に関する情報
#define MAPNO_HARDBLOCK 2 // 非破壊ブロック // 「#define」はショートカットみたいなもの
#define MAPNO_SOFTBLOCK 3 // 破壊可能ブロック
#define MAPNO_NONE 4 // 空
#define MAPNO_KEY 6 // 鍵
#define MOVEPOWER 1.5f // 上がる高さ
// マップデータ
#define CHIPSIZE 16 // 1チップの大きさ
#define MAP_X 15 // マップの大きさX
#define MAP_Y 15 // マップの大きさY
int mapdata[MAP_Y][MAP_X]=
{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,4,4,7,4,4,2,2,2,2,2,
2,2,2,2,3,4,4,4,4,4,3,2,2,2,2,
2,2,2,2,3,4,4,4,4,4,3,2,2,2,2,
2,2,2,2,2,4,4,4,4,4,2,2,2,2,2,
2,4,4,4,4,2,2,4,4,2,2,4,4,4,2,
2,4,4,4,4,4,4,3,4,4,3,4,4,4,2,
2,4,4,4,4,4,2,2,2,2,2,4,4,4,2,
2,2,2,2,2,2,4,4,4,2,2,4,2,2,2,
2,2,2,4,4,2,4,4,4,2,4,4,2,2,2,
2,2,2,2,4,4,4,4,4,4,4,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
}; // マップチップは2の乗数じゃなきゃいけない(128や256)
int i,k; // ループ変数
// テクスチャの表示領域指定
RECT rectTex;
// 移動モード0:受付中 1:左移動 2:右移動 3:上移動 4;下移動
int movemode = 0;
// ジャンプ
float move = MOVEPOWER; // ジャンプ
// アニメーション関係
int gametime = 0; // ゲームタイム
int mainanicount = 0; // メインキャラアニメカウント
//--------------------------------------------------------------------------------------
// Create any D3DPOOL_MANAGED resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
gPos_key.x=192; // 鍵の座標
gPos_key.y=128;
gPos_door.x=112; // 扉の座標
gPos_door.y=176;
return S_OK;
}
//--------------------------------------------------------------------------------------
// Create any D3DPOOL_DEFAULT resources here
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
{
return S_OK;
}
//--------------------------------------------------------------------------------------
// Handle updates to the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
// スタート画面からZで1面に移行
if(DXUTIsKeyDown('A'))
{
gamemode = 1; // 1面
}
if(gamemode == 1 && movemode == 0) // 落下処理(1面でなおかつ操作されてない時) // &&=なおかつ ||=または
{
if(mapdata[(int)gPos1.y/16+1][((int)gPos1.x+2)/16] != MAPNO_HARDBLOCK // 下が空白(左起点)
&& mapdata[(int)gPos1.y/16+1][((int)gPos1.x+13)/16] != MAPNO_HARDBLOCK // 下が空白(右起点)
&& mapdata[(int)gPos1.y/16+1][((int)gPos1.x+2)/16] != MAPNO_SOFTBLOCK
&& mapdata[(int)gPos1.y/16+1][((int)gPos1.x+13)/16] != MAPNO_SOFTBLOCK)
{
gPos1.y += 1.8f; // 重さ
if(mapdata[(int)gPos1.y/16+1][((int)gPos1.x+2)/16] != MAPNO_NONE
|| mapdata[(int)gPos1.y/16+1][((int)gPos1.x+13)/16] != MAPNO_NONE) // 主人公の左起点で下1個分ずれた所
{
/*gPos1.y=gPos1.y/16*16-1.8;*/ // 重さ分埋まるのでその補正
}
}
}
// 移動関係
switch(movemode)
{
case 0: // 入力待ちモード
if(DXUTIsKeyDown(VK_LEFT) && !DXUTIsKeyDown(VK_UP)) //左キーが押されたら(純粋に左移動)
{
if( mapdata[((int)gPos1.y+8)/16][((int)gPos1.x+2)/16] != MAPNO_HARDBLOCK
&& mapdata[((int)gPos1.y+8)/16][((int)gPos1.x+2)/16] != MAPNO_SOFTBLOCK) // 主人公の座標は左上が基準なので左側は「-1]などはいらない
movemode = 1; // 左下端(左に障害物)
}
else if(DXUTIsKeyDown(VK_RIGHT) && !DXUTIsKeyDown(VK_UP)) // 右キーが押されたら(純粋に右移動)
{
if( mapdata[((int)gPos1.y+8)/16][((int)gPos1.x+13)/16] != MAPNO_HARDBLOCK
&& mapdata[((int)gPos1.y+8)/16][((int)gPos1.x+13)/16] != MAPNO_SOFTBLOCK) // 主人公の右下端(右に障害物)
movemode = 2;
}
else if(DXUTIsKeyDown(VK_UP) && !DXUTIsKeyDown(VK_RIGHT) && !DXUTIsKeyDown(VK_LEFT)) // 上が押されつつ左右が押されていない(純粋に上移動)
{
if( mapdata[(int)gPos1.y/16-1][((int)gPos1.x+2)/16] != MAPNO_HARDBLOCK // 右側ブロックの上ジャンプ不可(左起点)
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+13)/16] != MAPNO_HARDBLOCK // 左側ブロックの上ジャンプ不可(右起点)
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+2)/16] != MAPNO_SOFTBLOCK
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+13)/16] != MAPNO_SOFTBLOCK)// 上になにもないならジャンプフラグへ
{
movemode = 3;
}
}
else if(DXUTIsKeyDown(VK_UP) && DXUTIsKeyDown(VK_RIGHT)) // 上が押されて右も押されたら
{
if( mapdata[(int)gPos1.y/16-1][((int)gPos1.x+2)/16] != MAPNO_HARDBLOCK // 左側ブロックの斜めジャンプ不可(左起点)
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+13)/16] != MAPNO_HARDBLOCK // 右側ブロックの斜めジャンプ不可(右起点)
&& mapdata[((int)gPos1.y+15)/16][((int)gPos1.x+13)/16] != MAPNO_HARDBLOCK // 主人公の右下端(右に障害物)
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+2)/16] != MAPNO_SOFTBLOCK
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+13)/16] != MAPNO_SOFTBLOCK
&& mapdata[((int)gPos1.y+15)/16][((int)gPos1.x+13)/16] != MAPNO_SOFTBLOCK) // 上になにもないならジャンプへ
{
movemode = 4;
}
}
else if(DXUTIsKeyDown(VK_UP) && DXUTIsKeyDown(VK_LEFT)) // 上が押されて左も押されたら
{
if( mapdata[(int)gPos1.y/16-1][((int)gPos1.x+2)/16] != MAPNO_HARDBLOCK // 右側ブロックの斜めジャンプ不可(左起点)
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+13)/16] != MAPNO_HARDBLOCK // 左側ブロックの斜めジャンプ不可(右起点)
&& mapdata[((int)gPos1.y+15)/16][((int)gPos1.x+2)/16] != MAPNO_HARDBLOCK // 主人公の左下端(左に障害物)
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+2)/16] != MAPNO_SOFTBLOCK
&& mapdata[(int)gPos1.y/16-1][((int)gPos1.x+13)/16] != MAPNO_SOFTBLOCK
&& mapdata[((int)gPos1.y+15)/16][((int)gPos1.x+2)/16] != MAPNO_SOFTBLOCK)
{ // 上になにもないならジャンプへ
movemode = 5;
}
}
break;
case 1: // 左移動モード
gPos1.x-=1.3f; // X座標を減らす
movemode = 0; // 移動していたら移動モードのリセット
break;
case 2: // 右移動モード
gPos1.x+=1.3f; // X座標を減らす
movemode = 0;
break;
case 3: // 上移動とジャンプ
gPos1.y -= move; // 加速度 -=0.5で少し斜めに上がる
if((mapdata[((int)gPos1.y-1)/16][((int)gPos1.x+2)/16] != MAPNO_NONE) // 上めり込み
|| (mapdata[((int)gPos1.y-1)/16][((int)gPos1.x+13)/16] != MAPNO_NONE))
{
gPos1.y+=move;
move=-0.5f;
}
move -= 0.07f; // 主人公の重さ的な (ここから下はジャンプしたあとの処理)
if(mapdata[(int)gPos1.y/16+1][((int)gPos1.x+2)/16] != MAPNO_NONE
&& mapdata[(int)gPos1.y/16+1][((int)gPos1.x+13)/16] != MAPNO_NONE) // 主人公の左起点で下1個分ずれた所
{
gPos1.y=(float)(((int)gPos1.y/16)*16); // Y座標調整
move= MOVEPOWER;
movemode = 0;
}
break;
case 4: // 右上移動とジャンプ
gPos1.x+=0.6f;
if(mapdata[((int)gPos1.y)/16][((int)gPos1.x+13)/16] != MAPNO_NONE
|| mapdata[((int)gPos1.y+14)/16][((int)gPos1.x+13)/16] != MAPNO_NONE)
{
gPos1.x-=0.6f; // 右側壁でつるんとなる処理 yは-され続けるけどxは下がるので壁で止まらない
}
gPos1.y -= move; // 加速度 -=0.5で少し斜めに上がる
if(move>0 && ((mapdata[((int)gPos1.y-1)/16][((int)gPos1.x+2)/16] != MAPNO_NONE) // move>0(上のブロックに頭突きをしたら)
|| (mapdata[((int)gPos1.y-1)/16][((int)gPos1.x+13)/16] != MAPNO_NONE)))
{
gPos1.y+=move;
move=0.0f; // moveを0に(下がる)
}
move -= 0.07f; // 主人公の重さ的な
if(mapdata[((int)gPos1.y)/16+1][((int)gPos1.x+2)/16] != MAPNO_NONE
|| mapdata[(int)gPos1.y/16+1][((int)gPos1.x+13)/16] != MAPNO_NONE) // 主人公の左起点で下1個分ずれた所
{
gPos1.y=(float)(((int)gPos1.y/16)*16);
move= MOVEPOWER;
movemode = 0;
}
break;
case 5: // 左上移動とジャンプ
gPos1.x-=0.6f;
if(mapdata[(int)gPos1.y/16+1][(int)gPos1.x/16] != MAPNO_NONE)
{
gPos1.x+=0.6f;
}
gPos1.y -= move; // 加速度 -=0.5ずつ上がっていく
if(move>0 && ((mapdata[((int)gPos1.y-1)/16][((int)gPos1.x+2)/16] != MAPNO_NONE) // move>0(上のブロックに頭突きをしたら)
|| (mapdata[((int)gPos1.y-1)/16][((int)gPos1.x+13)/16] != MAPNO_NONE)))
{
gPos1.y+=move;
move=-0.0f; // moveを0に(下がる)
}
move -= 0.07f; // 主人公の重さ的な
if(mapdata[(int)gPos1.y/16+1][((int)gPos1.x+2)/16] != MAPNO_NONE
|| mapdata[(int)gPos1.y/16+1][((int)gPos1.x+13)/16] != MAPNO_NONE) // 主人公の左起点で下1個分ずれた所
{
gPos1.y=(float)(((int)gPos1.y/16)*16);
move= MOVEPOWER;
movemode = 0;
}
break;
}
// めりこんだ後戻す処理
if((mapdata[(int)gPos1.y/16][((int)gPos1.x+2)/16] != MAPNO_NONE)
|| (mapdata[((int)gPos1.y+15)/16][((int)gPos1.x+2)/16] != MAPNO_NONE))// 右めりこみ
{
gPos1.x=(float)(((int)(gPos1.x+2)/16+1)*16-2); // 16[-2]めりこんだ後-2戻す
}
if((mapdata[(int)gPos1.y/16][((int)gPos1.x+13)/16] != MAPNO_NONE) // 左めり込み
|| (mapdata[((int)gPos1.y+15)/16][((int)gPos1.x+13)/16] != MAPNO_NONE))
{
gPos1.x=(float)(((int)(gPos1.x+13)/16-1)*16+2); // 16[+2]めりこんだ後+2戻す
}
// ブロック破壊
if(DXUTIsKeyDown('Z')) // Zが押されたら
{
if( mapdata[(int)gPos1.y/16][(int)gPos1.x/16 + 1] == MAPNO_SOFTBLOCK) // 右側に破壊可能ブロックがある場合
{
mapdata[(int)gPos1.y/16][(int)gPos1.x/16 + 1] = MAPNO_NONE; // 右側を背景にする(ブロックを破壊する)
}
else if(mapdata[(int)gPos1.y/16][(int)gPos1.x/16 ] == MAPNO_SOFTBLOCK) // 左側に破壊可能ブロックがある場合
{
mapdata[(int)gPos1.y/16][(int)gPos1.x/16 ] = MAPNO_NONE; // 左側を背景にする(ブロックを破壊)
}
}
// ブロック作成
if(DXUTIsKeyDown('X') && DXUTIsKeyDown(VK_RIGHT)) // Xが押されたら
{
if(mapdata[(int)gPos1.y/16][((int)gPos1.x+13)/16+1] == MAPNO_NONE) // 右側が空白の場合 [y16/16=0][(x2+13/16=1)+1]=2 次の座標つまりxが2ずれてても次の座標にブロックがだせる
{
mapdata[(int)gPos1.y/16][((int)gPos1.x+13)/16+1] = MAPNO_SOFTBLOCK; // 右側をブロックにする(ブロックを作成)
}
}
if(DXUTIsKeyDown('X') && DXUTIsKeyDown(VK_LEFT))
{
if(mapdata[(int)gPos1.y/16][((int)gPos1.x-13)/16] == MAPNO_NONE)
{
mapdata[(int)gPos1.y/16][((int)gPos1.x-13)/16] = MAPNO_SOFTBLOCK;
}
}
// 当たり判定(その他)
if(key == 1) // 鍵がある状態
{
if(gPos1.x<gPos_key.x+13 && gPos_key.x<gPos1.x+13 && gPos1.y<gPos_key.y+13 && gPos_key.y<gPos1.y+13) // 鍵の当たり判定
{
key = 0; // 鍵がない状態
}
}
// 鍵が無い状態になったら扉が開く 扉に当たったらステージ2へ
if(key == 0)
{
if(gPos1.x<gPos_door.x+13 && gPos_door.x<gPos1.x+13 && gPos1.y<gPos_door.y+13 && gPos_door.y<gPos1.y+13)
gamemode = 2;
}
// アニメーション関連
gametime++; // ゲームタイムの加算
if(DXUTIsKeyDown(VK_RIGHT) || DXUTIsKeyDown(VK_LEFT))
{
mainanicount++; // ソロモンアニメカウントの加算
}
else
{
mainanicount = 0; // ソロモンアニメカウントの初期化(動いてない時は、通常絵に)
}
if(mainanicount < 10)
{
SetRect(&rectTex,0,0,16,16);
}
else if(mainanicount < 20)
{
SetRect(&rectTex,16,0,32,16);
}
else if(mainanicount < 30)
{
SetRect(&rectTex,32,0,48,16);
}
else if(mainanicount < 40)
{
SetRect(&rectTex,48,0,64,16);
}
else
{
mainanicount = 0;
}
}
//--------------------------------------------------------------------------------------
// Render the scene
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
HRESULT hr;
// Clear the render target and the zbuffer
V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
// Render the scene
if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{
// ここから描画処理を行う
// スプライトの開始
pSprite->Begin(D3DXSPRITE_ALPHABLEND);
// スプライトで2D描画
switch(gamemode)
{
case 0: // スタート画面
pSprite->Draw(pTexture,NULL,NULL,&gPos,D3DCOLOR_ARGB(255,255,255,255));
break;
case 1: // 1面
for(i = 0;i<15;i++)
{
for(k = 0;k<15;k++)
{
SetRect(&rectTex,mapdata[i][k] * 16,0,mapdata[i][k] * 16 + 16,16);
pSprite->Draw(pTex_map,&rectTex,NULL,&D3DXVECTOR3((k * 16.0f),(i *16.0f),0),D3DCOLOR_ARGB(255,255,255,255));
}
}
// 鍵
if(key == 1)
{
SetRect(&rectTex,(6 * 16),0,(7 * 16),16);
pSprite->Draw(pTex_map,&rectTex,NULL,&gPos_key,D3DCOLOR_ARGB(255,255,255,255));
}
// 扉
if(door == 0)
SetRect(&rectTex,(5 * 16),0,(6 * 16),16);
pSprite->Draw(pTex_map,&rectTex,NULL,&gPos_door,D3DCOLOR_ARGB(255,255,255,255));
// 主人公の表示
SetRect(&rectTex,(0 * 16),0,(1 * 16),16);
pSprite->Draw(pTex_soro,&rectTex,NULL,&gPos1,D3DCOLOR_ARGB(255,255,255,255));
break;
case 2: // クリア画面
pSprite->Draw(pTex_clear,NULL,NULL,&gPos2,D3DCOLOR_ARGB(255,255,255,255));
break;
}
// スプライトの終了
pSprite->End();
V( pd3dDevice->EndScene() );
}
}
//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
bool* pbNoFurtherProcessing, void* pUserContext )
{
return 0;
}
//--------------------------------------------------------------------------------------
// Release resources created in the OnResetDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnLostDevice( void* pUserContext )
{
}
//--------------------------------------------------------------------------------------
// Release resources created in the OnCreateDevice callback here
//--------------------------------------------------------------------------------------
void CALLBACK OnDestroyDevice( void* pUserContext )
{
// テクスチャの解放
SAFE_RELEASE(pTexture); // スタート画面
SAFE_RELEASE(pTex_clear); // クリア画面
SAFE_RELEASE(pTex_map); // マップ1面
SAFE_RELEASE(pTex_soro); // ソロモン
// スプライトの解放
SAFE_RELEASE(pSprite);
}
//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
// Set the callback functions
DXUTSetCallbackDeviceCreated( OnCreateDevice );
DXUTSetCallbackDeviceReset( OnResetDevice );
DXUTSetCallbackDeviceLost( OnLostDevice );
DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
DXUTSetCallbackMsgProc( MsgProc );
DXUTSetCallbackFrameRender( OnFrameRender );
DXUTSetCallbackFrameMove( OnFrameMove );
// TODO: Perform any application-level initialization here
// Initialize DXUT and create the desired Win32 window and Direct3D device for the application
DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
DXUTCreateWindow( L"EmptyProject" );
DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 240, 240);
// スプライトの作成
D3DXCreateSprite(DXUTGetD3DDevice(),&pSprite);
// テクスチャのロード
D3DXCreateTextureFromFile(DXUTGetD3DDevice(),_T("start.png"),&pTexture); // スタート画面
D3DXCreateTextureFromFile(DXUTGetD3DDevice(),_T("clear.png"),&pTex_clear); // クリア画面
D3DXCreateTextureFromFile(DXUTGetD3DDevice(),_T("gazou.png"),&pTex_map); // 1面のマップチップ
D3DXCreateTextureFromFile(DXUTGetD3DDevice(),_T("soro.png"),&pTex_soro); // ソロモン
// 主人公の座標初期化
gPos1 = D3DXVECTOR3(16,144,0);
// Start the render loop
DXUTMainLoop();
// TODO: Perform any application-level cleanup here
return DXUTGetExitCode();
}