プチコンで遊ぼう! (はてなブログ版)

任天堂3DSのプチコンで遊ぼう! [twitter:@eida_s]

はてなダイアリーから移行しました。 はてなダイアリーのURLを開いても自動的にこちらにリダイレクトされますのでご了承ください。

BGMCHKの挙動

旧3DSLLかつプチコン3号 Ver3.3.1で以下を確認。

134番のBGMが終わってから、135番のBGMを流すつもりで以下のように処理を書くと、

BGMPLAY 134
WHILE BGMCHK():WEND
BGMPLAY 135

なぜかループがすぐ終了し、135番は演奏されない。

BGMPLAYを発行してからタイムラグがあるのかもしれない。

BGMPLAY 134
WHILE BGMCHK():VSYNC 1:WEND
BGMPLAY 135

だと大丈夫。134番の演奏が終わってから135番が演奏された。

BGMPLAY 134
WHILE BGMCHK():FOR I=1 TO 29:NEXT:WEND
BGMPLAY 135

でも大体問題ない。

BGMPLAY 134
WHILE BGMCHK():FOR I=1 TO 28:NEXT:WEND
BGMPLAY 135

だと大体ダメで135番が演奏されない。


しかし、WHILEループを除いて、

BGMPLAY 134
BGMPLAY 135

とすると、人間の耳には135番だけ演奏されているように聞こえる。

謎である。

パズル 7650 (パックマンDLC必要)

パックマンDLCを使ったパズル7650。
なんか見たことあるような?いや気のせいですw

ファイル名: ED7650

公開キー: QDAJR3B3 C33NY3AP E23N33D4

公開日: 2016/12/18 2016/06/27 2016/06/12

バージョン: 1.11 1.10 1.00

v1.11 WiiUでエラーになる問題を修正
v1.10 DLCがない場合の対応を少し修正
v1.00 初公開

必要DLCPACMAN
DLCがない場合は、スプライト等が代用品に置き換わります)

【遊び方】

1)十字キーでタイルをスライドし、同じ絵柄同士を合体させていきます。

2)同じ絵柄同士を合体させると得点になり、より得点の高い絵柄に変わります。

3)これを繰り返して7650点のタイル作成を目指してください。
(7650点を獲得してもゲームは続きます。)

4)A,B,X,Yボタンのいずれかを押すとメニューを表示し、リトライを選ぶと最初からやり直すことができます。

5)ハイスコアは、メニューからEXIT GAMEを選んだ時に保存されます。


【その他】

「7650」という数字にこじつけたかっただけなので、「パックマンの内容とかけはなれている」などの批判は受け付けませんw

ちなみにmkIIの時も似た(w)ゲームを作っていました。
http://d.hatena.ne.jp/eidaht/20140608/1402249061

SMILE BASIC 小技(9)

PRGINSで動的にコードを追加する方法。

PRGINSで他のスロットにコードを追加した後にUSEを実行すると、追加したコードを実行することができる。
PRGINS毎にUSEを使えば、何度でもコードを追加できる。

例:

VAR DQ$=CHR$(34)
PRGEDIT 3
PRGDEL -1

PRGINS "DEF A"
PRGINS " ?"+DQ$+"A"+DQ$
PRGINS "END"

USE 3
CALL "3:A"

PRGINS "DEF B"
PRGINS " ?"+DQ$+"B"+DQ$
PRGINS "END"

USE 3
CALL "3:B"

USEが2度現れているが、問題なく実行できる。

これを応用する例としては、ツール系のプログラムで設定ファイルにコードを書いて追加するとか、ユーザーに入力させたコードを実行する等が考えられる。

ただし、一般的な注意として、最初にプログラムを実行したスロットをPRG系命令で編集することはできないので気を付ける必要がある。

SMILE BASIC 小技(8)

BGのキャラ定義の一部がキャラクターコードに対応していることと、BGGETを使うと非常に簡単に自作キーボードを作ることができる。

具体的には、

TOUCH OUT STTM, TX, TY
G=BGGET(レイヤー番号,TX,TY,1)

とすると、GにBGのキャラ番号がとれる。
BGの32〜95番には、同一アスキーコードの英数字記号が割り当てられているので、これを使って処理する。

簡易キーボードの例:

前半部分で文字を並べているが、この文字のレイアウトを変えても、判定部分は一切変える必要がない。


実用例としては、この小技を使って、拙作のゲームブックドルアーガの塔アドベンチャーシートで、数値入力用パネルを実装している。
ゲームブック「ドルアーガの塔」アドベンチャーシート for プチコン3号 (β2版)


