Bananaware

ListenUp! [código]

Aug 24th, 2014 (edited)
43
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 30.58 KB | None | 0 0
  1. /**
  2.    Para facilitar a organização e o manejo, o código foi dividido em 9 arquivos.
  3.  */
  4.  
  5.  
  6.  
  7.  
  8.  
  9. /**
  10.    ListenUp.pde
  11.  */
  12.  
  13.  
  14. /*
  15.    ListenUp! Um jogo musical.
  16.  
  17.    Trabalho desenvolvido como parte da avaliação da disciplina de Algoritmos I do curso
  18.    de Bacharelado em Sistemas de Informação da Universidade Tecnológica Federal do Paraná,
  19.    campus Curitiba, no primeiro semestre de 2014.
  20.  
  21.    Estudantes: Caroline Alves da Silva
  22.                Jorge Luiz dos Santos Ramos Junior
  23.  
  24.    Orientadora: Sílvia Amélia Bim
  25.  
  26.    Tipo de licença: CC BY-NC-ND
  27.  
  28.    Data: 25/08/2014
  29. */
  30.  
  31.  
  32. import ddf.minim.*;
  33. import ddf.minim.ugens.*;
  34.  
  35.  
  36. // a maioria das declarações de variáveis são feitas no arquivo Vars
  37. // a maioria das declarações de funções são feitas no arquivo AuxFunctions
  38.  
  39.  
  40. // para começar, mostra a tela de loading. as coisas são carregadas no draw (if(frameCount<=1))
  41. void setup()
  42. {
  43.   loadingScreen();
  44. }
  45.  
  46.  
  47.  
  48. void draw()
  49. {
  50.   // se frameCount <= 1, significa que o programa ainda não foi carregado
  51.   if(frameCount <= 1)
  52.   {
  53.     load();
  54.   }
  55.  
  56.   // else, os recursos do programa já foram carregados. desenhar alguma das telas
  57.   else
  58.   {
  59.     switch(tela)
  60.     {
  61.       case DIFF_SELECT: difficultySelect(); break;
  62.       case JOGO_FACIL: easyMode(); break;
  63.       case JOGO_MEDIO: mediumMode(); break;
  64.       case JOGO_DIFICIL: hardMode(); break;
  65.       case END_SCREEN: endScreen(); break;
  66.       default: difficultySelect(); println("erro ao mudar de tela");
  67.     }
  68.   }  
  69. }
  70.  
  71.  
  72.  
  73. void mousePressed()
  74. {
  75.   // verifica qual set de botões deve ser usado de acordo com a tela atual
  76.   if (tela == DIFF_SELECT && loaded) // só permite que os botões sejam clicados após o jogo ser carregado, para evitar acessos à morte
  77.   {
  78.     for (int i = 0; i < diffButtons.length; i++)
  79.     {
  80.       diffButtons[i].action();
  81.     }
  82.   }
  83.  
  84.   else if (tela == JOGO_FACIL || tela == JOGO_MEDIO || tela == JOGO_DIFICIL)
  85.   {
  86.     for (int i = 0; i < barButtons.length; i++)
  87.     {
  88.       barButtons[i].action();
  89.     }
  90.   }
  91.  
  92.   // se o mouse for pressionado durante a tela final, voltar ao começo
  93.   else if (tela == END_SCREEN)
  94.   {
  95.     tela = DIFF_SELECT;
  96.   }
  97. }
  98.  
  99.  
  100.  
  101. void keyPressed()
  102. {
  103.   if (playing) // o programa só deve aceitar respostas se há um jogo em andamento
  104.   {
  105.     if (tela == JOGO_FACIL || tela == JOGO_MEDIO || tela == JOGO_DIFICIL) // redundância para mais segurança (redundante pois se o usuário está jogando, ele deve estar em uma dessas telas)
  106.     {
  107.       if (keyCode == UP)
  108.       {
  109.         enviaResposta(SUBIU);
  110.       }
  111.       else if (keyCode == DOWN)
  112.       {
  113.         enviaResposta(DESCEU);
  114.       }
  115.       else if (keyCode == RIGHT)
  116.       {
  117.         enviaResposta(IGUAL);
  118.       }
  119.     }
  120.   }
  121.  
  122.   else // se as condições forem corretas, também aceita as teclas enter ou espaço como hotkeys para iniciar um jogo
  123.   {
  124.     if (tela == JOGO_FACIL || tela == JOGO_MEDIO || tela == JOGO_DIFICIL)
  125.     {
  126.       if (keyCode == ENTER || keyCode == ' ')
  127.       {
  128.         if (!playing) notas = playSound(N_NOTAS, tempo);
  129.       }
  130.     }
  131.   }
  132.  
  133.   if (tela == END_SCREEN) // se qualquer tecla for apertada durante a tela final, voltar ao começo
  134.   {
  135.     tela = DIFF_SELECT;
  136.   }
  137. }
  138.  
  139.  
  140.  
  141. // para rodar o programa em fullscreen
  142. boolean sketchFullScreen()
  143. {
  144.   return true;
  145. }
  146.  
  147.  
  148.  
  149.  
  150.  
  151. /**
  152.    AuxFunctions.pde
  153.  */
  154.  
  155.  
  156. // apenas a resposta relativa ao intervalo de tempo atual deve ser aceita
  157. void gameCode()
  158. {
  159.   int millisComp = millisInicial + (int)(tempo*1000 * (posResposta+1));  // determina qual resposta deverá ser aceita
  160.   int millisLimite = millisInicial + (int)(tempo*1000 * (posResposta+2));  // tempo limite para a próxima resposta
  161.  
  162.   /* idéias:
  163.        - verificar se já é hora de aceitar a próxima resposta (millis() > millisComp). millisComp é atualizado a cada nota executada
  164.        - nessa hora, definir que o usuário pode fornecer uma resposta, e ainda não respondeu.
  165.        - parece redundante usar duas variáveis que praticamente dizem a mesma coisa, mas não consegui fazer funcionar com só uma...
  166.    */
  167.   if (millis() > millisComp && !podeResponder)
  168.   {
  169.     podeResponder = true;
  170.     jaRespondeu = false;
  171.   }
  172.  
  173.   // se o usuário não responder a tempo, entra nesse if e mostra em vermelho a flecha que ele deveria pressionar
  174.   if (millis() > millisLimite && playing)
  175.   {
  176.     respostaErrada(notas[posResposta+1] - notas[posResposta]);
  177.   }
  178. }
  179.  
  180.  
  181.  
  182. // desenha as flechas, barra inferior e score
  183. void drawPlayingInterface()
  184. {
  185.   drawArrows();
  186.   initBarButtons();
  187.   drawButtonBar();
  188.   drawButtonArray(barButtons);
  189.   drawScore();
  190. }
  191.  
  192.  
  193.  
  194. // calcula para qual tamanho uma imagem qualquer deve ser redimensionada para encaixar na tela e mantém suas proporções
  195. // o redimensionamento é feito para o tamanho da largura ou da altura (definido pelo parâmetro method)
  196. int[] fitToScreen(PImage img, char method)
  197. {
  198.   int[] dimensoes = new int[2];
  199.   float proporcao;
  200.  
  201.   if (method == 'w')
  202.   {
  203.     proporcao = (float)sketchWidth()/img.width;
  204.     dimensoes[0] = sketchWidth();
  205.     dimensoes[1] = (int)(img.height*proporcao);
  206.   }
  207.   else if (method == 'h')
  208.   {
  209.     proporcao = (float)sketchHeight()/img.height;
  210.     dimensoes[0] = (int)(img.width*proporcao);
  211.     dimensoes[1] = sketchHeight();
  212.   }
  213.   else
  214.   {
  215.     println("parâmetro inválido, use 'w' ou 'h'");
  216.     dimensoes[0] = 0;
  217.     dimensoes[1] = 0;
  218.   }
  219.  
  220.   return dimensoes;
  221. }
  222.  
  223.  
  224.  
  225. // método que retorna o tempo relativo a uma dificuldade
  226. float getTempo(int diff)
  227. {
  228.   float tempo = -1;
  229.  
  230.   switch(diff)
  231.   {
  232.     case FACIL: tempo = TEMPO_EASY; break;
  233.     case MEDIO: tempo = TEMPO_MEDIUM; break;
  234.     case DIFICIL: tempo = TEMPO_HARD; break;
  235.     default: println("erro ao retornar tempo");
  236.   }
  237.  
  238.   return tempo;
  239. }
  240.  
  241.  
  242.  
  243.  
  244.  
  245. /**
  246.    DrawingFunctions.pde
  247.  */
  248.  
  249.  
  250. void drawButtonBar()
  251. {
  252.   // calcula a posição Y do topo do retângulo transparente de acordo com o tamanho da janela
  253.   yTopo = sketchHeight() - sketchHeight()/6;
  254.  
  255.   // desenha a linha branca
  256.   stroke(255);
  257.   line(0, yTopo, sketchWidth(), yTopo);
  258.  
  259.   // desenha o retângulo transparente
  260.   noStroke();
  261.   fill(255, 255, 255, 128);
  262.   rect(0, yTopo, sketchWidth(), sketchHeight()-yTopo);
  263.  
  264.   // desenha os botões
  265.   image(playBtnImg, 15*sketchWidth()/32-playBtnImg.width/2, (yTopo+sketchHeight())/2-playBtnImg.height/2);
  266.   image(repeatBtnImg, 17*sketchWidth()/32-repeatBtnImg.width/2, (yTopo+sketchHeight())/2-repeatBtnImg.height/2);
  267.   image(backBtnImg, 13*sketchWidth()/32-repeatBtnImg.width/2, (yTopo+sketchHeight())/2-repeatBtnImg.height/2);
  268.   image(fwdBtnImg, 19*sketchWidth()/32-repeatBtnImg.width/2, (yTopo+sketchHeight())/2-repeatBtnImg.height/2);
  269. }
  270.  
  271.  
  272.  
  273. // desenha as três flechas de acordo com o estado atual do jogo (estado inicial/houve um acerto/houve um erro)
  274. void drawArrows()
  275. {
  276.   if (arrowState == INI) // estado inicial
  277.   {
  278.     image(downArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  279.     image(upArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  280.     image(rightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  281.   }
  282.   else if (arrowState == DOWN_R) // estado quando se acerta um "desceu" (seta para baixo verde, outras em seu estado normal)
  283.   {
  284.     image(greenDownArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  285.     image(upArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  286.     image(rightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  287.   }
  288.   else if (arrowState == UP_R) // estado quando se acerta um "subiu" (seta para cima verde, outras em seu estado normal)
  289.   {
  290.     image(downArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  291.     image(greenUpArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  292.     image(rightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  293.   }
  294.   else if (arrowState == RIGHT_R) // etc...
  295.   {
  296.     image(downArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  297.     image(upArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  298.     image(greenRightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  299.   }
  300.   else if (arrowState == DOWN_W)
  301.   {
  302.     image(redDownArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  303.     image(upArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  304.     image(rightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  305.   }
  306.   else if (arrowState == UP_W)
  307.   {
  308.     image(downArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  309.     image(redUpArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  310.     image(rightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  311.   }
  312.   else if (arrowState == RIGHT_W)
  313.   {
  314.     image(downArrowImg, sketchWidth()/4-downArrowImg.width/2, sketchHeight()/6);
  315.     image(upArrowImg, sketchWidth()/2-upArrowImg.width/2, sketchHeight()/6);
  316.     image(redRightArrowImg, sketchWidth()/2+sketchWidth()/4-rightArrowImg.width/2, sketchHeight()/6+rightArrowImg.height/2);
  317.   }
  318.   else
  319.   {
  320.     println("algo deu errado ao determinar o estado das flechas: " + arrowState);
  321.   }
  322. }
  323.  
  324.  
  325.  
  326. void drawScore()
  327. {
  328.   // calcula o tamanho e posição dos componentes de score
  329.   int rectWidth = (int)(sketchWidth()*0.13);
  330.   int rectHeight = (int)(sketchHeight()*0.12);
  331.   int rectXPos = sketchWidth() - rectWidth;
  332.   int rectYPos = sketchHeight()/22;
  333.  
  334.  
  335.   // desenha o retângulo verde
  336.   fill(goodColor);  
  337.   rect(rectXPos, rectYPos, rectWidth, rectHeight);
  338.  
  339.   // desenha o círculo branco (podemos usar os tamanhos que descobrimos para o rect, já que eles possuem relação entre si)
  340.   fill(whiteColor);
  341.   ellipse(sketchWidth()-rectWidth, sketchHeight()/22+rectHeight/2, rectHeight, rectHeight);
  342.  
  343.   // desenha o texto de score
  344.   textAlign(CENTER, CENTER);
  345.   textSize(rectHeight/3);
  346.   text(score, rectXPos + 3*rectWidth/5, rectYPos+rectHeight/2);
  347.  
  348.   // desenha texto de +10 ou -5 com a cor apropriada
  349.   if (arrowState > INI) // método interessante de verificar se a última resposta enviada pelo usuário foi correta
  350.   {
  351.     fill(goodColor);
  352.     text("+10", sketchWidth()-rectWidth, sketchHeight()/22+rectHeight/2);
  353.   }
  354.   else if (arrowState < INI)
  355.   {
  356.     fill(badColor);
  357.     text("-5", sketchWidth()-rectWidth, sketchHeight()/22+rectHeight/2);
  358.   }
  359. }
  360.  
  361.  
  362.  
  363.  
  364.  
  365. /**
  366.    LoadingFunctions.pde
  367.  */
  368.  
  369.  
  370.  
  371. void loadingScreen()
  372. {
  373.   background(255,204,42);
  374.   loadingImg = loadImage("img_abertura.png");
  375.  
  376.   // fator de redimensionamento da imagem
  377.   final float FATOR = 0.8;
  378.  
  379.   // calcula a proporção em que a imagem de carregamento deve ser redimensionada
  380.   int[] dimensoes = fitToScreen(loadingImg, 'h');
  381.  
  382.   // centraliza a imagem e redimensiona de acordo com o fator
  383.   loadingImg.resize((int)(dimensoes[0]*FATOR), (int)(dimensoes[1]*FATOR));
  384.   image(loadingImg, width/2-loadingImg.width/2, height/2-loadingImg.height/2); // centraliza
  385. }
  386.  
  387.  
  388.  
  389. // inicializa e carrega os objetos
  390. void load()
  391. {
  392.   // inicializa os objetos de áudio
  393.   minim = new Minim(this);
  394.   out = minim.getLineOut();
  395.  
  396.   // prepara as imagens
  397.   loadDifficultyImgs();
  398.   loadArrows();
  399.   loadBarImgs();
  400.   loadEasyImgs();
  401.   loadMediumImgs();
  402.   loadHardImgs();
  403.   loadEndImgs();
  404. }
  405.  
  406.  
  407.  
  408. /* abaixo, apenas funções que preparam imagens (carregam e redimensionam de acordo com as dimensões da tela) */
  409.  
  410. void loadDifficultyImgs()
  411. {
  412.   diffBgImg = loadImage("bg_menu.jpg");
  413.   galeraImg = loadImage("img_galera.png");
  414.   etiquetaImg = loadImage("img_etiqueta.png");
  415.   facilImg = loadImage("dif_facil.png");
  416.   medioImg = loadImage("dif_medio.png");
  417.   dificilImg = loadImage("dif_dificil.png");
  418.  
  419.   // calcula um fator de redimensionamento para a etiqueta e as imagens de dificuldade
  420.   // isso é necessário para que a interface seja apresentável em qualquer tamanho de tela
  421.   final float FATOR_ETIQUETA = sketchWidth()*0.12/etiquetaImg.width;
  422.   final float FATOR_DIFF = sketchHeight()*0.12/facilImg.height;
  423.  
  424.   // redimensiona o background para o tamanho da tela
  425.   diffBgImg.resize(sketchWidth(), sketchHeight());
  426.  
  427.   // redimensiona a galera proporcionalmente à largura da tela
  428.   int[] dimensoesGalera = fitToScreen(galeraImg, 'w');
  429.   galeraImg.resize(dimensoesGalera[0], dimensoesGalera[1]);
  430.  
  431.   // redimensiona as imagens de acordo com o fator calculado
  432.   etiquetaImg.resize((int)(etiquetaImg.width*FATOR_ETIQUETA), (int)(etiquetaImg.height*FATOR_ETIQUETA));
  433.   facilImg.resize((int)(facilImg.width*FATOR_DIFF), (int)(facilImg.height*FATOR_DIFF));
  434.   medioImg.resize((int)(medioImg.width*FATOR_DIFF), (int)(medioImg.height*FATOR_DIFF));
  435.   dificilImg.resize((int)(dificilImg.width*FATOR_DIFF), (int)(dificilImg.height*FATOR_DIFF));
  436. }
  437.  
  438.  
  439.  
  440. // as funções abaixo funcionam de forma similar
  441. void loadBarImgs()
  442. {
  443.   playBtnImg = loadImage("btn_tocar.png");
  444.   repeatBtnImg = loadImage("btn_repetir.png");
  445.   backBtnImg = loadImage("btn_back.png");
  446.   fwdBtnImg = loadImage("btn_fwd.png");
  447.  
  448.   float FATOR_BTN = sketchHeight()*0.09/playBtnImg.height;
  449.  
  450.   playBtnImg.resize((int)(playBtnImg.width*FATOR_BTN), (int)(playBtnImg.height*FATOR_BTN));
  451.   repeatBtnImg.resize((int)(repeatBtnImg.width*FATOR_BTN), (int)(repeatBtnImg.height*FATOR_BTN));
  452.   backBtnImg.resize((int)(backBtnImg.width*FATOR_BTN), (int)(backBtnImg.height*FATOR_BTN));
  453.   fwdBtnImg.resize((int)(fwdBtnImg.width*FATOR_BTN), (int)(fwdBtnImg.height*FATOR_BTN));
  454. }
  455.  
  456.  
  457.  
  458. void loadArrows()
  459. {
  460.   upArrowImg = loadImage("seta_sobe.png");
  461.   downArrowImg = loadImage("seta_desce.png");
  462.   rightArrowImg = loadImage("seta_mesmolugar.png");
  463.   greenUpArrowImg = loadImage("seta_sobe_verde.png");
  464.   greenDownArrowImg = loadImage("seta_desce_verde.png");
  465.   greenRightArrowImg = loadImage("seta_mesmolugar_verde.png");
  466.   redUpArrowImg = loadImage("seta_sobe_vermelho.png");
  467.   redDownArrowImg = loadImage("seta_desce_vermelho.png");
  468.   redRightArrowImg = loadImage("seta_mesmolugar_vermelho.png");
  469.  
  470.   float FATOR_SETA = sketchHeight()*0.44/upArrowImg.height;
  471.  
  472.   upArrowImg.resize((int)(upArrowImg.width*FATOR_SETA), (int)(upArrowImg.height*FATOR_SETA));
  473.   greenUpArrowImg.resize((int)(greenUpArrowImg.width*FATOR_SETA), (int)(greenUpArrowImg.height*FATOR_SETA));
  474.   redUpArrowImg.resize((int)(redUpArrowImg.width*FATOR_SETA), (int)(redUpArrowImg.height*FATOR_SETA));
  475.   downArrowImg.resize((int)(downArrowImg.width*FATOR_SETA), (int)(downArrowImg.height*FATOR_SETA));
  476.   greenDownArrowImg.resize((int)(greenDownArrowImg.width*FATOR_SETA), (int)(greenDownArrowImg.height*FATOR_SETA));
  477.   redDownArrowImg.resize((int)(redDownArrowImg.width*FATOR_SETA), (int)(redDownArrowImg.height*FATOR_SETA));
  478.   rightArrowImg.resize((int)(rightArrowImg.width*FATOR_SETA), (int)(rightArrowImg.height*FATOR_SETA));
  479.   greenRightArrowImg.resize((int)(greenRightArrowImg.width*FATOR_SETA), (int)(greenRightArrowImg.height*FATOR_SETA));  
  480.   redRightArrowImg.resize((int)(redRightArrowImg.width*FATOR_SETA), (int)(redRightArrowImg.height*FATOR_SETA));
  481. }
  482.  
  483.  
  484.  
  485. void loadEasyImgs()
  486. {
  487.   easyBgImg = loadImage("bg_easy.png");
  488.   guitarImg = loadImage("img_guitar.png");
  489.   vocalImg = loadImage("img_vocal.png");
  490.  
  491.   final float FATOR_PESSOAS = sketchHeight()*0.85/guitarImg.height;
  492.  
  493.   easyBgImg.resize(sketchWidth(), sketchHeight());
  494.  
  495.   guitarImg.resize((int)(guitarImg.width*FATOR_PESSOAS), (int)(guitarImg.height*FATOR_PESSOAS));
  496.   vocalImg.resize((int)(vocalImg.width*FATOR_PESSOAS), (int)(vocalImg.height*FATOR_PESSOAS));
  497. }
  498.  
  499.  
  500.  
  501. void loadMediumImgs()
  502. {
  503.   mediumBgImg = loadImage("bg_medium.png");
  504.   bateraImg = loadImage("img_batera.png");
  505.  
  506.   final float FATOR_BATERA = sketchHeight()*0.82/bateraImg.height;
  507.  
  508.   mediumBgImg.resize(sketchWidth(), sketchHeight());
  509.  
  510.   bateraImg.resize((int)(bateraImg.width*FATOR_BATERA), (int)(bateraImg.height*FATOR_BATERA));
  511. }
  512.  
  513.  
  514.  
  515. void loadHardImgs()
  516. {
  517.   hardBgImg = loadImage("bg_hard.png");
  518.   violinImg = loadImage("img_violino.png");
  519.   violaoImg = loadImage("img_violao.png");
  520.  
  521.   final float FATOR_VIOLIN = sketchHeight()*0.82/violinImg.height;
  522.   final float FATOR_VIOLAO = sketchHeight()*0.66/violaoImg.height;
  523.  
  524.   hardBgImg.resize(sketchWidth(), sketchHeight());
  525.  
  526.   violinImg.resize((int)(violinImg.width*FATOR_VIOLIN), (int)(violinImg.height*FATOR_VIOLIN));
  527.   violaoImg.resize((int)(violaoImg.width*FATOR_VIOLAO), (int)(violaoImg.height*FATOR_VIOLAO));
  528. }
  529.  
  530.  
  531.  
  532. void loadEndImgs()
  533. {
  534.   endBgImg = loadImage("bg_end.jpg");
  535.   txtPontuacaoImg = loadImage("img_pontuacao.png");
  536.  
  537.   final float FATOR_TEXTO = sketchWidth()*0.8/txtPontuacaoImg.width;
  538.  
  539.   endBgImg.resize(sketchWidth(), sketchHeight());
  540.   txtPontuacaoImg.resize((int)(txtPontuacaoImg.width*FATOR_TEXTO), (int)(txtPontuacaoImg.height*FATOR_TEXTO));
  541. }
  542.  
  543.  
  544.  
  545.  
  546.  
  547. /**
  548.    PlayScreens.pde
  549.  */
  550.  
  551.  
  552. void difficultySelect()
  553. {
  554.   image(diffBgImg, 0, 0);
  555.   image(galeraImg, 0, sketchHeight()-galeraImg.height);
  556.   image(etiquetaImg, sketchWidth()/2-etiquetaImg.width/2, 0); // centralizando a etiqueta
  557.  
  558.   image(facilImg, sketchWidth()/2-facilImg.width/2, 3*sketchHeight()/13-facilImg.height/2);
  559.   image(medioImg, sketchWidth()/2-medioImg.width/2, 5*sketchHeight()/13-medioImg.height/2);
  560.   image(dificilImg, sketchWidth()/2-dificilImg.width/2, 7*sketchHeight()/13-dificilImg.height/2);
  561.  
  562.   // inicializa os botões de dificuldade (para que seja possível clicar neles)
  563.   initDiffButtons();
  564.   drawButtonArray(diffButtons);
  565.   loaded = true;
  566. }
  567.  
  568.  
  569.  
  570. void easyMode()
  571. {
  572.   image(easyBgImg, 0, 0); // desenha a imagem de fundo relativa à dificuldade
  573.   image(guitarImg, sketchWidth()/30, sketchHeight()-guitarImg.height-sketchHeight()/64); // e os "bonecos" respectivos
  574.   image(vocalImg, (int)(sketchWidth()*0.64), sketchHeight()-vocalImg.height-sketchHeight()/128);
  575.  
  576.   tempo = getTempo(dificuldade); // inicializa a velocidade das notas relativa à dificuldade
  577.  
  578.   drawPlayingInterface(); // desenha os componentes de jogo (setas, barra inferior, score)
  579.   gameCode(); // código que faz o jogo funcionar
  580. }
  581.  
  582.  
  583.  
  584. // mediumMode() e hardMode() funcionam de maneira praticamente idêntica ao easyMode()
  585. void mediumMode()
  586. {
  587.   image(mediumBgImg, 0, 0);
  588.   image(bateraImg, sketchWidth()/25, sketchHeight()-bateraImg.height-sketchHeight()/64);
  589.  
  590.   tempo = getTempo(dificuldade);
  591.  
  592.   drawPlayingInterface();
  593.   gameCode();
  594. }
  595.  
  596.  
  597.  
  598. void hardMode()
  599. {
  600.   image(hardBgImg, 0, 0);
  601.   image(violinImg, (int)(sketchWidth()*0.18), (int)(sketchHeight()*0.16));
  602.   image(violaoImg, 6*sketchWidth()/10, sketchHeight()/3);
  603.  
  604.   tempo = getTempo(dificuldade);
  605.  
  606.   drawPlayingInterface();
  607.   gameCode();
  608. }
  609.  
  610.  
  611.  
  612. // tela final
  613. void endScreen()
  614. {
  615.   image(endBgImg, 0, 0);
  616.   image(txtPontuacaoImg, sketchWidth()/2-txtPontuacaoImg.width/2, 2*sketchHeight()/7);
  617.  
  618.   // desenha o círculo verde com o score dentro
  619.   fill(goodColor);
  620.   ellipse(sketchWidth()/2, 5*sketchHeight()/7, sketchHeight()/3, sketchHeight()/3);
  621.   fill(whiteColor);
  622.   textAlign(CENTER, CENTER);
  623.   textSize(sketchHeight()/7);
  624.   text(score, sketchWidth()/2, 5*sketchHeight()/7);  
  625. }
  626.  
  627.  
  628.  
  629.  
  630.  
  631. /**
  632.    RectButtons.pde
  633.  */
  634.  
  635.  
  636. class RectButton
  637. {
  638.   // variáveis de cada botão
  639.   int x, y, w, h, id;
  640.   color c;
  641.  
  642.   // construtor
  643.   public RectButton(int x, int y, int w, int h, color c, int id)
  644.   {
  645.     this.x = x;
  646.     this.y = y;
  647.     this.w = w;
  648.     this.h = h;
  649.     this.c = c;
  650.     this.id = id;
  651.   }
  652.  
  653.   // método que verifica se o mouse está em cima do botão (e, portanto, o botão é clicável)
  654.   boolean mouseOver()
  655.   {
  656.     if (mouseX >= x && mouseX <= x+w && mouseY >= y && mouseY <= y+h)
  657.     {
  658.       return true;
  659.     }
  660.     else
  661.     {
  662.       return false;
  663.     }
  664.   }
  665.  
  666.   // este método, que torna o botão visível, só é executado caso a variável de debug BUTTON_HITBOXES = true
  667.   void drawArea()
  668.   {
  669.     noStroke();
  670.     fill(c);
  671.     rect(x, y, w, h);
  672.   }
  673.  
  674.   // executa ações ao se clicar em um botão
  675.   void action()
  676.   {
  677.     boolean clickable = mouseOver();
  678.     if (clickable) // se algum botão é clicável
  679.     {
  680.       switch(id) // verifica qual foi e executa a ação correspondente
  681.       {
  682.         case FACIL: score = 0; arrowState = INI; dificuldade = FACIL; tela = JOGO_FACIL; break;
  683.         case MEDIO: score = 0; arrowState = INI; dificuldade = MEDIO; tela = JOGO_MEDIO; break;
  684.         case DIFICIL: score = 0; arrowState = INI; dificuldade = DIFICIL; tela = JOGO_DIFICIL; break;
  685.        
  686.         case PLAY: if (!playing) notas = playSound(N_NOTAS, tempo); break;
  687.         case REPLAY: if (!playing) replaySound(notas, tempo); break;
  688.         case BACK: if (!playing) tela = DIFF_SELECT; break;
  689.         case FORWARD: if (!playing) tela = END_SCREEN; break;
  690.       }
  691.     }
  692.   }
  693. }
  694.  
  695.  
  696.  
  697. // inicializa os botões de dificuldade (fácil, médio, difícil)
  698. void initDiffButtons()
  699. {
  700.   diffButtons = new RectButton[3];
  701.  
  702.   int diffButtonHeight = sketchHeight()/9;
  703.   int diffButtonWidth = (int)(2.7*diffButtonHeight);
  704.  
  705.   diffButtons[0] = new RectButton(sketchWidth()/2-diffButtonWidth/2, 3*sketchHeight()/13-diffButtonHeight/2, diffButtonWidth, diffButtonHeight, buttonHitboxColor, FACIL);
  706.   diffButtons[1] = new RectButton(sketchWidth()/2-diffButtonWidth/2, 5*sketchHeight()/13-diffButtonHeight/2, diffButtonWidth, diffButtonHeight, buttonHitboxColor, MEDIO);
  707.   diffButtons[2] = new RectButton(sketchWidth()/2-diffButtonWidth/2, 7*sketchHeight()/13-diffButtonHeight/2, diffButtonWidth, diffButtonHeight, buttonHitboxColor, DIFICIL);
  708. }
  709.  
  710.  
  711.  
  712. // inicializa os botões da barra inferior (back, play, repeat, forward)
  713. void initBarButtons()
  714. {
  715.   barButtons = new RectButton[4];
  716.  
  717.   int barButtonHeight = sketchHeight()/10;
  718.   int barButtonWidth = (int)(1.05*barButtonHeight);
  719.  
  720.   barButtons[0] = new RectButton(15*sketchWidth()/32-barButtonWidth/2, (yTopo+sketchHeight())/2-barButtonHeight/2, barButtonWidth, barButtonHeight, buttonHitboxColor, PLAY);
  721.   barButtons[1] = new RectButton(17*sketchWidth()/32-barButtonWidth/2, (yTopo+sketchHeight())/2-barButtonHeight/2, barButtonWidth, barButtonHeight, buttonHitboxColor, REPLAY);
  722.   barButtons[2] = new RectButton(13*sketchWidth()/32-barButtonWidth/2, (yTopo+sketchHeight())/2-barButtonHeight/2, barButtonWidth, barButtonHeight, buttonHitboxColor, BACK);
  723.   barButtons[3] = new RectButton(19*sketchWidth()/32-barButtonWidth/2, (yTopo+sketchHeight())/2-barButtonHeight/2, barButtonWidth, barButtonHeight, buttonHitboxColor, FORWARD);
  724. }
  725.  
  726.  
  727.  
  728. // desenha as áreas dos botões, caso a variável de debug BUTTON_HITBOXES = true
  729. void drawButtonArray(RectButton[] btns)
  730. {
  731.   if (BUTTON_HITBOXES)
  732.   {
  733.     for(int i = 0; i < btns.length; i++)
  734.     {
  735.       btns[i].drawArea();
  736.     }
  737.   }
  738. }
  739.  
  740.  
  741.  
  742.  
  743.  
  744. /**
  745.    RespostaFunctions.pde
  746.  */
  747.  
  748.  
  749. // método que processa a resposta enviada pelo usuário ao pressionar uma das teclas (up, down, right)
  750. void enviaResposta(int r)
  751. {
  752.   if (podeResponder) // se o usuário ainda não enviou uma resposta para a posição atual
  753.   {
  754.     int correta = notas[posResposta+1] - notas[posResposta]; // calcula qual a resposta correta
  755.    
  756.     if (correta == -1)
  757.     {
  758.       if (r == DESCEU)
  759.       {
  760.         respostaCerta(INI+r);
  761.       }
  762.       else
  763.       {
  764.         respostaErrada(INI-r);
  765.       }
  766.     }
  767.     else if (correta == 1)
  768.     {
  769.       if (r == SUBIU)
  770.       {
  771.         respostaCerta(INI+r);
  772.       }
  773.       else
  774.       {
  775.         respostaErrada(INI-r);
  776.       }
  777.     }
  778.     else if (correta == 0)
  779.     {
  780.       if (r == IGUAL)
  781.       {
  782.         respostaCerta(INI+r);
  783.       }
  784.       else
  785.       {
  786.         respostaErrada(INI-r);
  787.       }
  788.     }
  789.    
  790.     // não pode mais enviar uma resposta para esta posição
  791.     jaRespondeu = true;
  792.     podeResponder = false;
  793.   }
  794. }
  795.  
  796.  
  797.  
  798. // ações a executar quando o usuário acerta uma resposta
  799. void respostaCerta(int res)
  800. {
  801.   arrowState = res; // colore de verde a seta correspondente à resposta certa
  802.   score += 10; // aumenta o score
  803.   posResposta++; // incrementar a posição da próxima resposta
  804.   verificaPos();
  805. }
  806.  
  807.  
  808.  
  809. // ações a executar quando o usuário erra uma resposta (parecido com o método anterior)
  810. void respostaErrada(int res)
  811. {
  812.   // se entrou nesse switch-case, é porque o usuário não respondeu a tempo. colorir de vermelho a seta que seria a resposta correta
  813.   switch(res)
  814.   {
  815.     case -1: res = DOWN_W; break;
  816.     case +1: res = UP_W; break;
  817.     case +0: res = RIGHT_W; break;
  818.   }
  819.  
  820.   arrowState = res;
  821.   score -= 5;
  822.   posResposta++;
  823.   verificaPos();
  824. }
  825.  
  826.  
  827.  
  828. void verificaPos() // método que tenta evitar acessos à morte, que travam o programa :(
  829. {
  830.   if (posResposta >= notas.length-1)
  831.   {
  832.     posResposta = 0;
  833.     playing = false;
  834.   }
  835. }
  836.  
  837.  
  838.  
  839.  
  840.  
  841. /**
  842.    SoundFunctions.pde
  843.  */
  844.  
  845.  
  846. // sorteia uma sequência de n notas e executa
  847. int[] playSound(int n, float tempo)
  848. {
  849.   out.pauseNotes();
  850.  
  851.   int[] notas = new int[n];
  852.  
  853.   // inicializa a primeira posição
  854.   notas[0] = int(random(0, freqs.length));
  855.  
  856.   out.playNote(0.0, tempo-0.1, freqs[notas[0]]);
  857.  
  858.   for(int i = 1; i < n; i++)
  859.   {
  860.       // caso especial de frequência mais baixa (não pode sortear uma nota mais baixa)
  861.       if (notas[i-1] == 0)
  862.       {
  863.         notas[i] = notas[i-1] + int(random(2));
  864.       }
  865.       // caso especial de frequência mais alta (não pode sortear uma nota mais alta)
  866.       else if (notas[i-1] == freqs.length-1)
  867.       {
  868.         notas[i] = notas[i-1] + int(random(2))-1;
  869.       }
  870.       // caso padrão (sorteia frequência -1, +1 ou igual)
  871.       else
  872.       {
  873.         notas[i] = notas[i-1] + int(random(3))-1;
  874.       }
  875.      
  876.       out.playNote(tempo*i, tempo-0.1, freqs[notas[i]]);
  877.   }
  878.  
  879.   playing = true;
  880.   score = SCORE_INICIAL; // reseta o score
  881.   millisInicial = millis(); // armazena o momento em que começou a tocar as notas, para poder conferir se as respostas foram fornecidas a tempo
  882.   out.resumeNotes(); // executa as notas
  883.  
  884.   return notas;
  885. }
  886.  
  887.  
  888.  
  889. void replaySound(int[] notas, float tempo) // repete a sequência sorteada anteriormente
  890. {
  891.   out.pauseNotes();
  892.  
  893.   for (int i = 0; i < notas.length; i++)
  894.   {
  895.     out.playNote(tempo*i, tempo-0.1, freqs[notas[i]]);
  896.   }
  897.  
  898.   playing = true;
  899.   score = SCORE_INICIAL;
  900.   millisInicial = millis();
  901.   out.resumeNotes();
  902. }
  903.  
  904.  
  905.  
  906.  
  907.  
  908. /**
  909.    Vars.pde
  910.  */
  911.  
  912.  
  913. /* declarações das variáveis */
  914.  
  915.  
  916.  
  917. // tempo entre notas para cada dificuldade
  918. static final float TEMPO_EASY = 2;
  919. static final float TEMPO_MEDIUM = 1.2;
  920. static final float TEMPO_HARD = 0.6;
  921.  
  922.  
  923.  
  924. // variáveis do programa
  925. static final int N_NOTAS = 15;              // número de notas a ser executada em um jogo
  926. static final int SCORE_INICIAL = 5*N_NOTAS; // score base ao iniciar um jogo. esse valor não permite que o usuário termine com score negativo, já que um erro custa 5 pontos
  927. int tela = DIFF_SELECT;                     // tela a ser mostrada para o usuário
  928. int dificuldade = -1;                       // dificuldade (fácil, médio ou difícil)
  929. float tempo = -1;                           // tempo relacionado à dificuldade
  930. int millisInicial = MAX_INT;                // variável que armazena o momento em que o usuário começou a responder uma sequência, usada para verificar se ele está respondendo a tempo
  931. int arrowState = INI;                       // determina quais cores as flechas devem ter
  932. int score = 0;                              // score do usuário
  933. boolean loaded = false;                     // determina quando o programa deve começar a aceitar cliques do usuário
  934. boolean podeResponder = false;              // determina se o usuário pode ou não enviar uma resposta
  935. boolean jaRespondeu = false;                // determina se o usuário já enviou uma resposta para a nota atual
  936. boolean playing = false;                    // determina se o usuário está jogando no momento
  937. int posResposta = 0;                        // posição atual sendo respondida (por exemplo, se 0, o usuário deve enviar a resposta relativa às posições 0 e 1)
  938. color goodColor = color(180, 214, 96);      // cor relativa às coisas corretas
  939. color badColor = color(240, 80, 80);        // cor relativa às coisas erradas
  940. color whiteColor = color(248, 248, 255);    // branco legal
  941. int yTopo;                                  // posição Y do topo da barra
  942. int[] notas;                                // vetor com as notas que são executadas em uma sequência
  943.  
  944.  
  945.  
  946. // vetores de botões
  947. RectButton[] barButtons;
  948. RectButton[] diffButtons;
  949.  
  950.  
  951.  
  952. // variáveis para testes das hitboxes dos botões
  953. static final boolean BUTTON_HITBOXES = false; // mostra ou não as hitboxes
  954. color buttonHitboxColor = color(192, 0, 192, 128);
  955.  
  956.  
  957.  
  958. // frequências de notas que podem ser executadas
  959. String[] freqs = {"A4", "B4", "C#5", "D5", "E5", "F#5", "G#5", "A5", "B5", "C#6", "E6"};
  960.  
  961.  
  962.  
  963. // objetos minim
  964. Minim minim;
  965. AudioOutput out;
  966.  
  967.  
  968.  
  969. // variáveis relacionadas à interface
  970. PImage bg, loadingImg;
  971.  
  972.  
  973.  
  974. // imagens
  975. PImage diffBgImg, galeraImg, etiquetaImg, facilImg, medioImg, dificilImg; // tela de escolher dificuldade
  976. PImage upArrowImg, downArrowImg, rightArrowImg, greenUpArrowImg, greenDownArrowImg, greenRightArrowImg, redUpArrowImg, redDownArrowImg, redRightArrowImg; // setas de resposta
  977. PImage playBtnImg, repeatBtnImg, backBtnImg, fwdBtnImg; // botões da barra inferior
  978. PImage easyBgImg, guitarImg, vocalImg; // imagens do easy mode
  979. PImage mediumBgImg, bateraImg; // imagens do medium mode
  980. PImage hardBgImg, violinImg, violaoImg; // imagens do hard mode
  981. PImage endBgImg, txtPontuacaoImg; // imagens da tela final, onde o score é mostrado
  982.  
  983.  
  984.  
  985. /* abaixo grupos de constantes */
  986.  
  987. // tela em que o usuário está
  988. static final int DIFF_SELECT = 100;
  989. static final int JOGO_FACIL = 101;
  990. static final int JOGO_MEDIO = 102;
  991. static final int JOGO_DIFICIL = 103;
  992. static final int END_SCREEN = 104;
  993.  
  994. // dificuldades
  995. static final int FACIL = 200;
  996. static final int MEDIO = 201;
  997. static final int DIFICIL = 202;
  998.  
  999. // botões da barra inferior
  1000. static final int PLAY = 300;
  1001. static final int REPLAY = 301;
  1002. static final int BACK = 302;
  1003. static final int FORWARD = 303;
  1004.  
  1005. // constantes relacionadas às respostas
  1006. static final int DESCEU = 1000;
  1007. static final int SUBIU = 2000;
  1008. static final int IGUAL = 3000;
  1009.  
  1010. // constantes relativas ao estado das flechas
  1011. static final int INI = 10000;
  1012. static final int DOWN_R = INI+DESCEU;
  1013. static final int UP_R = INI+SUBIU;
  1014. static final int RIGHT_R = INI+IGUAL;
  1015. static final int DOWN_W = INI-DESCEU;
  1016. static final int UP_W = INI-SUBIU;
  1017. static final int RIGHT_W = INI-IGUAL;
  1018.  
  1019.  
  1020.  
  1021. // isso existe no lugar do size() e define o tamanho da janela como o tamanho da tela do usuário
  1022. public int sketchWidth()  { return displayWidth; }
  1023. public int sketchHeight() { return displayHeight; }
Add Comment
Please, Sign In to add comment