皆様
ご回答頂きありがとうございます。
みけCAT さんが書きました:各団体の所属者に対してまとめて行いたい処理と、所属者の数の最大はだいたいどのくらいですか?
100人程度か、4000人程度か、100000人程度かなどによって処理方法が変わるかもしれません。
各団体の所属者数は最低1人、最大でも60人程度を想定しています。
団体は最低1個、最大で4個までで、それらをまとめる大団体が最低2個、最大4個です。
よって、所属者の総数は最大で1,000名程度ということになります。
また、各団体の所属者に対して以下のような処理を行いたいと考えております。
・団体のリーダー(各団体の一番目に登録された所属者)の後をカルガモのように追随する
もしくは、特定のフォーメーションを構築する
・条件を満たした場合、リーダーと同じアクションを同時に起こす
任意で個別のアクションを起こさせることも出来ればなお良い
・特定条件で脱落者が発生し、それがリーダーの場合は団体が消滅、リーダー以外かつ最後尾ではない所属者が
脱落した場合は、その所属者の後ろにいる者が前に詰める
所属者が途中で増えることはない
団体のうちの一つをプレイヤーが直接制御し、同じ大団体に属する団体はプレイヤーが発する簡単な
命令に従い行動します。
プレイヤーが属さない大団体・団体は自動で行動します。
そのため、各団体のリーダーに対する処理を個別に行うこと、それ以外の所属者は、
自分の一つ前の所属者の情報を参照して処理するように出来なければならないものと思われます。
h2so5 さんが書きました:こんな方法はどうでしょうか。団体の階層はいくらでも深くできます。
本当はスマートポインタを使ったほうがいいですが、VS2008で使えるのかどうか分からないのでCGroupにメモリの管理を任せています。
ソースをご提示いただきありがとうございます。
これを確認したところ、かなり理想に近い挙動を確認できました。
ただ、上記条件を満たさなければならないため、これをどう活用するか悩んでおります。
・大団体・団体・所属者の数はゲーム開始前にセットされたcsvファイルから読み取り、必要数だけ生成する
(csvから読み出す処理は出来ています)
現状だと、自動的に必要な数だけ生成することができない?
・団体のリーダー(その団体に初めて登録された所属者)の識別方法
団体のイテレータがbegin()の際に処理するのではないかとは思いますが、その後に続く所属者が
どのようにして、自分の手前にいる所属者の情報を参照し、受け取るのか
現状では、下記コードのように、団体そのものを引数とする関数に、各団体を直接投げ込むことにより
リーダーとそれに続く所属者の処理を行っております。
現時点ではプレイヤーが直接制御する団体と、背景しか作成しておりませんが、他団体も同じクラスから
インスタンスを生成したいと考えております。
その際には、プレイヤーとそれ以外を識別し、処理を変えるようにする予定です。
コード:
#include "DxLib.h"
#include <math.h>
#include <stdlib.h>
#define PI 3.14159265359
#define CNUM 6
#define BGVMAX 10
#define BGHMAX 10
#define BGWIDTH 640
#define BGLENGTH 480
float extR;
float viewX;
float viewY;
int circleNum;
class CP{
public:
float x,y;
CP(){
x=y=0;
}
};
class CCircle{
public:
float x,y,r,angle,space,spd,diag,width,length,rx,ry,sx,sy;
int color,count,handle[12],frmn,cnum;
float rectAngle[4];
float X[6],Y[6],R;
CP p[4];
CP q[4];
void Init(CCircle A[CNUM], int circleNum, int handle){
A[0].cnum = circleNum;
for(int i=0;i<A[0].cnum;i++){
A[i].color = GetColor(255,30*i,20*i);
A[i].spd = 3;
A[i].r = 16;
A[i].space = 80;
A[i].angle = 0*PI/180;
A[i].x = 320 - i*space*cos(A[i].angle);
A[i].y = 240 - i*space*sin(A[i].angle);
A[i].width = 20 - i;
A[i].length = 50 - i*2;
A[i].diag = atan2( A[i].length, A[i].width) ;
A[i].handle[0] = handle;
A[i].count = 0;
A[i].frmn = 0;
}
}
void calcMove(CCircle A[CNUM]){
int NUMW = BGWIDTH * BGHMAX;
int NUML = BGLENGTH * BGVMAX;
if( A[0].x > NUMW - A[0].r )A[0].x = NUMW - A[0].r;
if( A[0].y > NUML - A[0].r )A[0].y = NUML - A[0].r;
if( A[0].x < A[0].r ) A[0].x = A[0].r;
if( A[0].y < A[0].r ) A[0].y = A[0].r;
viewX=A[0].x-320;
viewY=A[0].y-240;
A[0].rx=A[0].x-viewX;
A[0].ry=A[0].y-viewY;
for(int i=0;i<A[0].cnum;i++){
A[i].rectAngle[0] = PI/2 + A[i].angle;
A[i].rectAngle[1] = 3*PI/2 - 2*A[i].diag + A[i].angle;
A[i].rectAngle[2] = 3*PI/2 + A[i].angle;
A[i].rectAngle[3] = 5*PI/2 - 2*A[i].diag + A[i].angle;
A[i].calcRect();
if( i>0 ){
A[i].spd = A[i-1].spd;
A[i].sx = A[i-1].x - A[i].x;
A[i].sy = A[i-1].y - A[i].y;
A[i].rx = A[i-1].rx - A[i].sx * extR;
A[i].ry = A[i-1].ry - A[i].sy * extR;
}
A[i].count++;
}
A[0].x += A[0].spd * cos(A[0].angle);
A[0].y += A[0].spd * sin(A[0].angle);
if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) A[0].angle += 1*PI/180;
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) A[0].angle -= 1*PI/180;
if( CheckHitKey( KEY_INPUT_UP ) == 1 ) A[0].spd += 0.1;
if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) A[0].spd -= 0.1;
if( CheckHitKey( KEY_INPUT_NUMPAD0 ) == 1 ) A[0].spd = 0;
if( CheckHitKey( KEY_INPUT_NUMPAD1 ) == 1 ) extR = 1;
if( A[0].spd <= 0 ) A[0].spd = 0;
if( CheckHitKey( KEY_INPUT_1 ) == 1 ) A[0].frmn = 0;
if( CheckHitKey( KEY_INPUT_2 ) == 1 ) A[0].frmn = 1;
A[0].calcFormation(A,A[0].frmn);
}
void calcRect(){
for(int i=0;i<4;i++){
p[i].x = x + width/2 * cos(rectAngle[i]) - length/2 * sin(rectAngle[i]);
p[i].y = y + width/2 * sin(rectAngle[i]) + length/2 * cos(rectAngle[i]);
q[i].x = rx + (p[i].x-x) * extR;
q[i].y = ry + (p[i].y-y) * extR;
}
}
//formationNumberは仮のもの、現在はカルガモの動きのみ
void calcFormation(CCircle A[6], int formationNumber){
for(int i=1;i<6;i++){
X[i] = A[i-1].x - A[i].x;
Y[i] = A[i-1].y - A[i].y;
if( A[i].space * A[i].space < X[i]*X[i] + Y[i]*Y[i] ){
A[i].angle = atan2(Y[i],X[i]);
A[i].x += A[i].spd * cos(A[i].angle);
A[i].y += A[i].spd * sin(A[i].angle);
}
}
}
void Draw(CCircle A[6]){
for(int i=0;i<6;i++){
DrawRotaGraphF( A[i].rx, A[i].ry, extR, A[i].angle+PI/2, A[i].handle[0], TRUE, FALSE);
DrawCircle( A[i].rx, A[i].ry, A[i].r/4 * extR, A[i].color, TRUE);
A[i].DrawRect();
}
}
void DrawRect(){
for(int i=0;i<4;i++){
DrawLine( q[i%4].x, q[i%4].y, q[(i+1)%4].x, q[(i+1)%4].y, color);
}
}
};
class CBackGround{
public:
float x,y;
float width,length;
float sx,sy;
float rx,ry;
int handle;
CP p[4];
CP q[4];
void Init(CBackGround bg[BGVMAX][BGHMAX], int bghandle){
for(int i=0;i<BGVMAX;i++){
for(int j=0;j<BGHMAX;j++){
bg[i][j].width = BGWIDTH;
bg[i][j].length = BGLENGTH;
bg[i][j].x = BGWIDTH/2 + BGWIDTH*j;
bg[i][j].y = BGLENGTH/2 + BGLENGTH*i;
bg[i][j].handle = bghandle;
bg[i][j].p[0].x = bg[i][j].x - BGWIDTH/2;
bg[i][j].p[1].x = bg[i][j].x + BGWIDTH/2;
bg[i][j].p[2].x = bg[i][j].x + BGWIDTH/2;
bg[i][j].p[3].x = bg[i][j].x - BGWIDTH/2;
bg[i][j].p[0].y = bg[i][j].y + BGLENGTH/2;
bg[i][j].p[1].y = bg[i][j].y + BGLENGTH/2;
bg[i][j].p[2].y = bg[i][j].y - BGLENGTH/2;
bg[i][j].p[3].y = bg[i][j].y - BGLENGTH/2;
}
}
}
void Calc(CBackGround bg[BGVMAX][BGHMAX], CCircle A[6]){
for(int i=0;i<BGVMAX;i++){
for(int j=0;j<BGHMAX;j++){
bg[i][j].sx = A[0].x - bg[i][j].x;
bg[i][j].sy = A[0].y - bg[i][j].y;
bg[i][j].rx = A[0].rx - bg[i][j].sx * extR;
bg[i][j].ry = A[0].ry - bg[i][j].sy * extR;
bg[i][j].width = BGWIDTH * extR;
bg[i][j].length = BGLENGTH * extR;
bg[i][j].q[0].x = bg[i][j].rx - bg[i][j].width/2;
bg[i][j].q[0].y = bg[i][j].ry - bg[i][j].length/2;
bg[i][j].q[1].x = bg[i][j].rx + bg[i][j].width/2;
bg[i][j].q[1].y = bg[i][j].ry - bg[i][j].length/2;
bg[i][j].q[2].x = bg[i][j].rx + bg[i][j].width/2;
bg[i][j].q[2].y = bg[i][j].ry + bg[i][j].length/2;
bg[i][j].q[3].x = bg[i][j].rx - bg[i][j].width/2;
bg[i][j].q[3].y = bg[i][j].ry + bg[i][j].length/2;
}
}
}
void Draw(CBackGround bg[BGVMAX][BGHMAX]){
for(int i=0;i<BGVMAX;i++){
for(int j=0;j<BGHMAX;j++){
DrawModiGraphF(
bg[i][j].q[0].x, bg[i][j].q[0].y,
bg[i][j].q[1].x, bg[i][j].q[1].y,
bg[i][j].q[2].x, bg[i][j].q[2].y,
bg[i][j].q[3].x, bg[i][j].q[3].y,
bg[i][j].handle, TRUE
);
}
}
}
};
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
extR=1;
circleNum=6;
int bghandle=LoadGraph("dat/bg01.png");//640px*480pxの画像
CBackGround bg[BGVMAX][BGHMAX];
bg[0][0].Init(bg, bghandle);
int handle[12];
LoadDivGraph("dat/0.png",12,4,3,73,73,handle,TRUE);//仮の画像を利用中
CCircle *A;
A = new CCircle[circleNum];
A[0].Init(A, circleNum, handle[0]);
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
extR-=GetMouseWheelRotVolF()*0.01;
if(extR<=0.2)extR=0.2;
A[0].calcMove(A);
bg[0][0].Calc(bg, A);
bg[0][0].Draw(bg);
A[0].Draw(A);
if(CheckHitKey(KEY_INPUT_ESCAPE) == 1)break;
}
DxLib_End(); // DXライブラリ終了処理
return 0;
}
作成中のため色々と見苦しい点が多いとは存じますが、なにかご助言を頂ければ幸いです。
以上、よろしくお願い致します。
(余談ですが、3Dのカメラが使えないので、スクロール処理と拡大縮小処理に苦労しました)