#include "DxLib.h"
#include "math.h"
const double Pi = 3.14159; //円周率π
double ips= 8.85/pow(10,12.5); //真空の誘電率ε0
double k = 1/(4*Pi*ips); //比例係数k
double e = 1.6/pow(10,7); //電気素量e
char Key[256]; //キー取得
int pros[10], prosn; //処理制限...
int Blue, Red, White, Purple; //各種色
int num, Now_e; //電荷の個数
double x[50][50], y[50][50], r[50][50]; //観測点のx,y座標と観測点までの距離r
double x1, y1, xn[10], yn[10]; //n個目の電荷の位置xn,yn
double Ex[50][50], Ey[50][50]; //重ね合わせた電場Ex,Ey
double Exn[50][50][10], Eyn[50][50][10]; //n個目の電荷の作る電場Exn,Eyn
double e_size[10]; //n個目の電荷量
double magni; //描画倍率
int SelectNum = 0; // 現在の選択番号
int SelectNum_a = 0; //pros[4]の現在選択番号
// メニュー項目の表示に必要な構造体を用意する
typedef struct{
int x, y; // 座標格納用変数
char name[128]; // 項目名格納用変数
} MenuElement_t ;
int gpUpdateKey(); //キー入力更新(コピペ)
void Move_A(int i, int j); //
void Move_B_en(int i, int j, int k); //
void Move_B_ex(int i, int j); //
void Back(int pict); //背景表示
void En(double X, double Y, double e, int num); //
void E(int num); //
double EUnit(int i,int j); //電場を
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
if( ChangeWindowMode(FALSE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
SetDrawScreen( DX_SCREEN_BACK ); //裏画面に設定
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
int i,j,k,l;
// メニュー項目要素を5つ作る
MenuElement_t MenuElement[5]={
{ 80, 100, "電荷の数" }, // タグの中身の順番で格納される。xに80が、yに100が、nameに"ゲームスタート"が
{ 100, 150, "電荷の位置" },
{ 100, 200, "電荷の強さ" },
{ 100, 250, "移動させる電荷" },
{ 100, 300, "設定をデフォルト" },
};
White = GetColor( 255, 255, 255 ); // 白色...
Blue = GetColor( 100, 0, 200 ); // 青色...
Red = GetColor( 200, 0, 100 ); // 赤色...
Purple = GetColor( 255, 0, 255 ); // 紫色...
magni = 10.0;
num = 1;
Now_e = 0;
//各電荷の初期化
for(i=0;i<num;i++){e_size[i]=e;}
//e_size[0] = e;
/*
e_size[1] = -e;
e_size[2] = -e;
e_size[3] = e;
*/
//個数分の電荷の位置初期化
for(i=0;i<num;i++){
xn[i] = 25.5*magni;
yn[i] = 25.5*magni;
}
/*
xn[2] = 25.5*magni;
yn[2] = 10.0*magni;
xn[3] = 40.5*magni;
yn[3] = 10.0*magni;
*/
//各電荷の作る電場初期化
for(l=0;l<num;l++){
for(i=0;i<50;i++){
for(j=0;j<50;j++){
Exn[i][j][l] = 0.0;
Eyn[i][j][l] = 0.0;
}
}
}
//重ね合わせた電場及び観測点との距離初期化
for(i=0;i<50;i++){
for(j=0;j<50;j++){
r[i][j] = 0.0;
Ex[i][j] = 0.0;
Ey[i][j] = 0.0;
}
}
//観測点位置初期化(50×50の観測点)
for(i=0;i<50;i++){
for(j=0;j<50;j++){
x[i][j] = magni*i;
y[i][j] = magni*j;
}
}
//処理制限初期化
for(i=0;i==9;i++){pros[i] = 0;}
prosn = 0;
pros[1] = 1; //処理を段階1へ...
int Back1,Back2,Back3,Back4,Back5;
Back1 = LoadGraph( "coil.png" ); // 画像をロード
Back2 = LoadGraph( "coil-a.png" );
Back3 = LoadGraph( "coil-b.png" );
Back4 = LoadGraph( "coil-c.png" );
Back5 = LoadGraph( "coil-d.png" );
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
while(!ProcessMessage() && !ClearDrawScreen() && gpUpdateKey()==0 && !Key[KEY_INPUT_ESCAPE] ){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されていない
if(pros[0]==1){
DrawString(100,400, "上下左右キーで動くよ!" , White);//文字列表示
for(i=0;i<=num;i++){En(xn[i], yn[i], e_size[i], i);}
E(num);
for(i=0;i<50;i++){
for(j=0;j<50;j++){
DrawLine( 50+(10*i) , (10*j) ,
50+(10*i)+10*Ex[i][j]*EUnit(i,j) ,
(10*j)+10*Ey[i][j]*EUnit(i,j) ,
White , TRUE);
DrawBox(50+(10*i)+10*Ex[i][j]*EUnit(i,j)-1 , (10*j)+10*Ey[i][j]*EUnit(i,j)-1 ,
50+(10*i)+10*Ex[i][j]*EUnit(i,j)+1 , (10*j)+10*Ey[i][j]*EUnit(i,j)+1 ,
Purple,TRUE);
Ex[i][j] = 0.0;
Ey[i][j] = 0.0;
}
}
for(i=0;i<num;i++){
if(e_size[i]>0){DrawCircle(50+xn[i] ,yn[i] ,2 ,Red ,TRUE);}
else{DrawCircle(50+xn[i] ,yn[i] ,2 ,Blue ,TRUE);}
DrawFormatString(60+xn[i], 10+yn[i], White, "電荷%d", i);
}
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ){xn[Now_e] -= 2.0;}
if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ){xn[Now_e] += 2.0;}
if( CheckHitKey( KEY_INPUT_UP ) == 1 ){yn[Now_e] -= 2.0;}
if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ){yn[Now_e] += 2.0;}
Move_A(0,1);
prosn+=1;
}
if(pros[1]==1){
if(SelectNum==0){Back(Back2);}
if(SelectNum==1){Back(Back3);}
if(SelectNum==2){Back(Back4);}
if(SelectNum==3){Back(Back5);}
if(SelectNum==4){Back(Back1);}
// 計算フェーズ
if( Key[ KEY_INPUT_DOWN ] == 1 ){ // 下キーが押された瞬間だけ処理
SelectNum = ( SelectNum + 1 ) % 5; // 現在の選択項目を一つ下にずらす(ループする)
for( int i=0; i<5; i++ ){ // メニュー項目数である5個ループ処理
if( i == SelectNum ){ MenuElement[i].x = 80; }// 選択番号と同じ要素なら
else{ MenuElement[i].x = 100; }// 選択番号以外なら
}
}
if( Key[ KEY_INPUT_UP ] == 1 ){
SelectNum = ( SelectNum + 4 ) % 5;
for( int i=0; i<5; i++ ){ // メニュー項目数である5個ループ処理
if( i == SelectNum ){ MenuElement[i].x = 80; }// 選択番号と同じ要素なら
else { MenuElement[i].x = 100; }// 選択番号以外なら
}
}
// 描画フェーズ
for( int i=0; i<5; i++ ){ // メニュー項目を描画
DrawFormatString( MenuElement[i].x, MenuElement[i].y, GetColor(0,200,150), MenuElement[i].name );
}
Move_A(1,0);
Move_B_en(1,2,0);
Move_B_en(1,3,1);
Move_B_en(1,4,2);
Move_B_en(1,5,3);
prosn+=1;
}
if(pros[2]==1){
Back(Back1);
DrawFormatString( 200, 100, GetColor(200,200,255), "電荷の数:%d",num );
DrawString( 200, 120, "正常動作は電荷9個まで(>_<)", Purple );
if( Key[ KEY_INPUT_DOWN ] == 1 ){ num -= 1; }
if( Key[ KEY_INPUT_UP ] == 1 ){ num += 1; }
if( CheckHitKey( KEY_INPUT_RETURN ) == 1 ){
Move_B_ex(2,1);
for(i=0;i<num;i++){e_size[i]=e;}
for(i=0;i<num;i++){
xn[i] = 25.5*magni;
yn[i] = 25.5*magni;
}
}
prosn+=1;
}
if(pros[3]==1){
Back(Back1);
for(i=0;i<num;i++){
DrawFormatString( 200, 100+i*50, GetColor(200,200,255), "電荷%d x:%f y:%f",i,xn[i]/magni,yn[i]/magni );
}
Move_B_ex(3,1);
prosn+=1;
}
if(pros[4]==1){
Back(Back1);
for(i=0;i<num;i++){
if(SelectNum_a==i){DrawFormatString( 180, 100+i*50, GetColor(200,200,255), "電荷%dの大きさ:%fe",i,e_size[i]/e );}
else{DrawFormatString( 200, 100+i*50, GetColor(200,200,255), "電荷%dの大きさ:%fe",i,e_size[i]/e );}
}
if( Key[ KEY_INPUT_DOWN ] == 1 ){ SelectNum_a = (SelectNum_a + 1)%num; }
if( Key[ KEY_INPUT_UP ] == 1 ){ SelectNum_a = (SelectNum_a + (num-1))%num; }
if( Key[ KEY_INPUT_RIGHT ] == 1 ){ e_size[SelectNum_a] +=e ; }
if( Key[ KEY_INPUT_LEFT ] == 1 ){ e_size[SelectNum_a] -=e ; }
Move_B_ex(4,1);
prosn+=1;
}
if(pros[5]==1){
Back(Back1);
DrawFormatString( 200, 100, GetColor(200,200,255), "動かす電荷→電荷%d",Now_e );
if( Key[ KEY_INPUT_DOWN ] == 1 ){ Now_e = (Now_e+num-1)%num; }
if( Key[ KEY_INPUT_UP ] == 1 ){ Now_e = (Now_e+1)%num; }
Move_B_ex(5,1);
prosn+=1;
}
ScreenFlip();
}
DxLib_End();
return 0;
}
int gpUpdateKey(){
char tmpKey[256]; // 現在のキーの入力状態を格納する
GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
for( int i=0; i<256; i++ ){
if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
Key[i]++; // 加算
} else { // 押されていなければ
Key[i] = 0; // 0にする
}
}
return 0;
}
void Move_A(int i, int j)
{
if(prosn > 1 && Key[ KEY_INPUT_SPACE ] == 1 ){
pros[i]=0;
pros[j]=1;
prosn=0;
}
}
void Move_B_en(int i, int j, int k)
{
if(prosn > 1 && Key[ KEY_INPUT_RETURN ] == 1 && SelectNum==k ){
pros[i]=0;
pros[j]=1;
prosn=0;
}
}
void Move_B_ex(int i, int j)
{
if(prosn > 1 && Key[ KEY_INPUT_RETURN ] == 1 ){
pros[i]=0;
pros[j]=1;
prosn=0;
}
}
void Back(int pict)
{
SetDrawBlendMode( DX_BLENDMODE_ALPHA, 100 ); //ブレンドモードをαに設定
DrawGraph( 0, 0,pict , TRUE );
SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 ); //ブレンドモードをオフ
}
void En(double X, double Y, double e, int num)
{
int i,j;
for(i=0;i<50;i++){
for(j=0;j<50;j++){
r[i][j] = sqrt(pow(X-x[i][j],2)+pow(Y-y[i][j],2));
Exn[i][j][num] = ((k*e)/(r[i][j]*r[i][j]*r[i][j]))*(x[i][j]-X);
Eyn[i][j][num] = ((k*e)/(r[i][j]*r[i][j]*r[i][j]))*(y[i][j]-Y);
}
}
}
void E(int num){
int i,j,k;
for(i=0;i<50;i++){
for(j=0;j<50;j++){
for(k=0;k<num;k++){
Ex[i][j] += Exn[i][j][k];
Ey[i][j] += Eyn[i][j][k];
}
}
}
}
double EUnit(int i,int j){
return 1.0/sqrt(pow(Ex[i][j],2)+pow(Ey[i][j],2));
}