トップページ > 過去ログ > 記事閲覧
ソウルキャリバーの剣の軌跡
名前:ななし 日時: 2008/03/04 09:57

tp://www.youtube.com/watch?v=0W9HdiC2VZE ソウルキャリバーの剣の軌跡をDXライブラリで 表現してみたいのですが、さっぱりわかりません どなたか教えてくれませんか?

Page: 1 |

Re: ソウルキャリバーの剣の軌跡 ( No.1 )
名前:crow 日時:2008/03/04 23:43

ソウルキャリバーの剣の奇跡は3Dで作られているので、 全く同じ事をDXライブラリでするのは難しいと思います。 2Dの残像表現は、1〜数フレーム前の位置情報を保持しておいて、 そこに半透明もしくは色を変更した画像を残像として書き込む手法が主流です。 これも工夫次第ではかなり綺麗な表現ができると思うので、 いろいろ試してみてください。
Re: ソウルキャリバーの剣の軌跡 ( No.2 )
名前:ひら 日時:2008/03/04 23:44

DXライブラリは3Dに向いてないので何とも言えませんが、 考え方としては剣の軌跡(座標)を保持して、軌跡の部分を半透明の剣で描画すれば良いと思います。 参考としては、サンプルプログラムにあるホーミングレーザーの軌跡の部分を、 半透明にして見てみて下さい。 剣に近い(時間が新しい)ほど不透明にすれば、 軌跡っぽい感じになると思います。
Re: ソウルキャリバーの剣の軌跡 ( No.3 )
名前:ひら 日時:2008/03/04 23:44

すみません、被りました。
Re: ソウルキャリバーの剣の軌跡 ( No.4 )
名前:ななし 日時:2008/03/05 16:05

ありがとうございました。やってみますね。 エフェクト作るの難しいですね。 みなさんは、どうやっていますか?
Re: ソウルキャリバーの剣の軌跡 ( No.5 )
名前:かたぱると 日時:2008/04/08 09:49

こんなん作ってみました。 サンプルに全部はっつければ動くかと。 テストでガリガリっと適当に書いたものなので 見易さとかは割愛でする。 クラスとかにもせずグローバル変数でやっちゃってます。 本当であれば三角形を一枚一枚逆に並べて帯にしてやるのですが 今回は簡易なので始点が同じの扇状。 調整すれば綺麗に見える…かも? 以下をコピー #include "DxLib.h" #include <list> #define SHADOW_COUNT_DEC 2 // 消えるスピードの速さ #define SHADOW_MAXCOUNT 30 // 影生存タイマー #define SHADOW_ALLAY_MAX (int)(SHADOW_MAXCOUNT/SHADOW_COUNT_DEC)+1 // 影のMAX数 #define SWORD_COLLOR GetColor( 0 , 100 , 200 ) struct SWORDSHADOW { int baseX,baseY; // 根元 int beforeX,beforeY; // 1フレーム前の剣先 int nowX,nowY; // 現在の剣先 int color; // 影の色 int count; // 残りタイマー }; std::list<SWORDSHADOW> g_shadow; // 影データ int g_beforeX,g_beforeY; // 1フレーム前の剣先 void clearShadow(); // データクリア void shadowTrem(); // 影処理 void drawShadow(); // 表示 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { SetGraphMode( 640 , 480 , 16 ) ; ChangeWindowMode( true ) ; SetMainWindowText( "SwordEffectTest" ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } // 描画先を裏画面にセット SetDrawScreen( DX_SCREEN_BACK ) ; // 剣先リセット GetMousePoint( &g_beforeX , &g_beforeY ); // ループ while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 画面のクリア DrawBox( 0,0,640,480,GetColor(200,200,200),true); // 剣の処理 shadowTrem(); // 表示 drawShadow(); // 裏画面の内容を表画面に反映させる ScreenFlip() ; } // 一応データクリア clearShadow(); DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } // データクリア void clearShadow() { g_shadow.clear(); } // 影処理 void shadowTrem() { int nowX,nowY; GetMousePoint( &nowX,&nowY); // カウンター処理 std::list<SWORDSHADOW>::iterator ite; for( ite = g_shadow.begin() ; ite != g_shadow.end() ; ite++ ) { if( ite->count < SHADOW_COUNT_DEC ) { // カウントが足りないので削除 ite = g_shadow.erase(ite); } else { ite->count -= SHADOW_COUNT_DEC; } } // 追加処理 if( g_shadow.size() > SHADOW_ALLAY_MAX ) { // もう一杯だから追加しない } else { // 一個△追加。 SWORDSHADOW addShadow; addShadow.baseX = 320; addShadow.baseY = 240; addShadow.beforeX = g_beforeX; addShadow.beforeY = g_beforeY; addShadow.color = SWORD_COLLOR; addShadow.count = SHADOW_MAXCOUNT; addShadow.nowX = nowX; addShadow.nowY = nowY; g_shadow.push_back( addShadow ); } // OLD更新 g_beforeX = nowX; g_beforeY = nowY; } // 表示 void drawShadow() { std::list<SWORDSHADOW>::iterator ite; for( ite = g_shadow.begin() ; ite != g_shadow.end() ; ite++ ) { // 半透明設定(生存カウンターで代用) if( ite->count > 255 ) { SetDrawBlendMode( DX_BLENDMODE_ALPHA , 255 ); } else { SetDrawBlendMode( DX_BLENDMODE_ALPHA , ite->count ); } // 表示(三角形) DrawTriangle( ite->baseX , ite->baseY, ite->beforeX,ite->beforeY, ite->nowX , ite->nowY, ite->color , true ); } SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ); }
Re: ソウルキャリバーの剣の軌跡 ( No.6 )
名前:ひら 日時:2008/04/07 22:44

