Archive

Posts Tagged ‘Games’

Iuna Capoeira

August 3rd, 2010

Nossa… faz mais de seis meses que terminei minha pós, e ainda não postei aqui no blog o resultado do trabalho!! Que vergonha… mas é que as coisas estão meio corridas.

Bem, o projeto era um jogo de capoeira, porém não um jogo de luta, e sim um jogo de ritmo. O demo do jogo ficou pronto, embora ainda longe do que esperávamos (eu e o Guilherme Muniz, grande cara e colega!).

Conseguimos cumprir bem certos pontos que julgávamos essenciais como fluidez nas animações, e dinamismo do gameplay, e uma trilha sonora moderna, sem muitos clichês.

Embora alguns pontos ficaram mais fracos. Não gostei da arte 3D (fui eu que fiz), e com relação ao elemento de interface que indica a marcação do ritmo, também deve ser melhorado!

Estou trabalhando para portar esse demo para o iPhone, usando o Unity3D, e enfim concluir o jogo por completo. E chamar um bom artista 3D para fazer uma arte melhor :)

O demo foi feito com o Panda3D. Que se mostrou uma ótima ferramenta! Especialmente para suprir as necessidades que antevimos como críticas. Uma delas é a variedade de soluções para se manipular e controlar as animações de personagens. Comparando o Panda3D e o Unity3D(versão 2.6) nesse requisito… o Panda3D dá de 10×0! Tanto na facilidade de uso, quanto nos resultados. Espero que na versão 3 o Unity3D melhore.

abraço,

Portifólio , , ,

Aula 2 - GameCultura - Panda3D

January 11th, 2009

Na segunda aula do curso a idéia é começar a colocar interatividade nos objetos do game. Mas colocar interatividade nesses elementos a partir do código gerado na primeira aula, seria o fim do mundo, porque ficaria uma ‘zona’ o nosso código; Então decidi colocar tudo bonitinho em classes e seus objetos :)  …sim seria possível colocar tal interatividade sem uso de objetos, mas além de ficar uma ‘zona’, eu pergunto, não parece natural criar objetos para um jogo, uma vez que em um jogo, os objetos possuem suas ações? Para mim, a resposta é sim!

Um cara chamado Mark Guzdial, escreveu o seguinte (sobre POO): “Objetos possuem duas coisas: Objetos sabem coisas; Objetos podem fazer coisas”, isso me parece cair como uma luva para jogos :) Dessa forma começaremos a organizar nosso código como classes para nossos objetos do jogo.

 

Iniciantes: (caso você conheça orientação a objetos pule este trecho)

Você iniciante, que pode estar com medo de POO, digo que não se preocupe, a coisa não é tão feia, na verdade é muito mais simples do que se pode imaginar, e para ajudar você eu não usarei termos técnicos que não sejam extremamente necessários, e quando necessários farei de forma que vc os ache legal… espero :)

Para você entender isso melhor é simples, basta pensar naturalmente. Por exemplo, um cachorro late quando houve um barulho incomum, certo!? Então, para transformar isso em programação, nós temos que criar um tipo de objeto que ao ‘ouvir’ um evento incomum execute uma ação de latir. E essas ações nós iremos escrever em uma ‘classe’ que vai conter todas essas ‘instruções’, e só depois quando criamos o objeto é que elas irão acontecer… lembre-se disso e observe o que faremos adiante.

 

Mão na massa: (todos… :D )

Nós podemos começar com base no código da primeira aula. Que está assim:

arena = loader.loadModel(‘../res/eggs/plataformaBase’)
arena.setScale(4)
arena.reparentTo(render)
arena.setPos(20,30,5)

 

Nossa idéia é transformar os elementos do jogo em objetos, certo? Bem, a arena é um elemento importantíssimo do jogo, então vamos transformá-la em um objeto, para tal, teremos que criar uma classe, que terá apenas uma função, a de carregar a nossa arena no ‘render’ do Panda, e definir algumas propriedades. Vamos lá:

