Skip to content

Samara-Ferreira/PBL03-Breakout-Game

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

86 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Breakout game

Jogo inspirado no clássico Breakout, desenvolvido para o kit de desenvolvimento DE1-SoC utilizando linguagem C

Sobre o Projeto

Atualmente, a Apple é uma das maiores empresas de desenvolvimento e inovação tecnológica, com suas produções conhecidas de dispositivos móveis e computadores pessoais. Dois dos seus principais fundadores foram Steve Jobs e Wozniak, um inventor e um engenheiro que moldaram uma geração de jogos eletrônicos na década de 70 com a criação do jogo de arcade Breakout.

Este projeto tem o intuito de desenvolver um jogo inspirado no Breakout. É utilizada a placa FPGA DE1-SoC para executar o sistema e disponibilizar a interface de controle ao usuário. Um acelerômetro embutido na placa permite captar a movimentação pretendida pelo usuário. Botões são utilizados para executar comandos no jogo. E os dados de imagem são transmitidos por um cabo VGA para um monitor CRT, sendo ele, o dispositivo que fará a exibição das telas ao usuário.

Os requisitos para elaboração do sistema são apresentados a seguir:

  • O código carregado na DE1-SoC deve ser feito em linguagem C;
  • Um acelerômetro deve captar a movimentação feita na placa para alterar a posição da barra que irá colidir com a bola;
  • Os botões devem ser utilizados para executar comandos no jogo;
  • Os dados de imagem devem ser transmitidos de um cabo VGA para um monitor CRT.

Equipe:

Sumário

Descrição dos Equipamentos e Software Utilizados

Nesta seção, são apresentados os equipamentos e software utilizados durante o desenvolvimento do projeto.

o kit de desenvolvimento DE1-SoC

A placa DE1-SoC é um kit de desenvolvimento que combina um processador ARM Cortex-A9 dual-core com um FPGA Cyclone V da Intel. Essa placa oferece uma ampla gama de periféricos, incluindo porta VGA, porta Ethernet, USB, porta de áudio, entre outros, o que a torna ideal para projetos que envolvem tanto software quanto hardware. Ela é frequentemente utilizada em ambientes educacionais e de pesquisa para o desenvolvimento e aprendizado em sistemas embarcados e FPGA.

Kit de desenvolvimento DE1-SoC

Monitor CRT

O monitor utilizado no projeto foi o DELL M782p, um modelo CRT. Esse tipo de monitor utiliza um tubo de raios catódicos (CRT) para exibir imagens. O DELL M782p possui uma tela de visualização de 17 polegadas e uma resolução máxima de 1280x1024 pixels. Ele oferece uma interface VGA para conexão com o computador ou placa de desenvolvimento. O monitor CRT é conhecido por sua reprodução de cores vibrantes e tempos de resposta rápidos, sendo uma escolha adequada para projetos que exigem interação em tempo real, como jogos e simulações.

Monitor CRT DELL

Linguagem C

A linguagem C foi escolhida devido à sua eficiência, portabilidade e ampla utilização em sistemas embarcados. Sua sintaxe simples permite controle preciso sobre o hardware, enquanto suas bibliotecas padrão e ferramentas facilitam o desenvolvimento de código compacto e otimizado para dispositivos com recursos limitados.

Compilador GNU

O GCC, abreviação para "GNU Compiler Collection" (Coleção de Compiladores GNU), é uma distribuição integrada de compiladores amplamente utilizada que suporta várias linguagens de programação, incluindo C, C++, Objective-C, Fortran, Ada, entre outras. Ao ser invocado, o GCC passa por etapas de pré-processamento, compilação, montagem e vinculação. Oferece uma ampla gama de opções de linha de comando para personalização, facilitando a configuração de acordo com as necessidades específicas do desenvolvedor.

Vscode

O Visual Studio Code, conhecido como VSCode, é um ambiente de desenvolvimento amplamente usado. Desenvolvido pela Microsoft, é um editor de código gratuito e de código aberto com recursos como realce de sintaxe, conclusão de código e depuração integrada. Suporta várias linguagens e possui extensões para personalização. No projeto ele foi utilizado para desenvolver o código fonte do jogo.

