#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>