プログラミングTips
敵の数を数えるためのオブジェクトを作成します.$enemyCount に敵の数が入ります.
次のように、移動する前の場所を覚えておき、壁にぶつかったらその場所に戻すようにします。
($pat_maze+0 が壁のキャラクタパターンです)
次のように、壁との衝突を判定する箇所をふやします。判定処理を関数にしておくと便利です。
次のように、斜めに移動したときに、x座標だけ、あるいはy座標だけをもとの状態に戻すように試みます。
逆に「通れるキャラクタパターン」に注目しましょう。例えば、通れるキャラクタパターンが1種類(ここでは$pat_maze+1)
ならば、crashToWallを次のように変更すればよいです
迷路においては、曲がれる箇所が限られます。例えば1パターンあたりの大きさが
16*16のマップであれば、16ピクセル動く→向きを変える ... を繰り返して動く必要があります。
敵(Monster)を次のように変更します。
次のように、配列にメッセージを格納し、その中の要素をランダムに選ぶことで実現できます。
次のように、三角関数(sin,cos)を組み合わせて進行方向を決めることができます。
弾を出現させてから、移動方向をあらわすvx,vyの値を設定する方法がよいでしょう。
敵が弾を生成した後、プレイヤー($myChar)の位置にもとづき方向(tama.vx, tama.vy)を計算します。
このプログラムを参考にしてください。
Boss のプログラムで、体力を減らす処理を行っています。
チュートリアルのシューティングを例にとって説明します。
敵(Enemy)の当たり判定(atariHantei)メソッドで、弾(Tama)ぶつかったときに弾のほうにもdieメソッドを呼びます。
次のように、自機が死んだかどうかを監視し、死んだら新しい自機を作り出すオブジェクトを作成します。
弾オブジェクトに、持続時間をあらわす変数を用意し、1フレーム毎に減らしていくようにします。
敵に、ジャンプ中の処理を次のように加えます。
まず、動くブロック(Block)を作成します。
トラブルシューティング
Tonyuのオブジェクトは,そのオブジェクトの処理が終了すると消えてしまいます.プログラムに待機する処理か,ループする処理を加えましょう.
テキストオブジェクトをダブルクリックして,次のようにします.
使っているファイルに「読みだし専用」ファイルがあると発生します。ファイ
ルのプロパティで読みだし専用のチェックを外してください。
画面のプロパティで、色数が24Bit (Truecolor)の場合この症状が
発生することがあります。色数を16Bitに落してみて下さい。
画面外に出たオブジェクトを消していない可能性があります。
オブジェクトを消すには次のいずれかを行う必要があります。
次の例を見て下さい。
このオブジェクトは左から右に移動していきますが、
while(1)となっているため、画面右端にでても動きつづけます。
whileのループ条件(1) を変更して、次のようにするとよいでしょう。
または、次のような文を挟んでおくのもよいでしょう。
マップを初期化していないと正しく描けません。
マップを使うには、メニューの「ウィンドウ」>「マップ作成」 で、
マップの大きさを予め設定する必要があります。
効果音のwavファイルを他のアプリケーションが使っている場合、鳴らないこ
とがあります。エクスプローラでそのファイルのあるフォルダを開いている
だけでも鳴らないことがあるようです。
ソースの中に「全角スペース」が入っている可能性があります。
なにもないところでカーソルを動かしたときに、いっぺんに半角2文字分
動く場所があったらその部分が全角スペースです。半角スペースになおしてく
ださい
その他
特別な許可はいりません。有料プログラムも配布できます。
ただし配布できるファイルは次のいずれかです。
キャラクタパターン用ビットマップの作り方
を参考にファイルを作ってください。
while (1) {
$enemyCount=0; // 敵の数を格納する変数
for (t in $chars) { // すべてのオブジェクトを調べる
if (t is Enemy) { // tが敵だったら
$enemyCount++; // $enemyCount を増やす
}
}
update();
}
extends SpriteChar;
while(1) {
sx=x;sy=y; // 移動前の場所を保存
// キーボードで移動する
if (getkey(39)>0) x+=3;
if (getkey(37)>0) x-=3;
if (getkey(40)>0) y+=3;
if (getkey(38)>0) y-=3;
if ($map.getAt(x,y)==$pat_maze+0) {
// 壁にぶつかっていたら、移動前の場所に戻る
x=sx;y=sy;
}
update();
}
extends SpriteChar;
function crashToWall(x,y) {
// (x,y)の周囲が壁だったら1,そうでなければ0を返す
if ( $map.getAt(x+10,y)==$pat_maze+0 ||
$map.getAt(x,y+10)==$pat_maze+0 ||
$map.getAt(x-10,y)==$pat_maze+0 ||
$map.getAt(x,y-10)==$pat_maze+0 ) {
return 1;
} else {
return 0;
}
}
while(1) {
sx=x;sy=y; // 移動前の場所を保存
// キーボードで移動する
if (getkey(39)>0) x+=3;
if (getkey(37)>0) x-=3;
if (getkey(40)>0) y+=3;
if (getkey(38)>0) y-=3;
if (crashToWall(x,y)==1) {
// 壁にぶつかっていたら、移動前の場所に戻る
x=sx;y=sy;
}
update();
}
extends SpriteChar;
function crashToWall(x,y) {
// (x,y)の周囲が壁だったら1,そうでなければ0を返す
if ( $map.getAt(x+10,y)==$pat_maze+0 ||
$map.getAt(x,y+10)==$pat_maze+0 ||
$map.getAt(x-10,y)==$pat_maze+0 ||
$map.getAt(x,y-10)==$pat_maze+0 ) {
return 1;
} else {
return 0;
}
}
while(1) {
sx=x;sy=y; // 移動前の場所を保存
// キーボードで移動する
if (getkey(39)>0) x+=3;
if (getkey(37)>0) x-=3;
if (getkey(40)>0) y+=3;
if (getkey(38)>0) y-=3;
if (crashToWall(x,y)==1) {
// 壁にぶつかっていたら、移動前の場所に戻る
if (crashToWall(sx,y)==0) {
// x座標だけもとの状態に戻して、ぶつかっていなければ
x=sx; // x座標だけもとの状態に戻す
} else if (crashToWall(x,sy)==0) {
// y座標だけもとの状態に戻して、ぶつかっていなければ
y=sy; // y座標だけもとの状態に戻す
} else {
// x座標、y座標片方だけもどしたときに、いずれもぶつかっていたら
x=sx;y=sy; //両方もとの状態に戻す
}
}
update();
}
function crashToWall(x,y) {
// (x,y)の周囲が壁だったら1,そうでなければ0を返す
if ( $map.getAt(x+10,y)!=$pat_maze+1 ||
$map.getAt(x,y+10)!=$pat_maze+1 ||
$map.getAt(x-10,y)!=$pat_maze+1 ||
$map.getAt(x,y-10)!=$pat_maze+1 ) {
return 1;
} else {
return 0;
}
}
extends SpriteChar;
//注意:
// * $pat_block+0 を通路(通れるマップパターン)とする
// * 行き止まりがある通路ではうまく動かない(そのまま進んでしまう)
muki=1; // 0:left 1:right 2:up 3:down
while (1) {
// マップ1個あたり 16*16 の通路を動く
for(i=0 ;i<8; i++) { // 1フレームあたり2ピクセル*8フレーム
if (muki==0) x-=2;
if (muki==1) x+=2;
if (muki==2) y-=2;
if (muki==3) y+=2;
update();
}
// 進行方向に壁があるか、 5分の1の確率で向きを変える
if (hasWall()==1 || rnd(5)==0 ) {
if (muki==0 || muki==1) {
// 横に移動中、縦に移動できる通路があればその方向へ向きを変える
if (upOK()==1) muki=2;
if (downOK()==1) muki=3;
} else if (muki==2 || muki==3) {
// 縦に移動中、横に移動できる通路があればその方向へ向きを変える
if (leftOK()==1) muki=0;
if (rightOK()==1) muki=1;
}
}
}
function hasWall() {// 進行方向に壁があれば1を、なければ0を返す
if (muki==0 && leftOK()) return 0;
if (muki==1 && rightOK()) return 0;
if (muki==2 && upOK()) return 0;
if (muki==3 && downOK()) return 0;
return 1;
}
function leftOK() { //左に移動できるのなら1を、そうでなければ0を返す
if ($map.getAt(x-16,y)==$pat_block+0) return 1;
else return 0;
}
function rightOK() {//右に移動できるのなら1を、そうでなければ0を返す
if ($map.getAt(x+16,y)==$pat_block+0) return 1;
else return 0;
}
function upOK() {//上に移動できるのなら1を、そうでなければ0を返す
if ($map.getAt(x,y-16)==$pat_block+0) return 1;
else return 0;
}
function downOK() {//下に移動できるのなら1を、そうでなければ0を返す
if ($map.getAt(x,y+16)==$pat_block+0) return 1;
else return 0;
}
extends SpriteChar;
function damage() {// ダメージを与えるときにここを呼び出す。
if (damaged==1) return;
damaged=1;
life--;
if (life<=0) die();
}
function damageMotion() {// ダメージ中の動作
vy=-8;
while(1) {
x-=vx;
y+=vy;
vy++;
if (vy>0 && $map.getAt(x,y+24)==$pat_Block+0) break; // 着地したら動作終わり
update();
}
damaged=0;
}
// 途中略
while (1) {
if (damaged==1) damageMotion(); //ダメージを受けたら動作開始
if (crashTo($snowMan)) {
// 自機とぶつかったら
if ( $snowMan.y < y-8 && $snowMan.vy>0 ) {
// 自機は敵より少し上にいて、下方向に速度をもっているならば
damage(); // 敵がダメージを受ける
$snowMan.vy=-5; // 自機がはねあがる
} else {
$snowMan.die(); // そうでなければ自機が死ぬ
}
}
// 途中略
}
extends TextChar;
msgs=new Array(); // 配列を作成
msgs.add("おはよう"); // 配列に要素を追加
msgs.add("こんにちは");
msgs.add("こんばんは");
text=msgs.get(rnd(msgs.size())); // 要素のうちどれかを表示
// 移動速度
speed=1;
while (1) {
// 左右キーで回転する
if (getkey(37)) {angle+=1;}
if (getkey(39)) {angle-=1;}
// 方向にしたがって移動
x += cos(angle)*speed;
y += sin(angle)*speed;
update();
}
また、speed を変化させることによって加速、減速を表現することができます。
// 移動速度
speed=1;
while (1) {
// 左右キーで回転する
if (getkey(37)) {angle+=1;}
if (getkey(39)) {angle-=1;}
// 方向にしたがって移動
x += cos(angle)*speed;
y += sin(angle)*speed;
if (getkey(32)) speed=speed+0.1; // スペースキーが押されていたら加速
speed=speed*0.99; // 減速
update();
}
appearメソッドは、出現させたオブジェクトを戻り値として持つため、次のよ
うにすると値が設定できます。
//-------自機の処理(Jiki.tonyu)--------
extends SpriteChar;
while(1) {
if (getkey(39)>0) {x+=3;vx=6; vy=0;}
if (getkey(37)>0) {x-=3;vx=-6; vy=0;}
if (getkey(38)>0) {y-=3;vx=0; vy=-6;}
if (getkey(40)>0) {y+=3;vx=0; vy=6;}
if (getkey(32)==1) {
nobj=appear(new Tama(x,y,$pat_sample)); // nobjが、new Tama(x,y,$pat_sample)によって新規作成したオブジェクトを参照するようになる。
nobj.vx=vx; // 新しいオブジェクトの変数vxを指定
nobj.vy=vy; // 新しいオブジェクトの変数vyを指定
}
update();
}
//-------弾の処理(Tama.tonyu)-------
extends SpriteChar;
while(1) {
x+=vx;y+=vy;
update();
}
tama=appear(new Tama(x,y)); // 弾出現
dx=$myChar.x-x; // プレイヤーと敵の位置関係(x方向)
dy=$myChar.y-y; // プレイヤーと敵の位置関係(y方向)
a=angle(dx,dy); // プレイヤーと敵の角度
tama.vx=cos(a)*5; // 弾の移動方向(x方向)
tama.vy=sin(a)*5; // 弾の移動方向(y方向)
extends SpriteChar;
function atariHantei() {
for (t in $chars) {
if ( t is Tama && crashTo(t) ) {
// もし弾 t にぶつかったら
life=life-1; //体力をへらす
t.die(); //当たった弾をけす
if (life<1) die(); //もし体力がなくなったら死ぬ
}
}
}
life=5; // 敵の体力
while(1) {
while(x<$screenWidth) {// →移動
x=x+2;
atariHantei(); //上で定義した当たり判定のメソッドを呼ぶ
update();
}
while(x>0) { // ←移動
x=x-2;
atariHantei(); //上で定義した当たり判定のメソッドを呼ぶ
update();
}
}
まず、自機に新しくメソッドを追加します。damageという名前で、自機のlife
を1つへらし、lifeが0になったら死ぬように します
function damage() {
life=life-1;
if (life<=0) die();
}
life=3; // あらかじめ自機のライフをきめておく
while(1) {
if (getkey(39)>0 && x<$screenWidth ) x=x+3;
if (getkey(37)>0 && x>0) x=x-3;
: (中略)
}
-----------
次に、敵の処理で、自機を破壊する処理のところに注目します
if (crashTo($myChar)) $myChar.die();
これをdieのかわりにdamageにします。また、連続してダメージを受けるのをさけるため、敵を殺します
if (crashTo($myChar)) {
$myChar.damage();
die();
}
function atariHantei() {
for (t in $chars) {
if ( t is Tama && crashTo(t) ) {
t.die(); // ここを追加
die();
$score=$score+10;
}
}
if (crashTo($myChar)) $myChar.die();
}
extends SecretChar;
while (1) {
if ($myChar.isDead()) {//自機が死んでいたら
wait(30); // 30フレーム(0.5 秒)待つ
$myChar=appear(new MyChar(200,330,$pat_Sample+0)); // 新しい自機が出現する
}
update();
}
extends SpriteChar;
len=10; // 持続時間
while(len>0) { // len が 0 になるまで動く
y=y-8;
len--;
update();
}
while(1) {
:
:
(その他の処理省略)
:
:
// 敵がジャンプする
// jumping: ジャンプ中は1、着地中は0
// vy: 縦方向の移動量
if (jumping) { // ジャンプ中の処理
y+=vy; // 縦方向に vy だけ移動
vy=vy+0.5; // vy に 重力を加える
if ($map.getAt(x,y+15)==$pat_Block+0) {// 下にブロックがあれば、着地する
jumping=0;
}
} else { // 着地中の処理
if (rnd(100)==0) { // 100分の1の確率でジャンプを開始
vy=-10; // ジャンプした瞬間の縦の速度
jumping=1;
}
}
}
また、ジャンプ中に、ブロックの端や壁に当たって引き返す処理をさせないようにします。
if (!jumping) {
if ($map.getAt(x+vx,y)==$pat_Block+0 || $map.getAt(x+vx,y+32)!=$pat_Block+0) { // 進行方向のマップパターンがブロック、または斜め下がブロックでなかったら
a.pause(); // 待機前にアニメーションを止める
updateEx(3); // 3 フレーム待機
a.resume(); // 待機後にアニメーション再開
vx=-vx; // 進行方向を反転する
}
}
cx=x; cy=y; // 往復の中心
vx=5; vy=0; // 最初の移動方向
while(1) {
x+=vx;
y+=vy;
if (x< cx) vx+=0.1; else vx-=0.1;
if (y< cy) vy+=0.1; else vy-=0.1;
update();
}
次に、プレイヤーの処理において、ブロックの処理を追加します。
while(1) {
// ...他の処理は省略
// riding : ブロックに乗っていれば、そのブロックオブジェクトを指す。
// 乗っていなければNull
if (!riding) { //ブロックに乗っていないとき
// ブロックを探す
for (b in $chars) {
// ブロックにぶつかっていて、今下に落ちている途中ならば
if (b is Block && crashTo(b) && vy>0) {
// ブロックに乗る
riding=b;
// offsetX : ブロックと自分の横の相対位置
offsetX=x-riding.x;
}
}
} else { // ブロックに乗っているとき
vy=0; // 上下移動しない
x=riding.x+offsetX; // 横位置は、ブロックの位置+乗ったときの相対位置
y=riding.y-32; // 縦位置は、ブロックの位置-32
if (getkey(32)==1) {
// スペースキーが押されたら、乗っていない状態になる
vy-=10;
riding=null;
}
}
// 他の処理は省略...
}
extends TextChar;
wait();
テキストオブジェクトに何か処理をさせたい場合は,次のようにします
extends TextChar;
while(1) {
// ここに処理を書く
update();
}
extends SpriteChar;
while(1) {
x=x+10;
update();
}
extends SpriteChar;
while(x<$screenWidth) {
x=x+10;
update();
}
↑このプログラムでは、xが画面右端より左側にいる間だけwhileのなかをまわり
右端へ到達するとwhileループを脱出し、プログラムが終了します。
extends SpriteChar;
while(1) {
x=x+10;
if (x<0 || x>$screenWidth || y<0 || y>$screenHeight) die();
update();
}
追記:Ver 1.07からはscreenOut()メソッドで代用できます。
extends SpriteChar;
while(1) {
x=x+10;
if (screenOut()) die();
update();
}
他のアプリケーションを終了させてください、それでも鳴らない場合、
現在作っているプログラムが格納されたフォルダを、まるごと別の場所に
コピーしてみてください。コピーしたフォルダ内にあるプログラムを
実行させると鳴る場合があります。
extends SpriteChar;
while(1) {
// カーソルキーにしたがってうごく。画面端にくると動けないようにする
if (getkey(39)>0 && x<$screeenWidth) x+=3;
if (getkey(37)>0 && x>0) x-=3;
}
スペルミスです。$screeenWidthのスペルを確認してください。
変数を書きまちがえてもエラーになりません。代わりに
初期化されていない変数を使うことになるので
挙動がおかしくなります。充分注意してください。
extends SpriteChar;
while(1) {
// カーソルキーにしたがってうごく。画面端にくると動けないようにする
if (getkey(39)>0 && x<$screenWidth) x+=3;
if (getkey(37)>0 && x>0) x-=3;
}
update();を忘れています。
whileループの中に追加してください。
これらのアーカイブにマニュアルの類など、ユーザが独自に作成したファイル
を追加してもかまいません。
また、ランタイムのファイル名Player.exeは変更してもかまいません。
それ以外のファイル、フォルダ名は変更すると動作しない可能性があります。