#author("2023-05-18T21:53:22+09:00","","")
#author("2023-05-20T10:56:42+09:00","","")
* 円運動の実現 [#vd2b23f4]
** シューティングにも円運動を! [#fbcf9c3f]
例えば「自機をナナメに移動させた際に、普通の縦/横移動のみの時よりも約1.41421356倍速く進む」とか、「敵が7WAY弾を撃つ際にも以下のように左図とならず、右図になってしまう」というのは、個人的にアツくなかったりします。ここでの紹介は方向感覚をより自然に、より奇麗に見せるための手法です。[[固定小数点>doc.18]]を使用した計算を前提としていますので、まだ読んでない方は予習して来てください。

#ref(1.png,nolink)

** 増分値のテーブル化 [#b709246e]
円運動の増分値を算出するには、''三角比''を避けて通れません。しかし三角関数の計算はとりわけ時間を要します。そこでまず、方向数を有限個(ここでは256個)に限定して、予め全方向の解データをテーブルで持ってします。方向値と移動方向の関係は次の通りです。

     192
      ↑
 128 ← ○ → 000
      ↓
     064

256方向もあれば十分でしょうがPCゲームの場合、360方向では精度が甘いとのことで4096にしていることもあるそうです。このようにして最初に「テーブル定義」してしまえば、あとは配列データから値を引っ張り出すだけで解が求まるので、超高速になります。

** テーブルの製作方法 [#o04d060d]
さっそく「256を1ドットとみなす固定小数点方式」でテーブルを出力してみることにしましょう。

 #include <stdio.h>
 #include <math.h>
 
 #define PI		(3.1415926536)
 
 
 int main(int argc, char* argv[])
 {
 	FILE* fp;
 	int   i;
 	short val;
 	char  str[80];
 
 	// コサインテーブルを出力します
 	fp = fopen("cosdata.txt","w");
 	if(fp == NULL)
 	{
 		return -1;
 	}
 
 	fprintf(fp,"cos:\n");
 
 	for(i=0; i<256; i++)
 	{
 		val = (short)(cos(((double)i / 128) * PI) * 256);
 
 		sprintf(str, "\t,%5d\t\t/* no.%3d */\n", val, i);
 		fprintf(fp, str);
 	}
 	fclose(fp);
 
 
 	// サインテーブルを出力します
 	fp = fopen("sindata.txt","w");
 	if(fp == NULL)
 	{
 		return -1;
 	}
 
 	fprintf(fp,"sin:\n");
 
 	for(i=0; i<256; i++)
 	{
 		val = (short)(sin(((double)i / 128) * PI) * 256);
 
 		sprintf(str, "\t,%5d\t\t/* no.%3d */\n", val, i);
 		fprintf(fp, str);
 	}
 	fclose(fp);
 
 
 	return 0;
 }

上記のcos()とsin()が、円運動のための移動増分を算出している部分です。実は!・・・自分自身、何故三角比で求まるのか、そのメカニズムの詳細はよく分かっていません(爆)。・・・すいません数学苦手なもので。まぁ、難しく考えるよりも、「こんな呪文で、あーら不思議!」・・・そういうものだと思っておいたほうが気楽で良いですよ。

- 出力結果
- cosdata.txt 
 cos:
 	,  256		/* no.  0 */
 	,  255		/* no.  1 */
 	,  255		/* no.  2 */
 	,  255		/* no.  3 */
 	,  254		/* no.  4 */
 	,  254		/* no.  5 */
 	,  253		/* no.  6 */
 	,  252		/* no.  7 */
 	,  251		/* no.  8 */
 	,  249		/* no.  9 */
 	,  248		/* no. 10 */
 	,  246		/* no. 11 */
 	,  244		/* no. 12 */
 	,  243		/* no. 13 */
 	,  241		/* no. 14 */
 	,  238		/* no. 15 */
 	,  236		/* no. 16 */
 	,  234		/* no. 17 */
 	,  231		/* no. 18 */
 	,  228		/* no. 19 */
 	,  225		/* no. 20 */
 	,  222		/* no. 21 */
 	,  219		/* no. 22 */
 	,  216		/* no. 23 */
 	,  212		/* no. 24 */
 	,  209		/* no. 25 */
 	,  205		/* no. 26 */
 	,  201		/* no. 27 */
 	,  197		/* no. 28 */
 	,  193		/* no. 29 */
 	,  189		/* no. 30 */
 	,  185		/* no. 31 */
 	,  181		/* no. 32 */
 	,  176		/* no. 33 */
 	,  171		/* no. 34 */
 	,  167		/* no. 35 */
 	,  162		/* no. 36 */
 	,  157		/* no. 37 */
 	,  152		/* no. 38 */
 	,  147		/* no. 39 */
 	,  142		/* no. 40 */
 	,  136		/* no. 41 */
 	,  131		/* no. 42 */
 	,  126		/* no. 43 */
 	,  120		/* no. 44 */
 	,  115		/* no. 45 */
 	,  109		/* no. 46 */
 	,  103		/* no. 47 */
 	,   97		/* no. 48 */
 	,   92		/* no. 49 */
 	,   86		/* no. 50 */
 	,   80		/* no. 51 */
 	,   74		/* no. 52 */
 	,   68		/* no. 53 */
 	,   62		/* no. 54 */
 	,   56		/* no. 55 */
 	,   49		/* no. 56 */
 	,   43		/* no. 57 */
 	,   37		/* no. 58 */
 	,   31		/* no. 59 */
 	,   25		/* no. 60 */
 	,   18		/* no. 61 */
 	,   12		/* no. 62 */
 	,    6		/* no. 63 */
 	,    0		/* no. 64 */
 	,   -6		/* no. 65 */
 	,  -12		/* no. 66 */
 	,  -18		/* no. 67 */
 	,  -25		/* no. 68 */
 	,  -31		/* no. 69 */
 	,  -37		/* no. 70 */
 	,  -43		/* no. 71 */
 	,  -49		/* no. 72 */
 	,  -56		/* no. 73 */
 	,  -62		/* no. 74 */
 	,  -68		/* no. 75 */
 	,  -74		/* no. 76 */
 	,  -80		/* no. 77 */
 	,  -86		/* no. 78 */
 	,  -92		/* no. 79 */
 	,  -97		/* no. 80 */
 	, -103		/* no. 81 */
 	, -109		/* no. 82 */
 	, -115		/* no. 83 */
 	, -120		/* no. 84 */
 	, -126		/* no. 85 */
 	, -131		/* no. 86 */
 	, -136		/* no. 87 */
 	, -142		/* no. 88 */
 	, -147		/* no. 89 */
 	, -152		/* no. 90 */
 	, -157		/* no. 91 */
 	, -162		/* no. 92 */
 	, -167		/* no. 93 */
 	, -171		/* no. 94 */
 	, -176		/* no. 95 */
 	, -181		/* no. 96 */
 	, -185		/* no. 97 */
 	, -189		/* no. 98 */
 	, -193		/* no. 99 */
 	, -197		/* no.100 */
 	, -201		/* no.101 */
 	, -205		/* no.102 */
 	, -209		/* no.103 */
 	, -212		/* no.104 */
 	, -216		/* no.105 */
 	, -219		/* no.106 */
 	, -222		/* no.107 */
 	, -225		/* no.108 */
 	, -228		/* no.109 */
 	, -231		/* no.110 */
 	, -234		/* no.111 */
 	, -236		/* no.112 */
 	, -238		/* no.113 */
 	, -241		/* no.114 */
 	, -243		/* no.115 */
 	, -244		/* no.116 */
 	, -246		/* no.117 */
 	, -248		/* no.118 */
 	, -249		/* no.119 */
 	, -251		/* no.120 */
 	, -252		/* no.121 */
 	, -253		/* no.122 */
 	, -254		/* no.123 */
 	, -254		/* no.124 */
 	, -255		/* no.125 */
 	, -255		/* no.126 */
 	, -255		/* no.127 */
 	, -256		/* no.128 */
 	, -255		/* no.129 */
 	, -255		/* no.130 */
 	, -255		/* no.131 */
 	, -254		/* no.132 */
 	, -254		/* no.133 */
 	, -253		/* no.134 */
 	, -252		/* no.135 */
 	, -251		/* no.136 */
 	, -249		/* no.137 */
 	, -248		/* no.138 */
 	, -246		/* no.139 */
 	, -244		/* no.140 */
 	, -243		/* no.141 */
 	, -241		/* no.142 */
 	, -238		/* no.143 */
 	, -236		/* no.144 */
 	, -234		/* no.145 */
 	, -231		/* no.146 */
 	, -228		/* no.147 */
 	, -225		/* no.148 */
 	, -222		/* no.149 */
 	, -219		/* no.150 */
 	, -216		/* no.151 */
 	, -212		/* no.152 */
 	, -209		/* no.153 */
 	, -205		/* no.154 */
 	, -201		/* no.155 */
 	, -197		/* no.156 */
 	, -193		/* no.157 */
 	, -189		/* no.158 */
 	, -185		/* no.159 */
 	, -181		/* no.160 */
 	, -176		/* no.161 */
 	, -171		/* no.162 */
 	, -167		/* no.163 */
 	, -162		/* no.164 */
 	, -157		/* no.165 */
 	, -152		/* no.166 */
 	, -147		/* no.167 */
 	, -142		/* no.168 */
 	, -136		/* no.169 */
 	, -131		/* no.170 */
 	, -126		/* no.171 */
 	, -120		/* no.172 */
 	, -115		/* no.173 */
 	, -109		/* no.174 */
 	, -103		/* no.175 */
 	,  -97		/* no.176 */
 	,  -92		/* no.177 */
 	,  -86		/* no.178 */
 	,  -80		/* no.179 */
 	,  -74		/* no.180 */
 	,  -68		/* no.181 */
 	,  -62		/* no.182 */
 	,  -56		/* no.183 */
 	,  -49		/* no.184 */
 	,  -43		/* no.185 */
 	,  -37		/* no.186 */
 	,  -31		/* no.187 */
 	,  -25		/* no.188 */
 	,  -18		/* no.189 */
 	,  -12		/* no.190 */
 	,   -6		/* no.191 */
 	,    0		/* no.192 */
 	,    6		/* no.193 */
 	,   12		/* no.194 */
 	,   18		/* no.195 */
 	,   25		/* no.196 */
 	,   31		/* no.197 */
 	,   37		/* no.198 */
 	,   43		/* no.199 */
 	,   49		/* no.200 */
 	,   56		/* no.201 */
 	,   62		/* no.202 */
 	,   68		/* no.203 */
 	,   74		/* no.204 */
 	,   80		/* no.205 */
 	,   86		/* no.206 */
 	,   92		/* no.207 */
 	,   97		/* no.208 */
 	,  103		/* no.209 */
 	,  109		/* no.210 */
 	,  115		/* no.211 */
 	,  120		/* no.212 */
 	,  126		/* no.213 */
 	,  131		/* no.214 */
 	,  136		/* no.215 */
 	,  142		/* no.216 */
 	,  147		/* no.217 */
 	,  152		/* no.218 */
 	,  157		/* no.219 */
 	,  162		/* no.220 */
 	,  167		/* no.221 */
 	,  171		/* no.222 */
 	,  176		/* no.223 */
 	,  181		/* no.224 */
 	,  185		/* no.225 */
 	,  189		/* no.226 */
 	,  193		/* no.227 */
 	,  197		/* no.228 */
 	,  201		/* no.229 */
 	,  205		/* no.230 */
 	,  209		/* no.231 */
 	,  212		/* no.232 */
 	,  216		/* no.233 */
 	,  219		/* no.234 */
 	,  222		/* no.235 */
 	,  225		/* no.236 */
 	,  228		/* no.237 */
 	,  231		/* no.238 */
 	,  234		/* no.239 */
 	,  236		/* no.240 */
 	,  238		/* no.241 */
 	,  241		/* no.242 */
 	,  243		/* no.243 */
 	,  244		/* no.244 */
 	,  246		/* no.245 */
 	,  248		/* no.246 */
 	,  249		/* no.247 */
 	,  251		/* no.248 */
 	,  252		/* no.249 */
 	,  253		/* no.250 */
 	,  254		/* no.251 */
 	,  254		/* no.252 */
 	,  255		/* no.253 */
 	,  255		/* no.254 */
 	,  255		/* no.255 */

- sindata.txt
 sin:
 	,    0		/* no.  0 */
 	,    6		/* no.  1 */
 	,   12		/* no.  2 */
 	,   18		/* no.  3 */
 	,   25		/* no.  4 */
 	,   31		/* no.  5 */
 	,   37		/* no.  6 */
 	,   43		/* no.  7 */
 	,   49		/* no.  8 */
 	,   56		/* no.  9 */
 	,   62		/* no. 10 */
 	,   68		/* no. 11 */
 	,   74		/* no. 12 */
 	,   80		/* no. 13 */
 	,   86		/* no. 14 */
 	,   92		/* no. 15 */
 	,   97		/* no. 16 */
 	,  103		/* no. 17 */
 	,  109		/* no. 18 */
 	,  115		/* no. 19 */
 	,  120		/* no. 20 */
 	,  126		/* no. 21 */
 	,  131		/* no. 22 */
 	,  136		/* no. 23 */
 	,  142		/* no. 24 */
 	,  147		/* no. 25 */
 	,  152		/* no. 26 */
 	,  157		/* no. 27 */
 	,  162		/* no. 28 */
 	,  167		/* no. 29 */
 	,  171		/* no. 30 */
 	,  176		/* no. 31 */
 	,  181		/* no. 32 */
 	,  185		/* no. 33 */
 	,  189		/* no. 34 */
 	,  193		/* no. 35 */
 	,  197		/* no. 36 */
 	,  201		/* no. 37 */
 	,  205		/* no. 38 */
 	,  209		/* no. 39 */
 	,  212		/* no. 40 */
 	,  216		/* no. 41 */
 	,  219		/* no. 42 */
 	,  222		/* no. 43 */
 	,  225		/* no. 44 */
 	,  228		/* no. 45 */
 	,  231		/* no. 46 */
 	,  234		/* no. 47 */
 	,  236		/* no. 48 */
 	,  238		/* no. 49 */
 	,  241		/* no. 50 */
 	,  243		/* no. 51 */
 	,  244		/* no. 52 */
 	,  246		/* no. 53 */
 	,  248		/* no. 54 */
 	,  249		/* no. 55 */
 	,  251		/* no. 56 */
 	,  252		/* no. 57 */
 	,  253		/* no. 58 */
 	,  254		/* no. 59 */
 	,  254		/* no. 60 */
 	,  255		/* no. 61 */
 	,  255		/* no. 62 */
 	,  255		/* no. 63 */
 	,  256		/* no. 64 */
 	,  255		/* no. 65 */
 	,  255		/* no. 66 */
 	,  255		/* no. 67 */
 	,  254		/* no. 68 */
 	,  254		/* no. 69 */
 	,  253		/* no. 70 */
 	,  252		/* no. 71 */
 	,  251		/* no. 72 */
 	,  249		/* no. 73 */
 	,  248		/* no. 74 */
 	,  246		/* no. 75 */
 	,  244		/* no. 76 */
 	,  243		/* no. 77 */
 	,  241		/* no. 78 */
 	,  238		/* no. 79 */
 	,  236		/* no. 80 */
 	,  234		/* no. 81 */
 	,  231		/* no. 82 */
 	,  228		/* no. 83 */
 	,  225		/* no. 84 */
 	,  222		/* no. 85 */
 	,  219		/* no. 86 */
 	,  216		/* no. 87 */
 	,  212		/* no. 88 */
 	,  209		/* no. 89 */
 	,  205		/* no. 90 */
 	,  201		/* no. 91 */
 	,  197		/* no. 92 */
 	,  193		/* no. 93 */
 	,  189		/* no. 94 */
 	,  185		/* no. 95 */
 	,  181		/* no. 96 */
 	,  176		/* no. 97 */
 	,  171		/* no. 98 */
 	,  167		/* no. 99 */
 	,  162		/* no.100 */
 	,  157		/* no.101 */
 	,  152		/* no.102 */
 	,  147		/* no.103 */
 	,  142		/* no.104 */
 	,  136		/* no.105 */
 	,  131		/* no.106 */
 	,  126		/* no.107 */
 	,  120		/* no.108 */
 	,  115		/* no.109 */
 	,  109		/* no.110 */
 	,  103		/* no.111 */
 	,   97		/* no.112 */
 	,   92		/* no.113 */
 	,   86		/* no.114 */
 	,   80		/* no.115 */
 	,   74		/* no.116 */
 	,   68		/* no.117 */
 	,   62		/* no.118 */
 	,   56		/* no.119 */
 	,   49		/* no.120 */
 	,   43		/* no.121 */
 	,   37		/* no.122 */
 	,   31		/* no.123 */
 	,   25		/* no.124 */
 	,   18		/* no.125 */
 	,   12		/* no.126 */
 	,    6		/* no.127 */
 	,    0		/* no.128 */
 	,   -6		/* no.129 */
 	,  -12		/* no.130 */
 	,  -18		/* no.131 */
 	,  -25		/* no.132 */
 	,  -31		/* no.133 */
 	,  -37		/* no.134 */
 	,  -43		/* no.135 */
 	,  -49		/* no.136 */
 	,  -56		/* no.137 */
 	,  -62		/* no.138 */
 	,  -68		/* no.139 */
 	,  -74		/* no.140 */
 	,  -80		/* no.141 */
 	,  -86		/* no.142 */
 	,  -92		/* no.143 */
 	,  -97		/* no.144 */
 	, -103		/* no.145 */
 	, -109		/* no.146 */
 	, -115		/* no.147 */
 	, -120		/* no.148 */
 	, -126		/* no.149 */
 	, -131		/* no.150 */
 	, -136		/* no.151 */
 	, -142		/* no.152 */
 	, -147		/* no.153 */
 	, -152		/* no.154 */
 	, -157		/* no.155 */
 	, -162		/* no.156 */
 	, -167		/* no.157 */
 	, -171		/* no.158 */
 	, -176		/* no.159 */
 	, -181		/* no.160 */
 	, -185		/* no.161 */
 	, -189		/* no.162 */
 	, -193		/* no.163 */
 	, -197		/* no.164 */
 	, -201		/* no.165 */
 	, -205		/* no.166 */
 	, -209		/* no.167 */
 	, -212		/* no.168 */
 	, -216		/* no.169 */
 	, -219		/* no.170 */
 	, -222		/* no.171 */
 	, -225		/* no.172 */
 	, -228		/* no.173 */
 	, -231		/* no.174 */
 	, -234		/* no.175 */
 	, -236		/* no.176 */
 	, -238		/* no.177 */
 	, -241		/* no.178 */
 	, -243		/* no.179 */
 	, -244		/* no.180 */
 	, -246		/* no.181 */
 	, -248		/* no.182 */
 	, -249		/* no.183 */
 	, -251		/* no.184 */
 	, -252		/* no.185 */
 	, -253		/* no.186 */
 	, -254		/* no.187 */
 	, -254		/* no.188 */
 	, -255		/* no.189 */
 	, -255		/* no.190 */
 	, -255		/* no.191 */
 	, -256		/* no.192 */
 	, -255		/* no.193 */
 	, -255		/* no.194 */
 	, -255		/* no.195 */
 	, -254		/* no.196 */
 	, -254		/* no.197 */
 	, -253		/* no.198 */
 	, -252		/* no.199 */
 	, -251		/* no.200 */
 	, -249		/* no.201 */
 	, -248		/* no.202 */
 	, -246		/* no.203 */
 	, -244		/* no.204 */
 	, -243		/* no.205 */
 	, -241		/* no.206 */
 	, -238		/* no.207 */
 	, -236		/* no.208 */
 	, -234		/* no.209 */
 	, -231		/* no.210 */
 	, -228		/* no.211 */
 	, -225		/* no.212 */
 	, -222		/* no.213 */
 	, -219		/* no.214 */
 	, -216		/* no.215 */
 	, -212		/* no.216 */
 	, -209		/* no.217 */
 	, -205		/* no.218 */
 	, -201		/* no.219 */
 	, -197		/* no.220 */
 	, -193		/* no.221 */
 	, -189		/* no.222 */
 	, -185		/* no.223 */
 	, -181		/* no.224 */
 	, -176		/* no.225 */
 	, -171		/* no.226 */
 	, -167		/* no.227 */
 	, -162		/* no.228 */
 	, -157		/* no.229 */
 	, -152		/* no.230 */
 	, -147		/* no.231 */
 	, -142		/* no.232 */
 	, -136		/* no.233 */
 	, -131		/* no.234 */
 	, -126		/* no.235 */
 	, -120		/* no.236 */
 	, -115		/* no.237 */
 	, -109		/* no.238 */
 	, -103		/* no.239 */
 	,  -97		/* no.240 */
 	,  -92		/* no.241 */
 	,  -86		/* no.242 */
 	,  -80		/* no.243 */
 	,  -74		/* no.244 */
 	,  -68		/* no.245 */
 	,  -62		/* no.246 */
 	,  -56		/* no.247 */
 	,  -49		/* no.248 */
 	,  -43		/* no.249 */
 	,  -37		/* no.250 */
 	,  -31		/* no.251 */
 	,  -25		/* no.252 */
 	,  -18		/* no.253 */
 	,  -12		/* no.254 */
 	,   -6		/* no.255 */

** 増分値テーブルの利用法 [#y883b990]
上記の解答データをカットアンドペースト(と言ってもno.0の最初の「,」は削除)して、少々整形します。

 const s16 CosTbl[] = {                                                     
         :
    (cosデータ)
         :
 };
 const s16 SinTbl[] = {
         :
    (sinデータ)
         :
 };

 int main()
 {
 	u16 x,y;
 	u8  angle;
 
 	// 初期処理
 
 	for(;;)
 	{
 		// もろもろの処理
 
 		// 円運動
 		x += CosTbl[angle];
 		y += SimTbl[angle];
 		angle++;
 
 		// 表示処理
 	}
 
 	return 0;
 }

・・・とすれば、円運動ぽい動きになる気がしませんか?

** メモリ節約 [#e955f586]
上記説明ではsin用、cos用でデータをそれぞれ用意していましたが、実はcos分だけでOKだったりします。なぜならば!

 SinTbl[angle] = CosTbl[(angle + 192) & 0xff]

という式が成り立つためです。先ほどのデータを見比べてみて下さい。マクロを使ってみると簡単になります。

 #define SQR_VX(a, b)    (((s32)CosTbl[(a)]              * (b)) >> 8)
 #define SQR_VY(a, b)    (((s32)CosTbl[(192+(a)) & 0xff] * (b)) >> 8)

 		// 円運動(変更案)
 		x += SQR_VX(angle, speed);
 		y += SQR_VY(angle, speed);
 		angle++;

に置換えれば、見事CosTblのデータだけで同じ動作が可能になっています。ちなみに、SQR_VX(a, b)の b にはスピード値が入り、ここでも「256を1とみなす固定小数点」を使っています。したがって、例えばここに256を設定すれば、[1ドット * 三角比]の移動量になります。

** 出典元 [#lf05c45c]
- M-KAIさんの「Witchシューティングゲーム制作記帳」

** 履歴 [#cf651bbb]
- 2023/05/18
- 2008/07/01

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS