ページ 1 / 1
【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月01日(火) 19:05
by moba
WOLFRPGエディターからVC++/Dxlibに乗り換えようとしている者です。
今分からないのは、どうやって複数の処理を同時にこなすかです。
例えば、
・FPS制御、キャラチップの足踏みやマップの描画等を毎フレーム処理しながら
・文章の表示、8フレーム後に画面にエフェクトをかける、など"メイン"のイベントも実行している
このように、"メイン"で実行しているイベントが1フレームで終了しない場合に、
どうやってその他の処理を並列で処理すればいいか分かりません。
仮説を立てたのですが、もし、イベントコマンドの「ウェイト」が入る度に、
イベントの処理位置を覚えておいて、次のフレームでまた戻ってくるなら説明がつきます。
ですがソースを直接書き込むプログラミング部分ではそうもいかないと思います。
よろしければ、複数の処理を同時にこなす方法を教えていただけませんか。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月01日(火) 20:35
by softya(ソフト屋)
そうですね。キャラの移動やアニメや攻撃などのエフェクト、文章もですが、状態を変数に覚えておいて毎フレームその状態を参照しながら次の状態に変化させていきます。
例えば文章なら、どの文字列の何文字目をどの位置に出していると言う情報を覚える変数(構造体)と、ウェイト時間分のカウンタがあればご希望の機能は実現できると思います。
同時に見えますが、1フレーム何ですべての処理をこなせば事実上の同時処理です。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月01日(火) 20:54
by Dixq (管理人)
サンプルプログラムを作ってみました。
コード:
#include "DxLib.h"
class Player1 {
int x, counter;
public:
Player1() { x = 0, counter = 0; }
void update() {
if (counter % 60 == 0) {
x += 60;
}
counter++;
}
void draw() {
DrawCircle(x, 100, 10, GetColor(255, 255, 255), TRUE);
}
};
class Player2 {
int x, counter;
public:
Player2() { x = 0, counter = 0; }
void update() {
x++;
counter++;
}
void draw() {
DrawCircle(x, 200, 10, GetColor(255, 255, 255), TRUE);
}
};
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);
Player1 p1;
Player2 p2;
WaitKey();
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
p1.update();
p2.update();
p1.draw();
p2.draw();
}
DxLib_End();
return 0;
}
実行結果
[youtube]
[/youtube]
このようにカウンタを使えばマルチ処理が可能です。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月03日(木) 01:15
by moba
お二人ともマジ天使ありがとうございます。講座サイトのみならずお世話になります。
まだ分からないので、次の例ならどうするか教えていただけませんか。(これはウディタのコマンド文です。見かけの動きのニュアンスが伝わるといいのですが)
■文章:ある朝、精霊のお告げを聞いた勇者は…
■文章:勇者「そうだ、魔王倒すっべ!」
■動作指定:主人公 / 右 / 右 / 右 / 右 / 右
■動作完了までウェイト
■ウェイト:8 フレーム
■文章:村の復興のため、出稼ぎに出たのでした…
イベントに向かって決定ボタンを押した時に、例えば上のような演出をしたいです。
1つだけの文章の表示なら「文章表示中フラグ」をいじればいいかと思いますが、
1行ずつ順番に処理していく場合、1フレームで全ての状態を操作? するわけにもいかないと思います。
もちろんキャラの足踏みやFPSの制御も動いています。
上記のような演出を行うにはどうすればいいでしょうか。
この例が分かれば応用が利くかと思うのですが。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月03日(木) 17:39
by ISLe
つい先日Visual Studio 2015のUpdate 1が正式リリースされました。
そのリリースノートでアピールされていたC++のコルーチンを使ったコード書いてみました。
#現時点でこの機能は試験的な(experimental)実装です。
► スポイラーを表示
コード:
#include "DxLib.h"
#include <experimental/generator>
class Player1 {
int x, counter;
public:
Player1() { x = 0; }
auto update() {
for (;;) { // 無限ループ
for (counter = 0; counter < 640; ++counter) {
yield counter; // ここで関数を抜ける 次に呼び出されたときは続きから
if (counter % 60 == 0) {
x += 60;
}
}
x = 0;
}
}
void draw() {
DrawCircle(x, 100, 10, GetColor(255, 255, 255), TRUE);
}
};
class Player2 {
int x, counter;
public:
Player2() { x = 0; }
auto update() {
for (;;) { // 無限ループ
for (counter = 0; counter < 640; ++counter) {
yield counter; // ここで関数を抜ける 次に呼び出されたときは続きから
x++;
}
x = 0;
}
}
void draw() {
DrawCircle(x, 200, 10, GetColor(255, 255, 255), TRUE);
}
};
class Fade {
int a, counter;
public:
Fade() { a = 0; }
auto update() {
for (;;) { // 無限ループ
counter = 0;
a = 255;
for (; a > 0; --a) { // フェードインのループ
yield counter++; // ここで関数を抜ける 次に呼び出されたときは続きから
}
for (int i=0; i<(640-256*2); ++i) {
yield counter++; // 関数を抜けたいところに複数配置もOK
}
for (; a < 256; ++a) { // フェードアウトのループ
yield counter++; // 関数を抜けたいところに複数配置もOK
}
}
}
void draw() {
SetDrawBlendMode(DX_BLENDMODE_ALPHA, a);
DrawBox(0, 0, 640, 480, GetColor(0, 0, 0), TRUE);
SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0);
}
};
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
SetDrawScreen(DX_SCREEN_BACK);
Player1 p1;
Player2 p2;
Fade f;
auto p1_update_container = p1.update();
auto p2_update_container = p2.update();
auto f_update_container = f.update();
auto p1_update_iterator = begin(p1_update_container);
auto p2_update_iterator = begin(p2_update_container);
auto f_update_iterator = begin(f_update_container);
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
*p1_update_iterator; ++p1_update_iterator; // イテレータを使った呼び出し
*p2_update_iterator; ++p2_update_iterator;
*f_update_iterator; ++f_update_iterator;
p1.draw();
p2.draw();
f.draw();
}
DxLib_End();
return 0;
}
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月03日(木) 19:12
by moba
> ISLeさん
すみません、どういう文脈で書いてくださったのか分かりません…
そして必須のOSについて書いていなくてごめんなさい。Vistaなので実行できませんでした。
---
ソフト屋さんの日記を読んでいる内に、
イベントの処理をソースコードに直接書くのではなくて、外部ファイルにスクリプト(?)を書く方法を思いつきました。
これなら、1行ずつ順に処理(のための引数)を読み取って、処理が終わるたびに次の行(処理or状態)に移れると気付きました。
これで何でもできるようになるかは分かりませんが、他に思いつかないのでとりあえずこれで行ってみます。
皆さまありがとうございました。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月03日(木) 19:32
by びす
moba さんが書きました:1行ずつ順番に処理していく場合、1フレームで全ての状態を操作? するわけにもいかないと思います。
ウディタは触ったことがありませんが、ほぼ間違いなく、内部的には
実行中イベントの処理
マップの描画処理
FPSの制御処理
といった、mobaさんの挙げた一連の処理を毎フレーム実行しています
たとえば実行中イベントが「ウェイト」の場合の
実行中イベントの処理は
[tab=30]ウェイト時間、処理を停止する
[tab=30]実行中イベントを次のイベント(「ウェイト」の次の行)に変更する
ではなく
[tab=30]ウェイト時間をマイナス1する
[tab=30]ウェイト時間が0だったら、実行中イベントを次のイベント(「ウェイト」の次の行)に変更する
という具合に、毎フレーム実行して問題のない形で処理を作ります
これは、もし前者のように処理した場合、ウェイト中は「マップの描画」や「FPSの制御」が行われなくなってしまうためです
19:38編集 みやすくなったかもしれない
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月03日(木) 19:34
by moba
ぴすさんありがとうございます。
直接(追記:イベントの演出を)ソースコードに書き込んだ場合、「次の行に変更」する方法が思いつかずに困っていました。
毎フレーム回っているもので処理できるように、状態変数?をいじって、毎フレーム状態を見て処理するんですね。
ウディタでは、イベントの座標を直接書き込むとグラフィックが自動でついてきたのですが、あれのことだと分かりました。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月03日(木) 22:23
by softya(ソフト屋)
RPGのイベント自体をC++で書くことは余りありません。スクリプトなどがよくつかわれます。デバック効率やメンテンナンス性が悪いですから。
プログラムで書くのは使い回しが効く物のみです。どっちで書くほうが楽かという話と考えてもらったほうが良いしょう。
RPGの場合、シナリオ、制御スクリプト、演出スクリプトあるいはツール生成データなどなど必要に応じて増えていくものです。
敵データとかもファイル化しないとバランス調整が死にます。
Re: 【マップ&Ev】複数の処理を同時にこなすには[解決]
Posted: 2015年12月04日(金) 07:20
by moba
では、スクリプトでやってみます!
ソフト屋さんありがとうございます。今後も役に立つ考え方も教えていただいて助かりました。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月05日(土) 00:14
by ISLe
moba さんが書きました:> ISLeさん
すみません、どういう文脈で書いてくださったのか分かりません…
そして必須のOSについて書いていなくてごめんなさい。Vistaなので実行できませんでした。
moba さんが書きました:仮説を立てたのですが、もし、イベントコマンドの「ウェイト」が入る度に、
イベントの処理位置を覚えておいて、次のフレームでまた戻ってくるなら説明がつきます。
ですがソースを直接書き込むプログラミング部分ではそうもいかないと思います。
この仮説をそのままかつネイティブに実装できる方法を紹介しました。
いままでの常識は常識でなくなります。
最新であるVisual Studio 2015 Update 1で(/awaitオプションを付け)ないとコンパイルできません。
現時点では試験的なものですが、標準規格として採用を検討されているのでそう遠くない将来ふつうに使えるようになるでしょう。
Visual Studio 2015 Update 1のシステム要件にWindows Vistaは含まれているので、
Visual Studio 2015 Update 1をインストールすれば、Windows Vistaでコンパイルできるし実行することもできるはずです。
Re: 【マップ&Ev】複数の処理を同時にこなすには
Posted: 2015年12月06日(日) 01:08
by moba
>ISLeさん
それは絶対無理だと思っていました(笑) 教えてくださってありがとうございます。
良い方法かどうか僕には判断できないので見送らせていただきますが、いつか使うかもしれませんね。