超小型記号言語による数値計算とゲーム

 はじめての方は「続編のごあいさつ」からご覧ください。(新しい記事順に並べています)

目次
------------------------------------------------------------

第2回 z=f(x,y)のグラフ/プログラミング前編

第1回 z=f(x,y)のグラフ/準備編
タイトル変更のごあいさつ
続編のごあいさつ
------------------------------------------------------------

■第2回 z=f(x,y)のグラフ/プログラミング前編(2018/12/24掲載
,2019/01/03最終変更)
 ※この回(第2回)は
全面改訂しました。(2019/01/02)

 前回
(第1回)は、関数z=f(x,y)のグラフを表示する仕組みについて説明しました。
 理屈としてはこれですべてなのですが、グラフィックライブラリのない超小型記号言語でこれを実現しようとすると、実はそう簡単にはいきません。
 今回は、具体的な仕様と設計過程を説明しながら、実はそう簡単にはいかない諸問題の解決方法を示してゆくことにします。

手順1】画面設計
 曲面z=f(x,y)は、縦(x軸)×横(y軸)×高さ(z軸)=100×100×100の立方体の範囲で変化させることにします。
 パソコン画面には、この曲面を左斜め上(じゃなくて、
斜め上でした)から見下ろした時の見え方を、縦(S軸)×横(T軸)=50×100の長方形内に表示させます。
 なお、前回は
画面上の座標を大文字で(X,Y)としていましたが、3次元空間内での座標(x,y,z)と混同しないよう、今回から(S,T)とすることにします。
 以上を図2-1に示します。
   
    図2-1

 
【手順2】3D⇒2D変換式
図2-1より、3次元空間内の任意の点(x,y,z)は、パソコン画面上の点(S,T)としては

 S = +0.7x -f(x,y)
 T = +y -0.7x

となります。
 前回は、この式のx係数は0.5だったはずですが、実際に0.5でプログラミングすると理屈通りのグラフとならず、最終的に0.7に変更しました。
 0.7の根拠は図2-1でx軸とy軸との関係が直角二等辺三角形の長辺と短辺の関係(
1.41:1)にあり、そのおおまかな補正(1.41×0.7=0.987)ということで納得ください。
 
正直なところ私自身半信半疑で、xの係数が1未満なら0.5でも0.7でも何だって良いような気がするのですが、0.5だとうまくいかないので仕方ありません。

 ところで先程の式は
原理的な式であって2次元座標と3次元座標の原点位置の差と、各座標の変動範囲を考慮してスケーリングを行うと
 S = (+0.7x -f(x,y))/4 +25
 T = (+y -0.7x)/2 +50

となります。(*1)
 これで、3次元空間内でx,y,f(x,y)がそれぞれ0~99の範囲で変化しても、画面(S=0~49、T=0~99)からはみ出すことは無いはずです。

【手順3】配列の設計とアクセス方法
 次に、今回のプログラムで必要な配列を考えます。
 まず、画面表示バッファとして要素数50×100=5000個の配列が必要となります。これを

 画面表示バッファ Z(0,0)~Z(49,99)

とします。
 例えば、配列Z(34,87)に数値42が書き込んである状態で表示ルーチン(まだ説明していないけど)を実行すると、パソコン画面上の座標(34,87)にはASCIIコードで42である"*"が表示されます。
 それから、立体を画面表示させる場合「障害物に隠れて見えない面は表示しない」という処理(隠面処理)
必要となります。
 次回説明しますが、
この
隠面処理に横軸(T軸)の各点毎の最大高さと最小高さを記憶する配列を用意します。
 最大高さ記憶配列 MAXH(0)~MAXH(99)

 最小高さ記憶配列 MINH(0)~MINH(99)
  
とします。
 なお、
現状の超小型記号言語(Ver1.4)の配列の要素数は約1000個ですから、これらの配列エリアを準備するのは到底無理です。
 ここはあっさり諦めて、超小型記号言語のバージョンアップ(Ver1.4→Ver1.5)で配列エリアを拡張することにしました。


 次に、超小型記号言語での配列へのアクセス方法について説明します。
 単純な変数Zへのアクセスであれば
   #42 Z!          (変数Zに数値42を代入)
   Z@ ¥           (変数Zの内容を文字表示)
で代入、文字表示できます。
 この例では、
