Colisão não detectada! Alguma boa alma pode me ajudar?

8 respostas
N

Não entendo porque a colisão não está sendo detectada, o sprite do personagem atravessa os blocos do cenário. A idéia é ter duas variáveis para guardar a posição atual do sprite e duas para guardar a posição anterior do sprite. Então, quando a colisão é detectada, o sprite deveria voltar uma posição. Mas não é isso que acontece!

classe CharacterClass:

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class CharacterClass extends Sprite {
    
   private int posx, posy;   // To hold current position of sprite.
   private int lastx, lasty;   // To hold the last x and y positions.
   private int frameWidth, frameHeight;   // To hold size of sprite frame or frames.
   private int lives = 3;
              
   public CharacterClass(Image image, int frameWidth, int frameHeight) throws Exception {
      
      super(image, frameWidth, frameHeight);
      this.frameWidth = frameWidth;
      this.frameHeight = frameHeight;
                  
   }
   
   public int getLives() {
      return lives;    
   }
   
   public void setLives(int lives) {
      this.lives = lives;
   }
   
   public void startPosition() {
      posx = 16;
      posy = 16;
      lastx = posx;
      lasty = posy;
      this.setPosition(posx, posy);
   }   
   
   public void moveRight() {
      lastx = posx;   
      posx++;
      this.setPosition(posx, posy);   
   }
        
   public void moveLeft() {
      lastx = posx;
      posx--;
      this.setPosition(posx, posy);
   }

   public void moveUp() {
      lasty = posy;
      posy--;
      this.setPosition(posx, posy);   
   }
   
   public void moveDown() {
      lasty = posy;
      posy++;
      this.setPosition(posx, posy);
   }

   public void setLastPosition() {
      this.setPosition(lastx, lasty);
   }
   
   public void paintSprite(Graphics g) {
      this.paint(g);    
   }
   
}

classe GameCanvas:

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import java.io.InputStream;

public class GameCanvasClass extends GameCanvas implements Runnable {
    
   private boolean playing;   
   // TiledLayer.
   private TiledLayer tiledCenary;
   // Layer.
   private LayerManager layer1 = new LayerManager();
   // Game settings;
   public static int gameLevel = 0;
   public static int MAX_ENEMIES = 4;
   public static final int NUMBER_LEVELS = 10;
   public static boolean[] doneBuildLevel = new boolean[10];
   // Sprites.
   private CharacterClass player;
   private CharacterClass[] enemy = new CharacterClass[4];
   // Sounds.
   private Player playerSound;
   // Thread.
   private Thread thread;
   
   /** Creates a new instance of GameCanvasClass */
   public GameCanvasClass() throws Exception {
      
      super(true);
      for(int i = 0; i < 10; i++)
         doneBuildLevel[i] = false;    
      Image image = Image.createImage("/bear.PNG");
      player = new CharacterClass(image, 16, 16);
      player.startPosition();
                 
   }
   
   public void start() throws Exception {
      
      playing = true;
      thread = new Thread(this);
      thread.start();
            
      try {
         InputStream is = getClass().getResourceAsStream("sound.mid");
         playerSound = Manager.createPlayer(is, "audio/midi");
         playerSound.realize();
         playerSound.prefetch();
         playerSound.start();
      }
      catch(Exception e) {
         System.out.println(e);    
      }
   
   }
   
   public void run() {
        
      try {
         setupGameLevel(gameLevel);
      } 
      catch(Exception e) {
         e.printStackTrace();
      }
      
      Graphics g = getGraphics();
      
      while(playing == true) { 
         drawGameScreen(g);
         checkInput();
         checkCollision();
         try {
            Thread.sleep(15); 
         }
         catch(InterruptedException ie) {
         }
      }
      
   }
   
   public void stop() {
      
      playing = false;
      if(player.getLives() >= 1 )
         playing = true;
      else {
         System.out.println("GAME OVER");    
         try {
            if(playerSound != null) { 
               playerSound.stop();
               playerSound.close();
               playerSound = null;
            }
         }
         catch(Exception e) {
            System.out.println(e);    
         }
      }
   }
   
