例えば「自機をナナメに移動させた際に、普通の縦/横移動のみの時よりも約1.41421356倍速く進む」とか、「敵が7WAY弾を撃つ際にも以下のように左図とならず、右図になってしまう」というのは、個人的にアツくなかったりします。ここでの紹介は方向感覚をより自然に、より奇麗に見せるための手法です。固定小数点を使用した計算を前提としていますので、まだ読んでない方は予習して来てください。
円運動の増分値を算出するには、三角比を避けて通れません。しかし三角関数の計算はとりわけ時間を要します。そこでまず、方向数を有限個(ここでは256個)に限定して、予め全方向の解データをテーブルで持ってします。方向値と移動方向の関係は次の通りです。
192 ↑ 128 ← ○ → 000 ↓ 064
256方向もあれば十分でしょうがPCゲームの場合、360方向では精度が甘いとのことで4096にしていることもあるそうです。このようにして最初に「テーブル定義」してしまえば、あとは配列データから値を引っ張り出すだけで解が求まるので、超高速になります。
さっそく「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()が、円運動のための移動増分を算出している部分です。実は!・・・自分自身、何故三角比で求まるのか、そのメカニズムの詳細はよく分かっていません(爆)。・・・すいません数学苦手なもので。まぁ、難しく考えるよりも、「こんな呪文で、あーら不思議!」・・・そういうものだと思っておいたほうが気楽で良いですよ。
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 */
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 */
上記の解答データをカットアンドペースト(と言っても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; }
・・・とすれば、円運動ぽい動きになる気がしませんか?
上記説明では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ドット * 三角比]の移動量になります。