カッコイイ!素晴らしい。
Re: ソウルキャリバーの剣の軌跡 ( No.7 )
名前:かたぱると 日時:2008/04/08 09:54

見直して誤記とかちょいと手直し。 ついでに SHADOW_COUNT_DEC と SHADOW_MAXCOUNT を調整して 微妙に綺麗に見えるように(?)なったか? うーむ、簡易だとこんなもんだろうか(;-"-)
Re: ソウルキャリバーの剣の軌跡 ( No.8 )
名前:かたぱると 日時:2008/04/10 18:41

冗長で帯版。 ソースの汚さはとツッコミどころは 見逃してくださいm(_ _)m 剣先と鍔先の求め方は適当。 頑張って調整すれば実用できるんじゃないだろうかとか思ってみたり。 以下をコピー #include "DxLib.h" #include <math.h> #include <list> #define SHADOW_COUNT_DEC 2 // 消えるスピードの速さ #define SHADOW_MAXCOUNT 30 // 影生存タイマー #define SHADOW_ALLAY_MAX (((int)(SHADOW_MAXCOUNT/SHADOW_COUNT_DEC)+2)*2) // 影のMAX数 #define SWORD_COLLOR GetColor( 0 , 100 , 200 ) #define CALC_PI 3.14159265358979323846 struct SWORDSHADOW { int baseX,baseY; // 根元 int beforeX,beforeY; // 1フレーム前の剣先 int nowX,nowY; // 現在の剣先 int color; // 影の色 int count; // 残りタイマー }; std::list<SWORDSHADOW> g_shadow; // 影データ int g_beforeX,g_beforeY; // 1フレーム前の剣先 int g_beforeBX,g_beforeBY; // 1フレーム前の鍔先 void clearShadow(); // データクリア void shadowTrem(); // 影処理 void drawShadow(); // 表示 int calcDistance( int x1, int y1 , int x2 , int y2 ); // 二点の距離を求める int calcAngle( int x1, int y1 , int x2 , int y2 ); // 二点の角度を求める void calcMovePosition( int inX , int inY , int rota , int step ,int *outX , int *outY ); // 基点から角度の移動をした点を取る int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { SetGraphMode( 640 , 480 , 16 ) ; ChangeWindowMode( true ) ; SetMainWindowText( "SwordEffectTest" ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } // 描画先を裏画面にセット SetDrawScreen( DX_SCREEN_BACK ) ; // 剣先リセット GetMousePoint( &g_beforeX , &g_beforeY ); // 鍔先リセット(ダミー) GetMousePoint( &g_beforeBX , &g_beforeBY ); // ループ while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 画面のクリア DrawBox( 0,0,640,480,GetColor(200,200,200),true); // 剣の処理 shadowTrem(); // 表示 drawShadow(); // 裏画面の内容を表画面に反映させる ScreenFlip() ; } // 一応データクリア clearShadow(); DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } // データクリア void clearShadow() { g_shadow.clear(); } // 影処理 void shadowTrem() { int nowX,nowY; int nowBX,nowBY; GetMousePoint( &nowX,&nowY); DrawFormatString( 0,0,GetColor(255,255,255),"Rota:%d",calcAngle( 320 , 240 , nowX , nowY )); // 大雑把に鍔の位置を取る calcMovePosition( 320 , 240, calcAngle( 320 , 240 , nowX , nowY ), (int)( calcDistance( 320 , 240 , nowX , nowY ) * 0.4 ), &nowBX , &nowBY ); // カウンター処理 std::list<SWORDSHADOW>::iterator ite; for( ite = g_shadow.begin() ; ite != g_shadow.end() ; ite++ ) { if( ite->count < SHADOW_COUNT_DEC ) { // カウントが足りないので削除 ite = g_shadow.erase(ite); } else { ite->count -= SHADOW_COUNT_DEC; } } // 追加処理 if( g_shadow.size() >= SHADOW_ALLAY_MAX ) { // もう一杯だから追加しない } else { // 2個△追加。 SWORDSHADOW addShadow; // 1個目 addShadow.baseX = g_beforeBX; addShadow.baseY = g_beforeBY; addShadow.beforeX = g_beforeX; addShadow.beforeY = g_beforeY; addShadow.color = SWORD_COLLOR; addShadow.count = SHADOW_MAXCOUNT; addShadow.nowX = nowX; addShadow.nowY = nowY; g_shadow.push_back( addShadow ); // 2個目 addShadow.baseX = nowX; addShadow.baseY = nowY; addShadow.beforeX = g_beforeBX; addShadow.beforeY = g_beforeBY; addShadow.color = SWORD_COLLOR; addShadow.count = SHADOW_MAXCOUNT; addShadow.nowX = nowBX; addShadow.nowY = nowBY; g_shadow.push_back( addShadow ); } // OLD更新 g_beforeX = nowX; g_beforeY = nowY; g_beforeBX = nowBX; g_beforeBY = nowBY; } // 表示 void drawShadow() { std::list<SWORDSHADOW>::iterator ite; for( ite = g_shadow.begin() ; ite != g_shadow.end() ; ite++ ) { // 半透明設定(生存カウンターで代用) if( ite->count > 255 ) { SetDrawBlendMode( DX_BLENDMODE_ALPHA , 255 ); } else { SetDrawBlendMode( DX_BLENDMODE_ALPHA , ite->count ); } // 表示(三角形) DrawTriangle( ite->baseX , ite->baseY, ite->beforeX,ite->beforeY, ite->nowX , ite->nowY, ite->color , true ); } SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ); } // 二点間の距離を求める int calcDistance(int x1, int y1, int x2, int y2) { return (int)(sqrt(pow((double)(x1 - x2), 2) + pow((double)(y1 - y2), 2))); } // 二点間の角度を求める int calcAngle(int x1, int y1, int x2, int y2) { double angle; int returnAngle; if((x1-x2)==0 && (y1-y2)==0) { angle=0; } else { angle = -CALC_PI/2+(float)atan2(-(double)(y1-y2),(double)(x1-x2)); } // つかいづらいので-90度させる returnAngle = (int)(angle/CALC_PI*180)-90; if( returnAngle < 0 ) { returnAngle += 360; } return returnAngle; } // 座標を向きと移動量で移動させる void calcMovePosition( int inX , int inY ,int rota , int step ,int *outX , int *outY ) { //! RADに直す(本当はRADのままやり取りしたほうがよい) float radRota = (float)(rota * CALC_PI / 180); *outX = (int)(cosf(radRota) * step + inX); *outY = (int)(-sinf(radRota) * step + inY); }
Re: ソウルキャリバーの剣の軌跡 ( No.9 )
名前:とめ 日時:2008/04/15 19:37

かっこよすぎ。参考にさせていただきます

Page: 1 |