敵が円を描くプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
電気屋

敵が円を描くプログラム

#1

投稿記事 by 電気屋 » 15年前

どうも、たびたびお騒がせをしている電気屋です。
今回は、プログラムを共同作成中の仲間からちょっとした質問です。
マップの表示には、0、1、2とサイトでは役割がありますが、2のところの敵の遭遇を変更して、敵キャラがその”2”を中心にして円を描くように動くプログラムは作れないのか?と言う質問です。何度か挑戦はしているのですが、SINの値の書き方や、その他諸々がまだ勉強中なのでうまく動きません
書き方を教えてください。

自分もとはイベント係だったのでよく分かりません。 画像

たいちう

Re:敵が円を描くプログラム

#2

投稿記事 by たいちう » 15年前

質問が曖昧です。
現在どのようにデータを持っていて、どのように表示しているのかが、
全く判りません。これでは答えようがないのですが、ご理解いただけますよね?

円が難しいならば、直線運動は作れますか?
AからBまで動くプログラムを添付してくれたら、
回答者が前提条件を良く知ることができ、回答しやすいと思います。

直線運動も難しいならば、もっとハードルを下げ、
現在実行できるプログラムを添付してください。

電気屋

Re:敵が円を描くプログラム

#3

投稿記事 by 電気屋 » 15年前

現在、貼り付けたプログラムを実行しています。
1,直線
2,まっすぐ進みしばらく停止し、その後プレイヤーに向かって進み出ししばらくすると戻って行く
3,前進→後退→前進…エンドレス
4、回る
5,プレイヤーに向かう

このプログラムの”4,回る”ところを改良中で、中心点を上記でも書いたように敵に遭遇する”2”に置き換えたいのです。目標はマップ中の”2”のところをぐるぐる回ると作りたいと思っています。

この乗せているプログラムは、参考書(サイトも含む)を参考にしています。まだ、取りかかったばかりで、プログラムを読み切れていません。

最終的には、最初の方から描画しているのではなく、”2”の近くに来るとぐるぐる回ると作りたいとおもっています。

まだ、始めたばかりなのでよろしくお願いします。

kazuoni

Re:敵が円を描くプログラム

#4

投稿記事 by kazuoni » 15年前

管理人さんのプログラムではマップチップでマップを作成しているので、
32*32なのですが、電気屋さんはどの様に管理いているのでしょうか?
たいちうさんのおっしゃるように、「動作するプログラム」を載せるのが、
一番良い回答がもらえるのではないでしょうか。

