今日は、サンダーファイタータイピングゲームを実装します。ゲームプレイは非常に簡単です。それぞれの「敵」はいくつかの英語の単語です。キーボードで単語の文字を正しく入力すると、飛行機が弾丸を1つずつ発射して「敵」を破壊します。次の「敵」を殺す前に、現在の「敵」を殺す必要があります。これは、手の速さと単語の熟練度をテストするゲームです。 まず、最終的な効果を見てみましょう。 えーっと、UI インターフェースは非常にシンプルです。まずは基本機能を実装し、その後に高度な UI を検討します。 まず、インターフェースの構成を分析しましょう。 (1)平面は絵の下部の中央に固定されている。 (2)画面上部からランダムに生成される敵(単語) (3)航空機の前方から発射され、敵に向かってまっすぐに進んだ弾丸。 (4)ゲーム終了後のスコア表示。 以前のゲームと比較すると、今回はスポーツ部分が多く、より複雑になっているようです。 Flappy Birdでは、パイプは動いていますが、鳥のx座標とパイプの間隔と幅は変わらないため、境界を計算するのが簡単です。ピンボールとレンガのゲームでは、木の板とレンガは比較的単純または固定座標であるため、ピンボールの境界とレンガの接触面積を決定するだけで済みます。 Thunder Fighter Word Elimination ゲームでは、着地するターゲットの単語でも、飛んでくる弾丸でも、すべて独自の移動軌道を持っていますが、弾丸はターゲットを追従する必要があるため、リアルタイムの軌道計算操作が行われます。 高い建物は地面から始まります。ここまで説明してきましたが、まずは一番簡単なものから始めましょう。 1. 画面下部の中央に固定された平面これは非常にシンプルで、特に言うことはありません。ここでは、航空機のデフォルトの幅と高さは 40 ピクセルで、航空機は画面の中央下部に描画されます。 平面を描画する() { _this = this とします。 _this.ctx.save(); _this.ctx.drawImage( _this.planeImg、 _this.clientWidth / 2 - 20, _this.clientHeight - 20 - 40、 40, 40 ); _this.ctx.restore(); }, 2. 画面上部からランダムに生成される敵ここでは、デフォルトでは、一度に画面に表示される単語ターゲットは 3 つだけ、ターゲットの Y 軸移動速度は 1.3、ターゲットの半径は 10 です。 const _MAX_TARGET = 3; // 一度画面に表示されるターゲットの最大数 const _TARGET_CONFIG = { // 目標速度の固定パラメータ: 1.3、 半径: 10 }; 次に、まず単語ライブラリ配列から _MAX_TARGET 個の繰り返しのない単語をランダムに取り出し、残りの単語を循環単語ライブラリ this.wordsPool に格納します。 単語を生成する(数値) { // 表示されている単語と重複しない単語をプールからランダムに選択します。let arr = []; (i = 0; i < 数値; i++) の場合 { random = Math.floor(Math.random() * this.wordsPool.length); とします。 arr.push(this.wordsPool[ランダム]); this.wordsPool.splice(ランダム、1); } arr を返します。 }, ターゲットを生成する() { // ターゲットをランダムに生成する let _this = this; 長さを_this.targetArr.lengthとします。 長さ < _MAX_TARGET の場合 { txtArr = _this.generateWord(_MAX_TARGET - 長さ) とします。 (i = 0 とします; i < _MAX_TARGET - 長さ; i++) { _this.targetArr.push({ x: _this.getRandomInt() 関数 _TARGET_CONFIG.半径、 _this.clientWidth - _TARGET_CONFIG.radius )、 y: _TARGET_CONFIG.半径 * 2、 txt: txtArr[i], タイプインデックス: -1, ヒットインデックス: -1, dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2, dy: _TARGET_CONFIG.speed * Math.random().toFixed(1)、 回転: 0 }); } } } this.targetArr はターゲット オブジェクトを格納する配列であることがわかります。
さて、3 つのターゲットを生成したので、上から下へ移動してみましょう。 描画ターゲット() { // フレームごとにターゲットを描画します。let _this = this; _this.targetArr.forEach((アイテム、インデックス) => { _this.ctx.save(); _this.ctx.translate(item.x, item.y); //回転の中心点を設定します_this.ctx.beginPath(); _this.ctx.font = "14px Arial"; もし ( インデックス === _this.currentIndex || アイテム.typeIndex === アイテム.txt.length - 1 ){ _this.drawText( アイテム.txt.substring(0, アイテム.typeIndex + 1), -item.txt.長さ * 3、 _TARGET_CONFIG.半径 * 2、 "グレー" ); 幅を_this.ctx.measureText(とする アイテム.txt.substring(0, アイテム.typeIndex + 1) ).width; // タップされたテキストの幅を取得します_this.drawText( アイテム.txt.substring(アイテム.typeIndex + 1, アイテム.txt.length), -item.txt.長さ * 3 + 幅、 _TARGET_CONFIG.半径 * 2、 "赤" ); } それ以外 { _this.drawText( アイテム.txt、 -item.txt.長さ * 3、 _TARGET_CONFIG.半径 * 2、 "黄色" ); } _this.ctx.closePath(); _this.ctx.rotate((item.rotate * Math.PI) / 180); _this.ctx.drawImage( _this.targetImg、 -1 * _TARGET_CONFIG.半径、 -1 * _TARGET_CONFIG.半径、 _TARGET_CONFIG.半径 * 2、 _TARGET_CONFIG.半径 * 2 ); _this.ctx.restore(); アイテム.y += アイテム.dy; アイテム.x += アイテム.dx; (item.x < 0 || item.x > _this.clientWidth)の場合{ アイテム.dx * = -1; } if (item.y > _this.clientHeight - _TARGET_CONFIG.radius * 2) { // 一番下をヒット_this.gameOver = true; } // 回転 item.rotate++; }); } このステップでターゲットを描画することに関して特別なことは何もありません。dx と dy をランダムに増加させて、ターゲットが左端と右端に当たったときに跳ね返るだけです。主なポイントは単語の描画です。単語は typeIndex によって 2 つの部分に分割され、タップされた文字は灰色に設定され、次に、タップされた文字の幅が measureText によって取得され、タップされていない文字の X 軸オフセットが設定され、タップされていない文字が赤に設定されて、この単語が攻撃対象であることをプレイヤーに通知します。 3. 弾丸は飛行機の前方から発射され、敵に向かってまっすぐ進みます。弾丸はこのゲームの重要な要素です。弾丸を描くときに考慮すべき点は何ですか? (1)標的は常に動いており、発射された弾丸は常に標的を「追跡」する必要があるため、軌道は動的に変化します。 (2)ターゲットを破壊するには一定数の弾丸が必要ですが、弾丸はいつ画面から消えるのでしょうか? (3)ターゲットワードにヒットすると、次の弾丸が次のターゲットに発射されるため、弾丸の軌道は一意になります。 (4)弾痕効果の描き方 (5)ターゲット単語がロックされている場合、プレイヤーは次の単語を入力する前に現在の単語の入力を完了する必要があります。 設定する変数は次のとおりです。
まず、キーボードが押されたときにトリガーされる関数を記述します。 handleKeyPress(キー) { //キーボードが押されたら、現在のターゲットを決定します let _this = this; _this.currentIndex === -1の場合{ // 現在、撃たれているターゲットはありません。let index = _this.targetArr.findIndex(item => { item.txt.indexOf(key) === 0 を返します。 }); (インデックス!== -1)の場合{ _this.currentIndex = インデックス; _this.targetArr[インデックス].typeIndex = 0; _this.createBullet(インデックス); } } それ以外 { // ターゲットがすでに撃たれている場合( キー === _this.targetArr[_this.currentIndex].txt.split("")[ _this.targetArr[_this.currentIndex].typeIndex + 1 ] ){ // ターゲットオブジェクトを取得します_this.targetArr[_this.currentIndex].typeIndex++; _this.createBullet(_this.currentIndex); もし ( _this.targetArr[_this.currentIndex].typeIndex === _this.targetArr[_this.currentIndex].txt.length - 1 ){ // このターゲットはすでに撃たれています_this.currentIndex = -1; } } } }, // 弾を発射する createBullet(index) { _this = this とします。 this.bulletArr.push({ 度数: 1, dy: 4, x: _this.clientWidth / 2, y: _this.clientHeight - 60, ターゲットインデックス: インデックス }); } この関数が行うことは非常に明確です。キーボードで現在押されている文字を取得します。currentIndex === -1 の場合、攻撃されているターゲットがないことが証明されるため、ターゲット配列に移動して、その文字と等しい最初の文字を持つ単語を確認し、currentIndex を単語のインデックスに設定して、弾丸を発射します。攻撃されているターゲットがすでにある場合は、ヒットしていない単語の最初の文字が一致するかどうかを確認します。一致する場合は、ターゲット オブジェクトの typeIndex を増やして、弾丸を発射します。現在のターゲットがヒットしている場合は、currentIndex を -1 にリセットします。 次は弾丸を描きます。 箇条書きを描画する(){ // フレームごとに弾丸を描画します。let _this = this; // 弾がターゲットに当たったかどうかを判定します if (_this.bulletArr.length === 0) { 戻る; } _this.bulletArr = _this.bulletArr.filter(_this.firedTarget); _this.bulletArr.forEach(item => { targetX = _this.targetArr[item.targetIndex].x; とします。 targetY = _this.targetArr[item.targetIndex].y とします。 k = とします (_this.clientHeight - 60 - targetY) / (_this.clientWidth / 2 - targetX); // 航空機のヘッドとターゲットの傾斜 let b = targetY - k * targetX; // 定数 b item.y = item.y - bullet.dy; // y軸を1単位オフセット item.x = (item.y - b) / k; (i = 0; i < 15; i++ とします) { // 末尾の effect_this.ctx.beginPath() を描画します。 _this.ctx.arc( (item.y + i * 1.8 - b) / k、 項目.y + i * 1.8、 4 - 0.2 * 私、 0, 2 * 数学.PI ); _this.ctx.fillStyle = `rgba(193,255,255,${1 - 0.08 * i})`; _this.ctx.fill(); _this.ctx.closePath(); } }); }, firedTarget(アイテム) { // ターゲットがヒットしたかどうかを判断します let _this = this; もし ( item.x > _this.targetArr[item.targetIndex].x - _TARGET_CONFIG.radius && item.x < _this.targetArr[item.targetIndex].x + _TARGET_CONFIG.radius && item.y > _this.targetArr[item.targetIndex].y - _TARGET_CONFIG.radius && アイテム.y < _this.targetArr[item.targetIndex].y + _TARGET_CONFIG.radius ){ // 弾丸がターゲットに命中しました。let arrIndex = item.targetIndex; _this.targetArr[arrIndex].hitIndex++; もし ( _this.targetArr[arrIndex].txt.length - 1 === _this.targetArr[arrIndex].hitIndex ){ // すべての弾丸がターゲットに命中する let word = _this.targetArr[arrIndex].txt; _this.targetArr[arrIndex] = { // 新しいターゲット x を生成する: _this.getRandomInt( _TARGET_CONFIG.半径、 _this.clientWidth - _TARGET_CONFIG.radius )、 y: _TARGET_CONFIG.半径 * 2、 txt: _this.generateWord(1)[0], タイプインデックス: -1, ヒットインデックス: -1, dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2, dy: _TARGET_CONFIG.speed * Math.random().toFixed(1)、 回転: 0 }; _this.wordsPool.push(word); // ヒットしたターゲット単語がプールに戻ります_this.score++; } false を返します。 } それ以外 { true を返します。 } } 実は、これも非常に簡単です。弾丸オブジェクトの targetIndex を使用して、弾丸が攻撃したターゲット インデックスを記録します。次に、方程式 y = kx+b を解いて、航空機のヘッド (弾丸の開始点) とターゲットの軌道関数を取得します。各フレームで各弾丸の移動座標を計算し、弾丸を描画できます。 トレーリング効果は、トラックの y 軸の成長方向に沿って、透明度と半径が徐々に減少する多数の円を描くことによって実現されます。 firedTarget() 関数では、ターゲットにヒットした弾丸をフィルタリングするために使用されます。targetArr でまだ攻撃されている他のターゲットのインデックスに影響を与えないように、スプライス削除は使用されず、破壊されたターゲットの値が直接リセットされ、wordPool から新しい単語が選択され、現在の壊れた単語がプールに戻され、画像に重複したターゲットが表示されないようにします。 4. ゲーム終了後のスコアテキスト効果ターゲットが底に触れるとゲームは終了します。 これは実はイースターエッグです。キャンバスを使用して、このような点滅する光輪のテキストを描画するにはどうすればよいでしょうか?色を切り替えてバフを積み重ねるだけ、いや、ストロークを積み重ねるだけです。 ゲームオーバーを描画する() { _this = this とします。 //コンテキストの状態を保存します object_this.ctx.save(); _this.ctx.font = "34px Arial"; _this.ctx.strokeStyle = _this.colors[0]; _this.ctx.lineWidth = 2; //Halo_this.ctx.shadowColor = "#FFFFE0"; let txt = "ゲームオーバー、スコア: " + _this.score; 幅を_this.ctx.measureText(txt).widthとします。 (i = 60、i > 3、i -= 2 とします) { _this.ctx.shadowBlur = i; _this.ctx.strokeText(txt, _this.clientWidth / 2 - width / 2, 300); } _this.ctx.restore(); _this.colors.reverse(); } はい、はい、ここまででかなり完成したゲームができましたが、UI が少し粗いです。本物の Thunder Fighter のようなかっこいい爆発効果を実現したい場合は、大量のマテリアルとキャンバス描画が必要になります。 キャンバスはとてもパワフルで楽しいです。想像力が十分あれば、このキャンバスに何でも描くことができます。 いつものように、参考までに Vue の完全なコードを以下に示します。 <テンプレート> <div class="type-game"> <キャンバスid="type" 幅="400" 高さ="600"></キャンバス> </div> </テンプレート> <スクリプト> const _MAX_TARGET = 3; // 一度画面に表示されるターゲットの最大数 const _TARGET_CONFIG = { // 目標速度の固定パラメータ: 1.3、 半径: 10 }; const _DICTIONARY = ["apple", "orange", "blue", "green", "red", "current"]; エクスポートデフォルト{ 名前: "TypeGame", データ() { 戻る { ctx: null、 クライアント幅: 0, クライアントの高さ: 0, bulletArr: [], // 画面上の弾丸 targetArr: [], // 現在のターゲットを保存 targetImg: null, 平面画像: null、 現在のインデックス: -1, 単語プール: [], スコア: 0, ゲームオーバー: false、 色: ["#FFFF00", "#FF6666"] }; }, マウント() { _this = this とします。 _this.wordsPool = _DICTIONARY.concat([]); コンテナを document.getElementById("type"); _this.clientWidth = コンテナの幅; _this.clientHeight = コンテナの高さ; _this.ctx = コンテナ.getContext("2d"); _this.targetImg = 新しい画像(); _this.targetImg.src = require("@/assets/img/target.png"); _this.planeImg = 新しい画像(); _this.planeImg.src = require("@/assets/img/plane.png"); document.onkeydown = 関数(e) { キーを window.event.keyCode とします。 (キー >= 65 && キー <= 90) の場合 { _this.handleKeyPress(String.fromCharCode(key).toLowerCase()); } }; _this.targetImg.onload = 関数() { _this.generateTarget(); (関数animloop() { もし(!_this.gameOver) { _this.drawAll(); } それ以外 { _this.drawGameOver(); } window.requestAnimationFrame(アニメーションループ); })(); }; }, メソッド: { ゲームオーバーを描画する() { _this = this とします。 //コンテキストの状態を保存します object_this.ctx.save(); _this.ctx.font = "34px Arial"; _this.ctx.strokeStyle = _this.colors[0]; _this.ctx.lineWidth = 2; //Halo_this.ctx.shadowColor = "#FFFFE0"; let txt = "ゲームオーバー、スコア: " + _this.score; 幅を_this.ctx.measureText(txt).widthとします。 (i = 60、i > 3、i -= 2 とします) { _this.ctx.shadowBlur = i; _this.ctx.strokeText(txt, _this.clientWidth / 2 - width / 2, 300); } _this.ctx.restore(); _this.colors.reverse(); }, すべて描画() { _this = this とします。 _this.ctx.clearRect(0, 0, _this.clientWidth, _this.clientHeight); _this.drawPlane(0); _this.drawBullet(); _this.drawTarget(); _this.drawScore(); }, 平面を描画する() { _this = this とします。 _this.ctx.save(); _this.ctx.drawImage( _this.planeImg、 _this.clientWidth / 2 - 20, _this.clientHeight - 20 - 40、 40, 40 ); _this.ctx.restore(); }, 単語を生成する(数値) { // 表示されている単語と重複しない単語をプールからランダムに選択します。let arr = []; (i = 0; i < 数値; i++) の場合 { random = Math.floor(Math.random() * this.wordsPool.length); とします。 arr.push(this.wordsPool[ランダム]); this.wordsPool.splice(ランダム、1); } arr を返します。 }, ターゲットを生成する() { // ターゲットをランダムに生成する let _this = this; 長さを_this.targetArr.lengthとします。 長さ < _MAX_TARGET の場合 { txtArr = _this.generateWord(_MAX_TARGET - 長さ) とします。 (i = 0 とします; i < _MAX_TARGET - 長さ; i++) { _this.targetArr.push({ x: _this.getRandomInt() 関数 _TARGET_CONFIG.半径、 _this.clientWidth - _TARGET_CONFIG.radius )、 y: _TARGET_CONFIG.半径 * 2、 txt: txtArr[i], タイプインデックス: -1, ヒットインデックス: -1, dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2, dy: _TARGET_CONFIG.speed * Math.random().toFixed(1)、 回転: 0 }); } } }, ランダム整数を取得する(n, m) { Math.floor(Math.random() * (m - n + 1)) + n を返します。 }, テキストを描画します(txt, x, y, 色) { _this = this とします。 _this.ctx.fillStyle = 色; _this.ctx.fillText(txt, x, y); }, スコアを描画する() { // スコア this.drawText("スコア: " + this.score, 10, this.clientHeight - 10, "#fff"); }, 描画ターゲット() { // フレームごとにターゲットを描画します。let _this = this; _this.targetArr.forEach((アイテム、インデックス) => { _this.ctx.save(); _this.ctx.translate(item.x, item.y); //回転の中心点を設定します_this.ctx.beginPath(); _this.ctx.font = "14px Arial"; もし ( インデックス === _this.currentIndex || アイテム.typeIndex === アイテム.txt.length - 1 ){ _this.drawText( 項目.txt.substring(0, 項目.typeIndex + 1), -item.txt.長さ * 3、 _TARGET_CONFIG.半径 * 2、 "グレー" ); 幅を_this.ctx.measureText(とする アイテム.txt.substring(0, アイテム.typeIndex + 1) ).width; // タップされたテキストの幅を取得します_this.drawText( アイテム.txt.substring(アイテム.typeIndex + 1, アイテム.txt.length), -item.txt.長さ * 3 + 幅、 _TARGET_CONFIG.半径 * 2、 "赤" ); } それ以外 { _this.drawText( アイテム.txt、 -item.txt.長さ * 3、 _TARGET_CONFIG.半径 * 2、 "黄色" ); } _this.ctx.closePath(); _this.ctx.rotate((item.rotate * Math.PI) / 180); _this.ctx.drawImage( _this.targetImg、 -1 * _TARGET_CONFIG.半径、 -1 * _TARGET_CONFIG.半径、 _TARGET_CONFIG.半径 * 2、 _TARGET_CONFIG.半径 * 2 ); _this.ctx.restore(); アイテム.y += アイテム.dy; アイテム.x += アイテム.dx; (item.x < 0 || item.x > _this.clientWidth)の場合{ アイテム.dx * = -1; } if (item.y > _this.clientHeight - _TARGET_CONFIG.radius * 2) { // 一番下をヒット_this.gameOver = true; } // 回転 item.rotate++; }); }, handleKeyPress(キー) { //キーボードが押されたら、現在のターゲットを決定します let _this = this; _this.currentIndex === -1の場合{ // 現在、撃たれているターゲットはありません。let index = _this.targetArr.findIndex(item => { item.txt.indexOf(key) === 0 を返します。 }); (インデックス!== -1)の場合{ _this.currentIndex = インデックス; _this.targetArr[インデックス].typeIndex = 0; _this.createBullet(インデックス); } } それ以外 { // ターゲットがすでに撃たれている場合( キー === _this.targetArr[_this.currentIndex].txt.split("")[ _this.targetArr[_this.currentIndex].typeIndex + 1 ] ){ // ターゲットオブジェクトを取得します_this.targetArr[_this.currentIndex].typeIndex++; _this.createBullet(_this.currentIndex); もし ( _this.targetArr[_this.currentIndex].typeIndex === _this.targetArr[_this.currentIndex].txt.length - 1 ){ // このターゲットはすでに撃たれています_this.currentIndex = -1; } } } }, // 弾を発射する createBullet(index) { _this = this とします。 this.bulletArr.push({ 度数: 1, dy: 4, x: _this.clientWidth / 2, y: _this.clientHeight - 60, ターゲットインデックス: インデックス }); }, firedTarget(アイテム) { // ターゲットがヒットしたかどうかを判断します let _this = this; もし ( item.x > _this.targetArr[item.targetIndex].x - _TARGET_CONFIG.radius && item.x < _this.targetArr[item.targetIndex].x + _TARGET_CONFIG.radius && item.y > _this.targetArr[item.targetIndex].y - _TARGET_CONFIG.radius && アイテム.y < _this.targetArr[item.targetIndex].y + _TARGET_CONFIG.radius ){ // 弾丸がターゲットに命中しました。let arrIndex = item.targetIndex; _this.targetArr[arrIndex].hitIndex++; もし ( _this.targetArr[arrIndex].txt.length - 1 === _this.targetArr[arrIndex].hitIndex ){ // すべての弾丸がターゲットに命中する let word = _this.targetArr[arrIndex].txt; _this.targetArr[arrIndex] = { // 新しいターゲット x を生成する: _this.getRandomInt( _TARGET_CONFIG.半径、 _this.clientWidth - _TARGET_CONFIG.radius )、 y: _TARGET_CONFIG.半径 * 2、 txt: _this.generateWord(1)[0], タイプインデックス: -1, ヒットインデックス: -1, dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2, dy: _TARGET_CONFIG.speed * Math.random().toFixed(1)、 回転: 0 }; _this.wordsPool.push(word); // ヒットしたターゲット単語がプールに戻ります_this.score++; } false を返します。 } それ以外 { true を返します。 } }, 箇条書きを描画する(){ // フレームごとに弾丸を描画します。let _this = this; // 弾がターゲットに当たったかどうかを判定します if (_this.bulletArr.length === 0) { 戻る; } _this.bulletArr = _this.bulletArr.filter(_this.firedTarget); _this.bulletArr.forEach(item => { targetX = _this.targetArr[item.targetIndex].x; とします。 targetY = _this.targetArr[item.targetIndex].y とします。 k = とします (_this.clientHeight - 60 - targetY) / (_this.clientWidth / 2 - targetX); // 航空機のヘッドとターゲットの傾斜 let b = targetY - k * targetX; // 定数 b item.y = item.y - 4; // y軸を1単位オフセット item.x = (item.y - b) / k; (i = 0; i < 15; i++ とします) { // 末尾の effect_this.ctx.beginPath() を描画します。 _this.ctx.arc( (item.y + i * 1.8 - b) / k、 項目.y + i * 1.8、 4 - 0.2 * 私、 0, 2 * 数学.PI ); _this.ctx.fillStyle = `rgba(193,255,255,${1 - 0.08 * i})`; _this.ctx.fill(); _this.ctx.closePath(); } }); } } }; </スクリプト> <!-- CSS をこのコンポーネントのみに制限するために "scoped" 属性を追加します --> <スタイル スコープ lang="scss"> .type-ゲーム { #タイプ { 背景: #2a4546; } } </スタイル> 以上が、VUEとCanvasを使用してThunder Fighterタイピングゲームを実装する方法の詳細です。VUE Thunder Fighterゲームの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: MySQL 4.1/5.0/5.1/5.5/5.6の主な違い
>>: nginx proxy_cache バッチキャッシュクリアスクリプトの紹介
ユーザーが登録すると、ラベルをクリックして確認コードを変更します。クリックするとラベルに影の部分がで...
MySql ダウンロード1. 公式サイトを開き、ダウンロード パスを見つけます。ダウンロード アドレ...
最近、毎日変更されるページを iframe を使用して呼び出す必要があるプロジェクトがあります。その...
MySQL を使用する場合、日付は通常、datetime や timestamp などの形式で保存さ...
Nginx (エンジン x) は、IMAP/POP3/SMTP サービスも提供する高性能 HTTP ...
まず、VMware Workstation 15.1 バージョンをダウンロードします。Thunder...
実装のアイデア:まず、アラーム情報にはitemidが必要です。これは前提条件です。情報に渡されるパラ...
序文:親コンポーネントと子コンポーネント間でデータを渡す場合、通常は props と emittin...
IDC のサーバーの /partition 使用率がいっぱいです。 100% に到達しました!確認し...
記述した Dockerfile の内容は次のとおりです。 Python:3.6.8 から pip i...
ステップ1: MySQL YUMソースを取得するMySQLの公式サイトにアクセスして、RPMパッケー...
ソフトウェア パッケージが存在しない場合は、インストールされているソフトウェアのソフトウェア ソース...
目次成果を達成する完全なコード + 詳細なコメントまとめ成果を達成する完全なコード + 詳細なコメン...
目次ミニプログラム開発者ツールのソースコードを表示する方法ミニプログラムアーキテクチャ設計1. ミニ...
SVG (Scalable Vector Graphics)は、XML 構文に基づいた画像形式です。...