问题描述
代码链接以供参考:https://editor.p5js.org/tpant963/sketches/wQy1zfKBW
您好!因此,我使用p5.js制作了一个Java OOP概念复习游戏,在游戏中,屏幕上会出现一个问题,周围漂浮着气泡,上面有单词关联。如果当你点击气泡时它变成了绿色,这意味着你已经点击了正确的答案/联想。如果它变成红色,则表示您点击了错误的按钮。
我想设置我的游戏,以便如果所有正确答案都被单击(即所有可能变为绿色的气泡都已被单击),则会显示重新播放按钮,如果您单击它,游戏将重新开始,您可以再次玩游戏。
如何才能做到这一点?这是让我在美学上最接近我想要的最终结果的尝试的一个示例,但它不能返回到主菜单并在我单击重新播放时实际重新启动游戏。此外,我仍然可以在游戏过程中单击不正确的&q;气泡并得到相同的结果,这是我不想要的。
let menu = 0;
function draw() {
if (menu == 1) {
background(bubblepopperG)
fill(0)
textSize(25)
text(currentQuestion.question, 25, 300);
//Allow the bubbles to move and be displayed on the screen.
bubbles.forEach(bubble => {
bubble.move();
bubble.display();
})
if (answerCount > currentQuestion.correct.length){
background(bubblepopperG)
textSize(30)
text('YOU GOT ALL THE RIGHT BUBBLES!', 25, height / 2)
//Add button to return to main menu.
fill(255, 0, 255);
rect(180, 400, 250, 75);
stroke(100);
strokeWeight(3);
textSize(26);
text('PLAY AGAIN', 230, 450);
}
}
然后我尝试了相同的操作,但尝试在游戏结束时将MousePressed()函数分配给&Play Again&qot;按钮。代码如下:
if (answerCount > currentQuestion.correct.length){
menu = 4;
background(bubblepopperG)
textSize(30)
text('YOU GOT ALL THE RIGHT BUBBLES!', 25, height / 2)
//Add button to return to main menu.
fill(255, 0, 255);
rect(180, 400, 250, 75);
stroke(100);
strokeWeight(3);
textSize(26);
text('PLAY AGAIN', 230, 450);
}
}
function mousePressed(){
if (menu == 4) {
if (mouseX < 430 && mouseX > 180) {
if (mouseY < 475 && mouseY > 400) {
menu = 0
}
}
}
}
然而,这个版本甚至根本不允许显示游戏后的屏幕。它只会把我直接带回我制作的游戏菜单,但当我到达那里时,我无法点击任何东西。
谢谢
推荐答案
差一点!
简短回答:您已经有一个条件来检查是否已在边界框内按下按钮,以及一个条件来检查是否应该显示再次播放菜单(例如if(answerCount > currentQuestion.correct.length)
)。
记住您所处的状态/菜单,并使用正确的条件。
模仿您的代码,您会得到如下内容:
if(menu == 1){
if (mouseX < 430 && mouseX > 180) {
if (mouseY < 475 && mouseY > 400) {
// reset answer count
answerCount = 0;
// return to start menu
menu = 0;
}
}
}
更新:
根据您的评论,您需要计算正确气泡的数量(一种方法可能是过滤CorrectBubble
实例并计算它们(例如bubbles.filter(bubble => bubble instanceof CorrectBubble)
))以及正确气泡的总数和已点击的正确气泡的数量(同样,过滤可以有所帮助:例如correctBubbles.filter(bubble => bubble.col === bubble.clickedColor).length)
)
clicked()
可以更新内部布尔属性,这将使代码更具可读性(例如,在clicked()
中添加this.isClicked = true;
会使裁剪的气泡过滤器读作correctBubbles.filter(bubble => bubble.isClicked)
。
还有一个小的冲突检测错误,您的意思可能类似于if (d < this.r * 0.5)
(可能会将this.r
重命名为this.diameter
以反映它的使用方式)。
更好的是,可以将reset()
方法添加到Bubble
类,以重置boolean
标志和颜色:
reset(){
this.isClicked = false;
this.col = '#000000';
}
气泡被很好地封装到类中。您可以对最小化repetition的按钮执行相同的操作。
以下是您的主草图的修改版本,其中包含一个基本的Button
类来封装显示并在外接矩形功能中单击:
let menu = 0 //Variable to show the game main menu.
let bubblepopper; //A variable for the image
let bubblepopperM; //A variable for the menu background image
let bubblepopperG; //A variable for the game background image
const bubbles = []; //Array to store the bubbles.
let currentQuestion = null;
const questions = [
{
question: 'What are the 4 types of access modifiers?',
correct: ['public', 'private', 'protected', 'default'],
incorrect: ['method', 'class', 'protection', 'published', 'nested', 'abstract'],
},
{
question: 'Words that go with encapsulation:',
correct: ['class', 'method', 'variable','access modifiers'],
incorrect: ['initial', 'encapsulate', 'complex', 'automatic', 'primitive', 'interface'],
},
{
question: 'Things you can put in a UML OBJECT diagram:',
correct: ['classes', 'variables', 'components', 'methods'],
incorrect: ['packages', 'Java Project', 'client code', 'no booleans', 'no objects', 'concatenation'],
},
{
question: 'Abstract classes...',
correct: ['declare abstract', 'extend subclass', 'no instantiation', 'static & non-static'],
incorrect: ['interface', 'only static', 'slow', 'only public access', 'default methods', 'multiple inheritance'],
},
{
question: 'OOP important words:',
correct: ['encapsulation', 'inheritance', 'polymorphism', 'abstraction'],
incorrect: ['capsuling', 'aggravation', 'adhesion', 'dissociation', 'array', 'submethod'],
},
{
question: 'Which of the following words go together?',
correct: ['private class', 'getter', 'setter', 'protect data'],
incorrect: ['public class', 'char', 'float', 'array', 'settings', 'extends class'],
},
];
class Button{
constructor(x, y, width, height, label, textSize, fillColor){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.label = label;
this.textSize = textSize;
this.fillColor = fillColor;
}
draw(){
push();
textAlign(CENTER);
fill(this.fillColor);
rect(this.x, this.y, this.width, this.height);
stroke(100);
strokeWeight(3);
textSize(this.textSize);
fill(255);
text(this.label, this.x + (this.width * 0.5), this.y + (this.height * 0.75));
pop();
}
isPressed(){
return ((mouseX >= this.x && mouseX <= this.x + this.width) &&
(mouseY >= this.y && mouseY <= this.y + this.height));
}
}
let playButton;
let exitButton;
let instructionsButton;
function preload() {
bubblepopper = loadImage('Bubble Popper Logo.png');
bubblepopperM = loadImage('Bubble Popper Menu Background.jpg');
bubblepopperG = loadImage('Bubble Popper Game Background.jpg');
}
function setup() {
currentQuestion = questions[Math.floor(Math.random() * questions.length)];
createCanvas(600, 600);
for(let i = 0; i < currentQuestion.correct.length; i++) {
bubbles.push(new CorrectBubble(random(-3, 3), random(-3, 3), currentQuestion.correct[i], random(width), random(height), random(80,100)));
} //The new bubbles will be added to the bubbles array.
for(let i = 0; i < currentQuestion.incorrect.length; i++) {
bubbles.push(new IncorrectBubble(random(-3, 3), random(-3, 3), currentQuestion.incorrect[i], random(width), random(height), random(80,100)));
} //The new bubbles will be added to the bubbles array.
playButton = new Button(50, 100, 200, 75, 'PLAY', 50, color(64,224,208));
exitButton = new Button(50, 400, 200, 75, 'EXIT', 50, color(255, 0, 255));
instructionsButton = new Button(50, 250, 200, 75, 'INSTRUCTIONS', 26, color(64,224,208));
playAgainButton = new Button(180, 400, 250, 75, 'PLAY AGAIN', 26, color(255, 0, 255));
returnToMenuButton = new Button(180, 400, 250, 75, 'RETURN TO MENU', 26, color(255, 0, 255));
}
function mousePressed() {
//For each bubble in the array, click it and allow it to change to it's correct colour.
bubbles.forEach(bubble => bubble.clicked(mouseX, mouseY));
}
function draw() {
//Set up the main menu and the buttons in it.
background(bubblepopperM);
playButton.draw();
exitButton.draw();
instructionsButton.draw();
image(bubblepopper, 275, 150, 300, 300); //Add the Bubble Popper logo.
if (menu == 1) {
background(bubblepopperG)
fill(0)
textSize(25)
text(currentQuestion.question, 25, 300);
//Allow the bubbles to move and be displayed on the screen.
bubbles.forEach(bubble => {
bubble.move();
bubble.display();
})
const correctBubbles = getCorrectBubbles();
if (countClickedBubbles(correctBubbles) === correctBubbles.length){
background(bubblepopperG)
textSize(30)
text('YOU GOT ALL THE RIGHT BUBBLES!', 25, height / 2)
//Add button to return to main menu.
playAgainButton.draw();
}
}
//When clicked this will show the user instructions on how to play the game.
if (menu == 2) {
background(bubblepopperM)
fill(255);
stroke(100);
strokeWeight(3);
textSize(20)
text('1. A question will be displayed to do with object-oriented', 50, 150)
text('programming (OOP) concepts.', 80, 175)
text('2. Click on the bubbles with the correct word associations', 50, 225)
text('to the question. Correct answers will turn green,', 80, 250)
text(' incorrect answers will turn red when clicked on.', 80, 275)
text('3. The round is over when you select all the correct bubbles', 50, 325)
returnToMenuButton.draw();
}
//Will exit out of the program.
if (menu == 3) {
background(bubblepopperM);
fill(255);
textSize(50);
text('THANKS FOR PLAYING!', 25, height / 2);
playAgainButton.draw();
}
}
function getCorrectBubbles(){
return bubbles.filter(bubble => bubble instanceof CorrectBubble);
}
function countClickedBubbles(bubbles){
return bubbles.filter(bubble => bubble.col === bubble.clickedColor).length;
}
//Determine the mouse coordinates so that the user can click on the buttons.
function mouseClicked() {
if (menu == 0) {
if(playButton.isPressed()){
menu = 1;
}
if(instructionsButton.isPressed()){
menu = 2;
}
if(exitButton.isPressed()){
console.log('exit');
menu = 3;
}
}
if(menu == 1){
if (playAgainButton.isPressed()) {
// return to start menu
menu = 0;
}
}
//Allow the user to go back to the main menu if they click instructions.
if (menu == 2) {
if(returnToMenuButton.isPressed()){
menu = 0;
}
}
//Allow the user to go back to the main menu if they click exit.
if (menu == 3) {
if(playAgainButton.isPressed()){
menu = 0;
}
}
}
此外,还可以将基于menu
的功能封装到类中。以下是上述代码的变体,其中包含一个说明多态的基本状态机:
let bubblepopper; //A variable for the image
let bubblepopperM; //A variable for the menu background image
let bubblepopperG; //A variable for the game background image
const bubbles = []; //Array to store the bubbles.
let currentQuestion = null;
const questions = [
{
question: 'What are the 4 types of access modifiers?',
correct: ['public', 'private', 'protected', 'default'],
incorrect: ['method', 'class', 'protection', 'published', 'nested', 'abstract'],
},
{
question: 'Words that go with encapsulation:',
correct: ['class', 'method', 'variable','access modifiers'],
incorrect: ['initial', 'encapsulate', 'complex', 'automatic', 'primitive', 'interface'],
},
{
question: 'Things you can put in a UML OBJECT diagram:',
correct: ['classes', 'variables', 'components', 'methods'],
incorrect: ['packages', 'Java Project', 'client code', 'no booleans', 'no objects', 'concatenation'],
},
{
question: 'Abstract classes...',
correct: ['declare abstract', 'extend subclass', 'no instantiation', 'static & non-static'],
incorrect: ['interface', 'only static', 'slow', 'only public access', 'default methods', 'multiple inheritance'],
},
{
question: 'OOP important words:',
correct: ['encapsulation', 'inheritance', 'polymorphism', 'abstraction'],
incorrect: ['capsuling', 'aggravation', 'adhesion', 'dissociation', 'array', 'submethod'],
},
{
question: 'Which of the following words go together?',
correct: ['private class', 'getter', 'setter', 'protect data'],
incorrect: ['public class', 'char', 'float', 'array', 'settings', 'extends class'],
},
];
class Button{
constructor(x, y, width, height, label, textSize, fillColor){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.label = label;
this.textSize = textSize;
this.fillColor = fillColor;
}
draw(){
push();
textAlign(CENTER);
fill(this.fillColor);
rect(this.x, this.y, this.width, this.height);
stroke(100);
strokeWeight(3);
textSize(this.textSize);
fill(255);
text(this.label, this.x + (this.width * 0.5), this.y + (this.height * 0.75));
pop();
}
isPressed(){
return ((mouseX >= this.x && mouseX <= this.x + this.width) &&
(mouseY >= this.y && mouseY <= this.y + this.height));
}
}
class State{
constructor(){
}
mouseClicked(){}
draw(){}
}
class MainMenuState extends State{
draw(){
background(bubblepopperM);
playButton.draw();
exitButton.draw();
instructionsButton.draw();
image(bubblepopper, 275, 150, 300, 300); //Add the Bubble Popper logo.
}
mouseClicked(){
if(playButton.isPressed()){
currentState = playState;
}
if(instructionsButton.isPressed()){
currentState = instructionsState;
}
if(exitButton.isPressed()){
currentState = exitState;
}
}
}
class PlayState extends State{
draw(){
background(bubblepopperG)
fill(0)
textSize(25)
text(currentQuestion.question, 25, 300);
//Allow the bubbles to move and be displayed on the screen.
bubbles.forEach(bubble => {
bubble.move();
bubble.display();
})
}
mouseClicked(){
//For each bubble in the array, click it and allow it to change to it's correct colour.
bubbles.forEach(bubble => bubble.clicked(mouseX, mouseY));
// check if all correct bubbles have been clicked
const correctBubbles = getCorrectBubbles();
if (countClickedBubbles(correctBubbles) === correctBubbles.length){
currentState = winState;
}
}
}
class WinState extends State{
draw(){
background(bubblepopperG);
fill(255);
textSize(30);
text('YOU GOT ALL THE RIGHT BUBBLES!', 25, height / 2);
//Add button to return to main menu.
playAgainButton.draw();
}
mouseClicked(){
if(playAgainButton.isPressed()){
// reset clicked answers first
bubbles.forEach(bubble => bubble.reset());
// then change state
currentState = menuState;
}
}
}
class InstructionsState extends State{
draw(){
background(bubblepopperM)
fill(255);
stroke(100);
strokeWeight(3);
textSize(20);
text('1. A question will be displayed to do with object-oriented', 50, 150);
text('programming (OOP) concepts.', 80, 175);
text('2. Click on the bubbles with the correct word associations', 50, 225);
text('to the question. Correct answers will turn green,', 80, 250);
text(' incorrect answers will turn red when clicked on.', 80, 275);
text('3. The round is over when you select all the correct bubbles', 50, 325);
returnToMenuButton.draw();
}
mouseClicked(){
if(returnToMenuButton.isPressed()){
currentState = menuState;
}
}
}
class ExitState extends State{
draw(){
background(bubblepopperM);
fill(255);
textSize(50);
text('THANKS FOR PLAYING!', 25, height / 2);
playAgainButton.draw();
}
mouseClicked(){
if(returnToMenuButton.isPressed()){
currentState = menuState;
}
}
}
let playButton;
let exitButton;
let instructionsButton;
let menuState = new MainMenuState();
let playState = new PlayState();
let winState = new WinState();
let instructionsState = new InstructionsState();
let exitState = new ExitState();
let currentState = menuState;
function preload() {
bubblepopper = loadImage('Bubble Popper Logo.png');
bubblepopperM = loadImage('Bubble Popper Menu Background.jpg');
bubblepopperG = loadImage('Bubble Popper Game Background.jpg');
}
function setup() {
currentQuestion = questions[Math.floor(Math.random() * questions.length)];
createCanvas(600, 600);
for(let i = 0; i < currentQuestion.correct.length; i++) {
bubbles.push(new CorrectBubble(random(-3, 3), random(-3, 3), currentQuestion.correct[i], random(width), random(height), random(80,100)));
} //The new bubbles will be added to the bubbles array.
for(let i = 0; i < currentQuestion.incorrect.length; i++) {
bubbles.push(new IncorrectBubble(random(-3, 3), random(-3, 3), currentQuestion.incorrect[i], random(width), random(height), random(80,100)));
} //The new bubbles will be added to the bubbles array.
playButton = new Button(50, 100, 200, 75, 'PLAY', 50, color(64,224,208));
exitButton = new Button(50, 400, 200, 75, 'EXIT', 50, color(255, 0, 255));
instructionsButton = new Button(50, 250, 200, 75, 'INSTRUCTIONS', 26, color(64,224,208));
playAgainButton = new Button(180, 400, 250, 75, 'PLAY AGAIN', 26, color(255, 0, 255));
returnToMenuButton = new Button(180, 400, 250, 75, 'RETURN TO MENU', 26, color(255, 0, 255));
}
function draw() {
currentState.draw();
}
function mouseClicked() {
currentState.mouseClicked();
}
function getCorrectBubbles(){
return bubbles.filter(bubble => bubble instanceof CorrectBubble);
}
function countClickedBubbles(bubbles){
return bubbles.filter(bubble => bubble.isClicked).length;
}
当然,Button
类可以驻留在button.js
中,而states.js
中的状态类可以驻留在states.js
中:这将大大减少主草图中的代码。
这篇关于如何添加重新播放按钮(&Q;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!