Arquitetura da placa DE1-SoC

Nesta seção, será explorado a arquitetura da placa DE1-SoC, incluindo o processador ARM Cortex-A9, a estrutura de registros, o mapeamento de dispositivos de entrada/saída na memória, a memória utilizada, a comunicação entre o processador e o FPGA, e o processo de compilação nativa na placa.

Visão Geral dos Recursos do Processador ARM Cortex-A9

O processador ARM Cortex-A9 utiliza uma arquitetura de conjunto de instruções reduzido (RISC), onde as operações aritméticas e lógicas são realizadas nos registradores de uso geral. Os dados são movidos entre memória e registradores através de instruções Load e Store, com um comprimento de palavra de 32 bits e endereços de bytes em um estilo little-endian.

Estrutura do Registro

O processador ARM Cortex-A9 possui 15 registros de uso geral (R0 a R14), um contador de programa (R15) e um registro de status de programa atual, CPSR, todos com 32 bits. Dois registros são tratados de maneira especial: R13 é o Stack Pointer e R14 é um registro de link na ligação de sub-rotina.

Registradores disponíveis e sua organização interna

Instruções e Conjunto Thumb

As instruções têm 32 bits e são armazenadas na memória alinhadas por palavras. O conjunto Thumb oferece uma versão menor com instruções de 16 bits, resultando em requisitos menores de memória, úteis em aplicativos incorporados.

Memória

O HPS inclui uma porta de memória que conecta o ARM MPCORE a uma memória DDR3 de 1 GB. Esta memória é normalmente utilizada como local de armazenamento de programas e dados pelos processadores ARM. A memória é organizada em 256M x 32 bits e pode ser acessada por meio de acessos de palavras (32 bits), meias palavras e bytes.

Mapeamento de Dispositivos de E/S

Os dispositivos de entrada/saída acessíveis pelo processador ARM são mapeados na memória e podem ser acessados como locais de memória, utilizando instruções Load e Store.

Interrupções de Hardware

As interrupções de hardware podem ser geradas por dispositivos de E/S, ativando as entradas de solicitação de interrupção do processador (IRQ ou FIQ). Quando ocorre uma interrupção, o processador entra no modo de exceção correspondente e salva o estado atual do programa. O endereço salvo no registrador de link deve ser decrementado em 4 antes de retornar ao programa interrompido.

Diagrama de Blocos do Sistema DE1-SoC

O sistema DE1-SoC é composto pelo Hard Processor System (HPS) e FPGA dentro do chip Cyclone V SoC. O HPS inclui um processador dual-core ARM Cortex-A9, uma porta de memória DDR3 e dispositivos periféricos. O FPGA implementa dois processadores Intel Nios II e várias portas periféricas.

Diagrama da arquitetura da placa DE1-SoC

Comunicação entre Processador e FPGA via JTAG

A porta JTAG implementa um link de comunicação entre a placa DE1-SoC e seu computador host, permitindo a transferência de arquivos de programação FPGA para a placa DE1-SoC e o monitoramento por meio do programa Intel FPGA Monitor.

Compilação Nativa na Placa DE1-SoC

O processo de compilação nativa ocorre quando um programa é compilado em um sistema para rodar na mesma arquitetura do próprio sistema. Neste caso, vamos compilar nativamente um programa por meio da interface de linha de comando do Linux, usando sua cadeia de ferramentas de compilação integrada. O comando gcc invoca o GNU C Compiler, um compilador de código aberto amplamente usado para compilar programas Linux.

Periféricos da Placa DE1-SoC Utilizados

A seguir, serão feitas as descrições gerais dos periféricos utilizados da placa DE1-SoC e seus aspectos mais importantes. A Figura abaixo mostra a placa FPGA, com as indicações dos seus dispositivos que serão citados.

Layout dos periféricos da placa

Porta de Saída de Vídeo