class Arena():
    def __init__(self):
        self.carregaModelo()

    def carregaModelo(self):
        self.arena = loader.loadModel(‘../res/eggs/plataformaBase’)
        self.arena.setScale(4)
        self.arena.reparentTo(render)
        self.arena.setPos(20,30,5)

 

Pronto! Já temos a nossa classe pronta. Mas vamos dar uma olhada no que fizemos:

1- Primeiro criamos a classe com nome Arena

class Arena():

2- Definimos a iniciação da classe (ou também chamado método construtor), ele é sempre obrigatório quando trabalhamos com classes:

            def __init__(self):

3-  No __init__ nós chamamos a função que irá fazer o trabalho de carregar os modelos 3D e setar as propriedade que queremos:

                  self.carregaModelo()

4- Criamos a função que fará o trabalho:

            def carregaModelo(self):

5- O conteúdo da função você já conhece, com a exceção do uso do ’self’:

          self.arena = loader.loadModel(‘../res/eggs/plataformaBase’)
          self.arena.setScale(4)
          self.arena.reparentTo(render)
          self.arena.setPos(20,30,5)

O ’self’ é sempre algo que permite muitas conversas e debates, mas de forma sucinta: o ’self’ serve para que o objeto, busque as informações relativas, nele mesmo.

 

Agora resta instanciar o objeto, ou seja, criar o objeto:

objetoArena = Arena()

e então:

run()

obs.: Não esqueça dos ‘imports’, são os mesmos da primeira aula!

 

Execute o programa, e você terá a arena na tela.

arena

Ainda na classe Arena, nós podemos carregar o papel de parede, veja só:

class Arena(DirectObject):
    def __init__(self):
        self.carregaModelo()

    def carregaModelo(self):
        self.arena = loader.loadModel(‘../res/eggs/plataformaBase’)
        self.arena.setScale(4)
        self.arena.reparentTo(render)
        self.arena.setPos(20,30,5)

        self.parede = loader.loadModel(‘../res/eggs/papelParede’)
        self.parede.reparentTo(render)
        self.parede.setScale(1)
        self.parede.setPos(-5, 60, -2)

Isso vai colocar um céu no nosso jogo :)

Agora vamos pensar no objeto Avatar. Para esse pequeno demo, o avatar vai ter poucas ações mas o suficiente para aprender coisas importantes, eu montei uma relação de ações e propriedades (coisas que ele vai fazer, e coisas que ele vai saber) para esse avatar; Embora não vamos fazer tudo ao mesmo tempo, é bom termos uma panorâmica do todo:

Ações X Propriedades 
- se move para direita e esquerda                             

- pula

- colide com coisas(plataforma, Energia, obstáculos)

- sensível aos eventos de teclado

 

  - saúde                              

- velocidade

- altura do pulo

Além é claro de coisas básicas que são invisíveis ao jogador, tipo, carregar o próprio modelo. Então vamos começar por coisas básicas… vamos fazer nossa classe para o futuro ‘objetoAvatar’, começando por fazê-la carregar o modelo 3D:

class Avatar(DirectObject):
    def __init__(self):
        ‘Metodo construtor da classe Avatar.
        - Define os estados do Avatar: self.estados
        ‘

        self.estados = {‘direita’:0, ‘esquerda’:0, ‘pulo’:0}

        self.carregaAtor()

    def carregaAtor(self):
        ‘Carrega o modelo personagem.egg no NodePath ‘persona
        ‘

        self.persona = render.attachNewNode(‘persona’)
        self.personaActor = Actor(‘../res/eggs/personagem.egg’,
                             {‘idle’:‘../res/eggs/personagem-parado’,
                              ‘run’ :‘../res/eggs/personagem-correr’,
                              ‘jump’:‘../res/eggs/personagem-pular’}
                             )
        self.personaActor.setScale(.3)
        self.personaActor.loop(‘idle’)
        self.personaActor.reparentTo(self.persona)
        self.personaActor.setPos(0,0,0)
        self.persona.setPos(0,30,0)
        self.persona.setH(90)

 

Resumindo, 1: criamos uma classe chamada Avatar; 2: criamos um método de inicialização, onde chamamos a função que carrega o nosso modelo 3D; 3: criamos a função que carrega o modelo 3D.

