Is setting the BufferStrategy every time the game renders a good idea? - java

For some reason everyone sets their BufferStrategy to the BufferStrategy in their canvas whenever they render their game.
BufferStrategy bs;
Graphics2D g;
private void render() {
bs = window.getCanvas().getBufferStrategy();
if (bs == null) {
window.getCanvas().createBufferStrategy(3);
return;
}
g = (Graphics2D) bs.getDrawGraphics();
bs.show();
g.dispose();
}
// When thread starts
public void run() {
while (running) {
//Game loop stuff here.
render();
}
}
Can you just set it once instead of every time the game re-renders?

Related

How to draw transparent image in java with BufferedImage?

I'm willing to show an transparent image on a canvas in java with the help of graphics2D and BufferedImage.
Here is the code which loads image.
private static BufferedImage sprites,board;
public static void load(){
try {
board = new BufferedImage(100,100,BufferedImage.TYPE_INT_ARGB);
board = ImageIO.read(new File("res/chesssprite.png"));
} catch (IOException ex) {
Logger.getLogger(SpriteManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
and here is the code which renders the image
public void render(){
BufferStrategy bs = this.getBufferStrategy();
if(bs == null){
this.createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
Graphics2D g2d = (Graphics2D) g;
{
g2d.setColor(new Color(150,150,150));
g2d.fillRect(0,0,getWidth(), getHeight());
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(board,0,0,null);
}
g = g2d;
g.dispose();
bs.show();
}
I have search on net a lot but didn't come with an solution. If anyone knowns how to fix this.
Here is the image..
And here is how output looks like
Okay whoever facing these kind of problem:
Make sure the image is transparent. Test it in image viewer.
Remove the line g2d.setComposite(AlphaComposite.Src); This line adds alpha composites which make every transparent pixel black.

Java buffer strategy sometimes doesn't draw properly

I created a game in Java which uses buffer strategy. But sometimes I just get a white frame or a white border. That happens about every fifth time. I searched a lot but I really can't figure out what I'm doing wrong. The code compiles and there aren't any errors printed out.
If if fails, the frame looks for example like that:
white border
completely white frame
Here's code (only the relevant parts):
private BufferStrategy bs;
public Testclass(){
setResizable(false);
setSize(1000,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setIgnoreRepaint(true);
setVisible(true);
createBufferStrategy(2);
bs = getBufferStrategy();
}
protected void paint() {
do {
Graphics2D g=null;
try {
g = (Graphics2D) bs.getDrawGraphics();
g.setColor(Color.CYAN);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
} finally {
g.dispose();
}
bs.show();
} while (bs.contentsLost());
}
public static void main(String[] args) {
Testclass window = new Testclass();
window.paint();
}
I actually found a better way try this:
boolean BufferStrategyRunning = true;
while(BufferStrategyRunning == true) {
BufferStrategy BS = GUIFrame.getBufferStrategy();
if(BS == null) {
GUIFrame.createBufferStrategy(3);
continue;
}
Graphics g = BS.getDrawGraphics();
g.drawImage(CurrentScreen.BackgroundImage, 0, 0, null);
g.dispose();
BS.show();
}

Java Graphics(2D) for offscreen rendering

I'm getting into Java graphics at the moment and I'm reading the book Killer game programming in Java by Andrew Davison. He programs a simple window application that uses the Image class for off-screen rendering and then copying the image to the component. What I find confusing is that one can just create the image and then get the graphics context with:
dbg = dbImage.getGraphics();
I find it confusing, because then we only use the dbg Graphics object to draw stuff but later on we use the dbImage in the paintComponent method to display all the stuff we have drawn to the dbg Object:
g.drawImage(dbImage, 0, 0, null);
So how does the dbImage "know", that it contains all the graphics stuff we have drawn onto the dbg Graphics object?
Here is the whole code:
public class GamePanel extends JPanel implements Runnable{
private static final int PWIDTH = 500;
private static final int PHEIGHT = 400;
private Thread animator;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private Graphics dbg;
private Image dbImage = null;
private Counter counter;
public GamePanel(){
setBackground(Color.white);
setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
// create game components eg. counter.
counter = new Counter(10);
counter.start();
}
private void stopGame(){
running = false;
}
#Override public void addNotify(){
super.addNotify();
startGame();
}
public void startGame(){
if(animator == null || !running){
animator = new Thread(this);
animator.start();
}
}
#Override
public void run() {
running = true;
while(running){
gameUpdate();
gameRender();
repaint();
try{
Thread.sleep(20);
}
catch(InterruptedException ex){
// do something with the exception...
}
}
}
private void gameUpdate(){
if(!gameOver){
// update game state...
if(counter.getCounter() == 0)
gameOver = true;
}
}
private void gameRender(){
if(dbImage == null){
dbImage = createImage(PWIDTH, PHEIGHT);
if(dbImage == null){
System.out.println("dbImage is null");
return;
}
else
dbg = dbImage.getGraphics(); // get graphics context for drawing to off-screen images.
}
// clear the background
dbg.setColor(Color.white);
dbg.fillRect(0, 0, PWIDTH, PHEIGHT);
// draw game elements here...
dbg.setColor(Color.black);
dbg.drawString(Integer.toString(counter.getCounter()), 10, 10);
if(gameOver)
dbg.drawString("Game over...", 10, 20);
}
#Override public void paintComponent(Graphics g){
super.paintComponent(g);
if(dbImage != null)
g.drawImage(dbImage, 0, 0, null);
}
}
the important parts are only the paintComponent method and the gameRender() method though.
Basically, a Graphics object is not something you draw on. It's something you draw with.
When you call dbImage.getGraphics(), you are saying "Give me a toolbox that allows me to draw on this image". All of the draw methods in a Graphics object draw on the component for which it was created. They are not drawn on the Graphics object, they are drawn on the Image or the Component that belong to it.
Think of the Graphics object as the palette and brushes, and on the Image or Component as the canvas.
So when you are done running the operations with your dbg, it means you have an image full of colorful pixels that this Graphics object drew on it. Now you can take this image and copy it to another component - by using the drawImage "tool" in that component's Graphics - its "toolbox".

Java Game Image Buffering Leaves Tail

I have the following class (Snippet), and in my render() method, I am doing buffering using BufferStrategy. The issue I am having is when I move an image, it leaves a tail.
What Do I need to do with my code to make it so the tail doesn't show? Here is the code:
public class Main extends JFrame implements Runnable{
private BufferStrategy bufferStrategy;
public synchronized void start(){
Thread thread = new Thread(this);
thread.start();
}
public void run(){
// Main Game Loop
this.render();
// End Main Game Loop
}
protected void render(){
if(bufferStrategy == null){
this.createBufferStrategy(3);
bufferStrategy = this.getBufferStrategy();
}
Graphics g = bufferStrategy.getDrawGraphics();
// Loop through a list of items to draw
for(GameObject go : gameObjects){
Image sprite = go.getComponent(SpriteRenderer.class).getSprite();
Vector2 pos = go.getComponent(Transform.class).getPosition();
g.drawImage(sprite, (int)pos.x, (int)pos.y, this);
}
g.dispose();
bufferStrategy.show();
Toolkit.getDefaultToolkit().sync();
}
}
Edit
I figured it out:
Graphics g = bufferStrategy.getDrawGraphics();
super.paint(g);
You need to refresh every time the wheel moves and repaint the Canvas to black before painting the wheel's position again.

BufferStrategy not scaling Graphics2D

I am currently trying to program a simple platform game. I would like to scale the graphics up by a factor of 2/4/whatever so that I can get an old-school look and feel from the game. However, when I call scale on my Graphics2D instance, nothing happens.
#Override
public void paint(Graphics g) {
BufferStrategy bf = this.getBufferStrategy();
Graphics2D bfg = (Graphics2D) bf.getDrawGraphics();
mLevel.draw(bfg, this);
for (GameEntity entity : mGameEntities) {
entity.draw(bfg, this);
}
bfg.scale(2.0, 2.0);
bf.show();
}
The draw calls basically just end up calling g.drawImage(..). Everything else is drawn correctly, so I do not understand why it isn't scaling everything up by a factor of 2.
#MadProgrammer was correct - one must scale the Graphics2D instance before making any draw calls.
#Override
public void paint(Graphics g) {
BufferStrategy bf = this.getBufferStrategy();
Graphics2D bfg = (Graphics2D) bf.getDrawGraphics();
bfg.scale(2.0, 2.0);
mLevel.draw(bfg, this);
for (GameEntity entity : mGameEntities) {
entity.step();
entity.draw(bfg, this);
}
bf.show();
}

Categories

Resources