A placa possui uma porta de saída de vídeo com um controlador VGA, que pode ser conectado a um monitor do padrão VGA. As informações podem ser transmitidas de duas fontes: um buffer de pixels e um buffer de caracteres. O buffer de caracteres tem a função de especificar caracteres de texto que devem ser exibidos no monitor e, como não foi utilizado no sistema, ele não será focado nesse tópico.

As imagens exibidas no monitor tiveram como fonte o buffer de pixels. Ele contém os dados de cor de cada pixel transmitido pelo controlador VGA. Esse controlador suporta uma resolução de 640 x 480, porém, o buffer de pixels só fornece uma resolução de imagem de 320 x 240, por isso, cada valor de pixel é duplicado nas duas dimensões.

Cada pixel contém um conjunto de bits que são distribuídos entre as cores: vermelho, azul e verde. Uma imagem pode ser criada escrevendo os valores das cores no endereço do pixel especificado. O controlador do buffer de pixels lê os dados da memória e envia para o monitor VGA.

Com o objetivo de conseguir modificar o buffer de pixels sem alterar a imagem transmitida, a placa utiliza um sistema de "double buffer". Nesse esquema, existem dois espaços de armazenamento dos dados dos pixels, um que é transmitido para a tela VGA, chamado de "front buffer", e outro que não está sendo transmitido, mas pode ser modificado, chamado de "back buffer".

Cada vez que os dados dos pixels devem ser modificados, o usuário escreve no "back buffer" e quando quiser enviar esses dados para a tela VGA, é feita uma troca de buffers. Essa troca coloca o "back buffer" na frente e o "front buffer" atrás, assim, esse ciclo continua para se fazer o dinamismo das imagens exibidas. Porém, todos os pixels só são atualizados na tela com a frequência de 60 Hz, não podendo usar uma velocidade de troca de buffer superior a essa.

Acelerômetro ADXL345

O acelerômetro ADXL345 é um leitor de aceleração em intervalos regulares nos três eixos. Sua escala pode ser calibrada, porém, o seu intervalo de leitura máximo está entre -16g a 16g, sendo g, o valor de 9.81 metros por segundo ao quadrado.

Esse dispositivo está embutido na placa e sua comunicação é feita pelo protocolo de comunicação serial, I2C. É feita a conexão do acelerômetro com o controlador dessa comunicação para poder ler os dados e configurar a transmissão.

Os movimentos feitos com a placa, ou sua posição em relação a direção da gravidade, retornam determinadas medidas de aceleração. Sua utilização consiste em ler esses dados de aceleração retornados dos três eixos: x, y e z.

Botões

A placa disponibiliza quatro botões para utilização. Os dados de leitura dos botões são armazenados em um registrador de dados, com seus quatro bits menos significativos representando cada um dos botões. Quando um botão é pressionado, o seu respectivo bit é setado para 1, e quando é solto, para 0.

Existem outros dois registradores, o "interruptmask" e o "edgecapture". Esses registradores possuem um bit para cada botão, como o registrador de dados, porém, com funções diferentes. O "interruptmask" pode habilitar interrupções para cada botão, setando o seu respectivo bit para 1. O "edgecapture" seta o bit para 1 quando o botão é pressionado, e permanece nesse valor até que seja zerado diretamente. Setar um bit do "edgecapture" para 0 pode ser feito escrevendo o valor 1.

Drives de Dispositivos de Entrada e Saída (E/S)

Para realizar a comunicação com os dispositivos periféricos de hardware, é preciso utilizar programas de software, chamados de drivers, que vão disponibilizar a interface necessária para executar comandos nesses dispositivos. Os tipos de drivers utilizados foram os módulos de núcleo, sendo eles, módulos que podem ser adicionados ao núcleo na execução do programa.

A distribuição de Linux do DE1-SoC-UP disponibiliza módulos de núcleo prontos para realizar essa comunicação. Na linguagem C, esses módulos podem ser acessados adicionando na compilação do programa o comando "-lintelfpgaup", e no código, a declaração "#include <intelfpgaup/xxx.h>", sendo "xxx", o nome do driver utilizado. A seguir, serão descritas as funções pertinentes dos módulos de núcleo utilizados.

