Как создать форму цветка с эллипсами в функции класса?

#javascript #class #p5.js

Вопрос:

Я пытаюсь создать мини-игру, в которой цветок (состоящий из эллипсов) перемещается мышью горизонтально, чтобы ловить капли дождя.

Я борюсь с несколькими различными проблемами и хотел бы получить некоторую помощь!

Моя первая проблема заключается в том, что я изначально поместил маргаритку (многоточия) внутри gameScreen функции. Вместо этого я пытаюсь поместить его в класс, потому что это облегчит его нацеливание. Я новичок в классах и даже не могу понять, как разместить в них эллипс, не говоря уже о нескольких. Моя попытка поместить его в класс называется «дейзи» в приведенном ниже коде. Я не могу заставить его появиться.

Моя вторая проблема заключается в том, чтобы игра не заканчивалась, как только вы пропустите одну каплю. Я бы хотел, чтобы это закончилось после пропуска 3, но не могу понять, что мне нужно изменить, чтобы сделать это.

И, наконец, моя третья проблема заключалась бы в том, чтобы сделать цвет все более и более темным коричневым, поскольку капли воды отсутствуют.

Любая помощь по любому из этих вопросов будет высоко оценена! Я пытался понять это в течение нескольких дней, но безуспешно.

Исходный код фрагмента кода показан ниже:

 let screen = 0;
let score= 0;
let drop1;
let drop2;
let drop3;



function setup() {
  createCanvas(600, 400);
  drop1 = new rdrop1(70);
  drop2 = new rdrop1(50);
  drop3 = new rdrop1(25);
 
}

function draw() {

  if(screen == 0){
    startScreen();
  }
  
  else if(screen == 1){
    gameScreen();
  }
}

function startScreen(){
  background(9, 143, 18);
  fill(255);
  textAlign(CENTER);
  textSize(40);
  text('water the daisy', width / 2, height / 2);
  textSize(20);
  text('click to start', width / 2, height / 2   40);
    reset();
}

function gameScreen(){
  background(9, 143, 18);
  text("score = "   score, 50,25);
  noStroke();
  //flower
  fill(240, 252, 243);
  ellipseMode(CENTER);
  // ellipse(mouseX 25,height-50,50,50);
  ellipse(mouseX-25,height-50,50,50);
  ellipse(mouseX,height-75,50,50);
  ellipse(mouseX,height-25,50,50);
  fill(235, 216, 52);
  ellipse(mouseX,height-50,30,30);
  
  drop1.update();
  drop1.render();
  drop2.update();
  drop2.render();
  drop3.update();
  drop3.render();
  
  if(drop1.y>height){
    screen =2;
     }
  if(drop2.y>height){
    screen =2;
  }
  if(drop3.y>height){
    screen =2;
  }
  
  fill(255);
  if(drop1.y>height-75 amp;amp; drop1.x>mouseX-20 amp;amp; drop1.x<mouseX 20){
    score = 1;
    drop1.reset();
  }
  if(drop2.y>height-75 amp;amp; drop2.x>mouseX-20 amp;amp; drop2.x<mouseX 20){
    score = 1;
    drop2.reset();
  }
  if(drop3.y>height-75 amp;amp; drop3.x>mouseX-20 amp;amp; drop3.x<mouseX 20){
    score = 1;
    drop3.reset();
  }
}



function mousePressed(){
  if(screen==0){
    screen=1;
  }
  else if(screen==2){
    screen=0;
  }
}

function reset(){
  score=0;
  drop1.speed=0.8;
  drop1.y=-10;
  drop2.speed=0.8;
  drop2.y=-10;
  drop3.speed=0.8;
  drop3.y=-10;
}

class rdrop1{
  
  constructor(size){
    this.y = -10;
    this.x = random(20,width-20);
    this.size = size;
    this.speed = 2;
  }
  
  update(){
    this.y  = this.speed
    
  }
  
  render(){
  
    fill(7,179,223);
    ellipse(this.x,this.y,this.size,this.size);
  }
  
  reset(){
    this.y = -10
    this.x = random(20,width-20)
    this.speed = 0.2
  }
  // reduceLife(){
  // this.lifespan-=0.5
  // }
}

class daisy{
  constructor(xpos,ypos) {
    this.x = mouseX 25;
    this.y = height-50;
    this.diameter = 50;
  }
  
  render(){ 
    let c = map(rdrop1, 0, width, 0, 255);
     if(this.lifespan===0){
       fill (54, 32, 10)
     }
    fill (255, 253, 252)
    ellipse(this.x,this.y,this.diameter);
  }
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js" crossorigin=""></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js" crossorigin=""></script> 

Комментарии:

1. Я когда-либо работал только с p5j, и код, который я опубликовал, — это именно то, над чем я работаю. Я не могу понять, почему переполнение стека не считает, что он правильно отформатирован, поэтому я просто добавил ссылку на свой эскиз, чтобы вы могли проверить рабочий пример. Спасибо!

Ответ №1:

Я немного обновил ваш код, чтобы он имел дополнительные функции. У daisy класса есть health переменная, которая уменьшается всякий раз, когда он пропускает каплю дождя. Кроме того, когда это происходит, его цвет становится темнее.

Я добавил gameSettings переменную для хранения всех данных об игре. Преимущества этого заключаются в следующем: вы можете легко изменять атрибуты — например, чтобы иметь уровни сложности. Кроме того, он удаляет «волшебные» числа — жестко закодированные значения в основном игровом коде.

