Delphi初心者です。ゲームを制作中なのですが、相談に乗って頂けますでしょうか。
プログラムの骨格は、演算→描画の繰り返しなんですが、演算結果を次々と描画ルーチンに渡すと、描画が間に合わなくなったときに破綻してしまいます。
(描画で使っているコンポーネントがクラッシュしてしまう)
そこで、演算部で表示させるものを計算しキューに追加していき、CPUのアイドル時間を見つけてはキューから順次取り出して描画、という方法を試したいと思います。
(オーバーフローしたら破棄する)

そこで、スタックとかキューを使ったことがないのですが、単純に配列を使って、
1.データを最後尾に加える
2.データを先頭から出し、順次前に詰める
簡単な方法があったら教えて頂きたいと思います。
(それくらい手動でやれと言われそうですね(^_^;)
よろしくお願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

補足です。



上記ではちょっと説明が足りないようなのでかってに補足させてもらいます
実際のバッファリング処理では

演算の結果
↓ 描画(描画用のスレッドにてバッファに書き込み)
更新タイミング *作成者指定
↓ 転送(描画部分のスレッドと同期してる状態が前提)
画面更新

以上のプロセスを経て表示が行なわれます。
これが基本的なバッファリング描画です

トリプルバッファリングはこの描画用のバッファが2つになり交互に描画を行なうわけです。
ただ、交互に行なうのでは意味が無いので一部特殊な処理がありますが :-)

前提
演算の結果を描画する場合に転送待ち、描画中のバッファで利用できるバッファが無い時はその回の描画処理をキャンセルする。

演算の結果
↓ 描画(描画用のスレッドにてバッファに書き込み)
更新タイミング ※画面のリフレッシュレートに併せたかたち
↓ 転送(描画部分のスレッドと同期 ※描画が完了してなければ行なわない。
↓    この時点で後からの描画処理が完了してるようであればそちらを表示する
↓    後からの描画処理が完了した時点で前のバッファの内容を破棄し描画処理を行なえるように処理)
画面更新

描画、転送用のバッファを切り替え

大体こんな感じです
ダブルバッファリングですと描画転送が完了してからでないと描画処理が新たに行なえないので物によっては大幅に描画速度が低下します。(フレーム落ちが出ます)
トリプルバッファリングですと、描画中に再度描画処理が行なえますのでマシンのパフォーマンスを最大限に発揮できますが、マシンスペックが極端に低いと速度低下が激しくなります。
    • good
    • 0
この回答へのお礼

詳細なご説明、ありがとうございます。簡単そうで実は奥が深いんですね。ゲームプログラミングの専門書で勉強してみたいと思います。まずは簡単なものから始めて、自在にバッファを操れるようになりたいです(自作モノの改良はそれから^^;)。ありがとうございました。

お礼日時:2001/12/28 15:34

