|
 |
|
2017/4/27(Thu) 21:36:39|NO.79332
少しお久しぶりです。
シューティングゲームでリプレイ機能を追加したいと思い制作しているのですが、
わからないことがあったのでご質問させていただきます。
他のサイト様などを参考に下記のソースを作ったのですが、
JI_ido_kioku = "JK_JK.dat"
JI_TM_kioku = "JK_TM.dat"
SHT_kioku = "SHT.dat"
の記録方法だとファイルが3つ生成されます。
「ボム、Ctrlキー」も記憶したいので5つになってしまいます・・・・(ボムはXキー)
リプレイファイルは5個ぐらいまで別々に保存したいと思っているので、
5(.dat)*5(種類)=25個がフォルダ内に生成されてしまうので、さすがに困るので解決方法を探しております。
「sdim、poke、peek」は初めて使う命令で、
非効率的だと思うわれるし、やり方が間違っていると思うので、そこもご指摘いただけたら助かります。
それではよろしくお願いいたします。
*プレイモード
screen 0,240,320
;リプレイ
sdim JI_replay,32000
sdim TM_replay,32000
sdim SHT_replay,32000
JI_ido_kioku = "JK_JK.dat"
JI_TM_kioku = "JK_TM.dat"
SHT_kioku = "SHT.dat"
JI_timer = 0 ;自機タイマー
TM_timer = 0 ;弾タイマー
SHT_timer = 0 ;シフトタイマー
dialog "「はい」:ゲームプレイ / 「いいえ」:リプレイ再生",2
if stat = 6 : playmode = 0 ;「はい」をおした時
if stat = 7 : playmode = 1 : gosub *ロードする ;「いいえ」をおした時
;*******************************
JIKI_x = 112 : JIKI_y = 304 ;自機の位置
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
pos 0,0 : mes "十 "+ key
pos 0,20 : mes "Z "+ keyZ
pos 0,40 : mes "Skey "+ Skey
pos 0,60 : mes "タイマ "+ JI_timer
pos 0,80 : mes "TMタイマ "+ TM_timer
pos 0,100 : mes "SHTタイマ "+ SHT_timer
pos 0,120 : mes "モード "+ playmode
;***********************
gosub *自機移動
gosub *自機弾の移動
JI_timer = JI_timer + (JI_timer < 32000) ;自機タイマー加算
TM_timer = TM_timer + (TM_timer < 32000) ;弾タイマー加算
SHT_timer = SHT_timer + (SHT_timer < 32000) ;シフトタイマー加算
;自機
pos JIKI_x,JIKI_y
color ,255,255 : mes "■"
;自機弾
if JKSO_f = 1 {
pos JKSO_x,JKSO_y
color 255,255 : mes "▲"
}
;低速ショット
if TISK_f = 1 {
pos TISK_x-20,TISK_y
color 255 : mes "● ●"
}
stick en,32 ;エンターキー
if en : gosub *終了
redraw 1 : await 1
goto *メイン
;*******************************
*自機移動
if playmode = 0 : stick key,15 ;「はい」を押している場合
if key & 1 : JIKI_x- = 1
if key & 4 : JIKI_x+ = 1
if key & 2 : JIKI_y- = 1
if key & 8 : JIKI_y+ = 1
if playmode = 0 : poke JI_replay,JI_timer,key ;バッファに1byte書き込み (「はい」を押している場合)
if playmode = 1 : key = peek(JI_replay,JI_timer) ;バッファから1byte読み出し (「いいえ」を押している場合)
return
;************自機弾の移動***************
*自機弾の移動
if playmode = 0 : getkey keyZ,90 ;Zキー (「はい」を押している場合)
if keyZ AND JKSO_f = 0 {
JKSO_f = 1 ;自機弾フラグを「立てる」
JKSO_x = JIKI_x
JKSO_y = JIKI_y
TISK_DL_f = 1 ;低速玉が出るフラグを「立てる」
} else {
TISK_DL_f = 0
}
if JKSO_f = 1 : JKSO_y -= 1;↑に移動
if JKSO_y < 0 : JKSO_f = 0 ;一番上までいったら自機弾を「戻す」
if playmode = 0 : poke TM_replay,TM_timer,keyZ ;バッファに1byte書き込み (「はい」を押している場合)
if playmode = 1 : keyZ = peek(TM_replay,TM_timer) ;バッファから1byte読み出し (「いいえ」を押している場合)
;**************低速ショット*************
if playmode = 0 : getkey Skey,16 ;シフトキー (「はい」を押している場合)
if Skey AND TISK_f = 0 AND TISK_DL_f = 1 { ;シフトキーが押されている、低速ショットがない、低速玉が出るフラグが立った時
TISK_f = 1 ;低速ショットフラグを「立てる」
TISK_x = JIKI_x
TISK_y = JIKI_y
}
if TISK_f = 1 : TISK_y -= 1 ;↑に移動
if TISK_y < 0 : TISK_f = 0 ;一番上まで行ったら低速ショットを「戻す」
if playmode = 0 : poke SHT_replay,SHT_timer,Skey ;バッファに1byte書き込み (「はい」を押している場合)
if playmode = 1 : Skey = peek(SHT_replay,SHT_timer) ;バッファから1byte読み出し (「いいえ」を押している場合)
return
;*******************************
*ロードする
; bload "replay1.dat", 記録したデータ, ロードサイズ
bload JI_ido_kioku, JI_replay, 32000 ;自機移動
bload JI_TM_kioku, TM_replay, 32000 ;自機弾
bload SHT_kioku, SHT_replay, 32000 ;シフトキー
return
;*******************************
*終了
if playmode = 0 {;「はい」を押した場合
; bload "replay1.dat", 記録したデータ, セーブサイズ
bsave JI_ido_kioku, JI_replay, 32000;自機移動
bsave JI_TM_kioku, TM_replay, 32000 ;自機弾
bsave SHT_kioku, SHT_replay, 32000 ;シフトキー
}
goto *プレイモード

| |
|
2017/4/27(Thu) 22:06:21|NO.79333
こんな感じでどうでしょう?
*プレイモード
screen 0,240,320
;リプレイ
;確保する猟が少ないので、このままだとオーバーフローします。
;memexpand等を使い、適度に再確保してください。
sdim replay,32000
kioku = "replay.dat"
JI_timer = 0 ;自機タイマー
TM_timer = 0 ;弾タイマー
SHT_timer = 0 ;シフトタイマー
ct=0;データを書き込む位置を記録しておきます。
dialog "「はい」:ゲームプレイ / 「いいえ」:リプレイ再生",2
if stat = 6 : playmode = 0 ;「はい」をおした時
if stat = 7 : playmode = 1 : gosub *ロードする ;「いいえ」をおした時
;*******************************
JIKI_x = 112 : JIKI_y = 304 ;自機の位置
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
pos 0,0 : mes "十 "+ key
pos 0,20 : mes "Z "+ keyZ
pos 0,40 : mes "Skey "+ Skey
pos 0,60 : mes "タイマ "+ JI_timer
pos 0,80 : mes "TMタイマ "+ TM_timer
pos 0,100 : mes "SHTタイマ "+ SHT_timer
pos 0,120 : mes "モード "+ playmode
;***********************
gosub *自機移動
gosub *自機弾の移動
JI_timer = JI_timer + (JI_timer < 32000) ;自機タイマー加算
TM_timer = TM_timer + (TM_timer < 32000) ;弾タイマー加算
SHT_timer = SHT_timer + (SHT_timer < 32000) ;シフトタイマー加算
;自機
pos JIKI_x,JIKI_y
color ,255,255 : mes "■"
;自機弾
if JKSO_f = 1 {
pos JKSO_x,JKSO_y
color 255,255 : mes "▲"
}
;低速ショット
if TISK_f = 1 {
pos TISK_x-20,TISK_y
color 255 : mes "● ●"
}
;stickの使い方が間違っていたので修正しました。
;詳しくはHDL参照
stick en,32 ;エンターキー
if en&32: gosub *終了
redraw 1 : await 1
goto *メイン
;*******************************
*自機移動
if playmode = 0 : stick key,15 ;「はい」を押している場合
if key & 1 : JIKI_x- = 1
if key & 4 : JIKI_x+ = 1
if key & 2 : JIKI_y- = 1
if key & 8 : JIKI_y+ = 1
if playmode = 0 : poke replay,ct,key;バッファに1byte書き込み (「はい」を押している場合)
if playmode = 1 : key = peek(replay,ct) ;バッファから1byte読み出し (「いいえ」を押している場合)
ct+1
return
;************自機弾の移動***************
*自機弾の移動
if playmode = 0 : getkey keyZ,90 ;Zキー (「はい」を押している場合)
if keyZ AND JKSO_f = 0 {
JKSO_f = 1 ;自機弾フラグを「立てる」
JKSO_x = JIKI_x
JKSO_y = JIKI_y
TISK_DL_f = 1 ;低速玉が出るフラグを「立てる」
} else {
TISK_DL_f = 0
}
if JKSO_f = 1 : JKSO_y -= 1;↑に移動
if JKSO_y < 0 : JKSO_f = 0 ;一番上までいったら自機弾を「戻す」
if playmode = 0 : poke replay,ct,keyZ ;バッファに1byte書き込み (「はい」を押している場合)
if playmode = 1 : keyZ = peek(replay,ct) ;バッファから1byte読み出し (「いいえ」を押している場合)
ct+1
;**************低速ショット*************
if playmode = 0 : getkey Skey,16 ;シフトキー (「はい」を押している場合)
if Skey AND TISK_f = 0 AND TISK_DL_f = 1 { ;シフトキーが押されている、低速ショットがない、低速玉が出るフラグが立った時
TISK_f = 1 ;低速ショットフラグを「立てる」
TISK_x = JIKI_x
TISK_y = JIKI_y
}
if TISK_f = 1 : TISK_y -= 1 ;↑に移動
if TISK_y < 0 : TISK_f = 0 ;一番上まで行ったら低速ショットを「戻す」
if playmode = 0 : poke replay,ct,Skey ;バッファに1byte書き込み (「はい」を押している場合)
if playmode = 1 : Skey = peek(replay,ct) ;バッファから1byte読み出し (「いいえ」を押している場合)
ct+1
return
;*******************************
*ロードする
; bload "replay1.dat", 記録したデータ, ロードサイズ
bload kioku, replay, 320000 ;自機移動
return
;*******************************
*終了
if playmode = 0 {;「はい」を押した場合
; bload "replay1.dat", 記録したデータ, セーブサイズ
bsave kioku, replay, 32000;自機移動
}
goto *プレイモード

| |
|
2017/4/27(Thu) 22:18:59|NO.79334
書き忘れました。
>>「sdim、poke、peek」は初めて使う命令で、
>>非効率的だと思うわれるし、やり方が間違っていると思うので、そこもご指摘いただけたら助かります。
いいえ、プレイを保存する方法としてpoke peekの使用は最適です。
コメントに変換ミスがありました。
×確保する猟が少ないので
○確保する量が少ないので
|
|
2017/4/28(Fri) 00:33:55|NO.79335
リプレイ機能が正常に実プレイを再現できていない可能性が高そうですよ?
自機移動、自機弾の移動のサブルーチン内で
1."実キー"入力検出 (ゲームプレイ)
2.入力に対する応答(移動処理等)
3."実キー"入力保存処理
4."仮想キー"入力検出 (リプレイ再生)
という順番になっていて、リプレイ再生時とゲームプレイ時では入力に対する応答処理が1ループ遅れています。
多分、[4]の処理を[1]と[2]の間に持ってくるほうがよさそう?
さらに、[3]は[1]の後ならどこでもいいです。
で、ついでにあちこちに分岐があるとややこしい(と思う)ので、
キー入力部分を纏める方向でリファクタリングしてみたら、こんな感じですか。
// ## メイン以前は省略
*メイン
redraw 0 : color : boxf
;********カウンター***********
// ## ながくなるので描画部分省略
;***********************
gosub *入力処理 // 追加
gosub *自機移動
gosub *自機弾の移動
JI_timer = JI_timer + (JI_timer < 32000) ;自機タイマー加算
TM_timer = TM_timer + (TM_timer < 32000) ;弾タイマー加算
SHT_timer = SHT_timer + (SHT_timer < 32000) ;シフトタイマー加算
// ## ながくなるので描画部分省略
stick en,32 ;エンターキー
if en : gosub *終了
redraw 1 : await 1
goto *メイン
// ## ここから追加エリア
*入力処理
// 変数名として key、keyZよりも key_arrow、key_shoot等を推奨する。
if ( playmode == 0 ){
// キーボードからの入力。
stick key,15
getkey keyZ,90 // 'Z'
getkey Skey,16
// 入力の保存
poke JI_replay, JI_timer,key
poke TM_replay, TM_timer,keyZ
poke SHT_replay,SHT_timer,Skey
}
if ( playmode == 1 ){
// リプレイ情報からの読み出し
key = peek( JI_replay, JI_timer)
keyZ = peek( TM_replay, TM_timer)
Skey = peek(SHT_replay,SHT_timer)
}
return
// ## ここまで追加エリア
*自機移動
// if playmode = 0 : stick key,15
if key & 1 : JIKI_x- = 1
if key & 4 : JIKI_x+ = 1
if key & 2 : JIKI_y- = 1
if key & 8 : JIKI_y+ = 1
// if playmode = 0 : poke JI_replay,JI_timer,key
// if playmode = 1 : key = peek(JI_replay,JI_timer)
return
;************自機弾の移動***************
*自機弾の移動
// if playmode = 0 : getkey keyZ,90
if keyZ AND JKSO_f = 0 {
JKSO_f = 1 ;自機弾フラグを「立てる」
JKSO_x = JIKI_x
JKSO_y = JIKI_y
TISK_DL_f = 1 ;低速玉が出るフラグを「立てる」
} else {
TISK_DL_f = 0
}
if JKSO_f = 1 : JKSO_y -= 1;↑に移動
if JKSO_y < 0 : JKSO_f = 0 ;一番上までいったら自機弾を「戻す」
// if playmode = 0 : poke TM_replay,TM_timer,keyZ
// if playmode = 1 : keyZ = peek(TM_replay,TM_timer)
;**************低速ショット*************
// if playmode = 0 : getkey Skey,16
if Skey AND TISK_f = 0 AND TISK_DL_f = 1 { ;シフトキーが押されている、低速ショットがない、低速玉が出るフラグが立った時
TISK_f = 1 ;低速ショットフラグを「立てる」
TISK_x = JIKI_x
TISK_y = JIKI_y
}
if TISK_f = 1 : TISK_y -= 1 ;↑に移動
if TISK_y < 0 : TISK_f = 0 ;一番上まで行ったら低速ショットを「戻す」
// if playmode = 0 : poke SHT_replay,SHT_timer,Skey
// if playmode = 1 : Skey = peek(SHT_replay,SHT_timer)
return
// ## 入力と直結しないので以降は省略
すると、メモリ操作系統(peek、poke命令)がbsaveやbloadを行う箇所と同じように一か所に集まる。
これで少し考えやすくなります。
スペースさんのコードのうち、メインエリア内の変更を示すとこんな感じ。
*入力処理
if ( playmode == 0 ){
// キーボードからの入力。
stick key,15
getkey keyZ,90 // 'Z'
getkey Skey,16
// 入力の保存
poke replay,ct ,key
poke replay,ct+1,keyZ
poke replay,ct+2,Skey
}
if ( playmode == 1 ){
// リプレイ情報からの読み出し
key = peek(replay,ct )
keyZ = peek(replay,ct+1)
Skey = peek(replay,ct+2)
}
ct += 3
return
更に以下の点も吟味するべきでしょうか。
・ビット演算等で保存データサイズを減らせます。無理のない範囲で積極的に攻めてみましょう。
・データの長さ(容量)は記録したデータの長さだけあればいいはずです。
保存サイズ、読み込みサイズなどを工夫してみましょう。
・playmodeの0と1は#enum等を使うことで読みやすくできる可能性があります。
>スペースさん
多分そういう実装で問題ないとこちらも思いますが、
その実装の意図が回答者に通じていない気がします。

