Почему мой код проверяет оператор if только один раз, а затем останавливается? - PullRequest
0 голосов
/ 04 апреля 2020

В настоящее время я работаю над игрой в обработке, и пока я разделил ее на 3 части. Начальный экран, экран выбора уровня и экран игры. Кажется, что стартовый экран работает нормально, но когда пользователь попадает на экран выбора уровня, он только один раз проверяет оператор if, а затем останавливается. Вот соответствующий код:

int level = 0;
Player myPlayer;
Floor[] level1Floors = new Floor[5];
Selector levelSelector1;
Selector levelSelector2;
Selector levelSelector3;
Selector levelSelector4;
Selector levelSelector5;
Selector levelSelector6;
Selector levelSelector7;
Selector levelSelector8;
Selector levelSelector9;
Selector levelSelector10;


void setup () {
 size(800, 600);
 myPlayer = new Player(width/2, 500, 50, 50, 15, 0, 9, true, false, false, false, false);
 level1Floors[0] = new Floor(0, 525, width);
 level1Floors[1] = new Floor(width, 485, width/2);
 startButton = loadImage("playButton.png");
 startButtonHover = loadImage("playButtonHover.png");
 star = loadImage("Star.png");
 starUnlit = loadImage("StarUnlit.png");
 levelSelector1 = new Selector(1, 110, 210);
 levelSelector2 = new Selector(2, 255, 210);
 levelSelector3 = new Selector(3, 400, 210);
 levelSelector4 = new Selector(4, 545, 210);
 levelSelector5 = new Selector(5, 690, 210);
 levelSelector6 = new Selector(6, 110, 390);
 levelSelector7 = new Selector(7, 255, 390);
 levelSelector8 = new Selector(8, 400, 390);
 levelSelector9 = new Selector(9, 545, 390);
 levelSelector10 = new Selector(10, 690, 390);
}

void draw () {
 if (gamestate == 0) {
   startScreen();
 }
 if (gamestate == 1) {
   println("eh");
   levelSelection();
   levelSelector1.displaySelector();
   levelSelector2.displaySelector();
   levelSelector3.displaySelector();
   levelSelector4.displaySelector();
   levelSelector5.displaySelector();
   levelSelector6.displaySelector();
   levelSelector7.displaySelector();
   levelSelector8.displaySelector();
   levelSelector9.displaySelector();
   levelSelector10.displaySelector();
 }
 if (gamestate == 2) {
   if (level == 1) {
     background(54);
     level1();
   }
 }
}
void collision () {
 int trueY = myPlayer.y + myPlayer.yOffset;
 if (trueY > level1Floors[0].y) {
   myPlayer.y = level1Floors[0].y - myPlayer.yOffset;
   myPlayer.yvel = 0;
   myPlayer.flag = false;
 }else {
   myPlayer.yvel++;
 }
}

void keyPressed () {
 if (key == ' ' && !myPlayer.flag && gamestate == 2) {
   myPlayer.isJump = true;
 }
 if (key == 'a' && myPlayer.left == false && gamestate == 2) {
   myPlayer.left = true;
 }
 if (key == 'd' && myPlayer.right == false && gamestate == 2) {
   myPlayer.right = true;
 }
 if (key == 'g') {
   exit();
 }
}
void keyReleased () {
 if (key == ' ') {
   myPlayer.isJump = false;
 }
 if (key == 'a') {
   myPlayer.left = false;
 }
 if (key == 'd') {
   myPlayer.right = false;
 }
}

class Floor {
 int x1;
 int y;
 int x2;

 Floor (int tempX1, int tempY, int tempX2) {
   x1 = tempX1;
   y = tempY;
   x2 = tempX2;
 }

 void display () {
   strokeWeight(3);
   line(x1, y, x2, y);
 }
}

------------- this code is in a different tab ----------------
PImage star;
PImage starUnlit;
int starSize = 75;

void levelSelection () {
 background(130);
}

class Selector {
 int value;
 int x;
 int y;
 int sizeX;
 int sizeY;
 int radius;
 int fillValue;
 int strokeValue;

