atan2のテーブル化について(NESASM用)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
KEYONN_
記事: 70
登録日時: 13年前

atan2のテーブル化について(NESASM用)

#1

投稿記事 by KEYONN_ » 12年前

敵の弾発射処理をコーディングしようと思っているのですが、
何かと便利なatan2関数をテーブル化したいと思っています。
ファミコンの画面解像度は、256x224です。
こんな感じでatan2テーブルを利用したいのですが、
どうすれば出来ますでしょうか?

コード:

          lda Enemy_X,x
          sta X1
          lda Enemy_Y,x
          sta Y1
          lda Jiki01_X
          sta X2
          lda Jiki01_Y
          sta Y2
          jsr atan2calc
          sta Angle
     ;…最後の方
atan2: .incbin "atan2.bin"
〔注意〕256周期で変数というかレジスタがcharなので、0~255に見合った
サイズでお願いします。
[編注意]過去ログをみましたが、toyoさんの作ったatan2のテーブル化
ルーチンが見つかりませんでした。

アバター
KEYONN_
記事: 70
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#2

投稿記事 by KEYONN_ » 12年前

コード:

#include<stdio.h>
#include<math.h>

#define RD 3.141592653/256

int main()
{
	
	char ATN[32][30];
	int x,y;
	FILE *fp;
	for(x=0;x<32;x++)
	{
		for(y=0;y<30;y++)
		{
			ATN[x][y]=((int)(atan2(y,x)/RD));
		}
	}
	fp=fopen("atan.bin","wb");
fwrite(ATN,sizeof(char),sizeof(ATN),fp);				
	fclose(fp);
	return 0;
}
このソースをVC++6でコンパイルし、
実行してみたところ、値がバイナリエディタで
見たら、
全て0x00でした。
何故でしょうか?

box
記事: 2002
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#3

投稿記事 by box » 12年前

KEYONN_ さんが書きました:

コード:

	char ATN[32][30];
			ATN[x][y]=((int)(atan2(y,x)/RD));
この2行の意味合いがよくわからないです。
ATN[][]はchar型でいいんですか?
また、そこに代入するとき、(おそらくdouble型の)逆正接値をintにキャストした結果を最終的にchar型に代入する、
というやり方は本当に正しいのでしょうか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: atan2のテーブル化について(NESASM用)

#4

投稿記事 by h2so5 » 12年前

マクロを展開すると16行目は下のような式になりますが、意図した通りですか?

ATN[x][y]=((int)(atan2(y,x)/3.141592653/256));

アバター
KEYONN_
記事: 70
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#5

投稿記事 by KEYONN_ » 12年前

h2so5 さんが書きました:マクロを展開すると16行目は下のような式になりますが、意図した通りですか?

ATN[x][y]=((int)(atan2(y,x)/3.141592653/256));
今、書籍で確認したところ、ラジアンから角度に直すには
度数=ラジアン÷180*PI;
みたいです。
どうやら間違ってたみたいです。

ただ、この場合、256周期で持ちたいので、その辺はどうなるのかは
よく分かりません。

アバター
KEYONN_
記事: 70
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#6

投稿記事 by KEYONN_ » 12年前

box さんが書きました:
KEYONN_ さんが書きました:

コード:

	char ATN[32][30];
			ATN[x][y]=((int)(atan2(y,x)/RD));
この2行の意味合いがよくわからないです。
ATN[][]はchar型でいいんですか?
また、そこに代入するとき、(おそらくdouble型の)逆正接値をintにキャストした結果を最終的にchar型に代入する、
というやり方は本当に正しいのでしょうか?
いえ、正しくはないと思います。intとcharではバイトのサイズが違いますので
正しくないです。何故こういう書き方をしたかというと、元のソース
このページがこういう書き方をしていたからです。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: atan2のテーブル化について(NESASM用)

#7

投稿記事 by ISLe » 12年前

ATN配列の添字は何を意味しているのでしょうか?

atanの0.0~1.0の範囲をテーブルにするのではないでしょうか。
インデックス計算するのに割り算が必要ですけど。

アバター
KEYONN_
記事: 70
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#8

投稿記事 by KEYONN_ » 12年前

ISLeさんへ

>ATN配列の添字は何を意味しているのでしょうか?
256x224を8で割ったものです。ただ、その場合は、32x28になるのでしょう。
実画面は、32x30なので、勘違いしていました。

>atanの0.0~1.0の範囲をテーブルにするのではないでしょうか。
>インデックス計算するのに割り算が必要ですけど。
atan関数で0.0~1.0の範囲をテーブルにするのですね。
ちょっとやってみます。

アバター
KEYONN_
記事: 70
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#9

投稿記事 by KEYONN_ » 12年前

擬似コードで書くとこんな感じでしょうか?

コード:

char ATN[32][28];
double i;
for(i=0.0f;i<1.0f;i+=?;)
{
     ATN[?][?]=atan(i);
}
?の部分が分かりません。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: atan2のテーブル化について(NESASM用)

#10

投稿記事 by ISLe » 12年前

画面をタイル分割すると対象との距離が近いほど精度が低くなりますけど、そんなので良いのでしょうか?

atanの0.0~1.0のテーブルはもっと精度の高いところを目指しますので考え方が異なります。
atanの0.0~1.0は45度分にあたります。
x,yそれぞれの差分の比率からインデックスを求めるので、45度を何分割するか好きに決めて良いです。
円周を256分割する前提ということなので細かくしすぎても無駄になってしまいますけど。


申し訳ないですけど、具体的に8ビット環境の実装を考えるのはめんどうなので、以前わたしが書いたコードを紹介します。
精度が異なりますが、変形すればそのまま使える部分も多いかと思います。

アバター
KEYONN_
記事: 70
登録日時: 13年前

Re: atan2のテーブル化について(NESASM用)

#11

投稿記事 by KEYONN_ » 12年前

ISleさんへ
ありがとうございます。
参考になりそうです。
16ビット(2バイト)使って、計算したいと思います。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: atan2のテーブル化について(NESASM用)

#12

投稿記事 by softya(ソフト屋) » 12年前

16ビット(2バイト)でやる前にNESでもメモリが足りるガ計算したほうが良いと思います。
NESのメモリから逆算して最低限の精度が出る方法を探るのが先ですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: atan2のテーブル化について(NESASM用)

#13

投稿記事 by ISLe » 12年前

先の回答で、円周65536分割を想定したコード、と書きましたけど誤りでした。
65536じゃなくて32768でした。
さらに円周一周を0~32767で表す前提になっているだけで、分割数はもっと少ないです。
異なる分割数で作った関数が二つずつ入ってますので、変更箇所の見当を付けやすいかと思います。

閉鎖

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