AppGameKit Studio
Недостатньо оцінок
蒸気新聞社 マイコンBASICマガジン
Автор: Honekko
超絶初心者から始めるApp Game Kit Studio. ベーマガを読んでいた? ならば今日からプログラマーだ!
4
   
Нагородити
До улюбленого
В улюблених
Прибрати
第1章 まずはやってみよう!
App Game Kit Studioを起動して
File → New Projectを選択、Project名を適当につけます
そしてプロジェクト用の新規フォルダを作ろう



そうすると必要最小限のコードが書かれたプロジェクトが生成されます



なんじゃこりゃと思うかもしれませんが、気にせず実行してみよう!
RUNボタンをクリックだっ!


そうするとウィンドウが出てプログラムが実行されます
画面には現在のFPS(描写フレームレート)がリアルタイムに表示されています



さて、FPS表示を十分に満喫したらアプリを閉じて、コード部分を見ていきます
このプログラムの処理は大きく2つに分けられます
わかりやすいように20行目に赤い線を引いてみました



上部は起動した時のウィンドウサイズやタイトル、MAXFPSの設定など
アプリの基本的な部分の設定です

下部がこのプログラムのメイン部分、FPSの描写です
PrintでFPSを画面に描写し、Syncで描写の更新をしています
そしてdoとloopの間をずっと繰り返しているわけです

このプログラムは、実質Printのたった1行で構成されています
どうです? 簡単でしょう? (゚∀゚)
PRINTに始まり、PRINTに終わる
BASICの基本はPRINTだ! 画面に文字を表示させる!
これができれば、なんでも作れる! でしょ?

AGKのPRINTはこうだ!
Print ()
PrintC ()

PrintとPrintCって何が違うのか…
こういう時は実際にやってみよう!

前回作ったFPS表示プログラムを開いて、そこにコードを追加しよう
Print("BASIC ")
Print("MAGAZINE ")
PrintC("BASIC ")
PrintC("MAGAZINE ")
よし、できたらさっそく実行だ!



Printで表示させた文字は改行され
PrintCで書かれた文字はそのまま続けて書かれる
どうです? 簡単でしょう? (゚∀゚)
文字と画面に彩りを
あなたは、もはやあらゆる物を文字で表現できる
でも白黒画面じゃ寂しいよねぇ…
そこで活躍するのがSetClearColorだ
RGBカラーを指定することで好きな背景色にできるぞ!



書式は SetClearColor (RED,GREEN,BLUE)
doとloopの間にコードを書いていないのは
1回実行すれば背景はずっと青のままだからだ

では次は文字に色を付けてみよう
SetPrintColor() で同じように色をつけられるぞ



最後に、SetPrintSize() で文字のサイズを変えてみよう



やったな!お前はやればできる子だと思ってたよ!
どうです? 簡単でしょう? (゚∀゚)
テキストなら任せろ!変幻自在の魔術師 CreateText
あのぅ、できれば文字ごとに色やサイズを変えたいんですけど…
あ、そういうのもあるよね、そっちか〜 OKOK
よし、お前はPRINTから卒業だ! 今日からCreateTextを使え!
まずは今回のコードを御覧ください



11行目、SetWindowSize( 300, 200, 0 )に変更
実行時のサイズが無駄に大きかったのでコンパクトにしました

31行目、IF GETPOINTERPRESSED()=1 THEN EXIT
もし、マウスボタンが押されたならば、アプリを終了させます
IFのあとに条件(今回はマウスボタン)を指定し
それが1(ON)ならば(THEN)、EXITする(do loopから抜ける)という命令です
ウィンドウのXを押して閉じなくてもよくなりました

ではメインディッシュの25行目からのCreateTextについて解説していきます

書式は CreateText (ID,文字列)となります
文字列を記載する時はダブルクォーテーション("")で囲って記載します
では、IDとは何でしょうか?
これがPrintで生成される文字との大きな違いで
CreateTextは文字の書かれたシールを作る感覚です
そしてそのシールに "これは1番のシールだよ" と番号を振ります

CreateText (1,"BASIC MAGAZINE")
これでBASIC MAGAZINEと書かれた1番のシールができました

26行目、SetTextPosition
書式は SetTextPosition (ID,X座標,Y座標)
SetTextPosition (1,30,300) で1番のシールをX30,Y300の位置に貼ります

27行目、SetTextColor
書式は SetTextColor (ID,RED,GREEN,BLUE,ALPHA)
SetTextColor (1,255,0,0,255) で1番のシールを赤の不透明な色にします
ALPHAとは透過度の設定で、0で透明、255で不透明となります

28行目、SetTextSize
書式は SetTextSize (ID,サイズ)
SetTextSize (1,160)で1番のシールのサイズを160にします
どうです? 簡単でしょう? (゚∀゚)


CreateTextのよくあるエラー
やぁ、こんにちは
プログラマーが恐れおののくエラーの館へようこそ!
今回はCreateTextのよくある初心者エラーを解説するぞ
まずはエラー画像を見て頂こう



これは CreateText をdo loop内に書いてしまった時のエラーだ
なぜエラーになってしまうのかと言うと
すでに1番のIDでTEXTを作ってしまっているのに
loopでまた1番のTEXTを作成したためだ

CreateTextで作成されたTEXTはユニークな唯一の固有IDなので
同じIDで複数作ることはできない
そのため、do loop内で使いたいなら
do loop外であらかじめ作成しておいてから
SetText系で使用するようにしよう

do loop内で指定するまで画面に表示させたくないなら
SetTextColor(1,255,0,0,0) とアルファを0にして透過させれば
SetTextColorAlpha(1,255) で好きな時に画面に表示できるぞ!

SetText系コマンドは他にもあるので
AGKのHelpから検索して、いろいろ試してみよう!
どうです? 簡単でしょう? (゚∀゚)
でも日本語表示できないじゃん? ゴミ乙
そんな暴言吐く子には、もう教えてあげません!
今すぐお家に帰りなさい、ここから先は見ちゃダメよ、いいね?