| |
|
2017/4/28(Fri) 19:53:18|NO.79343
スペースさん返答ありがとうございます!
なるほど「ct」が1ずつ増加するので、バッファに1ずつずれて記憶されるんですね。
また、stickの使い方が間違っている指摘もありがとうございます。
本命のソースでもいくつかありそうなので、見直してきます・・・
ちゃんと本命でも動くのかテストするので、解決までは少々お時間いただきます。
|
|
2017/4/28(Fri) 22:29:20|NO.79351
掘木さん返答ありがとうございます!ソースも助かります。
>>リプレイ機能が正常に実プレイを再現できていない可能性が高そうですよ?
元のソースを何度かやってたら、微妙に動きが再現できなかったことがありました。
>>1."実キー"入力検出 (ゲームプレイ)
>>2.入力に対する応答(移動処理等)
>>3."実キー"入力保存処理
>>4."仮想キー"入力検出 (リプレイ再生)
>>という順番になっていて、リプレイ再生時とゲームプレイ時では入力に対する応答処理が1ループ遅れています。
>>多分、[4]の処理を[1]と[2]の間に持ってくるほうがよさそう?
>>さらに、[3]は[1]の後ならどこでもいいです。
元のソースだと「メインループ→gosubで1つのキー入力を保存読み出し→繰り返し」だと、確かにずれそうですね。
掘木さんのだと「メインループ→gosubで全てのキー入力を保存読み出し」で先に処理しているため、ずれることがなさそうです。
実は「poke」「 peek」の処理をgosubの先に1つにまとめたいなと思っていました。
また、ロードとする際に初期化が必要だったため追加しました。
さらに、下記の部分を「gosub」から「goto」に修正しました。
if stat = 6 : playmode = 0 : goto *メイン ;「はい」をおした時
if stat = 7 : playmode = 1 : goto *ロードする ;「いいえ」をおした時
;↑がgosubだと↑のreturnが無いまま、違うgosubの処理が入るため、gotoの方が適切と思われる
>>・データの長さ(容量)は記録したデータの長さだけあればいいはずです。保存サイズ、読み込みサイズなどを工夫してみましょう。
「if en&32 : gosub *終了」を「if en&32 OR ki_iti >= 4000 : gosub *終了」にして一時的に対応。
掘木さんとスペースさんのソースなどを参考にして修正しました。
本命のソースには一切適応していないため、解決まで少々(かなり)お時間がかかると思います。
*プレイモード
screen 0,240,320
;確保する量が少ないので、このままだとオーバーフローします。
;memexpand等を使い、適度に再確保してください。
;リプレイ
sdim replay,32000
kioku = "replay.dat"
ki_iti = 0 ;データを書き込む位置を記録
JIKI_x = 112 : JIKI_y = 304 ;自機位置
dialog "「はい」:ゲームプレイ / 「いいえ」:リプレイ再生",2
if stat = 6 : playmode = 0 : goto *メイン ;「はい」をおした時
if stat = 7 : playmode = 1 : goto *ロードする ;「いいえ」をおした時
;↑がgosubだと↑のreturnが無いまま、違うgosubの処理が入るため、gotoの方が適切と思われる
;***********ロードする*************
*ロードする
;初期化する(追加)
JIKI_x = 112;自機位置
JIKI_y = 304;自機位置
JKSO_f = 0 ;自機弾フラグ
JKSO_x = 0 ;自機弾X
JKSO_y = 0 ;自機弾Y
TISK_f = 0 ;低速ショットフラグ
TISK_DL_f = 0;低速玉が出るフラグ
TISK_x = 0 ;低速玉X
TISK_y = 0 ;低速玉Y
; bload "replay1.dat", 記録したデータ, ロードサイズ
bload kioku, replay, 320000
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
pos 0,0 : mes "十 "+ key
pos 0,20 : mes "Z "+ keyZ
pos 0,40 : mes "Skey "+ Skey
pos 0,60 : mes "ki_iti "+ ki_iti
pos 0,80 : mes "モード "+ playmode
;***********************
gosub *入力処理
gosub *自機移動
gosub *自機弾の移動
;自機
pos JIKI_x,JIKI_y
color ,255,255 : mes "■"
;自機弾
if JKSO_f = 1 {
pos JKSO_x,JKSO_y
color 255,255 : mes "▲"
}
;低速ショット
if TISK_f = 1 {
pos TISK_x-20,TISK_y
color 255 : mes "● ●"
}
stick en,32 ;エンターキー
if en&32 OR ki_iti >= 4000 : gosub *終了
/*/
・データの長さ(容量)は記録したデータの長さだけあればいいはずです。保存サイズ、読み込みサイズなどを工夫してみましょう。
→「OR ki_iti >= 4000」時間で制御してデータが膨らまないように対応)(数値は仮)
(まだテストソースなので、本命ソースに適応できるかは不明)
/*/
redraw 1 : await 1
goto *メイン
;***********************
*入力処理
if (playmode == 0) {
;各キー
stick key,15
getkey keyZ,90
getkey Skey,16
;入力の保存
poke replay,ki_iti ,key
poke replay,ki_iti+1,keyZ
poke replay,ki_iti+2,Skey
}
;入力の読み出し
if (playmode == 1) {
key = peek(replay,ki_iti )
keyZ = peek(replay,ki_iti+1)
Skey = peek(replay,ki_iti+2)
}
ki_iti+3
return
;*************自機移動*****************
*自機移動
if key & 1 : JIKI_x- = 1
if key & 4 : JIKI_x+ = 1
if key & 2 : JIKI_y- = 1
if key & 8 : JIKI_y+ = 1
return
;************自機弾の移動***************
*自機弾の移動
if keyZ AND JKSO_f = 0 {
JKSO_f = 1 ;自機弾フラグを「立てる」
JKSO_x = JIKI_x
JKSO_y = JIKI_y
TISK_DL_f = 1 ;低速玉が出るフラグを「立てる」
} else {
TISK_DL_f = 0
}
if JKSO_f = 1 : JKSO_y -= 1;↑に移動
if JKSO_y < 0 : JKSO_f = 0 ;一番上までいったら自機弾を「戻す」
;**************低速ショット*************
if Skey AND TISK_f = 0 AND TISK_DL_f = 1 { ;シフトキーが押されている、低速ショットがない、低速玉が出るフラグが立った時
TISK_f = 1 ;低速ショットフラグを「立てる」
TISK_x = JIKI_x
TISK_y = JIKI_y
}
if TISK_f = 1 : TISK_y -= 1 ;↑に移動
if TISK_y < 0 : TISK_f = 0 ;一番上まで行ったら低速ショットを「戻す」
return
;************終了**************
*終了
if playmode = 0 {;「はい」を押した場合
; bload "replay1.dat", 記録したデータ, セーブサイズ
bsave kioku, replay, 320000
}
goto *プレイモード

| |
|
2017/4/29(Sat) 12:32:06|NO.79358
stick が getkey と同じ動作をしているので、すべてを getkey で取得してみたサンプル
*データ初期化
sdim Playlog,32000
poke Playlog,0,128
*プレイモード
FrameCount = 0
dialog "「はい」:ゲームプレイ / 「いいえ」:リプレイ再生",2
if stat = 6 : playmode = 0 : title "プレイモード" : goto *メイン
if stat = 7 : playmode = 1 : title "リプレイモード" : goto *メイン
stop
*メイン
redraw 0
color 0,0,0 : boxf : color 255,255,255
DWORD = 0
if playmode = 0{
//プレイモード
getkey ValueKey,16 : if ValueKey : DWORD |= 1 << 0
getkey ValueKey,37 : if ValueKey : DWORD |= 1 << 1
getkey ValueKey,38 : if ValueKey : DWORD |= 1 << 2
getkey ValueKey,39 : if ValueKey : DWORD |= 1 << 3
getkey ValueKey,40 : if ValueKey : DWORD |= 1 << 4
getkey ValueKey,90 : if ValueKey : DWORD |= 1 << 5
getkey ValueKey,13 : if (ValueKey)||(FrameCount == 31999) : DWORD |= 1 << 7
poke Playlog,FrameCount,DWORD
} else {
//リプレイモード
DWORD = peek(Playlog,FrameCount)
}
if (DWORD & 1) : mes "Shiftキーが押されています"
if (DWORD & 2) : mes "←キーが押されています"
if (DWORD & 4) : mes "↑キーが押されています"
if (DWORD & 8) : mes "→キーが押されています"
if (DWORD & 16) : mes "↓キーが押されています"
if (DWORD & 32) : mes "Zキーが押されています"
if (DWORD & 128) : dialog "プレイ・リプレイが終了しました。" : goto *プレイモード
pos 0,0 : mes "プレイモード "+playmode
pos 0,15 : mes "入力ビット "+DWORD
pos 0,30 : mes "フレーム "+FrameCount
FrameCount++
redraw 1
await 10
goto *メイン