こんにちは、honiyonです。



 Delphiでしたら、DelphiXを使うと簡単ですよ。

 さて、それはさておきキューの実現方法ですが、TStringListクラスはご存じですか?簡単に説明すると、リストボックスみたいに文字列を「リスト」にして保存しておく事の出来るクラスです。(詳しくはヘルプを参照してください)
 データが文字列の場合はこれを使えば良いですが、そうでない時は TStringListの抽象クラスにあたる TListをオーバーライドして使えばそんな事も簡単に実現出来ちゃいます。(TListはデータのポインタを保持します)

 で、実際の使い方は、 List.Add(Data); で追加して、取り出し時は Data := List[0]; List.Delete(0); こんな感じです。

 参考になれば幸いです(..
 
    • good
    • 0
この回答へのお礼

なるほど、とても参考になりました。初心者なもので、いまいち直接目に見えないクラスは苦手なもので・・・いろいろと試してみます。ありがとうございました。

お礼日時:2001/12/28 15:31

動きの激しいゲームをコンポーネントだけで作るのはちょっと厳しいかと思いますが…。

(^^;
動きの激しいゲームでは以下のようにしているのが普通です。

画面描画用のワークメモリに描画する。
ワークメモリの内容をBITMAPとして画面に一括転送。(WindowsAPIで言えばBitBlt)

いわゆるダブルバッファという方法ですが、これだと画面のちらつきが抑えられます。
また画面描画メモリを2つ使用するトリプルバッファという方法もあります。
これは、

1.画面描画用のワークメモリAに描画する。
2.ワークメモリAの内容をBITMAPとして画面に一括転送。
3.画面描画用のワークメモリBに描画する。
4.ワークメモリBの内容をBITMAPとして画面に一括転送。

の繰り返しです。(実際には2と4は1、3終了後に非同期で行うのが普通)
これですと、1が間に合わなければ、次に描画するタイミングでは3を行うので、ワークメモリAやBの処理量は半分で済むことになります。

描画コンポーネントで実現するのであれば、ワーク用に2つ、実際の表示用に1つ作成して、上記のようなトリプルバッファ方式を使えば少しはマシになるかと思います。
でも、出来るかどうかわかりませんが…。(汗
    • good
    • 0
この回答へのお礼

単純な描画でそんなに動きは激しくないので、コンポーネントでやっています。自分でバッファリングするほど技量もないもので・・・。(^^;
描画メモリを確保して転送しながらというのは、いつかやってみたいです。もし参考になるページや書籍等ありましたら、教えていただければ幸いです。
もう少し頑張ってみます。ありがとうございました。

お礼日時:2001/12/27 20:48

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC# 再帰よるスタックオーバーフローについて

VB2008 C# でプログラムしていますが、
プログラムで再帰を多く行わなくてはならず、
スタックオーバーフローが出てしまいます。

スタックオーバーフローを解決するためには、アルゴリズムを変更し、
再帰の回数を減らすしか方法はないのでしょうか?

もしスタックの上限を変更する方法などがありましたら教えてください。

VBは初心者なので、なるべく簡単にお願いします。

Aベストアンサー

プロでもなく、C#の経験もないので、私の出る幕ではないと思いましたが、似たような質問をされた方がいらっしゃるようです。もしかしたら参考になるかもしれません。
http://oshiete1.goo.ne.jp/qa2438590.html

アマチュアの私には、アルゴリズムを変えるか、引数や局所変数を減らす、ぐらいしか思いつきません。C#ではstructは値型なんですか?そうすると、局所変数でstructを使うとスタックを多量に使うかもしれませんね(C#の内部を知らないので断言できませんが)。

QC#の演算でオーバーフローしてるみたいなのですが....

C#の演算でオーバーフローしてるみたいなのですが....

8行8列の逆行列を計算するために
C#で逆行列を掃き出し法を使って計算するプログラムを作ったんですが,どうやら,途中でオーバーフローしているみたいで困っています.
行列の各成分はdouble型で保持しています.


今まで,オーバーフローするような桁数の計算を
プログラムで扱ったことがないので,対策方法がわかりません.
みなさんは,オーバーフローにはどのような対策をしているのでしょうか?


どなたか,知恵を貸していただけないでしょうか?
よろしくお願いします.

Aベストアンサー

演算でオーバーフローになるのは、0に限りなく近い値で除算している場合がほとんどです。

例えば、
1-0.1×10
の計算をしたとき、0になるとは限りません。
処理系によっては、0ではなく、10^(-50)のようなの0に限りなく近い値になる場合があります。
それで除算をするとオーバーフローすることがあります。

対策としては、
0に限りなく近い値は0にする
という処理をします。

(0除算のチェックは当然していますよね)

Q四則演算と比較演算を行う式を定義する生成規則

一桁の数値と四則演算だけを記述できる簡単な文法
の生成規則

expr -> expr + term | expr - term | term
term -> term * factor | term / factor | factor
factor -> 0 | 1 | ... | 9 | (factor)

に、関係演算子 > と < を追加したとき、
どのような生成規則になりますか?

型という観点から考えると、bool型という概念が
新たに追加されることになり、2つの関係演算子は、
bool型同士の計算はできません。
ここの、bool型同士の計算ができない、という点が、
生成規則に反映されるのか、また、
bool型同士も計算できるような生成規則を作成し、
型検査は別に行うべきなのか、
そこのところが知りたいです。

よろしくお願いします。

Aベストアンサー

一日たって読み返すと自分の書いたこと最悪ですね。

まず、
>ただし、もう一階層うえに
>rel-exp2: rel-exp |
>rel-exp < rel-exp |
>rel-exp > rel-exp
>のようなものが必要になる(そうしないと自由度が低い)かと思います。
は、自分でも何を言っているのかわかりません;;
第一、書いたことと矛盾していますね。

「<」と「>」は真理値との演算できないので、「rel-exp」と「rel-exp」の比較できないですもんね。
ま、or演算やand演算の事指していたと思ってください・・・。(逃げです;;)
混乱させて申し訳ありません。

適当に書いていると恥ずかしい思いしますねぇ^^;

回答に対する補足の説明は大筋liar_adanさんと同じ考えです。
liar_adanさん、すごいですねぇ。

ただ、大体おわかりのことかと思いますが、
言語は、扱えるデータ、およびその構造とそれを操るための文法により構成されており、
どのようなデータ構造を扱わせるか、
またそれらデータ構造に対しどのような操作を行うかは、
全てポリシーにより決定されるかと思います。
そこから、実現の仕方の違いは、単純なポリシーの違いと捕らえてよいのではないでしょうか。

C言語の場合、メモリを直接操作することが主となる
(「基本的にどれも「値」」と書かれている主な理由になるかと思います)のに対し、
Javaの場合、元となる言語がインタプリタ上での動作であり、
純粋にデータ構造を操作することが主となる
(実行効率のためにプリミティブな型がベースにありますが)、
という言語の目的の違いもあるかとは思います。
これもまぁ、ポリシーですけどね。


あと、蛇足ですが、
liar_adanさんも解って書いてらっしゃると思いますが、
生成規則では型チェックは出来ません。
あくまで、型チェックは
「字句解析->構文解析->意味解析」
の意味解析の段階で行われるものです。

たとえば、日本語の文法でも、
「人間は猫である」という文は文法上はおかしくないですよね。

ただし、在るひとつの文法に出現する方に縛りをかけることは可能であり、
それにより、一部の型チェックを省くことは出来るかと思います。
「生成規則に型チェックを任せる」
というのはそういうことを言いたいのだと思います。

今回のお題を例にとれば、日本語で真理値のTRUEと数字を比較する際、
「1はTRUEよりも大きい」とする事も文法上は可能ですが、
「数字は数字同士でなければ比較できない」という縛りをかけることで、
「1はTRUEより・・・」とした時、数字とほかのものを比較することになり、
先ほどの縛りのため、出来なくなります。

Harryさんのお書きになった、
rel_expr -> fund_expr < fund_expr |
       fund_expr > fund_expr
なども、その一例だと思います。

厳密には「数字」の意味がわからなければいけず、
かりにTRUEを数字のひとつとした場合は、可能になってしまいますが。

「型検査は別に行うべきなのか」から、ご理解されているとは思いますが、
念のためと、これを読むほかの方のためにも・・・って、読む人いるのか疑問が。

こんなことを書くのは、自分のおさらいのためだったりします^^

そうそう、一番初めの問いに対する回答って出てないんですね。
個人的な意見としては、きれいな実装を望まれるようであれば、
意味解析が必要になりますが、
「bool型同士も計算できるような生成規則を作成」を選ばれたらよいのでは、と思います。
ただ、扱う演算が現状四則演算のみであり、
そのような実装を求められているわけでもないかと思いますので、
現実解としては
「bool型同士の計算ができないという点が生成規則に反映される」形でよいのでは。

一日たって読み返すと自分の書いたこと最悪ですね。

まず、
>ただし、もう一階層うえに
>rel-exp2: rel-exp |
>rel-exp < rel-exp |
>rel-exp > rel-exp
>のようなものが必要になる(そうしないと自由度が低い)かと思います。
は、自分でも何を言っているのかわかりません;;
第一、書いたことと矛盾していますね。

「<」と「>」は真理値との演算できないので、「rel-exp」と「rel-exp」の比較できないですもんね。
ま、or演算やand演算の事指していたと思ってください・・・。(逃げです;;)
混乱...続きを読む

QMaximaの順次出力

Basic言語などで、例えば10までの整数の和を求めるとき、
for i=1 to 10
a=a+i
print i
next i
とでもすれば、iが1まで、2まで、3まで…10までの計算結果が得られますよね。ところが、Maximaの場合は、for函数の中に出力命令は入れられないようなんですが?これは、仕方のないことなのでしょうか?
それぞれの計算結果は、配列に覚えこませてやるよりないのでしょうか。やろうとしていることは、複雑な式の展開なので、できるだけこの方法は避けたいのですが。

Aベストアンサー

本当は、

print a

ってやりたいのかな?ちょっと良く分かりませんが。

Maxima自体は本体はCommon Lispと言う「超」高級言語で、「やりたいこと」はほぼ可能だと思います。to_lisp();と言うコマンドでMaximaはCommon Lispモードへと変化します。

(%i1) to_lisp();

Type (to-maxima) to restart, ($quit) to quit Maxima.

MAXIMA> (do ((i 1 (1+ i))
(a 0 (+ a i)))
((> i 10))
(format t "~d~%" a))
0
1
3
6
10
15
21
28
36
45
NIL
MAXIMA>

多分こう言う事やりたいんじゃないですかね?

Qオーバーフローについて教えてください。

複数のIT用語辞典で調べるとオーバーフローとはデータ型が扱える範囲の上限を超えてしまうこととありました。
とするとint型の場合 32,767を超えることはオーバーフローと言うのでしょうけど、–32,768を下回ることはなんと言うのでしょうか?

Aベストアンサー

IT用語も、常に同じ意味で使われるとは限りません。

上に溢れる「オーバーフロー」と、下に溢れる「アンダーフロー」です。
この上下の基準が変われば、値の変わります。

整数の場合
最大値から最小値までが「上下」と考えれば、最小値より小さくなってしまうのは「アンダーフロー」です。
精度で考えれば、負の最小値(絶対値が最大)より小さくなることは、取り得る値を越えてしまうので「オーバーフロー」です(特に「負のオーバーフロー」といったりします)。「アンダーフロー」は最小精度の1より小さくなってしまうことです。


検索でいくつかの「IT用語」を見てみましたが、「解説」と言えるほど詳しくは書いてないように思えました。
大体の意味を掴んだら、より詳しい解説をしているサイトとか本とかで調べなおすのがいいかと思います。


人気Q&Aランキング

おすすめ情報