 var gameSettings = {
  canvasSize: {
    width: 600,
    height: 400
  },
  numRainDrops: 3,
  initialSpeed: 2,
  speedUp: 0.4,
  daisyDiameter: 40,
  daisyMaxHealth: 3,
  minRainDropSize: 25,
  maxRainDropSize: 75,
  backgroundColor: "rgb(9, 143, 18)",
  rainDropColor: "rgb(7, 179, 223)",
  daisyColor: "rgb(235, 216, 52)",
  textColor: "rgb(255, 255, 255)"
};

// Helper class to find intersections of circles.
// Can be improved for better accuracy
class boundingBox {
  constructor(x, y, w, h) {
    // Move x,y from center of circle to top,left of box
    this.x = x - w / 2;
    this.y = y - h / 2;
    this.width = w;
    this.height = h;
  }

  intersectsWith(other) {
    return (Math.abs((this.x   this.width / 2) - (other.x   other.width / 2)) * 2 < (this.width   other.width)) amp;amp;
      (Math.abs((this.y   this.height / 2) - (other.y   other.height / 2)) * 2 < (this.height   other.height));
  }
}

class Game {
  constructor() {
    this.gameStatus = "start";
    this.reset();
  }

  reset(width, height) {
    // An array of raindrops - not hard-coded to 3
    this.drops = [];
    for (let i = 0; i < gameSettings.numRainDrops; i  ) {
      this.drops.push(new rainDrop(map(random(), 0, 1, gameSettings.minRainDropSize, gameSettings.maxRainDropSize)));
    }
    this.daisy = new daisy(gameSettings.daisyDiameter);
    this.score = 0;
  }

  startGame() {
    this.gameStatus = "running";
  }

  draw() {
    if (this.gameStatus === "start") {
      this.startScreen();
    }
    else if (this.gameStatus === "running") {
      this.gameScreen();
    }
  }

  startScreen() {
    background(gameSettings.backgroundColor);
    fill(gameSettings.textColor);
    textAlign(CENTER);
    textSize(40);
    text('water the daisy', width / 2, height / 2);
    textSize(20);
    text('click to start', width / 2, height / 2   40);
  }

  // Main game loop
  gameScreen() {
    background(gameSettings.backgroundColor);
    this.daisy.draw();

    // Draw each raindrop and check if it hits the daisy
    for (let drop of this.drops) {
      drop.updateAndRender();
      if (drop.boundingBox.intersectsWith(this.daisy.boundingBox)) {
        this.score  = 1;
        drop.top();
      }
      else if (drop.isOffScreen()) {
        drop.top();
        this.daisy.health -= 1;
      }
    }

    fill(gameSettings.textColor);
    text("score = "   this.score, 50, 25);
  }

  isGameOver() {
    // Check for game over - daisy health is 0
    if (this.daisy.health <= 0) {
      this.gameStatus = "stopped";
      return true;
    }
  }
}

class rainDrop {
  constructor(size) {
    this.size = size;
    this.y = -10;
    this.x = random(20, width - 20);
    this.speed = gameSettings.initialSpeed;
  }

  // Move back to top
  top() {
    this.y = -10;
    this.x = random(20, width - 20);
    this.speed  = gameSettings.speedUp;
  }

  // Return this raindrops box
  get boundingBox() {
    return new boundingBox(this.x, this.y, this.size, this.size);
  }

  updateAndRender() {
    this.y  = this.speed;
    fill(gameSettings.rainDropColor);
    ellipse(this.x, this.y, this.size, this.size);
  }

  isOffScreen() {
    return this.y >= height;
  }
}

class daisy {
  constructor(d) {
    this.diameter = d;
    this.center = {
      x: mouseX   25,
      y: height - this.diameter
    };
    this.health = gameSettings.daisyMaxHealth;
  }

  get boundingBox() {
    return new boundingBox(this.center.x, this.center.y, this.diameter, this.diameter);
  }

  draw() {
    noStroke();
    ellipseMode(CENTER);

    // Petal color - the lower our health, the darker the petal
    const color = map(this.health, 0, gameSettings.daisyMaxHealth, 0, 255);
    fill(color, color, color);

    // Draw petals
    this.center.x = mouseX;
    ellipse(this.center.x, this.center.y - this.diameter / 2, this.diameter, this.diameter);
    ellipse(this.center.x, this.center.y   this.diameter / 2, this.diameter, this.diameter);
    ellipse(this.center.x - this.diameter / 2, this.center.y, this.diameter, this.diameter);
    ellipse(this.center.x   this.diameter / 2, this.center.y, this.diameter, this.diameter);

    // Draw center
    fill(gameSettings.daisyColor);
    ellipse(this.center.x, this.center.y, this.diameter * .7, this.diameter * .7);
  }
}

let game;

// Initialize
function setup() {
  createCanvas(gameSettings.canvasSize.width, gameSettings.canvasSize.height);
  game = new Game();
}

function draw() {
  game.draw();
  if (game.isGameOver()) {
    game.reset();
  }
}

function mousePressed() {
  if (game.gameStatus !== "running") {
    game.startGame();
  }
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>