| |
|
2017/4/29(Sat) 18:46:46|NO.79368
MillkeySoftwさんありがとうございます!
ビット計算は一度も使ったことがなく、
if ValueKey : DWORD | = 1 << 0
の部分がなんで動くのか、なんでそういう数値が返されるのか、現地点ではわかりませんでした。
特に「DWORD | = 1」がどういう処理なのかわからないです(´・ω・`)
DWORD | = 1 << 0 ;1
mes "0 " + DWORD
DWORD1 | = 1 << 1 ;2
mes "1 " + DWORD1
DWORD2 | = 1 << 2 ;4
mes "2 " + DWORD2
DWORD3 | = 1 << 3 ;8
mes "3 " + DWORD3
DWORD4 | = 1 << 4 ;16
mes "4 " + DWORD4
DWORD5 | = 1 << 5 ;32
mes "5 " + DWORD5
DWORD6 | = 1 << 6 ;64
mes "6 " + DWORD6
DWORD7 | = 1 << 7 ;128
って動いているのはわかるのですが、初めて見る処理の仕方なので、適応できるのかわからないです。
ビット計算を使う「ルール、メリット、デメリット」など把握してから適応しようかと思います。
なので、これに対する返答がしっかりと出来ないままになるかと思われます(´・ω・`)
すいません。けれどソースものすごくありがたいのです(`・ω・´)
|
|
2017/4/29(Sat) 22:18:25|NO.79372
ビットシフトは、普通に 「HSP ビット演算」で検索すると出てくるよ。
検索で出てきた説明を見た方がわかりやすいのでここではあえて答えません。
尚、サンプルとして投稿した内容は、掘木さんが言っていた
>>・ビット演算等で保存データサイズを減らせます。無理のない範囲で積極的に攻めてみましょう。
の応用です。
1種類のキーを 1ビットの ON / OFF に置き換えているのです。
主のスクリプトだと、十字キーの 4種類と SHIFT と Z なので、合計 6 種類
6種類をビット数に置き換えると、6ビットなので、1バイト 8ビットに収まります。
HSP で扱える最小単位が peek の 1バイトですので、最小単位の 1バイトが 1フレームのデータとなっています。
|
|
2017/5/6(Sat) 14:31:57|NO.79568
MillkeySoftwさん補足ありがとうございます!
超遅くなりましたけど、ビット計算すごく必要なことがわかりました。
あれから、「難易度、日付、点数」などを読み込めるように処理してました。
難易度は「0、1」などで判定できるので、1ビット計算で大丈夫なんですが、
日付の年が「2017」なので、pokeの扱える数値「255」を超えてしまいます。
「lpoke」を使えば「4294967295」まで収納できるのですが、4づつ加算していくのはあまりにも不毛すぎるので、
可能ならビット計算をして1ビットに収めようかと思います。
ミニソースで「点数」の処理をしてたのですが1点だったので「255」を超えることがなくって、
日付だけうまくいかないから何かと思ったらこんな単純なこととは・・・(今更)
ビット計算を今から勉強するので使いこなすまでには時間がかかると思います。
すいません解決まではまだです・・・中間報告っぽくなります(´・ω・`)
約1週間格闘してこれorz
|
|
2017/5/6(Sat) 21:55:57|NO.79577
>>NO.79568 アイドルさん
年が2000以上で1バイトに入らないのなら、下二桁だけ保存してしまっても構わないのだぞ。
…といいたいところなのですが、不毛なのはそのデータ構造のほうです…。
4ずつ増えると言ったりしているてことは、キー情報と一緒に1フレームごとに保存しようとしてますよねそれ。
落ち着いて考えよう。難易度なんてゲーム開始時に決定したら変わらないよね?
日付を記録するのも別に日付を跨いでゲームやってたのが記録されても嬉しくないよ。
大体いつ頃やったやつか分かればいいのでしょう。開始か終了かわからんけどもどっちかでいいっしょ。
そういう、ファイルデータに対して1個あれば十分な情報ってのはそれなりにある。
スコアもきっと最終スコアが分かれば十分じゃないかな。
リプレイ再生すれば得点は実際にプレイしたのと同じように加点されていくのだから。
これなら、年を保存するのに4バイト掛かろうが1バイトに縮めようが、全体のサイズとして3バイトしか変わらない。
こういうデータを纏めたエリアをヘッダと呼んだりする。
逆にキー情報はすべてのフレーム保存しなきゃならないので、3バイトが1バイトに縮むと容量として3分の1近くに縮む。
ヘッダを用意するときは、メモリマップをメモで残しておきましょう。
バイト| +0 +1 +2 +3
------+------------------------------------
0 |[ 年 ] [ 月 ] [ 日 ]
4 |[ 最終スコア ]
8 |[難易度] [ 武器 ] [ データ長 ]
12 |[ 開始乱数 ] [チェックコード ]
16 |[ F 1 ] [ F 2 ] [ F 3 ] [ F 4 ]
20 |[ F 5 ] [ F 6 ] [ F 7 ] [ F 8 ]
・・・・・・・・・・・・・・・・
キー情報を読み込みを16バイト目からにして、それより前にスコアなどの情報を用意したメモリマップの記述例。
並べ方とか何を入れるかは自由なんであくまで一例。
読み込み方法とかは考えよう。
|
|
2017/5/7(Sun) 11:05:15|NO.79584
参考までに私が実際に自作STGに使っているリプレイデータの保存部分の抜粋です。
堀木さんの書き込みと同じ原理で、ファイル冒頭部分に乱数のシード値や
スコアといった情報をまとめたヘッダ部分を保存し、フレームごとのキー入力情報は
ファイルの先頭から64バイト目以降に保存しています。
キー入力情報は別途sdimに確保したメモリに、1フレームにつき1バイトでpokeで書き込んでいます
#define REPLAYDATA_OFFSET 64 ;リプレイデータのオフセット(バイト)
#define REPLAY_BUF_SIZE 131072 ;リプレイデータを記録するバッファの長さ(フレーム数):約36分
;保存に必要なメモリの確保
dim ReplayFileHeader,REPLAYDATA_OFFSET/4;リプレイファイルヘッダ用配列
sdim ReplayDataBuf,REPLAY_BUF_SIZE ;リプレイデータを記録するメモリバッファ
;------------------------------------------------------------------
;リプレイファイルを保存するサブ
;------------------------------------------------------------------
*ReplaySaveSub
;ヘッダ作成
ReplayFileHeader(0)=RndSeed ;乱数シード値
ReplayFileHeader(1)=HiScore(GameMode) ;ハイスコア
ReplayFileHeader(2)=(DAY<<24)+(MONTH<<16)+YEAR ;日付
ReplayFileHeader(3)=(SECOND<<24)+(MINUTE<<16)+TIME ;時刻
ReplayFileHeader(4)=AveFPS ;平均FPS
ReplayFileHeader(5)=Version ;ソフトウェアのバージョン
;保存
FileName=dir_cur+"/user/replay_"+GameMode+".dat"
bsave FileName,ReplayFileHeader
await 0
bsave FileName,ReplayDataBuf,,REPLAYDATA_OFFSET
return
再生時には逆に、
ヘッダから必要な情報を読み出し変数にセットした後、
フレームごとにキー入力情報をpeekで読み出す、という流れになります。
参考になれば。

