Amigos com estão?
Pois então, estou treinando muito a aprendendo bastante, mas estou tendo um probleminha aqui com Draw(shape), pois preciso posiciona-lo na posicão x, y que eu deseje ou seja desenhar o shape numa posição especifica, então estou usando o método translate(). Se eu não usar buffer funciona normalmente porem se usar…, vejam o código completo do applet:
package testejava;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Point;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.JApplet;
public class TestaApplet extends JApplet implements Runnable
{
double x, y, ax, ay;
Shape sh;
Thread th;
boolean threadSuspended;
Image img;
Graphics2D buff;
@Override
public void init()
{
super.init();
sh = new Rectangle2D.Double(0,0, 20, 20);
setSize(640, 480);
x = 20;
y = 20;
th = null;
img = new BufferedImage(640, 480, BufferedImage.TYPE_INT_RGB);
buff = (Graphics2D) img.getGraphics();
}
@Override
public void start()
{
if (th == null)
{
th = new Thread(this);
threadSuspended = false;
th.start();
} else
{
if (threadSuspended)
{
threadSuspended = false;
synchronized (this)
{
notify();
}
}
}
}
@Override
public void stop()
{
threadSuspended = true;
}
@Override
public void update(Graphics g)
{
paint(g);
}
@Override
public void paint(Graphics g)
{
g.drawImage(img, 0, 0, null);
}
@Override
public void run()
{
while (th.isAlive())
{
try
{
Point p = getMousePosition();
if (p != null)
{
ax = p.x;
ay = p.y;
repaint();
}
Thread.sleep(10);
buff.setColor(Color.black);
buff.fillRect(0, 0, getSize().width, getSize().height);
buff.setColor(Color.white);
if (x < ax) x += 1; else x -= 1;
if (y < ay) y += 1; else y -= 1;
buff.translate(x, y);
buff.draw(sh);
}
catch(Exception e)
{
}
}
}
}
Rodem e vejam o que acontece!
Alguem me ajuda?
Obrigado a todos!
O método translate altera a matriz de projeção do seu Graphics e, portanto, é cumulativo. Para mais informações:
http://www.pontov.com.br/site/index.php/arquitetura/54-matematica-e-fisica/238-matrizes-e-transformacoes-parte-1
Há duas alternativas para corrigir o problema:
- Copie o contexto gráfico antes de mexer nele (isso é considerado uma boa prática de programação em Java2D):
Graphics2D g2d = (Graphics2D) buff.create();
g2d.setColor(Color.black);
g2d.fillRect(0, 0, getSize().width, getSize().height);
g2d.setColor(Color.white);
if (x < ax) x += 1; else x -= 1;
if (y < ay) y += 1; else y -= 1;
g2d.translate(x, y);
g2d.draw(sh);
g2d.dispose();
- Ao invés do translate, altere as posições x e y do seu Rectangle:
Graphics2D g2d = (Graphics2D) buff.create();
g2d.setColor(Color.black);
g2d.fillRect(0, 0, getSize().width, getSize().height);
g2d.setColor(Color.white);
if (x < ax) x += 1; else x -= 1;
if (y < ay) y += 1; else y -= 1;
sh.setRect(x, y, sh.getWidth(), sh.getHeight());
g2d.draw(sh);
g2d.dispose();
Para mais informações sobre boas práticas usando Java2D, leia: http://www.pontov.com.br/site/index.php/java
Tópico movido para o fórum de interface gráfica.
Obrigado amigão consegui resolver seguindo sua dica de salvar o estado das tranformações, veja:
buff.setColor(Color.black);
buff.fillRect(0, 0, getSize().width, getSize().height);
buff.setColor(Color.white);
if (x < ax) x += 1; else x -= 1;
if (y < ay) y += 1; else y -= 1;
AffineTransform af = buff.getTransform(); //estado atual do contexto
buff.translate(x, y);
buff.draw(sh);
buff.setTransform(af); //volta ao estado anterior
Tive que fazer assim pois não poderia dispor do meu objeto Graphics pois este é obtido do meu objeto BufferedImage para criar tipo um double buffer e é criado no método init. A segunda opção não serve pra mim pois pretendo criar vários tipos de shape e mudando a origem fica mais facil pois nem preciso saber qual shape é.
Valeu!
A primeira dica também funciona, e eu a recomendo por ser uma boa prática. Com ela você evita “sujar” o Graphics original do BufferedImage.
O dispose() ali é dado sobre a cópia do seu objeto graphics (criada no create()) e não no seu objeto em si.
[quote=ViniGodoy]A primeira dica também funciona, e eu a recomendo por ser uma boa prática. Com ela você evita “sujar” o Graphics original do BufferedImage.
O dispose() ali é dado sobre a cópia do seu objeto graphics (criada no create()) e não no seu objeto em si.
[/quote]
Entendi amigão, não tinha prestando atenção neste detalhe (create)! Vou fazer uns testes aqui pra descobri questões sobre velocidade de processamento, pois pretendo criar um joguinho para testes.
Valeu!
Se você pretende criar um joguinho, recomendo fortemente que você siga os tutoriais do Ponto V, já indicados. Neles, você vai aprender como criar um bom algorítmo de game loop, e como usar os recursos já implementados do Java (BufferStrategy) para implementar double buffering em seu applet. Isso evita problemas como flickering ou velocidade de execução instável.
Assim você poderá criar animações fluídas e de alta performance, como essas aqui:
http://www.pontov.com.br/files/outros/vinigodoy/particles/particles.html
Muito bom amigão, estou estudando muito essa parte pois adoro criar jogos. Estou estudando alguns livros e tutoriais e estou começando a entender toda essa bagaça ehehehe alias estou gostando muito pois as classes são muito poderosas. O que mais me deixa doido são as Threads, realmente ainda não consegui entende-las direito é bem complexo essa coisa de prograamas rodando em paralelo. Gostaria de entender o ciclo completo das Threads de uma maneira mais simples possivel, embora eu consiga usa-las ainda não consegui compreende-las…
Valeu!
Infelizmente a bibliografia de java hoje está bastante desatualizada. O livro do Brackeen (um dos melhores de Java, na minha opinião) ensina, por exemplo, você a fazer um ThreadPool no braço, sendo que esse recurso existe por padrão no Java 5.
Ultimamente, não tenho mais recomendado o Java como linguagem para desenvolvimento de jogos, exceto no caso do Android.
Se quer uma linguagem igualmente fácil e poderosa, use o C# com XNA. O XNA cobre diversos aspectos deixados de lado no Java: sons, música, controles diversos, parte 3D. Além disso, ele permite a publicação das aplicações no X-Box, inclusive na X-Box Live. Sem falar que o C# também é uma das linguagens da poderosíssima Unity3D. A Microsoft tem investimento e um papel ativo no mercado de jogos, que sempre foi negligenciado pela Sun, e definitivamente não é um dos focos da Oracle.
PS: De onde você é? Existe uma pós graduação em jogos de computadores aqui em Curitiba, onde dou aula, na PUC do Paraná:
http://www.pucpr.br/cursos/especializacao/mostra_curso.php?processo=198&curso=3067&campus=1
Se você ainda não tem faculdade, temos também o curso de graduação tecnológica em jogos.
Obrigado pela dica! Eu sou do Rio de Janeiro, gostaria muito de fazer algum estudo relacionado a criação de jogos, mas estou esperando alguma faculdade pela internet mesmo pois meu tempo é bem escasso e eu gosto muito de aprender sozinho hehhe.
Quanto ao C# eu não sei, pois não confio muito na MS, sempre usei linguagens dos concorrentes dela como o Delphi, o C da Borland e atualmente o GCC. Eu acho que o Java embora não tenha uma API (atualmente) boa como XNA, tem uma padronização mais forte e é mais garantido em um futuro não muito distante. A MS sempre tenta colocar um gatinho escondido para quebrar algum padrão e nos colocar dependentes de seus padrões. Eu sei que o C# não é propriedade da MS mas atualmente quem usa hoje o C# esta atrelado ao Visual Studio.
Mais uma vez obrigado pelas dicas!
Se a idéia é fugir da MS então, parte mesmo para o C++.
Há boas APIs para a linguagem, como a UDK e a Ogre. Terá suporte fácil a integração com SO para controles, DirectX ou OpenGL e estará estudando uma das linguagens usadas na indústria de jogos profissional.
Agora, a MS ganhou bastante maturidade nos últimos anos. Sem falar que o perfil dela na área de jogos é bem diferente do da área de aplicações. Lembre-se que ela não só domina 98% do mercado dos PCs, como também possui um dos três grandes consoles do mercado e, por também ser dona do Windows (e do DirectX), é uma das poucas empresas de consoles que tem interesse em abrir o desenvolvimento para PCs.
Finalmente, também vale lembrar que um dos criadores do C# é a principal mente por trás do Delphi e do C++ Builder.