たしかにAGKはデフォでは日本語が文字化けして使えません
でも、ちょろっと手間をかければ、すぐ使えちゃいます
まずは日本語フォントを手に入れましょう
今回はgoogleがフリーで公開しているフォントを使います
Noto Sans Japaneseでググってダウンロードしてきてください
そうしましたらZIPファイルを適当な場所に解凍しましょう

生成されたファイルの中から NotoSansJP-Regular.otfをコピーして
AGKで作成したプロジェクトファイルフォルダのmediaの中にペーストします
拡張子がotfだと読み込めないので、一般的なttfにリネームします
NotoSansJP-Regular.ttf ですね



AGKの上部メニュー、EditからPreferencesを選び
そこにあるCustom Editor Fontで
先程のmediaフォルダにあるフォントを選択してください



これでエディター部分に日本語を表示できるようになりました
でもね、直接入力はできないかもしれません…
メモ帳等に書いてコピペしましょう(CTRL+C,CTRL+V)



ではCreateTextで日本語を表示させてみましょう
コードはこんな感じです



文字化けしちゃいましたね?
アプリ側でも日本語フォントを指定してあげる必要があります

フォントの読み込み書式は LoadFont(ID,フォント名)
LoadFont( 1, "NotoSansJP-Regular.ttf" )

テキストにフォントを指定する時の書式は SetTextFont(テキストID,フォントID )
SetTextFont( 2, 1 )
ではもう一度実行してみましょう!



やったぜ! これで日本語も自由自在だ!
どうです? 簡単でしょう? (゚∀゚)
画像を表示しよう
文字を使いこなせたなら、次は絵だ!
画像を貼り付けて華やかな見た目にしよう

まず使用する画像をプロジェクトのmediaフォルダに入れます
前回フォントを入れた場所ですね


では今回のコードを御覧ください



36行目、画像を読み込みます、書式は LoadImage (ID,画像ファイル名)
LoadImage (1,"castle.png")

37行目、読み込んだ画像を貼り付けます
CreateSprite (このSpriteのID,LoadImageで読み込んだ画像ID)
CreateSprite (1,1)

38行目、スプライトのサイズ変更、書式は SetSpriteSize (SpriteのID,width,height)
SetSpriteSize (1,500,-1)

1番のスプライトを幅500に変更します
高さが-1になっていますが、こうすると自動で縦横比を維持した数値にしてくれます
200x150の画像を500x300にしたら歪んでしまいますよね?
-1にすると、わざわざ自分で計算しなくても良いので楽です

39行目、画像位置の指定、書式は SetSpritePosition (ID,X,Y)
SetSpritePosition (1, 160, 200 )

CreateTextの画像版といった感じで
シールをつくってぺたりんこするだけです
どうです? 簡単でしょう? (゚∀゚)
ゲームブックを作ろう
さて、いよいよゲームを作ってみよう
今まで覚えた事と、スパイスをひとつまみすれば
あなたはテキストアドベンチャー、すなわちゲームブックを作ることができる!

秘伝のレシピはこれだ!



52行目、AddVirtualButton(ID,X座標,Y座標,サイズ)
そのあとは、TextやSpriteと同じで
いつものSet系でパラメーターを指定していきます
ここまで学んできたあなたなら、解説は不要だと思うので省略
ど忘れしたらAGK内のHELP HOMEから検索してみましょう

57行目からのdo loop内
IF GetVirtualButtonPressed(1)=1 THEN exit
これは先程作成したボタンが押された(ON=1)なら、loopからexitする

59行目、IF GETPOINTERPRESSED()=1 THEN goto Shutdown
画面がクリックされたなら、Shutdownラベルへ移動
Shutdownラベルは84行目、最後にコロン(:)をつけるとgotoで指定できるラベルになります
ここに飛んだら、ENDでプログラムを終了させます

63行目、ボタンを押してloopから抜けてきたら
もうボタンはいらないので削除

66行目からはメッセージウィンドウの作成
CreateEditBox(ID)で入力BOXをつくりSet系で大きさや色を指定
75行目のSetEditBoxActive(ID,Active)でActive=0にして表示専用にします
ここがActiveだと掲示板の入力フォームのように自由に文字を書き込めるスペースになります

77行目、BOX内にテキストを表示
CHR(10)は改行のユニコードです、これを挟むことで好きな場所で改行できます

なんだかゲームっぽくなってきましたね? ね? なったよね?!
どうです? 簡単でしょう? (゚∀゚)
なにがわからないのかわからない
今時、ゲームブックなんて流行らないんじゃボケェ!
アクション、シューティング、FPS、ローグライクRPGはどうやって作るんじゃい?!

ひぇぇっぇえ 怖っ (;>Д<)
すんませんすんませんすんません!

とりあえず公式のチュートリアル動画をみてみましょう
https://youtube.com/playlist?list=PLlLxfPB9MrBtN8vFOZIUhotV9cs3VCV5Z

これを見れば、シューティングはもちろん、テトリスだって作れちゃいます

公式のガイドもあるので目を通しておきましょう
https://www.appgamekit.com/documentation/home.html

使い方がよくわからないコードがある?
そういった時は、公式フォーラムの上部にあるSEARCHから検索してみましょう
サンプルコードなどを見つけられるので非常に参考になります
https://forum.thegamecreators.com/

どうです? 簡単でしょう? (゚∀゚)
謝辞
マイコンBASICマガジン 電波新聞社
たのしく遊んで学べる最高の教科書でした、ありがとう!
廃刊になってしまいましたが、現在も電子工作マガジンの付録として生き続けているぞ
Kindle電子書籍化されているので付録単体でも購入可能
IchigoJam BASICのプログラムがメインに掲載されている

