HotSoupProcessorの記録 -3ページ目

HotSoupProcessorの記録

コンピューター言語 HotSoupProcessor の練習記録です

自作でちょっとしたものを作ろうと思うと、
関数とか、モジュール的なものを使いたくなるのですが
モジュールの中では、変数は流用されているのかなと思ってテストしてみました。

-----
  goto *Main

#module myMod
; 値の初期設定
#defcfunc local setValue int nValue
  a = nValue
  return a
; 足し算
#defcfunc local addValue int nValue
  a = a + nValue
  return a
#global


*Main
  ret = setValue@myMod(10)
  mes "return:" + ret

  ret = addValue@myMod(5)
  mes "return:" + ret

  mes "a:" + a
  
  stop
-----
この結果は、
  return:10
  return:15
  a:0
となりました。


つまり、どこで定義した変数も、クラス内のメンバ変数のような扱いということのようです。
生き続けて、他の関数からも見える。(addValue())

もちろん、外からは見えない。(最後のa)
ずいぶんお久しぶりです。
特に何があったというわけではありませんが
なんとなく遠ざかっておりました。ぐぅぐぅ

やりたいときがベストタイミングってことで
ふとやってみました。
自分で作った関数定義です。

-----
; 自作関数(正式にはユーザ定義関数)
  goto *MainProgram

; 足し算関数
#defcfunc myAdd int a, int b
  return a+b

; 引き算関数
#defcfunc mySub int a, int b
  return a-b

; メイン関数
*MainProgram
  ansAdd = myAdd( 10, 20 )
  mes "10+20=" + ansAdd

  ansSub = mySub( 40, 30 )
  mes "40-30=" + ansSub

  stop

----
前回、少しびびっていましたが、たいしたことはない感じ。
あえて言えば、プロトタイプ宣言したい感じ。

あと気をつけなくちゃいけないことが、変数のすべてがグローバル変数的な扱いになる。
つまり、myAdd()内で定義した変数を、mySub()で参照・変更が可能ということ。
これは危ないねってことで、モジュール化して固めるらしいです。
あ、あと、ラベルの重複防止も兼ねて。

それがこんな感じ。
-----
; 自作関数(正式にはユーザ定義関数)
  goto *MainProgram

#module
; 足し算関数
#defcfunc myAdd int a, int b
  return a+b
#global

#module
; 引き算関数
#defcfunc mySub int a, int b
  return a-b
#global

; メイン関数
*MainProgram
  ansAdd = myAdd( 10, 20 )
  mes "10+20=" + ansAdd
  
  ansSub = mySub( 40, 30 )
  mes "40-30=" + ansSub

  stop

----
変更点
・#module
 ~
 #global
  で囲みました。
こうすると、関数名以外は同じ変数名・ラベルを使ってもいい。

さらに関数名もかぶるよ!という場合は、モジュールに名前も付けられます。
----
; 自作関数(正式にはユーザ定義関数)
  goto *MainProgram

#module myModAdd
; 足し算関数
#defcfunc local myCalc int a, int b
  return a+b
#global

#module myModSub
; 引き算関数
#defcfunc local myCalc int a, int b
  return a-b
#global

; メイン関数
*MainProgram
  ansAdd = myCalc@myModAdd( 10, 20 )
  mes "10+20=" + ansAdd
  
  ansSub = myCalc@myModSub( 40, 30 )
  mes "40-30=" + ansSub

  stop

----
変更点
・#moduleの後ろに名前をつけました。
・関数名を2つ同じにしました。
・関数名の前にlocalをつけました。

localは・・・よくわからないから今のところはお決まりの呪文だと覚えておくことにします。合格
ちょっと触っていなかったので復習も兼ねて、
簡単そうなプログラムを作ってみました。ニコニコ

「カーソルが乗ると、色が変る」

でもこれじゃさすがに簡単そうだったので
「カーソルが乗ると、じわっと色が変る」
にしてみました。
もちろん、離れるときもじわっと戻ります。