こっからはエスパーになります。
例えば、32*32と仮定し、
int hantei[15][20] = {
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,2,0,0,0,0,0,0,0,0,2,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,2,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,2,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,2,1,1 },
        { 1,1,1,1,1,0,2,0,0,0,1,0,2,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,2,0,1,1 },
        { 1,1,1,1,1,0,0,2,0,0,0,0,2,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
とし、

hantei[3][6]=2

を対象位置とします。
対象は、

x1=32*6=192 , y1=32*3=96

が左上の頂点となる辺の長さ32の正方形です。
なのでこの中心座標は

x=x1+32/2 , y=y1+32/2

となります。ゆえに、円の中心(x,y)で、半径32/2の円の円周上を回ればよいわけです。
なので、回転する座標(X,Y)は

double rad
X=(32/2)*cos(rad)+x , Y=(32/2)*sin(rad)+y (訂正1/15 18:56)

って感じになるかと。
もし、対象となるマップチップが2であり、
かつ、その位置から9方向のなかに2があったら、円は大きくなりますね。
(そのあたりのアルゴリズムも組み込むのかわかりませんが。) 画像

電気屋

Re:敵が円を描くプログラム

#5

投稿記事 by 電気屋 » 15年前

kazuoniさんありがとうございます。
今、自分が参考にしているサイトはシューティングの館の敵表示のところで、まだまだ勉強中の身です。
まだ、ハッカーさんの書いてくださったプログラムは、真似できそうにありませんでした。(組んでみたのですが、まだ自分に早かったようです。)

はじめから、高望みしたのがいけなかったと思います。なので


int hantei[15][20] = {
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};

このマップの真ん中を画像が円を描く用に動くプログラム作っていきたいと思います。

今,シューティングの館のプログラムを変更して

void EnemyPattern1(int i){ //まっすぐ進む
enemy.x+=sin(PI*(enemy.counter)/160.0f)*1.0f;
enemy.y+=sin(PI*(enemy.counter)/160.0f)*1.0f;

}
//////////////////////////////////////////////
enemy.pattern=1; //どういう軌道を描くか
enemy.flag=1; //出現フラグを立てる
enemy.counter=0;//出現して何カウント目か測るカウンター初期化
enemy.size=0.5f;//敵の大きさ
enemy.range=(MONSTER1_X_SIZE-60)/2.0f*enemy.size;//あたり判定範囲
enemy[i].x=320; //xの初期座標
enemy[i].y=240; //yの初期座標
///////////////////////////////
DrawRotaGraph( (int)enemy[i].x , (int)enemy[i].y , enemy[i].size , 0.0f , image[enemy_img[1]] , TRUE ) ;
/////////////////////////////////
この用に組んでいるのですが、sinのやり方が分からず、変な風に動きます。
アドバイスお願いします。
///////////////////////////////////////////////////////////////////////
またハッカーさんのプログラムを自分なりに読んでみたのですが多分間違っていると思うので訂正をお願いします
hantei[3][6]=
{0,0,0,0,0,0}
{0,0,0,0,0,0}
{0,0,0,0,0,0}
//hanteiの中に2あるかどうか判定する

1マスが32ビットなので
Xマスは6マスなので
X1=32*6=198

Yマスは3マスなので
Y1=32*3=96

その後、そのhanteiの中心を求めるため
X=X1/2
Y=Y1/2

で中心を求める
/////////////////////////////////////////////////////////////////////////
double rad//角度
X=(1マスのXの真ん中)*cos(角度)+x , Y=(1マスのYの真ん中)*sin(角度)+y 画像

たいちう

Re:敵が円を描くプログラム

#6

投稿記事 by たいちう » 15年前

座標系が判らないので適当です。
うまく表示できるように、r, cx, cyを調節してください。
void EnemyPattern4(int i){      //ぐるぐる回る
    if(enemy.counter<100)
        enemy.x-=2.5f;
    if(enemy.counter>=100){
        float r = 2.5f; // 半径
        float cx = 10f; // 中心のX座標
        float cy = 10f; // 中心のY座標
        float theta = PI*(enemy.counter-100.0f)/160.0f;
        enemy.x = cx + r * cos(theta);
        enemy.y = cy - r * sin(theta);
    }
}


直線運動は差分を次々に足すことで計算していますが、
円運動は差分じゃなくて、直接計算した方が簡単で誤差も小さくなります。

またこのプログラムでは、enemy.counter==100で、
運動が連続しないと思います(瞬間移動してしまう)。
連続させることもできますが、まずは回転させてみてください。
それから連続性に取り組み、判らなければ再度尋ねてください。

また差分で書く場合は連続性が保証されるという利点があります。
こちらも説明できますが、まずは回転させてみてください、ということで。

電気屋

Re:敵が円を描くプログラム

#7

投稿記事 by 電気屋 » 15年前

回ることができました。
連続性について教えて貰えますか?
現時点でも、回るのですが連続性がつくとどうなるのですか?
教えてください。 画像

kazuoni

Re:敵が円を描くプログラム

#8

投稿記事 by kazuoni » 15年前

> このマップの真ん中を画像が円を描く用に動くプログラム作っていきたいと思います。

これはおかしいくないですか?
っというのも、電気屋さんの書いたマップデータでは、0と1から構成されているので、
どこを回ったらいいのかはっきりしないと思います。
せめて、回転させたい場所は違う数値のほうがよいかと。

とりあえず、作ってみました。(要DXライブラリ)
管理人さんの紹介していらっしゃる龍神録プログラミングの館の中で用いられている
0.png
を用いているので、ご用意を。

適当に殴り書きしてしまったこともあり、解読はかなりしづらいと思いますが・・・。

とりあえず、

1、マップチップのデータをコピー
2、関数RoteOnMap::GetRoteDataFromMapに1のデータを渡し、繰り返し文でまわしていると、
円を描く場所のデータが返ってくるのでそれを記憶(終了時に要関数RoteOnMap::DeleteRoteData)
3、2のデータを元に、楕円の方程式に代入
4、かなり微妙ですけど、まぁ、らしく回ってます。

解析はしないほうがいいかもです・・・。

重要追記
プログラムの関数GetHitKeyStateAll_2で、
for(int i=0;i<258;++i) ×
for(int i=0;i<256;++i) ○
に訂正を。危ないことしてました・・・ 画像

電気屋

Re:敵が円を描くプログラム

#9

投稿記事 by 電気屋 » 15年前

kazuoniさんありがとうございます
自分なりにkazuoniさんのプログラムを解読中です。あっているか確認してください。
(1文ずつ乗せます。1つ1つ覚えたいので。)
#include "DxLib.h"
#include <math.h>

const double PI = 3.1415926535898; //円周率
const int ClientWidth = 640;    //画面幅(X)
const int ClientHeight = 480; //画面幅(Y)
const int CellSize = 32; //1マスの大きさ

//////////////////////////////////////////////////////////////
//構造体(円を描く)
/////////////////////////////////////////////////////////////
namespace
{
typedef struct
{
float cx,cy;
float a,b;
float theta;
float speed; // degree / loop
} RoteData;
//////////////////////////////////////////////////////////////
//画面の設定
/////////////////////////////////////////////////////////////
const int WidthNum = ClientWidth/CellSize; //640
const int HeightNum = ClientHeight/CellSize; //480
/////////////////////////////////////////////////////////////
//設定
/////////////////////////////////////////////////////////////
const int Color[/url] = { 0x00ff00 , 0xffffff };  //マップカラー
const int RoteNum = 2;
const int CheckedNum = 3;
//////////////////////////////////////////////////////////////
//マップ(640*480)
/////////////////////////////////////////////////////////////
const int hantei[HeightNum][WidthNum] = {
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,1 },
{ 1,1,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
{ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
////////////////////////////////////////////////////////////////
//キーの取得
////////////////////////////////////////////////////////////////
int GetHitKeyStateAll_2(int KeyStateBuf[/url])
{
char GetHitKeyStateAll_Key[256];
GetHitKeyStateAll( GetHitKeyStateAll_Key );
for(int i=0;i<256;++i)
{
if(GetHitKeyStateAll_Key==1)
++KeyStateBuf;//キーを取得したらKeyStateBufに+1
else
KeyStateBuf=0;キーを取得しなかったらKeyStateBufに0
}
return 0;
}
//////////////////////////////////////////////////////////////////
float GetRadianFromDegree(float deg)
{
return (float)PI*deg/180.0f;//degの値を返す
}
} 

電気屋

Re:敵が円を描くプログラム

#10

投稿記事 by 電気屋 » 15年前

質問なのですが、kazuoni からいただいたプログラムを実行して、終了させた後にメッセージBOXで
/////////////////////////////////////////////////////////////////////////
データ実行防止
コンピュータ保護のため、このプログラムはWindowsにより終了しました。

名前: DxLid
/////////////////////////////////////////////////////////////////////////
とでたのですが、何なのでしょうか?

電気屋

Re:敵が円を描くプログラム

#11

投稿記事 by 電気屋 » 15年前

kazuoniさんから頂いたプログラムは自分にはまだハードルが高かった用です。解読しようとはしているのですが。どうもサンプル文の用にはいきません。


なので、たいちうさんのプログラムを変更して
////////////////////////////////////////////////
//たいちうさんのプログラム
////////////////////////////////////////////////
if(enemy.counter<100)
enemy.x-=2.5f;
if(enemy.counter>=100){
float r = 10; // 半径
float cx = 320; // 中心のX座標
float cy = 240; // 中心のY座標
float theta = PI*(enemy.counter-100.0f)/160.0f;
enemy.x = cx + r * cos(theta);
enemy.y = cy - r * sin(theta);
}
////////////////////////////////////////////////
とおいていますが、これだとcyが240と決まっているので瞬間移動してしまいます。(y座標がランダムなので)
なのでyの値が変わったら、cyの値も変わるにはどうすればいいですか?お願いします。 画像

たいちう

Re:敵が円を描くプログラム

#12

投稿記事 by たいちう » 15年前

enemyの型が判らないけど、例えばこんな感じで。
struct Enemy {
    // これを追加する
    float cx;
    float cy;
};

void EnemyPattern4(int i){      //ぐるぐる回る
    float r = 2.5f; // 半径
    if(enemy.counter<100)
        enemy.x-=2.5f;
    if (enemy.counter==100) {
        enemy.cx = enemy.x - r;
        enemy.cy = enemy.y;
    }
    if(enemy.counter>=100){
        float theta = PI*(enemy.counter-100.0f)/160.0f;
        enemy[i].x = enemy[i].cx + r * cos(theta);
        enemy[i].y = enemy[i].cy - r * sin(theta);
    }
}


三角関数等の使い方を自分で理解しないと全部質問することになりますよ。

電気屋

Re:敵が円を描くプログラム

#13

投稿記事 by 電気屋 » 15年前

ありがとうございます。確かに全部聞く事になりそうなので、サイトのどこの部分を勉強すればいいのか教えてください。そしたら復習もできますし、一通り自分でも考えられるので。
お願いします。

たいちう

Re:敵が円を描くプログラム

#14

投稿記事 by たいちう » 15年前

> サイトのどこの部分

このサイトのことですか?
どこかに書いてあるかどうかも知りません。
三角関数を理解するためには、高校の数学の教科書が一番だと思います。

電気屋

Re:敵が円を描くプログラム

#15

投稿記事 by 電気屋 » 15年前

わかりました。勉強してがんばってみたいと思います。少しの間、勉強して、三角関数を理解してらまた来たいと思います。 画像

電気屋

Re:敵が円を描くプログラム

#16

投稿記事 by 電気屋 » 15年前

自学でどうにか理解することができるようになりました。ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る