変数Zの内容は文字コードと解釈され、ディスプレイ上には"*"が表示されます。

 
1次元配列Z(X)の場合、その実体は「変数Zの番地と変数Xの値を番地と見做して加算した番地」のメモリです。
 したがって、配列Z(55)なら変数Zの代わりに「Z #55 +」を使い(逆ポーランド記法ね!)
    #42 Z #55 +!    (配列Z(55)に数値42を代入)
    Z #55 +@ ¥     (
配列Z(55)の内容を文字表示)
とします。
 超小型記号言語ではアルファベット大文字(A~Z)が単独で現れた場合、数値(0~25)と解釈されることさえ知っていれば問題ないと思います。

 では、2次元配列Z(X,Y)はどうするかというと、これを
配列Z(X+50*Y)と考えます。(ここではX,Yの範囲が、X=0~49,Y=0~99という前提です)
 1次元配列になってしまえば理屈は簡単で、例えば配列Z(13,77)に数値42を代入するには
    #42 Z #13 #50 #77 *++!    (配列Z(13+50*77)に数値42を代入)
    Z #13 #50 #77 *++@ ¥      (
配列Z(13+50*77)の内容を文字表示)
とします。
 2次元配列Z(13,77)を1次元配列Z(13+50*77)に置き換えているのが判るかと思います。


 今回の説明はここまでとします。
 次回、後編で表示方法、
隠面処理、エッジの強調などの説明をしたいと思います。
 理屈はともかく、すでに完成してる
3Dグラフィクスプログラム(3dg.vts)を動かしてみましょう。
 Windowsパソコン上で動作させるとして、必要なファイルは

 超小型記号言語 vts15.zip
 サンプルプログラム vts-prg1.zip

です。両方とも「
超小型記号言語のページからダウンロードできます。

 2つのファイルを解凍後、同一フォルダに入れ、超小型記号言語の実行ファイルvtsxx15.exeをダブルクリックします。

 コマンドプロンプトが立ち上がって
"?"を表示したら、"3dg.vts"Enterをキーインすると動作します。

 なお、
コマンドプロンプトの文字が大きいと正しく曲面が表示されません。
 この場合は、1回だけは次の操作を行ってください。


 コマンドプロンプトの上側のタイトルバーを右クリックし「プロパティ」を選択
 ここで
 フォントサイズ=10
 フォント=MSゴシック
 画面バッファのサイズ=幅120以上、高さ60以上
 ウィンドウのサイズ
=幅120以上、高さ60以上
であることを確認(
必要に応じて変更)

 3dg.vts内の関数FNZを書き換えることで、色々な関数の曲面を表示することができます。
 
サンプルプログラムに曲面定義集が同梱されていますので参考にしてください。(三角関数とかは無理なので悪しからず)

 最後に、実行画面を図2-2に示します。
(ディスプレイの解像度は1280×1024)

    図2-2

 では、次回まで。

 --------------------
(*1)実際のプログラミングでは、この式を変形して

 S = (+7x -10f(x,y))/40 +25
 T = (+10y -7x)/20 +50

で計算します。この方が整数演算で誤差が小さくなります。
超小型記号言語のコードは逆ポーランド記法なので
 X@ #7 * X@ Y@ :FNZ #10 * - #40 / #25 + S!
 Y@ #10 * X@ #7 * - #20 / #50 + T!

となります。 


