如何为p5.js游戏创建“您赢了”屏幕?

时间:2019-05-17 17:49:27

标签: javascript p5.js

我必须为我的最终项目创建一个游戏。游戏的概念是移动正方形并到达白色圆圈,同时避开黑色圆圈。当正方形碰到黑色圆圈时,我可以创建一个“游戏结束”屏幕,但是,当我对白色正方形使用相同的逻辑时,它将不起作用。当正方形在某个位置但黑色圆圈在文本上方时,它偶尔会起作用。

我的第二个问题是,我希望有一个仅在开头运行的标题屏幕。我希望一旦在键盘上按下字母P后标题屏幕消失。当我尝试将“标题屏幕”放入设置功能时,游戏无法运行。如果我将“标题屏幕”放到绘图中,它每次都会运行(尽管我知道为什么)。我也不熟练为标题屏幕编写自己的函数。

我主要关心的是“您赢了”屏幕。如果创建“标题屏幕”太复杂,则无需添加。

这是我的代码:https://editor.p5js.org/pawlisko/sketches/WClx1upD-

var player; 
var goals = [];
var enemies = [];

function setup() {
  createCanvas(400, 400);
  noStroke();
  for(let i=0;i<150;i++) {
        enemies.push(new Enemy());
  }
  for(let i=0;i<1;i++) {
        goals.push(new Goal());
  }

  player = {};
  player.x = 350;
  player.y = 10;
  player.w = 10;
  player.h = 10;
}

function draw() {
  background(0);

//start screen
  fill(227, 101, 91);
  textSize(50);
  textAlign(CENTER);
  text("Circle Maze",200, 200);
  textSize(12);
  textAlign(CENTER);
  text("Press 'P' to play.",200, 250);
//text
  text("Goal: Reach the gold square. Don't touch black circles.", 200, 290);
  text("Use keys 'W, A, S, D' to move. Refresh page to play again.", 200, 330);

if(key == 'p'){
  background(227, 101, 91);

//player
  fill(255,183,173);
  rect(player.x, player.y, player.w, player.h);

//goal
   for(let i=0;i<goals.length;i++) {
        goals[i].show();
     var end = goals[i];

//game won
     for(let g of goals) {
      d = dist(player.x, player.y, g.x, g.y);
      if(d<player.w && player.h + g.r) {
        fill(0);
        rect(0,0,400,400);
        fill(227, 101, 91);
        textSize(50);
        textAlign(CENTER);
        text("You Win",200, 200);
        textSize(12);
        textAlign(CENTER);
        text("Press 'R' to play again.",200, 250);
        }
      }
    }


//enemies
   for(let i=0;i<enemies.length;i++) {
        enemies[i].show();
     var end2 = enemies[i];

//game over
     for(let e of enemies) {
      d = dist(player.x, player.y, e.x, e.y);
      if(d<player.w && player.h + e.x) {
        fill(0);
        rect(0,0,400,400);
        fill(227, 101, 91);
        textSize(50);
        textAlign(CENTER);
        text("Game Over",200, 200);
        textSize(12);
        textAlign(CENTER);
        text("Press 'R' to play again.",200, 250);
        }
      }
    }
  }
}

function keyTyped () {
  //Moving character
    if(key === 'w') {
    player.y -= 10;
    direction = 0;
    }
    else if(key === 's') {
    player.y += 10;
    direction = 1;
  }
  if(key === 'a'){
    player.x -= 10;
    direction = 3;
  }
  else if(key === 'd') {
    player.x += 10;
    direction = 2;

  }
  if(key === 'r') {
      resetSketch();
    }
}

class Enemy {
    constructor() {
        this.x = random(width);
        this.y = random(height);
        this.r = 8;
}
    show() {
        fill(5);
        circle(this.x,this.y,this.r);
    } 
}

class Goal {
  constructor() {
    this.x = random(width);
    this.y = random(height);
    this.r = 50;
  }
  show() {
    fill(255);
    circle(this.x,this.y,this.r);
    } 
}

1 个答案:

答案 0 :(得分:0)

对于第一个问题,您可以使用this post来分解用于查找矩形是否与圆相交的算法。对于您来说,这应该更简单,因为矩形没有旋转。


// something like

var circ = {};
circ.c = center;
circ.r = radius;

var rect= {};
rect.tl = topleft;
rect.l = length;
rect.h = height;

function circRectIntersection(circle, rectangle){
   if (  (circle.c.x > rectangle.tl.x) &&
       (circle.c.y > rectangle.tl.y) &&
       (circle.c.x < rectangle.tl.x + rectangle.l) &&
       (circle.c.y < rectangle.tl.y + rectangle.h))
      return true; // circle is "in" rectangle
  if (  (circle.c.x > rectangle.tl.x) &&
        (circle.c.x < rectangle.tl.x + rectangle.l) &&
        ((abs(circle.c.y - rectangle.tl.y) < r) || (abs(circle.c.y - (rectangle.tl.y + rectangle.h)) < r)))
      return true; // horizontal lines of the rectangle intersect with the circle  possibly with all vertices outside
  if (  (circle.c.y > rectangle.tl.y) &&
        (circle.c.y < rectangle.tl.y + rectangle.h) &&
        ((abs(circle.c.x - rectangle.tl.x) < r) || (abs(circle.c.x - (rectangle.tl.x + rectangle.l)) < r)))
      return true; // vertical lines of the rectangle intersect with the circle, possibly with all vertices outside
   if ( (dist(circle.c.x, circle.c.y, rectangle.tl.x, rectangle.tl.y) < r) ||
        (dist(circle.c.x, circle.c.y, rectangle.tl.x + rectangle.l, rectangle.tl.y) < r) ||
        (dist(cricle.c.x, circle.c.y, rectangle.tl.x, rectangle.tl.y + rectangle.h) < r) || 
        (dist(circle.c.x, circle.c.y, rectangle.tl.x + rectangle.l, rectangle.tl.y + rectangle.h) < r)) 
      return true; // one of the vertices of the rectangle is in the circle

      return false;
}

我尝试将dist函数保存到最后,因为它们在计算上更加昂贵。不用说,尽管矩形和圆形之间的交点比带有圆形的圆形或带有另一个矩形的矩形要复杂,所以在尝试rect-circ之前,我建议使用rect-rect或circ-circ。

关于第二个问题,您可能应该使用描述当前屏幕模式的标志。

您可以:

  1. 具有一组描述游戏状态的布尔值
  2. 具有描述模式的int(例如,如果int为2,则说明您在游戏中;如果int为1,则说明您在“主菜单”中)
  3. 与2相同,但带有一个大写的字符串

无论哪种方式,重点是仅当您处于某个屏幕的“模式”时才调用该屏幕的图形和渲染功能。

类似这样:


var mode = 0;
const welcomeScreen = 0;
const gameScreen = 1;
const gameOverScreen = 2;
const winScreen = 3;


draw(){
  if (mode == welcomeScreen){ // draw welcome screen}
  else if (mode == gameScreen){ // draw and do game logic}
  else if (mode == gameOverScreen){ // draw game over screen}
  else if (mode == winScreen){ // draw win screen}
}

您也可以使用开关盒代替上面的else-if链。

最后,要使重置游戏更加容易,您可以将游戏的“初始化”过程置于其自己的函数中,并在每次您知道要过渡到gameScreen时调用它。

希望这会有所帮助。