------
; タイルのマス目上にマウスカーソルがあると、そのタイルがじわっと光る
  screen 0, 400, 300
  nTileSize = 50

  ; タイルの色
  ; 暗い色
  dim naBlack, 3
  naBlack = 0, 0, 50
  ; 明るい色
  dim naWhite, 3
  naWhite = 255, 255, 0
  ; じわっと光るステップ数(ステータスの値に使用する)
  nShineStep = 100

  ; 全タイルに、光状態のステータスを持たせる[ 0 ~ nShineStep ]
  nTileNum_x = int( ginfo_sx / nTileSize )
  nTileNum_y = int( ginfo_sy / nTileSize )
  dim naShineStatus, nTileNum_x, nTileNum_y
  for i, 0, nTileNum_x, 1
    for j, 0, nTileNum_y, 1
      naShineStatus(i,j) = 0
    next
  next

  ; 関数の使い方がよくわからないため使用するグローバル変数
  ; DrawOneTile()で使用
  ; タイルのx方向index
  gnX = 0
  ; タイルのy方向index
  gnY = 0
  ; 光らせる度合い(最大nShineStep)
  gnShine = 0


; メイン処理
*DrawMain
  redraw 0

  ; タイルを描く
  gosub *DrawTile

  redraw 1
  
  await 5
  goto *DrawMain
  
  stop


; タイルを描く
*DrawTile
  nTileNum_x = int( ginfo_sx / nTileSize )
  nTileNum_y = int( ginfo_sy / nTileSize )

  ; マウスがあるタイルを調べる
  mouse_i = int( mousex / nTileSize )
  mouse_j = int( mousey / nTileSize )

  for i, 0, nTileNum_x, 1
    for j, 0, nTileNum_y, 1
      ; マウスがある場合は光らせる
      if( (i=mouse_i) and (j=mouse_j) ){
        if( naShineStatus(i,j) < nShineStep ){  // 最大に光っていないタイルのみ
          naShineStatus(i,j) = naShineStatus(i,j) + 3  // 光るのは暗くするより早く
          // ※最後、少しmaxを超えるけど気にしない
        }
      }else{
        ; マウスがない場合は暗くさせる
        if( naShineStatus(i,j) > 0 ){  // もともと明るいタイルのみ
          naShineStatus(i,j) = naShineStatus(i,j) - 1
        }
      }
      
      ; 描画
      gnX = i
      gnY = j
      gnShine = naShineStatus(i,j)
      gosub *DrawOneTile
    next
  next
  
  return


; 指示があったタイルを1つだけ描く
; ※ 関数の使い方がよくわからないので、ひとまずグローバル変数で。。(恥
;    よくわからない点メモ
;      ・moduleを定義しないといけないのか?
;      ・変数は基本的にローカル変数なのか?
;      ・グローバル変数も使いたいときはどう記述するか?
; 引数
; gnX:タイルのx方向index
; gnY:タイルのy方向index
; gnShine:光らせる度合い(最大nShineStep)
*DrawOneTile
  ; 色の計算
  if( gnShine<=0 ){
    nR = naBlack(0)
    nG = naBlack(1)
    nB = naBlack(2)
  }else:if( gnShine>=nShineStep ){
    nR = naWhite(0)
    nG = naWhite(1)
    nB = naWhite(2)
  }else{
    nR = naBlack(0) + int( (gnShine*(naWhite(0) - naBlack(0)))/nShineStep )
    nG = naBlack(1) + int( (gnShine*(naWhite(1) - naBlack(1)))/nShineStep )
    nB = naBlack(2) + int( (gnShine*(naWhite(2) - naBlack(2)))/nShineStep )
  }

  ; 背景
  color nR, nG, nB
  boxf i*nTileSize, j*nTileSize, (i+1)*nTileSize, (j+1)*nTileSize
  
  ; 上のふち
  color 0, 0, 0
  line gnX*nTileSize, gnY*nTileSize, (gnX+1)*nTileSize, gnY*nTileSize
  
  ; 左のふち
  line gnX*nTileSize, gnY*nTileSize, gnX*nTileSize, (gnY+1)*nTileSize
  
  return
----------
アルゴリズムの問題なので、
HSP的に、特に難しい技術は使っていません。
長いけど、読めばわかるという感じ。

すべてのタイルごとにステータスを持って、
マウスカーソルの位置を見て、それを変えて、
それを元に色を決定する
というロジックです。



以前やったかもしれないけども、
内部関数の使い方がわからなかったので使いませんでしたあせる

じゃ、それは次の課題かなぁ。