   private void setupGameLevel(int level) throws Exception {
      
      if( (level == 0) && (doneBuildLevel[level] == false) ) {
         // Building cenary for the first level.
         tiledCenary = TiledLayerClass.buildTiledCenary(gameLevel);
         // Append to the layer.
         layer1.append(player);
         layer1.append(tiledCenary);             
      
      }
            
   }
   
   private void checkInput() {
      
      int keyState = getKeyStates();
      
         if( (keyState & UP_PRESSED) != 0) 
            player.moveUp();
         if( (keyState & DOWN_PRESSED) != 0) 
            player.moveDown();
         if( (keyState & RIGHT_PRESSED) != 0) 
            player.moveRight();
         if( (keyState & LEFT_PRESSED) != 0) 
            player.moveLeft();
               
   }
   
   private void checkCollision() {
      
      if(player.collidesWith(tiledCenary, false) == true) { 
         System.out.println("Collision!");
         player.setLastPosition();
      }
                  
   }
   
  private void drawGameScreen(Graphics g) {
      
      g.fillRect(0, 0, 256, 256);
      player.paintSprite(g);
      layer1.setViewWindow(player.getX() + 16, player.getY() + 16, 128, 110);
      layer1.paint(g, 0, 0);
      g.setColor(0, 0, 0);
      flushGraphics();
   
   }
   
}

8 Respostas

M

Teu cenário tá aparecendo na tela ?? Nunca usei aquele buildTiledCenary. Tenta criar = new TiledLayer
Um exemplo da Vanessa Sabino aqui:
http://www.linuxchix.org.br/artigos/GameAPI-unificado.pdf

N

Sim o TiledLayer aparece sem problemas. Eu não havia colocado essa classe por motivos de espaço. Lá vai:

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

public class TiledLayerClass {
    
   public static TiledLayer tiledLayer;
       
   /** Creates a new instance of TiledLayerClass */
   public TiledLayerClass() {
   }
    
   public static TiledLayer buildTiledCenary(int level) throws Exception {
      
      if(level == 0) {
         Image image = Image.createImage("/square1.PNG");
         tiledLayer = new TiledLayer(15, 15, image, 16, 16);
         int map[] = {
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1,
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1                
         };
         for(int i = 0; i < map.length; i++) {
            int column = i % 15;
            int line = (i - column) / 15;
            tiledLayer.setCell(column, line, map[i]);
         }
      }
      else if(level == 1) {
         Image image = Image.createImage("/square2.PNG");    
         tiledLayer = new TiledLayer(15, 15, image, 16, 16);
         int map[] = {
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,         
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1                
         };
         for(int i = 0; i < map.length; i++) {
            int column = i % 15;
            int line = (i - column) / 15;
            tiledLayer.setCell(column, line, map[i]);
         }
      }
          return tiledLayer;
   }

}
M

E ele tá imprimindo o “Collision!!” ?? Talvez o erro esteja em setar os valores devolta, tenta colocar um valor fixo no método setLastPosition, tipo setPosition(5, 5), que dai tu vê se ele vai pra essa posição quando der colisão.
Quando tu faz if(player.collidesWith(tiledCenary, false) == true) este true não precisa, porque o método já vai retornar true ou false.
É meio difícil achar o erro assim só olhando o código, o que eu faço sempre é ir colocando strings de teste, tipo System.out.print(“AAA”); pra ver se ele passa pelo caminho e imprime isso ou vai pra outro lado. Se tu quiser me mandar o projeto só me manda uma MP q dai te passo meu email, dai vejo se arrumo um tempo essa semana e dou uma olhada. (nada garantido).

Abraço.

N

Sim, está imprimindo “Collision!”, mas atravessa os blocos mesmo assim.

M

Acolisão então está sendo detectada, tu deve estar fazendo algo errado na hora de passar os valores pra ele retornar a posição.
Coloca prints nas saidas posy e posx de cada método, up, down…, e também no setLastPosition, pra ver se ele realmente está pegando o valor certo pra retornar.

