"Interactive overlay" 在 p5.js

"Interactive overlay" in p5.js

我想在 p5.js 中执行以下操作。假设我有一个 canvas 大致像这样:

假设我使用函数 mouseClicked() 和它们在 canvas 中的各自坐标为这些红色方块提供了一些交互性(例如,如果我点击一个方块,改变它的颜色)。

现在我想用那个蓝色的 "i" 按钮来显示某种信息框,它应该大致如下所示:

我希望 "info dialog" 在用户点击 "OK-button" 时消失(这不是一个真正的按钮,只是 p5 canvas 中的一个正方形)。

问题: 是否有一种优雅的方法来停用 "square interactivity" 并激活 "OK button interactivity" 并在信息出现时以相反的方式进行交互框未显示?

我能想到的唯一方法是这样的:

function mouseClicked(){
  if(infoBoxIsBeingDisplayed){
    do something
  }else{
    do something else
  }
}

不过,这似乎有点绕。

如果有任何关于如何做得更好的建议,我将不胜感激。

我之前 运行 遇到过类似的问题,我想出的解决这个问题的最好方法(这是一种相当不完整的方法)是将方块移到canvas。抱歉,我的代码可能真的很乱,但看看函数游戏,你就会明白我做了什么

如果你 运行 游戏全屏显示。

示例:(要玩游戏,请使用 A 和 D 或使用箭头键,但我建议使用 A 和 D,因为代码片段的设置方式不适合页面,页面会四处移动当你按下箭头键时)

var bs = [];
var speed;
var ship1;
var num = 40;
var d;
var gscore = 0;
var highscore = 0;
var cap = 0;

function setup() {
    createCanvas(windowWidth,windowHeight- 4);
    
    for(var i = 0; i < num; i++) {
        bs[i] = new Box(random(0, width), random(-600,-30));
    }
    
    ship1 = new ship();
    button1 = new button();
    
}

function draw() {
    background(0);
    if(cap == 0){
         gscore = gscore + 0.1;
    }
    if(highscore < gscore){
        highscore = gscore;
    }
    speed = map(gscore,4,100,4,5);
    ship1.show();
    ship1.update();
    
    
    
    for(var i = 0; i < num; i++) {
        bs[i].update();
        bs[i].show();
        if(bs[i].y >= height){
            bs[i].x = random(0, width);
            bs[i].y = random(-600,-30);
        }
        for(var j = 0; j < num; j++) {
            if(bs[i].touch(bs[j])){
                if(bs[i] != bs[j]){
                    bs[j].x = random(0, width);
                    bs[j].y = random(-600,-30);
                }
            }
        }
        if(bs[i].touch(ship1)){
            game();
        }
     }
    push();
    fill(255,0,0);
    textSize(36);
    
    text("score: "+ floor(gscore),0,36);
    text("highscore: "+floor(highscore),0,72);
    pop();
        
    
    
    
    
}


function Box(x, y) {
    
    this.x = x;
    this.y = y;
    this.show = function() {
        fill(255);
        noStroke();
        rect(this.x, this.y, 30, 30);
    }
    this.update = function() {
        this.y = this.y + speed;
    }
    this.touch = function(other){
        d = dist(this.x, this.y, other.x, other.y);
        if(d < 15/*half of the squares*/+15/*the total area of the ship*/){
            return true;
        }else {
            return false;
        }
    }


}

function game(){//look here, game is the end game screen
    for(var i = 0; i < num; i++) {
        bs[i].x = -200;//making all squares x value -200
        bs[i].y = -200;//making all squares y value -200
    }
    ship1.x = -200;//making ship x value -200
    ship1.y = -200;//making ship y value -200
    cap = 1;//cap is a variable made to stop the score from increasing when the end game screen is shown its "capping" the score
    
    
    push();
    fill(255,0,0);
    textAlign(CENTER);
    textSize(64);
    text("You lose", width/2, height/2);
    fill(255);
    text("Try again?", width/2,height/2+64);
    button1.touch();//touch checks if the mouse is over the button(the button sucks ass btw the hitbox for it is a square not a rectangle)
    button1.show();//showing the button
    button1.update();//updates the text and button color when highlighted
    fill(texthover);
    textSize(48);
    text("Yes",width/2, height/2+145);
    pop();
    
}
function button(){
    this.x = width/2;
    this.y = height/2+128;
    this.d;
    
    this.update = function() {
        this.x = width/2;
        this.y = height/2+128;
    }
    this.show = function(){
        push();
        rectMode(CENTER);
        fill(hover);
        rect(this.x, this.y, 128, 64, 50);
        pop();

    }
    this.touch = function(){
        this.d = dist(this.x, this.y, mouseX, mouseY);
        if(this.d <32){
            hover = 51;
            texthover = 255;
            if(mouseIsPressed){
                for(var i = 0; i < num; i++) {
                    bs[i].x = random(0, width);
                    bs[i].y = random(-600,-30);
                
                }
                ship1.x = width/2;
                ship1.y = 450;
                gscore = 0;
                cap = 0;

                
            }
        }else {
            hover = 200;
            texthover = 0;
        }
        
    }
    
}

function ship() {
    this.x = width/2;
    this.y = 450;
    
    this.update = function() {        
        if(keyIsDown(LEFT_ARROW) || keyIsDown(65)) {
            if(this.x>14){
                this.x = this.x - map(gscore,2,100,2,3);
                
            }
        }
        if(keyIsDown(RIGHT_ARROW) || keyIsDown(68)) {
            if(this.x<width- 15){
                this.x = this.x + map(gscore,2,100,2,3);
            }
        
        }
    }
    this.show = function() {
        push();
        rectMode(CENTER);
        fill(200,200,0);
        rect(this.x+15, this.y+5, 5, 30);
        fill(150,100,200);
        rect(this.x+15, this.y + 15,30, 15)
        pop();
        
    }
    
    

    
    
}
function windowResized() {
    createCanvas(windowWidth,windowHeight- 4);
    button1.update();
}


    
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/addons/p5.dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>

您的解决方案似乎不错,而且似乎 "convoluted" 比任何其他选项都要少。保持简单。

您可以通过将逻辑拆分为更小的实用程序函数来清理代码。像这样:

function mouseClicked(){
  if(infoBoxIsBeingDisplayed){
    mouseClickedInfoBox();
  }else{
    mouseClickedSquaresCanvas();
  }
}

然后你的逻辑将在那些实用函数中,特定于每个屏幕。您可以进一步拆分它以概括您的边界检查,但想法是一样的。