Se você reparou bem na função carregaAtor(), reparou uma pequena mudança no procedimento que fizemos na aula 1. Na aula 1, nós criamos um nó chamado ‘persona’ ao grafo de cena (ligado ao render), e nesse nó estava no nosso modelo 3D, vejo o esquema abaixo:

esquema de grafo de cena

Mas agora a coisa mudou um pouquinho, criamos um nó chamado ‘persona’ ao render, e ao nó persona criamos um nó ‘personaActor’, que esse sim guarda o modelo 3D. Isso irá nos permitir maior flexibilidade no futuro, e uma estrutura mais organizada. Ah, aquela variável self.estados, que na verdade é um dicionário, servirá para fazermos nosso avatar se mover.

Outra pequena mudança: class Avatar(DirectObject):  reparou nisso? o que é esse DirectObject? Bem esse DirectObject é o que permitirá nosso avatar receber os inputs de teclado, e outros eventos! :) mas que por hora não está funcionando… mas, lembre-se dele.

Agora é criar o objeto baseado na classe Avatar, e testar; Então após o término da classe, e antes do comando run():

objetoAvatar = Avatar()

tela do jogo

 

Eventos e Tarefas (Task)

Agora vamos trabalhar muito na classe Avatar, implementando as funcionalidades principais.

A primeira das funcionalidades serão os inputs de teclado, e movimentação, e para tornar isso possível iremos falar sobre duas coisas super importantes no Panda3D, os Eventos e as tarefas (Tasks).

Eventos podem ser entendidos como mensagens que ‘circulam’ pelo sistema, e alguns objetos, ao receberem esses eventos podem reagir a ele, com alguma ação. Esses eventos podem ser gerados de diversas formas, via input de teclado, colisões, ou serem criados ao gosto do desenvolvedor.

Para o Panda3D, os inputs de teclado serão sempre eventos, sempre! É um padrão do sistema, sempre que uma tecla é pressionada gera um evento, basta que um objeto esteja apto a tratar esse evento. É exatamente o que temos que fazer para, por exemplo, tornar possível a movimentação do nosso personagem. Está lembrado do DirectObject? class Avatar(DirectObject): lembra que isso é o que permitirá a uma classe tratar eventos.

Tarefas por sua vez são funções que serão executadas todos os frames. Por exemplo, se um elemento do jogo tem que se mover constantemente, deve haver uma função que faça com que ele se mova, e tal função deve ser definida como tarefa, para que ela executada a cada frame.

A lógica da movimentação do nosso avatar será feita em duas partes, primeira: haverá uma tarefa que irá mover nosso personagem, dependendo dos valores do dicionário self.estados;  segunda: faremos com que a classe Avatar ao receber um evento das teclas direcionais do teclado, modifique os valores do dicionário self.estados.

esquema da lógica para mover o personagem

Para colocar isso em prática temos que criar algumas funções, uma para capturar os eventos, uma para alterar o self.estados, uma para mover o avatar:

 

