質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1200閲覧

p5.jsでFPSゲームを作っているが、弾がうまく発射できない

teratera2

総合スコア3

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/07/13 15:20

p5.jsでFPSゲームを作成している中で、スペースキーを押下したときにプレイヤーの向いている向きに弾を発射する処理を行っているのですが1発目の弾を打った後に2発目の弾をプレイヤーの向きを変えて打つと、1発目の弾の向きが途中で2発目の弾を打った時の向きになってしまいます。
弾の向きをお互い干渉させないためにはどのように修正を加えれば良いでしょうか?
回答をお願い致します。

p5

1'use strict'; 2 3class Vec2 { 4 /** 5 * @param {number} x 6 * @param {number} y 7 */ 8 constructor(x, y) { 9 this.x = x; 10 this.y = y; 11 } 12 /** 13 * @param {Vec2} b 14 */ 15 add(b) { 16 let a = this; 17 return new Vec2(a.x+b.x, a.y+b.y); 18 } 19 /** 20 * @param {Vec2} b 21 */ 22 sub(b) { 23 let a = this; 24 return new Vec2(a.x-b.x, a.y-b.y); 25 } 26 copy() { 27 return new Vec2(this.x, this.y); 28 } 29 /** 30 * @param {number} s 31 */ 32 mult(s) { 33 return new Vec2(s*this.x, s*this.y); 34 } 35 mag() { 36 return sqrt(this.x ** 2 + this.y ** 2); 37 } 38} 39 40class Ray2 { 41 /** 42 * @param {Vec2} pos このレイの始点の位置ベクトル. 43 * @param {Vec2} way このレイの始点から伸びる方向ベクトル. 44 */ 45 constructor(pos, way) { 46 this.pos = pos; 47 this.way = way; 48 } 49 /** 50 * @param {Vec2} begin 51 * @param {Vec2} end 52 */ 53 static withPoints(begin, end) { 54 return new Ray2(begin, end.sub(begin)); 55 } 56 get begin() { 57 return this.pos; 58 } 59 get end() { 60 return this.pos.add(this.way); 61 } 62 /** 63 * @param {Ray2} r2 64 */ 65 intersection(r2) { 66 let r1 = this; 67 // Y軸並行の線分はこのコードでは扱えないので、並行の場合は微妙にずらす 68 // an dirty hack since this code cannot handle Y-axis parallel rays. 69 if (abs(r1.way.x) < 0.01) r1.way.x = 0.01; 70 if (abs(r2.way.x) < 0.01) r2.way.x = 0.01; 71 72 // r1,r2を直線として見て、その交点を求める 73 // Treat r1,r2 as straight lines and calc the intersection point. 74 let t1 = r1.way.y / r1.way.x; 75 let t2 = r2.way.y / r2.way.x; 76 let x1 = r1.pos.x; 77 let x2 = r2.pos.x; 78 let y1 = r1.pos.y; 79 let y2 = r2.pos.y; 80 let sx = (t1*x1 - t2*x2 - y1 + y2) / (t1 - t2); 81 let sy = t1 * (sx - x1) + y1; 82 83 // 交点が線分上にないときはnullを返す 84 // Return null if the intersection point is not on r1 and r2. 85 if ( 86 sx > min(r1.begin.x, r1.end.x) 87 && sx < max(r1.begin.x, r1.end.x) 88 && sx > min(r2.begin.x, r2.end.x) 89 && sx < max(r2.begin.x, r2.end.x) 90 ){ 91 return new Vec2(sx, sy); 92 }else{ 93 return null; 94 } 95 } 96} 97 98class Player { 99 constructor() { 100 this.pos = new Vec2(0, 0); 101 this.angle = 0; 102 } 103} 104 105class Game { 106 constructor() { 107 this.player = new Player(); 108 this.walls = []; 109 } 110 reset() { 111 this.player.pos = new Vec2(150, 250); 112 this.player.angle = 0; 113 114 this.walls = [ 115 Ray2.withPoints(new Vec2(50, 50), new Vec2(100, 300)), 116 Ray2.withPoints(new Vec2(100, 300), new Vec2(250, 200)), 117 Ray2.withPoints(new Vec2(250, 200), new Vec2(50, 50)), 118 ]; 119 } 120} 121 122class PlayerShot { 123 constructor() { 124 this.pos = new Vec2(0,0); 125 this.size = 0; 126 this.speed = 0 127 this.alive = false; 128 } 129 set(p,size,speed) { 130 this.pos.x = p.x; 131 this.pos.y = p.y; 132 this.size = size; 133 this.speed = speed; 134 this.alive = true; 135 } 136 move(angle) { 137 this.pos.x += cos(angle) * this.speed; 138 this.pos.y += sin(angle) * this.speed; 139 if(this.pos.y < 0 140 || this.pos.y < -480 141 || this.pos.x > 720 142 || this.pos.x < 0) { 143 this.alive = false; 144 } 145 } 146} 147 148// グローバル変数 Global variables 149let game; 150let fire = false; 151var CHARA_COLOR = 'rgba(0, 0, 255, 0.75)'; 152var CHARA_SHOT_COLOR = 'rgba(0, 255, 0, 0.75)'; 153var CHARA_SHOT_MAX_COUNT = 10; 154let tempAngle = 0; 155 156let charaShot = new Array(CHARA_SHOT_MAX_COUNT); 157for(let i = 0; i < CHARA_SHOT_MAX_COUNT; i++){ 158 charaShot[i] = new PlayerShot(); 159} 160 161function setup() { 162 createCanvas(720, 480); 163 164 game = new Game(); 165 game.reset(); 166} 167 168function draw() { 169 noSmooth(); 170 171 // 背景 172 background(64); 173 174 // 壁を描画. Draw the walls 175 strokeWeight(3); 176 stroke('white'); 177 let walls = game.walls; 178 for(let wall of walls) { 179 line(wall.begin.x, wall.begin.y, wall.end.x, wall.end.y); 180 } 181 182 // プレイヤーを描画. Draw the player 183 stroke('yellow'); 184 strokeWeight(20); 185 let player = game.player; 186 point(player.pos.x, player.pos.y); 187 188 // キー入力. Key input 189 if (keyIsDown(LEFT_ARROW)) player.angle -= PI / 120; 190 if (keyIsDown(RIGHT_ARROW)) player.angle += PI / 120; 191 //スペースキーで発射 192 if (keyIsDown(32)) {fire = true; 193 tempAngle = player.angle; 194 } 195 196 // fireフラグの値により分岐 197 if(fire){ 198 // すべての自機ショットを調査する 199 for(let i = 0; i < CHARA_SHOT_MAX_COUNT; i++){ 200 // 自機ショットが既に発射されているかチェック 201 if(!charaShot[i].alive){ 202 // 自機ショットを新規にセット 203 charaShot[i].set(player.pos, 3, 5); 204 205 // ループを抜ける 206 break; 207 } 208 } 209 // フラグを降ろしておく 210 fire = false; 211 } 212 213 // すべての自機ショットを調査する 214 for(let i = 0; i < CHARA_SHOT_MAX_COUNT; i++){ 215 // 自機ショットが既に発射されているかチェック 216 if(charaShot[i].alive){ 217 // 自機ショットを動かす 218 charaShot[i].move(tempAngle); 219 220 // 自機ショットを描くパスを設定 221 point( 222 charaShot[i].pos.x, 223 charaShot[i].pos.y 224 ); 225 } 226 } 227 228 // 3Dビューを描画. Draw the 3d view. 229 { 230 let viewRect = new Ray2(new Vec2(380, 40), new Vec2(320, 240)); 231 let fov = PI / 2; 232 let centerAngle = player.angle; 233 let leftAngle = centerAngle - fov/2; 234 let rightAngle = centerAngle + fov/2; 235 let beamTotal = 32; 236 let beamIndex = -1; 237 for(let angle=leftAngle; angle<rightAngle-0.01; angle+=fov/beamTotal) { 238 beamIndex++; 239 let beam = new Ray2( 240 player.pos.copy(), 241 new Vec2(cos(angle), sin(angle)).mult(120) 242 ); 243 stroke('yellow'); 244 strokeWeight(1); 245 line(beam.begin.x, beam.begin.y, beam.end.x, beam.end.y); 246 247 // 光線が2枚以上の壁にあたっていたら、一番近いものを採用する。 248 // Adapt the nearest beam. 249 let allHitBeamWays = walls.map(wall => beam.intersection(wall)) 250 .filter(pos => pos !== null) 251 .map(pos => pos.sub(beam.begin)); 252 if (allHitBeamWays.length === 0) continue; 253 let hitBeam = allHitBeamWays.reduce((a, b) => a.mag() < b.mag() ? a : b); 254 255 stroke('yellow'); 256 strokeWeight(8); 257 let hitPos = hitBeam.add(beam.begin); 258 point(hitPos.x, hitPos.y); 259 260 let wallDist = hitBeam.mag(); 261 let wallPerpDist = wallDist * cos(angle - centerAngle); 262 let lineHeight = constrain(2800 / wallPerpDist, 0, viewRect.way.y); 263 let lineBegin = viewRect.begin.add( 264 new Vec2( 265 viewRect.way.x/beamTotal*beamIndex, 266 viewRect.way.y/2-lineHeight/2 267 ) 268 ); 269 let lightness = 224; 270 strokeWeight(0); 271 fill(lightness); 272 rect(lineBegin.x, lineBegin.y, 7, lineHeight); 273 } 274 275 // 3Dビューの枠を描画. Draw border lines of the 3d view. 276 noFill(); 277 stroke('cyan'); 278 strokeWeight(4); 279 rect(viewRect.pos.x, viewRect.pos.y, viewRect.way.x, viewRect.way.y); 280 } 281} 282 283function touchMoved(event) { 284 let player = game.player; 285 player.pos.x = event.clientX; 286 player.pos.y = event.clientY; 287}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2021/07/14 00:33

どこか動作が確認できるサイトにアップして下さい
guest

回答1

0

ベストアンサー

if(charaShot[i].alive){
// 自機ショットを動かす
charaShot[i].move(tempAngle);

上記のところですべての弾を同じ角度に設定しているから向きが同じになっていると思われます。

class PlayerShot

のところで、constructor,setにangleも追加してはどうでしょうか。
そして、引数なしのmoveで弾を動かす感じです。
検証はしていません。

投稿2021/07/14 03:01

gas.engine

総合スコア608

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teratera2

2021/07/18 14:42

ありがとうございます! 弾をお互いに干渉させないで発射する事が出来ました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問