あつし様とyuki様の対談で構成された当たり判定の講義を掲載致しました。
当たり判定に関しては、非常に役に立つお話です。
あつし様によるサンプルも同時掲載しています。
あつし様とyuki様によるあたり判定対談
HSPによるものですが、Lingoにも十分対応できます。
あつし様、yuki様ありがとうございます。
BBSでのあつしさんの当たり判定の書き込みを記録しました。
yukiさんと、あつし様の対談で構成されています。
-関連リンク-
ZOO・・・・・・強力なマップエディタ「MapEdiyr(マップ・エディル)」を公開しているあつし様のサイトです。
『MapEdiyr』・・・・・・あつし様制作の驚愕の高性能マップエディタです。是非、一度触れてみてください。
■どうしたらいいのやらまったくわかりません
どのようにして当たり判定&進入禁止これってどうやってするんですか?
■マップはどのように作ってるのでしょう?
そのマップの作り方によって衝突の判定方法は異なります。
簡単なのでは、「全て正方形で構成する」とか、
チョット複雑にして、「正方形に対角線を引いて、正方形の内部にも、歩けるところと、歩けないところを作る」とか、「多角形の内部が歩けて、外部は歩けない」とか、いろいろ有りますよね?
もしマップに高低差があると、また変わってきます。
「ゆきだるまの物語」を例に考えてみると、
どうも、斜めの直線とかが多いので、マップを正方形に区切るとすると、正方形が非常に小さくなります。
仮に、大きな正方形でマップを構成すると、斜めの直線のところでは、ごつごつしてしまって、目に見えない出っ張りが、ユーザーを苦しめることになります。
■ そう考えると、マップを、一辺が1~2ピクセルの正方形で区切ることになります。
すると、データ量が増えて、マップデータを作るのに、
時間がかかるかもしれません。
(専用のソフトを作れば、全然大変ではないですが、打ち込みだときついかも。でも、ソフトさえ作ってしまえば、凄く強いかも。)
さて、何らかの方法で、マップを作ったとしましょう。
そして、マップ上のある位置において、そこが、
歩ける場所かどうかを返す関数を
bool IsWalkable( x, y )
とでも定義しましょう。
(注意:関数IsWalkableは、マップ上のある点の座標を示す2つの整数値を引数にし、そこが「歩行可能」ならtrueを返し、「不可能」ならfalseを返す関数。)
【1】ユーザーが、十字キーの右を押す。
【2】キャラが、移動する先の位置を計算する。
(計算するだけで、移動はさせない。)
【3】IsWalkable関数で、移動先の位置が、歩行可能な場所かどうかをチェックする。
【4】可能であれば、移動し、そうでなければ移動しない。
■最も単純な方法はこんなカンジでしょうか?
実際には、滑りとか、壁に沿って移動するとかを実現するためには、正方形で区切るのではなく、多角形で区切るべきでしょう。
マップをどう表現するかによって、また要求されるアクションに応じて、判定方法は異なりますので、あくまで概念的なことしかいえませんが、具体的にコードを示してくれれば、もっと具体的なアドバイスもできると思います。
■私が使っているソフトはHSPです。
マップチップを並べた所にキャラを歩かせることが出来るようになった程度のおばかさんです。
一辺あたり32×32の正方形のチップを並べたマップです。あつしさんが言っているような複雑なマップは私にはとても作れません。
【1】ユーザーが、十字キーの右を押す。
【2】キャラが、移動する先の位置を計算する。
(計算するだけで、移動はさせない。)
【3】IsWalkable関数で、移動先の位置が、歩行可能な場所かどうかをチェックする。
【4】可能であれば、移動し、そうでなければ移動しない
上のような過程をへて通行可能だとかを判断しているんですか、ん~ん、、なるほど~
うう、、、アドバイスを頂いたのはいいんですが良くわからないです、ごねんなさい、おバカな私にはどうやって作っていいのやら、、、
■チップの事で質問ですが、
えっと、一辺が1~2ピクセルってそんなに小さくですか、それと「大きな正方形でマップを構成すると、斜めの直線のところでは、ごつごつしてしまって」とありますがどのくらいから大きなに入るでしょうか。
■ごつごつしてしまうのは、あくまで、感覚的なものです。
ですから、「具体的にどこから」と言う事はありません。
例えば、45度の直線を、32×32の正方形を並べて描くと、
ごつごつしませんか?
でも、90度に近い、80度なら、45度のと比べると、
それほどごつごつしません。
(うぅ、この説明で分かって頂けるかな~?)
ですから、「ゆきだるまの物語」の様に、
いろんな角度の直線があって、
しかもごつごつした感じを出さないようにするためには、
正方形を出来るだけ小さくすべきだろうと考えたわけです。
と、ここまで書いてきましたが、
あくまでこれは、「マップを正方形で区切る場合」です。
ゆきだるまの物語の場合は、別の方法をとるべきでしょう。
(すぃくさんはどうしてるんだろ?)
で、本題に戻りますが、
「キーの入力を受け取る部分」は有りますか?
(と言うかあるはず。)
その部分をまず探しましょう。
見つかったら、ここに書いてみてください。
まったりと行きましょう。
あせる事ないです。(^^)
■こんばんは~
あっそうか、まっぷのゴツゴツ感ってそうですよね、確かに感じます。
小さくする事でなめらかになるんですね。
えっと、キー入力の情報取得ですよね、HSPの場合
stickとgetkeyですよね、
stickの方を使ってキーの情報を取得しました。
これでいいんですよね
■HSPには手も触れたことない私ですが、
にわか勉強してみました。
で、作ったサンプルがこれ。
サンプル(ソース付き)
まあ、実行してみてください。
そんな感じです。
ちゃんと海と、山にぶつかってるでしょ!?(^^)ノ
(あ、ちなみに操作は十字キーだけですので。
「海に見えね~」とか「これ、山?」とか言う苦情はごかんべんを・・・。)
さてさて、問題は「どうなってるの」ですよね?
ソースを見ていきましょう。
(一番メインとなるところは、なんと言っても、
key関数です。)
■まず、画像を読み込む。
buffer 2;
picload “player.bmp”;
buffer 3;
picload “map.bmp”;
次に定数が二つほどあります。
#const TRIGER 1+2+4+8
#const MOVE 4
TRIGERは、stickに渡すパラメータです。
この場合、十字キーすべてについて、
押されている間は、命令を受け取る必要がありますからね。
MOVEは、キャラクタの移動量です。
この値が大きくなるほど、キャラクタはスピードアップします。
(ただし、1、2、4、8、16、32のどれかにするようにして下さい。でないと、判定がうまく行きません。
コードでは4にしました。)
次は、おなじみのコード
screen 0,320,320,4;
title “sample1″
そして、つぎに、キャラクタの座標を入れる変数を書きます。
x = 0;
y = 0;
さて、次は重要なマップデータの作成です。
dim map,10,10;
map.0.6 = 1;
:
省略
:
map.9.6 = 1;
配列は、作成されると、0に初期化されていますので、
歩けるところを0とし、歩けないところを1とすることにしました。
■つまり、山と海のところは1になります。
左上から、32×32の正方形に区切っていくと、
画面のサイズは320×320ですから、縦横10個ずつの合計100
個のマス目に区切られます。
左上のマス目を0行0列として、その右は、0行1列となります。
一番右下は、9行9列で、その上は、8行9列ですね。
ですから、map.bmpに書かれている通りに、山のマス目と、海のマス目のところを、1にしていきます。
(チョットめんどいですね・・。専用のソフトを作るべきかも・・。)
次もおなじみのmain関数です。
ループさせてます。
ここで呼び出しているkey関数は、ユーザーの入力を受け取って、キャラクタの座標(x、y)を変更する関数。
paintは、その情報をもとに、キャラクタと、マップを表示する関数です。
awaitは、windowsに処理を返しているだけです。
*main
gosub *key;
gosub* paint;
await 1;
goto *main
■次に来るのは、(このソースの)ラスボスのkey関数ですが、
そのまえに、下っ端のpaint関数を倒しておきましょう。
redrawは、ちらつきを抑えるために書いているだけで、
なくても動作しますが、書いておきましょう。
次に(白で)画面をクリアしていますが、
よくよく考えると、その2行はいりませんでした。
(なぜかというと、map.bmpを次に画面いっぱいに描画しているからです。)
マップの描画と、キャラクタの描画をして、
終わりです。
*paint
redraw 0;
color 255,255,255; 画面をクリア
boxf 0,0,320,320;
pos 0, 0;
gmode 0,320,320,256;
gcopy 3,0,0,320,320;
pos x,y; 画像を表示
gmode 3,32,32,200;
gcopy 2,0,0,32,32;
redraw 1;
return
■さて、ついに来ました。ラスボスが!?(何
このコードの半分ほどを占める超大作(ウソ)です。
まず、大まかな概要から説明します。
下に書いたのが、key関数の骨組みです。
*key
stick keycode, TRIGER, 1;
if( keycode&1 ){
}
if( keycode&2){
}
if( keycode&4){
}
if( keycode&8){
}
return
■まず、stick命令で、押されているキーのコードを受け取り、
次に、if文で押されていた時の処理を書いています。
ここで、押されるであろうキーは、十字キーの4つのキー(上下左右)で、それぞれのキー番号が、左が1で、上が2、右が4で、下が8です。
まず、左が押されていた時の処理を考えて見ましょう。
キャラクターは、いまフィールド上にいて、
左に移動しようとしています。
移動後の位置は、(x-MOVE、y)ですね?
(キャラクターの位置は、キャラクターの左上の頂点の位置のことです。真ん中ではありません。)
移動後に、キャラクターが、山とか海にぶつかったかどうか判断するには、キャラクターの左上の頂点と左下の頂点が、マップ上の「歩ける」所の上にあるかどうかを判断すれば良いのです。
(それで判断できるのは、キャラクターの移動量が32以下で、マップの1マス分を、飛び越えないからです。)
■では、それをどうやって判断すれば良いでしょうか?
まず、移動後の、左上の頂点と、左下の頂点の座標を考えましょう。
左上は(x-MOVE,y)ですね。
左下は(x-MOVE,y+31)ですね。
(「な ぜ31なのか?32じゃないの?」と思うかもしれませんが、ゆっくり考えてみてください。32×32の正方形の、左上の頂点を[0,0]とすると、その下 の2番目の頂点は[0,1]です、さらにその下の3番目の頂点は[0,2]となります。ですから、32番目の頂点は[0,31]なのです。つまり、左上が [x、y]なら、左下は[x、y+31]となります。)
さて、座標は計算できました。
とりあえず、この計算した値を、
tmpx = x-MOVE;
tmpy = y;
tmpz = y+31;
として入れておきましょう。
つまり、左上は(tmpx,tmpy)で、左下は(tmpx,tmpz)となります。
(tmpは、temporary<一時的な>という意味です。)
■さて、座標はわかったけど、この座標が、
マップ上の、どのマス目に入るかを計算しなくてはいけません。
その計算は簡単です。
ソースに有るように、32で割ってやれば良いのです。
tmpx = tmpx / 32;
tmpy = tmpy / 32;
tmpz = tmpz / 32;
本当なら、割ると小数点以下に数がつづくのですが、
HSPでは整数に勝手にしてくれて、1.763とかも、1にしてくれます。
ですから、32で割ると、tmpxが0~31なら0になり、32~63なら1という風になります。
これは、マス目の番号になりますね。
つまり、左上の頂点はtmpy行tmpx列、左下はtmpz行tmpx列となります。
しかしここで問題が一つあります。
キャラクターが、左隅から、画面外へ出て行ってしまった場合です。
つまり、tmpxが0より小さくなる時です。
しかし、tmpxは-31より小さくなることはありえませんから、32で割ると、-0.xxxとなり、整数に変換されて0となり、結局この場合もオッケーとなります。
■さて、ここまで来れば、後は簡単。
map.tmpy.tmpxが0で、かつmap.tmpz.tmpxも0であるかどうか確かめるだけです。
そして、もしそうだったら、キャラクターの座標を更新します。
x -= MOVE;
ただし、ここで忘れてはいけないのが、
キャラクターが画面左端から外に出て行ってしまう場合です。
そうならない様に、
if( x < 0 ){
x = 0;
}
としておきましょう。
@チョット休憩・・・
さて、あと上と右と下が有りますが、
左の場合とほぼ同じことをしていますので、
分かるのではないかと・・・・。
わかんなかったら遠慮なくど~ぞ~。
(というか、この説明で分かっていただけたのだろうか?)
P.S.なんか、異様に長くなってしまいました。m(__)m
■ソースまで付けてもらっちゃって、その上ソースの説明をこと細かくしてくれて本当にどうもありがとう~!!
山と海の所を歩けないようになってる。
初めてのソフトであつしさんはこんなすぐに作れるなんてスゴイです!!
マップのサイズが320×320になっているんですね。
一枚でマップを呼び込むんですね、一枚で呼び込むのって重くないですか、大丈夫ですか?
チップで呼び込んでマップを構成するのとどう違うんだろう?
えっと~、マップで1の所が歩行禁止ですか
「配列は、作成されると、0に初期化されていますので、
歩けるところを0とし、歩けないところを1とすることにしました。」
↑上のようにありましたが、
作成されると、0に初期化されていますって、どういうことですか?
ほかにもなんで32で割るのだとか、
えっと関数、関数って出て来ますが、関数って何ですか?
■プログラミングって言うのは、一度やったことなら、たいていチャチャットできてしまうものです。
>一枚で呼び込むのって重くないですか、大丈夫ですか?
う~ん、どうでしょうか?
HSPの内部構造を私は知りませんし、このあいだ始めて使ったばかりなので、経験則とかもいえません。
ただ、320×320とかなら、普通は問題ありません。
言語が違いますが、800×600の画像とかを、ぼこぼこ読み込んだり消したりした事あるので・・・。
ただし、メモリがシビアなら問題かもしれませんが、
おそらく、そんな環境では、まともなソフトは動きません。(特にゲーム)
■ >0に初期化されていますって、どういうことですか?
例えば、
dim a,10;
と書いたとしましょう。
このコードでは、「名前がaの、要素数が10の配列」を作っています。
では例えば、このコードのすぐ後に、
mes a.0;
と書いたとしたら、一体何が書かれるでしょうか?
つまり言い換えると、a.0には、どんな値が入っているでしょうか?
答えは、0です。
普通は、
a.0 = 45;
として、値を代入しますが、
もししなくても、もとから0という値が入っているのです。
(「そんなの当然やん。」とは思わないで下さい。
例えば、c++という言語なら、0にはならず、予測不可能な値が入ります。237657とか、-12など。あくまで
、HSPが新しく作った変数とか配列の要素を、0で”初期化”してくれているだけなのです。)
■ このように、もとから何もしなくても、新しい変数とか配列の要素には、0がはいっている事を、「0に初期化されている」と言います。
もし仮に、新しい変数や配列の要素に、もとから-1が入っていたとすると、「-1に初期化されている」という事になります。(そんな言語見たことありませんが・・)
ちなみに、このもとから入っている値の事を、初期値と言います。(物理とかで、出て来たりすると思います。)
さて、コードの中では、1にセットしてばかりで、
0にセットしているものは一つもありません。
1にセットしなかった配列の要素は、もとから0です。
ですから、セットする必要がなかったのです。
だから、省略したのです。
これができるのは、「0に初期化されている(もとから0になっている)と分かっている」からです。
■ >なんで32で割るの?
マップは、32×32の正方形を並べて作ってありますよね?
そして、その一つ一つの正方形に対して、「歩ける(0)」か「歩けない(1)」という情報をセットしました。
「どこにセットしたの?」というと、あのmapという名前の配列にセットしたのでしたね?
いま、画面の大きさは320×320ですから、32×32の正方形で区切ると、縦横10個ずつの計100個の正方形で区切ることになります。
(サンプルを見てみてください。チェックマークのようになっているでしょう?その一つ一つの正方形が、32×32のサイズになっていて、縦横ちょうど10個ずつあります。)
まず、区切ったそれぞれの正方形に、番号を割り当てましょう。
一番左上の正方形を0行0列とし、その右を0行1列、さらにその右を0行2列、さらにその次は0行3列と言うことになります。
また、一番左上の0行0列の正方形からみて、その下は、
1行0列の正方形で、さらにその下は2行0列となります。
ちなみに、一番右下は、9行9列です。
■ さて、番号をつけましたが、これに何の意味があったのでしょうか?
例えば、「n行m列の場所にある正方形」を考えましょう。
この正方形上をキャラクターが歩けるでしょうか?
つまりこの正方形の持つ「歩ける(0)」か「歩けない(1)」かという情報は、配列mapのどこに格納されているのでしょうか?
答えは、「map.n.mに入っている。」です。
つまり、map.n.m が0ならば歩けて、1なら歩けないことになります。
さて、ではマップ上のある座標(x、y)が、歩ける正方形の上かどうかを確かめるにはどうしたら良いでしょうか?
それには、座標(x、y)が、何行何列の正方形の上なのかを知る必要が有ります。
もしそれが分かれば、先ほど見たように、その正方形の上が「歩ける」かどうか分かり、座標(x、y)が「歩ける」場所なのかどうか分かります。
x/32は、列番号に。
y/32は、行番号に対応すると思いませんか?
つまり、座標(x、y)の点は、(y/32)行(x/32)列の正方形上にあると思いませんか?
じっくり考えてみてください。
■ (「x/32は小数にならないの?例えば、xが16の時、x/32は0.5じゃないか!!0.5列って何だよいったい!!」と思うかもしれません。
しかし、HSPでは数値は全て、整数に勝手に変換されます。
その場合、四捨五入などと言う事はしてくれません。
小数点以下は切り捨てです。つまり、先ほど見た0.5は、0になってしまうのです。
つまり、0列のことを意味するんです。それから、一つ注意しておかなければならないことがあります。
それは、x座標もしくはy座標が-32以下または320以上のときです。このとき、x/32は-1以下もしくは10以上となってしまいます。
しかし、-1列とか、10列とかは存在しませんので、そうならないように、サンプルでは、少し手を加えてあります。
if( tmpx > 319 ){
tmpx = 319;
}
このようにして、320以上になったりしないようにしているのです。
ちなみに、-32以下になることは「テレポートでもしない限り」ありえないので、何の対策もしていません。
)
■ >関数って何?
実はこれ、僕の間違いでした。
HSPには、関数などどうやら存在しない(?)ようですね。
たいていの言語には、関数という概念があるので、
あるものと思ってしまいました。
関数ではなく、ラベルの間違いです。
key関数ではなく、keyラベルですし、
paint関数ではなく、paintラベルです。
ラベルについては、HSPのヘルプをごらんあれ~。
■マップの一枚呼び込みって320×320ぐらいであれば問題ないんですね、良かった~
0に初期化する、そういうのがあったんですね、全てではないにしても、ん~んなるほど、、
まったく知りませんでした。
HSPは少数にならないってことは細かい計算は出来ないのかな?
以前なんとかマップチップ上でキャラを歩かせる事が出来たって喜んでいた物ではなく、新しく作ってみました。
なんとか作れるものですね。以前はまったくわからなかったのに、、、
↓こんな感じにマップ表示とマップ上のキャラ移動を作っていました。
■ buffer 2,32,32 :picload “kyara.bmp”;キャラ
buffer 3,32,32 :picload “kusa.bmp” ;草1
buffer 4,32,32 :picload “mizu.bmp” ;水2
;このまま実行しても動きません、↑素材を用意しないとだめですね、
screen 0,320,320
dim map,10,10
map.0.0=1,1,1,2,2,2,2,2,2,2
map.0.1=1,1,1,1,2,2,2,2,2,2
map.0.2=1,1,1,1,1,2,2,2,2,2
map.0.3=1,1,1,1,1,1,2,2,2,2
map.0.4=1,1,1,1,1,1,1,2,2,2
map.0.5=1,1,1,1,1,1,1,1,2,2
map.0.6=1,1,1,1,1,1,1,1,2,2
map.0.7=1,1,1,1,1,1,1,1,1,2
map.0.8=1,1,1,1,1,1,1,1,1,2
map.0.9=1,1,1,1,1,1,1,1,1,2
*main
redraw 2 ;画面には描画しないモード
;——-マップチップ描画—————————-
repeat 10,0 : cntx=cnt : repeat 10,0 : cnty=cnt
if map.cntx.cnty>-1 : pos cntx*32,cnty*32 : gcopy 3
if map.cntx.cnty>1 : pos cntx*32,cnty*32 : gcopy 4
loop : loop
■ ;——-キー入力————————————
stick key,1+2+4+8
if key&1:x=x-3 : if x<0 : x+3
if key&2:y=y-3 : if y<0 : y+3
if key&4:x=x+3 : if x>290 : x-3
if key&8:y=y+3 : if y>290 : y-3
pos x,y
gcopy 2
gmode 2
redraw 1
await 15
goto *main
■ 教えていただいた当たり判定は一枚で取り込みですよね、もし当たり判定を↑上のに組み込む込むとしたらどうやったらいいでしょうか?
それと、キャラの方向で、いろんな方向にキャラを見えるように組み込むにはどうしたらいいんですか?
上を押すと上向きのキャラが下を押すと下向きのキャラみたいにです。
■ こんどはどういう仕組みになるんだろう?
マップを並べたものを保存しなきゃいけないんですよね、
BMPなどで出力しなきゃいけないのかな~
BMPとかでなくてデーターで保存するのかな?
マップがそのままホルダーの中で見えてしまうとゲームが面白くなくなっちゃうし・・・。
えっと、プログラムの設計図みないなのでなんかありましたよね、
そんなのをどこかで見たような覚えがあるのですが、
名前はチャットににたような感じだったような、、、間違っていたらゴメンナサイ。
いまさらですが私が作りたいのはRPGです、行きなりエベレストに挑んだら間違いなく遭難してしまいますよね。
私は本当に幸せものです。
二人の先導者、すぃくさんとあつしさんのご協力の下少しずつお山を登れるのですから。
お二人には感謝感謝です!!
■@もし当たり判定を↑上のに組み込む込むとしたらどうや
@ったらいいでしょうか?
私たちが今やっているあたり判定の方法は、
下にどんな絵があるかにまったく関係ありません。
ですから、同じように組めばそれで良いのです。
今回のサンプルはこちら。
サンプル(ソース付き)
チョット今時間がないので説明は後回しですが、
やってることは殆ど変わっていません。
paintラベルのところの、マップを表示する部分が少し変わった程度です。
■ @いろんな方向にキャラを見えるように組み込むには
@どうしたらいいんですか?
先ほどのサンプルに、少し手を加えたのがこちら。
サンプル(ソース付き)
殆ど同じですね。
変数mukiに、最後に押されたキーに応じて、
値をセットして、表示する時に、その値に応じて、
処理を変えているだけです。
@えっと、プログラムの設計図みないなのでなんか
@ありましたよね、そんなのをどこかで見たような
@覚えがあるのですが、名前はチャットににたよう
@な感じだったような、間違っていたらゴメンナサイ。
@もし良かったら、おバカな私にはイラストのような
@これだと解りやすいかもです、もしよかったら
@チャットでプログラムの動きを教えてくれませんか。
この文章なのですが、私には良くわからなかったのですが・・・・。
最後のチャットはchatのことですよね?
”プログラムの設計図”とはいったい?
■サンプルどうもありがとう!
今までと変わらないんですか、そうなんだ、あっ、ムキの変数が方向ごとにですか、そっかこうするのか、
なるほどスゴイ!!
いままでサブルーチンってほとんど使ってこなかったけど
なんかすごいですねサブルーチンって、それに見やすいですね。
調べてみたのですが、チャートでしたフローチャートと言うようです。本当にごめんなさい
マップチップ描画の所ですがなんか長いような、
ためしに元のをこのようにしてみたらエラーが出ました。
はじめにカキコしたのもチョッとおかしかったんですよね。ほんとゴメンナサイ。
↓直してみました
;——-マップチップ描画——————
repeat 10,0 : cntx=cnt : repeat 10,0 : cnty=cnt
if map.cntx.cnty>-1 : pos cntx*32,cnty*32 : gcopy 3
if map.cntx.cnty>1 : pos cntx*32,cnty*32 : gcopy 4
loop : loop
■@マップチップの描画を直してみました
見たところ、ちょっと問題があります。
問題は、
if map.cntx.cnty>-1 : pos cntx*32,cnty*32 : gcopy 3
if map.cntx.cnty>1 : pos cntx*32,cnty*32 : gcopy 4
の部分です。
始めのif文では、「map.cntx.cntyが-1より大きい時」となっていますから、1の場合も、2の場合も実行されます。
さらに次のif文では、「map.cntx.cntyが1より大きい時」となっていますから、2の場合に実行されます。
つまり、「map.cntx.cntyが2の時」には、同じ場所にgcopy 3とgcopy 4をすることになります。
二重書き込みしていることになるわけです。
■速度的に、それで問題なければそれでも良いですが、
HSPはスクリプト言語ですから、処理速度はそんなに速くありません。
他にも、いろんな機能を追加していくことを考えると、
少し問題となるかもしれません。
sample2のコードでは、
if( map.cnty.cntx == 0 ){}
if( map.cnty.cntx == 1 ){}
としていますが、こうすれば、二重書き込みはなくなりますよね?
まあ、ちゃんと動くなら、どちらでも良い話ではありますが・・・。
■やっぱり問題があったんですね、ごめんなさい。これだと二重書き込みになちゃうんですね、んん、、、
いろいろ付け加えていくと問題が出てくるんですね。
if( map.cnty.cntx == 0 ){}
0の所を2、3なんかにして、今までのように作ったらOKですよね。
if( map.cnty.cntx == 0 ){}
if( map.cnty.cntx == 1 ){}
if( map.cnty.cntx == 2 ){}
みたいな形にして配列に2の所を加えて今までのようにbufferに素材を作ってそれを持てくればいいですよね、あっていますか?
こうすればイロイロな地形を作れますよね。でもこれだとbufferなんかを余計に使っちゃいますよね。
やっぱり、マップエディータを作った方がいいのかな~
ん~ん、、、、
上の所で=が二つ続いていますよね。
==ってありますが、これって=とどう違うの?
それと{ }←の使い方が解りません。何の役割をしているんですか?
■@bufferに素材を作ってそれを持てくればいいですよね、
@あっていますか?
あってますよ~。
それで良いと思いますよ~。
@bufferなんかを余計に使っちゃいますよね。
別にそれで良いと思いますよ~。
いっぱい使う事になるかもしれませんが、
それはやむ負えないと思います。
@==ってありますが、これって=とどう違うの?
HSPプログラミングガイドを見ましょ~ね~。
こう言うわかんない事が出てきたら、プログラミングガイドを見ましょう。
たいていはそれで解決します。
それでダメなら、実験してみましょう。
例えば、sample2の==の部分を、=に変えてみてください。
何も変わりませんね?
HSPでは、(恐ろしいことに)”==”と”=”は同じ意味を持ちます。
他の言語では、この二つを使い分ける場合が多いのですが、「HSPではまったく同じ」です。
■{}は、式をまとめて書くときに使います。
以下の二つを見てください。
if(条件式){
式1;
式2;
}
if(条件式)
式1;
式2;
上のコードでは、「条件式が真の時には、式1と式2の両方が実行されます」また「偽の時は、両方とも実行されません」。
下のコードでは、「条件式が真の時には、式1と式2の両方が実行されます」が、「条件式が偽の時にも、式2は実行されます」。
上の方のコードは、
if(条件式)式1:式2;
と一緒です。
(もしかしたら間違えてるかも・・・・。
HSPは、だいぶ他のメジャー言語と異なるので・・・、常識が通用しない・・・。)
■=の件で本当にゴメンナサイ。
たしか==と=は同じみたいなことはたしか書かれていたかとおもいます。でもなんで同じなのに二つなの?と疑問になってしまって、聞いてみたのですが、本当にゴメンナサイです。
if( map.cnty.cntx == 2 ){}
↑このあいだの2だとかに変えたら違う地形にできました。
でもこれだとここも歩行禁止になってしまってるんですよね。
前に教えてもらった一枚取り込みの方法だといろんなチップの上を歩かせたりも出来るんですよね。
やっぱり前の方がいいのかな~
ところで、マップエディタってどういう構造になっているんですか?
まず素材を用意して、今までと同じように配列を使ってマップを作るんですよね。
それから、出来たマップをセーブかな?
手順というかこんな感じですか?
大雑把ですけど、ほかに何かありますか?
マップのところですが、
エラーになっているっていうかマップが反転していますが、どうしてでしょう?
これでいいんですか?
■@マップエディタ
マップエディタが必要なのは、
「マップがでかくなると、打ち込みがしんどい」
という理由です。
例えば、配列が今は10×10でしたが、100×100とかになると、チョットいらいらしませんか?
さらにこれが、100×100を10個とかなると、パソコンに八つ当たりしてしまうかもしれません。
いちいち「ここは山だから3ね~」「ここは浜辺だから4~」とかやるのはしんど過ぎです。
■そこで、しんどい事はパソコンにやってもらおうと言う事になります。
ですから、マップエディタの御仕事は、
「完成したマップから、配列を計算して、配列を生成するコードを書き出す」事です。(他にもいろいろ有りますが・・)
[マップエディタの一例]
さて、今回のサンプルはこちら。
サンプル(ソース付き)
(超ぷち)マップエディタです。
さすがに、にわか勉強では限界が見えてきました。
で、操作方法の説明。
①マウスの左をクリックすると、クリックされた場所が、草→水→山→草と変って行きます。
②マウスの右をクリックすると、現在の状況をmapcode.txtに保存します。
③エンターキーを押すと、mapcode.txtから、データを読み込みます。
■今回のサンプルでは、palhsp.hpiというプラグインを使用しています。
このpalhsp.hpiをHSPの”本体”があるところに置いて下さい。(例C:\Program Files\hsp26)
実行ファイル(hsptmp.exe)を実行するだけなら必要ありませんが、tpd001.asを実行するためには必要です。
@マップのところですが、
@エラーになっているっていうかマップが反転してい
@ますが、どうしてでしょう?
@これでいいんですか?
う~ん、言っている意味が良くわからないです。
もう少し、具体例を挙げてみてもらえませんか?
■今回のサンプル、メインとなるのは、
やはり、keyラベルのところです。
チョット難しいかもしれませんね・・・?
ですが、基本の積み重ねです。
なんとな~く分かっていただけるのでは・・・?
「ここ何してんの?」というところが有れば、容赦なく言って下さい。
なお、今回使用したプラグインについては、
こちら
をご覧下さいませ。
■なるほど、たしかにマップが大きくなると打ち込みってきつくなりますよね。
そこでマップエディタが必要になってくるんですね。
■マップが反転って書いていたのは、
↓プログラム上こうなっていますが、
dim map, 10, 10;
map.0.0 = 0,0,0,1,1,1,1,1,1,1;
map.0.1 = 0,0,0,0,1,1,1,1,1,1;
map.0.2 = 0,0,0,0,0,1,1,1,1,1;
map.0.3 = 0,0,0,0,0,0,1,1,1,1;
map.0.4 = 0,0,0,0,0,0,0,1,1,1;
map.0.5 = 0,0,0,0,0,0,0,0,1,1;
map.0.6 = 0,0,0,0,0,0,0,0,1,1;
map.0.7 = 0,0,0,0,0,0,0,0,0,1;
map.0.8 = 0,0,0,0,0,0,0,0,0,1;
map.0.9 = 0,0,0,0,0,0,0,0,0,1;
↓実際に表示されるときにはこういうふうに
dim map, 10, 10;
map.0.0 = 0,0,0,0,0,0,0,0,0,0;
map.0.1 = 0,0,0,0,0,0,0,0,0,0;
map.0.2 = 0,0,0,0,0,0,0,0,0,0;
map.0.3 = 1,0,0,0,0,0,0,0,0,0;
map.0.4 = 1,1,0,0,0,0,0,0,0,0;
map.0.5 = 1,1,1,0,0,0,0,0,0,0;
map.0.6 = 1,1,1,1,0,0,0,0,0,0;
map.0.7 = 1,1,1,1,1,0,0,0,0,0;
map.0.8 = 1,1,1,1,1,1,1,0,0,0;
map.0.9 = 1,1,1,1,1,1,1,1,1,1;
反転といったのはこういうことですが、これでいいんですか?
マップの反転
直す方法はありますが、別に問題ないと思いますよ?
プレイヤーは、コードなんて見ませんし。
見たって理解できない。
「動けばいいのです!!たぶん!!」(ウソ)
でもま~、綺麗なコードはもっと後で追求したらいいんじゃないでしょうか?
@何度もクリックしたくなるこの中毒性
そこまで言って頂けると、うれしい限りです。^^
もっとも、アプリケーションとしてはあまり役立ちませんが。バックアップの方、宜しくお願いします。
おはようございま~す
マップの反転はエラーっと言うわけではないんですね。
そうですよねたしかに、プレイヤーにはプログラムは見えませんものね。安心しました。いろいろくふうしてみます。
if( map.cnty.cntx == 2 ){}
↑数字2とか3に変えていくと。
これって、配列の当たり判定で0が歩けて1が歩行禁止
にでしたよね、やっぱり2なんかは歩けなくなちゃいますか?
歩けなくなちゃいますか?
今は、「0が歩けて」「1が歩けない」にしていますが、
例えば、「0以下が歩ける」「1以上は歩けない」にしたら、2とか3にしても問題はないですよね?
あたり判定の部分で、
if(( map.tmpy.tmpx == 0 ) && ( map.tmpy.tmpz == 0 ))のところを、
if(( map.tmpy.tmpx <= 0 ) && ( map.tmpy.tmpz <= 0 ))にすれば、万事オッケーです。
こうする事で、歩ける場所にもさまざまなバリエーションを加える事ができます。
例えば、いまは0を草にしていますが、-1を湿地帯とかにしても、「そこは歩ける事になります」。
歩けない場所も、同様にして追加できます。
こんばんは~
本当だ今まで歩けなかったところが歩けるようになりました。本当にありがとう!!う~ん、なるほど~<=0ですねこうすればいいんですね。
こうなると、マップの幅が広がっておもしろですね。
本当に本当にありがとう!
できました。こちら
マップエディタ
リリース0.5アップしました。
@選択範囲
選択範囲を解除するには、メニューの「選択範囲(S)」→「選択を解除(D)」を押してください。
選択範囲に関する操作は、他に「全てを選択」「選択範囲を反転」が有ります。使ってみてください^^
あんまり驚かせないでよあつしさん、心臓止まっちゃうよ~!!
なんかペイントツールのような感じのマップエディタですね。選択範囲に塗りつぶしなんて、作業効率アップにとても効果的ですよね。は~~、、すごいな~、、、
ヒストリー機能でしたっけ、こんなことも出来ちゃうの?スゴイな~は~~~、、、
ため息つきっぱなしです、、、
あの、虫眼鏡の拡大って出来ないけどこれでいいんですか?
使っていただいてありがと~
で、問題の虫眼鏡ですが、虫眼鏡は本来なら、
@「左クリックで拡大」
@「右クリックで縮小」
@「マウスの真ん中のホイールを回して拡大縮小」
とするはずでした。
しかし、現在のところ、
@「マウスの真ん中のホイールを回して拡大縮小」
しかできません。
しかも、倍率は1/2倍と1倍と2倍のみです。
ですが、この機能の実装は、比較的簡単なので、
次のバージョンには、実装できると思います。
マウスの真ん中の所をクリクリすると拡大縮小しますね、スゴイ!!
これってHSPで作ったんですか?
メニューの所なんかすごいよね、メニューも多いし何より、離れていたのがくっ付いたりとかしたりして、本当にスゴイですよ!!
MapEditor Release 0.5aが公開されました。
おもな変更点は以下のとうりです。
@拡大ツールで1/4倍と4倍が出来るようになった。
@拡大ツールで「左クリックで拡大」、「右クリックで縮小」が出来るようになった。
@マップサイズの変更で、切り取り位置を指定できるようになった。
@コード生成機能が付いた。
@サンプルとして、HSPのサンプルを追加。
一覧表示機能はまだ未実装です。スミマセン。
しかし、これで、だいたいの機能が実装されました。
アプリとして、それなりに役立つかも(?)
あとは、仕上げです。
URLを忘れてました^^
こちら
大きくなる~小さくなる~すごい!
マップエディタの縮小拡大機能を使っていたら、ラピィタのあのシーンが急に頭の中をフッと、、
人がゴミのようだ!!「ムスカ」なんか急に頭をよぎったデスよ。不思議不思議??どうしてだろう?
1/4倍って大きなマップの時には全体を見回せますね、それに大きくなるからこれだと小さなチップでも使いやすいですよね。
あれからイロイロやってはみたのですが、ダメでした。マップのロード出来ないです、、、、(泣
マップエディタもそうですが、なんか難しい~
ん~ん、あらためて思うデス、ソフト作れる人って本当にスゴイ!!尊敬しちゃいます!!
短時間にあんなスゴイマップエディタを作ってしまったあつしさん、すぃくさんはすぃくさんで、
あんなスゴイゲームを作っちゃいますから。ハ~、、スゴイな~
私も早く作れるようになりたいな~
ロードって文字ではなく数字でとの事でえっと、
intでしたよね数字のって、イロイロやってはみたのですがどうもダメでした。
前に数値の配列変数でやるって書いてあったと思うけど、どうやってやるんですか?
配列の変数の所にマップの変数がくるんですか?
そうだとしたらどんなふうになるんだろう?
間違っていたらゴメンナサイ。
説明不足でしたね、
intこれって文字のstrに対して変数を数値型にするっていうのでしたよね、
そういう意味でカキコしたのでしたが説明不足ですいませんでした。
はい、そうですよね、配列変数はdimとsdimでしたよね、
dim map,10,10
これって前に一枚マップでのと同じですね。
一枚マップを描くのはなんとなくわかるのですが、、、
う~んと、やっぱりセーブが出来てないのかな?
そうだったら、ロードも出来ないですよね、、、
map←この変数がセーブデータに来るわけですね。
それを読み込むのかな?
数学でもそうですが、プログラミングでは
「困った時は簡略化する」が常套手段です。(たぶん)
今「マップデータを読み込む」という目標があります。
そのために必要な処理は、「ファイルからデータを読み出す」ことです。
しかし、これでは何していいか分かりませんから、
簡略化してみましょう。
①変数xの値をファイルに保存する。
②変数xにファイルから値を読み込む。
変数xは配列でもなんでもない、ただの変数です。
(数学的には、スカラーと呼ばれる物になります。)
これをやってみましょう。
まず、「①変数xの値をファイルに保存する」には、
bsave命令を使います。
bsave “filename” x 4 0
さて、ここで「なぜ4なの?」と思うかもしれませんが、
「変数一個分のサイズが4だから」です。
(正確には違います。しかし、そう考えてもいいです。)
次に、「②変数xにファイルから値を読み込む」をしましょう。
これには、すぃくさんのおっしゃるように、bloadを使います。
bload “filename” x 4 0
どうでしょうか?簡単でしょ?
さて、ではマップデータの読み込み、書き込みをして見ましょう。
まず、変数を作らなくてはいけませんね。
dim map, 10, 10
つぎに、ファイルに保存しましょう。
bsave “filename”, map, 4*10*10, 0
さて、どこが変わったでしょうか?
変わったのは、セーブするデータのサイズですね。
変数mapは、10×10の配列ですから、
100個の変数の集まりと考えられます。
ですから、データのサイズは4*10*10になるのです。
最後にファイルから読み込みましょう。
bload “filename”, map, 4*10*10, 0
簡単ですね?
つけたしですが、MapEditorにソースコード生成機能
をつける予定です。
ですから、読み込まなくても、コピペでコードに書き込めるようにしようと思います。
もちろん、ファイルに保存するようにもしますが。
でも、ファイルからの読み込みは、大変重要な部分ですので、しっかり出来るようになっておいて損はないと思いますよ。
どう転んでも、必ず必要になるスキルですから。
スクリプトを組む時ってメインを作ってから、タコ足配線みたいに、
必要な事をサブルーチンでつぎ足していけばいいんですか?
組み方のコツが良くわからなくて??
プログラムの組み立て方は、いろいろな種類があります。
私が好きなのは、オブジェクトという概念なのですが、
まあ、そんなことは抜きにして、基本的に、その人にとって分かりやすければ何でもいいです。
分かりやすいとは、あとで修正しやすいと言う事でもあります。
HSPは言語的にシンプルですので、たいしたバリエーションはもてませんが・・・。
まあ、それはともかくとして、
「サブルーチンで継ぎ足して行く」というのは、いい方法だと思いますよ。
突沸は大丈夫でした。容器割れなかったし。
教科書&ノートは黄色に染まってしまいましたが・・・。
ロゴライターと言うのは、「Logo言語を操る統合ソフト」
なのですが、なんか検索したら、公式サイトがアクセスできなくなってた・・・。
つぶれたの・・・?(T T)
スクリプトの組み方、タコ足配線サブルーチンでいいんですね。
今、絵日記を作っています。
てっ、HSPから離れてない、、、、
まだ単色黒で消しゴム機能がある程度です。
マウスで一回描くごとに上書き保存されるようになっています。
ええっと、これは戻る機能をつけてみたいなと思ってイロイロしていたら
こういう風になりました。
なんか上手くいかない?
戻り機能って、どういう風に作ったらいいんでしょうか?
アドバイスお願いします!
あつしさんの言うように簡略化ですね、あきらめず作っていくつもりです。
今後ともどうぞよろしくお願いいたしま~す☆
基本的に、ヒストリー機能は「行った動作を保存しておく」ということにつきます。
例:「位置(x,y)の色をcからdにした。なら、xとyとcとdを保存する必要がありますね。」
問題はどうやって保存するかです。
これは、言語によってまちまちですが、なんにせよ、保存用のメモリを確保する事になります。
言語はCGIですか?
ヒストリー機能はかなり高度です。
私のMapEditorでも、その機能を追加したために、
コードがかなり複雑になっています。
これは、簡略化の観点から見ると、真っ先に削るべきかと。
というか、説明するのは、かなりこんなんです。
MapEditorのように比較的単純なソフトでも、コードが
主要部分だけで、6000行にも及びますので・・・。
こんばんは~
あう、あうう、、、
ヒストリー機能って6000行もですか、ううう、、、
難しい機能だったんですね、そんな難しい機能を簡単に作ってしまうあつしさんってやっぱりすごいです。
ヒストリー機能をつけるのは私には無理っぽいですね。
ほかをもっと勉強ですね、言語はいままでどうり、HSPですよ。
えっと、また基本的なことを良いですか?
簡略化って意味ってえっと、スクリプトを組むのに全体をまず簡単に作っておくってことですよね。
そして、バージョンアップしていくってことですよね。
@チョット補足。
ヒストリー機能は確かに高度ですが、それは、MapEditorがある程度の機能を持っているからです。
機能が増えると、ヒストリーとして、保存するものが増え、
保存したデータから、復元する処理も、多くなります。
しかし「機能は一つだけ」とか、「Undoは一回のみ可能」とかなら簡単です。
つまり、簡略化すれば恐れるに足りません。
ただ、「それでソフトとしてどうか?」
と言われると、首を傾げざるをえません。
(私的に使う場合は、全然かまわないですが。)
@簡略化
そういう考え方でいいと思います。
”かろうじて”動くようなソフトを初めは作ります。
初めから、完成品を作ろうと思うと、ものすごく気が重く、
「あそこはどうだろ?あっちはどうしよ?」とかになり、
どうしてよいか分からなくなります。
”とりあえず”動くものを作って、後から少しずつ修正していくのがベストです。(たぶん。個人で作る場合。)
もちろん、当初はまったく想定していなかった
機能をつける場合なんかもありますから、
すぃくさんのように、太い幹を増築することもありますよ。
こんばんは~
簡略化って初めは、かろうじて動くような感じでいいんですね。
とりあえず動くものを作って、少しずつ修正ですね。
わかりました、全体を見るっていうか広い眼で見るって感じですね。
足元(あそこはどうだろ?あっちはどうしよ?)だけをみていてはダメって事ですね。
下だけを見て歩いていたら誰かにぶつかっちゃうもんね。
理想的なのは、気楽に少しずつ作っている間に、あれ?出来ちゃったって感じでしょうね。
さて、リリース0.9が完成しました。
こちら
「MapEdiyr(マップ・エディル)」です。
ほんとは、「MapEdiyr Atushi」にしようかと思ったのですが、やめました。
アナウンスでした。
絵日記ですが少しずつ作ってます、えっとチョッとつまずいちゃいました。
ぺん先の太さで円、まるの描き方なんですが、四角のboxfでは太さの調整はできるのですが、丸にするのが出来ません。
mes “●”で出来なくはないのですが、小さくするとおかしくなってしまうので、ん~んん、、、どうしたらいいんだろう?
こんなページ見つけました。
HSPについて、「これでもか」ってくらい書かれています。
NO.12が大変参考になると思います。
BBSでのあつしさんの当たり判定の書き込みを記録しました。
yukiさんと、あつし様の対談で構成されています。
-関連リンク-
ZOO・・・・・・強力なマップエディタ「MapEdiyr(マップ・エディル)」を公開しているあつし様のサイトです。
『MapEdiyr』・・・・・・あつし様制作の驚愕の高性能マップエディタです。是非、一度触れてみてください。
■どうしたらいいのやらまったくわかりません
どのようにして当たり判定&進入禁止これってどうやってするんですか?
■マップはどのように作ってるのでしょう?
そのマップの作り方によって衝突の判定方法は異なります。
簡単なのでは、「全て正方形で構成する」とか、
チョット複雑にして、「正方形に対角線を引いて、正方形の内部にも、歩けるところと、歩けないところを作る」とか、「多角形の内部が歩けて、外部は歩けない」とか、いろいろ有りますよね?
もしマップに高低差があると、また変わってきます。
「ゆきだるまの物語」を例に考えてみると、
どうも、斜めの直線とかが多いので、マップを正方形に区切るとすると、正方形が非常に小さくなります。
仮に、大きな正方形でマップを構成すると、斜めの直線のところでは、ごつごつしてしまって、目に見えない出っ張りが、ユーザーを苦しめることになります。
■ そう考えると、マップを、一辺が1~2ピクセルの正方形で区切ることになります。
すると、データ量が増えて、マップデータを作るのに、
時間がかかるかもしれません。
(専用のソフトを作れば、全然大変ではないですが、打ち込みだときついかも。でも、ソフトさえ作ってしまえば、凄く強いかも。)
さて、何らかの方法で、マップを作ったとしましょう。
そして、マップ上のある位置において、そこが、
歩ける場所かどうかを返す関数を
bool IsWalkable( x, y )
とでも定義しましょう。
(注意:関数IsWalkableは、マップ上のある点の座標を示す2つの整数値を引数にし、そこが「歩行可能」ならtrueを返し、「不可能」ならfalseを返す関数。)
【1】ユーザーが、十字キーの右を押す。
【2】キャラが、移動する先の位置を計算する。
(計算するだけで、移動はさせない。)
【3】IsWalkable関数で、移動先の位置が、歩行可能な場所かどうかをチェックする。
【4】可能であれば、移動し、そうでなければ移動しない。
■最も単純な方法はこんなカンジでしょうか?
実際には、滑りとか、壁に沿って移動するとかを実現するためには、正方形で区切るのではなく、多角形で区切るべきでしょう。
マップをどう表現するかによって、また要求されるアクションに応じて、判定方法は異なりますので、あくまで概念的なことしかいえませんが、具体的にコードを示してくれれば、もっと具体的なアドバイスもできると思います。
■私が使っているソフトはHSPです。
マップチップを並べた所にキャラを歩かせることが出来るようになった程度のおばかさんです。
一辺あたり32×32の正方形のチップを並べたマップです。あつしさんが言っているような複雑なマップは私にはとても作れません。
【1】ユーザーが、十字キーの右を押す。
【2】キャラが、移動する先の位置を計算する。
(計算するだけで、移動はさせない。)
【3】IsWalkable関数で、移動先の位置が、歩行可能な場所かどうかをチェックする。
【4】可能であれば、移動し、そうでなければ移動しない
上のような過程をへて通行可能だとかを判断しているんですか、ん~ん、、なるほど~
うう、、、アドバイスを頂いたのはいいんですが良くわからないです、ごねんなさい、おバカな私にはどうやって作っていいのやら、、、
■チップの事で質問ですが、
えっと、一辺が1~2ピクセルってそんなに小さくですか、それと「大きな正方形でマップを構成すると、斜めの直線のところでは、ごつごつしてしまって」とありますがどのくらいから大きなに入るでしょうか。
■ごつごつしてしまうのは、あくまで、感覚的なものです。
ですから、「具体的にどこから」と言う事はありません。
例えば、45度の直線を、32×32の正方形を並べて描くと、
ごつごつしませんか?
でも、90度に近い、80度なら、45度のと比べると、
それほどごつごつしません。
(うぅ、この説明で分かって頂けるかな~?)
ですから、「ゆきだるまの物語」の様に、
いろんな角度の直線があって、
しかもごつごつした感じを出さないようにするためには、
正方形を出来るだけ小さくすべきだろうと考えたわけです。
と、ここまで書いてきましたが、
あくまでこれは、「マップを正方形で区切る場合」です。
ゆきだるまの物語の場合は、別の方法をとるべきでしょう。
(すぃくさんはどうしてるんだろ?)
で、本題に戻りますが、
「キーの入力を受け取る部分」は有りますか?
(と言うかあるはず。)
その部分をまず探しましょう。
見つかったら、ここに書いてみてください。
まったりと行きましょう。
あせる事ないです。(^^)
■こんばんは~
あっそうか、まっぷのゴツゴツ感ってそうですよね、確かに感じます。
小さくする事でなめらかになるんですね。
えっと、キー入力の情報取得ですよね、HSPの場合
stickとgetkeyですよね、
stickの方を使ってキーの情報を取得しました。
これでいいんですよね
■HSPには手も触れたことない私ですが、
にわか勉強してみました。
で、作ったサンプルがこれ。
サンプル(ソース付き)
まあ、実行してみてください。
そんな感じです。
ちゃんと海と、山にぶつかってるでしょ!?(^^)ノ
(あ、ちなみに操作は十字キーだけですので。
「海に見えね~」とか「これ、山?」とか言う苦情はごかんべんを・・・。)
さてさて、問題は「どうなってるの」ですよね?
ソースを見ていきましょう。
(一番メインとなるところは、なんと言っても、
key関数です。)
■まず、画像を読み込む。
buffer 2;
picload “player.bmp”;
buffer 3;
picload “map.bmp”;
次に定数が二つほどあります。
#const TRIGER 1+2+4+8
#const MOVE 4
TRIGERは、stickに渡すパラメータです。
この場合、十字キーすべてについて、
押されている間は、命令を受け取る必要がありますからね。
MOVEは、キャラクタの移動量です。
この値が大きくなるほど、キャラクタはスピードアップします。
(ただし、1、2、4、8、16、32のどれかにするようにして下さい。でないと、判定がうまく行きません。
コードでは4にしました。)
次は、おなじみのコード
screen 0,320,320,4;
title “sample1″
そして、つぎに、キャラクタの座標を入れる変数を書きます。
x = 0;
y = 0;
さて、次は重要なマップデータの作成です。
dim map,10,10;
map.0.6 = 1;
:
省略
:
map.9.6 = 1;
配列は、作成されると、0に初期化されていますので、
歩けるところを0とし、歩けないところを1とすることにしました。
■つまり、山と海のところは1になります。
左上から、32×32の正方形に区切っていくと、
画面のサイズは320×320ですから、縦横10個ずつの合計100
個のマス目に区切られます。
左上のマス目を0行0列として、その右は、0行1列となります。
一番右下は、9行9列で、その上は、8行9列ですね。
ですから、map.bmpに書かれている通りに、山のマス目と、海のマス目のところを、1にしていきます。
(チョットめんどいですね・・。専用のソフトを作るべきかも・・。)
次もおなじみのmain関数です。
ループさせてます。
ここで呼び出しているkey関数は、ユーザーの入力を受け取って、キャラクタの座標(x、y)を変更する関数。
paintは、その情報をもとに、キャラクタと、マップを表示する関数です。
awaitは、windowsに処理を返しているだけです。
*main
gosub *key;
gosub* paint;
await 1;
goto *main
■次に来るのは、(このソースの)ラスボスのkey関数ですが、
そのまえに、下っ端のpaint関数を倒しておきましょう。
redrawは、ちらつきを抑えるために書いているだけで、
なくても動作しますが、書いておきましょう。
次に(白で)画面をクリアしていますが、
よくよく考えると、その2行はいりませんでした。
(なぜかというと、map.bmpを次に画面いっぱいに描画しているからです。)
マップの描画と、キャラクタの描画をして、
終わりです。
*paint
redraw 0;
color 255,255,255; 画面をクリア
boxf 0,0,320,320;
pos 0, 0;
gmode 0,320,320,256;
gcopy 3,0,0,320,320;
pos x,y; 画像を表示
gmode 3,32,32,200;
gcopy 2,0,0,32,32;
redraw 1;
return
■さて、ついに来ました。ラスボスが!?(何
このコードの半分ほどを占める超大作(ウソ)です。
まず、大まかな概要から説明します。
下に書いたのが、key関数の骨組みです。
*key
stick keycode, TRIGER, 1;
if( keycode&1 ){
}
if( keycode&2){
}
if( keycode&4){
}
if( keycode&8){
}
return
■まず、stick命令で、押されているキーのコードを受け取り、
次に、if文で押されていた時の処理を書いています。
ここで、押されるであろうキーは、十字キーの4つのキー(上下左右)で、それぞれのキー番号が、左が1で、上が2、右が4で、下が8です。
まず、左が押されていた時の処理を考えて見ましょう。
キャラクターは、いまフィールド上にいて、
左に移動しようとしています。
移動後の位置は、(x-MOVE、y)ですね?
(キャラクターの位置は、キャラクターの左上の頂点の位置のことです。真ん中ではありません。)
移動後に、キャラクターが、山とか海にぶつかったかどうか判断するには、キャラクターの左上の頂点と左下の頂点が、マップ上の「歩ける」所の上にあるかどうかを判断すれば良いのです。
(それで判断できるのは、キャラクターの移動量が32以下で、マップの1マス分を、飛び越えないからです。)
■では、それをどうやって判断すれば良いでしょうか?
まず、移動後の、左上の頂点と、左下の頂点の座標を考えましょう。
左上は(x-MOVE,y)ですね。
左下は(x-MOVE,y+31)ですね。
(「な ぜ31なのか?32じゃないの?」と思うかもしれませんが、ゆっくり考えてみてください。32×32の正方形の、左上の頂点を[0,0]とすると、その下 の2番目の頂点は[0,1]です、さらにその下の3番目の頂点は[0,2]となります。ですから、32番目の頂点は[0,31]なのです。つまり、左上が [x、y]なら、左下は[x、y+31]となります。)
さて、座標は計算できました。
とりあえず、この計算した値を、
tmpx = x-MOVE;
tmpy = y;
tmpz = y+31;
として入れておきましょう。
つまり、左上は(tmpx,tmpy)で、左下は(tmpx,tmpz)となります。
(tmpは、temporary<一時的な>という意味です。)
■さて、座標はわかったけど、この座標が、
マップ上の、どのマス目に入るかを計算しなくてはいけません。
その計算は簡単です。
ソースに有るように、32で割ってやれば良いのです。
tmpx = tmpx / 32;
tmpy = tmpy / 32;
tmpz = tmpz / 32;
本当なら、割ると小数点以下に数がつづくのですが、
HSPでは整数に勝手にしてくれて、1.763とかも、1にしてくれます。
ですから、32で割ると、tmpxが0~31なら0になり、32~63なら1という風になります。
これは、マス目の番号になりますね。
つまり、左上の頂点はtmpy行tmpx列、左下はtmpz行tmpx列となります。
しかしここで問題が一つあります。
キャラクターが、左隅から、画面外へ出て行ってしまった場合です。
つまり、tmpxが0より小さくなる時です。
しかし、tmpxは-31より小さくなることはありえませんから、32で割ると、-0.xxxとなり、整数に変換されて0となり、結局この場合もオッケーとなります。
■さて、ここまで来れば、後は簡単。
map.tmpy.tmpxが0で、かつmap.tmpz.tmpxも0であるかどうか確かめるだけです。
そして、もしそうだったら、キャラクターの座標を更新します。
x -= MOVE;
ただし、ここで忘れてはいけないのが、
キャラクターが画面左端から外に出て行ってしまう場合です。
そうならない様に、
if( x < 0 ){
x = 0;
}
としておきましょう。
@チョット休憩・・・
さて、あと上と右と下が有りますが、
左の場合とほぼ同じことをしていますので、
分かるのではないかと・・・・。
わかんなかったら遠慮なくど~ぞ~。
(というか、この説明で分かっていただけたのだろうか?)
P.S.なんか、異様に長くなってしまいました。m(__)m
■ソースまで付けてもらっちゃって、その上ソースの説明をこと細かくしてくれて本当にどうもありがとう~!!
山と海の所を歩けないようになってる。
初めてのソフトであつしさんはこんなすぐに作れるなんてスゴイです!!
マップのサイズが320×320になっているんですね。
一枚でマップを呼び込むんですね、一枚で呼び込むのって重くないですか、大丈夫ですか?
チップで呼び込んでマップを構成するのとどう違うんだろう?
えっと~、マップで1の所が歩行禁止ですか
「配列は、作成されると、0に初期化されていますので、
歩けるところを0とし、歩けないところを1とすることにしました。」
↑上のようにありましたが、
作成されると、0に初期化されていますって、どういうことですか?
ほかにもなんで32で割るのだとか、
えっと関数、関数って出て来ますが、関数って何ですか?
■プログラミングって言うのは、一度やったことなら、たいていチャチャットできてしまうものです。
>一枚で呼び込むのって重くないですか、大丈夫ですか?
う~ん、どうでしょうか?
HSPの内部構造を私は知りませんし、このあいだ始めて使ったばかりなので、経験則とかもいえません。
ただ、320×320とかなら、普通は問題ありません。
言語が違いますが、800×600の画像とかを、ぼこぼこ読み込んだり消したりした事あるので・・・。
ただし、メモリがシビアなら問題かもしれませんが、
おそらく、そんな環境では、まともなソフトは動きません。(特にゲーム)
■ >0に初期化されていますって、どういうことですか?
例えば、
dim a,10;
と書いたとしましょう。
このコードでは、「名前がaの、要素数が10の配列」を作っています。
では例えば、このコードのすぐ後に、
mes a.0;
と書いたとしたら、一体何が書かれるでしょうか?
つまり言い換えると、a.0には、どんな値が入っているでしょうか?
答えは、0です。
普通は、
a.0 = 45;
として、値を代入しますが、
もししなくても、もとから0という値が入っているのです。
(「そんなの当然やん。」とは思わないで下さい。
例えば、c++という言語なら、0にはならず、予測不可能な値が入ります。237657とか、-12など。あくまで
、HSPが新しく作った変数とか配列の要素を、0で”初期化”してくれているだけなのです。)
■ このように、もとから何もしなくても、新しい変数とか配列の要素には、0がはいっている事を、「0に初期化されている」と言います。
もし仮に、新しい変数や配列の要素に、もとから-1が入っていたとすると、「-1に初期化されている」という事になります。(そんな言語見たことありませんが・・)
ちなみに、このもとから入っている値の事を、初期値と言います。(物理とかで、出て来たりすると思います。)
さて、コードの中では、1にセットしてばかりで、
0にセットしているものは一つもありません。
1にセットしなかった配列の要素は、もとから0です。
ですから、セットする必要がなかったのです。
だから、省略したのです。
これができるのは、「0に初期化されている(もとから0になっている)と分かっている」からです。
■ >なんで32で割るの?
マップは、32×32の正方形を並べて作ってありますよね?
そして、その一つ一つの正方形に対して、「歩ける(0)」か「歩けない(1)」という情報をセットしました。
「どこにセットしたの?」というと、あのmapという名前の配列にセットしたのでしたね?
いま、画面の大きさは320×320ですから、32×32の正方形で区切ると、縦横10個ずつの計100個の正方形で区切ることになります。
(サンプルを見てみてください。チェックマークのようになっているでしょう?その一つ一つの正方形が、32×32のサイズになっていて、縦横ちょうど10個ずつあります。)
まず、区切ったそれぞれの正方形に、番号を割り当てましょう。
一番左上の正方形を0行0列とし、その右を0行1列、さらにその右を0行2列、さらにその次は0行3列と言うことになります。
また、一番左上の0行0列の正方形からみて、その下は、
1行0列の正方形で、さらにその下は2行0列となります。
ちなみに、一番右下は、9行9列です。
■ さて、番号をつけましたが、これに何の意味があったのでしょうか?
例えば、「n行m列の場所にある正方形」を考えましょう。
この正方形上をキャラクターが歩けるでしょうか?
つまりこの正方形の持つ「歩ける(0)」か「歩けない(1)」かという情報は、配列mapのどこに格納されているのでしょうか?
答えは、「map.n.mに入っている。」です。
つまり、map.n.m が0ならば歩けて、1なら歩けないことになります。
さて、ではマップ上のある座標(x、y)が、歩ける正方形の上かどうかを確かめるにはどうしたら良いでしょうか?
それには、座標(x、y)が、何行何列の正方形の上なのかを知る必要が有ります。
もしそれが分かれば、先ほど見たように、その正方形の上が「歩ける」かどうか分かり、座標(x、y)が「歩ける」場所なのかどうか分かります。
x/32は、列番号に。
y/32は、行番号に対応すると思いませんか?
つまり、座標(x、y)の点は、(y/32)行(x/32)列の正方形上にあると思いませんか?
じっくり考えてみてください。
■ (「x/32は小数にならないの?例えば、xが16の時、x/32は0.5じゃないか!!0.5列って何だよいったい!!」と思うかもしれません。
しかし、HSPでは数値は全て、整数に勝手に変換されます。
その場合、四捨五入などと言う事はしてくれません。
小数点以下は切り捨てです。つまり、先ほど見た0.5は、0になってしまうのです。
つまり、0列のことを意味するんです。それから、一つ注意しておかなければならないことがあります。
それは、x座標もしくはy座標が-32以下または320以上のときです。このとき、x/32は-1以下もしくは10以上となってしまいます。
しかし、-1列とか、10列とかは存在しませんので、そうならないように、サンプルでは、少し手を加えてあります。
if( tmpx > 319 ){
tmpx = 319;
}
このようにして、320以上になったりしないようにしているのです。
ちなみに、-32以下になることは「テレポートでもしない限り」ありえないので、何の対策もしていません。
)
■ >関数って何?
実はこれ、僕の間違いでした。
HSPには、関数などどうやら存在しない(?)ようですね。
たいていの言語には、関数という概念があるので、
あるものと思ってしまいました。
関数ではなく、ラベルの間違いです。
key関数ではなく、keyラベルですし、
paint関数ではなく、paintラベルです。
ラベルについては、HSPのヘルプをごらんあれ~。
■マップの一枚呼び込みって320×320ぐらいであれば問題ないんですね、良かった~
0に初期化する、そういうのがあったんですね、全てではないにしても、ん~んなるほど、、
まったく知りませんでした。
HSPは少数にならないってことは細かい計算は出来ないのかな?
以前なんとかマップチップ上でキャラを歩かせる事が出来たって喜んでいた物ではなく、新しく作ってみました。
なんとか作れるものですね。以前はまったくわからなかったのに、、、
↓こんな感じにマップ表示とマップ上のキャラ移動を作っていました。
■ buffer 2,32,32 :picload “kyara.bmp”;キャラ
buffer 3,32,32 :picload “kusa.bmp” ;草1
buffer 4,32,32 :picload “mizu.bmp” ;水2
;このまま実行しても動きません、↑素材を用意しないとだめですね、
screen 0,320,320
dim map,10,10
map.0.0=1,1,1,2,2,2,2,2,2,2
map.0.1=1,1,1,1,2,2,2,2,2,2
map.0.2=1,1,1,1,1,2,2,2,2,2
map.0.3=1,1,1,1,1,1,2,2,2,2
map.0.4=1,1,1,1,1,1,1,2,2,2
map.0.5=1,1,1,1,1,1,1,1,2,2
map.0.6=1,1,1,1,1,1,1,1,2,2
map.0.7=1,1,1,1,1,1,1,1,1,2
map.0.8=1,1,1,1,1,1,1,1,1,2
map.0.9=1,1,1,1,1,1,1,1,1,2
*main
redraw 2 ;画面には描画しないモード
;——-マップチップ描画—————————-
repeat 10,0 : cntx=cnt : repeat 10,0 : cnty=cnt
if map.cntx.cnty>-1 : pos cntx*32,cnty*32 : gcopy 3
if map.cntx.cnty>1 : pos cntx*32,cnty*32 : gcopy 4
loop : loop
■ ;——-キー入力————————————
stick key,1+2+4+8
if key&1:x=x-3 : if x<0 : x+3
if key&2:y=y-3 : if y<0 : y+3
if key&4:x=x+3 : if x>290 : x-3
if key&8:y=y+3 : if y>290 : y-3
pos x,y
gcopy 2
gmode 2
redraw 1
await 15
goto *main
■ 教えていただいた当たり判定は一枚で取り込みですよね、もし当たり判定を↑上のに組み込む込むとしたらどうやったらいいでしょうか?
それと、キャラの方向で、いろんな方向にキャラを見えるように組み込むにはどうしたらいいんですか?
上を押すと上向きのキャラが下を押すと下向きのキャラみたいにです。
■ こんどはどういう仕組みになるんだろう?
マップを並べたものを保存しなきゃいけないんですよね、
BMPなどで出力しなきゃいけないのかな~
BMPとかでなくてデーターで保存するのかな?
マップがそのままホルダーの中で見えてしまうとゲームが面白くなくなっちゃうし・・・。
えっと、プログラムの設計図みないなのでなんかありましたよね、
そんなのをどこかで見たような覚えがあるのですが、
名前はチャットににたような感じだったような、、、間違っていたらゴメンナサイ。
いまさらですが私が作りたいのはRPGです、行きなりエベレストに挑んだら間違いなく遭難してしまいますよね。
私は本当に幸せものです。
二人の先導者、すぃくさんとあつしさんのご協力の下少しずつお山を登れるのですから。
お二人には感謝感謝です!!
■@もし当たり判定を↑上のに組み込む込むとしたらどうや
@ったらいいでしょうか?
私たちが今やっているあたり判定の方法は、
下にどんな絵があるかにまったく関係ありません。
ですから、同じように組めばそれで良いのです。
今回のサンプルはこちら。
サンプル(ソース付き)
チョット今時間がないので説明は後回しですが、
やってることは殆ど変わっていません。
paintラベルのところの、マップを表示する部分が少し変わった程度です。
■ @いろんな方向にキャラを見えるように組み込むには
@どうしたらいいんですか?
先ほどのサンプルに、少し手を加えたのがこちら。
サンプル(ソース付き)
殆ど同じですね。
変数mukiに、最後に押されたキーに応じて、
値をセットして、表示する時に、その値に応じて、
処理を変えているだけです。
@えっと、プログラムの設計図みないなのでなんか
@ありましたよね、そんなのをどこかで見たような
@覚えがあるのですが、名前はチャットににたよう
@な感じだったような、間違っていたらゴメンナサイ。
@もし良かったら、おバカな私にはイラストのような
@これだと解りやすいかもです、もしよかったら
@チャットでプログラムの動きを教えてくれませんか。
この文章なのですが、私には良くわからなかったのですが・・・・。
最後のチャットはchatのことですよね?
”プログラムの設計図”とはいったい?
■サンプルどうもありがとう!
今までと変わらないんですか、そうなんだ、あっ、ムキの変数が方向ごとにですか、そっかこうするのか、
なるほどスゴイ!!
いままでサブルーチンってほとんど使ってこなかったけど
なんかすごいですねサブルーチンって、それに見やすいですね。
調べてみたのですが、チャートでしたフローチャートと言うようです。本当にごめんなさい
マップチップ描画の所ですがなんか長いような、
ためしに元のをこのようにしてみたらエラーが出ました。
はじめにカキコしたのもチョッとおかしかったんですよね。ほんとゴメンナサイ。
↓直してみました
;——-マップチップ描画——————
repeat 10,0 : cntx=cnt : repeat 10,0 : cnty=cnt
if map.cntx.cnty>-1 : pos cntx*32,cnty*32 : gcopy 3
if map.cntx.cnty>1 : pos cntx*32,cnty*32 : gcopy 4
loop : loop
■@マップチップの描画を直してみました
見たところ、ちょっと問題があります。
問題は、
if map.cntx.cnty>-1 : pos cntx*32,cnty*32 : gcopy 3
if map.cntx.cnty>1 : pos cntx*32,cnty*32 : gcopy 4
の部分です。
始めのif文では、「map.cntx.cntyが-1より大きい時」となっていますから、1の場合も、2の場合も実行されます。
さらに次のif文では、「map.cntx.cntyが1より大きい時」となっていますから、2の場合に実行されます。
つまり、「map.cntx.cntyが2の時」には、同じ場所にgcopy 3とgcopy 4をすることになります。
二重書き込みしていることになるわけです。
■速度的に、それで問題なければそれでも良いですが、
HSPはスクリプト言語ですから、処理速度はそんなに速くありません。
他にも、いろんな機能を追加していくことを考えると、
少し問題となるかもしれません。
sample2のコードでは、
if( map.cnty.cntx == 0 ){}
if( map.cnty.cntx == 1 ){}
としていますが、こうすれば、二重書き込みはなくなりますよね?
まあ、ちゃんと動くなら、どちらでも良い話ではありますが・・・。
■やっぱり問題があったんですね、ごめんなさい。これだと二重書き込みになちゃうんですね、んん、、、
いろいろ付け加えていくと問題が出てくるんですね。
if( map.cnty.cntx == 0 ){}
0の所を2、3なんかにして、今までのように作ったらOKですよね。
if( map.cnty.cntx == 0 ){}
if( map.cnty.cntx == 1 ){}
if( map.cnty.cntx == 2 ){}
みたいな形にして配列に2の所を加えて今までのようにbufferに素材を作ってそれを持てくればいいですよね、あっていますか?
こうすればイロイロな地形を作れますよね。でもこれだとbufferなんかを余計に使っちゃいますよね。
やっぱり、マップエディータを作った方がいいのかな~
ん~ん、、、、
上の所で=が二つ続いていますよね。
==ってありますが、これって=とどう違うの?
それと{ }←の使い方が解りません。何の役割をしているんですか?
■@bufferに素材を作ってそれを持てくればいいですよね、
@あっていますか?
あってますよ~。
それで良いと思いますよ~。
@bufferなんかを余計に使っちゃいますよね。
別にそれで良いと思いますよ~。
いっぱい使う事になるかもしれませんが、
それはやむ負えないと思います。
@==ってありますが、これって=とどう違うの?
HSPプログラミングガイドを見ましょ~ね~。
こう言うわかんない事が出てきたら、プログラミングガイドを見ましょう。
たいていはそれで解決します。
それでダメなら、実験してみましょう。
例えば、sample2の==の部分を、=に変えてみてください。
何も変わりませんね?
HSPでは、(恐ろしいことに)”==”と”=”は同じ意味を持ちます。
他の言語では、この二つを使い分ける場合が多いのですが、「HSPではまったく同じ」です。
■{}は、式をまとめて書くときに使います。
以下の二つを見てください。
if(条件式){
式1;
式2;
}
if(条件式)
式1;
式2;
上のコードでは、「条件式が真の時には、式1と式2の両方が実行されます」また「偽の時は、両方とも実行されません」。
下のコードでは、「条件式が真の時には、式1と式2の両方が実行されます」が、「条件式が偽の時にも、式2は実行されます」。
上の方のコードは、
if(条件式)式1:式2;
と一緒です。
(もしかしたら間違えてるかも・・・・。
HSPは、だいぶ他のメジャー言語と異なるので・・・、常識が通用しない・・・。)
■=の件で本当にゴメンナサイ。
たしか==と=は同じみたいなことはたしか書かれていたかとおもいます。でもなんで同じなのに二つなの?と疑問になってしまって、聞いてみたのですが、本当にゴメンナサイです。
if( map.cnty.cntx == 2 ){}
↑このあいだの2だとかに変えたら違う地形にできました。
でもこれだとここも歩行禁止になってしまってるんですよね。
前に教えてもらった一枚取り込みの方法だといろんなチップの上を歩かせたりも出来るんですよね。
やっぱり前の方がいいのかな~
ところで、マップエディタってどういう構造になっているんですか?
まず素材を用意して、今までと同じように配列を使ってマップを作るんですよね。
それから、出来たマップをセーブかな?
手順というかこんな感じですか?
大雑把ですけど、ほかに何かありますか?
マップのところですが、
エラーになっているっていうかマップが反転していますが、どうしてでしょう?
これでいいんですか?
■@マップエディタ
マップエディタが必要なのは、
「マップがでかくなると、打ち込みがしんどい」
という理由です。
例えば、配列が今は10×10でしたが、100×100とかになると、チョットいらいらしませんか?
さらにこれが、100×100を10個とかなると、パソコンに八つ当たりしてしまうかもしれません。
いちいち「ここは山だから3ね~」「ここは浜辺だから4~」とかやるのはしんど過ぎです。
■そこで、しんどい事はパソコンにやってもらおうと言う事になります。
ですから、マップエディタの御仕事は、
「完成したマップから、配列を計算して、配列を生成するコードを書き出す」事です。(他にもいろいろ有りますが・・)
[マップエディタの一例]
さて、今回のサンプルはこちら。
サンプル(ソース付き)
(超ぷち)マップエディタです。
さすがに、にわか勉強では限界が見えてきました。
で、操作方法の説明。
①マウスの左をクリックすると、クリックされた場所が、草→水→山→草と変って行きます。
②マウスの右をクリックすると、現在の状況をmapcode.txtに保存します。
③エンターキーを押すと、mapcode.txtから、データを読み込みます。
■今回のサンプルでは、palhsp.hpiというプラグインを使用しています。
このpalhsp.hpiをHSPの”本体”があるところに置いて下さい。(例C:\Program Files\hsp26)
実行ファイル(hsptmp.exe)を実行するだけなら必要ありませんが、tpd001.asを実行するためには必要です。
@マップのところですが、
@エラーになっているっていうかマップが反転してい
@ますが、どうしてでしょう?
@これでいいんですか?
う~ん、言っている意味が良くわからないです。
もう少し、具体例を挙げてみてもらえませんか?
■今回のサンプル、メインとなるのは、
やはり、keyラベルのところです。
チョット難しいかもしれませんね・・・?
ですが、基本の積み重ねです。
なんとな~く分かっていただけるのでは・・・?
「ここ何してんの?」というところが有れば、容赦なく言って下さい。
なお、今回使用したプラグインについては、
こちら
をご覧下さいませ。
■なるほど、たしかにマップが大きくなると打ち込みってきつくなりますよね。
そこでマップエディタが必要になってくるんですね。
■マップが反転って書いていたのは、
↓プログラム上こうなっていますが、
dim map, 10, 10;
map.0.0 = 0,0,0,1,1,1,1,1,1,1;
map.0.1 = 0,0,0,0,1,1,1,1,1,1;
map.0.2 = 0,0,0,0,0,1,1,1,1,1;
map.0.3 = 0,0,0,0,0,0,1,1,1,1;
map.0.4 = 0,0,0,0,0,0,0,1,1,1;
map.0.5 = 0,0,0,0,0,0,0,0,1,1;
map.0.6 = 0,0,0,0,0,0,0,0,1,1;
map.0.7 = 0,0,0,0,0,0,0,0,0,1;
map.0.8 = 0,0,0,0,0,0,0,0,0,1;
map.0.9 = 0,0,0,0,0,0,0,0,0,1;
↓実際に表示されるときにはこういうふうに
dim map, 10, 10;
map.0.0 = 0,0,0,0,0,0,0,0,0,0;
map.0.1 = 0,0,0,0,0,0,0,0,0,0;
map.0.2 = 0,0,0,0,0,0,0,0,0,0;
map.0.3 = 1,0,0,0,0,0,0,0,0,0;
map.0.4 = 1,1,0,0,0,0,0,0,0,0;
map.0.5 = 1,1,1,0,0,0,0,0,0,0;
map.0.6 = 1,1,1,1,0,0,0,0,0,0;
map.0.7 = 1,1,1,1,1,0,0,0,0,0;
map.0.8 = 1,1,1,1,1,1,1,0,0,0;
map.0.9 = 1,1,1,1,1,1,1,1,1,1;
反転といったのはこういうことですが、これでいいんですか?
マップの反転
直す方法はありますが、別に問題ないと思いますよ?
プレイヤーは、コードなんて見ませんし。
見たって理解できない。
「動けばいいのです!!たぶん!!」(ウソ)
でもま~、綺麗なコードはもっと後で追求したらいいんじゃないでしょうか?
@何度もクリックしたくなるこの中毒性
そこまで言って頂けると、うれしい限りです。^^
もっとも、アプリケーションとしてはあまり役立ちませんが。バックアップの方、宜しくお願いします。
おはようございま~す
マップの反転はエラーっと言うわけではないんですね。
そうですよねたしかに、プレイヤーにはプログラムは見えませんものね。安心しました。いろいろくふうしてみます。
if( map.cnty.cntx == 2 ){}
↑数字2とか3に変えていくと。
これって、配列の当たり判定で0が歩けて1が歩行禁止
にでしたよね、やっぱり2なんかは歩けなくなちゃいますか?
歩けなくなちゃいますか?
今は、「0が歩けて」「1が歩けない」にしていますが、
例えば、「0以下が歩ける」「1以上は歩けない」にしたら、2とか3にしても問題はないですよね?
あたり判定の部分で、
if(( map.tmpy.tmpx == 0 ) && ( map.tmpy.tmpz == 0 ))のところを、
if(( map.tmpy.tmpx <= 0 ) && ( map.tmpy.tmpz <= 0 ))にすれば、万事オッケーです。
こうする事で、歩ける場所にもさまざまなバリエーションを加える事ができます。
例えば、いまは0を草にしていますが、-1を湿地帯とかにしても、「そこは歩ける事になります」。
歩けない場所も、同様にして追加できます。
こんばんは~
本当だ今まで歩けなかったところが歩けるようになりました。本当にありがとう!!う~ん、なるほど~<=0ですねこうすればいいんですね。
こうなると、マップの幅が広がっておもしろですね。
本当に本当にありがとう!
できました。こちら
マップエディタ
リリース0.5アップしました。
@選択範囲
選択範囲を解除するには、メニューの「選択範囲(S)」→「選択を解除(D)」を押してください。
選択範囲に関する操作は、他に「全てを選択」「選択範囲を反転」が有ります。使ってみてください^^
あんまり驚かせないでよあつしさん、心臓止まっちゃうよ~!!
なんかペイントツールのような感じのマップエディタですね。選択範囲に塗りつぶしなんて、作業効率アップにとても効果的ですよね。は~~、、すごいな~、、、
ヒストリー機能でしたっけ、こんなことも出来ちゃうの?スゴイな~は~~~、、、
ため息つきっぱなしです、、、
あの、虫眼鏡の拡大って出来ないけどこれでいいんですか?
使っていただいてありがと~
で、問題の虫眼鏡ですが、虫眼鏡は本来なら、
@「左クリックで拡大」
@「右クリックで縮小」
@「マウスの真ん中のホイールを回して拡大縮小」
とするはずでした。
しかし、現在のところ、
@「マウスの真ん中のホイールを回して拡大縮小」
しかできません。
しかも、倍率は1/2倍と1倍と2倍のみです。
ですが、この機能の実装は、比較的簡単なので、
次のバージョンには、実装できると思います。
マウスの真ん中の所をクリクリすると拡大縮小しますね、スゴイ!!
これってHSPで作ったんですか?
メニューの所なんかすごいよね、メニューも多いし何より、離れていたのがくっ付いたりとかしたりして、本当にスゴイですよ!!
MapEditor Release 0.5aが公開されました。
おもな変更点は以下のとうりです。
@拡大ツールで1/4倍と4倍が出来るようになった。
@拡大ツールで「左クリックで拡大」、「右クリックで縮小」が出来るようになった。
@マップサイズの変更で、切り取り位置を指定できるようになった。
@コード生成機能が付いた。
@サンプルとして、HSPのサンプルを追加。
一覧表示機能はまだ未実装です。スミマセン。
しかし、これで、だいたいの機能が実装されました。
アプリとして、それなりに役立つかも(?)
あとは、仕上げです。
URLを忘れてました^^
こちら
大きくなる~小さくなる~すごい!
マップエディタの縮小拡大機能を使っていたら、ラピィタのあのシーンが急に頭の中をフッと、、
人がゴミのようだ!!「ムスカ」なんか急に頭をよぎったデスよ。不思議不思議??どうしてだろう?
1/4倍って大きなマップの時には全体を見回せますね、それに大きくなるからこれだと小さなチップでも使いやすいですよね。
あれからイロイロやってはみたのですが、ダメでした。マップのロード出来ないです、、、、(泣
マップエディタもそうですが、なんか難しい~
ん~ん、あらためて思うデス、ソフト作れる人って本当にスゴイ!!尊敬しちゃいます!!
短時間にあんなスゴイマップエディタを作ってしまったあつしさん、すぃくさんはすぃくさんで、
あんなスゴイゲームを作っちゃいますから。ハ~、、スゴイな~
私も早く作れるようになりたいな~
ロードって文字ではなく数字でとの事でえっと、
intでしたよね数字のって、イロイロやってはみたのですがどうもダメでした。
前に数値の配列変数でやるって書いてあったと思うけど、どうやってやるんですか?
配列の変数の所にマップの変数がくるんですか?
そうだとしたらどんなふうになるんだろう?
間違っていたらゴメンナサイ。
説明不足でしたね、
intこれって文字のstrに対して変数を数値型にするっていうのでしたよね、
そういう意味でカキコしたのでしたが説明不足ですいませんでした。
はい、そうですよね、配列変数はdimとsdimでしたよね、
dim map,10,10
これって前に一枚マップでのと同じですね。
一枚マップを描くのはなんとなくわかるのですが、、、
う~んと、やっぱりセーブが出来てないのかな?
そうだったら、ロードも出来ないですよね、、、
map←この変数がセーブデータに来るわけですね。
それを読み込むのかな?
数学でもそうですが、プログラミングでは
「困った時は簡略化する」が常套手段です。(たぶん)
今「マップデータを読み込む」という目標があります。
そのために必要な処理は、「ファイルからデータを読み出す」ことです。
しかし、これでは何していいか分かりませんから、
簡略化してみましょう。
①変数xの値をファイルに保存する。
②変数xにファイルから値を読み込む。
変数xは配列でもなんでもない、ただの変数です。
(数学的には、スカラーと呼ばれる物になります。)
これをやってみましょう。
まず、「①変数xの値をファイルに保存する」には、
bsave命令を使います。
bsave “filename” x 4 0
さて、ここで「なぜ4なの?」と思うかもしれませんが、
「変数一個分のサイズが4だから」です。
(正確には違います。しかし、そう考えてもいいです。)
次に、「②変数xにファイルから値を読み込む」をしましょう。
これには、すぃくさんのおっしゃるように、bloadを使います。
bload “filename” x 4 0
どうでしょうか?簡単でしょ?
さて、ではマップデータの読み込み、書き込みをして見ましょう。
まず、変数を作らなくてはいけませんね。
dim map, 10, 10
つぎに、ファイルに保存しましょう。
bsave “filename”, map, 4*10*10, 0
さて、どこが変わったでしょうか?
変わったのは、セーブするデータのサイズですね。
変数mapは、10×10の配列ですから、
100個の変数の集まりと考えられます。
ですから、データのサイズは4*10*10になるのです。
最後にファイルから読み込みましょう。
bload “filename”, map, 4*10*10, 0
簡単ですね?
つけたしですが、MapEditorにソースコード生成機能
をつける予定です。
ですから、読み込まなくても、コピペでコードに書き込めるようにしようと思います。
もちろん、ファイルに保存するようにもしますが。
でも、ファイルからの読み込みは、大変重要な部分ですので、しっかり出来るようになっておいて損はないと思いますよ。
どう転んでも、必ず必要になるスキルですから。
スクリプトを組む時ってメインを作ってから、タコ足配線みたいに、
必要な事をサブルーチンでつぎ足していけばいいんですか?
組み方のコツが良くわからなくて??
プログラムの組み立て方は、いろいろな種類があります。
私が好きなのは、オブジェクトという概念なのですが、
まあ、そんなことは抜きにして、基本的に、その人にとって分かりやすければ何でもいいです。
分かりやすいとは、あとで修正しやすいと言う事でもあります。
HSPは言語的にシンプルですので、たいしたバリエーションはもてませんが・・・。
まあ、それはともかくとして、
「サブルーチンで継ぎ足して行く」というのは、いい方法だと思いますよ。
突沸は大丈夫でした。容器割れなかったし。
教科書&ノートは黄色に染まってしまいましたが・・・。
ロゴライターと言うのは、「Logo言語を操る統合ソフト」
なのですが、なんか検索したら、公式サイトがアクセスできなくなってた・・・。
つぶれたの・・・?(T T)
スクリプトの組み方、タコ足配線サブルーチンでいいんですね。
今、絵日記を作っています。
てっ、HSPから離れてない、、、、
まだ単色黒で消しゴム機能がある程度です。
マウスで一回描くごとに上書き保存されるようになっています。
ええっと、これは戻る機能をつけてみたいなと思ってイロイロしていたら
こういう風になりました。
なんか上手くいかない?
戻り機能って、どういう風に作ったらいいんでしょうか?
アドバイスお願いします!
あつしさんの言うように簡略化ですね、あきらめず作っていくつもりです。
今後ともどうぞよろしくお願いいたしま~す☆
基本的に、ヒストリー機能は「行った動作を保存しておく」ということにつきます。
例:「位置(x,y)の色をcからdにした。なら、xとyとcとdを保存する必要がありますね。」
問題はどうやって保存するかです。
これは、言語によってまちまちですが、なんにせよ、保存用のメモリを確保する事になります。
言語はCGIですか?
ヒストリー機能はかなり高度です。
私のMapEditorでも、その機能を追加したために、
コードがかなり複雑になっています。
これは、簡略化の観点から見ると、真っ先に削るべきかと。
というか、説明するのは、かなりこんなんです。
MapEditorのように比較的単純なソフトでも、コードが
主要部分だけで、6000行にも及びますので・・・。
こんばんは~
あう、あうう、、、
ヒストリー機能って6000行もですか、ううう、、、
難しい機能だったんですね、そんな難しい機能を簡単に作ってしまうあつしさんってやっぱりすごいです。
ヒストリー機能をつけるのは私には無理っぽいですね。
ほかをもっと勉強ですね、言語はいままでどうり、HSPですよ。
えっと、また基本的なことを良いですか?
簡略化って意味ってえっと、スクリプトを組むのに全体をまず簡単に作っておくってことですよね。
そして、バージョンアップしていくってことですよね。
@チョット補足。
ヒストリー機能は確かに高度ですが、それは、MapEditorがある程度の機能を持っているからです。
機能が増えると、ヒストリーとして、保存するものが増え、
保存したデータから、復元する処理も、多くなります。
しかし「機能は一つだけ」とか、「Undoは一回のみ可能」とかなら簡単です。
つまり、簡略化すれば恐れるに足りません。
ただ、「それでソフトとしてどうか?」
と言われると、首を傾げざるをえません。
(私的に使う場合は、全然かまわないですが。)
@簡略化
そういう考え方でいいと思います。
”かろうじて”動くようなソフトを初めは作ります。
初めから、完成品を作ろうと思うと、ものすごく気が重く、
「あそこはどうだろ?あっちはどうしよ?」とかになり、
どうしてよいか分からなくなります。
”とりあえず”動くものを作って、後から少しずつ修正していくのがベストです。(たぶん。個人で作る場合。)
もちろん、当初はまったく想定していなかった
機能をつける場合なんかもありますから、
すぃくさんのように、太い幹を増築することもありますよ。
こんばんは~
簡略化って初めは、かろうじて動くような感じでいいんですね。
とりあえず動くものを作って、少しずつ修正ですね。
わかりました、全体を見るっていうか広い眼で見るって感じですね。
足元(あそこはどうだろ?あっちはどうしよ?)だけをみていてはダメって事ですね。
下だけを見て歩いていたら誰かにぶつかっちゃうもんね。
理想的なのは、気楽に少しずつ作っている間に、あれ?出来ちゃったって感じでしょうね。
さて、リリース0.9が完成しました。
こちら
「MapEdiyr(マップ・エディル)」です。
ほんとは、「MapEdiyr Atushi」にしようかと思ったのですが、やめました。
アナウンスでした。
絵日記ですが少しずつ作ってます、えっとチョッとつまずいちゃいました。
ぺん先の太さで円、まるの描き方なんですが、四角のboxfでは太さの調整はできるのですが、丸にするのが出来ません。
mes “●”で出来なくはないのですが、小さくするとおかしくなってしまうので、ん~んん、、、どうしたらいいんだろう?
こんなページ見つけました。
HSPについて、「これでもか」ってくらい書かれています。
NO.12が大変参考になると思います。