Porta de Saída de Vídeo

Módulo indicado pelo nome "video". As funções utilizadas são:

  • video_open: Abre o dispositivo de vídeo VGA;
  • video_clear: Limpa todos os gráficos do buffer de pixels que não está sendo transmitido;
  • video_erase: Limpa todos os dados de caracteres da tela;
  • video_show: Faz a troca entre os buffers, modificando qual será transmitido para o monitor VGA;
  • video_box: Escreve um quadrado ou retângulo no buffer que não está sendo transmitido. Nos seus parâmetros, são passadas as coordenadas das extremidades opostas da forma geométrica e a cor que ela terá.

Acelerômetro

Módulo indicado pelo nome "accel". As funções utilizadas são:

  • accel_open: Abre o dispositivo do acelerômetro;
  • accel_read: Lê os dados do acelerômetro. Os seus parâmetros utilizados são ponteiros que irão setar os valores dos três eixos nos endereços indicados;
  • accel_init: Inicializa o dispositivo do acelerômetro;
  • accel_calibrate: calibra o dispositivo do acelerômetro.

Botões

Módulo indicado pelo nome "KEYS". As funções utilizadas são:

  • KEY_open: Abre o dispositivo dos botões;
  • KEY_read: Lê os dados dos botões. É passado como parâmetro um ponteiro que irá setar os sinais retornados dos botões no endereço indicado. Os sinais coletados não representam o estado atual dos botões, mas, sim, se eles foram pressionados antes da última leitura. Portanto é preciso liberar os resquícios de dados antes de iniciar a lógica do sistema.

Interface do Usuário

A seguir, a interface exibida para o usuário no monitor VGA e as suas possíveis transições, juntamente com os cenários em que o uso dos botões interfere no estado do jogo.

O jogo se inicia com a tela inicial mostrada abaixo. Ela exibe o título do jogo e a opção de iniciar a partida, sendo ela, a única opção disponível. Caso o quarto botão da placa seja pressionado, a partida se inicia.

Transição da tela inicial para a partida

O campo de jogo possui os seguintes elementos: o valor do score atual exibido na parte superior esquerda; as linhas laterais e superior para delimitar a área que a bola pode percorrer; os blocos que devem ser destruídos, com cores variadas no decorrer das fileiras; a bola de jogo; e a barra inferior controlada pelo usuário. Caso o quarto botão da placa seja pressionado, a partida é pausada.

Transição da partida para a partida pausada

É indicado que a partida está pausada pela mensagem do canto superior direito e pela mudança da cor da bola. Além disso, também aparece ao lado a opção que o usuário pode escolher em seguida. Primeiramente aparece a opção de continuar o jogo, indicada pela palavra "play", e caso o quarto botão seja pressionado, é alterada para a opção de sair da partida, indicada pela palavra "exit". O quarto botão altera entre essas duas opções.

Transição da partida pausada com a opção de "play" para a opção de "exit", e vice-versa

Na tela de pause, o terceiro botão seleciona a opção atual, podendo sair da partida ou continuar o jogo.

Transição da partida pausada na opção de "play" para o retorno da partida

Transição da partida pausada na opção de "exit" para o retorno da tela inicial

Quando um bloco é destruído pela bola, ele não aparece mais na tela e sua respectiva pontuação é somada no score.

Ilustração da quebra de um bloco

Se a bola ultrapassar a altura da barra inferior, a partida é encerrada, assim, a tela de derrota é exibida com a frase "game over" e o score alcançado.

Transição da partida para tela de derrota

O uso do quarto botão faz a transição da tela de derrota para a tela inicial.

Transição da tela de derrota para a tela inicial

Caso todos os blocos sejam destruídos, a partida foi ganha. Na tela de vitória, é exibida a frase "you win" e dois foguetes sobem verticalmente.

Transição da partida para a tela de vitória

