Avançar para a área de conteúdo

ir para o conteúdo principal

developerWorks Brasil  >  Software livre  >

Construindo um Jogo de Laser Baseado em Arduino, Parte 3: Transmita e Acerte

Inicie rapidamente seus projetos eletroeletrônicos com a plataforma de hardware e software livre Arduino

developerWorks
Ir para a página anteriorPágina 4 de 10 Ir para a próxima página

Opções de documento

Código de amostra


Classificar este tutorial

Ajude-nos a melhorar este conteúdo


Escrevendo o Código de Disparo

O código para disparar a arma é dividido em algumas funções diferentes:

  • senseFire — Verifica o botão para ver se foi pressionado.
  • fireShot — Dispara o tiro quando um pressionamento de botão é detectado.
  • oscillationWrite — Usado para tratar da oscilação real do disparo.
  • selfDestruct — Para tratar da auto-destruição quando uma arma tiver feito muitos disparos.

A Função senseFire

Para sentir e tratar corretamente de um pressionamento de botão, é necessário verificar diversas coisas: o estado do pino, a variável que revela se esse pressionamento de botão já foi tratado, se o jogador ainda está vivo e o número de disparos feitos pelo jogador. Se o jogador ainda estiver vivo e o número de disparos for maior do que seis, é necessário verificar se esse tiro é o que quebra a arma e elimina o jogador. Nesse caso, vamos supor que o número máximo absoluto de disparos que uma arma possa fazer seja 20. Escolha um número aleatório entre um e 20 e, se esse número for menor ou igual ao número de disparos, a arma é auto-destruída. (Você irá colocar a auto-destruição real em uma função que será escrita posteriormente.) A função senseFire tem a aparência da Listagem 7.


Listagem 7. Função senseFire

void senseFire() {
  trigger = digitalRead(triggerPin);
  if (trigger == LOW && fired == false) {
    Serial.println("Button Pressed");
    fired = true;
    myShots++;
    if (myHits <= maxHits && myShots > maxShots && random(1,20)
<= myShots) {
      Serial.println("SELF DESTRUCT");
      selfDestruct();
    } else if (myHits <= maxHits) {
      Serial.print("Firing Shot : ");
      Serial.println(myShots);
      fireShot(myCode, myLevel);
    }

  } else if (trigger == HIGH) {
    if (fired == true) {
      Serial.println("Button Released");
    }
    // reconfigure a variável acionada
    fired = false;
    Serial.println("Button Released");
  }
}

Um problema um tanto quanto mais complicado é onde essa função é chamada. Você não pode simplesmente emiti-la na função loop como está escrita ou ela somente perceberá um pressionamento de botão toda vez que um disparo recebido for reconhecido. Você poderia emitir a função no loop while na função senseIR , mas isso serve para obscurecer as coisas um pouco. Vamos alterar esse loop while para uma instrução if e retornar da função se você não estiver recebendo um sinal. Você também precisa fazer uma leve modificação na leitura de pulseIn , incluindo um valor de tempo limite (caso contrário, pulseIn aguardará um segundo inteiro entre as leituras).


Listagem 8. Modificando a Leitura de pulseIn

...
if (pulseIn(sensorPin, LOW, 500) < startBit) {
  digitalWrite(blinkPin, LOW);
  ret[0] = -1;
  return;
}
...

Você pode incluir a chamada da função senseFire na função loop .


Listagem 9. Chamada da Função senseFire para a Função loop

void loop() {
  senseFire();
  senseIR();

  if (ret[0] != -1) {
...

Disparar e sentir são funções separadas. Se uma arma for atingida exatamente na mesma hora em que a arma estiver sendo disparada, o tiro não será registrado. Devido à maneira como o exemplo reproduz sons, isso deve ser verdadeiro enquanto o som estiver sendo reproduzido. Há maneiras como isso pode ser melhorado posteriormente, se você se sentir ambicioso, mas por hora, não se preocupe muito com isso. Se a arma de todos funcionar da mesma forma e for construía da mesma forma, o campo de jogo está essencialmente nivelado.



Voltar para parte superior


A Função fireShot

Quando um pressionamento de botão for detectado e você souber que a arma não foi auto-destruída, você pode disparara o tiro em si. Lembre-se, um tipo consiste em duas informações (Quem e O que) colocadas entre um bit inicial e um bit final. No caso de um jogador, Quem é o código do jogador e O que é o nível do jogador. Esses valores são mantidos nas variáveis myCode e myLevel e são passados na função senseFire .

A função fireShot segue esta sequência:

  1. Ative o LED de feedback
  2. Codifique Quem em binário
  3. Codifique O QUE em binário
  4. Envie o bit inicial
  5. Envie o binário
  6. Envie o bit final
  7. Reproduza um sinal
  8. Desative o LED de feedback

Para iniciar, você irá declarar a função, inicializar uma array para conter os dados codificados e ativar o LED de feedback, conforme mostrado abaixo.


Listagem 10. Declarando a Função fireShot e Inicializando uma array

void fireShot(int player, int level) {
  int encoded[8];
  digitalWrite(blinkPin, HIGH);

Preencha primeiro a array de dados codificada com as informações do jogador e, em seguida, com as informações de nível.


Listagem 11. Preencher a array

  for (int i=0; i<4; i++) {
    encoded[i] = player>>i & B1;   //codifique os dados como '1' ou '0'
  }
  for (int i=4; i<8; i++) {
    encoded[i] = level>>i & B1;
  }

Envie o bit inicial, como na Listagem 12, usando a função oscillationWrite que você escreverá em um momento. Após enviar cada bit, você precisa enviar o que é chamado de um separador (essencialmente um flash) e pausar por pouco tempo.


Listagem 12. Enviando o Bit Inicial

  oscillationWrite(senderPin, startBit);
  digitalWrite(senderPin, HIGH);
  delayMicroseconds(waitTime);

Agora que você enviou o bit inicial e pausou, irá percorrer a array codificada para trás, enviar cada bit através da mesma função oscillationWrite e incluir um separador e uma pausa no final de cada bit.


Listagem 13. Incluindo um Separador e uma Pausa no Final de Cada Bit

  for (int i=7; i>=0; i--) {
    if (encoded[i] == 0) {
      oscillationWrite(senderPin, zero);
    } else {
      oscillationWrite(senderPin, one);
    }

    digitalWrite(senderPin, HIGH);
    delayMicroseconds(waitTime);
  }

Envie o bit final, reproduza um sinal para indicar o disparo e desative o LED de feedback.


Listagem 14. Enviando o Bit Final

  oscillationWrite(senderPin, endBit);
  playTone(100, 5);
  digitalWrite(blinkPin, LOW);
}

O sinal reproduzido aqui é extremamente simples. Abstrair todo o sinal sendo reproduzido para um conjunto separado de funções, para que elas pudessem ser descarregadas para a área de troca mais facilmente, seria uma excelente melhora.

Alguns funções desta série, incluindo fireShot , mas principalmente oscillationWrite, foram baseadas em ou retiradas de código escrito por Paul Malmsten e postado nos fóruns do Arduino (consulte Recursos). Disponibilizar esse código para o público em geral facilitou a conclusão desta série.



Voltar para parte superior


A Função oscillationWrite

A função oscillationWrite , na Listagem 15, trata da transmissão do sinal na frequência desejada: 38 kHz. Você irá ativar o pino do emissor por 13 microssegundos, em seguida, desativará por 13 microssegundos (isso cria um ciclo) por um período de tempo determinado pelo o que você deseja enviar (um zero ou um um, um bit inicial ou um bit final).


Listagem 15. Função oscillationWrite

void oscillationWrite(int pin, int time) {
  for(int i = 0; i <= time/26; i++) {
    digitalWrite(pin, HIGH);
    delayMicroseconds(13);
    digitalWrite(pin, LOW);
    delayMicroseconds(13);
  }
}

Se você tiver optado por usar uma frequência diferente para seus sensores e armas, é necessário reescrever esta seção de código conforme necessário.



Voltar para parte superior


A Função selfDestruct

A função selfDestruct é mostrada na Listagem 16. Quando uma arma tiver disparo muitos tiros, o jogador é eliminado. Faça isso configurando os acertos do jogador para maxHits+1 e reproduzindo um som interessante.


Listagem 16. Função selfDestruct

void selfDestruct() {
  myHits  = maxHits+1;
  playTone(1000, 250);
  playTone(750, 250);
  playTone(500, 250);
  playTone(250, 250);
}

Nesse ponto, você está pronto para testar o disparo de sua arma. Respire fundo e prepare-se para pressionar alguns botões.



Voltar para parte superior



Ir para a página anteriorPágina 4 de 10 Ir para a próxima página