いらすとや
https://www.irasutoya.com/
画像を使用させていただきました、ありがとうございます
第2章 タイルマップを作ってみよう
2章ではRPGのフィールドマップや、アクション、シューティングゲームの背景など
さまざまな2Dゲームで使われる、タイルマップを作ってみよう!
今回のコードは、これだ!



20行目までは、自動で作られるコードなので21行目から解説していくぞ
まずは、10マスx10マスのマップデータの作成だ

21行目 Dim tilemap[100]
さぁ、いきなりやばいやつが出てきたぞ、Dimとは変数を宣言する命令だ
ここでは、tilemapという名前の変数に
[100]すなわち 0-100の合計101個のデータを入れる箱をつくったわけだ
なぜ10x10マスの100でいいのに101個作ったのかというと、単に人間側の利便性の問題だ
たとえば、1番目の箱を取ってくださいと言われたときに
数字は0から始まるので1と書かれた箱は実際のデータ上では2番目の箱なのだ
しかし101個作って、0を無視して1から使えば数字通りの場所の箱が取れるというわけだ

Dim tilemap[100] =[0,
0番目のデータで折り返して10x10の数字を見やすくならべていく
100個並べたら、最後を]で閉じて完了だ

32行目 do-loopの開始
34行目から39行目、For-Nextを使い、命令を繰り返してデータを描写していく
For i=1 to 100
変数iを1から始めて100になるまで繰り返す

printC (tilemap[i])
変数tilemapのi番目の中のデータを画面にプリントする

If i=10 or i=20 or ... PrintC (CHR(10))
もしiの値が指定した数字だったなら改行する
10x10なので10ごとに改行していく
ここで0番目をダミーにして101個のデータを作ったのが効いてくる
9,19,29,39... なんて書かなくていいから、断然見やすいし間違えにくい!

Endif
これは第1章で使ったIfの別の使い方で、1行にまとめてThenで処理する方法と
今回の様にThenを使わないで処理する方法がある
長文だったり、条件に合った時に複数の命令をするときは、If-Endifの方がすっきりするぞ

Next i
変数iに+1して34行目のForに戻る

さて、これにて解説終了!
プログラムを実行すれば、画面にDimで格納したデータが描写されたはずだ
20行ほどで出来ちゃうんだから、ちょろいね!
どうです? 簡単でしょう? (゚∀゚)
画像タイルを貼り付ける
Dimの使い方を理解したら、次はデータを参照して画像を貼り付けてみよう
コード & 実行画面カモーン!



21-31行目まで、マップデータの格納
1が壁、2が草原、3が水場、4が道の画像になる

33行目から、画像の読み込み
38行目はこの後に使う処理の準備として、変数yに0を入れておく
40行目から、画像貼り付け処理

CreateSprite (i,tilemap[i])
例えばiが12であった場合は
CreateSprite (12,2)となり、ID12番の画像は草原となる


42行目
SetSpritePosition (i, ((i*32 -32) - (y*320)), (y*32))
括弧内で画像を置くX座標とY座標を計算させている
用意した画像ファイルは32x32ドットなので
1枚目を貼るとX座標の0-31、Y座標の0-31までを使用する
2枚目を重ならないように右に貼るとするとX座標は32になる
iが2であるから、(i*32 -32)で、(64-32) = 32と計算できる
iが5、つまり5枚目の画像ならば (160-32) = 128でX座標は128だ

先に43行目の解説
If Mod(i,10) = 0 Then y = y+1
Modとは括弧内の数字を除算して、その余りを返す命令だ
上の例だと、iが10の倍数でない場合は何らかの0ではない数字を返す
しかし10の倍数の時は割り切れるので0を返す
0だったならば、変数yにy+1した数を入れる
この変数yは、画像のY座標とX座標の計算に使われる

42行目に戻って
((i*32 -32) - (y*320)), (y*32))
X座標の計算部分、-(y*320)が何かというと
画像を10の倍数個並べた後の改行されたX座標を補正している
例えば上から4行目、左から4番目の画像ID34のX座標は
(34*32 -32)-(3*320) = (1088-32)-(960) = 96 となり
(96,(y*32)) すなわち (96,96) X座標96,Y座標96となる訳である

プログラムとは...数学である!知恵熱でるね!
といったところで、今回はおひらき
どうです? 簡単でしょう? (゚∀゚)

☆豪華特別付録☆
今回はHonekko謹製タイルマップ画像をプレゼント!
ライバルに差をつけろ!


コラム AGKにおける計算優先順位
SetSpritePosition (i, ((i*32 -32) - (y*320)), (y*32))
このコードを見て、どういう順番で計算するんや…と困惑した方へ
AGKにおける計算優先順位を表にまとめましたので参考にどうぞ
記号
意味
優先度
( )
括弧
1
^
累乗
2
*
乗算
3
/
除算
3
+
加算
4
-
減算
4
マップをループスクロールさせよう
よしっ! では第2章の締めくくりとして
作ったタイルマップを動かしてみよう
まずは、どうやってスクロールさせるのかを考えてみる
今回はシンプルにスプライト画像のXY座標を加算と減算する


右へとスクロールさせるなら、座標Xに+1をしていけばいい
そして画面からはみでたら、一番左へ移動させる
しかしこの方法だと、2のときに画面左側に隙間が見えてしまう


これを防ぐにはどうしたらよいか?
タイルマップを1マス多めに作っておけばOKだ
切れ目が見える前に画面外でタイルが移動するので気づかれない
ではちょっと長いが、今回のコードを見ていこう



11行目、ウィンドウサイズを320から64ドット減らして256にする
これは見える部分を10x10から8x8にすることで
上下左右の画面外に1枚タイルを配置できる
同様に15行目もサイズを変更する

21行目からのマップデータは上下左右がつながった時に
見栄えが良いようにマップデザインを少し変更した

42行目、最初の見えてる部分をマップ中央にするために
X,Y座標の補正をした

46行目、バーチャルジョイスティックを中央に置いた