| |
|
2017/5/7(Sun) 11:08:27|NO.79585
訂正
誤)キー入力情報は別途sdimに確保したメモリに、1フレームにつき1バイトでpokeで書き込んでいます
正)キー入力情報はsdimに確保したメモリ(ReplayDataBuf)に、1フレームにつき1バイトでpokeで書き込んでいます
|
|
2017/5/7(Sun) 16:11:34|NO.79589
掘木さんありがとうございます。
>>年が2000以上で1バイトに入らないのなら、下二桁だけ保存してしまっても構わないのだぞ。
「gettime」で2017を取得して、-2000すれば17て表示されるので、
頭に20を表示させるか、20の部分は表示されない仕様にしていいと思っています。
;日付取得
repeat 4
HIZUK(cnt) = gettime(cnt)
loop
HIZUK(0)-2000;255以内に収めるため-2000する
>>4ずつ増えると言ったりしているてことは、キー情報と一緒に1フレームごとに保存しようとしてますよねそれ。
そうです(´・ω・`)
リプレイ選択画面で「日付、点数、難易度、キャラクター」などの情報も出せたらいいなーって思ってたので、
リプレイのファイルに「キー入力、日付、点数、難易度、キャラクター」を保存して読み込もうと思ってました。
ゲーム内の数値をリプレイファイルに入れる変数に代入する(例:GM_SKOA→RP_SKOA)
リプレイ選択画面では最終スコアの8桁を表示。
リプレイ再生されたらゲーム内の変数だけ初期化、動きを読み込めばゲーム内だけ点数が加算されることはわかっています。
>>日付を記録するのも別に日付を跨いでゲームやってたのが記録されても嬉しくないよ。
STGの場合そうもいかないんですよ・・・
スコアが重要なSTGでどれだけその点数に到達できたのかってユーザーにとっては重要な要素なので、
可能であれば追加してあげたいのです。
ですが、自分が求めた分、その分難しいのが返ってくるということでもあるので、
今の自分ではできそうもなかったら、スコアと日付だけ取らないで処理することも考えています。
>>こういうデータを纏めたエリアをヘッダと呼んだりする。
>>ヘッダを用意するときは、メモリマップをメモで残しておきましょう。
ほ、ほぇ〜。知らないことが増えてしまった・・・
何かしら管理は必要とは思ってたので参考になります。
|
|
2017/5/7(Sun) 16:41:43|NO.79591
いやいや誤解してませんかね?(横から)
>>>>日付を記録するのも別に日付を跨いでゲームやってたのが記録されても嬉しくないよ。
>>STGの場合そうもいかないんですよ・・・
>>スコアが重要なSTGでどれだけその点数に到達できたのかってユーザーにとっては重要な要素なので、
>>可能であれば追加してあげたいのです。
これ、「開始時刻」のみ記録しておけばいいよね。毎フレーム日付データいらないよね? っていう話です。
毎フレームに時刻データは無駄ですから。開始地点の日付時刻さえわかっていればプレイ中の日付時刻は計算できますし。
まず、記録に必要なデータをざっくり読んで上げてみますと、以下の通り。
>リプレイタイトルに日付、点数、難易度、キャラクター
>リプレイデータにキー入力、日付、点数、難易度、キャラクター
となっています。
ここでデータ構成をしていくと、リプレイデータのヘッダ(先頭)に必要なデータは
「日付、点数、難易度、キャラクター」となります。
仮に乱数を利用している場合は、使用した乱数の初期化データも必要になります。
//リプレイ中に再現しなければならないため
そして、毎フレームのデータになりますが、
>キー入力、日付、点数、難易度、キャラクター
ここから、日付、点数、難易度、キャラクターは取り除けます
(日付・点数は計算で出せますし、難易度はリプレイ中は変わらないはず。キャラクターも変わらないならいらない)
こうして、毎フレームのキー入力さえ保存すれば良くなります。
|
|
2017/5/7(Sun) 17:49:56|NO.79594
最初にどれをリプレイデータで保存したいか整理すればいいんじゃないの?
まずは、主が保存したいように保存してみればいい。
その後に一つのリプレイデータの保存サイズが大きすぎればその分節約を考えればいいし。
そんなに大きくないと思うならそのままでいいし。
無理に考える必要もないと思う。
|
|
2017/5/7(Sun) 21:56:18|NO.79597
Velgailさん。
>>これ、「開始時刻」のみ記録しておけばいいよね。毎フレーム日付データいらないよね? っていう話です。
>>毎フレームに時刻データは無駄ですから。開始地点の日付時刻さえわかっていればプレイ中の日付時刻は計算できますし。
あぁ、これに関しては大丈夫です!わかってます!
かなりまどろっこしくなってしまい申し訳ないです。
次レスあたりにまとめます。
MillkeySoftwさん。
>>最初にどれをリプレイデータで保存したいか整理すればいいんじゃないの?
>>まずは、主が保存したいように保存してみればいい。
確かにそうでしたね(´・ω・`)
まずはべたねたな打ち方でもいいから書いてみて、困ったところを提示した方がよかったです。
|
|
2017/5/8(Mon) 21:40:02|NO.79609
すいません。まとめられました。
・最初に質問した、保存読み出しは「NO.79351」で解決している。
(本命ソースでは動くか心配だったため解決に入れてない)
>>本命のソースには一切適応していないため、解決まで少々(かなり)お時間がかかると思います。
・ビット計算
使ったこともなく、サイトも見ていたんだけど理解できていない
>>「sdim、poke、peek」は初めて使う命令で、
(↑このぐらいのレベルで、ついでに「マクロ、モジュール」も使ったことがない)
・「日付、点数」で、「poke」の扱える数値「255」を越えてしまう。
「lpeek」を使うか、短縮できないか調べてから再度聞くつもりでした。
(日付に関しては下記で対応できるけど、ハイスコアがわからない)
>>「gettime」で2017を取得して、-2000すれば17て表示されるので、
>>頭に20を表示させるか、20の部分は表示されない仕様にしていいと思っています。
■結論■
「lpeek」使う場合、4つづつずらさないといけないので、その分加算されてしまいデータが膨らむおそれがある。
短縮する方法を自分が出来る範囲なら対応(ハイスコアが該当)
(短縮するヒントは「NO.79358」からあると思うので、聞かずにやってました)
|
|
2017/5/8(Mon) 21:45:58|NO.79610
●ソース●
・「poke」では「255」までしか扱えないので、「lpeek」を使って確保してあります(これならハイスコアに対応できます)
・リプレイファイルは3つまで保存できる予定ですが、ミニソースでは2つ保存できる用にしてあります。
・「リプレイファイル選択」では、選択されたファイルの「日付、ハイスコア、難易度、キャラクター」を表示させるつもり。
(ミニソースではデバックのため、最初っから表示させてあります)
・1週間こもっている特に作成してたソースのため最適化できておりません。
・本命ソースに近い構想にしてあるため変更点が多いです・・・すいません・・・
screen 0,240,320
;日付の配列
dim HIZUK,4
dim RP_HIZUK,4
dim HIZUK2,4
dim RP_HIZUK2,4
*プレイモード
;リプレイ
sdim replay1,320000
sdim replay2,320000
kioku1 = "replay1.dat"
kioku2 = "replay2.dat"
;ロード(「リプレイファイル選択」で表示させたいデータだけロードする)
bload kioku1, replay1
bload kioku2, replay2
;1つ目のファイル
RP_HIZUK(0) = lpeek(replay1,0) ;日付
RP_HIZUK(1) = lpeek(replay1,4) ;日付
RP_HIZUK(3) = lpeek(replay1,8) ;日付
RP_TENSU = lpeek(replay1,12) ;点数
RP_NAIND = lpeek(replay1,16) ;難易度
;2つ目のファイル
RP_HIZUK2(0) = lpeek(replay2,0) ;日付
RP_HIZUK2(1) = lpeek(replay2,4) ;日付
RP_HIZUK2(3) = lpeek(replay2,8) ;日付
RP_TENSU2 = lpeek(replay2,12) ;点数
RP_NAIND2 = lpeek(replay2,16) ;難易度
;初期化する
ki_iti = 0 ;データを書き込む位置
ki_iti_ni = 0 ;データを書き込む位置
JIKI_x = 112 : JIKI_y = 304 ;自機位置
playmode = 0 ;モード
Activ_ID = 0 ;アクティブID
MENI_KASO_c = 0 ;メニューカーソル
MENI_c = 0 ;リプレイの位置
RIPU_c = 0 ;ファイル選択の位置
HZON_c = 0 ;保存の位置
TENSU = 0 ;ゲーム点数
NAIND = 0 ;ゲーム難易度
;*******プレイ選択肢***********
*プレイ選択
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "Activ_ID " + Activ_ID
pos 0,20 : mes "MENI_c " + MENI_c
pos 0,40 : mes "RIPU_c " + RIPU_c
pos 0,60 : mes "MENI_KASO_c " + MENI_KASO_c
pos 0,80 : mes "モード " + playmode
pos 0,110 : mes "NAIND " + NAIND
pos 0,130 : mes "RP_NAIND " + RP_NAIND
pos 0,150 : mes "RP_NAIND2 " + RP_NAIND2
pos 0,180 : mes "TENSU " + TENSU
pos 0,200 : mes "RP_TENSU " + RP_TENSU
pos 0,220 : mes "RP_TENSU2 " + RP_TENSU2
pos 130,70 : mes ""+ RP_HIZUK(0) + "年" + RP_HIZUK(1) + "月" + RP_HIZUK(3) + "日"
;■■■■■■表示処理■■■■■■
;▼▼▼Activ_ID = 0▼▼▼
;「プレイする」、「リプレイ」選択
if Activ_ID = 0 {
if MENI_c = 0 {
;「プレイする」にカーソルが移動した場合
pos 20,250 : color 255 : mes "プレイする"
pos 20,270 : color 94,114,94 : mes "リプレイ"
} else { ;「リプレイ」にカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "プレイする"
pos 20,270 : color 255 : mes "リプレイ"
}
}
;▼▼▼Activ_ID = 1▼▼▼
;リプレイファイル選択
if Activ_ID = 1 {
;「replay1」にカーソルが移動した場合
if RIPU_c = 0 {
pos 20,250 : color 255 : mes "replay1.dat"
pos 20,270 : color 94,114,94 : mes "replay2.dat"
} else { ;「replay2」リプレイにカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "replay1.dat"
pos 20,270 : color 255 : mes "replay2.dat"
}
}
;●●●Zキー処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
if MENI_c = 0 : goto *ロードする ;「プレイ」を選択したら実行
if MENI_c = 1 { ;「リプレイ」を選択したら実行
Activ_ID += 1 ;アクティブIDを+1する
if Activ_ID = 2 { ;「リプレイファイル選択」を選択したら実行
playmode = 1 ;リプレイモードにする
goto *ロードする
}
}
}
}
;Aを押したら難易度をノーマルにする(ミニソースのため擬似的に置いている)
getkey Akey,65 ;(Aキー)
if Akey&65 : NAIND = 1
;************↑↓*************
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *プレイ選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *プレイ選択↑↓
}
redraw 1 : await 15
goto *プレイ選択
;*********プレイ選択↑↓**********
*プレイ選択↑↓
switch Activ_ID
;第一層
case 0
MENI_c = MENI_c + MENI_KASO_c ;カーソルの値を入れる
if MENI_c < 0 { ;↑を押した場合
MENI_c = 1
}
if MENI_c > 1 { ;↓を押した場合
MENI_c = 0
}
swbreak
;第二層
case 1
RIPU_c = RIPU_c + MENI_KASO_c ;カーソルの値を入れる
if RIPU_c < 0 { ;↑を押した場合
RIPU_c = 1
}
if RIPU_c > 1 { ;↓を押した場合
RIPU_c = 0
}
swbreak
swend
return
;***********ロードする*************
*ロードする
;初期化する
JIKI_x = 112 : JIKI_y = 304;自機位置X、Y
JKSO_f = 0 ;自機弾フラグ
JKSO_x = 0 : KSO_y = 0 ;自機弾X、Y
TISK_DL_f = 0;低速玉が出るフラグ
TISK_f = 0 ;低速ショットフラグ
TISK_x = 0 : TISK_y = 0 ;低速X、Y
;選択したファイルを読み込む
if playmode = 1 { ;リプレイモード
if RIPU_c = 0 : bload kioku1, replay1, 320000
if RIPU_c = 1 : bload kioku2, replay2, 320000
}
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
pos 0,0 : mes "十 "+ key
pos 0,20 : mes "Z "+ keyZ
pos 0,40 : mes "Skey "+ Skey
pos 0,60 : mes "Ctrl_key "+ Ctrl_key
pos 0,80 : mes "ki_iti "+ ki_iti
pos 0,100 : mes "ki_iti_ni "+ ki_iti_ni
if playmode = 0 : pos 0,120 : mes "プレイ中"
if playmode = 1 : pos 0,120 : mes "リプレイ中"
pos 0,140 : mes "リプ選択 " + RIPU_c
pos 0,170 : mes "NAIND " + NAIND
pos 0,190 : mes "RP_NAIND " + RP_NAIND
pos 0,210 : mes "RP_NAIND2 " + RP_NAIND2
pos 0,240 : mes "TENSU " + TENSU
pos 0,260 : mes "RP_TENSU " + RP_TENSU
pos 0,280 : mes "RP_TENSU2 " + RP_TENSU2
pos 130,70 : mes ""+ RP_HIZUK(0) + "年" + RP_HIZUK(1) + "月" + RP_HIZUK(3) + "日"
;***********************
gosub *入力処理
gosub *自機移動
gosub *自機弾の移動
;自機
pos JIKI_x,JIKI_y
color ,255,255 : mes "■"
;自機弾
if JKSO_f = 1 {
pos JKSO_x,JKSO_y
color 255,255 : mes "▲"
}
;低速ショット
if TISK_f = 1 {
pos TISK_x-20,TISK_y
color 255 : mes "● ●"
}
stick en,32 ;エンターキー
if en&32 : goto *リプレイ保存処理
redraw 1 : await 1
goto *メイン
;***********************
*入力処理
if playmode = 0 { ;プレイモード
stick key,15 ;移動
getkey keyZ,90 ;Zキー
getkey Skey,16 ;シフトキー
// getkey Xkey,88 ;Xキー
getkey Ctrl_key,17 ;コントロールキー
;▼▼▼入力の保存▼▼▼
;1つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay1,0,RP_HIZUK(0) ;年
lpoke replay1,4,RP_HIZUK(1) ;月
lpoke replay1,8,RP_HIZUK(3) ;日
lpoke replay1,12,RP_TENSU ;点数
lpoke replay1,16,RP_NAIND ;難易度
lpoke replay1,20,kixyara ;キャラクター
/*/
lpoke replay1,ki_iti+24,key ;移動
lpoke replay1,ki_iti+28,keyZ ;ショット
lpoke replay1,ki_iti+32,Skey ;シフトキー
// lpoke replay1,ki_iti+36,Xkey ;Xキー
lpoke replay1,ki_iti+40,Ctrl_key;コントロールキー
;2つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay2,0,RP_HIZUK2(0) ;年
lpoke replay2,4,RP_HIZUK2(1) ;月
lpoke replay2,8,RP_HIZUK2(3) ;日
lpoke replay2,12,RP_TENSU2 ;点数
lpoke replay2,16,RP_NAIND2 ;難易度
lpoke replay2,20,kixyara2 ;キャラクター
/*/
lpoke replay2,ki_iti_ni+24,key ;移動
lpoke replay2,ki_iti_ni+28,keyZ ;ショット
lpoke replay2,ki_iti_ni+32,Skey ;シフトキー
// lpoke replay2,ki_iti_ni+36,Xkey ;Xキー
lpoke replay2,ki_iti_ni+40,Ctrl_key;コントロールキー
}
;▼▼▼入力の読み出し▼▼▼
if playmode = 1 { ;リプレイモード
if RIPU_c = 0 { ;ファイルの1つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK(0) = lpeek(replay1,0) ;年
RP_HIZUK(1) = lpeek(replay1,4) ;月
RP_HIZUK(3) = lpeek(replay1,8) ;日
RP_TENSU = lpeek(replay1,12) ;点数
RP_NAIND = lpeek(replay1,16) ;難易度
kixyara = lpeek(replay1,20) ;キャラクター
/*/
key = lpeek(replay1,ki_iti+24) ;移動
keyZ = lpeek(replay1,ki_iti+28) ;ショット
Skey = lpeek(replay1,ki_iti+32) ;シフトキー
// Xkey = lpeek(replay1,ki_iti+36) ;Xキー
Ctrl_key = lpeek(replay1,ki_iti+40);コントロールキー
}
if RIPU_c = 1 { ;ファイルの2つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK2(0) = lpeek(replay2,0) ;年
RP_HIZUK2(1) = lpeek(replay2,4) ;月
RP_HIZUK2(3) = lpeek(replay2,8) ;日
RP_TENSU2 = lpeek(replay2,12) ;点数
RP_NAIND2 = lpeek(replay2,16) ;難易度
kixyara2 = lpeek(replay2,20) ;キャラクター
/*/
key = lpeek(replay2,ki_iti_ni+24) ;移動
keyZ = lpeek(replay2,ki_iti_ni+28) ;ショット
Skey = lpeek(replay2,ki_iti_ni+32) ;シフトキー
// Xkey = lpeek(replay2,ki_iti_ni+36) ;Xキー
Ctrl_key = lpeek(replay2,ki_iti_ni+40);コントロールキー
}
}
ki_iti+20
ki_iti_ni+20
return
;*************自機移動*****************
*自機移動
if key & 1 : JIKI_x- = 1
if key & 4 : JIKI_x+ = 1
if key & 2 : JIKI_y- = 1
if key & 8 : JIKI_y+ = 1
return
;************自機弾の移動***************
*自機弾の移動
if keyZ AND JKSO_f = 0 {
JKSO_f = 1 ;自機弾フラグを「立てる」
JKSO_x = JIKI_x
JKSO_y = JIKI_y
TISK_DL_f = 1 ;低速玉が出るフラグを「立てる」
TENSU += 100 ;点数(敵を撃破したときに加算されるけど、ミニソースなのでここで加算)
} else {
TISK_DL_f = 0
}
if JKSO_f = 1 : JKSO_y -= 1;↑に移動
if JKSO_y < 0 : JKSO_f = 0 ;一番上までいったら自機弾を「戻す」
;**************低速ショット*************
if Skey AND TISK_f = 0 AND TISK_DL_f = 1 { ;シフトキーが押されている、低速ショットがない、低速玉が出るフラグが立った時
TISK_f = 1 ;低速ショットフラグを「立てる」
TISK_x = JIKI_x
TISK_y = JIKI_y
}
if TISK_f = 1 : TISK_y -= 1 ;↑に移動
if TISK_y < 0 : TISK_f = 0 ;一番上まで行ったら低速ショットを「戻す」
return
;●●●リプレイ保存処理●●●
*リプレイ保存処理
*保存選択が終わるまで繰り返す
redraw 0 : color : boxf
color ,255
;************カウンター**********
pos 0,0 : mes "HZON_c " + HZON_c
pos 0,20 : mes "MENI_KASO_c " + MENI_KASO_c
pos 0,60 : mes "ki_iti "+ ki_iti
pos 0,80 : mes "ki_iti_ni "+ ki_iti_ni
pos 0,150 : mes "NAIND " + NAIND
pos 0,170 : mes "RP_NAIND " + RP_NAIND
pos 0,190 : mes "RP_NAIND2 " + RP_NAIND2
pos 0,220 : mes "TENSU " + TENSU
pos 0,240 : mes "RP_TENSU " + RP_TENSU
pos 0,260 : mes "RP_TENSU2 " + RP_TENSU2
pos 130,70 : mes ""+HIZUK(0) + "年" + HIZUK(1) + "月" + HIZUK(3) + "日"
if playmode = 1 : goto *プレイモード ;リプレイモードでエンター押したら、プレイモードに戻る
if playmode = 0 { ;プレイモード
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *保存選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *保存選択↑↓
}
;■■■■■■表示処理■■■■■■
;「1つ目に保存する」にカーソルが移動した場合
if HZON_c = 0 {
pos 100,200 : color 255 : mes "1つ目に保存する"
pos 100,220 : color 94,114,94 : mes "2つ目に保存する"
} else { ;「2つ目に保存する」にカーソルが移動した場合
pos 100,200 : color 94,114,94 : mes "1つ目に保存する"
pos 100,220 : color 255 : mes "2つ目に保存する"
}
;●●●保存処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
if HZON_c = 0 { ;1つ目を選択した場合
RP_TENSU = TENSU ;ゲーム中の「点数」をリプレイの変数に代入
RP_NAIND = NAIND ;ゲーム中の「難易度」をリプレイの変数に代入
;日付取得
repeat 4
HIZUK(cnt) = gettime(cnt)
loop
lpoke replay1,0,HIZUK(0) ;日付
lpoke replay1,4,HIZUK(1) ;日付
lpoke replay1,8,HIZUK(3) ;日付
lpoke replay1,12,RP_TENSU ;点数
lpoke replay1,16,RP_NAIND ;難易度
bsave kioku1, replay1, 320000
goto *プレイモード
}
if HZON_c = 1 { ;2つ目を選択した場合
RP_TENSU2 = TENSU ;ゲーム中の「点数」をリプレイの変数に代入
RP_NAIND2 = NAIND ;ゲーム中の「難易度」をリプレイの変数に代入
;日付取得
repeat 4
HIZUK2(cnt) = gettime(cnt)
loop
lpoke replay2,0,HIZUK2(0) ;日付
lpoke replay2,4,HIZUK2(1) ;日付
lpoke replay2,8,HIZUK2(3) ;日付
lpoke replay2,12,RP_TENSU2 ;点数
lpoke replay2,16,RP_NAIND2 ;難易度
bsave kioku2, replay2, 320000
goto *プレイモード
}
}
}
}
redraw 1 : await 1
goto *保存選択が終わるまで繰り返す
;*******保存選択↑↓**********
*保存選択↑↓
HZON_c = HZON_c + MENI_KASO_c
if HZON_c < 0 { ;↑を押した場合
HZON_c = 1
}
if HZON_c > 1 { ;↓を押した場合
HZON_c = 0
}
return

| |
|
2017/5/8(Mon) 23:09:22|NO.79613
うーん、これはゆっくりアドバイスしていったほうがよさそう。
まず、キー入力を保存するバッファに無駄があります。
リプレイファイルの先頭部分で、日付や難易度といった情報を4バイト単位で
読み書きするのは分かります。
しかし、各キーの情報いずれもは0〜255(1バイト)の範囲に収まるのですから、
個別にそれぞれ4バイトずつ使って読み書きする必要はないと思います。
アイドルさんのソースのその部分を最低限手直しするとすれば、
;***********************
*入力処理
if playmode = 0 { ;プレイモード
stick key,15 ;移動
getkey keyZ,90 ;Zキー
getkey Skey,16 ;シフトキー
// getkey Xkey,88 ;Xキー
getkey Ctrl_key,17 ;コントロールキー
;▼▼▼入力の保存▼▼▼
;1つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay1,0,RP_HIZUK(0) ;年
lpoke replay1,4,RP_HIZUK(1) ;月
lpoke replay1,8,RP_HIZUK(3) ;日
lpoke replay1,12,RP_TENSU ;点数
lpoke replay1,16,RP_NAIND ;難易度
lpoke replay1,20,kixyara ;キャラクター
/*/
poke replay1,ki_iti+24,key ;移動
poke replay1,ki_iti+25,keyZ ;ショット
poke replay1,ki_iti+26,Skey ;シフトキー
// poke replay1,ki_iti+27,Xkey ;Xキー
poke replay1,ki_iti+28,Ctrl_key;コントロールキー
;2つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay2,0,RP_HIZUK2(0) ;年
lpoke replay2,4,RP_HIZUK2(1) ;月
lpoke replay2,8,RP_HIZUK2(3) ;日
lpoke replay2,12,RP_TENSU2 ;点数
lpoke replay2,16,RP_NAIND2 ;難易度
lpoke replay2,20,kixyara2 ;キャラクター
/*/
poke replay2,ki_iti_ni+24,key ;移動
poke replay2,ki_iti_ni+25,keyZ ;ショット
poke replay2,ki_iti_ni+26,Skey ;シフトキー
// poke replay2,ki_iti_ni+27,Xkey ;Xキー
poke replay2,ki_iti_ni+28,Ctrl_key;コントロールキー
}
;▼▼▼入力の読み出し▼▼▼
if playmode = 1 { ;リプレイモード
if RIPU_c = 0 { ;ファイルの1つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK(0) = lpeek(replay1,0) ;年
RP_HIZUK(1) = lpeek(replay1,4) ;月
RP_HIZUK(3) = lpeek(replay1,8) ;日
RP_TENSU = lpeek(replay1,12) ;点数
RP_NAIND = lpeek(replay1,16) ;難易度
kixyara = lpeek(replay1,20) ;キャラクター
/*/
key = peek(replay1,ki_iti+24) ;移動
keyZ = peek(replay1,ki_iti+25) ;ショット
Skey = peek(replay1,ki_iti+26) ;シフトキー
// Xkey = peek(replay1,ki_iti+27) ;Xキー
Ctrl_key = peek(replay1,ki_iti+28);コントロールキー
}
if RIPU_c = 1 { ;ファイルの2つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK2(0) = lpeek(replay2,0) ;年
RP_HIZUK2(1) = lpeek(replay2,4) ;月
RP_HIZUK2(3) = lpeek(replay2,8) ;日
RP_TENSU2 = lpeek(replay2,12) ;点数
RP_NAIND2 = lpeek(replay2,16) ;難易度
kixyara2 = lpeek(replay2,20) ;キャラクター
/*/
key = peek(replay2,ki_iti_ni+24) ;移動
keyZ = peek(replay2,ki_iti_ni+25) ;ショット
Skey = peek(replay2,ki_iti_ni+26) ;シフトキー
// Xkey = peek(replay2,ki_iti_ni+27) ;Xキー
Ctrl_key = peek(replay2,ki_iti_ni+28);コントロールキー
}
}
ki_iti+5 ;1フレームにつきキー情報は5バイトに収まる
ki_iti_ni+5
return
となり、リプレイデータをこの段階で四分の一に圧縮できます。
さらに圧縮して、1フレーム当たり1バイトにできますが、
まずはここまで理解していただかないと先に進めないと思います。