class Avatar(DirectObject):
    def __init__(self):
        ‘Metodo construtor da classe Avatar.
        - Define os estados do Avatar: self.estados
        ‘

        self.estados = {‘direita’:0, ‘esquerda’:0, ‘pulo’:0}

        self.carregaAtor()
        self.capturaEventos()

        taskMgr.add( self.mover, ‘moverPersona’ )

    def carregaAtor(self):
        ‘Carrega o modelo personagem.egg no NodePath ‘persona
        ‘

        self.persona = render.attachNewNode(‘persona’)
        self.personaActor = Actor(‘../res/eggs/personagem.egg’,
                             {‘idle’:‘../res/eggs/personagem-parado’,
                              ‘run’ :‘../res/eggs/personagem-correr’,
                              ‘jump’:‘../res/eggs/personagem-pular’}
                             )
        self.personaActor.setScale(.3)
        self.personaActor.loop(‘idle’)
        self.personaActor.reparentTo(self.persona)
        self.personaActor.setPos(0,0,0)
        self.persona.setPos(0,30,0)
        self.persona.setH(90)

    def capturaEventos(self):
        ‘Tratamento de eventos INPUT
        arrow_right = direita
        arrow_left = esquerda
        ‘

        self.accept( ‘arrow_right’, self.alteraEstado, [‘direita’,1] )
        self.accept( ‘arrow_left’, self.alteraEstado, [‘esquerda’,1] )
        self.accept( ‘arrow_right-up’, self.alteraEstado, [‘direita’,0] )
        self.accept( ‘arrow_left-up’, self.alteraEstado, [‘esquerda’,0] )

    def alteraEstado(self, chave, valor):
        ‘Modifica os estados de acao, de acordo com os valores recebidos
        acao ->; estados: direita, esquerda
        valor ->; valor que sera atribuido a acao
        ‘

        self.estados[chave] = valor

    def mover(self, task):
        ‘tarefa responsavel pela movimentacao do personagem
        ‘

        #DIREITA
        if (self.estados[‘direita’] != 0):
            self.persona.setX( self.persona.getX()+0.1 )
        #ESQUERDA
        if (self.estados[‘esquerda’] !=0):
            self.persona.setX( self.persona.getX()-0.1 )

        return Task.cont

 

Vamos aos detalhes. Primeiro vamos observar aquela primeira parte da lógica, onde uma função (tipo task) fará nosso personagem se mover de acordo com valores do ‘estados’. Essa é a função mover()! Observe a chamada dessa função lá no __init__:

taskMgr.add( self.mover, ‘moverPersona’ )

O taskMgr, é um objeto ‘global’ no sistema Panda3D, que irá gerenciar todas as tarefas do jogo, afinal cada elemento do jogo pode ter sua tarefa… o que nós fazemos aqui foi dizer a esse gerenciador (taskMgr) para executar a função self.mover (do avatar) todos os frames. Agora na função mover(), propriamente dita, repare que ela está recebendo uma variável task -> def mover(self, task): <- ISSO É OBRIGATÓRIO! Sempre que uma função seja definida como tarefa, ela deve receber a variável de tarefa (no caso task), isso se explica, por exemplo na última linha da função -> return Task.cont <- isso quer dizer que essa tarefa deve ser novamente executada no próximo frame (significa: tarefa.continue  :) ). Sim, a execução dessas tarefas podem ser largamente personalizadas, dê uma olhada aqui.

Bem, a lógica interna da função mover(), está bem simples. Os valores do self.estado, começam todos com 0(zero), e dentro da função se o estado direita for diferente de 0(zero), ele altera a coordenada X em 0.1 positivo, o que dará a sensação do personagem se mover para a direita. E logo depois a mesma lógica é aplicada para o mover para a esquerda.

Agora a segunda parte da lógica, onde o evento do teclado será capturado, e acionará uma alteração nos valores do dicionário. A captura dos eventos, é feita na função capturaEventos() … a estrutura para isso é muito simples, é o comando accept():

self.accept( ‘nome_do_evento’, funçao_que_trata_Evento, [parametros] )

No caso selecionamos os eventos ‘arrow_left’, ‘arrow_right’ que são disparados quando as teclas são pressionadas, e os eventos ‘arrow_left-up’ e ‘arrow_right-up’ que acontecem quando as mesmas teclas são ’soltas’.

self.accept( ‘arrow_right’, self.alteraEstado, [‘direita’, 1] )

Então o que fizemos foi, quando ocorrem o evento ‘arrow_right’, disparamos a função alteraEstado() para trabalhar com os parâmetros ‘direita’, e 1.

A função alteraEstado(), apenas tem o trabalho de alterar os valores do dicionário (ou…),  recebendo a informação de qual chave alterar, e o valor a ser atualizado, só.

Simples não!? Agora você pode testar o programa e ver ele funcionar com o nosso avatar se movendo para os lados.

Na próxima aula vamos falar de colisões, e de como tratar os eventos gerados por elas.

Aqui está o arquivo final desta aula.

Games, Panda3D , ,

Jogos, significações e sociedade

October 26th, 2008

