STGの敵のスクリプトコードについて

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

STGの敵のスクリプトコードについて

#1

投稿記事 by KEYONN_ » 15年前

どうも、こんばんは、TKOZです。
STGゲームを作っていて、敵のスクリプトをプログラムソース内に作ってみたのは、いいんですが、
うまく動かないです。
具体的には、敵が前のソースではたくさん出てきたのに、今回はあまり出てこないし、
出てきたは良いんですが、スクリプトどおりに動かないです。

構造体配列の添え字が関係していると思うのですが、特にIF文が怪しい気がします。

enum Scr{UP,DOWN,LEFT,RIGHT,RIGHTROTATE,LEFTROTATE,STOP,RESET,IF,SINMOVE,SHOT,
RIGHTMOVEROTATE,LEFTMOVEROTATE};

typedef struct Script_{
int time;//タイム(プログラムカウンタみたいなもの?)
int Instraction;//命令文
int Oprand;//引数
}Script_;



typedef struct Enemy_{
float x;
float y;
float Speed;
int Kind;//敵番号
int Hp;//体力
int width;
int height;
int Flag;//表示フラグ
float MoveAngle;//移動角度
int DrawAngle;//表示角度
}Enemy_;
#define MAX_ENEMY 100
#define MAX_SCRIPT 2


void ExecuteScript(int i,int ScriptNumber)
{
Script_ SCRIPT[MAX_SCRIPT][20]={
{
{0,IF,(Enemy.x-J.x<10) && (J.x-Enemy.x<10)},
{1,DOWN,2},
{2,DOWN,2},
{3,RESET,0},
{4,RESET,0},
{5,RESET,0},
{6,RESET,0},
{7,RESET,0},
{8,RESET,0},
{9,RESET,0},
{10,RESET,0},
{11,RESET,0},
{12,RESET,0},
{13,RESET,0},
{14,RESET,0},
{15,RESET,0},
{16,RESET,0},
{17,RESET,0},
{18,RESET,0},
{19,RESET,0}
},

{
{0,IF,(Enemy.x>J.x)},
{1,LEFTMOVEROTATE,2},
{2,IF,(Enemy.x>J.x)},
{3,LEFTROTATE,2},
{4,IF,(Enemy.x<J.x)},
{5,RIGHTMOVEROTATE,2},
{6,IF,(Enemy.x<J.x)},
{7,RIGHTROTATE,2},
{8,DOWN,2},
{9,RESET,0},
{10,RESET,0},
{11,RESET,0},
{12,RESET,0},
{13,RESET,0},
{14,RESET,0},
{15,RESET,0},
{16,RESET,0},
{17,RESET,0},
{18,RESET,0},
{19,RESET,0}
}
};
static int time[MAX_SCRIPT]={0};
static int time2[MAX_SCRIPT]={0};
static int Operand[MAX_SCRIPT]={0};
static int Instraction[MAX_SCRIPT]={0};
static int flag=0;

if(flag==0)
{
for(i=0;i<MAX_SCRIPT;i++)
time=timeGetTime();
flag=1;
}

for(int j=0;j<MAX_SCRIPT;j++)
{
if(timeGetTime()-time[j]>SCRIPT[time2[j]].time)
{
time[j]=timeGetTime();
time2[j]++;
switch(SCRIPT[time2[j]].Instraction)
{
back:;
case DOWN:
Enemy.y+=SCRIPT[i][time2[j]].Oprand;
break;
case RESET:
time2[j]=0;
break;
case RIGHTROTATE:
Enemy[i].DrawAngle-=SCRIPT[i][time2[j]].Oprand;
break;
case LEFTROTATE:
Enemy[i].DrawAngle+=SCRIPT[i][time2[j]].Oprand;
break;
case RIGHTMOVEROTATE:
Enemy[i].MoveAngle-=SCRIPT[i][time2[j]].Oprand;
break;
case LEFTMOVEROTATE:
Enemy[i].MoveAngle+=SCRIPT[i][time2[j]].Oprand;
break;
case IF:
if(SCRIPT[i][time2[j]].Oprand)
{
SCRIPT[i][time2[j]].Instraction=SCRIPT[i][time2[j]+1].Instraction ;
goto back;
}else{
time2[j]++;
}
break;
}
}
}
}

とし、
関数MoveEnemyにて


void MoveEnemy(void)
{
int i;
static int diff;

for(i=0;i<100;i++)
{
if(Enemy[i].Flag==1)
{
ExecuteScript(i,Enemy[i].Kind );
switch(Enemy[i].Kind)
{
case 1:
/*
if( (Enemy[i].x-J.x<10) && (J.x-Enemy[i].x<10) ) Enemy[i].y+=2;
Enemy[i].y+=2;
*/
break;

case 2:

break;
case 3:

break;
}

if(Enemy[i].x<0 || Enemy[i].x+32>16*25 || Enemy[i].y>320 || Enemy[i].y<-72)
{
Enemy[i].Flag = 0;
}
}
}
}

ookami

Re:STGの敵のスクリプトコードについて

#2

