Jogo que iremos desenvolver: Smash! |
Hoje começaremos com uma série de tutoriais sobre desenvolvimento de jogos/games para Android. Para isso iremos construir juntos, passo a passo, o jogo que estou chamando de Smash! Nessa primeira parte aprenderemos como fazer os personagens, e o background utilizando a classe Sprite.
O jogo é bastante simples: há os personagens rosas e os dourados. O objetivo do jogador é derrotar todos os rosas (clicando neles) sem clicar nos dourados, no mínimo de tempo possível. A medida que se avança nas fases os personagens ficam mais rápidos.
Iremos utilizar como base para o desenvolvimento o nosso Android Game Engine que estamos desenvolvendo aqui no blog. Iremos usar a 1ª versão dele, que tem pouca coisa mas o suficiente para criar esse jogo. Se você quer saber como funciona essa engine, quer entender como o jogo roda, acesse os tutoriais sobre ele aqui.
Então vamos começar. Crie um novo projeto com as suas preferências. A primeira coisa a se fazer é adicionar o Android Game Engine no projeto. Isso é simples. Primeiro crie uma pasta "libs" na raiz do seu projeto (junto com src, res...) e nessa pasta coloque esse aquivo. Agora vá no eclipse, abra essa pasta (se ainda não apareceu no Package Explorer do eclipse de um F5 que irá aparecer), dê um clique direito no arquivo que adicionamos (AndroidGameEngine.jar) e vá em Build Path -> Add to Build Path como mostra a figura:
Adicionando a biblioteca do Android Game Engine ao projeto. |
Feito isso vamos começar a codificação do jogo de fato. Vamos começar com o sprite do personagem dourado, chamado de Gold, por ser bastante simples. Ele apenas vai ficar rodando o cenário, e não há alteração na animação. Ele irá estender a classe Sprite:
package com.tutoriandroid.games.smash;
import java.util.Random;
import android.graphics.Bitmap;
import com.gdacarv.engine.androidgame.Sprite;
public class Gold extends Sprite {
public int speedX, speedY;
public Gold(int x, int y, Random random, Bitmap bmp, int bmp_rows, int bmp_columns) {
super(bmp, bmp_rows, bmp_columns);
setAnimation(ANIM_GO); // Seta a animação apenas como "ida" (ciclíca).
speedX = random.nextInt(7) - 3; //Velocidade horizontal de -3 a 3.
speedY = random.nextInt(7) - 3; //Velocidade vertical de -3 a 3.
this.x = x;
this.y = y;
}
@Override
public void update() { // Anda.
super.update();
x += speedX;
y += speedY;
}
}
Bem simples não? O construtor recebe como parâmetros a posição (x, y), uma instância para gerar números randômicos (poderia criar uma nova dentro do construtor, mas acho melhor utilizar a mesma para todas as instâncias), a imagem em Bitmap, e a quantidade de linhas e colunas de frames dessa imagem.
Vamos então partir para o sprite do personagem rosa, chamado de Pink, que é um pouco mais complexo por envolver diferentes animações e tipo de movimentação:
package com.tutoriandroid.games.smash;
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Paint;
import com.gdacarv.engine.androidgame.Sprite;
public class Pink extends Sprite {
public int speed = 1; // Velocidade da movimentação/animação.
public byte direction = 0; // Direção da movimentação/animação.
private boolean dying = false, dead = false;
protected byte animationSpeedControl = 0;
public Pink(int x, int y, Random random, Bitmap bmp, int bmp_rows, int bmp_columns) {
super(bmp, bmp_rows, bmp_columns);
direction = (byte) random.nextInt(8); // Direção aleatória.
int frame = 1 + direction*3; // Seta o frame inicial para a direção
setAnimation(frame, frame, frame+3, ANIM_GOBACK);
this.x = x;
this.y = y;
}
@Override
public void update() {
animationSpeedControl++; // Esta versão do Android Game Engine não
if(animationSpeedControl >= 6 - speed){ // suporta mudança na
super.update(); // velocidade da animação, então foi feito
animationSpeedControl = 0; // esse hack para diminuir a
} // velocidade, que estava muito rápida.
if(!dying){ // Se não está morrendo, anda na direção.
x += direction % 4 > 0 ? direction > 4 ? -speed : speed : 0;
y += Math.abs((direction-2) % 4) > 0 ? direction > 6 || direction < 2 ? speed : -speed : 0;
}
else{ // Se está morrendo, aumenta a transparência até ficar invisível.
int alpha = mPaint.getAlpha();
if(alpha <= 25)
dead = true;
else
mPaint.setAlpha(alpha-10);
}
}
public void changeDirection(byte direct){ // Muda a direção e muda a animação de acordo.
direction = direct;
int frame = 1 + direction*3;
setAnimation(frame, frame, frame+3, ANIM_GOBACK);
}
public void kill(){ // Função que será chamada quando o jogador clicar no Pink.
dying = true;
setAnimation(0, 0, 1, ANIM_STOP);
mPaint = new Paint();
}
}
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Paint;
import com.gdacarv.engine.androidgame.Sprite;
public class Pink extends Sprite {
public int speed = 1; // Velocidade da movimentação/animação.
public byte direction = 0; // Direção da movimentação/animação.
private boolean dying = false, dead = false;
protected byte animationSpeedControl = 0;
public Pink(int x, int y, Random random, Bitmap bmp, int bmp_rows, int bmp_columns) {
super(bmp, bmp_rows, bmp_columns);
direction = (byte) random.nextInt(8); // Direção aleatória.
int frame = 1 + direction*3; // Seta o frame inicial para a direção
setAnimation(frame, frame, frame+3, ANIM_GOBACK);
this.x = x;
this.y = y;
}
@Override
public void update() {
animationSpeedControl++; // Esta versão do Android Game Engine não
if(animationSpeedControl >= 6 - speed){ // suporta mudança na
super.update(); // velocidade da animação, então foi feito
animationSpeedControl = 0; // esse hack para diminuir a
} // velocidade, que estava muito rápida.
if(!dying){ // Se não está morrendo, anda na direção.
x += direction % 4 > 0 ? direction > 4 ? -speed : speed : 0;
y += Math.abs((direction-2) % 4) > 0 ? direction > 6 || direction < 2 ? speed : -speed : 0;
}
else{ // Se está morrendo, aumenta a transparência até ficar invisível.
int alpha = mPaint.getAlpha();
if(alpha <= 25)
dead = true;
else
mPaint.setAlpha(alpha-10);
}
}
public void changeDirection(byte direct){ // Muda a direção e muda a animação de acordo.
direction = direct;
int frame = 1 + direction*3;
setAnimation(frame, frame, frame+3, ANIM_GOBACK);
}
public void kill(){ // Função que será chamada quando o jogador clicar no Pink.
dying = true;
setAnimation(0, 0, 1, ANIM_STOP);
mPaint = new Paint();
}
}
Nota para o hack que fiz para poder alterar a velocidade da animação, pois tava muito rápida. Diferente do Gold, esse sprite não usa speedX e speedY, ele usa um speed geral e define sua direção entre as oito possíveis. Cada valor de 0 a 7, que a variável direction pode assumir tem o seguinte significado:
Direções assumidas por Pink |
Ainda falta o background mas isso mostrarei depois. Vamos agora fazer nossa GameView para, pelo menos, mostrar nossas Sprites andando pelo cenário:
package com.tutoriandroid.games.smash;
import java.util.ArrayList;
import java.util.Random;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.MotionEvent;
import com.gdacarv.engine.androidgame.GameView;
public class MainGameView extends GameView {
protected int level = 0, score = 0;
protected ArrayList<Pink> pinks; //Lista dos Pinks.
protected ArrayList<Gold> golds; //Lista dos Golds.
public MainGameView(Context context) {
super(context);
}
@Override
protected void onLoad() {
pinks = new ArrayList<Pink>();
golds = new ArrayList<Gold>();
Random random = new Random();
Resources res = getResources();
Bitmap bitmapPink = BitmapFactory.decodeResource(res, R.drawable.pink);
Bitmap bitmapGold = BitmapFactory.decodeResource(res, R.drawable.gold_head);
int limitPinkX = getWidth()-bitmapPink.getWidth()/6, // Define os limites da tela
limitPinkY = getHeight()-bitmapPink.getHeight()/5, // que os pinks e golds podem
limitGoldX = getWidth()-bitmapGold.getWidth()/8, // aparecer inicialmente.
limitGoldY = getHeight()-bitmapGold.getHeight();
for(int i = 0; i < 10; i++)
pinks.add(new Pink(random.nextInt(limitPinkX), random.nextInt(limitPinkY), random, bitmapPink, 5, 6));
for(int i = 0; i < 10; i++)
golds.add(new Gold(random.nextInt(limitGoldX), random.nextInt(limitGoldY), random, bitmapGold, 1, 8));
mSprites.addAll(pinks); // Adiciona Pinks e Golds a lista de Sprites para serem
mSprites.addAll(golds); // desenhados e atualizados automaticamente.
}
@Override
public void update() {
super.update();
for(Pink pink : pinks) // Para cada Pink, verifica se ele chegou nas bordas da tela e
if(pink.x < 0) // muda de direção caso ocorra.
pink.changeDirection((byte) (4 - pink.direction % 4));
else if(pink.x > getWidth()-pink.width)
pink.changeDirection((byte) (8 - pink.direction));
else if(pink.y < 0)
pink.changeDirection((byte) ((12 - pink.direction) % 8));
else if(pink.y > getHeight()-pink.height)
pink.changeDirection((byte) (5 - (pink.direction+1) % 8));
for(Gold gold : golds)
// Para cada Gold, verifica se ele chegou nas bordas da tela e
if(gold.x < 0 || gold.x > getWidth()-gold.width)
// muda de direção caso ocorra.
gold.speedX *= -1;
else if(gold.y < 0 || gold.y > getHeight()-gold.height)
gold.speedY *= -1;
}
}
Se tudo estiver certo, dará erro apenas acusando a falta de R.drawable.pink e R.drawable.gold_head. Basta adicionar essas duas imagens na sua pasta res/drawable-hdpi:
gold_head.png |
pink.png |
Para testar o projeto, basta ir na sua Activity principal e mudar o setContentView para:
setContentView(new MainGameView(this));
Adicionalmente, se quiser pode deletar o res/layout/main.xml pois ele não será usado. Se tudo der certo você poderá executar e ver seus Pinks e Golds rodando na tela de maneira satisfatória, como na imagem:
Sprites andando |
Agora vamos então colocar um background. Uma solução bem simples é pegar uma imagem grande e desenhar no fundo da tela, mas ai você pode ter problema por o tamanho da tela não ser fixo, e sempre terá o mesmo background. Então escolhi usar uma imagem pequena, com 4 tiles, e construir o background dinamicamente aleatoriamente usando o tamanho da tela para isso.
background.png |
E imagem a ser utilizada é essa:
E a minha classe Background é essa:
package com.tutoriandroid.games.smash;
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import com.gdacarv.engine.androidgame.Sprite;
public class Background extends Sprite {
private Bitmap mBitmap; // O Bitmap final (background montado).
public Background(Random random, int stageWidth, int stageHeigth, Bitmap bmp) {
super(bmp);
mBitmap = Bitmap.createBitmap(stageWidth, stageHeigth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mBitmap); // Usa-se um canvas para desenhar no Bitmap.
Rect source = new Rect(0, 0, 32, 32); // Preenche o fundo todo com o primeiro tile
Rect destiny = new Rect();
for(int i = 0; i < canvas.getWidth(); i += 32){
destiny.right = (destiny.left = i) + 32;
for(int j = 0; j < canvas.getHeight(); j += 32){
destiny.bottom = (destiny.top = j) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
}
int tilesX = stageWidth/32 + 1, // Preenche alguns espaços aleatórios com grama alta.
tilesY = stageHeigth/32 + 1,
qts;
qts = (int) (random.nextInt((int) (tilesX*tilesY*0.3f))+tilesX*tilesY*0.1f);
source.right = (source.left = 32) + 32;
for(int i = 0; i < qts; i++){
destiny.right = (destiny.left = random.nextInt(tilesX)*32) + 32;
destiny.bottom = (destiny.top = random.nextInt(tilesY)*32) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
qts = (int) (random.nextInt((int) (tilesX*tilesY*0.1f))+tilesX*tilesY*0.05f);
source.right = (source.left = 64) + 32;// Preenche alguns espaços aleatórios com plantas.
for(int i = 0; i < qts; i++){
destiny.right = (destiny.left = random.nextInt(tilesX)*32) + 32;
destiny.bottom = (destiny.top = random.nextInt(tilesY)*32) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
qts = (int) (random.nextInt((int) (tilesX*tilesY*0.1f))+tilesX*tilesY*0.05f);
source.right = (source.left = 96) + 32;// Preenche alguns espaços aleatórios com flores.
for(int i = 0; i < qts; i++){
destiny.right = (destiny.left = random.nextInt(tilesX)*32) + 32;
destiny.bottom = (destiny.top = random.nextInt(tilesY)*32) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, null); // Substitui o onDraw original para desenhar o Bitmap montado.
}
}
import java.util.Random;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import com.gdacarv.engine.androidgame.Sprite;
public class Background extends Sprite {
private Bitmap mBitmap; // O Bitmap final (background montado).
public Background(Random random, int stageWidth, int stageHeigth, Bitmap bmp) {
super(bmp);
mBitmap = Bitmap.createBitmap(stageWidth, stageHeigth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mBitmap); // Usa-se um canvas para desenhar no Bitmap.
Rect source = new Rect(0, 0, 32, 32); // Preenche o fundo todo com o primeiro tile
Rect destiny = new Rect();
for(int i = 0; i < canvas.getWidth(); i += 32){
destiny.right = (destiny.left = i) + 32;
for(int j = 0; j < canvas.getHeight(); j += 32){
destiny.bottom = (destiny.top = j) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
}
int tilesX = stageWidth/32 + 1, // Preenche alguns espaços aleatórios com grama alta.
tilesY = stageHeigth/32 + 1,
qts;
qts = (int) (random.nextInt((int) (tilesX*tilesY*0.3f))+tilesX*tilesY*0.1f);
source.right = (source.left = 32) + 32;
for(int i = 0; i < qts; i++){
destiny.right = (destiny.left = random.nextInt(tilesX)*32) + 32;
destiny.bottom = (destiny.top = random.nextInt(tilesY)*32) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
qts = (int) (random.nextInt((int) (tilesX*tilesY*0.1f))+tilesX*tilesY*0.05f);
source.right = (source.left = 64) + 32;// Preenche alguns espaços aleatórios com plantas.
for(int i = 0; i < qts; i++){
destiny.right = (destiny.left = random.nextInt(tilesX)*32) + 32;
destiny.bottom = (destiny.top = random.nextInt(tilesY)*32) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
qts = (int) (random.nextInt((int) (tilesX*tilesY*0.1f))+tilesX*tilesY*0.05f);
source.right = (source.left = 96) + 32;// Preenche alguns espaços aleatórios com flores.
for(int i = 0; i < qts; i++){
destiny.right = (destiny.left = random.nextInt(tilesX)*32) + 32;
destiny.bottom = (destiny.top = random.nextInt(tilesY)*32) + 32;
canvas.drawBitmap(bmp, source, destiny, null);
}
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, null); // Substitui o onDraw original para desenhar o Bitmap montado.
}
}
Não explicarei alguns detalhes pois não acho importante para o contexto, mas se alguém tiver alguma dúvida basta entrar em contato, deixar um comentário, que eu respondo com maior prazer.
Vamos fazer umas pequenas modificações no MainGameView para mostrar o background. Primeiro adicione a variável ao objeto e ficará assim:
...
protected ArrayList<Pink> pinks; |
protected ArrayList<Gold> golds; |
protected Background background; ... |
Depois temos que instanciar o Background e coloca-lo na lista de Sprites:
...
for(int i = 0; i < 10; i++) |
golds.add(new Gold(random.nextInt(limitGoldX), random.nextInt(limitGoldY), random, bitmapGold, 1, 8)); |
background = new Background(random, getWidth(), getHeight(), BitmapFactory.decodeResource(res, R.drawable.background)); |
mSprites.add(background); |
mSprites.addAll(pinks); |
mSprites.addAll(golds); ... |
Fique atento para a ordem a qual se adiciona os Sprites na lista de Sprites pois isso define quem será desenhado primeiro. No nosso caso, primeiro o background, depois os Pinks, e por ultimo os Golds (gods devem ser desenhados em cima dos pinks para atrapalhar o jogador de clickar nos pinks).
Pronto, agora o jogo está como a primeira imagem, com o background bonitinho (designers podem discordar) e os personagens andando pela tela.
Nos próximos tutoriais faremos o jogo responder ao toque na tela, e adicionaremos pontos, levels e menus.
Parte 2 >>
Parte 2 >>
Até mais.
36 comentários:
O melhor tutorial que já vi na net!
Queria saber sobre o Adobe AIR for android e iOS, será se compensa mais?
Talvez se seu jogo for bastante complexo, você queira desenvolver para ambas as plataformas, e não quer aprender exatamente como funciona em cada uma, então compensa.
Tem como eu fazer a Sprite com imagens em GIF ?
Não do jeito que foi explicado e implementado. Até tem como usar gif no Android, mas não é nem um pouco fácil.
Segui todo o tutorial, deu alguns erros estranhos, dai eu consegui arruma tipo no Pink, eu acrescentei um @SuppressWarnings("unused") em cima do public class Pink extends Sprite {
fiz isso em outros tbm, dai não deu mais erro, só que quando eu vou testa o jogo ele abre normalmente, e quando eu toco na tela pra jogar, monstra os Golds rodando na tela, e quando eu vou clicar em algun, dá um erro ! e o jogo fecha, tirei algumas prints olha:
http://i49.tinypic.com/1zdvvcg.png
http://i49.tinypic.com/14w3y8g.png
http://i45.tinypic.com/6nvz92.png
http://i49.tinypic.com/200fqzk.png
repare que eu troquei todas as Variáveis de Pink pink pinks e Gold gold golds para Zumbi zumbi zumbis e Humano humano humanos.
Pelo que vi o erro ocorre no onDraw. Verifique se você não está tentando desenhar algo nulo. Mais do que isso só posso afirmar se você me passar o código fonte.
Iae conseguiu identificar algum erro ?
Ainda não identifiquei o erro. Se você me mandar zipado o código fonte completo poderei testar aqui. gdacarv@gmail.com
Olá Natan, tudo sobre isso pode ser encontrado aqui: http://tutoriandroid.blogspot.com.br/2012/02/configurando-o-ambiente-de.html
Rapaz, que tutorial interessante... Estou desenvolvendo um jogo de plataforma e o seu tutorial me ajudou muito a enteder conceitos básicos!!! E com certeza te pertubarei mais! rsrsrs Valeu !!!
Que bom que está sendo útil! =]
Valeu me ajudou bastante vc poderia depois ensinar a fazer jogos 3D mais completo como:FRONTILLINE COMAND e BLOOD & GLORY
@Eduardo: Que bom que foi útil! Agora, para fazer jogos que nem os citados estude bastaaaaante e use uma engine (www.unity3d.com)
Ótimo post, o ADT tem limite de imagens que podem ser adicionadas no resouces? Porque quando eu adiciono até umas 6 imagens para usar no game fica tudo bem. quando adiciono mais de seis (independente c é selecionada de uma vez ou tudo junto) o ADT não reconhece as imagens. Isso impossibilita de usa-las no game, pois dá erro
Dae cara, gostei do tutorial bem legal.
Tentei fazer ele aqui só que ta dando um erro. Abro ele normal e os personagem ficam caminhando, mas quando fecho o jogo ou a activity perde o foco da um NullPointerException no onDraw da GameView... sabe o que pode ser?
Abraço.
Unknown: Que eu saiba não existe esse limite, e com certeza não seria de 6 imagens. Talvez se suas imagens for muiiiito grande podem estar estourando a memória. Talvez seja algum problema no formato das imagens ou algo assim. Cheque se os aquivos de imagem não contém espaços ou outros caracteres proibidos no nome.
@Victor89: Aparentemente é algum problema na Game Engine, mas agora não sei exatamente qual o problema. Se quiser investigar: http://code.google.com/p/gdacarv-android-game-engine/
Quero muito aprender a fazer games, mas sou completamente novo nesse mundo. O que devo estudar?
que linguagens? onde as estudo? Por onde começar? por favor me ajude.
@Hilter: Comece estudando lógica de programação e game design. Depois você vai se especializando, estuda uma linguagem de programação utilizada em jogos como C++, pearl ou, no caso de Android, Java. Depois estude a plataforma ou engine que irá desenvolver, Android, Unity, Unreal...
Tudo isso você acha na Internet, mas pode procurar também livros, cursos, academia...
Gustavo, me tira uma dúvida, por favor!
O bitmap passado por parametro para a Classe "Gold" (filha de Sprites) é apenas uma referencia/ponteiro para um bitmap pré carregado, correto?
Ele não vai alocar o espaço do bitmap todo para cada objeto Gold que criar, certo?
Valeu ! Parabéns pelo tutorial, tá show de bola. Venho seguindo desde a Engine !
@Luis: Correto, a instancia do objeto é a mesma, logo só um bitmap é carregado.
Tenho uma duvida: tenho uma Classe que é uma View que criei, que extende LinearLayout e é gerada a partir um modelo em um XML pelo getLayoutInflater().inflate();
Como exporto essa Classe como jar de biblioteca para que eu posso importar essa class e utilizar essa View em outros projetos?
Obg
oq é "ECLIPSE" ???
AJUDA ???
Oioi! Obrigada pelo tutorial! Bem fácil de entender!
Tenho uma dúvida... rodei essa primeira parte do jogo no meu celular e em outros, e notei que para os celulares com resolução 320x480, a imagem de background fica errada e não consigo resolver isto! Vc poderia me ajudar?
Segue a imagem de como fica o background:
(só troquei os golds por kirbys azuis haha)
http://sphotos-c.ak.fbcdn.net/hphotos-ak-prn2/970266_500306836684406_1479162916_n.jpg
Ao cara que perguntou o que é eclipse sugiro que estude um pouco mais antes de tentar desenvolver esse tutoria.
Você pode até conseguir, mas se não sabe nem ao menos o que é eclipse é muito provável que não compreenda nada dos comandos que serão usados.
Eclipse é o ambiente de desenvolvimento que ele utiliza para a plataforma android!
http://www.eclipse.org/
Um eclipse é um evento astronômico que acontece quando um objeto celeste se move para a sombra de outro. O termo é derivado do termo grego antigo ἔκλειψις (ékleipsis), do verbo ἐκλείπω (ekleípō), "deixar para trás", uma combinação do prefixo ἐκ- (ek-), das preposições ἐκ, ἐξ (ek, ex), "fora", e o verbo λείπω (leípō), "deixar" .1 Quando acontece um eclipse dentro de um sistema estelar, como o Sistema Solar, ele forma um tipo de sizígia, o alinhamento de três ou mais corpos celestes do mesmo sistema gravitacional em uma linha reta .2
O termo eclipse é usado com mais frequência para descrever um eclipse solar, quando a sombra da Lua cruza a superfície da Terra, ou um eclipse lunar, quando a Lua se move na sombra da Terra. Entretanto, ele pode se referir a eventos além do sistema Terra-Lua: por exemplo, um planeta entrando na sombra de uma de suas luas, uma lua entrando na sombra do planeta que orbita, ou uma lua cruzando a sombra de outra lua. Um sistema estelar binário também pode produzir eclipses se o plano de suas órbitas intersecta a posição do observador.
Alguém sabe me dizer o por que desse erro "Cannot make a static reference to the non-static field Pink.x" isto esta ocorrendo nos comando Pink, pink, Gold, gold, já adicionei as imagens na pasta certa por que continua o erro
...
cara, posta mais imagens de onde ficam os arquivos ae
O meu nao esta achando a figura Bitmap bitmapPink = BitmapFactory.decodeResource(res, R.drawable.pink);
Bitmap bitmapGold = BitmapFactory.decodeResource(res, R.drawable.gold_head);
e esta na pasta drawable que foi pedido pra colocar
Alguem pode me ajudar estou fazendo um jogo diferente desse estou tentando colocar um progress bar em uma surface View e nao estou conseguindo me mande um email: wesleybezerra7@hotmail.com
Olá, estou fazendo o tutorial.
Mas aconteceu um erro no fundo.
Segue em anexo a imagem no jogo
http://www.casimages.com.br/i/140503060704304447.png.html
Alguém pode me dizer como conserto isso?
Olá, muito bom o tutorial.
Tentei fazer um exemplo aqui. Abro ele normal, consigo movimentar a imagem do fundo através de toque em tela, mas quando fecho o jogo ou a activity perde o foco da um NullPointerException no onDraw da GameView... sabe o que pode ser?
Abraço.
Olá Gustavo, peguei todo o código e colei exatamente como está e utilizei a ultima versão do Eclipse com ADT e emulei com AVD usando as configurações para android <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" / >. Ocorre os seguintes erros: 1- cada gold é gerado no canto superior - esquerdo da tela, mesmo quando passa de uma fase para outra ele adicina um novo gold na mesma posição. O background é gerado como se fossem faixas horizontais de 16px e deixando um espaço de 16px entre uma linha e outra. Teria alguma relação com as versões do android?
Cara aqui não está funcinando não, aparece Unfortunately, Smash has Stopped.
Oq pode ser??
O jogo funciona com o emulador do android do eclipse no windons com o mouse, ou apenas no celular com touch screen?
Postar um comentário