A tela de vitória possui uma animação contínua de fogos de artifício. Quando chegam em certa altura, os fogos explodem e exibem os traços das explosões. Os fogos continuam surgindo, um por um, enquanto o usuário estiver na tela de vitória.

Início da animação de fogos

Caso o quarto botão seja pressionado, a tela de vitória é encerrada e o usuário volta a tela inicial.

Transição da tela de vitória para a tela inicial

Dinâmica e Regras de Jogo

O objetivo principal do jogo Breakout é destruir todos os blocos que compõem a estrutura do cenário, utilizando uma bolinha. O jogador assume o controle de uma barra para rebater a bolinha e evitar que ela caia no "abismo", representado pela parte inferior da tela. Para garantir uma experiência dinâmica e desafiadora, o jogo conta com uma série de regras que serão apresentadas nesta seção.

Jogabilidade: Controle da Barra

A movimentação da placa é baseada na inclinação da placa DE1-SoC. O jogador deverá posicionar a placa em uma certa inclinação para a direita ou esquerda, o que resultará na movimentação da barra correspondente. Esse controle é realizado através do acelerômetro disponível na placa.

É importante ressaltar que a movimentação da barra está limitada pelas paredes laterais do cenário, ou seja, a barra não pode ultrapassar essas paredes durante o jogo.

Além disso, é crucial entender que a barra não possui uma velocidade fixa. Sua velocidade varia de acordo com o ângulo de inclinação da placa. Quanto maior o ângulo de inclinação, maior será a velocidade da barra, e vice-versa.

Os gifs a seguir ilustram a movimentação da placa e a consequente movimentação da barra de acordo com esses movimentos.

Movimento da barra a partir do movimento da placa

Características da Bola e sua Movimentação

A bola apresenta duas características principais: sua movimentação contínua e suas interações com as estruturas do cenário. Na física do jogo, a bolinha mantém um movimento incessante nos eixos horizontal (x) e vertical (y), exceto em casos específicos nos quais o botão de pausa é acionado.

Quando a bolinha colide com algum objeto no cenário, como paredes laterais, superior, blocos ou a barra controlada pelo jogador, ela é capaz de se refletir a partir do ponto de colisão. Essa reflexão pode ocorrer de três maneiras distintas: inversão de sentido apenas no eixo x, apenas no eixo y, ou simultaneamente nos dois eixos.

Analisando as diferentes colisões com cada objeto do cenário, temos as seguintes características:

Colisão com a Barra

Durante a colisão com a barra, a bolinha pode refletir-se em três direções distintas, dependendo do ponto de impacto. A barra é dividida em três partes: direita, esquerda e centro. Quando a bolinha atinge a parte direita da barra, ela é refletida para a direita; quando atinge a parte esquerda, é refletida para a esquerda; e quando atinge o centro, ocorre uma reflexão perfeita.

Além disso, após a colisão, tanto o ângulo quanto a velocidade da bolinha são alterados. Cada lado da barra oferece quatro velocidades diferentes e ângulos distintos de reflexão, o que adiciona variedade e desafio ao jogo.

Para visualizar essas colisões, são disponibilizadas duas imagens anexas. A primeira imagem ilustra a mudança de direção da bolinha apenas no eixo y, alterando seu ângulo a partir do ponto de colisão. Já a segunda imagem mostra a inversão nos eixos x e y, proporcionando uma mudança significativa na trajetória da bolinha.

Bola colidindo nas 3 zonas da barra e tendo sua direção alterada no eixo y

Bola colidindo nas 3 zonas da barra e tendo sua direção alterada no eixo x e y

Colisão com as Paredes

Durante a colisão com as paredes, a bolinha experimenta uma reflexão perfeita a partir do ponto onde ocorreu a colisão. Em cada caso de colisão com a parede, as seguintes situações são observadas:

  • Colisão com Paredes Laterais: Ao colidir com uma das paredes laterais, a bolinha conserva sua direção no eixo y e inverte o sentido no eixo x.

