所以我尝试在 p5.js 中的菜单屏幕(当前只是带有一行文本的空白画布)和实际游戏屏幕之间切换。我目前尝试的是使用一个名为“state”的变量,该变量根据其值在菜单代码和实际游戏代码之间进行分支(菜单的状态 = 1,游戏的状态 = 2)。当状态从1变为2时,确实会切换到游戏画面,但只是静止的一帧,无法玩。
正如我上面所说,我尝试使用名为“state”的变量在不同的游戏状态之间进行分支。我编写的代码如下,不包括类。
var state;
var character;
var platform;
function setup() {
state = 1;
createCanvas(800, 400);
}
function draw() {
background(220);
if(state == 1){
text("press enter to start",20,20);
}
else if(state == 2){
enemy = new Enemy(50, 0)
character = new Player(200, 200);
platform = new Platform(0, 350, width, 50);
character.update();
platform.update();
enemy.update();
enemy.show();
character.show();
platform.show();
}
if (keyIsDown(UP_ARROW))
{
if (!character.jumping && character.grounded) {
character.jumping = true;
character.grounded = false;
character.velY = -character.speed * 3;
}
}
if (keyIsDown(LEFT_ARROW)) {
character.velX = -character.speed;
}
if (keyIsDown(RIGHT_ARROW)) {
character.velX = character.speed;
}
}
function keyPressed(){
if(keyCode === ENTER)
state = 2
}
我认为问题在于,每次重复绘制循环时,它都会创建所有类的新实例,使得游戏看起来像静止的帧,因为每个循环都替换了对象。虽然我认为这就是问题所在,但我不知道如何解决它。任何帮助将不胜感激,不仅针对这个问题,而且针对我的代码。
draw()
函数中根据场景编号切换的分支应该只更新和绘制,而不是初始化该场景的状态。只有从菜单转换到游戏屏幕的代码才应该创建与游戏相关的实体。否则,您每秒会创建一个新的 Enemy
、Player
和 Platform
大约 60 次,始终处于其初始位置,因此它们看起来是不动的。
换句话说,将像
enemy =
这样的任务移动到 if(keyCode === ENTER)
分支中,这应该被视为特定于游戏场景的 setup()
函数(以及可选的菜单场景拆卸)。
另请参阅 使用 p5.js 从一个场景过渡到下一个场景,它展示了一种更稳健的设计,可以处理具有复杂过渡的许多场景,每个场景都具有特定的输入和渲染行为。该答案中的方法还在每个场景的变量周围添加了闭包,从而更容易防止状态意外从一个场景泄漏到另一个场景。
除此之外,
1
和2
是神奇的数字,并且可以改进为至少是描述性字符串或符号,或者可能是布尔值let menuActive = true; // or false
。或者您可以将 draw()
函数替换为 draw()
的游戏版本并删除分支:
function setup() {
createCanvas(800, 400);
}
function draw() {
background(220);
text("press enter to start", 20, 20);
}
function gameLoop(t) {
background(150);
text("you're in the game loop!", sin(frameCount / 2) + 10, 20);
}
function initializeGameLoop() {
// one-time set up gameLoop here
print("switching scenes");
draw = gameLoop;
}
function keyPressed() {
// you can check which state you're in like this,
// or alternatively, override/redefine keyPressed
// the same way as done with draw()
// v---------------v
if (keyCode === ENTER && draw !== gameLoop) {
/* optionally tear down state for the menu screen here */
initializeGameLoop();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.js"></script>
这种方法具有更少的状态、更少的幻数和更少的分支,所有这些都增加了程序的复杂性,使它们更难以理解和维护。