⇒ 動作確認はこちらからどうぞ。
前回はPacmanクラスをつくりましたが、今回はMonsterクラスをつくります。
モンスターはパックマンがパワー餌を食べたとき以外は基本的にバックすることはありません。進行方向を決めておき、交差点などに差し掛かったときはランダムで方向を変更させます。
そこでモンスターの現在の座標から方向転換しなければならない位置にいるのか?そのとき方向転換できる方向はどれかを求める処理が必要です。IsCrossPosition関数(後述)はモンスターが交差点やT字路、L字路にいるかどうかを判定するものであり、GetDirectsMonsterMove関数はそのときに進行可能な方向の配列を取得する関数です。
またモンスターは赤色のものを除き、巣のなかにいます。巣のなかでは上下に往復運動を繰り返し、適切な時間になったら巣からでてきます。
IsMonsterInHome関数でモンスターは巣の中にいるのかどうか調べて、その場合はMonsterMoveInHome関数で上下に移動させています。StandbyCountという変数がありますが、これは巣の中から出てくるまでの時間です。StandbyCount が0になったら巣の中央に移動させ巣の外に移動させます。
それからパックマンがパワー餌を食べると、モンスターはイジケ状態になり、もと来た道を逆走します。このときはReverseMove 関数でモンスターの現在の進行方向の逆方向に移動できるかを調べて移動できる場合は逆走させます。モンスターの位置から逆走できない場合はなにもしていません。このあたりはちょっと適当な処理になっています。
モンスターの描画ですが、4つのモンスターに0,1,2,3のIDをつけて赤、ピンク、ライトブルー、オレンジのイメージを取得してこれをつかって描画します。イジケ状態のときは青色になりパワー餌の効果が切れる時間がせまると青、白と交互に色を変えます。
GoHome関数はパックマンに食われたときに巣のなかに移動させるためのものです。実際のパックマンではモンスターは目玉だけになって巣に戻りますが、いまは一瞬で巣のなかに瞬間移動する仕様になっています。この部分は改良の余地ありです。
ではMonsterクラスを示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
class Monster { Id: number = 0; InitPosition: Position = null; Position: Position = null; Direct: number = Direct.None; StandbyCount: number = 0; IsIjike: boolean = false; constructor(id, x, y, direct) { this.Id = id; this.InitPosition = new Position(); this.Position = new Position(); this.InitPosition.CenterX = x; this.InitPosition.CenterY = y; this.Position.CenterX = x; this.Position.CenterY = y; this.Direct = direct; } Move() { this.Position.CenterX = Math.round(this.Position.CenterX * 10) / 10; this.Position.CenterY = Math.round(this.Position.CenterY * 10) / 10; // もし角にいるなら進行方向を変える if (this.IsCrossPosition() || this.Direct == Direct.None) { let directs = this.GetDirectsMonsterMove(); if (directs.length == 1) this.Direct = directs[0]; else if (directs.length > 1) { let index = Math.floor((Math.random() * directs.length)); this.Direct = directs[index]; } } // もし巣のなかにいるなら前後に移動させる if (this.IsMonsterInHome()) { this.MonsterMoveInHome(); } // 巣から出た直後は交差点ではないので、ここで進路選択をする if (this.Direct == Direct.North && this.Position.CenterX == 12.5 && this.Position.CenterY == 10) { if (Math.random() < 0.5) this.Direct = Direct.West; else this.Direct = Direct.East; } // 移動させる if (this.Direct == Direct.West) this.Position.CenterX -= 0.1; if (this.Direct == Direct.East) this.Position.CenterX += 0.1; if (this.Direct == Direct.North) this.Position.CenterY -= 0.1; if (this.Direct == Direct.South) this.Position.CenterY += 0.1; // ワープさせる if ((this.Position.CenterX == 0 && this.Position.CenterY == 13) && this.Direct == Direct.West) this.Position.CenterX = 25; if ((this.Position.CenterX == 25 && this.Position.CenterY == 13) && this.Direct == Direct.East) this.Position.CenterX = 0; // イジケ状態から回復させる if (CounterattackTime <= 0) this.IsIjike = false; } // モンスターは曲がり角や十字路、T字路にいるのか? IsCrossPosition() { let x = this.Position.CenterX; let y = this.Position.CenterY; if (y == 0) { if (x == 0 || x == 5 || x == 11 || x == 14 || x == 20 || x == 25) return true; return false; } if (y == 4) { if (x == 0 || x == 5 || x == 8 || x == 11 || x == 14 || x == 17 || x == 20 || x == 25) return true; return false; } if (y == 7) { if (x == 0 || x == 5 || x == 8 || x == 11 || x == 14 || x == 17 || x == 20 || x == 25) return true; return false; } if (y == 10) { if (x == 8 || x == 11 || x == 14 || x == 17) return true; return false; } if (y == 13) { if (x == 5 || x == 8 || x == 17 || x == 20) return true; return false; } if (y == 16) { if (x == 8 || x == 17) return true; return false; } if (y == 19) { if (x == 0 || x == 5 || x == 8 || x == 11 || x == 14 || x == 17 || x == 20 || x == 25) return true; return false; } if (y == 22) { if (x == 0 || x == 2 || x == 5 || x == 8 || x == 11 || x == 14 || x == 17 || x == 20 || x == 23 || x == 25) return true; return false; } if (y == 25) { if (x == 0 || x == 2 || x == 5 || x == 8 || x == 11 || x == 14 || x == 17 || x == 20 || x == 23 || x == 25) return true; return false; } if (y == 28) { if (x == 0 || x == 11 || x == 14 || x == 25) return true; return false; } return false; } // モンスターが進行可能な方向の配列を取得する GetDirectsMonsterMove(): number[] { let x = this.Position.CenterX; let y = this.Position.CenterY; let ret = []; if (this.IsCrossPosition()) { if (CanMoveNorth(x, y) && this.Direct != Direct.South) ret.push(Direct.North); if (CanMoveEast(x, y) && this.Direct != Direct.West) ret.push(Direct.East); if (CanMoveSouth(x, y) && this.Direct != Direct.North) ret.push(Direct.South); if (CanMoveWest(x, y) && this.Direct != Direct.East) ret.push(Direct.West); } else { if (CanMoveNorth(x, y)) ret.push(Direct.North); if (CanMoveEast(x, y)) ret.push(Direct.East); if (CanMoveSouth(x, y)) ret.push(Direct.South); if (CanMoveWest(x, y)) ret.push(Direct.West); } return ret; } // モンスターは巣の中にいるのか? IsMonsterInHome() { if ( 8 < this.Position.CenterX && this.Position.CenterX < 17 && 10 < this.Position.CenterY && this.Position.CenterY < 16 ) return true; else return false; } // 巣の中にいるモンスターを上下に移動させる MonsterMoveInHome() { // this.StandbyCount が0になったら巣の中央に移動させ巣の外に移動させる if (this.StandbyCount == 0) { if (this.Position.CenterX == 12.5 && this.Position.CenterY > 10) { console.log("X=" + this.Position.CenterX); this.Direct = Direct.North; } else if (this.Position.CenterX < 12.5) { this.Direct = Direct.East; } else if (this.Position.CenterX > 12.5) { this.Direct = Direct.West; } } else { // this.StandbyCount が0よりも大きいときは上下に移動させる if (this.Position.CenterY == 12) this.Direct = Direct.South; if (this.Position.CenterY == 14) { this.Direct = Direct.North; this.StandbyCount--; } } } // パックマンがパワー餌を食べたときに方向転換させる ReverseMove() { if (this.IsMonsterInHome()) return; if (this.Direct == Direct.North && CanMoveSouth(this.Position.CenterX, this.Position.CenterY)) this.Direct = Direct.South; else if (this.Direct == Direct.South && CanMoveNorth(this.Position.CenterX, this.Position.CenterY)) this.Direct = Direct.North; else if (this.Direct == Direct.East && CanMoveWest(this.Position.CenterX, this.Position.CenterY)) this.Direct = Direct.West; else if (this.Direct == Direct.West && CanMoveEast(this.Position.CenterX, this.Position.CenterY)) this.Direct = Direct.East; } // パックマンに撃退されたモンスターを巣の中に移動させる GoHome() { this.Position.CenterX = 12.5; this.Position.CenterY = 13; this.Direct = Direct.North; this.IsIjike = false; } Draw() { let monsterImage: HTMLImageElement = monsterImages[this.Id]; if (this.IsIjike) { if (CounterattackTime > 5000 || stoping) monsterImage = ijikeImages[0]; else { if (CounterattackTime % 1000 < 500) monsterImage = ijikeImages[0]; else monsterImage = ijikeImages[1]; } } // 別のところで // const offsetX = 40; const offsetY = 60; // const magnification = 18.0; const charctorSize = 35;と定義されている let x = this.Position.CenterX * magnification - charctorSize / 2 + offsetX; let y = this.Position.CenterY * magnification - charctorSize / 2 + offsetY; con.drawImage(monsterImage, x, y, charctorSize, charctorSize); } } |