 Selector(int tempVal, int tempX, int tempY) {
   value = tempVal;
   x = tempX;
   y = tempY;
   sizeX = 120;
   sizeY = 120;
   radius = 20;
   fillValue = 70;
   strokeValue = 55;
 }

 void displaySelector () {
   fill(fillValue);
   stroke(strokeValue);
   strokeWeight(6);
   rectMode(CENTER);
   rect(x, y, sizeX, sizeY, radius);
   fill(255);
   textSize(40);
   textAlign(CENTER,CENTER);
   text(value, x, (y-20));
   imageMode(CENTER);
   image(starUnlit, (x - 30), (y + 20), starSize, starSize);
   image(starUnlit, x, (y + 30), starSize, starSize);
   image(starUnlit, (x + 30), (y + 20), starSize, starSize);

   if (mouseX > (x - 60) && mouseX < (x + 60) && mouseY > (y - 60) && mouseY < (y + 60)) {
     println("wow ur computer is a potato");
     sizeX = 130;
     sizeY = 130;
     fillValue = 90;
     strokeValue = 75;
   }else {
     println("u succ");
     sizeX = 120;
     sizeY = 120;
     fillValue = 70;
     strokeValue = 55;
   }

   if (mouseX > (x - 60) && mouseX < (x + 60) && mouseY > (y - 60) && mouseY < (y + 60) && mousePressed) {
     gamestate = 2;
     level = value;
   }
 }
}

------------ this is also in a different tab idk if it is relevant though ---------------
PImage startButton;
PImage startButtonHover;
int startButtonx = 400;
int startButtony = 350;

void startScreen () {
 background(130);
 imageMode(CENTER);
 image(startButton, startButtonx, startButtony, 100, 100);
 textAlign(CENTER,CENTER);
 textSize(60);
 text("OBJECTIVE: BREAK OUT", width/2, height/6);

 if (dist(mouseX, mouseY, startButtonx, startButtony) < 43) {
   imageMode(CENTER);
   image(startButtonHover, startButtonx, startButtony, 110, 110);
 }
 if (dist(mouseX, mouseY, startButtonx, startButtony) < 43 && mousePressed) {
   gamestate = 1;
 }
} 

void level1  () {
 background(54);
 myPlayer.display();
 level1Floors[0].display();
 level1Floors[1].display();
 collision();
 myPlayer.jump();
}

class Player {
 int x;
 int y;
 int vSide;
 int hSide;
 int yOffset;
 int speed;
 int yvel;
 int xvel;
 boolean isCollide;
 boolean isJump;
 boolean right;
 boolean left;
 boolean flag;

 Player (int tempX, int tempY, int tempVSide, int tempHSide, int tempSpeed, int tempyvel, int tempxvel, boolean tempIsCollide, boolean tempIsJump, boolean tempRight, boolean tempLeft, boolean tempFlag) {
   x = tempX;
   y = tempY;
   vSide = tempVSide;
   hSide = tempHSide;
   speed = tempSpeed;
   yvel = tempyvel;
   xvel = tempxvel;
   isCollide = tempIsCollide;
   isJump = tempIsJump;
   right = tempRight;
   left = tempLeft;
   flag = tempFlag;
   yOffset = 25;
 }

 void display() {
   fill(0);
   strokeWeight(2);
   stroke(255);
   rectMode(CENTER);
   rect(x, y, hSide, vSide);

   y += yvel;
 }

 void jump () {
   if (isJump) {
     y -= 20;
     flag = true;
   }
   if (left && x >= 25) {
     x -= xvel;
   }
   if (right && x <= (width - 25)) {
     x += xvel;
   }
 }
}

Я знаю, что код довольно дезорганизован, и я планирую исправить проблему позже. Проблема заключается в классе Selector, если я прав, поскольку именно здесь находятся 2 оператора if, которые не продолжают проверять, выполняется ли условие. Буду признателен за любую помощь, спасибо за ваше время.

1 Ответ

0 голосов
/ 07 апреля 2020

Вашу проблему было сложнее диагностировать, чем кажется. Как вы уже догадались, на экране выбора уровня есть проблема. Но проблема также в методе startScreen(), и симптом, который вы видите, «зависание», является следствием этих вещей в связи с реализованной логикой выбора уровня c.

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