N

Só tem mais um detalhe interessante:
Somente em certos trechos do cenários a colisão com o TiledLayer é detectada! (ou seja, imprime “Collision!”). Em outros trechos do cenário o sprite atravessa os blocos sem nada acontecer…

Para quem quiser testar o programa, aqui está a classe MidletClass:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class MidletClass extends MIDlet implements CommandListener {
    
   private Display display;
   private Command exitCommand;
             
   public void startApp()  {
      
      display = Display.getDisplay(this);
      exitCommand = new Command("Exit", Command.EXIT, 0);
                
      try {
         GameCanvasClass gcc = new GameCanvasClass();
         gcc.addCommand(exitCommand);
         gcc.setCommandListener(this);
         new SplashScreen(display, gcc);
         gcc.start();
      }
      catch(Exception e) {
      }
             
   }
   
   public Display getDisplay() {
      return getDisplay();    
   }
    
   public void pauseApp() {
   }
    
   public void stopApp() {
      destroyApp(true);    
      notifyDestroyed();
   }
   
   public void destroyApp(boolean unconditional) {
   }

   public void commandAction(Command c, Displayable d) {
      
      if(c == exitCommand)    
         stopApp();   
           
   }
   
}

A classe responsável pelo Splash Screen está incorreta e como isso não afeta a lógica do jogo, não é necessário postar. Com 3 sprites .png de tamanho 16 x 16 (personagem, inimigo e bloco para cenário) vocês podem montar o jogo e testar melhor o código e ajudar na correção dos bugs.

Obrigado pela ajuda desde já.

M
Bom vamos lá, pro player ao invés de usar setposition usa o move(), como eu vou colocar na classe abaixo. Agora quanto ao cenário assim, ainda não entendi o porque ele tá fazendo isso, mas ele tá criando a imagem no lugar certo mas a posição onde ele realmente está é muito mais longe, por exemplo, quando tu bate num lugar vazio e trava lá está o cenário mas tá "invisível" e quando tu passa por cima das barras do cenário ele não está realmente lá, não sei porque ele está fazendo isso. Uma alternativa que eu vi, mas meio tosca, é tu fazer o cenário com figuras de 1x1 e preencher tudo que tu quiser, vai ficar um mapa gigante, mas se mais nada funcionar é uma alternativa, testa pesquisar mais sobre isso. Pro player eu acho que fca mais fácil e resolveu o problema assim:
public void moveRight() {
	  lastx=-1;
	  lasty=0;
      this.move(1, 0);   
   }
       
   public void moveLeft() {
      lastx=+1;
      lasty=0;
      this.move(-1, 0);
   }

   public void moveUp() {
	   lasty=+1;
	   lastx = 0;
      
      this.move(0, -1);   
   }
   
   public void moveDown() {
	   lasty=-1;
	   lastx = 0;
      this.move(0, 1);
   }

   public void setLastPosition() {
	   this.move(lastx, lasty);
	   
   }
E pra montar o cenário eu acho que fica melhor arrays bidimensionais, mas ai é de cada um, se bem que desse jeito não precisa dividir.
tiledLayer = new TiledLayer(15, 15, image, 16, 16);
         int map[][] = {
            {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},       
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},   
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},     
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},     
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},     
            {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},    
            {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},     
            {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},     
            {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},       
            {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1},
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},     
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},      
            {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},      
            {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
           for (int row=0; row<15; row++) 
    			for (int col=0; col<15; col++)
    				tiledLayer.setCell(col, row,map[row][col]);
Espero que ajude! Abraço.
N

Ok, fiz algumas correções, agora está funcionando.

Com certeza, vou me familiarizar com esse método e começar a usá-lo.

Em breve retorno com mais dúvidas!

Obrigado!

Criado 29 de abril de 2007
Ultima resposta 1 de mai. de 2007
Respostas 8
Participantes 2