■第1回 z=f(x,y)のグラフ/準備編(2018/12/09掲載
,2018/12/24最終変更)
 前回で、(とはいっても3か月前ですが)数値計算とゲームプログラミングの土台となるプログラミング言語の開発が終了しました。
 いよいよ、今回から「数値計算とゲームプログラミング」を開始します。

 最初のテーマは、z=f(x,y)のグラフです。
 このテーマは、パソコン黎明期にグラフィック機能をアピールするにはうってつけでした。
 この記事も、当時のパソコン雑誌を参考にしています。(*1)
 ただ、超小型記号言語にはグラフィック機能がありません。
 そこで、コマンドプロンプト画面に"*"を表示することでグラフィック機能を代用することとします。
 幸いなことに、現在のパソコンではコマンドプロンプト上で400×150以上の文字表示が可能で、当時のパソコンのグラフィック機能と比べ遜色ありません。

 さて、今回は3次元空間に、水平方向には直交するx軸、y軸、高さ方向にはz軸があるものとします。
 この場合、関数z=f(x,y)は、任意のx,yに対してz軸(高さ)方向にf(x,y)だけ上方向にプロットされます。
 このプロットされた点の集まりが、関数z=f(x,y)で表された曲面ということになります。
 非常に単純な例ですが、f(x,y)=1であれば、高さ1のところにある水平な曲面(平面)を表します。

 次に、2次元であるパソコンのディスプレイ上では、縦方向(下向き)にX軸、水平方向(右向き)にY軸があることとします。
 このパソコンのディスプレイ(2次元)に立体的なz=f(x,y)の曲面を表示させるには、曲面をある方向から見た場合に限定してディスプレイに表示 するしかありませ ん。
 ここで、任意の方向から曲面を見た時のディスプレイ表示を考えると、たぶん行列とか三角関数が登場してきます。
 そっち方面(画像)は私の専門外ですし、どうせ超小型記号言語にはそんな機能(行列とか三角関数)はありません。
 ということで、見る方向はある特定の斜め方向に限定することとします。

  今回の話は、単純化すると3次元空間の任意の点(x,y,z)を、ある関係式で2次元空間(=パソコンのディスプレイ)の点(X,Y)に変換することです。
 では、その変換式は次の図1-1ではどういう式になるでしょうか。


    図1-1

 まだ、プログラミグしていないので、100%の確証はないのですが、たぶん
 X = +x/2 -z
 Y = +y -x/2

でしょう。(*2)
 図をみれば判ります。(数学は不要です)
 それなら、3次元空間の曲面f(x,y)は2次元座標表示では
 X = +x/2 -f(x,y)
 Y = +y -x/2
となるはずです。(*3)

 唐突ですが、今回はここまで。
 次回は、実はそう簡単にはいかない諸問題について説明します。
 --------------------
(*1)参考文献
 「エンサイクロペディア・アスキーVolume3、H68TR 3次元グラフィックス(アスキー出版)」
(*2)(*3)最初はxに係数(1/2)を付けていなかったですが
x軸が真下ではなく斜め左下方向に延びているためx軸の増減は他の軸の半分の効果しか無いと考え、xに係数(1/2)を付けました。

■タイトル変更のごあいさつ(2018/09/17掲載,2018/09/23最終変更)
 続編では、約半年前から土台となるプログラミング言語の開発から始めてきました。
 一応、現時点(Ver1.3)で実用レベルに達したと判断し、今後はこの言語を使用して数値計算とゲームプログラミングを行ってゆくことにします(*3)
 気の早い人は、ダウンロードして同梱のサンプルプログラムを動かしてみてください。(*1)
 なお、本文書のタイトルは実態に合わせて「超小型記号言語による数値計算とゲーム」に変更し、言語開発過程の記事は削除しました。(*2)
 --------------------
(*1)超小型記号言語は、トップページの「その他-超小型記号言語」からダウンロードできます。
(*2)旧タイトルは「続マイクロBASICによる数値計算とゲーム」でした。
(*3)Ver1.3で実用レベルに達したと書いたけれど、数値が16ビット(0~65535)だと計算精度がなかなか上がらないことを思い出しました。
 ということで、Ver1.4で数値を32ビット(0~42949672965)に改造してしまいました。
 これで準備完了です。

■続編のごあいさつ(2017/12/29掲載)
 これまで、マイコンキットZCPU1/K(E)のマイクロBASICを使用して数値計算とゲームプログラミングを行ってきました。
 しかしこの1年近く、忙しさとネタ切れのせいで、変わったテーマをお届けするといっておきながら放置状態でした。

 m(。-_-。)m

 今年からは、長続きするよう、タイトルに囚われずに気楽に趣味のプログラミングに突っ走ることにしました。(開き直りってやつね)
 まず最初に本キットが無くてもWindowsパソコンがあれば試すことができるように、土台となるプログラミング言語の開発から始めます。
 最初からタイトルから逸脱しているじゃん!という突っ込みは無視します。(きっぱり)
 人の作った俺様言語になんて興味ない!という意見はもっともです。(私も同感です)
 では、残った少数の方々のみお読みください。
 

[タ カミコムボードのトッ プページへ移動]