| |
|
2017/5/8(Mon) 23:15:15|NO.79614
あと、メインループのウェイトが
await 1
になっていますが、これだと1秒間に1000回もメインループを回すことになるのですが
これが想定している仕様ですか?
通常、一般的なSTGだと1秒間(1000ミリ秒)に60フレームが普通なので
1000(ミリ秒)÷60(フレーム)で
await 17 または 16
あたりが適正かと思います。
|
|
2017/5/8(Mon) 23:46:44|NO.79616
先ほどの続きです。
キー入力情報は
・方向キーは0〜15の値となる。
・その他のキーはgetkeyの戻り値であるから0または1となる。
この前提で、キー入力情報を1フレームにつき1バイトに圧縮します。
今度も、なるべく元のソースに手を入れないように直すとすればこんな感じでしょうか。
;***********************
*入力処理
if playmode = 0 { ;プレイモード
stick key,15 ;移動
getkey keyZ,90 ;Zキー
getkey Skey,16 ;シフトキー
// getkey Xkey,88 ;Xキー
getkey Ctrl_key,17 ;コントロールキー
;キー入力情報(方向キー+ボタン4つまで)を1バイト(0−255)の数値にまとめる
key_Matome=Ctrl_key*128+Xkey*64+Skey+32+keyZ*16+(key & 15)
;▼▼▼入力の保存▼▼▼
;1つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay1,0,RP_HIZUK(0) ;年
lpoke replay1,4,RP_HIZUK(1) ;月
lpoke replay1,8,RP_HIZUK(3) ;日
lpoke replay1,12,RP_TENSU ;点数
lpoke replay1,16,RP_NAIND ;難易度
lpoke replay1,20,kixyara ;キャラクター
/*/
poke replay1,ki_iti+24,key_Matome ;キー入力を保存
;2つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay2,0,RP_HIZUK2(0) ;年
lpoke replay2,4,RP_HIZUK2(1) ;月
lpoke replay2,8,RP_HIZUK2(3) ;日
lpoke replay2,12,RP_TENSU2 ;点数
lpoke replay2,16,RP_NAIND2 ;難易度
lpoke replay2,20,kixyara2 ;キャラクター
/*/
poke replay2,ki_iti+24,key_Matome ;キー入力を保存
}
;▼▼▼入力の読み出し▼▼▼
if playmode = 1 { ;リプレイモード
if RIPU_c = 0 { ;ファイルの1つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK(0) = lpeek(replay1,0) ;年
RP_HIZUK(1) = lpeek(replay1,4) ;月
RP_HIZUK(3) = lpeek(replay1,8) ;日
RP_TENSU = lpeek(replay1,12) ;点数
RP_NAIND = lpeek(replay1,16) ;難易度
kixyara = lpeek(replay1,20) ;キャラクター
/*/
key_Matome = peek(replay1,ki_iti+24) ;キー入力を読み出し
;まとめられたキー情報を各変数へ戻す
key = key_Matome & 15 ;方向キー
keyZ = (key_Matome & 16)/16 ;ショット
Skey = (key_Matome & 32)/32 ;シフトキー
// Xkey = (key_Matome & 64)/64 ;Xキー
Ctrl_key = (key_Matome & 128)/128 ;コントロールキー
}
if RIPU_c = 1 { ;ファイルの2つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK2(0) = lpeek(replay2,0) ;年
RP_HIZUK2(1) = lpeek(replay2,4) ;月
RP_HIZUK2(3) = lpeek(replay2,8) ;日
RP_TENSU2 = lpeek(replay2,12) ;点数
RP_NAIND2 = lpeek(replay2,16) ;難易度
kixyara2 = lpeek(replay2,20) ;キャラクター
/*/
key_Matome = peek(replay2,ki_iti+24) ;キー入力を読み出し
;まとめられたキー情報を各変数へ戻す
key = key_Matome & 15 ;方向キー
keyZ = (key_Matome & 16)/16 ;ショット
Skey = (key_Matome & 32)/32 ;シフトキー
// Xkey = (key_Matome & 64)/64 ;Xキー
Ctrl_key = (key_Matome & 128)/128 ;コントロールキー
}
}
ki_iti++ ;1フレームにつきキー情報は1バイトに収まる
ki_iti_ni++
return
キー入力保存時は、入力情報を変数key_Matomeに1バイト(0−255)の数字として代入。
リプレイ再生時は逆に、読み出したkey_Matomeから、それぞれのキー入力用変数に戻す。
これで当初からすればキー情報を保存するメモリ量が二十分の一になります。
本当は、同じ事を2回別々に書いてあるreplay1とreplay2のコードを
ひとつにまとめるべきなのですが、とりあえず混乱しないように少しずつ。

| |
|
2017/5/8(Mon) 23:59:13|NO.79617
すみません、上記のソースに誤記がありました。
誤)
;キー入力情報(方向キー+ボタン4つまで)を1バイト(0−255)の数値にまとめる
key_Matome=Ctrl_key*128+Xkey*64+Skey+32+keyZ*16+(key & 15)
正)
;キー入力情報(方向キー+ボタン4つまで)を1バイト(0−255)の数値にまとめる
key_Matome = Ctrl_key*128 + Xkey*64 + Skey*32 + keyZ*16 + (key & 15)
※式の中のスペースは分かりやすいように入れたものです。
ちなみにこのゲームは最大で何分間くらいのリプレイの保存を想定してるのでしょうか?
|
|
2017/5/9(Tue) 23:22:32|NO.79620
ZAPさんありがとうございます!
まずは「NO.79613」の返答です。
lpoke replay1,20,kixyara ;キャラクター
poke replay1,ki_iti+24,key ;移動
poke replay1,ki_iti+25,keyZ ;ショット
「lpoke」使った後に「poke」使えたんですね・・・
別のミニソースで、出来るのかな?って思ってテストしてたのですが、
簡易的なものだったためか失敗したので、いったん保留して質問に答えてました・・・orz
お陰でデーターが大きい物は「lpoke」を使って4つ確保して、
データーが小さい物は「poke」を使って1つ確保できることがわかりました。
;▼▼▼入力の保存▼▼▼
;1つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay1,0,RP_HIZUK(0) ;年
lpoke replay1,4,RP_TENSU ;点数
poke replay1,8,RP_HIZUK(1) ;月
poke replay1,9,RP_HIZUK(3) ;日
poke replay1,10,RP_NAIND ;難易度
poke replay1,11,kixyara ;キャラクター
/*/
poke replay1,ki_iti+9,key ;移動
poke replay1,ki_iti+10,keyZ ;ショット
poke replay1,ki_iti+11,Skey ;シフトキー
// poke replay1,ki_iti+12,Xkey ;Xキー
poke replay1,ki_iti+13,Ctrl_key ;コントロールキー
;▼▼▼入力の読み出し▼▼▼
if playmode = 1 { ;リプレイモード
if RIPU_c = 0 { ;ファイルの1つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK(0) = lpeek(replay1,0) ;年
RP_TENSU = lpeek(replay1,4) ;点数
RP_HIZUK(1) = peek(replay1,5) ;月
RP_HIZUK(3) = peek(replay1,6) ;日
RP_NAIND = peek(replay1,7) ;難易度
kixyara = peek(replay1,8) ;キャラクター
/*/
key = peek(replay1,ki_iti+9) ;移動
keyZ = peek(replay1,ki_iti+10) ;ショット
Skey = peek(replay1,ki_iti+11) ;シフトキー
// Xkey = peek(replay1,ki_iti+12) ;Xキー
Ctrl_key = peek(replay1,ki_iti+13);コントロールキー
}
}
ki_iti+5
>>NO.79614
>>await 1
>>になっていますが、これだと1秒間に1000回もメインループを回すことになるのですが
>>これが想定している仕様ですか?
あぁああああ!サイトのを参考にして作ったままだったので忘れてました。
「await」は「16」に修正ました。(本命はちゃんと16です・・・)
それに伴い、「自機弾の移動、低速ショット」を「-15」に修正しました。
>>NO.79616
>>「key_Matome=Ctrl_key*128+Xkey*64+Skey+32+keyZ*16+(key & 15)」
例えば「keyZ*16」は8ビットに収納する。
getkeyは「0、1」で判断するため2種類になるので、「8(ビット)*(2種類)となり「8*2=16」になる。
それがキーごとにあるので、「16、32〜・・・」となる、っていう解釈であってますでしょうか。
っと思ったら「keyZ = (key_Matome & 16)/16」ここで割り算がががががが。