Вы можете удивиться, почему я говорю все это. Есть веская причина: я хочу, чтобы вы могли задать свой следующий вопрос таким образом, чтобы люди могли на него ответить. Если бы вы задали вопрос об определенной функциональности c, это было бы достаточно просто, но это отладка. Отладить код без необходимости запуска гораздо сложнее, чем мог бы. Вот почему я рассказал вам о публикации минимального воспроизводимого примера . Если вам нужна помощь с ошибкой, возможность воспроизвести ее - это мощный инструмент для тех, кто хочет помочь. То, что я был единственным, кто ответил, может быть связано с этим недостатком.


Проблема в mousePressed. Если вы прочитаете немного об этом в документации по обработке, вы увидите следующее: «Переменная mousePressed хранит информацию о том, нажата или нет кнопка мыши в данный момент».

Это также означает, что mousePressed будет истинным, пока кнопка мыши нажата. Пользователь может щелкнуть случайное место, удерживая кнопку нажатой, и перетащить мышь к селектору уровня, и он будет регистрироваться в вашем коде, как если бы он щелкнул по этому уровню.

Вот что происходит:

  1. В startScreen() пользователь нажимает на изображение, чтобы начать.
  2. Состояние игры переходит в «выбор уровня» быстрее, чем видит глаз, и становится быстрее, чем палец на мышь может отпустить кнопку.
  3. Селектор уровня, который появляется прямо там, где находится мышь, регистрирует это как щелчок.
  4. Состояние игры изменяется на «2», но уровень, который пользователь выбирает по ошибке еще не доступен Кажется, что игра зависает, потому что она застряла там.

Как вы можете видеть, вы должны найти способ разграничить «удерживание кнопки» и пользователь на самом деле что-то нажимает. На данный момент это всего лишь небольшая ошибка, но по мере того, как вы будете использовать эту программу, она будет становиться все более разочаровывающей.

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

Но давайте пока пойдем простым путем (шаг за шагом) для ясности):

  1. Добавьте эту глобальную переменную:

    boolean leftMouseButtonClicked = false;
    

    Это заменит проблему c mousePressed позже.

  2. Добавьте этот метод в ваш проект:

    void mouseClicked() {
      if (mouseButton == LEFT) {
        leftMouseButtonClicked = true;
      }
    }
    

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

  3. Изменить для этого метод draw():

    void draw () {
      switch (gamestate) {
      case 0:
        startScreen();
        break;
      case 1:
        levelSelection();
        levelSelector1.displaySelector();
        levelSelector2.displaySelector();
        levelSelector3.displaySelector();
        levelSelector4.displaySelector();
        levelSelector5.displaySelector();
        levelSelector6.displaySelector();
        levelSelector7.displaySelector();
        levelSelector8.displaySelector();
        levelSelector9.displaySelector();
        levelSelector10.displaySelector();
        break;
      case 2:
        switch (level) {
        case 1:
          level1();
          break;
        default:
          gamestate = 1;
        }
      }
    
      leftMouseButtonClicked = false;
    }
    

    Это примерно то же самое , с парой важных изменений:

    3.1. Я взял на себя смелость использовать оператор switch вместо нескольких операторов if, которые были раньше. switch легко читается, и дела должны быть взаимоисключающими, чтобы это работало. Вместо этого вы могли бы использовать форму if - else if - else if..., но мне больше нравится switch для удобства чтения.

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

    3.3. Я отключаю leftMouseButtonClicked логическое значение, чтобы оно не оставалось "включенным" все время.

  4. Измените каждое место, где вы написали mousePressed, чтобы вместо него использовать leftMouseButtonClicked.

Это все, что нужно сделать, чтобы исправить ситуацию. Я пытался не оптимизировать ваш код, чтобы он остался вашим (за исключением тех switch, которые я не смог устоять). Ваш код имеет смысл и намного лучше структурирован, чем многие другие. Конечно, это может быть улучшено, но это то, чему вы научитесь, становясь лучше. И я уверен, что у тебя все будет хорошо.

Надеюсь, я все прояснил. Хорошего кодирования и веселья!

...