51,52行目、ジョイスティックの値を四捨五入して正負を逆転させる
JoyX = Round(GetVirtualJoystickX(1)*-1)
JoyY = Round(GetVirtualJoystickY(1)*-1)
スティックから返される値は(0.123456)のような小数点を含む0から1の数なので
Round()を使って四捨五入し、小数点以下を切り捨てて
後の計算で誤差によるズレが生じないようにした
この処理でJoyX,Yの値は、0、1、-1といった整数になる

正負を逆転させたのは、スティックを右にたおすと画面は左
左に倒すと右に、つまり倒す方向と逆にスクロールする訳だから
-1を掛けることで逆転させる必要がある
スティック左(-1)なら-1をかけて右(1)となる
下(1)なら上(-1)方向へとスクロールだ

54行目から、すでに生成されている100個の画像座標を再設定していく
GetX = Round(GetSpriteX(i))
GetY = Round(GetSpriteY(i))
変数GetX,YにGetSprite命令で取得したID(i)の画像位置を格納
これも後々誤差がでないように数値を四捨五入してある

FinalX = (GetX + JoyX)
FinalY = (GetY + JoyY)
最終座標の決定、取得した現座標をスクロール座標へと補正

If GetX >= 287 Then FinalX = -32
If GetX <= -63 Then FinalX = 256
If GetY <= -63 Then FinalY = 256
If GetY >= 287 Then FinalY = -32
画像座標が端ならば逆側に配置換えする

SetSpritePosition (i, (FinalX) , (FinalY))
画像を移動させて終了だ

では今回は特別に、実行画面を動画でお楽しみください
どうです? 簡単でしょう? (゚∀゚)



コラム 小数点計算の誤差とは?
何度か小数点を扱う時に四捨五入して
小数点以下切り捨て処理を行っていたが
なぜそんなことをする必要があるのだろうか?

人間ならまだしも、正確無比なコンピューター様が
計算ミスをするなんてことがありえるのか?

びっくりすることだが、小数点を含む数の場合
誤差が生じることはありえるのだ
有名なところだと、0.1 + 0.2を計算した時に
0.30000000000000004になってしまうことがある

なぜこんなことが起きるのかというと
コンピューターは0と1を使った2進数で処理しているので
整数以外の計算は誤差が生じてしまうことがある
興味を持たれた方は「小数点 二進数 誤差」で検索してみてね

上記のプログラムの場合、ジョイスティックの値は
その傾き度合いによって(0.000000)から(1.000000)の値を取る
0.000001程度の数の誤差が生じても
気にすることないじゃないかと思うかもしれないが
例えば60FPSの場合、1秒間に60回描写処理をしているし
それが100個、1000個の画像、時間的には1分、10分、1時間
となった場合、どんどん誤差が蓄積されていって
最終的には画像の描写位置が1ドットずれてしまうかもしれない
そういった事態を避けるために、毎回小数点以下のゴミを削除している訳だ

まったく、コンピューター様も適当だな!
だが、人間味があってたいへんよろしい (゚∀゚) かわいいやつめ!
第3章 ポップアップヘルプを作ろう
3章では、もはやゲームにおいて必須ともいえるポップアップヘルプを作ってみよう
ToolTip、ToolHint、TipHelpなどいろいろ呼び名があるが、好きに読み替えてほしい
昔はマニュアルでアイコンやアイテム、スキルや能力の説明をしたものだが
現在はチュートリアルと、このポップアップヘルプで全てを理解させるのだ

では、今回のコード、いってみよう!

(見づらい場合は画像クリックで表示される元画像URLをクリックしてね)

20行目まではいつもの自動生成コード
画面サイズは400x400に変更してある

21行目から、画像の読み込み
29行目から、画像の貼り付け
38行目、貼った画像の枚数を変数SpriteNumに入れておく
画像を追加、削除したときはこの数を変えるだけで動くようにした

40行目から、Dimを使って箱を作り、画像の座標データを格納する
Dim[6,6]だと
[0,0] [0,1] [0,2] [0,3] [0,4] [0,5] [0,6]
[1,0] [1,1] [1,2] [1,3] [1,4] [1,5] [1,6]
[2,0] [2,1] [2,2] [2,3] [2,4] [2,5] [2,6]
[3,0] [3,1] [3,2] [3,3] [3,4] [3,5] [3,6]
[4,0] [4,1] [4,2] [4,3] [4,4] [4,5] [4,6]
[5,0] [5,1] [5,2] [5,3] [5,4] [5,5] [5,6]
[6,0] [6,1] [6,2] [6,3] [6,4] [6,5] [6,6]
合計49個の箱ができる

SpriteID[A,B]
Aは先程貼り付けた画像のIDを表している
SpriteID[1,B]であれば、CreateSprite(1,1)のことだ

43行目から
SpriteID[i,1]=GetSpriteX(i)
SpriteID[i,2]=GetSpriteY(i)
SpriteID[i,1]、[i,2]にはGetSprite命令で取得したX,Y座標
これは画像の左上の座標になる

45行目から
SpriteID[i,3]=GetSpriteWidth(i)
SpriteID[i,4]=GetSpriteHeight(i)
SpriteID[i,3]、[i,4]には画像の縦横の長さを取得し格納する

47行目から
SpriteID[i,5]=SpriteID[i,1]+SpriteID[i,3]
SpriteID[i,6]=SpriteID[i,2]+SpriteID[i,4]
[i,1]に[i,3]の数値、[i,2]に[i,4]の数値を加算した値を
SpriteID[i,5]、[i,6]の箱に格納する
すなわち画像の右下部分の座標になる
これらをFor Next命令を使い、6つの画像の座標DATAを格納していく

51行目から、Dimに "as string" をつけて文字列を格納する箱を作る
そしてポップアップで表示する文字データを入れる
長い文章は適当にCHR(10)の改行コードをいれておこう

60行目から、ポップアップ用のテキストシールをあらかじめ作っておく
64行目、SetTextDepthで描写優先順位を上げる
この値は0-10000の値を取り、少ないほど優先して前面に描写される
テキストの既定値は9でスプライトは10だ