また、上記の小技を使って簡単なゲームを作ってみた。
OSE! Catch The Gyoku
キー【EBNECE3E】
遊び方:
 「玉」をタッチでつかまえてください。
 ただし、人質になっているキングとクイーンを間違えてタッチしたり、画面外に逃げられると負けになります。

バイナリファイル調査その(2)

型変換調査
(1)

VAR A#[10]
A#[0]=1.5
A#[1]=2.5
SAVE "DAT:BINDATA",A#
VAR B%[0]
LOAD "DAT:BINDATA",B%
?"LEN=";LEN(B%)
?B%[0]
?B%[1]
?B%[2]
?B%[3]

とすると、

LEN=10
1
2
0
0

と表示される。

(2)

VAR A%[10]
A%[0]=1
A%[1]=2
SAVE "DAT:BINDATA",A%
VAR B#[0]
LOAD "DAT:BINDATA",B#
?"LEN=";LEN(B#)
?B#[0]
?B#[1]
?B#[2]
?B#[3]

とすると、

LEN=10
1
2
0
0

と表示される。

つまり、直接的にバイナリとして読み込まれるわけではなく、
LOAD時に、SAVE時の型として一度読み込まれてから、その後に変数に代入されていることがわかる。

バイナリファイル調査その(1)

バイナリファイルサイズ調査
(1)

VAR A[1]
a[0]=1
SAVE "DAT:BINTEST",A

とすると、36バイトのファイルが作成された。

(2)

VAR A#[2]
A#[0]=1
A#[1]=2
SAVE "DAT:BINTEST",A#

だと44バイト。

(3)

VAR A%[1]
A%[0]=1
SAVE "DAT:BINTEST",A%

だと32バイト。

(4)

VAR A%[2]
A%[0]=1
A%[1]=2
SAVE "DAT:BINTEST",A%

だと36バイト。

よって、
ヘッダー28バイト+(倍精度小数なら8バイト、整数なら4バイト)*個数
の大きさと思われる。


#ヘッダーが読み取れたら、GRPファイルかそうじゃないか判別できると思って調査しはじめたけど、今のところヘッダーを読み取る方法はない。

PRGINSしたコードを呼び出すことができるか

昨日、いろいろ試していた結果。
あるスロットから他のスロットにPRGINSでコードを追加して、追加したコードを呼び出すことができるか、という研究。

PRGEDIT 3
FUNCNM$="_ABC"
IF !CHKCALL(FUNCNM$) THEN
 PRGINS "COMMON DEF "+FUNCNM$+"()"
 PRGINS " RETURN 1"
 PRGINS "END"
ENDIF
USE 3

PRINT CALL(FUNCNM$)  '1が表示される

ポイントは、PRGINSをした後でUSEを実行していること。
おそらく、USEでそのスロットがコンパイルされるようだ。
(その証拠にUSE 3をPRGINSより前に入れると、Undefined functionエラーになる)

第4回大喜利で入賞したLOWERDASHもこの考え方で、起動時にコードを追加している。
が、USEは何回でも呼び出せるので、プログラム中で必要な時にどんどんコードを追加するという使い方ができると思う。
現在作成中の構造体ライブラリには一部にこの考え方を使おうかと思う。

SMILE BASIC 小技(7)

テキストの表示デモの例。
昔からある技をSMILE BASICで焼き直したもの。
他にもたくさんあったと思うが、基本的なものを書いた。

今回は長いので公開キーで。
【D3KKXJAX】

1.ターミナル風 ■を付けて表示する基本型。

FOR I=0 TO LEN(T$)-1
 LOCATE X+I,Y:PRINT MID$(T$,I,1);"■";
 WAIT 2
NEXT
WAIT 30
LOCATE X+I,Y:PRINT " ";

2.真ん中から表示する 文字数が奇数/偶数を考慮する。

M1=FLOOR(LEN(T$)/2-0.5)
M2=LEN(T$) DIV 2
FOR I=0 TO FLOOR(LEN(T$)/2-0.5)
 LOCATE X+M1-I,Y:PRINT MID$(T$,M1-I,1);
 LOCATE X+M2+I,Y:PRINT MID$(T$,M2+I,1);
 WAIT 5
NEXT

3.電光掲示板風 長い文字列の一部を場所を変えながら取る。

W=20
FOR I=0 TO LEN(T$)+W*2-1
 LOCATE X,Y
 PRINT MID$(" "*W+T$+" "*W,I,W)
 WAIT 3
NEXT

4.泡のように現れる 「.oO」を連続するとアニメっぽく見える。

FOR I=0 TO LEN(T$)-1
 REPEAT
  R=RND(LEN(T$))
 UNTIL CHKCHR(X+R,Y)==0
 LOCATE X+R,Y:PRINT ".";
 WAIT 3
 LOCATE X+R,Y:PRINT "o";
 WAIT 3
 LOCATE X+R,Y:PRINT MID$(T$,R,1);
 WAIT 3
NEXT

5.回転しているように見える 「O|」で回転ぽく見える。

FOR I=0 TO 20
 LOCATE X,Y
 ATTR 4*(I MOD 4==2)
 PRINT T$*(I MOD 2==0)+"|"*LEN(T$)*(I MOD 2==1);
 WAIT 12
NEXT
ATTR 0


6.明るくなって消える 点灯の間隔で明度を表す。

FOR I=0 TO 80
 LOCATE X,Y
 PRINT T$
 WAIT 5-MIN(25,ABS(40-I)) DIV 5
 LOCATE X,Y
 PRINT " "*T$
 WAIT MIN(25,ABS(40-I)) DIV 5
NEXT

(番外)6.のGPUTCHR版 色で指定した方がクオリティが高い。

FOR I=0 TO 80
 L=MIN(255,400-ABS(40-I)*10)
 GPUTCHR X*8,Y*8,T$,RGB(L,L,L)
 WAIT 5
NEXT

3号プログラミング 覚え書き(6) スマイルボタン編

・スマイルボタンに設定したプログラムはSLOT 4で実行される。
 SLOT 4には他のスロットにはない特有の制限、機能がある。

・スマイルボタンに設定したプログラムからスロット指定なしでEXECされたプログラムもSLOT 4で実行される。
 この時、読み込まれたファイルはSLOT 4で実行されるので、SLOT 4の制限が課される。
 ただし、SLOT 0〜3にLOADして、EXEC スロット番号とする場合はこの限りではない。SLOT 0〜3に読み込まれたライブラリも同様。EXEC "PRGスロット番号:ファイル名"もスロットにロードしてからEXECするので同様。

 スマイルボタンに設定されたプログラム、および、そのプログラムからスロット指定なしでEXECされたプログラムは、いずれも動作が同じになるので、以下では「SLOT 4で実行されるプログラム 」ということにする。

・COMMON DEFが使えない
 SLOT 4で実行されるプログラム中にCOMMON DEFがあると、「Can't use in tool program」というエラーになる。

・SLOT 4でのみ、他のプロジェクトのファイルをEXECで直接実行できる
 SLOT 4で実行されるプログラムについてのみ、EXEC "プロジェクト名/ファイル名" とすると、他のプロジェクトのファイルを直接実行できる。

 なお、SLOT 0〜3でEXEC "プロジェクト名/ファイル名"を実行するとIllegal function callになる。

CHKFILEで指定するファイル名に必ずファイル種別を付ける必要がある
 以前はSLOT 4で実行する場合はファイル種別を付ける必要があったが、現在(Ver.3.2.1で確認)ではSLOT 0〜3と同様につける必要がなくなった。

SMILE BASIC 小技(6)

INC,SHIFT,UNSHIFT,PUSH,POPは文字列にも使うことができる。

VAR A$="ABC",C$

INC A$,"DEF"   '文字列の最後に追加
PRINT A$       'ABCDEF
C$=SHIFT(A$)   '文字列の先頭の一文字を取る
PRINT C$,A$    'A   BCDEF
UNSHIFT A$,"Z" '文字列の先頭に文字を付け加える
PRINT A$       'ZBCDEF
PUSH A$,"G"    '文字列の最後に文字を加える
PRINT A$       'ZBCDEFG
C$=POP(A$)     '文字列の最後の一文字を取る
PRINT C$,A$    'G   ZBCDEF

DECは文字列には使えない模様。(使い方を知ってたら教えてください。)

なお、これらの命令・関数は、文字列を参照型として扱う。
参照型とは何かをここで詳しく書くことはできないが、
概ね以下のように思っていただければよい。

通常、
VAR A$="ABC"
A$=A$+"D"
のようにすると、"ABC"とあったメモリの場所とは別の場所に”ABCD"という文字列が作成され、A$はそこを指すようになる。
これが普通の文字列の動作。

しかし、上記の参照型の命令(例えばINC)の場合、"ABC"とあったメモリの位置に"D"が追加されて、結果として"ABCD"になる。

これはPRINT命令でA$を表示した結果は同じなので、まったく同じことのようだが、別の変数に参照を代入した場合に違いが出てくる。

VAR A$="ABC"
VAR B$=A$
A$=A$+"D"
PRINT A$  'ABCD
PRINT B$  'ABC
VAR A$="ABC"
VAR B$=A$
INC A$,"D"
PRINT A$  'ABCD
PRINT B$  'ABCD

ここで詳しく説明できないので、詳細は別項を立てる。