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

シンプルなアナログ時計SS

シンプルなアナログ時計SS


            ; シンプルなアナログ時計スクリーンセーバー for HSP 3.0β7 or later
            ;
            ; HISTORY
            ;  Shark++
            ;   2005-04-16 HSPのβ版を試したくなり、
            ;              アナログ時計スクリーンセーバーを作り始める
            ;   2005-04-17 アナログ時計部分は完成
            ;   2005-04-21 針の形を変更
    
            ; ※HSPwikiからDL
            #include "typeutil.as"  ; ddim
            #include "math.as"              ; deg2rad
    
    #module
    
            #uselib "gdi32.dll"
    ;       #func PolyPolygon      "PolyPolygon"      int, int, var, int
            #func PolyPolygon      "PolyPolygon"      int, var, var, int
            #func CreatePen        "CreatePen"        int, int, int
            #func CreateSolidBrush "CreateSolidBrush" int
            #func SelectObject     "SelectObject"     int, int
            #func DeleteObject     "DeleteObject"     int
            #func GetStockObject   "GetStockObject"   int
            #define PS_SOLID        0
            #define NULL_BRUSH      5
    
    #deffunc porygon array ptpos, int count, int border_color, int fill_color
    
            ; porygon ptpos, count, border_color, fill_color
            ; 指定された描画頂点位置・線の色・背景色で多角形を描きます
            ;  ptpos        = 描画頂点位置
            ;     ※メモリ上では、X,Y の順に並んでいなければならない
            ;      dim ptpos,4,2 ではダメで、dim ptpos,2,4 にしなければいけない
            ;      また閉じた図形(頂点の最初と最後が同じ)でなければ描画されない
            ;  count        = 頂点の数
            ;  border_color = 線の色
            ;  fill_color   = 塗りつぶす色
    
            mref bmscr,67
            dim  _count,1 : _count = count
    
            ; 
            if (-1 = border_color) & (-1 = fill_color) : return
            if -1 = border_color : border_color = fill_color
    
            CreatePen PS_SOLID, 1, border_color
            SelectObject bmscr.4, stat
            hOldPen = stat
    
            if -1 = fill_color {
                            GetStockObject NULL_BRUSH }
            else {  CreateSolidBrush fill_color }
            SelectObject bmscr.4, stat
            hOldBrush = stat
    
            PolyPolygon bmscr.4, ptpos, _count, 1
    
            SelectObject bmscr.4, hOldPen
            DeleteObject stat
    
            if -1 != fill_color {
                    SelectObject bmscr.4, hOldBrush
                    DeleteObject stat
            }
    
            return
    
    #deffunc box int x1, int y1, int x2, int y2
            ; box x1,y1,x2,y2
            ; 画面上に、(p1,p2)と(p3,p4)を左上、右下の点として、
            ; 現在の描画色で矩形(四角形)を描画します。
    
            line x2, y1, x1, y1
            line x2, y2
            line x1, y2
            line x1, y1
    
            return
    
    #global
    
            #define ctype RGB(%1,%2,%3)     ((%1*65536)+(%2*256)+%3)
            #define rgbcolor(%1) color (%1/$10000)&$ff,(%1/$100)&$ff,%1&$ff
    
            ; パッケージオプション
            #packopt name "sstime"
            #packopt type 2         ; スクリーンセーバー
            #packopt xsize 320      ; 設定画面の横サイズ
            #packopt ysize 200      ; 設定画面の縦サイズ
            #packopt hide 1
    
            ;-----------------------------------------------------------------
            ; 引数評価
            ;-----------------------------------------------------------------
            s = dir_cmdline : type = peek(s,1)              ; コマンドラインの2文字目を取り出す
            if ('A'<=type)&(type<='Z') : type+=32   ; 大文字を小文字に変換する
            if type='p' : goto *sspre                               ; プレビュー
            if type='s' : goto *ssproc                              ; フルスクリーン
            if type='c' : goto *sscfg                               ; コンフィグ
            if type=0   : goto *sscfg                               ; コンフィグ
            ;
            ;       コマンドラインがどれでもない時はエラーを表示。
            ;       HSPスクリプトエディタでためしに実行してみる場合には、
            ;       HSPメニュー「起動オプション」を選んで、「/s」や「/p」などの
            ;       スイッチを指定してコンパイル+実行をしてください。
            ;
            dialog "Unknown switch ["+s+"]"
            end
    
    *sscfg
            dialog "", 0, "シンプルなアナログ時計"
    
            end
    
    *sspre
            ; 描画範囲指定
            sx = ginfo_winx - 10
            sy = ginfo_winy - 10
            dx = 5
            dy = 5
            goto *ssinit
    
    *ssproc
            ; 描画範囲指定
            sx = ginfo_dispx - 20
            sy = ginfo_dispy - 20
            dx = 10
            dy = 10
    
            bgscr 0, ginfo_dispx, ginfo_dispy, , 0, 0
    
    *ssinit
    
            cls 4
            title "シンプルなアナログ時計"
    
            crFill   = $006600
            crBorder = $00ff00
    
            ; 幅・高さを小さいほうにあわせる→正方形に
            if sy < sx : dx += (sx - sy) / 2 : sx = sy
            if sx < sy : dy += (sy - sx) / 2 : sy = sx
    
            cx = sx / 2
            cy = sy / 2
    
            n = 100.0
            gosub *init_sincos_table
    
            ; 範囲は 〜 100
            nn = 100.0
    
            ; 時計の針の位置(時)
            ddim clock_h,6,2
            clock_h.0.0 =  -5.0 : clock_h.0.1 =  -3.0
            clock_h.1.0 =  -8.0 : clock_h.1.1 =  50.0
            clock_h.2.0 =   0.0 : clock_h.2.1 =  60.0
            clock_h.3.0 =   8.0 : clock_h.3.1 =  50.0
            clock_h.4.0 =   5.0 : clock_h.4.1 =  -3.0
            clock_h.5.0 =   0.0 : clock_h.5.1 =  -5.0
            count_h = 6
    
            ; 時計の針の位置(分)
            ddim clock_m,6,2
            clock_m.0.0 =  -4.0 : clock_m.0.1 =  -2.0
            clock_m.1.0 =  -4.0 : clock_m.1.1 =  80.0
            clock_m.2.0 =   0.0 : clock_m.2.1 =  85.0
            clock_m.3.0 =   4.0 : clock_m.3.1 =  80.0
            clock_m.4.0 =   4.0 : clock_m.4.1 =  -2.0
            clock_m.5.0 =   0.0 : clock_m.5.1 =  -4.0
            count_m = 6
    
            ; 時計の針の位置(秒)
            ddim clock_s,5,2
            clock_s.0.0 =  -1.0 : clock_s.0.1 =  -8.0
            clock_s.1.0 =  -1.0 : clock_s.1.1 =  87.0
            clock_s.2.0 =   0.0 : clock_s.2.1 =  90.0
            clock_s.3.0 =   1.0 : clock_s.3.1 =  87.0
            clock_s.4.0 =   1.0 : clock_s.4.1 =  -8.0
            count_s = 5
    
            ; 文字盤のポッチ
            potti1_size = 2.0, 2.0
            ; 文字盤のポッチ(5分ごと)
            potti5_size = 2.0, 2.0
            ; 針の留め金のポッチ
            center_size = 1.0, 1.0
    
            ; 文字盤ポッチの半径
            potti_r = 95.0, 95.0
    
            ; 実際の描画範囲に拡大処理
            ; ※clock_h.cnt.0 ではエラーが起きる
            #define ctype ZOOM_SX(%1) %1=(%1)*cx/nn
            #define ctype ZOOM_SY(%1) %1=(%1)*cy/nn
    
            repeat count_h : ZOOM_SX(clock_h(cnt,0)) : ZOOM_SY(clock_h(cnt,1)) : loop
            repeat count_m : ZOOM_SX(clock_m(cnt,0)) : ZOOM_SY(clock_m(cnt,1)) : loop
            repeat count_s : ZOOM_SX(clock_s(cnt,0)) : ZOOM_SY(clock_s(cnt,1)) : loop
    
            ZOOM_SX(potti1_size.0) : ZOOM_SY(potti1_size.1)
            ZOOM_SX(potti5_size.0) : ZOOM_SY(potti5_size.1)
            ZOOM_SX(center_size.0) : ZOOM_SY(center_size.1)
            ZOOM_SX(potti_r.0)     : ZOOM_SY(potti_r.1)
    
            dim hpos,2,(count_h + 1)
            dim mpos,2,(count_m + 1)
            dim spos,2,(count_s + 1)
    
            gsel 0,2
    
    *main
            ; メインループ
    
            gosub *draw
    
            wait 1
            goto *main
    
    *draw
            ; dx    = 描画位置(横)
            ; dy    =    〃   (縦)
            ; sx    = 描画サイズ(幅)
            ; sy    =    〃     (高さ)
            ; cx    = 描画サイズ 1/2 (幅)
            ; cy    =    〃      1/2 (高さ)
    
            redraw 0
    
            gosub *draw_potti
            gosub *draw_time
    
            redraw 1
    
            return
    
    *draw_potti
            ; dx    = 描画位置(横)
            ; dy    =    〃   (縦)
            ; sx    = 描画サイズ(幅)
            ; sy    =    〃     (高さ)
            ; cx    = 描画サイズ 1/2 (幅)
            ; cy    =    〃      1/2 (高さ)
    
            ; 文字盤のポッチ
            repeat 60
                    rr = 1 * (cnt * 6 * n + 0.5)
                    px = dx + cx + (t_sin.rr * potti_r.0)
                    py = dy + cy + (t_cos.rr * potti_r.1)
    
                    if cnt \ 5 {
                            rgbcolor crFill
                            circle px-potti1_size.0, py-potti1_size.1, px+potti1_size.0, py+potti1_size.1, 1
            
                            rgbcolor crBorder
                            circle px-potti1_size.0, py-potti1_size.1, px+potti1_size.0, py+potti1_size.1, 0
                    }
                    else {
                            ; 5分ごと
                            rgbcolor crFill
                            boxf px-potti5_size.0, py-potti5_size.1, px+potti5_size.0, py+potti5_size.1
            
                            rgbcolor crBorder
                            box px-potti5_size.0, py-potti5_size.1, px+potti5_size.0, py+potti5_size.1
                    }
            loop
    
            return
    
    *draw_time
            ; dx    = 描画位置(横)
            ; dy    =    〃   (縦)
            ; sx    = 描画サイズ(幅)
            ; sy    =    〃     (高さ)
            ; cx    = 描画サイズ 1/2 (幅)
            ; cy    =    〃      1/2 (高さ)
    
            ; 前に描画した針を消す
            porygon hpos, count_h, RGB(0,0,0), RGB(0,0,0);crFill
            porygon mpos, count_m, RGB(0,0,0), RGB(0,0,0);crFill
            porygon spos, count_s, RGB(0,0,0), RGB(0,0,0);crFill
    
            _time = gettime(4), gettime(5), gettime(6), gettime(7)
    ; DEBUG
    ;       _time = gettime(5), gettime(6), gettime(7) / 16, 0
    
            ; 時
            r = 360.0 * ((_time.0 \ 12) * 3600 + _time.1 * 60 + _time.2) / 43200
            gosub *get_rotation_matrix
    
            repeat count_h
                    hpos(0,cnt) = dx + cx + (clock_h(cnt,0) * rm.0.0 + clock_h(cnt,1) * rm.0.1)
                    hpos(1,cnt) = dy + cy + (clock_h(cnt,0) * rm.1.0 + clock_h(cnt,1) * rm.1.1)
            loop
            hpos.0.count_h = hpos.0.0
            hpos.1.count_h = hpos.1.0
    
            porygon hpos, count_h, crBorder, crFill
    
            ; 分
            ; ミリ秒まで計算しないでも十分だろう
            r = 360.0 * (_time.1 * 60 + _time.2) / 3600
            gosub *get_rotation_matrix
    
            repeat count_m
                    mpos(0,cnt) = dx + cx + (clock_m(cnt,0) * rm.0.0 + clock_m(cnt,1) * rm.0.1)
                    mpos(1,cnt) = dy + cy + (clock_m(cnt,0) * rm.1.0 + clock_m(cnt,1) * rm.1.1)
            loop
            mpos.0.count_m = mpos.0.0
            mpos.1.count_m = mpos.1.0
    
            porygon mpos, count_m, crBorder, crFill
    
            ; 秒
            r = 360.0 * (_time.2 * 1000 + _time.3) / 60000
            gosub *get_rotation_matrix
    
            repeat count_s
                    spos(0,cnt) = dx + cx + (clock_s(cnt,0) * rm.0.0 + clock_s(cnt,1) * rm.0.1)
                    spos(1,cnt) = dy + cy + (clock_s(cnt,0) * rm.1.0 + clock_s(cnt,1) * rm.1.1)
            loop
            spos.0.count_s = spos.0.0
            spos.1.count_s = spos.1.0
    
            porygon spos, count_s, crBorder, crFill
    
            ; 針の留め金
            px = dx + cx
            py = dy + cy
    
            rgbcolor crFill
            circle px-center_size.0, py-center_size.1, px+center_size.0, py+center_size.1, 1
    
            rgbcolor crBorder
            circle px-center_size.0, py-center_size.1, px+center_size.0, py+center_size.1, 0
    
    
            return
    
    *init_sincos_table
            ; SIN・COS 計算用テーブルを作成
            ; [IN]
            ;  n = 1度あたりの分割数
            ; [OUT]
            ;  t_sin = SINテーブル
            ;  t_cos = COSテーブル
    
            ddim t_sin,360*n
            ddim t_cos,360*n
    
            repeat 360*n
                    t_sin(cnt) = sin(deg2rad(1.0 * cnt / n))
                    t_cos(cnt) = cos(deg2rad(1.0 * cnt / n))
            loop
    
    ; 大して速度が変わらない
    ;       repeat 899
    ;               m = cnt
    ;               t_cos( 899-cnt) =  t_sin(1+cnt)
    ;               t_cos( 900+cnt) = -t_sin(cnt)
    ;               t_cos(1800+cnt) = -t_sin(900-cnt)
    ;               t_cos(2700+cnt) =  t_sin(cnt)
    ;       loop
    
            return
    
    *get_rotation_matrix
            ; 回転行列を取得(角度を180度変える)
            ; [IN]
            ;  r = 取得角度
            ;  n = SIN・COS 計算用テーブルの1度あたりの分割数
            ; [OUT]
            ;  rm = 回転行列(2*2)
    
            ; 時計の針用に角度を180度変える
            r += 180.0 : if 360 <= r : r -= 360
    
            rr = 1 * (r * n + 0.5)
            ; 回転行列
            ; X = x * cosβ - y * sinβ
            ; Y = x * sinβ + y * cosβ
            ddim rm,2,2
            rm.0.0 =  t_cos.rr
            rm.0.1 = -t_sin.rr
            rm.1.0 =  t_sin.rr
            rm.1.1 =  t_cos.rr
    
            return