Esse foi o título do meu artigo sobre games e sociedade… tema do meu primeiro post aqui no blog.

Demorei bastante para atualizar o blog, porque estava envolvido com coisas super urgentes. :P

Bem, o artigo não ficou exatamente como eu gostaria. Não tive tempo para explorar um monte de outras coisas que dariam maior profundidade à análise. Mas quem leu até agora gostou. :)

Este é o link para você baixar o artigo. Abaixo coloco o resumo do artigo para você ler e decidir se vale a pena fazer o download, ou não.

Abstract
Este artigo tem por objetivo demonstrar que jogos
eletrônicos espelham necessidades primitivas do ser
humano que nos acompanham desde os princípios da
nossa evolução. Para tal demonstração, percorreremos
a história de nossa evolução, observando a evolução de
nossa vida social pelas lentes da biologia, antropologia
e sociologia, pontuando momentos onde os jogos
exercem papel fundamental para a construção da nossa
sociedade.
Keywords: socialização, antropologia cultural, games,
significados
Contatos do Autor: barbeirovsk [at] gmail [dot] com

Resumo
O ser humano deriva de uma linhagem de primatas de
aproximadamente três  milhões de anos, durante a
evolução daquele primata mudanças não só físicas
ele desenvolveu grande parte de sua cultura, e a
necessidade de trabalho em grupo na busca de
alimentos.
Embora a caça tenha deixado de ser um padrão da
busca de alimentos, ela deixou grandes marcas na
nossa cultura, a tal ponto que foi re-significada e hoje
encontramos suas características principais em jogos
modernos. A maior razão dessa re-significação, talvez
tenha se dado num intuito de manter os indivíduos
humanos vivendo em sociedade. E recordar hábito
antigos, especialmente os que tornam os homens
dependentes uns dos outros, se tornaria essencial com
o surgimento de cidades.
Os jogos, como re-significação da caça, proporcionam
ao indivíduo grande vivência de seus instintos, e
canalizando-os para um evento, permite a sociedade
criar uma identidade, um modus operandi coletivo.
Dessa forma os jogos eletrônicos se tornaram mais um
elemento dentro desse mosaico de re-significações
existentes na nossa cultura, nos permitindo vivenciar
de novas formas o que ainda não vivenciamos.

É isso,

abraço.

Games , , , ,

Socialização em Games

July 1st, 2008

Por conta do meu curso de pós-graduação, eu estou me preparando para escrever um artigo sobre a socialização que acontece em torno dos games.

Esse comportamento me chama bastante a atenção. Porque que geralmente se prefere jogar quando se está em grupo? Porque é tão bacana ir a uma lan house?

Bem, algumas formas de explicação eu tenho na ponta da língua. Mas, neste artigo, vou dar um enfoque especial nas razões biológicas disso acontecer.

Para tanto estou lendo alguns livros e artigos. E já vou recomendar três leituras para quem esteja interessado.

1. “A árvore do conhecimento”, dos biólogos chilenos Humberto Maturana, e Francisco Varela.

2. “The Naked ape”, do biólogo inglês Desmond Morris.

3. “Entre games e folgações: apontamentos de uma antropóloga na lan house”, de Vanessa Andrade Pereira.

A árvore do conhecimento, é um livro excepcional, deveria vir da maternidade quando nasce o bebê, como uma documentação da classe homo sapiens. No livro os autores falam dos princípios da vida, da organização das células, e vão narrando o processo evolutivo dos seres pluri-celulares até chegar a nossa capacidade cognitiva. É um livro que deveria ser de leitura obrigatória de todos os seres humanos.

The Naked ape, segue uma linha semelhante, mas com enfoque no comportamento humano, e no porque nós humanos desenvolvemos nossos comportamentos, tudo com uma base evolutiva do ser humano.

Entre games e folgações, é na verdade um poster, onde Vanessa Pereira fala sobre sua inicial pesquisa sobre as relações sociais que se desenvolveram em uma lan house de Porto Alegre. Esse artigo é fácil de se achar pelo Google, ele está hospedado no Scielo.

Games , , , ,