如何让2D Javascript游戏脚本在React页面上运行



我有一个HTML网站,它可以玩一个完全用javascript编程的游戏。我正在尝试将网站从HTML布局转换为更现代的React布局,但不知道如何渲染游戏。

在HTML版本中,我有以下代码要在游戏脚本中加载到页面:

window.addEventListener('loadGameEngine', loadGameEngine); 
async function loadGameEngine() {
window.removeEventListener('loadGameEngine', loadGameEngine); 
const canvas = document.getElementById("playground");
const context = canvas.getContext('2d');
const map = new GameMap(canvas); 
const loader = new Loader(); 
await loader.init(); 
const renderer = new Renderer(context, map, loader); 
const mouse = new Mouse(canvas); 
const ui = new UI(canvas, context, loader, mouse); 
const economics = new Economics(map); 
const game = new Game(canvas, renderer, ui, map, mouse); 
game.init(); 
}

然后在游戏HTML页面的主体中,我有这样的:

<div class="body">
<div class="Game__container">
<div class="canvas">
<canvas
id="playground"
width="1152"
height="576"
class="game"
></canvas>
</div>
</div>
</div>
<script type="module" src="Scripts/Engine/main.js"></script>
<script type="module" src="Scripts/Blockchain/web3.js"></script>
<script type="module" src="Scripts/Blockchain/metamask.js"></script>
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>

我尝试了多种不同的方法来加载React项目中的脚本,但Main脚本似乎从未运行过。我尝试将脚本添加到React项目的index.html中,如下所示:

<script type="text/babel" data-type="module" src="../src/Scripts/Engine/main.js"></script>
<script type="text/babel" data-type="module" src="../src/Scripts/Blockchain/metamask.js"></script>
<script type="text/babel" data-type="module" src="../src/Scripts/Blockchain/web3.js"></script> 
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>

我还尝试使用React钩子函数将脚本直接加载到React页面,如下所示:

const useScript = url => {
useEffect(() => {
const script = document.createElement('script');
script.src = url;
script.async = true;
script.type = "text/babel";
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, [url]);
};

然后调用Game组件中的CCD_ 1。当我在本地web服务器上检查元素时,我可以通过两种方式看到脚本。这是我的游戏组件的代码:

const Game = props => {
useScript("../../Scripts/Engine/main.js");
useScript("../../Scripts/Blockchain/web3.js");
useScript("../../Scripts/Blockchain/metamask.js");
useScript("https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js");
return (
<>
<div style={{ margin: "6px 0px" }}>
Gaming
</div>
<div className="body">
<div className="Game__container">
<div className="canvas">
<canvas
id="playground"
width="1152"
height="576"
className="game"
></canvas>
</div>
</div>
</div>
</>
)
}

不要像在HTML中那样加载脚本,而是从文件中export类和函数,然后import它们进入最顶部的App.js文件:

首先从你的文件中导出正确的函数和类(我不知道你的文件看起来怎么样,所以你需要自己展示或弄清楚(:

// in the file Scripts/Engine/main.js
export { map, Economics, game }
// in the file Scripts/Blockchain/web3.js
export { renderer, mouse, ui, loader }

然后将其导入您的主App.js文件:

import { map, Economics, game } from "Scripts/Engine/main.js"
import { renderer, mouse, ui, loader } from "Scripts/Blockchain/web3.js"
import /* your stuff */ from "Scripts/Blockchain/metamask.js"

然后在同一组件内部调用useEffect钩子:

useEffect(() => {
const canvas = document.getElementById("playground");
const context = canvas.getContext('2d');
const map = new GameMap(canvas); 
const loader = new Loader(); 
await loader.init(); 
const renderer = new Renderer(context, map, loader); 
const mouse = new Mouse(canvas); 
const ui = new UI(canvas, context, loader, mouse); 
const economics = new Economics(map); 
const game = new Game(canvas, renderer, ui, map, mouse); 
game.init();
}, []}

这将在渲染页面时加载脚本,但会在组件正确渲染后立即初始化它们。

你也可以做出改进来完成事情,就像你通常在反应中所做的那样。在组件顶部创建变量const canvasRef = useRef(null),用const canvas = canvasRef.current交换const canvas = document.getElementById("playground"),并在useScript0语句中将ref添加到画布:<canvas ref={canvasRef}></canvas>

最新更新