65行目、SetTextVisible(1,0) 作成したテキストを隠す
67行目からは、文字が見やすいように背景用のスプライトを生成しておく
71行目、PopVisible=0
ポップアップ描写のON/OFFを判定する変数に"0"を入れておく

73行目からdo loopの開始
まずは現在のマウス座標を取得しMouseX,MouseYに格納
77行目からは、格納しているDATAを画面に描写させる

87行目から、重なり判定と、ポップアップヘルプの作成
For NextとIf文で6枚の画像とマウス座標が重なっているか調べる
89行目、格納してある座標DATAとマウス座標から重なりを判定
範囲内にマウスがあるのならば
EndIfまでに書かれたコードを実行する

90行目、SetTextString(1,SpriteName[i])
すでに作ってあるテキストシールに
その画像に対応する文字データを書き込む

91〜92行目、テキストと背景スプライトの座標指定
93〜94行目、作成したポップアップヘルプの縦横の長さを取得
95行目、縦の長さから文章が何行かを計算
96行目、背景スプライトの大きさ変更
左右には4ドットの余白を作るので横幅を+8する
縦はフォントサイズに行数を掛ければOKだ

97行目、PopVisible=1
ポップアップ描写のON/OFF判定変数に1を入れてONにする

101行目からポップアップ描写ON/OFF処理
変数PopVisibleを参照して各種処理を行う
そして109行目でPopVisible変数に0を入れて終了だ

おつかれさま〜、今回のコードは長かったね
ではプログラムを実行してみよう!
動画で見たほうがわかりやすいと思うので、こちらをどうぞ


どうです? 簡単でしょう? (゚∀゚)


☆豪華特別付録☆
今回もHonekko謹製画像をプレゼント!
このコードを手打ちしてる人がいたら、テストでつかってね☆ミ


ドラッグ & ドロップ
さて、ここまでに学んだコマンドを使って
さまざまなゲームでよくみかける、ドラッグ&ドロップをやってみよう
3章のまとめ、応用編のスタート!



180行もあるじゃね〜かコンチキショー!!
と思うかもしれないが、がんばって付いてきてほしい
文字が見づらい場合はコード画像をクリックして
そこに表示される元画像URLをクリッックすると大きくなるぞ

20行目まで、自動生成コード
今回の画面サイズは360x240だ

21行目から、画像データの読み込み
アイテム画像が9個、背景画像が1個

29行目、サウンドデータの読み込み
これもCreateSpriteと同じで
LoadSoundOGG(ID,ファイル名)で、あらかじめ読み込んでおく

31行目から、Dimを使ってアイテムを配置する場所のデータを保管
左に12箇所、右に12箇所、合計24箇所のデータだ
番号は以下の画像のようになっている



BoxP[1]のデータを見てみると
BoxP[1,0]=8 左上のX座標は8
BoxP[1,1]=46 左上のY座標は46
BoxP[1,2]=39 右下のX座標は39
BoxP[1,3]=90 右下のY座標は90
BoxP[1,4]=1 BOXはfull、つまりここにはアイテムをドロップできない
BoxP[1,5]=0 装備タイプ=0、ここにはアイテムを装備できない
1が頭、2が胴、3が手に装備するタイプをドロップできる
そして9が何でも置けるインベントリとなる

43行目から画像を貼って、50行目から座標を設定
アイテムの初期位置は右側のインベントリなので
13番目から順にBoxPの座標を参照して配置していく

55行目から、アイテムの左上、右下の座標を格納
マウスでアイテムをドラッグする時の判定に使われる

64行目から、アイテムの説明文と装備タイプのデータ格納

76行目から、ポップアップヘルプ用のテキストと背景作成

88行目から、変数の設定
PopVisibleは、ポップアップのフラグ (0=off / 1=on)
DragFlagは、アイテムを掴んでいるときは1
SetItemは、アイテムを別の場所に移動させる処理のフラグ
MC= の部分はポップアップヘルプの背景に書かれる枠の色の格納
詳細は後ほど

92行目から、押すとプログラムを終了させるボタンの配置

97行目、Do-Loopの開始
98行目から、マウス座標の取得

102行目から、左マウスボタンが押された時の処理
103行目、左マウスボタンがONで、アイテムドラッグ中ではないなら
DragSprite= GetSpriteHit (MouseX,MouseY)
マウス座標にあるスプライトのIDを取得してDragSpriteに格納

105行目、取得したIDが画像なし(0)
ポップアップBOX(998)、背景(999)かチェック
"< >"は、〜ではない、つまり"="の逆の意味になる
ここでアイテム以外をつかまないようにしている訳だ

106行目から、アイテムであった場合、その画像の座標を取得
DragXとDragYは、ドラッグした画像の元座標となる
そしてドラッグフラグに1を入れて、アイテムつかみ中にする

112行目から、ボタンをはなしてドロップした時の処理
入り組んでいるので、こちらの画像をどうぞ



113行目、左マウスボタンが押されていない
かつ、アイテムをつかみ中である場合
1番に進み、2番を24回実行する
すなわち、全部の装備欄、インベントリをチェックする訳だ

115行目、マウス座標が、どこかのBox座標の中にある
かつ、BoxP[i,4]=0、すなわち空ならば3番に進む

