Introdução à Programação Orientada a Objetos em Python com Pygame(parte 1)
Lucas Mateus
Posted on September 27, 2023
Resumo
Este guia tem como objetivo simplificar o ensino da programação orientada a objetos de forma lúdica e acessível, usando Python como linguagem de base e o Pygame como ferramenta de apoio. A programação orientada a objetos é uma abordagem crucial para desenvolvedores, pois oferece um meio organizado e eficiente de criar sistemas complexos e reutilizáveis.
Requisitos para compreensão desta publicação:
- Noção de programação estruturada
- Compreensão da linguagem Python
- Biblioteca pygame devidamente instalada no ambiente de desenvolvimento
Programação Orientada a Objetos vs. Programação Estruturada
Na programação estruturada, o programa é dividido em funções ou procedimentos, onde o foco está na sequência de instruções para manipular dados. Já na programação orientada a objetos, o código é estruturado em torno de objetos, que são instâncias de classes que representam entidades do mundo real. Esses objetos contêm dados (atributos) e funções (métodos) que operam nesses dados. A programação orientada a objetos utiliza da reutilização de código e a modelagem mais precisa de sistemas complexos, enquanto a programação estruturada é mais linear e depende de funções independentes para executar tarefas específicas.
O que são classes e objetos?
Classe
Imagine uma classe como um modelo, um conjunto de regras para criar instâncias que seguem esse modelo. Ela é como uma forma que permite a criação de vários objetos, cada um com suas próprias características e funcionalidades, mas todos baseados na mesma estrutura inicial.
Objetos
Se uma classe é a forma de um bolo, um objeto é o próprio bolo. Usando a mesma forma (classe), podemos criar múltiplos bolos (objetos) com diferentes sabores e detalhes, mas todos compartilhando a mesma base estrutural.
Atributos
Atributos são as características de um objeto, ou em termos de programação, os dados associados a esse objeto. Por exemplo, uma classe chamada Bolo pode ter um atributo chamado "sabor". Cada instância dessa classe pode ter um sabor único, como chocolate ou morango. Essas instâncias compartilham o atributo "sabor" da classe, mas cada objeto individual possui um sabor próprio.
Métodos
Os métodos são as ações que um objeto pode realizar, ou seja, as funções que um objeto pode desempenhar. Continuando com a analogia do bolo, imagine que, além de possuir um sabor, um bolo também pode realizar a ação de ser cortado em fatias. Portanto, em nossa classe Bolo, podemos criar um método chamado "cortar" que define como um bolo deve ser dividido em pedaços. Quando aplicamos esse método a um objeto bolo específico, ele segue as instruções da classe para cortar-se em fatias, produzindo fatias de bolo prontas para serem servidas. Cada objeto da classe Bolo tem a capacidade de cortar-se em fatias, mas a ação real de cortar é realizada individualmente por cada objeto quando chamamos o método. Assim, os métodos possibilitam objetos a executarem tarefas específicas, mantendo a consistência e a flexibilidade da lógica de programação orientada a objetos. Em resumo, é uma função porém ela opera em cima dos dados do próprio objeto.
Entendendo o Método construtor e pondo a mão na massa
O método construtor é uma parte fundamental da programação orientada a objetos, em Python ele é representado pelo nome especial __init__
. Ele desempenha um papel crucial na criação de objetos a partir de uma classe. O principal propósito do método construtor é inicializar os atributos de um objeto quando ele é criado. Em resumo o método construtor, é um método que é executado assim que um novo objeto é criado, e é responsável por atribuir dados aos atributos dos objetos.
Falamos tanto na nossa classe Bolo, mas até agora não vimos em código. Agora vamos criar não somente um bolo, como também a forma dele. Em python (e a maioria das demais linguagens de programação) as classes tem a primeira letra maiúscula, e é usado o operador class
para a criação.
class Bolo:
# metodo construtor
def __init__(self, sabor, textura):
# atributos
self.sabor = sabor
self.textura = textura
# metodo fatiar
def fatiar(self, fatias):
print(f'Bolo de `{self.sabor} fatiado em `{fatias} fatias\n')
Como dito anteriormente, um método funciona de forma similar a uma função, logo é possível passar parâmetros para esse métodos, e esses serão os dados que irão ser alocados nos atributos deste objeto, como visto no código.
Mas o que é esse parâmetro "self" que esta sendo passado nos métodos? Em Python, self
é uma convenção usada como o primeiro parâmetro em métodos de uma classe. O objetivo principal do self é representar a instância do objeto atualmente em execução, permitindo o acesso aos atributos e métodos dessa instância dentro dos métodos da classe. Em outras palavras, o self
é a representação de um instância, se eu tenho um objeto bolo1, é como se quando eu chamasse o método, eu passasse o próprio bolo1 como parâmetro, sinalizando que é para operar em cima dos dados daquele objeto específico, iremos ver um método funcionando logo a frente.
Com nossa forma pronta, vamos criar os nosso bolos. Para criar um novo objeto em python basta apenas chamar a classe pelo nome e entre parênteses, passa os parâmetros que são exigidos no construtor.
# Criando um objeto bolo usando o construtor
meu_bolo1 = Bolo('Chocolate', 'Fofa')
meu_bolo2 = Bolo('Morango', 'Molenga')
Pronto, agora temos dois novos objetos vindos da mesma classe, com características distintas. Para acessar métodos e atributos de um objeto basta apenas usar o .
e chamar o atributo, e no caso dos método usar os parênteses, como uma função. Rode o código e veja a mágica acontecer.
# verificando sabores
print(meu_bolo1.sabor)
print(meu_bolo2.sabor)
# Fatiando um bolo
# com o parametro self é como se estivesse ocorrendo algo assim:
# meu_bolo1.fatiar(meu_bolo1, 8)
meu_bolo1.fatiar(8)
E com esses conhecimentos já estamos preparados pra começar o nosso joguinho.
Iniciando o projeto do jogo
A habilidade de abstrair os conceitos abordados é essencial para poder compreender o que está acontecendo em código de agora em diante. Vamos fazer uma réplica do jogo Flappy Bird usando pygame e o que aprendemos até agora. Vamos ver da maneira de maneira mais prática as classes e objetos em funcionamento .
Criando o arquivo de constantes
Existem dados que nunca irão ser mudados no nosso código, logo podemos declara-los como constates, para isso vamos deixa-las em um arquivo separado. Crie um arquivo chamado consts.py e cole o código abaixo. Iremos adicionar mais futuramente, mas por hora o que precisamos já está ai.
# Configurações do jogo
# tamanho da tela
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
# titulo
TITLE = 'Flappy Bird'
# taxa de atualização da tela
FPS = 60
Com nossas constantes definidas podemos usa-las no nosso código para a criação da primeira classe do nosso projeto, que será literalmente a classe do jogo, vamos criar uma classe que contenha com atributos parâmetros importantes para o funcionamento do jogo que está para ser criado. Em seu diretório crie uma classe um arquivo de nome game.py
e cole o o código abaixo.
import pygame
import consts
class Game:
def __init__(self):
# iniciando o pygame
pygame.init()
# criando tela
self.screen = pygame.display.set_mode(
(consts.SCREEN_WIDTH, consts.SCREEN_HEIGHT))
pygame.display.set_caption(consts.TITLE)
self.clock = pygame.time.Clock()
self.running = True
Perceba que o método construtor não recebe nenhum parâmetro, todos os atributos foram definidos dentro da própria classe, lembre que o construtor não precisa nescessariamente receber parâmetros, podemos inicializar os atributos com os dados que quisermos, no caso estamos usando os módulos do pygame. Perceba que o atributo clock
recebe uma classe vinda do pygame, um atributo pode conter qualquer coisa, incluindo outros objetos. Posteriormente iremos interagir com esse atributo novamente.
Precisamos fazer nosso jogo rodar de alguma forma, vamos criar um método que faça isso. na sua classe Game
, faça essas mudanças a seguir.
import pygame
import consts
class Game:
def __init__(self):
# iniciando o pygame
pygame.init()
# criando tela
self.screen = pygame.display.set_mode(
(consts.SCREEN_WIDTH, consts.SCREEN_HEIGHT))
pygame.display.set_caption(consts.TITLE)
self.clock = pygame.time.Clock()
self.running = True
def game_events(self):
# retorna todos os objetos do tipo event
for event in pygame.event.get():
# acessa o atributo type do objeto event
if event.type == pygame.QUIT:
self.running = False
def run(self):
while self.running:
# o metodo tick define os FPS do jogo
self.clock.tick(consts.FPS)
self.game_events()
Perceba que a partir do nosso atributo clock
que é um objeto, chamamos um método dessa classe, método esse que define a quantos frames por segundo nosso jogo irá rodar. Note também que para chamarmos um método da classe, dentro dela mesma, nos utilizamos o self
, já que estamos operando dentro da própria instância. Agora não só estamos criando nossa própria classe, como tambem estamos utilizando outras dentro dela.
def game_events(self):
# retorna todos os objetos do tipo event
for event in pygame.event.get():
# acessa o atributo type do objeto event
if event.type == pygame.QUIT:
self.running = False
Como visto nesse trecho, também estamos buscando dentro do módulo do pygame, todos os objetos do tipo event
, estamos acessando o seu atributo type
, para fazer uma verificação. Com essa verificação agora temos uma opção de fechar a tela de nosso jogo, quando tornamos o atributo responsável por manter o loop do jogo para False
.
Rodando o jogo
Com o que foi feito até então, temos o nosso modelo, porém ainda não fizemos nosso bolo. Em seu diretório crie um arquivo chamado main.py
e cole o seguinte código e execute-o.
import game
if __name__ == "__main__":
my_game = game.Game()
my_game.run()
Em sua tela deve estar algo similar a isso:
Ainda não temos nada além uma tela vazia, porém ai está! Essa tela vazia é o nosso objeto! Os métodos que criamos estão sendo executados em tempo real! O nome na nossa guia é o atributo que definimos lá no começo! Até mesmo se fecharmos essa simples tela sem nada, vai ser um método que criamos que está sendo executado. Tudo que estamos vendo compõe o nosso objeto mygame
, que vem da classe game
que criamos, e ainda tem muito mais por vir.
Considerações finais
Esse é só o começo do nosso projeto, ainda há muito a ser feito, e muito conhecimento pra ser aprendido. Obrigado por chegar até aqui comigo e espero que possa me acompanhar nos próximos capítulos desse projeto.
Caso queira ver o progresso do código, ele está no meu perfil do github, sinta-se a vontade para opinar e contribuir.
ATÉ A PROXIMA
Posted on September 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
September 27, 2023