Bola colidindo com as paredes laterais direita e esquerda, e mudando sua trajetóia

  • Colisão com a Parede Superior: Quando a bolinha colide com a parede superior, ocorre o oposto das paredes laterais: ela mantém sua direção no eixo x e inverte o sentido no eixo y.

Bola colidindo com a paredes superior e mudando sua trajetóia

  • Colisão entre Paredes Superior e Lateral: Se a bolinha colide entre a parede superior e lateral, ocorre a inversão nos dois eixos simultaneamente.

Bola colidindo com a paredes superior e lateral ao mesmo tempo, e mudando sua trajetóia

  • Colisão entre barra e Paredes Laterais: Quando a bolinha colide entre a barra e uma das laterais, também ocorre a inversão nos dois eixos simultaneamente.

Bola colidindo com a parede lateral e a barra, e mudando sua trajetóia

Colisão com os blocos

O último tipo de colisão é com os blocos. Se a colisão ocorre nas laterais, é invertido o eixo x; nas partes superior e inferior, é invertido o eixo y. Adicionalmente, há colisões específicas nas pontas dos blocos, onde o comportamento varia dependendo do movimento da bola (subindo ou descendo) e da presença de blocos adjacentes. Assim, segue algumas imagens para ilustrar essas colisões.

Bola colidindo com as partes laterais do bloco e mudando sua trajetóia

Bola colidindo com a parte superior e inferior do bloco, e mudando sua trajetóia

Bola colidindo com os vértices do bloco e mudando sua trajetória nas três possibilidades

Pontuação

O sistema de pontuação é baseado na quebra de blocos após cada colisão. Cada fileira de blocos possui um valor específico a ser pontuado. Os níveis mais baixos até os superiores possuem as seguintes pontuações progressivas: 1, 3, 5, 7, 9 e 11.

fileira de blocos e seus pontos

Finalização do Jogo

Existem duas condições de finalização do jogo: vitória ou derrota do jogador. A vitória é alcançada quando todos os blocos são quebrados durante a partida. Por outro lado, a derrota ocorre sempre que a bola ultrapassa o nível da barra, resultando em sua queda e encerramento do jogo.

Bola ultrapassando a linha limite do jogo e perdendo o jogo

Algoritmos de Jogo

Para implementar as regras do jogo a nível de software, foram desenvolvidos diversos algoritmos responsáveis por gerenciar o comportamento dos elementos do jogo. Nesta seção, serão apresentadas as sequências responsáveis pela movimentação da bolinha e sua interação com os objetos do cenário.

Algoritmo de Colisão

Este algoritmo permite que a bolinha reconheça os objetos no cenário do jogo. Como todos os objetos têm formato retangular, exceto a bolinha, que é circular, foi desenvolvido um algoritmo clássico de detecção de colisão entre círculo e retângulo.

A lógica do algoritmo baseia-se em comparar um círculo com certo raio ligeiramente maior (raio da bola mais o raio de colisão) e um retângulo de dimensões h e b Inicialmente, é procurado o ponto mais próximo entre o círculo e o retângulo, analisando as dimensões x e y. Esta análise permite considerar apenas os limites do retângulo.

Em seguida, é calculada a distância euclidiana entre a bola e o ponto de impacto utilizando o teorema de Pitágoras, e esse valor é arredondado, já que o jogo é em pixels. Se a distância calculada for menor ou igual ao raio da bola, significa que ocorreu uma colisão, e o algoritmo retorna 1. Caso contrário, retorna 0 para indicar que não houve colisão.

A imagem apresenta um fluxograma do algoritmo, proporcionando uma visão do seu funcionamento. Além disso, fornece uma representação cartesiana para uma compreensão visual mais abrangente.

Fluxograma e visão cartesiana da detecção de colisão entre retângulo e círculo

Algoritmo de Verificação Contínua

Em simulações físicas, a verificação de colisões é um processo contínuo e crucial para garantir a precisão e a fidelidade da simulação. Enquanto a abordagem discreta atualiza a posição dos objetos em intervalos fixos de tempo, a verificação contínua de colisões é mais precisa, evitando problemas como o "efeito de túnel".

