Graphics2D

Bem eu estou desenvolvendo um jogo e como mapa estou usando tiles, varios quadradinhos dai eu posso usa a mesma imagem em varios lugares mas como eu faço pra carregar só a parte do mapa que eu quero?? eu uso uma ArrayList e o MapEntity guarda sua localização e um sprite,

e outra tem como ficar redesenhando o mapa sem passar pelo meu loop?
pq eu uso assim

Graphics2D g = new Graphics2D();
for(MapEntity a : myMapEntities){
a.draw(g);
}
g.dispose();

e ficar faznedo isso toda hora deixa o jogo mei travando dai o bonequinho aparece aqui depois lá dai mais pra frente =/
alguem tem essas duas respostas??

Se map entity guarda a localização de seus Sprites, então você pode testar com um if e ver se ela deve ser pintada ou não.

Afinal, você também deve ter as coordenadas de onde o seu mapa estiver pintando. Nesse caso, não pinte se:

A figura estiver fora do lado esquerdo do mapa:
sprite.getX() + spritex.width() &lt mapa.minX()

A figura estiver fora para o lado direito do mapa:
sprite.getX() &gt mapa.max()

A figura estiver acima do topo do mapa:
sprite.getY() + spritex.height() &lt mapa.minY()

A figura estiver abaixo da parte inferior do mapa:
sprite.getY() &gt mapa.maxY()

Só se todas essas condições estiverem atingidas, você pinta o sprite.

Note que isso é muito similar ao algoritmo de bounding box, entre o retângulo do sprite e o retângulo do mapa. Se você tiver duas classes Rectangle2D, uma representando o Sprite e outra a área útil do mapa, pode usar o método intersects para testar a mesma coisa.

public class Map { public void draw(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); for(MapEntity a : myMapEntities){ if (a.rect().intersects(this.getShownRect())) { a.draw(g2d); } } g2d.dispose(); } }

PS: Tá fazendo um jogo? Qual é? No outro tópico você acabou nem me falando. É um RPG? Vai usar java 3D ou só 2D?

Só 2D
é algo mais parecido com RPG
e por enquanto o nome é Overseas

e pra pintar minha tela tenho que passar toda hora pelo loop? pq fico pesado fica montando todas as imagens

Tem sim que passar toda hora pelo loop e desenhar as imagens.

Montar todas as imagens não é tão lento assim. Carregue as imagens que você vai usar na memória (em um BufferedImage). Existem alguns métodos para aumentar as changes do java2D otimizar o desenho das imagens para você (ou seja, mandar a placa de vídeo desenha-las), é o que ensina o tutorial do Space Invaders do Coke and Code.

Agora, tome cuidado com a velocidade de seu jogo. Quando o micro for lento, você pode “pular” uma etapa de desenho das imagens para compensar a velocidade do jogo. É o que descreve este artigo, que escrevi. Da mesma forma, quando o micro for rápido demais, você deve dar alguns sleeps, para que a velocidade de seu jogo permaneça sempre constante.

Assim, é sempre bom separar o desenho de seus sprites (faze de renderização) do processamento da lógica. Dê uma olhada no link que te passei e como aquele algoritmo é aplicado no Vikanoid. :wink:

E qualquer dúvida, pode perguntar! :slight_smile:

Eu to usando sobre oque vi no Coke and Code do Space Invaders eu li e to usando aquilo sobre a classe Entity, Sprite, SpriteStore, dai pra mapa e personagens uso classes que extendem Entity
é uma má pratica ter uma Array tão grande pro mapa??
pq olha imagina ter um mapa [100][100]
não ia fica meio lento?? ou meio confuso pra continuar desenhando em Updates?

Veja bem. Performance não é tanto o problema, mas sim memória.
Um array de 100x100, vai ocupar pelo menos 40KB.

Agora, a maior parte desse array irá ser ocupado por referências um mesmo tipo de tile, como grama ou o chão de sua caverna. Um desperdício, não?

A solução para isso é usar uma matriz dispersa, que retorna o seu tile default caso não haja um tile cadastrado. Para isso, você cria um map, com outro map dentro.

Eu implementei rapidinho aqui essa classe, que representa esse conceito. Não testei, pode ser que alguns ajustes tenham que ser feitos (não tem como remover um tile, por exemplo). Mas acho que já dá para te dar uma idéia de como funciona uma matriz desse tipo:

[code]public class Matrix<T> {
private Map<Integer, Map<Integer, T>&gt map;
private T defaultValue;

public Matrix(T defaultValue) {
    if (defaultValue == null)
        throw new IllegalArgumentException(&quot;Default value cannot be null!&quot;);
    
    this.defaultValue = defaultValue;
    this.map = new HashMap&lt;Integer, Map&gt;&lt;Integer, T&gt;&gt();
}

public T get(int line, int column) {
    Map&lt;Integer, T&gt; columns = map.get(line);
    if (columns == null)
        return defaultValue;
    
    T tile = columns.get(column);
    if (tile == null)
        return defaultValue;
    
    return tile;
}

public T put(int line, int column, T value) {
    Map&lt;Integer, T&gt; columns = map.get(line);
    if (columns == null) {
        columns = new HashMap&lt;Integer, T&gt;();
        map.put(line, columns);
    }
    
    T oldValue = columns.put(column, value);
    if (oldValue == null)
        return defaultValue;
    
    return oldValue;
}

}[/code]

Pra usar, basta fazer:

[code]Matrix<Tile> tileMap = new Matrix<Tile>(new GrassTile());
RockWallTile rockWall = new RockWallTile();

tileMap.put(5,5, rockWall);
tileMap.put(6,5, rockWall);
tileMap.put(7,5, rockWall);

tileMap.put(5,6, rockWall);
tileMap.put(7,6, rockWall);

tileMap.put(5,7, rockWall);
tileMap.put(6,7, rockWall);
tileMap.put(7,7, rockWall);

if (tileMap.get(player.getTilePos().getX(), player.getTilePos().getY()) == rockWall) {
//O jogador colidiu com a parede? Faz alguma coisa…
}[/code]

private Map<Integer, Map><Integer, T>> map;

da erro nessa parte fala que tem um > amais se tira aparece misplaced Constructors

Eu sei que vc disse que podia ter alguns problemas eu nunca vi Map assim^^

Tem que tirar o &gt depois da segunda palavra Map.

Já corrigi no post ali em cima. Não sei pq, mas o GUJ colocou isso automático!

Na verdade, é um mapa de um inteiro para um outro mapa.

Ah sim, outra alternativa (comum em jogos de RPG) é não usar um tilemap, e sim um ArrayList de sprites. Colisões e coisas do tipo você detecta por um algoritmo de Bounding Region qualquer.

^^ vlw agora eu entendi aquilo

e outra coisa eu percebi que outro erro meu era usar tiles de 25 por 25 pixels e uma tela de 800 por 600 dai ficava 32 coluna e 24 linhas de tiles isso era pesado pra carrega vou usar agora uns 12 por 8 por ai

Mano to tentando usa seu exemplo mas como faço pra desenha?? eu vou explicar mais ou menos como faço

Tenho a classe Tile que tem Um Sprite como atributo(que tem um metodo draw(Graphics g , int x, int y))
dai meus MapsTiles(GrassTile, WaterTile, etc.) extendem Tile e só tem o Sprite como atributo dai a posição x e y to usando do Map no modo que vc passou mas como faço rpa desenha a parte que eu quero(não pela localização, mas desenha as partes tipo da 0 < 12 coluna e da 0 < 8 linha?

Cara, não entendi sua dúvida. Testa com um if se o tile está dentro da tela e, se estiver, usa o seu método draw! Não é só fazer isso?

o if eu sei pra ve qual desenhar mas ta dando erro no draw fala que tem que da Cast pra Tile mas mesmo assim nada eu vou ve se arrumo hoje eu passei muito mal ontem e vou continua o jogo depois

Mark, se der para escrever em português ao invés de internetquês o pessoal do fórum agradeceria…

Pois então essa parte eu sei calcula oque ta perto do personagem e desenha mas agora tenho outro problema
o método get só em tetorna o default

olha meu void pra pinta do map

/* Graphics pra da draw, lineI:linha inicial, columnI:coluna inicial, lineF e columnF, linha final e coluna final respectivamente*/ public void draw(Graphics g, int lineI, int columnI, int lineF, int columnF){ for(int i = lineI; i <= lineF;i++){ for(int j = columnI; j <= columnF;j++){ for(int column = 0; column<12;column++){ for(int row = 0; row<8;row++){ ((Tile)this.get(i, j)).draw(g,column*25,row*25); } } } } }

e só pint ao GrassTile

Desculpa eu comi umas letra sem ve^^

e outra duvida se eu tive muitos Tiles tipo assin uns 100 vou ter que te 100 classes de Tile? não tem como ter uma classe mais genérica?

EDIT: eu acho que cria uma classe Tile que receba uma string com o nome do arquivo serve^^
dai eu instancio ela e adiciona no Map

e outra como eu resolvo isso de só me retornar o defaultValue?
mesmo se eu adicionar outo tile tipo no 0, 0 e chamar pra pinta só esse me retorna o defaultValue

Finalmente resolvi aquilo de só vim o defaultTile ams agora o meu metodo só pinta o mesmo Tile o que se referencia no 0,0 eu sei que é porque to passando umas 1000 vezes no mesmo ponto pra da draw antes de muda de linha dai pinta tudo de azul=/