投稿記事 by ookami » 15年前

「うまく動く」について、もうちょっと詳しくお願いします。

160行ものソースにコメントがほとんど無かったので、ソースは読めていませんが、「敵が前のソースではたくさん出てきたのに、今回はあまり出てこない」というのは、スクリプトとは関係ないのではないでしょうか?

KEYONN_

Re:STGの敵のスクリプトコードについて

#3

投稿記事 by KEYONN_ » 15年前

ネットカフェから書き込みです。
うまく動かないというのは、例えば、
上の例で言うと、
Script_ SCRIPT[MAX_SCRIPT][20]={
{
{0,IF,(Enemy.x-J.x<10) && (J.x-Enemy.x<10)}, //自機とのx座標の差が10ピクセル未満なら
{1,DOWN,2}, //2ピクセル下降する
//以下、IF文は引数が合致していればそのすぐ下の行を実行し、
//条件が合ってなければ一行飛ばす
{2,DOWN,2}, //2ピクセル下降する
{3,RESET,0}, //以下リセット
{4,RESET,0},
{5,RESET,0},
{6,RESET,0},
{7,RESET,0},
{8,RESET,0},
{9,RESET,0},
{10,RESET,0},
{11,RESET,0},
{12,RESET,0},
{13,RESET,0},
{14,RESET,0},
{15,RESET,0},
{16,RESET,0},
{17,RESET,0},
{18,RESET,0},
{19,RESET,0}
},

{
{0,IF,(Enemy.x>J.x)}, //自機より敵のx座標が大きければ
{1,LEFTMOVEROTATE,2}, //移動角度を2°左に回転させる
{2,IF,(Enemy.x>J.x)}, //自機より敵のx座標が大きければ
{3,LEFTROTATE,2}, //描画角度を2°左に回転させる
{4,IF,(Enemy.x<J.x)}, //自機の方がx座標が大きければ
{5,RIGHTMOVEROTATE,2}, //移動角度を2°右に回転させる
{6,IF,(Enemy.x<J.x)}, //自機の方がx座標が大きければ
{7,RIGHTROTATE,2}, //描画角度を2°右に回転させる
{8,DOWN,2}, //無条件で2ピクセル下降する
{9,RESET,0}, //以下リセット
{10,RESET,0},
{11,RESET,0},
{12,RESET,0},
{13,RESET,0},
{14,RESET,0},
{15,RESET,0},
{16,RESET,0},
{17,RESET,0},
{18,RESET,0},
{19,RESET,0}
}
};

この様な動きを再現したかったのですが、うまくいきません。

たいちう

Re:STGの敵のスクリプトコードについて

#4

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

> 構造体配列の添え字が関係していると思うのですが、
> 特にIF文が怪しい気がします。

InstractionがIFの場合には、
if文の条件としてOprandの評価をしたいのですね。
C/C++ではできません。

ここではパターン毎に関数を作ってますね。
http://dixq.net/rp/12.html

敵の動きをスクリプトにまとめたい、
という気持ちは判りますので、
今週末にでも何か方法を考えてみたいと思います。
実用的な方法を考え出せるとは限りませんけど。

たいちう

Re:STGの敵のスクリプトコードについて

#5

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

マクロを使ってみた。役に立つかな?
#include <iostream>

using namespace std;

struct Enemy_ {
    float  x;
    float  y;
    float  MoveAngle;
} Enemy[10];

struct Jiki {
    float  x;
    float  y;
} J;

#define LEFTROTATE(X)  Enemy.MoveAngle += X
#define RIGHTROTATE(X) Enemy.MoveAngle -= X
#define DOWN(X)        Enemy.y += X

#define MAKE_PATTERN_BEGIN(PATTERN_NAME) void PATTERN_NAME(int i) { if (false) {
#define CASE(X, Y)                       } if (X) { Y;
#define DEFAULT(Y)                       } else { Y; }
#define MAKE_PATTERN_END                 }

MAKE_PATTERN_BEGIN(enemy_pattern0)
    CASE(Enemy.x>J.x, LEFTROTATE(2))
    CASE(Enemy.x<J.x, RIGHTROTATE(2))
    DEFAULT(DOWN(2))
MAKE_PATTERN_END

int main() {
    cout << "x, y, MoveAngle : " << Enemy[0].x << ", " << Enemy[0].y << ", " << Enemy[0].MoveAngle << endl;
    J.x = 5;
    enemy_pattern0(0);
    cout << "x, y, MoveAngle : " << Enemy[0].x << ", " << Enemy[0].y << ", " << Enemy[0].MoveAngle << endl;
    J.x = 0;
    enemy_pattern0(0);
    cout << "x, y, MoveAngle : " << Enemy[0].x << ", " << Enemy[0].y << ", " << Enemy[0].MoveAngle << endl;

    return 0;
}

KEYONN_

Re:STGの敵のスクリプトコードについて

#6

投稿記事 by KEYONN_ » 15年前

たいちうさん

ありがとうございます。
解決しました。

それにしてもマクロってこんな使い方も出来るんですね。便利です。

閉鎖

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