No contexto deste projeto, o algoritmo de verificação contínua de colisões é implementado para garantir que as colisões sejam detectadas entre cada intervalo de tempo, mesmo em movimentos rápidos ou objetos pequenos.

Modelo discreto e contínuo de verificação de colisão

O algoritmo de verificação contínua de colisões funciona da seguinte maneira: a partir de um número pré-definido de pontos intermediários entre a posição atual da bola e sua próxima posição, o algoritmo verifica se ocorrerá alguma colisão em cada ponto. Isso é feito ao calcular as coordenadas da bola em cada ponto intermediário e verificar se houve colisão com outros objetos do cenário.

Se uma colisão é detectada em algum ponto intermediário, a bola é movida para a posição onde ocorreu a colisão, e o tipo de colisão é informado para que a reflexão adequada seja realizada na próxima interação. Por outro lado, se nenhum ponto intermediário apresentar colisão, a bola realiza um movimento normal entre os quadros, sem nenhuma reflexão.

Segue uma versão simplificada para facilitar o entendimento do algoritmo: um gráfico de tempo e espaço que ilustra os testes realizados para 10 pontos intermediários em uma velocidade de 8 pixels por quadro, juntamente com uma versão do fluxograma do algoritmo.

Modelo discreto e contínuo de verificação de colisão

Fluxograma do algoritmo de verificação contínua de colisão

Solução Geral do projeto

A solução integral deste sistema demonstra sua capacidade completa de atender a todas as demandas requisitadas. Antes de entrar no loop principal do programa, os periféricos utilizados - VGA, acelerômetro e botões - são inicializados. Além disso, os elementos do jogo são iniciados, atribuindo suas características e posições iniciais. Por fim, a MEF (Máquina de Estados Finitos) da troca de telas é iniciada na tela de menu.

Dentro do loop principal, o sistema busca e exibe qual tela deve ser mostrada com base no estado atual. Após a exibição, o programa verifica se a tela atual é a do jogo. Se não for, verifica se algum botão foi pressionado para realizar a troca de cenário. Caso contrário, a execução retorna ao início do loop principal.

Se o jogo estiver em execução, o sistema lê o acelerômetro para verificar a movimentação da placa. Em seguida, move os objetos do jogo - bola e barra. A movimentação da barra é baseada nos dados do acelerômetro, enquanto a bola se move conforme o algoritmo de verificação contínua.

Após realizar todos os movimentos, o sistema analisa se a bola atingiu algum bloco e, se sim, remove esses blocos. Por fim, verifica se o jogo chegou ao fim. Se não, verifica se houve pressionamento de botão durante os passos anteriores e realiza a troca ou não de telas. Se o jogo terminar, os elementos do jogo são reorganizados para uma nova partida e a tela é alterada para a de vitória ou derrota. Em seguida, o loop principal é executado novamente.

Para uma compreensão mais clara da explicação, apresentamos abaixo um fluxograma detalhando o algoritmo utilizado na solução geral.

Fluxograma da solução geral do problema

Testes Realizados

A seguir, os testes realizados para assegurar o bom funcionamento do sistema.

  • Transição da tela inicial para a partida.

Transição da tela inicial para a partida

  • Colisão da bola com a parte do meio inferior de um bloco, e com a parte do meio da barra, preservando sua direção.

Colisão da bola com o meio inferior do bloco e com o meio da barra

  • Colisão da bola com as paredes laterais e superior.

Colisão da bola com as paredes laterais e superior

  • Colisão da bola com as diferentes partes da barra. Quanto mais a bola se aproxima da lateral, mais rápida será sua velocidade seguinte após a colisão. Colidir com o lado esquerdo direciona a bola para a esquerda, e com o lado direito, para a direita.

Mudança de velocidade e direção da bola dependendo do local que ela colide com a barra

  • Colisão da bola com as laterais dos blocos.

Colisão da bola com as laterais dos blocos

  • Colisão simultânea com dois blocos, na parte inferior e na lateral.

