Show do Zecão - Um Jogo de perguntas e respostas
Você conhece o jogo Show do milhão ? Sabia que foi feito em Visual Basic ? (pelo menos até a versão 2). Temos ai um exemplo bem sucedido de uma aplicação feita em Visual Basic. |
Tudo bem , o jogo não tem muitos recursos gráficos e, é, em sua essência, até um jogo muito simples. Mas foi um sucesso de vendas, mostrando que agradou o público e que atingiu o objetivo.
Já pensou se você tivesse a mesma ideia ( e o mesmo marketing) $$$ ?
Bem, não fique frustrado.
Vou mostrar como criar um jogo igualzinho ao Show do Milhão e aproveitar para abordar alguns tópicos importantes como:
Veja agora as principais telas(na verdade todas as telas) do sensacional jogo - Show do Zecão :
frmintroducao: A tela de abertura |
|
frmsplash: A tela inicial |
|
frmnome: A tela de identificação do usuário |
|
A tela de apresentação dos valores das rodadas |
|
A tela de perguntas |
|
A tela de pergunta mostrando o acionamento da ajuda com os agentes microsoft : Genie e Merlin em ação |
|
A tela de encerramento do jogo |
O funcionamento do jogo - Show do Zecão - é idêntico ao jogo Show do Milhão e será dissecado neste artigo (o jogo foi feito em algumas horas).
Por isso não espere por recursos gráficos de primeira , nem efeitos com animação (eu não usei...). Os arquivos de som também foram gerados no gravador de som do windows.
Apesar de tudo isto, o jogo funciona bem, mostrando que você pode desenvolver sistemas comerciais sem ser um mestre em VB, e, se você tiver um bom conhecimento geral poderá ganhar - Um milhão de reais...
A lógica do jogo
Bem a lógica do jogo e responder as perguntas e a medida que você for acertando você vai em frente avançado para fase seguinte até alcançar a última fase com a pergunta que vale 1.000.000,00 de reais. Mas o que interessa para nós é o seguinte:
Onde estão armazenadas essas perguntas ?
Como o programa seleciona cada pergunta e exibe as opções de resposta ?
Como o sistema verifica se a pergunta esta certa ou errada ?
Vamos responder todas essas perguntas explicando-as em detalhes. A primeira é fácil: As perguntas estão armazenadas em um banco de dados Access . A estrutura da tabela que contém as perguntas é muito importante e você logo vai saber por que.
Temos um banco de dados Access chamado Perguntas.mdb que contém uma tabela chamada Perguntas com a seguinte estrutura:
Assim uma pergunta será visualizada na tabela assim:
Pergunta | resp1 | resp2 | resp3 | resp4 | respostacerta | utilizada | Nivel | |
1 | Quanto é dois mais dois ? |
3 |
5 |
4 |
6 |
3 |
N |
A |
Percebeu que com esta estrutura basta posicionar o ponteiro no registro para extrair a Pergunta , as opções de Resposta e a coluna com a Resposta Certa para comparar com a resposta indica pelo usuário.
As colunas pergunta , resposta1, resposta2, resposta3 e resposta4 , você preenche quando cadastra a pergunta no banco de dados . O nosso jogo já tem algumas perguntas cadastradas e também permitirá a você cadastrar mais perguntas.
A coluna - respostacerta - irá armazenar o número da questão correta, desta forma , para saber se o usuário escolheu a opção correta basta comparar a opção clicada com o número da coluna correspondente a Pergunta.
A coluna - ja_utilizada - indica se a pergunta já foi utilizada ou não , desta forma nunca repetiremos a mesma pergunta duas vezes no mesmo jogo. Quando o jogo começa todas as colunas referentes ao campo - ja_utilizada - possuem o valor N e após o usuário acertar a pergunta o campo - ja_utilizada - é atualizado para S , com isto esta pergunta não será mais selecionada no jogo em curso.
A coluna - tipo - indica a que fase a pergunta pertence , com isto podemos filtrar perguntas referentes a uma determinada fase . Fazemos isto utilizando as consultas Seleção SQL.
Assim para filtrar as perguntas por fase podemos usar uma consulta com a seguinte sintaxe:
SELECT perguntas.numero, perguntas.pergunta, perguntas.resposta1, perguntas.resposta2, perguntas.resposta3, perguntas.resposta4, perguntas.ja_utilizada, perguntas.tipo FROM perguntas WHERE (((perguntas.tipo)="A")) ORDER BY perguntas.numero; |
Esta consulta seleciona as perguntas , opções de resposta , resposta certa e o tipo da pergunta da tabela Perguntas quando a pergunta for do tipo A ( perguntas da primeira fase) e as ordena por número da pergunta.
Obs: Basta alterar a letra na cláusula Where para B , C ou D para obter consultas para outras fase ; cada uma corresponde a fase 2 , 3 e 4. Teremos portanto quatro consultas nomeadas como : Fase1 , Fase2 , Fase3 e Fase4 que selecionarão as perguntas referentes a cada fase do jogo.
Agora que você tem uma visão geral vamos passear pelas telas do jogo e abordar os aspectos mais importantes utilizados para criar o Show do Zecão.
A Introdução
Ao iniciar o projeto a tela de introdução será exibida e cada linha da mensagem será exibida compassadamente na tela . Quando a última mensagem (Boa Sorte) for exibida , após alguns segundos o formulário - frmintroducao - será fechado e será exibido o formulário , vemos abaixo o formulário em tempo de desenho do projeto. Como disse eu não me preocupei com os efeitos visuais , por isso usei recursos simples apenas para ilustrar as possibilidades.
Neste formulário foram usados controles:
1-) Timers - Para controlar a exibição das mensagens. 2-) Labels - Contém os dizeres de cada frase 3-) Image - Para exibir o logo Show do Zecão. |
Você vai perceber que ao iniciar o projeto uma música começa a tocar continuamente conforme as frases vão sendo exibidas na tela.
Como obtemos este recurso ?
Estamos usando arquivos do tipo WAV , portanto , para obter o recurso de tocar um arquivo WAV continuamente usaremos uma API declarada em um módulo . Eis a declaração:
Public Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long |
Então para tocar um arquivo wav basta chamar a função informando sua localização e nome, assim:
Call sndPlaySound("c:\ashowzecao\certa.wav", 0)
Isto irá tocar o arquivo certa.wav localizado no diretório c:\ashowzecao uma única vez, para que o arquivo seja continuamente tocado devemos usar as constantes :
Const SND_ASYNC = &H1 'modo assíncrono. toca musica sem parar
Const SND_LOOP = &H8
Você deve declarar estas constantes na seção General Declarations do formulário. A chamada da função , nestes casos, deverá ser feita usando estas constantes, assim:
Call sndPlaySound("c:\show do zecao\entrada.wav", SND_ASYNC + SND_LOOP)
Assim o código que exibe toca a música para o formulário frmintroducao é:
Private Sub Timer2_Timer() Call sndPlaySound("c:\show do zecao\entrada.wav", SND_ASYNC + SND_LOOP) Timer2.Enabled = False End Sub |
Estamos usando o controle Timer - Timer2 - para acionar o arquivo entrada.wav . Um controle Timer é usado para processar tarefas em um determinado intervalo de tempo.
O arquivo é acionado após quase um segundo da carga do formulário. Este tempo é definido na propriedade Interval do controle Timer2 . A propriedade Interval é definida em milisegundos , assim cada 1000 corresponde a 1 segundo.
Atribuímos o valor a propriedade assim:
Timer2.interval = 500 ´ou definimos a propriedade no próprio controle assim:
Após a chamada a função SndPlaySound desabilitamos o controle Timer2 - ( Timer2.enabled= False ) , evitamos assim que a função seja chamada novamente após decorrido o tempo definido em Interval.
O outro controle Timer - Timer1 - foi usado para , da mesma forma , exibir na tela as frases em intervalos de tempo distintos. O código é o seguinte:
Private Sub Timer1_Timer() If contador = 3 Then Label1.Visible = True End If If contador = 13 Then Label2.Visible = True End If If contador = 21 Then Label3.Visible = True End If If contador = 31 Then Image1.Visible = True End If If contador = 38 Then Label4.Visible = True End If If contador = 50 Then Call sndPlaySound("c:\ashowzecao\semsom.wav", 0) Unload Me frmSplash.Show vbModal End If contador = contador + 1 End Sub |
Observe que usamos a variável contador , que é incrementada a intervalos de tempo definido em Timer1.interval . Usamos o arquivo chamado semsom.wav para interromper a musica acionada em entrada.wav.
Demos uma possibilidade de o usuário interromper a exibição de todas as frases na tela e a música exibindo o formulário frmSplash . Basta ele clicar no formulário para que isto ocorra. O código é:
Private Sub Form_Click() Call sndPlaySound("c:\ashowzecao\semsom.wav", 0) Unload Me frmSplash.Show vbModal nd Sub |
Agora observe o código do evento Load do formulário.
Private Sub Form_Load() contador = 0 If Dir(App.Path & "\show.ini") <> "" Then valortempo = ReadINI("Geral", "Tempo", App.Path & "\show.ini") valorajuda = ReadINI("Geral", "Ajuda", App.Path & "\show.ini") atualizaperguntas = ReadINI("Geral", "Atualiza", App.Path & "\show.ini") Else MsgBox " O ARQUIVO DE CONFIGURAÇÃO - NÃO FOI LOCALIZADO !. OS VALORES PADRÕES SERÃO ASSUMIDOS !" valortempo = 40 valorajuda = 2 atualizaperguntas = "SIM" End If End Sub |
Este código além de inicializar o contador, também procura pelo arquivo Show.ini lendo o seu conteúdo e atribuindo os valores definidos no arquivo a variáveis de configuração.
Os arquivos INI eram muito usados no Windows 3.X e ainda podem ser utilizados para determinadas tarefas.
No nosso jogo usamos o arquivo Show.INI para configurar algumas preferências do usuário . São Elas :
O tempo de resposta - valortempo - O usuário poderá alterar o tempo que ele tem para responder a uma pergunta
Quantas vezes a ajuda pode ser acionada - valorajuda - O usuário poderá definir quantas vezes ele poderá recorrer a Ajuda. (usando os agentes Microsoft)
Atualizar o conteúdo do campo ja_utilizado - atualizarperguntas - O usuário poderá definir se deseja ( S) ou não ( N) que o arquivo de perguntas seja atualizado para exibir novamente as perguntas já utilizadas ou não.
O que é um arquivo INI ?
Um arquivo INI é um arquivo texto usado para armazenar/fornecer configurações pessoais para sistemas/usuários;
Um arquivo INI é um arquivo com dados externo ao programa principal e esta formatado em : Seções(FileName) , Entradas e Valores :
[Seçao1]
entrada=valor
entrada=valor
entrada=valor
[Seção2]
entrada=valor
entrada=valor
A Seção identifica um conjunto de entradas e valores e esta relacionado a um determinado programa. Como muitos programas podem usar o mesmo arquivo INI ( Ex: o arquivo WIN.INI ) geralmente uma seção trazia o nome do programa que iria usá-la.
Uma Entrada funciona como um identificador para variáveis.
Os Valores são usados , como o próprio nome diz , para atribuir valores as entradas , e , sempre estão no formato Strings , mesmo sendo números.
Um exemplo de arquivo INI é o WIN.INI cuja estrutura mostramos em parte a seguir:
[windows] load= run= NullPort=None device=HP DeskJet 690C,HPDSKJTB,LPT1: SingleClickSpeed=067614 [Desktop] Wallpaper=(None) TileWallpaper=0 WallpaperStyle=2 Pattern=120 49 19 135 225 200 140 30 |
No nosso caso estamos usando o arquivo SHOW.INI para guardar algumas preferências do usuário. Sua estrutura é a seguinte:
[Geral]
Tempo=50
Ajuda=2
Atualiza=SIM
Como fazemos para acessar e/ou alterar os valores em um arquivo INI ?
Boa pergunta !
Para fazer isto usamos duas API's do Windows , vamos apresentá-las:
1-) API usada para ler os arquivos INI . Geralmente você faz esta declaração em um módulo:
Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nsize As Long, ByVal lpFileName As String) As Long |
2-) API usada para escrever em uma arquivo INI. Geralmente você faz esta declaração em um módulo
Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long |
Agora basta escrever duas funções que usam estas API´s , uma para ler e outra para escrever. Elas estão prontas abaixo:
1-) Função - ReadINI - lê um arquivo INI. Precisa de três parâmetros : O nome da Seção , o nome da Entrada e o nome do Arquivo INI.
Public Function ReadINI(Secao As String,
Entrada As String, Arquivo As String) 'Arquivo=nome do arquivo ini 'Secao=O que esta entre [] 'Entrada=nome do que se encontra antes do sinal de igual Dim retlen As String Dim Ret As String Ret = String$(255, 0) retlen = GetPrivateProfileString(Secao, Entrada, "", Ret, Len(Ret), Arquivo) Ret = Left$(Ret, retlen) ReadINI = Ret End Function |
2-) A função - WriteINI - escreve em um arquivo INI. Precisa de quatro parâmetros : o nome da Seção , o nome da Entrada , o nome do Texto ( Valor ) e o nome do arquivo INI.
Public Sub WriteINI(Secao As String, Entrada
As String, Texto As String, Arquivo As String) 'Arquivo=nome do arquivo ini 'Secao=O que esta entre [] 'Entrada=nome do que se encontra antes do sinal de igual 'texto= valor que vem depois do igual WritePrivateProfileString Secao, Entrada, Texto, Arquivo End Sub |
No nosso caso para Ler os valores do arquivo SHOW.INI usamos o seguinte código:
valortempo = ReadINI("Geral", "Tempo", App.Path & "\show.ini") valorajuda = ReadINI("Geral", "Ajuda", App.Path & "\show.ini") atualizaperguntas = ReadINI("Geral", "Atualiza", App.Path & "\show.ini") |
As variáveis valortempo, valorajuda e atualizaperguntas irão armazenar os valores lidos do arquivo Show.ini através da função ReadINI.
Para escrever em um arquivo INI alterando os valores das entradas: Tempo, Ajuda e Atualiza , usamos o seguinte código:
Call WriteINI("Geral", "Tempo", txttempo.Text, App.Path & "\show.ini") Call WriteINI("Geral", "Ajuda", txtajuda.Text, App.Path & "\show.ini") Call WriteINI("Geral", "Atualiza", txtatualiza.Text, App.Path & "\show.ini") |
Os valores são informados nas caixas de texto txttempo.txt , txtajuda.text e txtatualiza.text . Como isso lemos e escrevemos em arquivos INI.
O formulário de perguntas e respostas
Para não tornar o artigo muito longo e enfadonho vamos direto ao módulo mais importante do projeto : o arquivo frmperguntas.
É na carga deste formulário que geramos as perguntas, aguardamos a resposta do usuário, verificamos se o tempo não acabou, solicitamos a ajuda, verificamos se a resposta esta correta, se o usuário resolveu parar, enfim as principais ações do jogo.
Então vamos por partes...
A seção General Declarations do formulário frmperguntas é a seguinte: Nele definimos as variáveis que serão visíveis em todo o formulário.
Dim rsperg As Recordset Dim selecao As Integer Dim sql As String Dim tempo As Integer Dim Genie As IAgentCtlCharacterEx 'inicializa o ator Const DataAtor = "genie.acs" 'define o caminho para o agente que voce vai usar Const dataAtor2 = "merlin.acs" 'define o caminho para o agente que voce vai usar Dim Merlin As IAgentCtlCharacter Const SND_ASYNC = &H1 'modo asíncrono. toca musica sem parar Const SND_LOOP = &H8 ' |
1-) Exibindo a barra de progresso e o valor das variáveis globais
O código do evento Load do formulário frmperguntas é os seguinte:
Private Sub Form_Load() lblusuario.Caption = NomeUsuario selecao = 1 tempo = valortempo progbar1.Max = valortempo progbar1.Min = 0 lbltempo.Caption = tempo randomize
gera_perguntas |
As variáveis NomeUsuario , selecao , valortempo e tempo são variáveis globais definidas no nosso arquivo de módulo show.bas.
Progbar1 é o nome da nossa barra de progresso que indica o tempo que resta para responder a pergunta.
Como implementamos essa barra de progresso ?
|
A barra de
progresso - Progbar1 - usada no projeto possui as propriedades
definidas na figura ao lado.
A propriedade Max e Min são definidas em tempo de execução como:
progbar1.Max = valortempo Estes valores são definidos no arquivo INI. Assim o usuário pode aumentar/diminuir o valor do tempo de resposta. Também usamos uma label acima da barra de progresso que exibe o valor numérico do tempo que resta para responder a pergunta. Este valor é definido em : lbltempo.Caption = tempo A instrução Randomize irá permitir que as perguntas sejam geradas de forma aleatórias. |
Como queremos que a barra de progresso reflita o tempo restante usamos um controle Timer com propriedade interval definida como sendo igual a 1000 ( 1000 = 1 segundo ), com isso , a cada segundo o evento Timer é acionado. Incluímos então no evento Timer o código a seguir:
Private Sub Timer2_Timer() Dim aumento As Integer progbar1.Value = progbar1.Value + 1 tempo = tempo - 1 lbltempo.Caption = tempo
If progbar1.Value = valortempo Then |
Com ele incrementamos o valor da barra de progresso - progbar1 - em uma unidade ( progbar1.Value + 1) e decrementamos o valor da variável tempo de 1 ( tempo - 1 ) exibindo assim o valor número decrescendo .
Se o valor da barra de progresso for igual ao tempo máximo definido ( valortempo ) um aviso sonoro é emitido , o formulário é descarregado e o formulário frmparar exibe quanto o usuário ganhou até aquele instante.
2-) Gerando as perguntas
Como já dissemos as perguntas do nosso jogo estão armazenadas em um banco de dados Access ( usei a versão 2000 ). O nome do banco de dados é - Perguntas.mdb. A tabela que contém as questões chama-se Perguntas.
Quando o formulário frmperguntas for chamado, o banco de dados já deverá ter sido aberto. Na verdade ele foi aberto quando o usuário forneceu o nome e clicou no botão Jogar. O código é o seguinte:
Set ws = DBEngine.Workspaces(0) Set db = ws.OpenDatabase(App.Path & "\perguntas.mdb") |
Já deu para perceber que estamos usando DAO . Por que ? Por que é mais simples e rápido.
Temos também armazenadas no banco de dados quatro consultas referentes as perguntas de cada fase do jogo. Assim para a fase 1 temos a consulta :
SELECT perguntas.numero, perguntas.pergunta, perguntas.resposta1, perguntas.resposta2, perguntas.resposta3, perguntas.resposta4, perguntas.respostacerta, perguntas.ja_utilizada, perguntas.tipo FROM perguntas WHERE (((perguntas.tipo)="A")) ORDER BY perguntas.numero; |
Para a fase 2 temos a consulta :
SELECT [perguntas].[numero], [perguntas].[pergunta], [perguntas].[resposta1], [perguntas].[resposta2], [perguntas].[resposta3], [perguntas].[resposta4], [perguntas].[respostacerta], [perguntas].[ja_utilizada], [perguntas].[tipo] FROM perguntas WHERE ((([perguntas].[tipo])="B")) ORDER BY [perguntas].[numero]; |
ate a fase 4. Então basta selecionarmos as perguntas de cada fase usando cada consulta pertinente. Como não queremos repetir uma pergunta iremos selecionar somente as perguntas que ainda não foram utilizadas ( ja_utilizada="N").
Private Sub gera_perguntas() Dim posicao As Long If Fase = 1 Then sql = "Select * from Fase1 where ja_utilizada='N'" ElseIf Fase = 2 Then sql = "Select * from Fase2 where ja_utilizada='N'" ElseIf Fase = 3 Then sql = "Select * from Fase3 where ja_utilizada='N'" ElseIf Fase = 4 Then sql = "Select * from Fase4 where ja_utilizada='N'" End If Set rsperg = db.OpenRecordset(sql, dbOpenDynaset) rsperg.MoveLast rsperg.MoveFirst If rsperg.RecordCount > 0 Then posicao = rsperg.RecordCount Else posicao = 1 End If questao = Int((posicao * Rnd) + 1) Move questao lblpergunta.Caption = rsperg.Fields(1) For i = 0 To 3 lblresp(i).Caption = rsperg.Fields(i + 2) Next End Sub |
A seguir geramos um recordset do tipo Dynaset chamado rsperg com a consulta sql . Usamos as propriedades MoveLast e MoveFirst para movermos o ponteiro do para fim do arquivo e para o inicio de forma a obter um valor correto para a quantidade de registros ( Recordcount ) do recordset.
Sabendo a quantidade de registros , na verdade estou sabendo a quantidade de perguntas que tenho. Agora podemos gerar as questões.
3 -) Como gerar perguntas Aleatórias ?
Para gerar perguntas aleatórios utilizamos a função Rnd em conjunto com a instrução Randomize.
A função Rnd gera números pseudo aleatórios. Pseudo aleatórios por que parece que são aleatórios mas na verdade não são. Para um número ser aleatório ele não pode ser previsível e isto não ocorre com a função Rnd.
Esta função tem a seguinte sintaxe:
Rnd[(numero)] - Número é um valor do tipo Single. Os valores retornados são:
Se número for | Rnd irá gerar |
menor que zero | O mesmo número sempre . O número será usado como semente.(seed) |
Maior que zero | O próximo número na sequência. |
Igual a zero | O mais recente número gerado. |
Não fornecido | O próximo número aleatório na sequência. |
Cada vez que a função Rnd é chamada, um novo valor é gerado. Este valor é sempre menor que 1 mas maior ou igual a zero , temos então que : 0 <= Rnd < 1
Então para gerar números em uma faixa que você deseja, é o só usar a fórmula:
Int((MaiorValor - MenorValor + 1) * Rnd) + MenorValor
Exemplo:
Para gerar números aleatórios entre 100 e 200 fazemos : Int( 101 * Rnd ) + 100
Para gerar números aleatórios entre 1 e 10 fazemos : Int( 10 * Rnd ) + 1
Isto teria um efeito indesejável não é mesmo ? Como contornar este problema ?
Para evitar isto usamos a instrução Randomize. Ela inicializa o gerador de números aleatórios com base no relógio do sistema(pois não usamos argumentos na instrução).
Portanto para evitar gerar a mesma sequência usamos a instrução Randomize antes de chamar a função Rnd. Podemos fazer isto somente uma vez.(Por isso colocamos a instrução Randomize no evento do formulário)
Se você precisar repetir uma determinada sequência de números , basta chamar a função Rnd com um argumento negativo e imediatamente usar a instrução Randomize com um argumento numérico indicando a semente que deseja usar. Assim :
'Faz o VB iniciar usando um parâmetro em Randomize.
Rnd -1
'Faz o VB usar o valor 123 como ponto de partida ( seed ).
Randomize 123
|
Vejamos então o código da rotina que irá gerar as perguntas:
Private Sub gera_perguntas() exit sub
End If |
Logo no início temos a montagem da instrução SQL que irá gerar o recordset com as perguntas. Como temos 4 fases , conforme a fase do jogo iremos selecionar perguntas usando as consultas armazenadas no banco de dados . Então montamos a instrução assim:
sql = "Select * from Fase1 where
ja_utilizada='N'"
Aqui selecionamos todos os registros gerados pela consulta Fase1 quando a
pergunta ainda foi utilizada. Fazemos isto para cada fase do jogo.
A seguir geramos o recordset e movimentamos o ponteiro para o final do arquivo retornando ao inicio logo a seguir. Com isto teremos a quantidade de registro deste recordset.
Set rsperg = db.OpenRecordset(sql, dbOpenDynaset)
rsperg.MoveLast
rsperg.MoveFirst
A seguir apenas verificamos se realmente existem perguntas no recordset gerado , se não houver perguntas avisamos o usuário e saímos da rotina:
If
rsperg.RecordCount > 0 Then
posicao = rsperg.RecordCount
Else
msgbox 'Não há perguntas cadastradas para esta fase !
"
exit sub
End If
Agora vamos gerar um número aleatório entre 1 e a quantidade de registros que existe no recordset ( posição). Com isto sempre estaremos trabalhando com as perguntas existentes no arquivo. Com o número gerado movemos a ponteiro para o registro com este número.
questao =
Int((posicao * Rnd) + 1)
Move questao
Finalmente com o ponteiro no registro , extraímos
os campos referentes a pergunta e as opções de resposta. Usamos o objeto Fields , onde rsperg.Fields(1) refere-se ao segundo campo do
recordset ( o indíce zero é o primeiro campo ).
lblpergunta.Caption =
rsperg.Fields(1)
For i = 0 To 3
lblresp(i).Caption = rsperg.Fields(i + 2)
Next
4-) Pedindo Ajuda
O usuário pode pedir Ajuda durante o jogo ( a quantidade de vezes que ele pode pedir ajuda você configura no arquivo SHOW.INI , lembra ? ) . Aqui usamos os agentes microsoft - Genie e Merlin. (Você pode usar outros...).
Então quando o usuário clica no botão ajuda temos o seguinte código:
Private Sub lblopcao2_Click() If lblopcao2.Caption = "NÃO" Then lblresp(selecao - 1).ForeColor = vbYellow lblopcao1.Caption = "Parar" lblopcao2.Caption = "Ajuda" Else If Fase < 4 Then ' não carrega na ultima pergunta (não tem ajuda) If Not estacarregado Then ajuda = ajuda + 1 If genio Then Agent1.Characters.Load "Genie", DataAtor 'carrega o ator Set Genie = Agent1.Characters("Genie") 'define o ator que vai atuar estacarregado = True Genie.LanguageID = &H409 'define a linguagem Genie.MoveTo 590, 240 Genie.Show 'faz o ator aparecer End If If magico Then Agent1.Characters.Load "Merlin", dataAtor2 'carrega o ator Set Merlin = Agent1.Characters("Merlin") 'define o ator que vai atuar estacarregado = True Merlin.LanguageID = &H409 'define a linguagem Merlin.MoveTo 490, 240 Merlin.Show 'faz o ator aparecer End If End If ' esta carregado End If End If End Sub |
Se o botão estiver exibindo a palavra Ajuda , então , a primeira coisa que verificamos é a fase do jogo em que estamos.
Se a fase do jogo não for a última fase ( if fase < 4 ) então verificamos se o agente já esta carregado (if Not estacarregado );
Se o agente não estiver carregado incrementamos a variável ajuda de uma unidade e verificamos se o agente ainda pode ser carregado ( if genio then/ if magico then ).
As variáveis públicas genio e magico são variáveis boleanas definidas no módulo do projeto e de início possuem o valor True ;
Quando o número de vezes que o usuário pediu ajuda for maior que a quantidade de ajuda definida no arquivo Show.ini ( If ajuda > valorajuda Then ) então genio ou magico recebem o valor False não podendo ser mais carregados.
O código para carga do agente é o seguinte:
Agent1.Characters.Load "Genie", DataAtor
'carrega o ator
Set Genie = Agent1.Characters("Genie")
'define o ator que vai atuar
estacarregado = True
Genie.LanguageID = &H409
'define a linguagem
Genie.MoveTo 590, 240
Genie.Show
'faz o ator
aparecer
Para recebe Ajuda você deve clicar no agente desejado para ele 'falar' a resposta correta para você (você pode implementar o efeito sonoro de voz para agente ... ). O código é o seguinte:
Private Sub Agent1_Click(ByVal CharacterID As String, ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Integer, ByVal y As Integer) If CharacterID = "Merlin" Then If ajuda > valorajuda Then magico = False End If fala = "A resposta correta é a ...: " fala = fala & rsperg(6) Merlin.Speak fala End If If CharacterID = "Genie" Then If ajuda > valorajuda Then genio = False End If fala = "A resposta correta é a ... " fala = fala & rsperg.fields(6) Genie.Speak fala End If End Sub |
Ao clicar em um agente , verificamos qual o agente que você clicou ( CharacterID = "Merlin" ) e , se o número de ajudas solicitado for maior que o permitido definimos a variável magico ou genio , conforme o agente , para False de forma que este agente não poderá ser mais carregado.
A seguir fazermos o agente 'falar' ( Genie.Speak fala ) a resposta correta. A resposta correta é o sétimo campo do recordset rsperg ( rsperg.fields(6) ) .
5-) Verificando a resposta correta
Quando o usuário seleciona uma opção e clica no botão SIM , o código a seguir entra em ação :
Private Sub lblopcao1_Click() If lblopcao1.Caption = "SIM" Then If selecao = rsperg(6) Then atualiza_registro Call sndPlaySound("c:\ashowzecao\certa.wav", 0) Pergunta = Pergunta + 1 If Fase >= 4 Then Unload Me frmparar.Show vbModal End If If Pergunta > 5 Then Fase = Fase + 1 Pergunta = 1 End If Unload Me frmvalores.Show vbModal Else lblresp(rsperg(6) - 1).ForeColor = vbWhite lblresp(selecao - 1).ForeColor = vbYellow Refresh Call sndPlaySound("c:\ashowzecao\errada.wav", 0) Sleep 4000 Unload Me frmparar.Show vbModal End If Else lblresp(selecao - 1).ForeColor = vbYellow End If If lblopcao1.Caption = "Parar" Then Call sndPlaySound("c:\ashowzecao\temcerteza.wav", 0) Sleep 3000 Unload Me frmparar.Show vbModal End If End Sub |
Ao clicar no botão SIM , verificamos se a seleção é igual a resposta correta (selecao = rsperg.fields(6)) ; se a resposta for correta atualizamos o registro marcando-o como já utilizado através da rotina:
Private Sub atualiza_registro()
rsperg.Edit
rsperg!ja_utilizada = "S"
rsperg.Update
End Sub
A seguir emitimos o aviso sonoro (Call sndPlaySound("c:\ashowzecao\certa.wav", 0) ) , incrementamos a variável pergunta de uma unidade ( pergunta = pergunta + 1 ) , verificamos se estamos na última fase ( em caso positivo descarregamos o formulário e o jogo é encerrado ).
Se a variável pergunta for maior que 5 , retornamos ao valor 1 e mudamos de fase :
If Pergunta > 5 Then
Fase = Fase + 1
Pergunta = 1
End If
Se o usuário errar ou escolher parar o jogo , o código a seguir é executado:
lblresp(rsperg(6) - 1).ForeColor = vbWhite
lblresp(selecao - 1).ForeColor = vbYellow
Refresh
Call sndPlaySound("c:\ashowzecao\errada.wav", 0)
Sleep
4000
Unload Me
frmparar.Show vbModa
Mostramos qual a resposta correta ( lblresp(rsperg(6) - 1).ForeColor = vbWhite ) , emitimos o aviso sonoro , usamos uma pausa de 4 segundos ( sleep 4000 ) - declarada no módulo do projeto) e o jogo é encerrado.
Com isso vou terminando por aqui as explicações sobre este jogo.( O código dos demais formulários não apresentam nada de novo).
A intenção foi mostrar as principais rotinas envolvidas na criação de um projeto de um jogo usando banco de dados e alguns efeitos . Se você quiser e tiver tempo pode incrementar o jogo com telas , sons e efeitos tornando-o um mais amigável e mais eficiente.
Se não quiser pode jogar a vontade com a vantagem que você pode cadastrar as suas perguntas e respostas e alterar alguns parâmetros como tempo de resposta e quantidade de ajudas.
Percebeu que não é preciso muito para você um criar um projeto viável comercialmente e ganhar uns trocados... ?
Agora é com você...
Obs: Eu vou disponibilizar somente os códigos fontes do jogo , os arquivos de som você vai ter que gerar para poder usar. Infelizmente os arquivos WAV ocupam muito espaço , que para mim é precioso.
O jogo completo esta no Super DVD Visual Basic.
Para baixar os fontes clique aqui : Show do Zecão ( 154 KB )
Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira ! Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: