[トップ][編集][ノート][編集履歴][一覧][最近の更新][->English]

HSPコンテスト:ショートプログラム:数学・物理編:移動


 中学校か高校か、忘れましたが、内分点の公式があります。それを利用した移動ルーチンを書いてみたいと思います。

 まず、内分点の公式を思い出しましょう。 (x1,y1) (x2,y2)の二点が存在するとき、その二つの点をα:βに内分する点(x3,y3)は次のようにして求まります。

  • x3=(αx1+βx2)/(α+β)
  • y3=(αy1+βy2)/(α+β)

 α+β=τとして、β=τ-αとすると、

  • x3=(αx1+(τ-α)x2)/τ
  • y3=(αy1+(τ-α)y2)/τ

 となります。ここで、αを0からτまで変化させると、α=0のときx3=x2 α=τのとき,x3=x1となり、x2からx1へとx3が移動することがわかります。またτは移動にかかる時間なので、この値を調整することによって、特定の座標への移動が簡単に出来るようになります。以上のことを踏まえたスクリプトを書いてみました。(p1からp2への移動になってますがあまり気にしないでください)

randomize
repeat
        p1x=p2x
        p1y=p2y

        rnd p2x,640
        rnd p2y,480

        repeat 0xFF
                redraw 0
                color 255,255,255
                boxf 0,0,640,480

                px=((p2x*cnt)+(p1x*(0xFF-cnt))) /0xFF
                py=((p2y*cnt)+(p1y*(0xFF-cnt))) /0xFF

                pos p2x,p2y
                color 255,0,0
                mes "●"

                color 0,0,0
                pos px,py
                mes "●"

                redraw 1
                await 16
        loop
loop

 また以下にその技術を用いて、筆者が去年のHSPプログラミングコンテストに出したもののスクリプトを張っておきます。いまさらながら、sprocket氏( http://sprocket.babyblue.jp/ )の三角関数テーブル作成ルーチンを使わせていただいたことにお礼を申し上げます。

//----------------------------------------
        dim sin,1024 ; テーブル用配列
        dim cos,1024
        sin.256=1024
        repeat 256
                r=cnt<<23/166886 ; ラジアンに変換
                sin.cnt=r*r>>10*r>>13/3*r>>15*r>>17/5+r-(r*r>>10*r>>17/3)-(r*r>>10*r>>13/3*r>>15*r>>13/5*r>>13/6*r>>17/7) +4>>3
                a=512-cnt
                sin.a=sin.cnt    ; 位相をpi/4ずらしてコピー
        loop
        
        repeat 512              ; 位相をpi/2ずらしてコピー
                a=cnt+512
                sin.a=-sin.cnt
        loop

        repeat 1024             //sinからCosを算出
                a=cnt+768&1023
                cos.a=sin.cnt
        loop
//----------------------------------------

        s=cmdline:peek c,s,1            ; コマンドラインの2文字目を取り出す
        if c='c' |(c=0) {       //Config
                dialog "No Configuration.",0,"Mathline."
                end;
        }
        if c='p' :screen 0,,,1:else{    //プレビューかどうか
                bgscr 2,dispx,dispy,1
        }


        repeat 256
                palette cnt,cnt,cnt,cnt
        loop
        palfade 



        dim PointLX,1024
        dim PointLY,1024
        dim PointNX,1024
        dim PointNY,1024

//-------------------------初期化ルーチンここまで-------------------------
//alpha 次のモデルのアルファ合成値(256単位)
//
//
//

        CenterX=winx/2
        CenterY=winy/2
        range=winy-16

        randomize

        repeat
                alpha=cnt&0xFF;
                if alpha=0{
                        memcpy PointLX,PointNX,1024*4
                        memcpy PointLY,PointNY,1024*4

                        if next>1{
                                repeat 60
                                        gosub *drawline
                                loop
                        }

                        last=next

                        *@
                        rnd t,19;
                        if next==t : goto *@b
                        next=t;
                        gosub *curbeline
                }               
                gosub *drawline
        loop


//-------------------------------------------------------------------


*curbeline
        rnd rev1,2
        rnd rev2,2

        repeat 1024
                dup PX,PointNX.cnt
                dup PY,PointNY.cnt

                theta1=cnt      //&1023;
                theta2=cnt*2    &1023;
                theta3=cnt*3    &1023;
                theta4=cnt*4    &1023;
                theta5=cnt*5    &1023;
                theta6=cnt*6    &1023;
                theta12=cnt*12  &1023;

//---------------収束系---------
                if next=0{      //収束
                        PX=0;
                        PY=0;
                }

                if next=1{              //ランダム発散
                        rnd PX,0x800
                        rnd PY,0x800
                        PX-=0x400
                        PY-=0x400
                        if PX*PX+(PY*PY)>0x100000:continue cnt
                }

//-----------------基本三角関数-------------
                if next=2{      //sin wave
                        PX=theta1-512<<1
                        PY=sin.theta2
                }

                if next=3{              //CosWave
                        PX=theta1-512<<1
                        PY=cos.theta2
                }

                if next=4{              //tangent wave
                        PX=theta1-512<<1
                        if sin.theta3==0 :theta3++;
                        PY=cos.theta3<<6 / sin.theta3
                }

//---------------直線系------------
                if next=5{                      //box
                        theta=theta1&0xff<<3-0x400
                        if theta1<0x100{        //0〜255
                                PX=theta;
                                PY=-0x400
                                goto *@f;
                        }
                        if theta1<0x200{ //256-511
                                PX=0x400
                                PY=theta
                                goto *@f;
                        }
                        if theta1<0x300{        //512-768
                                PX=-theta
                                PY=0x400
                        }
                        else {
                                PX=-0x400
                                PY=-theta
                        }               
                }

                if next=6{              //十字
                        theta=cnt&0b0100000000
                        PX=cos.theta*cos.theta1>>10;
                        PY=sin.theta*sin.theta1>>10;
                }
//---------------円系---------------
                if next=7{      //circle
                        PX=cos.theta1
                        PY=sin.theta1
                }

                if next=8{      //ぎざぎざ円
                        r=sin.theta12+1024>>2+512
                        PX=r*cos.theta1>>10
                        PY=r*sin.theta1>>10
                }

                if next=9{      //渦巻き
                        PX=theta1*cos.theta12>>10
                        PY=theta1*sin.theta12>>10
                }

                if next=10{     //多重円
                        if theta1\0x100==255 : theta4=0
                        theta=theta1&0b1100000000+0x80
                        PX=theta *cos.theta4>>10
                        PY=theta *sin.theta4>>10
                }


                if next=11{     //道路工事中?
                        theta=theta1&0b11111
                        PX=theta *cos.theta3>>5
                        PY=theta *sin.theta3>>5
                }

//------------リサージュ-------------
                if next=12{     
                        PX=sin.theta5
                        PY=cos.theta6
                }

                if next=13{     //リサージュ
                        PX=sin.theta6
                        PY=cos.theta5
                }


//--------------サイクロイド系-----------
                if next=14{     //ひし形
                        PX=cos.theta1
                        PX=PX*PX*PX>>20
                        PY=sin.theta1
                        PY=PY*PY*PY>>20
                }

                if next=15{     //三角形(内サイクロイド)
                        PY=sin.theta1*2+cos.theta2 /3+0x100
                        PX=cos.theta1*2+sin.theta2 /3
                }

                if next=16{     //外サイクロイド
                        PX=sin.theta1*6+sin.theta6 /7
                        PY=cos.theta1*6+cos.theta6 /7
                }

                if next=17{     //葉っぱ
                        PX=sin.theta4*cos.theta1>>10
                        PY=sin.theta4*sin.theta1>>10
                }

                if next=18{     //万華鏡
                        PX=sin.theta12+sin.theta1/2
                        PY=cos.theta12+cos.theta1/2
                }



                //-------------------------
        *@
                if rev1:PX=-PX
                if rev2:PY=-PY


        loop

return





*drawline

        redraw 0

        palcolor 
        boxf

        ColorSride=ColorSride+10&0xFF
        repeat 1024
                palcolor cnt-ColorSride&0xFF

                NPX =alpha*PointNX.cnt
                NPX+=256-alpha*PointLX.cnt
                NPY =alpha*PointNY.cnt
                NPY+=256-alpha*PointLY.cnt
                temp=NPX-LPX>>8
                Distance =temp*temp
                temp=NPY-LPY>>8
                Distance+=temp*temp

                DNPX=NPX*range>>19+CenterX
                DNPY=NPY*range>>19+CenterY
                DLPX=LPX*range>>19+CenterX
                DLPY=LPY*range>>19+CenterY

                if Distance > 10000 {
                        pset DNPX,DNPY 
                }
                else {
                        line DLPX,DLPY,DNPX,DNPY
                }

                LPX=NPX
                LPY=NPY
        loop
        redraw
        await 16
return