Colisão da bola com dois blocos simultaneamente

  • Colisão da bola com a ponta do bloco.

Colisão da bola com a ponta do bloco

  • Aparecimento da tela de derrota após a bola ultrapassar o limite inferior do campo de jogo. Transição da tela de derrota para a tela inicial.

Transição de tela na perda de jogo

  • Pausando a partida e selecionando as opções de continuar e voltar para a tela inicial.

Opções do estado de pausa

  • Animação da tela de vitória.

Animação da tela de vitória

Conclusão

A implementação do jogo inspirado no clássico Breakout, por meio do código em linguagem C no kit de desenvolvimento DE1-SoC, demonstrou ser uma experiência interativa e envolvente para os jogadores. Durante o processo de desenvolvimento, foram atendidos todos os requisitos estabelecidos, utilizando a arquitetura da placa e seus drivers como base sólida para a criação do jogo e implementação dos algoritmos necessários.

A interação harmoniosa entre o software e o hardware, possibilitada pela placa, permitiu a utilização integrada dos periféricos VGA, acelerômetro e botões, contribuindo para uma experiência de jogo mais imersiva. Os testes realizados evidenciaram a eficiência e confiabilidade do sistema, validando sua capacidade de operar de forma consistente em diversas condições de jogo.

Este projeto, além de alcançar seus objetivos iniciais, proporcionou um aprofundamento significativo dos conhecimentos em sistemas embarcados e arquitetura ARM. Ele capacitou os desenvolvedores a conciliar aspectos tanto de software quanto de hardware, estabelecendo uma base sólida para futuras explorações nas áreas de sistemas digitais e desenvolvimento de software.

Execução do Projeto

Para iniciar o projeto, siga os passos abaixo para obter o código-fonte, compilar o código em C e executa-lo em um dispositivo FPGA DE1-SoC.

Passo 1: Clonar o Repositório

Abra o terminal e execute o seguinte comando para obter o código do repositório:

git clone https://github.com/Samara-Ferreira/PBL03-Breakout-Game.git

Passo 2: Acessar o Diretório e Compilar o Código em C

cd PBL03-Breakout-Game\Modules

Compile e execute o código usando o comando:

make all

Referências

CAMACHO, Karla (2023). Breakout. Disponível em: https://pop.proddigital.com.br/consoles/breakout. Acessado em: 24 de fevereiro de 2024.

RIBEIRO, Cristiano (2018). Avaliação de algoritmos de detecção de colisão em jogos 2D para Android. Disponível em: https://dspace.unipampa.edu.br/bitstream/riu/3328/1/Cristiano%20Daitx%20Ribeiro%202018.pdf. Acessado em: 27 de fevereiro de 2024.

BARREIROS, Emanoel. Colisões entre retângulos e círculos. Disponível em: https://emanoelbarreiros.github.io/game/colisao_circ_rect/. Acessado em: 27 de fevereiro de 2024.

Introduction to the ARM Cortex-A9 Processor. Disponível em: https://github.com/fpgacademy/Tutorials/releases/download/v21.1/ARM_intro_intelfpga.pdf. Acessado em: 27 de fevereiro de 2024.

Using the ARM Generic Interrupt Controller. Disponível em: https://github.com/fpgacademy/Tutorials/releases/download/v21.1/ARM_GIC.pdf. Acessado em: 27 de fevereiro de 2024.

Using ROS* on DE-Series Boards. Disponível em: https://github.com/fpgacademy/Tutorials/releases/download/v21.1/ROS.pdf. Acessado em: 27 de fevereiro de 2024.

Using the Accelerometer on DE-Series Boards. Disponível em: https://github.com/fpgacademy/Tutorials/releases/download/v21.1/Accelerometer.pdf. Acessado em: 27 de fevereiro de 2024.

Accessing HPS Devices from the FPGA. Disponível em: https://github.com/fpgacademy/Tutorials/releases/download/v21.1/Accessing_Hard_Processor_System.pdf. Acessado em: 27 de fevereiro de 2024.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •