Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (476)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  "combining" a new BufferedImage (SOLVED with a better way)  (Read 2258 times)
0 Members and 1 Guest are viewing this topic.
Offline sakus

Senior Newbie





« Posted 2012-04-14 12:22:04 »

Hi,

I'm making a health bar for my little game and because I wanted something nicer looking, instead of simply using fillrect I have an empty framed health bar as a BufferedImage and I draw small pieces of gradiented bar (another BufferedImage) inside the empty bar frames. The amount of bar pieces needed to draw depends on how much HP the player has left, so the maximum amount of pieces to draw is 100.

So every game loop update, it checks the player's HP and then goes through a loop to draw as many tiny pieces of a health bar as is needed. I'm thinking this can't be efficient and is at least one of the reasons my screen update is getting jerky at times.

What I'd like to do instead, is go through that loop to build a health bar according to the actual hp, then save the result as a new BufferedImage and draw that one on the screen instead. But I can't figure out how to do this.

Instead of drawing the small pieces over and over again, I would then in the game loop only draw the previously generated BufferedImage and generate a new one only if the player's HP has actually changed since the last one was generated.

This make sense? How would I generate a new BufferedImage for a bar which is already filled out by the correct amount?

Here's the current loop to draw the health bar for reference. This can't be efficient. getHpBarSprite() and getHpPortionSprite() return BufferedImages that have been loaded from PNG's. getHpLeft() returns the percentage of HP left.

The free horizontal space inside the hp bar sprite is 200 pixels and the hp portion sprite is 2 pixels wide (not 100 pixels and 1 pixel because then the bar would've been too small to my taste..)

1  
2  
3  
g.drawImage(gameResources.getHpBarSprite(), 10, 10, null);
for (int x = 0; x < playerPlane.getHpLeft(); x++)
    g.drawImage(gameResources.getHpPortionSprite(), 12+x*2, 12, null);


This is what it looks like at 20% HP left. It does exactly what I want, but I want to do it in a better way so that I wouldn't have to go through that stressful drawing loop every single game loop iteration..

I'm just now starting to build the actual HUD starting with the HP bar so don't mind those messy ammo/lives etc texts visible in the pic..

Offline 65K
« Reply #1 - Posted 2012-04-14 13:54:27 »

I can't speak of mobile devices, but a half-decent modern machine is able to render many thousand (managed) images per second. Thus, up to 100 health bar fractions shouldn't be a problem.

Anyway, drawing only one image will be faster and you can just create a new image with
GraphicsConfiguration#createCompatibleImage()
GraphicsConfiguration#createCompatibleVolatileImage()

The graphics configuration is available by calling
Graphics2D#getDeviceConfiguration()
Component#getGraphicsConfiguration()

I should use images for my progress bars as well, cause I draw them with plain rectangles, and thus they look primitive and ugly  Cry  Grin

Offline nsigma
« Reply #2 - Posted 2012-04-14 14:16:05 »

You only need two drawImage(..) calls.  Firstly draw your health bar background as you are doing, then use the scaling version of drawImage to draw your gradient on top.  You only need to have a single pixel wide gradient image too, and you can use the lowest quality scaling setting (nearest neighbour) as it won't make a difference to the output.

eg.

1  
g.drawImage(gradient_image, x, y, <HEALTH% x HEALTH_BAR_WIDTH>, <GRADIENT_HEIGHT>, null);



Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sakus

Senior Newbie





« Reply #3 - Posted 2012-04-14 14:36:47 »

You only need two drawImage(..) calls.  Firstly draw your health bar background as you are doing, then use the scaling version of drawImage to draw your gradient on top.  You only need to have a single pixel wide gradient image too, and you can use the lowest quality scaling setting (nearest neighbour) as it won't make a difference to the output.

Ah nice, didn't even realize it can be used like that, thanks!

I reduced the gradient pic to 1px wide and this is working (getHpLeft() returns the HP percentage as an int, i.e. 80 for 80% and the bar is 200px)

1  
2  
g.drawImage(gameResources.getHpBarSprite(), 10, 10, null);         
g.drawImage(gameResources.getHpPortionSprite(), 12, 12, playerPlane.getHpLeft() * 2, 10, null);

Online ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #4 - Posted 2012-04-14 16:56:36 »

You don't even need to use an image for this. A LinearGradientPaint would have been sufficient Tongue

Offline sakus

Senior Newbie





« Reply #5 - Posted 2012-04-14 17:33:55 »

Hm so I see, I'll look into that. Thanks
Offline nsigma
« Reply #6 - Posted 2012-04-14 18:18:51 »

You don't even need to use an image for this. A LinearGradientPaint would have been sufficient Tongue

Different, yes. Better? Not necessarily. Scaling a 1px image is a known technique for optimizing a horizontal or vertical gradient. It can give better performance - a little or a lot depending on graphics pipeline, etc. It might be premature optimization if the OP hadn't already done it!  Smiley

Praxis LIVE - open-source intermedia toolkit and live interactive visual editor
Digital Prisoners - interactive spaces and projections
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 743
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2012-04-14 19:31:59 »

In Java2D performance tips/articles you see that axis aligned linear gradients are much (much!) faster when faked with n*1px images.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Online ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #8 - Posted 2012-04-14 20:28:06 »

n * 1px images > stretching the image?! And how about the performance of LinearGradientPaint?

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (18 views)
2014-07-24 01:59:36

Riven (17 views)
2014-07-23 21:16:32

Riven (14 views)
2014-07-23 21:07:15

Riven (17 views)
2014-07-23 20:56:16

ctomni231 (45 views)
2014-07-18 06:55:21

Zero Volt (40 views)
2014-07-17 23:47:54

danieldean (32 views)
2014-07-17 23:41:23

MustardPeter (36 views)
2014-07-16 23:30:00

Cero (51 views)
2014-07-16 00:42:17

Riven (50 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!