116行目、ここで掴んでいるアイテムが装備可能かを判定する
BoxP[i,5]、そのBoxの装備タイプが
Len(SpriteDescription[DragSprite,3] or BoxP[i,5]=9 なら4番へ

このLenは文字列の文字数を数字で返すコードで
アイテム説明DATA内にある"@"の数を数字に変換している
つまり"@@@" なら"3"を意味する
Boxとアイテムが同じタイプなら4番へ
もしくは何でも置けるインベントリなら4番の処理へと進む

117行目から、どこからそのアイテムを取ってきたかを調べる
そのアイテムの元座標であるDragXとDragYを参照し
24個のアイテム欄と照合、BoxP[j,4]に0を入れて、空のフラグにする

120行目、場所が見つかったなら、それ以上調べる必要はないので
For-Next変数のjに24を入れてループを終わらせる

123、124行目、DragX,DragYにBoxP[i,0],BoxP[i,1]
すなわちアイテムを落とした場所のBox座標を入れる
これで画像を適当に箱に落としても、かっちりハマってくれる

125行目、アイテムを落とした箱にfullフラグを入れる
126行目、アイテムを落とした時の音を鳴らす
装備タイプによって、違う音を鳴らしている

127行目、処理が終わったならiに24をいれてループ終了

131行目、アイテムを放したので、DragFlagを0
そしてアイテム移動処理フラグに1を入れる

134行目から159行目まで、ポップアップの処理
これは前回紹介したので、追加した縁取り処理だけ解説する

144、145行目 DrawBoxを使って枠を描く
書式はDrawBox(x,y,x2,y2,color1,color2,color3,color4,filled )
左上XY座標、右下XY座標、各コーナーの色、そして塗りつぶすかどうか
colorは、MakeColor(255,255,255,255)のようにRGBと透過度を指定する
横に長くなるので、90行目で変数MCに格納しておいた

160行目から、SetItem=1、つまりアイテム移動処理フラグがONなら
落とした画像を元の場所、もしくは落とした場所のBoxに配置する
163行目からの処理で、その配置場所の座標データを書き込む
そしてSetItemフラグを0にする

170行目、アイテムを掴んでいるなら
画像をマウスに追従して移動させる

175行目、Exitボタンが押されたかチェック
押されたならloopから抜けて終了

キンコンカンコ〜ン、本日の授業はここまで!
では、ドラッグ&ドロップしまくって癒やされてほしい
実行動画はこちらっ!


どうです? 簡単でしょう? (゚∀゚)

☆豪華特別付録☆
Honekko謹製、アイテム&背景セット
このコードを手打ちしてる人がいたら、テストでつかってね☆ミ


第4章 変数を分かりやすくしよう
ここまで付いてこれたあなたなら
もはや2Dゲームは何でも作れると言っても過言ではない
冗談抜きで今までに使ってきたコマンドで作れてしまう
プログラムも頭から尻へと順番に処理する一本糞方式で全然問題ない
ぜひ、なにかプログラムを打ち込んで、一喜一憂してみてね♪

さて、そんなBASICプログラマーになったあなたへ
第4章からはApp Game Kit Studioの便利機能や小技を紹介していこうと思う

プログラムの規模が大きくなればなるほど、変数の数は膨大になり
「この変数なんだっけ?」となることがあるはずだ
今回はそんな変数を分かりやすくする方法を解説する

今回のコードはこちら!



20行目までは自動生成コード
今回の画面サイズは360x240だ

22行目、さぁ今回の目玉、Typeの登場だ
これは変数をグループ化する命令で
Type Player1とすることで、ここからEndTypeまでの変数はPlayer1グループになる
Player1グループの中に、文字列型のname、result
整数型のhp、atk、def、spd、lukが存在する

32行目から、同様にPlayer2のグループを作る

42行目、このグループを使う変数を宣言する
p1という変数はPlayer1グループだよというわけだ
この宣言をするとどうなるか?
p1.name という感じで "." とグループ内変数を続けて表記することで
そのターゲットの変数を呼び出せる

DIMコマンドで考えてみよう
DIM p1 [4] で5個の箱を作り
[0]=hp [1]=atk [2]=def [3]=spd [4]=lukの値を格納する
後になってp1 [3]ってなんだっけかなぁとなる事もあるはずだ

一方でTypeでグループ化したものは
p1.spd となれば、即座にspdであることが分かる
またTypeであれば、整数型、文字列型などの混在も容易だし
DIMのように[x]を付けることで複数の箱を作ることもできる

45行目、Gosubを使ってサブルーチンへ飛ばす
サブルーチンを実行したあとReturnでここに戻ってくる

47行目、文字サイズの変更

49行目、do - loopの開始

51行目からPrintを使って文字の描写
プレイヤーのステータスと対戦結果の表示

62行目、マウスクリックされたならサブルーチンに飛ばして結果を再抽選させる
サブルーチンの処理が終わったらReturnでここに戻る

64行目、画面の再描写
65行目 loop

67行目から、Randombonusサブルーチン

69行目から74行目、グループ化された変数に基礎DATA入力

76行目、ステータスボーナスに使うポイントの設定
50ポイントのボーナスポイントをP1、P2用に設定

78行目から、ランダムでステータスにポイントを割り振る
Random(0,bonusP1) で0からbonusP1までの値でランダムに数値が決定される
つまり Random(0,50)であり、0から50までの値になる
その後、使ったボーナスポイントをbonusP1から引く
順番にBCDと処理していくが、もし途中でbonusP1がゼロになっても
Random(0,0)でゼロを返すだけだなので問題ない

82行目から、ボーナスポイントを基礎ステータスに追加
lukには残ったボーナスポイントを加える(残っていれば)

88行目から同様にPlayer2も処理する

98行目から、For-Nextを使い3戦の結果をresultに書き込む
紙面の都合上、勝敗はランダムで決定した

107行目、Returnで呼び出されたGosubの場所へ戻る

さて、今回のコードはここまで!
変数をグループ化することで、だいぶ分かりやすくなってない?
それでは実行して思う存分ランダムな結果を楽しもう
どうです? 簡単でしょう? (゚∀゚)

Save & Load
変数を使いこなせるようになったあなたに
今回は変数DATAのセーブ&ロードを解説しよう
DATAをファイルに書き出すことでプログラムを終了させても
次回に変数DATAを引き継ぐことができるようになる

アクション、シューティングのハイスコア
RPG、SLGの各種ステータス、ゲーム設定パラメーターなど
DATAの保存は、もはや必須と言っていい機能だ

それでは今回のコードはこちら!



前回使ったコードを使いまわしているので
変更点だけ解説していく

35行目から、ボタンの設置と設定
49行目、セーブファイル名を設定
$はString、すなわち文字列型の変数を表している

50行目、ファイルがすでにあるかのチェック
初回起動など、ファイルがない場合にロードすると
DATAファイルが見つからずにエラーになるので
無い場合はSavedatサブルーチンに飛ばしてファイルを作成する

セーブファイルはデフォルトの場所に作られるが
場所を変えたい場合は、好きな場所に変えられるぞ
HELP HomeからCommands→FileにあるSet系コマンドを見てみよう

61行目から、各ボタンが押されたなら
対応するサブルーチンへ飛ばす

68行目から、セーブサブルーチン
OpenToWrite (ID,ファイル名) でファイルを開いて
DATAを書き込んだら CloseFile(ID)で閉じる
書き込み命令は、そのDATAの型にあわせて記述する
p1.nameは文字列型なので WriteString(ID,文字列)
p1.hpは整数型なので WriteInteger(ID,整数) となる

79行目から、ロードサブルーチン
OpenToReadでファイルを開いて
各変数にDATAを順番通りに読み込んでいく
これもDATAの型にあわせて命令を記述する
たとえば p1.atkは整数型なので ReadInteger(ID)となる

さて、本日の解説はここまで
さっそくプログラムを実行して
納得いくまでセーブ&ロードをしまくろう

どうです? 簡単でしょう? (゚∀゚)

DATAを分かりやすくしよう
変数DATAの読み書きをマスターしたあなたは
DATAファイル自体を自由に編集してみたいと思うかもしれない
前回紹介した方法だと、コンピューターには分かりやすいファイルだが
そのままだと内容を編集するには手間がかかるDATA記載方式だった

そこで今回は、人間にも理解しやすく編集も容易な方法で
DATAファイルを作成していきたいと思う
では、今回のコードはこちら!



ふたたびコードを使いまわしているので
変更点だけ解説していく

49行目、セーブファイル名設定
今回の目玉、JSON形式のファイルだ
JSONとは…

JavaScript Object Notation(JSON、ジェイソン)はデータ記述言語の1つである。
軽量なテキストベースのデータ交換用フォーマットであり
プログラミング言語を問わず利用できる。
名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。
(wikipediaより)

テキストベースで作られているので、人間にも分かりやすく、編集も容易だ
セーブされたファイルの中身はこのようになっている



シンプルなルールで作られたファイルなので、何も恐れることはない
さらにいえば、ファイルはApp Game Kitが勝手に作ってくれるので
あなたは特に何もする必要はない、命令コードを実行するのみだ

70行目、WriteString (1,p1.tojson())で
p1すなわちPlayer1グループのファイルをJSON形式で一気に書き出す
このコマンドひとつで全部やってくれる、らくちんだね!

76行目、p1.fromjson (ReadString(1))で
p1グループにJSON形式DATAを読み込む

なんと、これにて終了ぉ〜
さぁ、これであなたはJSONマスターだ!
JSONファイルを開いて、能力を欲望の赴くままに書き換えてみよう



どうです? 簡単でしょう? (゚∀゚)

Function
どんなゲームにも必須な機能としてオプション設定がある
ユーザーの多種多様なPC環境で快適に動くように手助けしよう!
今回はその中でも重要な、音量、リフレッシュレートの設定をしてみよう
コードは長いが、ほとんどTextとSpriteの設定だから恐れることはないぞ!



えっ? ちょっと!画像見て帰らないで!?
順番に解説していくから、ね?



9行目〜、オプション保存用のDATA設定
19行目、Global宣言をして作成したTypeを変数へと紐付け、詳細は後述
22行目〜、設定保存ファイルの存在確認と設定読み込み
ファイルが無い場合はMakeFileファンクションを使ってファイルを作る
その後、設定DATAを読み込み

では、新しく出てきたコマンド、Functionについて解説する
これは簡単に言うと、自分で独自の命令コマンドを作るようなものだ
例えば今回のMakeFileであれば
このファンクションを使用された時に実行される一連の命令が
533行目以降のFunction〜EndFunction間に記載されている

一見、Gosubでラベルに飛ばされた時のような挙動をしているが
Gosubには無い便利機能もあるので使い分けしていきたい
しかし、ファンクションの注意すべき仕様として
ファンクション内で変数はローカル変数として扱われるというのがある
詳しくはAGK内ヘルプから、Guides→ Functions and variable scope を読んでほしい
もしくは
https://www.appgamekit.com/documentation-studio/guides/functions_and_branching.htm#
こちらからどうぞ

そのため、ファンクションの外でも中でも共通して同じ変数を扱えるように
19行目でオプションDATAのGlobal宣言をしているわけだ



27行目〜、Window上部のバーに表示されるプログラム名とWindowサイズを設定
ユーザーはWindowの端をドラッグすることでリサイズできることとする

32行目〜、Config.vsyncが1なら、SetVSyncでVSyncをONにする
vsync=0 すなわちVSyncがOFFなら、SetSyncRateでFPS上限を設定する
SetVSync命令とSetSyncRate命令は競合するので注意が必要だ

例えばSetVSync(1)でVSyncをONにすると
それ以前にSetSyncRateでFPSの設定がされていても
リフレッシュレートは現在使用しているモニターのレートになる
SetSyncRate()でFPSを設定した場合
VSyncがONに設定してあったとしても自動的にOFFになる
常に最後に実行された命令が優先されると覚えておこう



44行目〜、BGMとサウンドの読み込みと音量設定
49行目でBGMを再生する

51行目からタイトルメニュー画面の描写
54行目、他の場所からタイトルに戻ってくる時用にラベルを設置



96行目からDo-Loopの開始
GetTextHitTest命令を使って
描写したTextにマウスカーソルが当たっているかチェック
当たっていた場合は色を変更する
さらにマウスボタンが押されたなら、その先のルーチンへと飛ばす
今回は紙面の都合上、オプション以外はプログラム終了とする

マウスカーソルがテキストと重なっておらず
なおかつ色が変更されているなら元のカラーに戻す
今回は、緑のカラーを参照して変更されたか判断させている



129行目から、メニューから飛ばされてきた各ルーチンの処理
Delete系で必要のないTextや画像を削除
Optionのみ先のルーチンへ進むが、処理が速すぎるため
飛ばされた先のTextまでクリックしてしまう
この誤クリックを避けるため、waitを0.5秒入れる

546行目〜、Waitファンクションの処理
ResetTimer()でタイマーを初期化
そのタイマーがWaitファンクションコマンドで渡された数値だけ待機する
Wait(0.5)で0.5秒、 Wait(3)で3秒、好きな秒数を指定できる

152行目からオプション画面の描写と処理
TextBGはファンクション命令で(TextのID、TextのX座標、TextのY座標)を渡すことで
Textの裏にTextの長さに合わせた黒いBOXを描写することができる



554行目〜、TextBGファンクションの処理
GetTextTotalWidth(TextID)でTextの横の長さを取得
GetTextTotalHeight(TextID)でTextの縦の長さを取得
それらに補正を加えてSpriteのサイズを決定
渡されたTextX、TextYの値から座標を決定

このようにパラメーターを渡すことで様々な処理ができるのが
ファンクションの便利なところだ



337行目から、Do-Loopの開始

340行目、確認用FPSを表示
346行目〜、左マウスボタンが押された時の処理
347行目、左マウスボタンが押されていて、かつDragFlag=0の時
348行目、GetSpriteHitで取得したスプライトIDを変数に入れる
349行目〜、スプライトIDがドラッグバーのIDなら、フラグをONにする



357行目〜、ドラッグバーの移動と処理
358行目、DragFlagとBgmFlagをチェック、両方1ならバーが掴まれている
359〜360行目、マウス座標がバーの可動範囲外なら可動範囲に収める
361行目、バーの位置を移動させる
362行目、マウス座標からボリュームの値を計算して変数に格納
363行目、ボリュームの変更



366行目〜、同様にサウンドバーの処理



375行目〜、マウスの左ボタンがリリースされた時の処理
マウスの左ボタンがOFFで、かつドラッグ中であった場合
すべてのフラグを解除して、SaveFileファンクションで設定の保存

381行目〜、BGMとSoundボリューム値のText更新



385行目〜、フルスクリーン設定の処理
387行目、On、Off文字へのHitチェック
389行目〜、Textにマウスが当たっていて
かつ、マウスボタンが押されたなら、On、Offの切り替え
TextBGファンクションで文字の長さに合わせた背景BOXの生成
SetWindowSizeで画面サイズをデフォルトに戻し、フルスクリーン設定適用
SaveFile()で設定を保存



408行目〜、Windowサイズ設定の処理
30行目でSetWindowAllowResize(1)に設定済みなので
AGKではWindowの端をマウスドラックすれば自由にサイズ変更可能だ
そのため今回は左にWindowサイズSaveボタン、右にResetボタンを配置した



432行目〜、VSync設定の処理
前述した通り、SetVSyncとSetSyncRate命令は競合するので
それに合わせた処理を行っている



465行目〜、MAX FPSの設定と処理



506行目〜、オプション設定からぬけるExitの処理
513行目、Sync()で画面を更新

キ〜ンコン〜カン〜コ〜〜ン
本日の授業はこれにて終了!
第4章で覚えたことのまとめとして、オプション設定を作ってみたけど
どうだったかな?
プログラムは長かったけど、やってることは難しくはなかったはずだ
これであなたは、BASIC、変数、DATAの読み書き、Function、AGK基本設定をマスターした
あとは美少女画像を描いて、オールドスクールなゲームをちょろっと加えれば
ゲームの完成だ! やったぜ!?

どうです? 簡単でしょう? (゚∀゚)

Коментарів: 10
Honekko  [автор] 8 січ. о 5:25 
Thank you! :autonautwuv:
Whenever I think of another article, I plan to update it very slowly.
I always end up coming back to my beloved home, AGK. :contented_bird:hehe
Staplers AFK awhile 8 січ. о 0:31 
Holy wow this is good. I can't read it, but I saw the progression of what you taught in the English. The input system at the end hopefully gets people familiar with using collision detection with Sync rate.
Thank you for writing this guide. Writing in this language is what kept my skills for iOS and other job-related.
Ganbatte.
Honekko  [автор] 22 листоп. 2024 о 7:13 
ありがとうございます!:happy_creep:
来年はPasocomMini PC-8801mkⅡSRが発売されるようで、ベーマガにも何やら動きがあるようです。
https://dempa-digital.com/article/605994
edolantrick 21 листоп. 2024 о 21:14 
マイコン BASICmagazineがまさか付録とはいえ復活しているとは・・・・・当然アマゾンで全部ポチりました。これからも頑張ってください。応援しています。
Honekko  [автор] 14 черв. 2024 о 22:54 
Thank you! :hana1::hana2:
Good luck to all of us. :autonautstar1up:
Carhd 14 черв. 2024 о 13:59 
incredible work!:cozykcdknight::firemissile:
Honekko  [автор] 31 січ. 2023 о 4:58 
ありがとうございます、励みになります:autonautstar1up:
edolantrick 30 січ. 2023 о 14:04 
大変参考になりました。是非これからも色々載せてください。
Honekko  [автор] 18 листоп. 2021 о 7:43 
I would like to help the first step for beginners. I hope people who read this guide will think "I feel like I can do it myself". :D
Thank you for your comment. From Japan with Love <3
Virtual Nomad 17 листоп. 2021 о 18:18 
you've obviously put a lot of work into this primer guide. i'm sure new users will appreciate it.
thanks for sharing :)