| |
|
2017/5/9(Tue) 23:22:56|NO.79621
ヒントは「2進数」です。
目の前にon/offスイッチが横に8個並んでいると想像してください。
onならスイッチが「1」になります。
offならスイッチが「0」になります。
すべてのスイッチがoffなら「00000000」→ 10進数でいうと「0」で表せます。
すべてのスイッチがonなら「11111111」 → 10進数でいうと「255」で表せます。
このスイッチ1つ1つを、方向キーだったり、Zキーだったりに当てはめると・・・
2進数の概念が理解できれば、式の意味が分かると思います。
|
|
2017/5/9(Tue) 23:30:13|NO.79622
>>getkeyは「0、1」で判断するため2種類になるので、「8(ビット)*(2種類)となり「8*2=16」になる。
>>それがキーごとにあるので、「16、32〜・・・」となる、っていう解釈であってますでしょうか。
あ、すいません!
2進数でした。ぐぇええええ。おぇええoiz
|
|
2017/5/9(Tue) 23:30:34|NO.79623
実はキーコード記録するならこんなテクニックもあります。
拙作の http://hsp.tv/play/pforum.php?mode=pastwch&num=70762#71983 を利用して……
a=37,38,39,40,'Z','X','A','S'
myStickSetup a//キー配列を登録します。
repeat
redraw 0
color 255,255,255
boxf
color 0,0,0
pos 0,0
myStick key,15,0//使い方はstickと全く同じにしました。
mes key
redraw 1
await 16
loop
実はこのときのkeyは、myStickSetupの個数が8個なので、高々255までの値……pokeで済むわけです。
これを利用すると、myStick命令でstickのように扱いながら、得られたデータをそのまま保存することで、
リプレイ時に簡単に互換させることが出来ます。
ちなみに、myStickSetupで使用するキー数が16以下であればwpokeで書ける(2byte)ので、キー数が増えた場合はそうやって対処すれば。
|
|
2017/5/9(Tue) 23:35:20|NO.79624
なお、読み出したキーコードをわざわざ割っているのは、
getkeyで入力状態を得た結果と同じ
押されていない状態→「0」
押されている状態→「1」
にするためです。
キー判定プログラムの中で
押されている状態→「ゼロ以外」
でもよいのであれば、わざわざ割り戻して1にする必要はありません。
|
|
2017/5/9(Tue) 23:47:04|NO.79625
>Velgailさん
これは便利なモジュールですね。
自分も、ジョイパッドとキーボードを両方とも読み出して、
その合成値をStick命令と同等に扱えるモジュールを自作して使っているので
それを紹介してもよかったのですが、
ここで一足飛びにモジュールを紹介するよりも
概念を理解していただくほうがよいのではないかと思い、
あえて提示されたスクリプトを微修正していく方法を取りました。
確かに方向キー以外に使用するボタンが4つを超えると8ビットでは
収納しきれないので、wpokeを使う必要がありますね。
|
|
2017/5/10(Wed) 07:52:44|NO.79627
>>すべてのスイッチがoffなら「00000000」→ 10進数でいうと「0」で表せます。
>>すべてのスイッチがonなら「11111111」 → 10進数でいうと「255」で表せます。
key=15 (0000 0000 0000 0001)
keyZ=16 (0000 0000 0000 0010)
Skey=32 (0000 0000 0000 0100)
Xkey=64 (0000 0000 0000 1000)
Ctrl_key=128 (0000 0000 0001 0000)
キー入力されていれば上の箇所の1が入り、押されてなければ0ということですね・・・
>>ちなみにこのゲームは最大で何分間くらいのリプレイの保存を想定してるのでしょうか?
まだ1面のみの超体験版のため、どのぐらいか見積もれてないんですよね・・・
「ki_iti+10」で加算してた時にプレイしたときは、5万ぐらいいきましたが
ユーザーがぶらぶらする可能性もあるので、別途で考えようかなと思ってました。
|
|
2017/5/10(Wed) 21:17:48|NO.79663
Velgailさん。
ほぇ〜。
理解できそうでできないような・・・
時間をかければ出来るかもしれないです・・・多分。
リンク先ではモジュールを使っているので、いったん置いておきます(´Д`)
いやモジュールも理解はなんとなく理解はしていると思うんだけど(使わなくってもできそうだけど)、
また別の所にいくと踏み外しそうなので、後回しにして落ち着いたタイミングで見てみようと思います。
ソースありがとうございます!
|
|
2017/5/10(Wed) 21:30:24|NO.79665
ZAPさん。
再度ありがとうございます。
>>なお、読み出したキーコードをわざわざ割っているのは、
>>getkeyで入力状態を得た結果と同じ
>>押されていない状態→「0」
>>押されている状態→「1」
落ち着いてみたらよくわかりました。
keyZ = (key_Matome & 16)/16 ;ショット
; 入力されていれば16が入る、16/16の計算により1になる(押されている)
; 入力されていれば0が入る、0/16の計算により0になる(押されていない)
例えばkeyZであれば上記のようになり、ON、OFF判定できるということですね。
今度こそ大丈夫な・・・はず!
ちょいちょいソース修正してきます(`・ω・´)
|
|
2017/5/12(Fri) 08:08:41|NO.79696
情報を整理してソースを修正してきました。
*入力処理
if playmode = 0 { ;プレイモード
stick key,15 ;移動
getkey keyZ,90 ;Zキー
getkey Skey,16 ;シフトキー
// getkey Xkey,88 ;Xキー
getkey Ctrl_key,17 ;コントロールキー
;キー入力情報(方向キー+ボタン4つまで)を1バイト(0−255)の数値にまとめる
key_Matome = Ctrl_key*128 + Xkey*64 + Skey*32 + keyZ*16 + (key & 15)
;▼▼▼入力の保存▼▼▼
;1つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay1,0,RP_HIZUK(0) ;年
lpoke replay1,4,RP_TENSU ;点数
poke replay1,8,RP_HIZUK(1) ;月
poke replay1,9,RP_HIZUK(3) ;日
poke replay1,10,RP_NAIND ;難易度
poke replay1,11,kixyara ;キャラクター
/*/
poke replay1,ki_iti+12,key_Matome ;キー入力を保存
;2つ目の入力の保存
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay2,0,RP_HIZUK2(0) ;年
lpoke replay2,4,RP_TENSU2 ;点数
poke replay2,8,RP_HIZUK2(1) ;月
poke replay2,9,RP_HIZUK2(3) ;日
poke replay2,10,RP_NAIND2 ;難易度
poke replay2,11,kixyara2 ;キャラクター
/*/
poke replay2,ki_iti+12,key_Matome ;キー入力を保存
}
;▼▼▼入力の読み出し▼▼▼
if playmode = 1 { ;リプレイモード
if RIPU_c = 0 { ;ファイルの1つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK(0) = lpeek(replay1,0) ;年
RP_TENSU = lpeek(replay1,4) ;点数
RP_HIZUK(1) = peek(replay1,8) ;月
RP_HIZUK(3) = peek(replay1,9) ;日
RP_NAIND = peek(replay1,10) ;難易度
kixyara = peek(replay1,11) ;キャラクター
/*/
key_Matome = peek(replay1,ki_iti+12) ;キー入力を読み出し
key = key_Matome & 15 ;方向キー
keyZ = (key_Matome & 16)/16 ;ショット
Skey = (key_Matome & 32)/32 ;シフトキー
// Xkey = (key_Matome & 64)/64 ;Xキー
Ctrl_key = (key_Matome & 128)/128 ;コントロールキー
}
if RIPU_c = 1 { ;ファイルの2つ目を選択した場合
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK2(0) = lpeek(replay2,0) ;年
RP_TENSU2 = lpeek(replay2,4) ;点数
RP_HIZUK2(1) = peek(replay2,8) ;月
RP_HIZUK2(3) = peek(replay2,9) ;日
RP_NAIND2 = peek(replay2,10) ;難易度
kixyara2 = peek(replay2,11) ;キャラクター
/*/
key_Matome = peek(replay2,ki_iti+12) ;キー入力を読み出し
key = key_Matome & 15 ;方向キー
keyZ = (key_Matome & 16)/16 ;ショット
Skey = (key_Matome & 32)/32 ;シフトキー
// Xkey = (key_Matome & 64)/64 ;Xキー
Ctrl_key = (key_Matome & 128)/128 ;コントロールキー
}
}
ki_iti+1
ki_iti_ni+1
>>本当は、同じ事を2回別々に書いてあるreplay1とreplay2のコードを
>>ひとつにまとめるべきなのですが、とりあえず混乱しないように少しずつ。
あ、これ見落としていました・・・
;▼▼▼入力の保存▼▼▼
;▼▼▼入力の読み出し▼▼▼
の所を1つだけにして「ki_iti+1」のみ処理。
「bsave」するとき:「ファイル1、ファイル2」のどちらかを選択した時に、それに保存。
「bload」するとき:「ファイル1、ファイル2」のどちらかを選択した時に、それれを呼び出す。
上記をおこなえば、メインの処理で選んだファイルの「;▼▼▼入力の読み出し▼▼▼」ができそうな気がします・・・
が!なんか違うような・・・

| |
|
2017/5/13(Sat) 10:45:30|NO.79723
基本的な考え方はそれで合っています。
リストを見るに、リプレイファイルの内容を表示して
それを選択するために複数のファイルを読み込んでおかなければならない、
というところから発想がスタートしているようですが、
実際にプレイ中に記録するのはひとつのバッファがあれば十分ですし、
記録するときにファイル名さえ変えれば対応できます。
リプレイ選択部分についてですが、bloadのヘルプによると
bloadの第2パラメータで読み込むサイズを指定できます。
これで、各リプレイファイルの冒頭部分(キー情報以外の部分)だけを
読み込んでリスト化すれば事足ります。
リプレイファイルの数だけ、キー情報を含んだファイルサイズと同じ大きさの
バッファを作って読み込むのはメモリの無駄です。
実際にリプレイの記録/再生に使うバッファはひとつだけでよくて、
先ほどのリプレイファイル情報を読み出すためのバッファとは別に、たとえば
sdim replay_buf,320000
とでも確保しておき、
選択後の処理で、たとえば選択されたファイル番号が変数Numに入っているとしたら
FileName="replay"+Num+".dat"
bload FileName,replay_buf
で読み出し、これを使って再生すればいい訳ですし、
保存する時も保存する番号が選択されてから、
FileName="replay"+Num+".dat"
bsave FileName,replay_buf
で保存する。
こうすれば、上記のリストでreplay1、replay2にそれぞれ書いている
保存、読み出しのコードを1本化できます。
がんばってください。
|
|
2017/5/13(Sat) 10:58:55|NO.79724
あと、これは老婆心ですが、
リプレイファイルは自分の動きを記録しているだけなので、
プレイ内容を再現するには敵側の挙動もプレイ時と全く同じに再現する必要があります。
そちらは大丈夫ですか?
|
|
2017/5/13(Sat) 17:14:01|NO.79735
ZAPさん!やりました!
コメントしてから「*入力処理」のところで配列にすれb・・・いや意味ないな・・
やっぱ変数代入するか・・と思いながら考えてました。
でもその方法が中々思いつかず色々試していましたが、ヒントを見てやりかたがわかりました。
お陰ですごい小さくなりデータが膨らむ心配がなくなりました。
もしリプレイファイルを増やす場合は、変数で増加するため汎用性もあるというオマケつき!
「bload」のp3の「ファイルのオフセット」いいですねぇ。
これがあれば、キー入力の部分からスタートするっていうことができるし、
しかも「2面から読み込む」なども対応できそうですね。
ただ、2面とかは途中で言った通り、1面しかないのでかなり先の話になりそうですw
ソースはこんな感じになりました><
本当にありがとうございます!
よっしゃーメインソース修正するじぇ〜。
screen 0,240,320
;日付の配列
dim HIZUK,4
dim RP_HIZUK,4
*プレイモード
;初期化する
ki_iti = 0 ;データを書き込む位置
JIKI_x = 112 : JIKI_y = 304 ;自機位置
playmode = 0 ;モード
Activ_ID = 0 ;アクティブID
MENI_KASO_c = 0 ;メニューカーソル
MENI_c = 0 ;リプレイの位置
RIPU_c = 0 ;ファイル選択の位置
HZON_c = 0 ;保存の位置
TENSU = 0 ;ゲーム点数
NAIND = 0 ;ゲーム難易度
;*******プレイ選択肢***********
*プレイ選択
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "Activ_ID " + Activ_ID
pos 0,20 : mes "MENI_c " + MENI_c
pos 0,40 : mes "RIPU_c " + RIPU_c
pos 0,60 : mes "MENI_KASO_c " + MENI_KASO_c
pos 0,80 : mes "モード " + playmode
pos 0,110 : mes "NAIND " + NAIND
pos 0,130 : mes "RP_NAIND " + RP_NAIND
pos 0,180 : mes "TENSU " + TENSU
pos 0,200 : mes "RP_TENSU " + RP_TENSU
pos 130,70 : mes ""+ RP_HIZUK(0) + "年" + RP_HIZUK(1) + "月" + RP_HIZUK(3) + "日"
;■■■■■■読み込み処理■■■■■■
kioku = "replay" + RIPU_c + ".dat" ;リプレイで選んだ数値を「RIPU_c」に入れて、「replay0.dat、replay1.dat...」と出し分けする
sdim replay,320000
;ロード(「リプレイファイル選択」で表示させたいデータだけロードする)
bload kioku, replay
;ファイル読み込み
RP_HIZUK(0) = lpeek(replay,0) ;年
RP_TENSU = lpeek(replay,4) ;点数
RP_HIZUK(1) = peek(replay,8) ;月
RP_HIZUK(3) = peek(replay,9) ;日
RP_NAIND = peek(replay,10) ;難易度
;■■■■■■表示処理■■■■■■
;▼▼▼Activ_ID = 0▼▼▼
;「プレイする」、「リプレイ」選択
if Activ_ID = 0 {
if MENI_c = 0 {
;「プレイする」にカーソルが移動した場合
pos 20,250 : color 255 : mes "プレイする"
pos 20,270 : color 94,114,94 : mes "リプレイ"
} else { ;「リプレイ」にカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "プレイする"
pos 20,270 : color 255 : mes "リプレイ"
}
}
;▼▼▼Activ_ID = 1▼▼▼
;リプレイファイル選択
if Activ_ID = 1 {
;「replay1」にカーソルが移動した場合
if RIPU_c = 0 {
pos 20,250 : color 255 : mes "replay1.dat"
pos 20,270 : color 94,114,94 : mes "replay2.dat"
} else { ;「replay2」リプレイにカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "replay1.dat"
pos 20,270 : color 255 : mes "replay2.dat"
}
}
;●●●Zキー処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
if MENI_c = 0 : goto *ロードする ;「プレイ」を選択したら実行
if MENI_c = 1 { ;「リプレイ」を選択したら実行
Activ_ID += 1 ;アクティブIDを+1する
if Activ_ID = 2 { ;「リプレイファイル選択」を選択したら実行
playmode = 1 ;リプレイモードにする
goto *ロードする
}
}
}
}
;Aを押したら難易度をノーマルにする(ミニソースのため擬似的に置いている)
getkey Akey,65 ;(Aキー)
if Akey&65 : NAIND = 1
;************↑↓*************
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *プレイ選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *プレイ選択↑↓
}
redraw 1 : await 15
goto *プレイ選択
;*********プレイ選択↑↓**********
*プレイ選択↑↓
switch Activ_ID
;第一層
case 0
MENI_c = MENI_c + MENI_KASO_c ;カーソルの値を入れる
if MENI_c < 0 { ;↑を押した場合
MENI_c = 1
}
if MENI_c > 1 { ;↓を押した場合
MENI_c = 0
}
swbreak
;第二層
case 1
RIPU_c = RIPU_c + MENI_KASO_c ;カーソルの値を入れる
if RIPU_c < 0 { ;↑を押した場合
RIPU_c = 1
}
if RIPU_c > 1 { ;↓を押した場合
RIPU_c = 0
}
swbreak
swend
return
;***********ロードする*************
*ロードする
;初期化する
JIKI_x = 112 : JIKI_y = 304;自機位置X、Y
JKSO_f = 0 ;自機弾フラグ
JKSO_x = 0 : KSO_y = 0 ;自機弾X、Y
TISK_DL_f = 0;低速玉が出るフラグ
TISK_f = 0 ;低速ショットフラグ
TISK_x = 0 : TISK_y = 0 ;低速X、Y
;(キャラクターデーターである「11」から過ぎたデータを読み込みたいため、p3の値を「11」)
if playmode = 1 : bload kioku, replay, 11;リプレイ選択時、選択したファイルを読み込む
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
pos 0,0 : mes "十 "+ key
pos 0,20 : mes "Z "+ keyZ
pos 0,40 : mes "Skey "+ Skey
pos 0,60 : mes "Ctrl_key "+ Ctrl_key
pos 0,80 : mes "ki_iti "+ ki_iti
if playmode = 0 : pos 0,120 : mes "プレイ中"
if playmode = 1 : pos 0,120 : mes "リプレイ中"
pos 0,140 : mes "リプ選択 " + RIPU_c
pos 0,170 : mes "NAIND " + NAIND
pos 0,190 : mes "RP_NAIND " + RP_NAIND
pos 0,240 : mes "TENSU " + TENSU
pos 0,260 : mes "RP_TENSU " + RP_TENSU
pos 130,70 : mes ""+ RP_HIZUK(0) + "年" + RP_HIZUK(1) + "月" + RP_HIZUK(3) + "日"
;***********************
gosub *入力処理
gosub *自機移動
gosub *自機弾の移動
;自機
pos JIKI_x,JIKI_y
color ,255,255 : mes "■"
;自機弾
if JKSO_f = 1 {
pos JKSO_x,JKSO_y
color 255,255 : mes "▲"
}
;低速ショット
if TISK_f = 1 {
pos TISK_x-20,TISK_y
color 255 : mes "● ●"
}
stick en,32 ;エンターキー
if en&32 : goto *リプレイ保存処理
redraw 1 : await 16
goto *メイン
;***********************
*入力処理
if playmode = 0 { ;プレイモード
stick key,15 ;移動
getkey keyZ,90 ;Zキー
getkey Skey,16 ;シフトキー
// getkey Xkey,88 ;Xキー
getkey Ctrl_key,17 ;コントロールキー
;キー入力情報(方向キー+ボタン4つまで)を1バイト(0−255)の数値にまとめる
key_Matome = Ctrl_key*128 + Xkey*64 + Skey*32 + keyZ*16 + (key & 15)
;▼▼▼▼入力の保存▼▼▼▼
/*/←でコメントアウトしている所はゲーム終了直前に保存する
lpoke replay1,0,RP_HIZUK(0) ;年
lpoke replay1,4,RP_TENSU ;点数
poke replay1,8,RP_HIZUK(1) ;月
poke replay1,9,RP_HIZUK(3) ;日
poke replay1,10,RP_NAIND ;難易度
poke replay1,11,kixyara ;キャラクター
/*/
poke replay,ki_iti+12,key_Matome;キー入力を保存
}
;▼▼▼▼入力の読み出し▼▼▼▼
if playmode = 1 { ;リプレイモード
/*/←でコメントアウトしている所はゲーム終了直前に保存する
RP_HIZUK(0) = lpeek(replay1,0) ;年
RP_TENSU = lpeek(replay1,4) ;点数
RP_HIZUK(1) = peek(replay1,8) ;月
RP_HIZUK(3) = peek(replay1,9) ;日
RP_NAIND = peek(replay1,10) ;難易度
kixyara = peek(replay1,11) ;キャラクター
/*/
key_Matome = peek(replay,ki_iti+12) ;キー入力を読み出し
key = key_Matome & 15 ;方向キー
keyZ = (key_Matome & 16)/16 ;ショット
Skey = (key_Matome & 32)/32 ;シフトキー
// Xkey = (key_Matome & 64)/64 ;Xキー
Ctrl_key = (key_Matome & 128)/128 ;コントロールキー
}
ki_iti+1
return
;*************自機移動*****************
*自機移動
if key & 1 : JIKI_x- = 4
if key & 4 : JIKI_x+ = 4
if key & 2 : JIKI_y- = 4
if key & 8 : JIKI_y+ = 4
return
;************自機弾の移動***************
*自機弾の移動
if keyZ AND JKSO_f = 0 {
JKSO_f = 1 ;自機弾フラグを「立てる」
JKSO_x = JIKI_x
JKSO_y = JIKI_y
TISK_DL_f = 1 ;低速玉が出るフラグを「立てる」
TENSU += 100 ;点数(敵を撃破したときに加算されるけど、ミニソースなのでここで加算)
} else {
TISK_DL_f = 0
}
if JKSO_f = 1 : JKSO_y -= 15;↑に移動
if JKSO_y < 0 : JKSO_f = 0 ;一番上までいったら自機弾を「戻す」
;**************低速ショット*************
if Skey AND TISK_f = 0 AND TISK_DL_f = 1 { ;シフトキーが押されている、低速ショットがない、低速玉が出るフラグが立った時
TISK_f = 1 ;低速ショットフラグを「立てる」
TISK_x = JIKI_x
TISK_y = JIKI_y
}
if TISK_f = 1 : TISK_y -= 15;↑に移動
if TISK_y < 0 : TISK_f = 0 ;一番上まで行ったら低速ショットを「戻す」
return
;●●●●リプレイ保存処理●●●●
*リプレイ保存処理
;*****保存選択が終わるまで繰り返す*****
*保存選択が終わるまで繰り返す
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "HZON_c " + HZON_c
pos 0,20 : mes "MENI_KASO_c " + MENI_KASO_c
pos 0,60 : mes "ki_iti "+ ki_iti
pos 0,150 : mes "NAIND " + NAIND
pos 0,170 : mes "RP_NAIND " + RP_NAIND
pos 0,220 : mes "TENSU " + TENSU
pos 0,240 : mes "RP_TENSU " + RP_TENSU
pos 130,70 : mes ""+HIZUK(0) + "年" + HIZUK(1) + "月" + HIZUK(3) + "日"
if playmode = 1 : goto *プレイモード ;リプレイモードでエンター押したら、プレイモードに戻る
if playmode = 0 { ;プレイモード
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *保存選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *保存選択↑↓
}
;■■■■■■表示処理■■■■■■
;「1つ目に保存する」にカーソルが移動した場合
if HZON_c = 0 {
pos 100,200 : color 255 : mes "1つ目に保存する"
pos 100,220 : color 94,114,94 : mes "2つ目に保存する"
} else { ;「2つ目に保存する」にカーソルが移動した場合
pos 100,200 : color 94,114,94 : mes "1つ目に保存する"
pos 100,220 : color 255 : mes "2つ目に保存する"
}
;●●●保存処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
;ゲーム中のデーターをリプレイに入れるため代入処理
RP_TENSU = TENSU ;ゲーム中の「点数」をリプレイの変数に代入
RP_NAIND = NAIND ;ゲーム中の「難易度」をリプレイの変数に代入
;「保存」で選んだ数値を「HZON_c」に入れて、「replay0.dat、replay1.dat...」と出し分けする
kioku = "replay" + HZON_c + ".dat"
;日付取得
repeat 4
HIZUK(cnt) = gettime(cnt)
loop
lpoke replay,0,HIZUK(0) ;年
lpoke replay,4,RP_TENSU ;点数
poke replay,8,HIZUK(1) ;月
poke replay,9,HIZUK(3) ;日
poke replay,10,RP_NAIND ;難易度
bsave kioku, replay, 320000
goto *プレイモード
}
}
}
redraw 1 : await 1
goto *保存選択が終わるまで繰り返す
;*******保存選択↑↓**********
*保存選択↑↓
HZON_c = HZON_c + MENI_KASO_c
if HZON_c < 0 { ;↑を押した場合
HZON_c = 1
}
if HZON_c > 1 { ;↓を押した場合
HZON_c = 0
}
return

