冗長で帯版。
ソースの汚さはとツッコミどころは
見逃してください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);
}