Archived

This topic is now archived and is closed to further replies.

Rah

[java] Best method for graphics in a Java Applet?

Recommended Posts

Hi, I''m a reasonable C++ graphics programmer and am recently trying to port some of my games over to java, v1.1, for use in web pages. My aim is to create games such as those on the MSN gaming zone; Bejewelled and the like. My main question is on graphics. Are the AWT Image functions fast enough in comparrison to perhaps my own custom blitting routines? I''ve seen ways for accessing the pixel data directly... would it be quicker, and worth the effort, of writing my own pixel copying functions rather than using the basic drawImage() func? What is the prefered professional way of doing this? It would also be great if anyone had some source for a similar game applet (jdk 1.1) so I could see just how to lay out my graphics classes etc. Any help greatly appreciated, Cheers, Russ. russx2@btinternet.com

Share this post


Link to post
Share on other sites
Well, I think that things such as image masking (for transperacy in sprites etc.) is often fastest achieved by using transparent gif images and feeding them to some variant of drawImage().

For other image manipulation, you could use an ImageProducer and write the pixel array directly. I tend to use both of these methods, depending on what I''m coding.


/ dr-m

Share this post


Link to post
Share on other sites
Using paint() routines and drawImage() is not blitting. The paint function is called whenever the JVM feels like calling it. There is no ''professional way'' of doing games/graphics in java, you might want to look at some java demos (www.cfxweb.net). Forcing the JVM to update is something that can be done with ImageObserver and things like that, but I''m not sure how much compatability you''ll get w/java1.1. You''re pretty much on your own for doing this sort of advanced 1.1 stuff. If you manage to do it, I''ll be highly impressed.

Share this post


Link to post
Share on other sites
Hi,

Just as a follow up to this post, what is the general opinion on forcing your own renders?

By this I mean overriding paint(), repaint() and update() etc. and just obtaining the screen reference directly (this.getGraphics()) and drawing everything in the main loop.

Are there any advantages or pitfalls to this method? Can it be recommended at all?

Thanks for your time,

Russ

Share this post


Link to post
Share on other sites
I''ve done quite a bit of Java 1.1 game programming (many of the games on www.loquesea.com, a Latin-American portal site, were written by me).

Use the Java blit-like functions (drawImage, etc) whenever possible. Its very likely that these are in fairly well optimized C/C++ (though it depends what JVM the applet is running under). If you write your own routines in Java you may get slightly more consistent results, but on decently optimized JVMs (like the MS JVM run from IE) they will be slower than the built-in functions, even if you write theoretically ''perfect'' algorithms.

Do as much as you can in offscreen buffers and then blit these to one large offscreen buffer the same size as the Applet (preferably using some sort of dirty rectangle system to cut down on the memory copies), and then blit this larger offscreen buffer to the main graphics object in one call.

Something like this works well as a paint method (where offscreen is an Image object and drawMyGameStuffIntoOffscreenBuffer() takes a Graphics object and uses it to drawImage/pixelpush/whatever your graphics into it):


public void paint(Graphics g)
{
if(offscreen == null)
{
offscreen = createImage(getSize().width, getSize().height);
}

Graphics og = offscreen.getGraphics();

drawMyGameStuffIntoOffscreenBuffer(og);

g.drawImage(offscreen, 0, 0, null);
og.dispose();
}



Its often good to override the [update(Graphics g)] method of the Applet to have it simply call paint(), ala:

public void update(Graphics g)
{
paint(g);
}


Otherwise update will ''clear'' the display before calling paint which can result in some slowdown that doesn''t need to be there (since you''ll cover the screen with your offscreen image each frame anyway), and possibly annoying flicker, depending on the JVM.

Share this post


Link to post
Share on other sites
In response to your other question -- I suggest keeping the drawing stuff in ''paint()'' just to be somewhat ''standard''.

However, you *can* put a call to repaint() in the main loop, which should force the JVM to call paint. That''s how most of the ''arcady'' games I''ve written have worked. Yes, it will cost you a function call, but it keeps things a bit cleaner and the cost is really negligable (at least under IE and Netscape 4''s JVMs, which were the primary two I''ve targetted).

The more traditional board-type games allowed the JVM to do lazy repaint()ing as it saw fit...that was good enough for them.

Share this post


Link to post
Share on other sites
Well the main question is it real time or not?

The Tips I am about to give you are for real time stuff....

First of all I recommened setting the paint() & and update() methods to {} - otherwords nothing. Other wise they will run concurrently to your main loop which slows things down and makes things messy.

Have a Graphics var that you use to refer to the applet graphics object ( I use a var like this Graphics gm; standing for graphics main), initialize this in your init method like this....

gm = this.getGraphics();

By refering to that you will be able to draw to the applet display area.

Now the next big question is how much do you want to draw and how much control do you want over the drawing process?

Becasue at a certain point after you draw X amount of things it is actually quicker to do your own blitting methods.

You may do this buy construct a pixel buffer (just an int array 0xAARRGGBB) and build an image from that. You do that buy creating an image source to build the image from. If you don''t require masking (or are doing you own blitting and masking) then it is also a good idea to use a 24 bit color model (which can be feed into the image source when you construct the image for the first time) and this way the constructed image won''t be masked and built about %30 faster. Also setAnimated(true) on your image source and then you can use the .newPixels() method when reconstructing the image each frame (don''t forget to construct the image with createImage when initializing in for the first time) which is also faster as you don''t create a new image each time.

That is the fastest way to do graphics. Doing you own blitting may seem a bit of a development over head but once you have done that then the amount of control you have is limitless and you can do real time drawing fx instead of having to use pre rendered images and since the JVM has a memory limit of something between 48-64megs if you have a graphics intensive game (like my game Nebuloids which runs at the edge of the JVM which is a bit naughty! ) then you can consume that free space in no time at all!

For an example of some the real time stuff I am talking about please check out my Chaoslab & Chaoslab2 (alpha).

Hope that is helpful.

Any one how thinks java is not a real contender in the game development world has there head in the sand and once you get used to the kid gloves that java provides you won''t miss C/C++ and all it hang ups (pointers? who needs em!). As JVM gets faster and PC''s get faster the performance issue with java will be less of an issue, not that I have noticed that much, most performane issues are due to bad design.

Oh yeah and one last thing, I would suggest getting Opera as it is a wonderful browser as an alternative to IE (which still has the faster JVM by far!) as stuff that works in Opera will work in NS and Opera is much more of a better user epxerience compared to NS. At the end of the day I use IE the most as its the fastest but I still test stuff in Opera to make sure it is truly cross platform compatible and since it uses the Sun Hot Spot JVM 1.3.1 you know your code will be good on other plats (not that I have had many problems outside of small descrepancies on the IMACS).

:-)









Share this post


Link to post
Share on other sites