| |
|
2017/5/13(Sat) 17:19:08|NO.79736
>>プレイ内容を再現するには敵側の挙動もプレイ時と全く同じに再現する必要があります。
>>そちらは大丈夫ですか?
こちらは多分大丈夫だと思います。
「NO.79351」の時からチクチクとメインに適応させてちゃんと再生できてたので><
リプレイは自機のみの動きにして、敵や弾などの自機以外に関しては、
初期化して配置しなおせば出来るっということがわかっているので、
再生された動きにどおりに敵を撃破していくことを確認できております!
|
|
2017/5/13(Sat) 17:26:52|NO.79737
問題は乱数を使う場合です。
敵の動きやそれ以外の要素にも全くランダムな要素のないゲームなら問題ないのですが、
どこか1ヶ所でも乱数を使う場合は、プレイ時とリプレイ再生時に、
全くおなじ乱数を再現できないとそこでずれてしまいます。
|
|
2017/5/14(Sun) 10:35:46|NO.79748
ZAPさん。
>>問題は乱数を使う場合です。
>>全くおなじ乱数を再現できないとそこでずれてしまいます。
乱数のことを考慮していませんでした・・・
動作確認できたところがちょうど乱数の箇所じゃなかったんですよね・・・
STGなので乱数とは切っても切れない縁なのでなんとかしないといけないですね。
ある程度ランダムに見える弾幕とか作れると思うのですが、
やはり毎回違う結果っというのは必要になってきますね・・・
プレイ中:乱数で出た数値を変数に収納
リプレイ:変数を読み込んで配置する
っというやり方が適切かなっと思ったんですが、
例えば下記のソースのように3発あったら、3発分収納しないといけないので
3発分代入するはめになるんですよね・・・
ってことはこの考え方は間違っていると思います・・・
STGのランダム弾は100発近く出す場合もあるし・・・
また下記のソースではまだ不具合があります・・・難しい・・・
screen 0,240,320
dim RP_TEKI_x,3
*プレイモード
;初期化
ki_iti = 0 ;データを書き込む位置
Activ_ID = 0 ;アクティブID
MENI_c = 0 ;リプレイの位置
RIPU_c = 0 ;ファイル選択の位置
MENI_KASO_c = 0 ;メニューカーソル
playmode = 0 ;モード
HZON_c = 0 ;保存の位置
TEKI_y = 0 ;敵弾
TEKI_RAN = 0 ;敵弾乱数
TEKI_c = 0 ;弾カウント
;*******プレイ選択肢***********
*プレイ選択
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "Activ_ID " + Activ_ID
pos 0,20 : mes "MENI_c " + MENI_c
pos 0,40 : mes "RIPU_c " + RIPU_c
pos 0,60 : mes "MENI_KASO_c " + MENI_KASO_c
pos 0,80 : mes "モード " + playmode
;■■■■■■読み込み処理■■■■■■
kioku = "replay" + RIPU_c + ".dat"
sdim replay,320000
;▼▼▼「プレイする」、「リプレイ」選択▼▼▼
if Activ_ID = 0 {
if MENI_c = 0 { ;「プレイする」にカーソルが移動した場合
pos 20,250 : color 255 : mes "プレイする"
pos 20,270 : color 94,114,94 : mes "リプレイ"
} else { ;「リプレイ」にカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "プレイする"
pos 20,270 : color 255 : mes "リプレイ"
}
}
;▼▼▼リプレイファイル選択▼▼▼
if Activ_ID = 1 {
if RIPU_c = 0 { ;「replay1」にカーソルが移動した場合
pos 20,250 : color 255 : mes "replay1.dat"
pos 20,270 : color 94,114,94 : mes "replay2.dat"
} else { ;「replay2」リプレイにカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "replay1.dat"
pos 20,270 : color 255 : mes "replay2.dat"
}
}
;●●●Zキー処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
if MENI_c = 0 : goto *ロードする ;「プレイ」を選択したら実行
if MENI_c = 1 { ;「リプレイ」を選択したら実行
Activ_ID += 1 ;アクティブIDを+1する
if Activ_ID = 2 { ;「リプレイファイル選択」を選択したら実行
playmode = 1 ;リプレイモードにする
goto *ロードする
}
}
}
}
;************↑↓*************
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *プレイ選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *プレイ選択↑↓
}
redraw 1 : await 15
goto *プレイ選択
;*********プレイ選択↑↓**********
*プレイ選択↑↓
switch Activ_ID
;第一層
case 0
MENI_c = MENI_c + MENI_KASO_c ;カーソルの値を入れる
if MENI_c < 0 { ;↑を押した場合
MENI_c = 1
}
if MENI_c > 1 { ;↓を押した場合
MENI_c = 0
}
swbreak
;第二層
case 1
RIPU_c = RIPU_c + MENI_KASO_c ;カーソルの値を入れる
if RIPU_c < 0 { ;↑を押した場合
RIPU_c = 1
}
if RIPU_c > 1 { ;↓を押した場合
RIPU_c = 0
}
swbreak
swend
return
;***********ロードする*************
*ロードする
if playmode = 1 : bload kioku, replay
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
if playmode = 0 : pos 0,20 : mes "プレイ中"
if playmode = 1 : pos 0,20 : mes "リプレイ中"
pos 0,40 : mes "リプ選択 " + RIPU_c
pos 0,60 : mes "TEKI_x " + TEKI_x
pos 0,80 : mes "TEKI_c " + TEKI_c
pos 0,100 : mes "TEKI_RAN " + TEKI_RAN
pos 0,130 : mes "RP_TEKI_x(0) " + RP_TEKI_x(0)
pos 0,150 : mes "RP_TEKI_x(1) " + RP_TEKI_x(1)
pos 0,170 : mes "RP_TEKI_x(2) " + RP_TEKI_x(2)
;***********************
gosub *入力処理
gosub *敵弾
;敵弾
if TEKI_f = 1 {
pos TEKI_x,TEKI_y
color 255,,255 : mes "★"
}
if ki_iti >= 530 : goto *リプレイ保存処理
redraw 1 : await 16
goto *メイン
;***********************
*入力処理
if playmode = 0 { ;プレイモード
if TEKI_c = 0 : RP_TEKI_x(0) = TEKI_x
if TEKI_c = 1 : RP_TEKI_x(1) = TEKI_x
if TEKI_c = 2 : RP_TEKI_x(2) = TEKI_x
poke replay,ki_iti ,RP_TEKI_x(0)
poke replay,ki_iti+1,RP_TEKI_x(1)
poke replay,ki_iti+2,RP_TEKI_x(2)
}
if playmode = 1 { ;リプレイモード
RP_TEKI_x(0) = peek(replay,ki_iti)
RP_TEKI_x(1) = peek(replay,ki_iti+1)
RP_TEKI_x(2) = peek(replay,ki_iti+2)
}
ki_iti+3
return
;************敵弾***************
*敵弾
if TEKI_c <= 3 {
if playmode = 0 { ;プレイモード
randomize ;乱数初期化
TEKI_RAN = rnd(100) ;乱数
}
if TEKI_f = 0 {
TEKI_f = 1
if playmode = 0 : TEKI_x = 100 + TEKI_RAN
if playmode = 1 { ;リプレイモード
if TEKI_c = 0 : TEKI_x = RP_TEKI_x(0)
if TEKI_c = 1 : TEKI_x = RP_TEKI_x(1)
if TEKI_c = 2 : TEKI_x = RP_TEKI_x(2)
}
TEKI_y = 0
}
if TEKI_f = 1 : TEKI_y += 5 ;↓に移動
if TEKI_y >= 330 {
TEKI_c += 1 ;敵弾カウント
TEKI_f = 0 ;一番下までいったら敵弾を「戻す」
}
}
return
;●●●●リプレイ保存処理●●●●
*リプレイ保存処理
;*****保存選択が終わるまで繰り返す*****
*保存選択が終わるまで繰り返す
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "HZON_c " + HZON_c
pos 0,20 : mes "MENI_KASO_c " + MENI_KASO_c
if playmode = 1 : goto *プレイモード ;リプレイモードで来たらプレイモードに戻る
if playmode = 0 { ;プレイモード
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *保存選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *保存選択↑↓
}
;■■■■■■表示処理■■■■■■
if HZON_c = 0 { ;「1つ目に保存する」にカーソルが移動した場合
pos 100,200 : color 255 : mes "1つ目に保存する"
pos 100,220 : color 94,114,94 : mes "2つ目に保存する"
} else { ;「2つ目に保存する」にカーソルが移動した場合
pos 100,200 : color 94,114,94 : mes "1つ目に保存する"
pos 100,220 : color 255 : mes "2つ目に保存する"
}
;●●●保存処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
kioku = "replay" + HZON_c + ".dat"
poke replay,0,RP_TEKI_x(0)
poke replay,1,RP_TEKI_x(1)
poke replay,2,RP_TEKI_x(2)
bsave kioku, replay, 320000
goto *プレイモード
}
}
}
redraw 1 : await 1
goto *保存選択が終わるまで繰り返す
;*******保存選択↑↓**********
*保存選択↑↓
HZON_c = HZON_c + MENI_KASO_c
if HZON_c < 0 { ;↑を押した場合
HZON_c = 1
}
if HZON_c > 1 { ;↓を押した場合
HZON_c = 0
}
return

