関数が使えないとsin、cos、sqrtなども使えないので少々無理があるんですが、
・六芒星の外側の点6つを繫げると正六角形になる
・正六角形も六芒星も正三角形を組み合わせると描ける
・正三角形を2等分すると、30度・60度・90度の直角三角形になり各辺の比率が1:2:√3になる
これらの性質を利用し、√3は定数にして比率で計算すればできないことはないので
実際にやってみました。
#define root3 1.732050807568877 // 3の平方根
// root3 = 1.732050807568877;としても可
r = 0.0; // 六芒星の外接円の半径(発射台からの距離)
ddim center, 2; // 発射台 中心点の座標
center = 320.0, 240.0;
cr = 10.0; // 発射台の大きさ(半径)
ddim point, 2, 30; // 弾の座標
pr = 5.0; // 弾の大きさ(半径)
pspeed = 2.0; // 弾速
loop_counter = 0; // ループカウンタ
*main
redraw 0;
color 255, 255, 255:boxf;
gosub *calc_points // 弾座標計算
// 弾 描画
color 255, 0, 0;
repeat 30
circle point(0, cnt)+center(0)-pr, point(1, cnt)+center(1)-pr, point(0, cnt)+center(0)+pr, point(1, cnt)+center(1)+pr, 1;
loop
r = pspeed * loop_counter; // 弾座標更新
// 発射台描画
color 0, 0, 0;
circle center(0)-cr, center(1)-cr, center(0)+cr, center(1)+cr, 1;
redraw 1;
await 17;
loop_counter++; // 弾座標更新用カウンタ
loop_counter \= 780/pspeed; // 弾が全て画面外に出た時のリセット用
goto *main
*calc_points
// 正六角形の頂点座標(上から順に時計回り)
point(0, 0) = 0.0, -1.0*r; // 正六角形の上の頂点座標
point(0, 1) = r*root3/2.0, -r/2.0; // 正六角形の右上の頂点座標
point(0, 2) = point(0, 1), -point(1, 1); // 正六角形の右下の頂点座標
point(0, 3) = point(0, 0), -point(1, 0); // 正六角形の下の頂点座標
point(0, 4) = -point(0, 1), point(1, 2); // 正六角形の左下の頂点座標
point(0, 5) = point(0, 4), point(1, 1); // 正六角形の左上の頂点座標
// 六芒星の交点(△と▽の交点)座標
p01 = (point(0, 1) - point(0, 5)) / 3.0; // 一時計算用変数
point(0, 6) = p01 + point(0, 5), point(1, 1); // △と▽の上辺の交点座標(左)
point(0, 7) = p01*2.0 + point(0, 5), point(1, 1); // △と▽の上辺の交点座標(右)
p01 = (point(0, 3) - point(0, 5)) / 3.0; // 一時計算用変数X
p02 = (point(1, 3) - point(1, 5)) / 3.0; // 一時計算用変数Y
point(0, 8) = p01 + point(0, 5), p02 + point(1, 5); // △と▽の左斜辺の交点座標(上)
point(0, 9) = p01*2.0 + point(0, 5), p02*2.0 + point(1, 5); // △と▽の左斜辺の交点座標(下)
point(0, 10) = -point(0, 8), point(1, 8); // △と▽の右斜辺の交点座標(上)
point(0, 11) = -point(0, 9), point(1, 9); // △と▽の右斜辺の交点座標(下)
// 各点の中点の座標
point(0, 12) = (point(0, 0)+point(0, 7)) / 2.0, (point(1, 0)+point(1, 7)) / 2.0;
point(0, 13) = (point(0, 7)+point(0, 10)) / 2.0, (point(1, 7)+point(1, 10)) / 2.0;
point(0, 14) = (point(0, 10)+point(0, 2)) / 2.0, (point(1, 10)+point(1, 2)) / 2.0;
point(0, 15) = (point(0, 2)+point(0, 11)) / 2.0, (point(1, 2)+point(1, 11)) / 2.0;
point(0, 16) = (point(0, 11)+point(0, 9)) / 2.0, (point(1, 11)+point(1, 9)) / 2.0;
point(0, 17) = (point(0, 9)+point(0, 4)) / 2.0, (point(1, 9)+point(1, 4)) / 2.0;
point(0, 18) = (point(0, 4)+point(0, 8)) / 2.0, (point(1, 4)+point(1, 8)) / 2.0;
point(0, 19) = (point(0, 8)+point(0, 6)) / 2.0, (point(1, 8)+point(1, 6)) / 2.0;
point(0, 20) = (point(0, 6)+point(0, 0)) / 2.0, (point(1, 6)+point(1, 0)) / 2.0;
point(0, 21) = (point(0, 1)+point(0, 10)) / 2.0, (point(1, 1)+point(1, 10)) / 2.0;
point(0, 22) = (point(0, 10)+point(0, 11)) / 2.0, (point(1, 10)+point(1, 11)) / 2.0;
point(0, 23) = (point(0, 11)+point(0, 3)) / 2.0, (point(1, 11)+point(1, 3)) / 2.0;
point(0, 24) = (point(0, 3)+point(0, 9)) / 2.0, (point(1, 3)+point(1, 9)) / 2.0;
point(0, 25) = (point(0, 9)+point(0, 8)) / 2.0, (point(1, 9)+point(1, 8)) / 2.0;
point(0, 26) = (point(0, 8)+point(0, 5)) / 2.0, (point(1, 8)+point(1, 5)) / 2.0;
point(0, 27) = (point(0, 5)+point(0, 6)) / 2.0, (point(1, 5)+point(1, 6)) / 2.0;
point(0, 28) = (point(0, 6)+point(0, 7)) / 2.0, (point(1, 6)+point(1, 7)) / 2.0;
point(0, 29) = (point(0, 7)+point(0, 1)) / 2.0, (point(1, 7)+point(1, 1)) / 2.0;
return;
正直手抜きなのでそれぞれ単独で座標計算するとか
精度が微妙だとか個人的に納得できない点は多々ありますが
三角関数を使用せず、1次関数の計算等すらも無しで幾何学的な図形を描くのは
無謀なので誰がやってもこんな感じになる気がします。
もう少しがんばれば多少効率的に組めるような感覚もありますが
いっそ六芒星の基準になる座標をあらかじめ定数データとして
発射した位置から放射線状に広がるようにフレーム毎に
係数を増やして乗算するだけの方がいいかもしれません。