| |
|
2017/5/14(Sun) 10:39:38|NO.79749
空気さん。
色んなサイトを見てなんとなく動きはわかったのですが、
質問に答えるためいったん保留してたので、何故「OR」や「AND」がそういう機能なのかわからないままでした。
私の中では「OR:または」「AND:一致」っていうところにいたので、
ビット計算ではこうです!って言われても「え?OR?え?」ってところからスタートしてました。
このサイト様の内容はすごくわかりやすいですね。
私の検索の仕方が悪かったようなので参考にしてみます。ありがとうございます!
|
|
2017/5/14(Sun) 13:41:57|NO.79757
ランダムの結果をいちいち変数に入れていたら日がくれますよ〜
要はプレイ時とリプレイ時に同じ乱数を発生させればいいのです
rnd関数のヘルプをみればヒントが書いてあります
|
|
2017/5/14(Sun) 14:42:39|NO.79758
まちがい
randomize関数のヘルプを見てください。
|
|
2017/5/14(Sun) 14:53:16|NO.79759
ちなみにrandomize関数は、乱数系列を初期化するときだけ用いればよく、
通常はゲーム開始前に一度、実行しておけば十分です。
以後はその「初期化された系列の乱数」が順に発生するので、
rnd関数で呼び出すだけでちゃんと乱数になります。
上のアイドルさんのリストのように、
rnd関数で乱数を引く前に逐一randomize関数を呼び出す必要性はありません。
従って、「ゲーム開始直前にrandomize」するときに、
どういう値で初期化するかによって、以後の乱数の出目が決まるので、
初期化する値(乱数のシード)を保存しておけばよいわけです。
がんばってください。
|
|
2017/5/14(Sun) 15:02:20|NO.79760
シード値を指定した乱数のサンプルです。
randam_seedに同じ値を設定すると、乱数の出目は毎回同じになります。
シードの値をいろいろ変えて試してみてください。
;シード値を設定して乱数を初期化
randam_seed=128
randomize randam_seed
pos 0,0 :mes "乱数のシード値 "+randam_seed
;シード値の系列により初期化された乱数を発生
repeat 24
pos 0,cnt*16+32
a=rnd(100)
mes a
loop
stop
|
|
2017/5/14(Sun) 23:30:11|NO.79780
ZAPさんできました!
>>ランダムの結果をいちいち変数に入れていたら日がくれますよ〜
あぁ・・・やっぱそうですよねー・・・
>>randomize関数のヘルプを見てください。
おぉ、ん?んん?
んーーー・・・
>>rnd関数で乱数を引く前に逐一randomize関数を呼び出す必要性はありません。
初めて知った・・・そうだったのですね。
あんま使わない命令だったもんで配置場所まで気を使ってませんでしたorz
ヒントを頼りに色々調べてようやく理解できました。
randomizeのp1の数値によって、配置パターンが変わるんですね。全然知らなかったです・・・
(普通は「randomize」のp1意識しないから余計に時間かかった)
例えば「randomize 1」だとしたら「rnd」で「1」のパターンを呼び出すって感じですね。
そしてそのパターンがわかるものが、ZAPさんが書いてくれた乱数シードってわけですね。
んで、それがわかったのならパターンの値を変化するようにすればいいので、
そのやり方さえわかれば後はスムーズでした。
パターンの値を毎回変える方法は色々あると思うのですが「gettime」を使って
秒ごとにパターンを変えることにしました。
しかしこのままメインに適応すると、ここでやり取りしている人達にバレるのは非常にまずいので、
秒数などによって配列を呼び出す方法がいいかなーっと思って作り直そうと思います。
例)10秒→10番の配列を呼び出す
その配列の数値を「randomize」のパターンにする。とかね。
大変助かりました!これでリプレイのランダム要素もクリアできそうです!
本当にありがとうございます!長くなるので困った人のために次のレスでソース書いておきます。
|
|
2017/5/15(Mon) 18:44:32|NO.79788
gettimeなぞ用いなくとも、それこそ乱数初期化時にランダムからシード値を作ればよいのです。
randomize
rnd_seed=rnd(32768)
randomize rnd_seed
これで得られたシード値をリプレイファイルのヘッダ部分にでも保存しておけば・・・
あとはがんばってください。
|
|
2017/5/15(Mon) 21:51:42|NO.79796
ZAPさん。
レスしてから次の日の出かける前に乱数でもいいことに気がついて・・・いや・・お恥ずかしい・・・orz
朝は別の問題に気がついて、それの動作確認をしていました。
特定のタイミングでランダムを持った物が出現する場合は、if文などで制御しないといけなくって、
ifなで「rnd」をくくってあげないと、常に「rnd」に値が入ってしまい、乱数がずれてしまうので、
条件がある物はその条件どおりにくくる必要があることがわかりました。
ずっとミニソースでやってたので見落としてた部分だったので気がつけてよかったです・・・
また、乱数にどのように数値はいるかのシードソースは、
メインと同じ構成にしないと同じようにならないこともわかりました(例:ミニではリピード&ループ、メインでは「goto」など)
(デバックする時に必要になると思うので、ここら辺注意してやってみます)
ほんと色々ありがとうございます!大変助かりました!
|
|
2017/5/15(Mon) 21:55:15|NO.79797
役に立てるかわかりませんが。
困った人のために乱数用のソース出しておきます。
screen 0,240,320
*プレイモード
ki_iti = 0 ;データを書き込む位置
Activ_ID = 0 ;アクティブID
MENI_c = 0 ;リプレイの位置
RIPU_c = 0 ;ファイル選択の位置
MENI_KASO_c = 0 ;メニューカーソル
playmode = 0 ;モード
HZON_c = 0 ;保存の位置
TEKI_y = 0 ;敵弾
TEKI_c = 0 ;敵弾カウント
kasan = 0 ;ストップさせるための値
;*******プレイ選択肢***********
*プレイ選択
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "Activ_ID " + Activ_ID
pos 0,20 : mes "MENI_c " + MENI_c
pos 0,40 : mes "RIPU_c " + RIPU_c
pos 0,60 : mes "MENI_KASO_c " + MENI_KASO_c
pos 0,80 : mes "モード " + playmode
pos 0,100 : mes "RAN_PTN " + RAN_PTN
;■■■■■■読み込み処理■■■■■■
kioku = "replay" + RIPU_c + ".dat"
sdim replay,320000
;▼▼▼「プレイする」、「リプレイ」選択▼▼▼
if Activ_ID = 0 {
if MENI_c = 0 { ;「プレイする」にカーソルが移動した場合
pos 20,250 : color 255 : mes "プレイする"
pos 20,270 : color 94,114,94 : mes "リプレイ"
} else { ;「リプレイ」にカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "プレイする"
pos 20,270 : color 255 : mes "リプレイ"
}
}
;▼▼▼リプレイファイル選択▼▼▼
if Activ_ID = 1 {
if RIPU_c = 0 { ;「replay1」にカーソルが移動した場合
pos 20,250 : color 255 : mes "replay1.dat"
pos 20,270 : color 94,114,94 : mes "replay2.dat"
} else { ;「replay2」リプレイにカーソルが移動した場合
pos 20,250 : color 94,114,94 : mes "replay1.dat"
pos 20,270 : color 255 : mes "replay2.dat"
}
}
;●●●Zキー処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
if MENI_c = 0 : goto *ゲーム開始 ;「プレイ」を選択したら実行
if MENI_c = 1 { ;「リプレイ」を選択したら実行
Activ_ID += 1 ;アクティブIDを+1する
if Activ_ID = 2 { ;「リプレイファイル選択」を選択したら実行
playmode = 1 ;リプレイモードにする
goto *ゲーム開始
}
}
}
}
;************↑↓*************
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *プレイ選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *プレイ選択↑↓
}
redraw 1 : await 15
goto *プレイ選択
;*********プレイ選択↑↓**********
*プレイ選択↑↓
switch Activ_ID
;第一層
case 0
MENI_c = MENI_c + MENI_KASO_c ;カーソルの値を入れる
if MENI_c < 0 { ;↑を押した場合
MENI_c = 1
}
if MENI_c > 1 { ;↓を押した場合
MENI_c = 0
}
swbreak
;第二層
case 1
RIPU_c = RIPU_c + MENI_KASO_c ;カーソルの値を入れる
if RIPU_c < 0 { ;↑を押した場合
RIPU_c = 1
}
if RIPU_c > 1 { ;↓を押した場合
RIPU_c = 0
}
swbreak
swend
return
;***********ゲーム開始*************
*ゲーム開始
if playmode = 0 {
randomize ;乱数パターンをランダムに決めるるため初期化する
RAN_PTN = rnd(100) ;乱数を代入
}
if playmode = 1 { ;リプレイの場合ロードする
bload kioku, replay
RAN_PTN = peek(replay,0)
}
randomize RAN_PTN ;乱数のパターンを決める
;************メイン***********
*メイン
redraw 0 : color : boxf
;********カウンター***********
color ,255
if playmode = 0 : pos 0,20 : mes "プレイ中"
if playmode = 1 : pos 0,20 : mes "リプレイ中"
pos 0,40 : mes "リプ選択 " + RIPU_c
pos 0,60 : mes "TEKI_x " + TEKI_x
pos 0,80 : mes "TEKI_c " + TEKI_c
pos 0,100 : mes "パターン " + RAN_PTN
pos 0,120 : mes "乱数 " + RAN_TI
pos 0,140 : mes "kasan " + kasan
;***********************
gosub *敵弾
;敵弾
if TEKI_f = 1 {
pos TEKI_x,TEKI_y
color 255,,255 : mes "★"
}
if kasan >= 280 : goto *リプレイ保存処理
kasan++ ;ストップさせるための値
redraw 1 : await 16
goto *メイン
;************敵弾***************
*敵弾
if kasan >= 50 { ;←(if文)何かしらの条件でランダムが出現する場合のチェック用 (数値をなら数値、フラグならフラグを使う)
RAN_TI = rnd(100)
if TEKI_c <= 2 {
if TEKI_f = 0 {
TEKI_f = 1
TEKI_x = 100 + RAN_TI
TEKI_y = 0
}
if TEKI_f = 1 : TEKI_y += 5 ;↓に移動
if TEKI_y >= 330 : TEKI_f = 0 : TEKI_c++ ;一番下までいったら敵弾を「戻す」
}
}
return
;●●●●リプレイ保存処理●●●●
*リプレイ保存処理
;*****保存選択が終わるまで繰り返す*****
*保存選択が終わるまで繰り返す
redraw 0 : color : boxf
;************カウンター**********
color ,255
pos 0,0 : mes "HZON_c " + HZON_c
pos 0,20 : mes "MENI_KASO_c " + MENI_KASO_c
if playmode = 1 : goto *プレイモード ;リプレイモードで来たらプレイモードに戻る
if playmode = 0 { ;プレイモード
stick KASO
if KASO & 2 { ;↑ボタン
MENI_KASO_c = -1
gosub *保存選択↑↓
}
if KASO & 8 { ;↓ボタン
MENI_KASO_c = 1
gosub *保存選択↑↓
}
;■■■■■■表示処理■■■■■■
if HZON_c = 0 { ;「1つ目に保存する」にカーソルが移動した場合
pos 100,200 : color 255 : mes "1つ目に保存する"
pos 100,220 : color 94,114,94 : mes "2つ目に保存する"
} else { ;「2つ目に保存する」にカーソルが移動した場合
pos 100,200 : color 94,114,94 : mes "1つ目に保存する"
pos 100,220 : color 255 : mes "2つ目に保存する"
}
;●●●保存処理●●●
getkey Zkey,90 ;決定 (Zキー)
if Zkey = 0 AND ZkeyGate = 1 : ZkeyGate = 0;Zキーを押していない、Zキーゲートが立っている時 → Zキーゲートを「0」にする
if Zkey = 1 AND ZkeyGate = 0 {
ZkeyGate = 1 ;Zキーゲートを「立てる」
if Zkey {
kioku = "replay" + HZON_c + ".dat"
poke replay,0,RAN_PTN
bsave kioku, replay, 320000
goto *プレイモード
}
}
}
redraw 1 : await 1
goto *保存選択が終わるまで繰り返す
;*******保存選択↑↓**********
*保存選択↑↓
HZON_c = HZON_c + MENI_KASO_c
if HZON_c < 0 { ;↑を押した場合
HZON_c = 1
}
if HZON_c > 1 { ;↓を押した場合
HZON_c = 0
}
return

| |
|
2017/5/16(Tue) 21:58:37|NO.79816
あ、解決入れ忘れてました。
皆さんお忙しい中本当にありがとうございます!
アドバイスしてもらったところは、落ち着いたタイミングで勉強しようと思います。
またわからない時があったらなるべく簡潔に描きますがその時があったらまたよろしくお願いしますペコリ(o_ _)o))
リプレイ機能が正常までいけたら1面が完成するので、その時になったら是非プレイしてくださいませ><
今はこんぐらいしかお礼ができないけど><
|
|