Don’t use BufferStrategy, or add a Canvas to the Applet.
Aren’t the static ints x and y rather expensive? I’m doing something similar, but storing everything in one array of ints. Seems to save nearly 100 bytes.
Keys go into the array based on keycode. Mouse coords go into [ 0 ] and [ 1 ], and the mouse button state into [ 2 ]. I’m not tracking the other mouse buttons, but that would be easy to add.
public void processEvent(AWTEvent e)
{
int id = e.getID();
if (id == KeyEvent.KEY_PRESSED || id == KeyEvent.KEY_RELEASED) // 401 or 402
{
mouseAndKeys[((KeyEvent) e).getKeyCode()] = 402 - id;
}
if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED) // 501 or 502
{
mouseAndKeys[2] = 502 - id;
}
if (id == MouseEvent.MOUSE_MOVED || id == MouseEvent.MOUSE_DRAGGED)
{
mouseAndKeys[0] = ((MouseEvent) e).getX();
mouseAndKeys[1] = ((MouseEvent) e).getY();
}
if (id == WindowEvent.WINDOW_CLOSING)
{
mouseAndKeys[KeyEvent.VK_ESCAPE] = 1;
}
}
Andy.
[quote=“Ranger,post:20,topic:32568”]
I have overridden the init, destroy, processKeyEvent, and paint, methods. I have also implemented the run method from the Runnable interface. The init method starts my game loop thread. The destroy method sets a boolean flag to tell the run method to stop. It is a lot of overhead, and I am hoping there is a more efficient way?
this is my best working applet-structure:
public class Name extends Applet implements Runnable {
Image I;
public void init() { (new Thread(this)).start(); }
public void update(Graphics g) { g.drawImage(I,0,0,this); }
public void run() {
while(true) {
// code here
repaint();
Thread.sleep(30);
}
}
}
for double-buffering use another Image (eg. J) and paint everything
to J and at the end draw J to I, this should work quite well.
maybe you can replace the update-method too, by replacing
repaint() with getGraphics().drawImage(I,0,0,null), if so you
dont need I to be global, but I have not tested this…
Just found out why you said Don’t. Using a Canvas and calling createBufferStrategy and getBufferStrategy uses more bytes then overriding the paint method and calling repaint. :
I think you’ll find if the user refreshes the web page, the init method will be called again, kicking off another thread, and the old thread will continue to run.
Also, I think you want to override the paint method, not the update method.
Finally, you may like to look at using VolatileImages.
…but I could be wrong.
You can override update-method to ensure repaint is only done when you call repaint().
paint-method is called more often (when os calls the applet to repaint eg)
I got an email asking me how I dealt with destroy() calls in my L4kD applet, and here it is:
public void run()
{
// Set up
while (true)
{
// Game logic
if (!isActive()) return;
}
}
Ah! Never realised the isActive method existed, and it is exactly what I was after! Thank you!!!
I’m so desperate for bytes, I’m questioning the masters! :o
FYI: The template listed on http://wiki.java.net/bin/view/Games/4KGamesDesign says:
static boolean keys[] = new boolean[65536];
public static void main(String args[]) {
However, moving the keys array instantiation into the main method saved me 12 bytes:
static boolean keys[];
public static void main(String args[]) {
keys = new boolean[65536];
The template also says: t.enableEvents(AWTEvent.KEY_EVENT_MASK); However, aren’t key events on by default?
I know when I override processKeyEvent(KeyEvent event) I do not have to enable key events. You might still need to enable them if you override processEvent(AWTEvent event) instead. Going with processKeyEvent will also save you the cast from AWTEvent to KeyEvent.
Hmm, that’s interesting - I wonder if that is a quirk of a particular implementation, or is a documented piece of functionality.
What is your main Container subclassing? Applet, Frame or JFrame?
To date, it’s always been JFrame, and it’s Sun’s JRE 1.6.0_03.
Edit: I just did a test with the game I’m currently implementing. It extends JFrame, and calls enableEvents(0x30) - that’s AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK, for those not familiar. I added an override for processKeyEvent, and sure enough I’m receiving key events even though they were not explicitly enabled,
I tried to delete the enableEvents() call, but the game stopped working, could you test comenting your code and looking if the keyboard works?? (I’m in jdk1.6.0_11)
I’m subclassing JApplet. Java 1.6.0_10
I found the Java code that enables the key events. It’s in the first line of the JComponent constructor
public JComponent() {
super();
// We enable key events on all JComponents so that accessibility
// bindings will work everywhere. This is a partial fix to BugID
// 4282211.
enableEvents(AWTEvent.KEY_EVENT_MASK);
Looks like it has been there since Java 1.3.
Ah, good find.
Though, that doesn’t explain the behaviour of Applet/JApplet/Frame or JFrame?
Unless ofcourse Container has the same call in it’s constructor? (too lazy to start Eclipse & check myself :D)
Logically, I guess this means that if you ever call disableEvents(AWTEvent.KEY_EVENT_MASK) on a JComponent, it will have the side-effect of causing accessibility bindings(what are those???) to stop working…
Something the fixer should of thought about when they put that hack fix in :
So, does the Apple JRE also contain this same quirk?
Tip of the day:
BULLET/LASER/MACHINE GUN EFFECT
Ah, those dreaded bullets that your player or baddies generates. Takes up a lot of code do to all that bullet management code! E.g., making array for storing bullets, position, where they are going, do collision detection etc?
SIMPLE SOLUTION! Create a STROKE that alternates:
BasicStroke bulletStrokes[] = {
new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, new float[] {2, 26}, 0),
new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, new float[] {2, 26}, 7),
new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1, new float[] {2, 26}, 14)
};
Then you can simply alternate the index to the bulletStrokes array in order to animate. The above array has the exactly same bullet, but the last parameter tells how it’s shifted in order to make it animate. 2 strokes are enough if it’s some sort of machine gun effect.
Now, let’s say you have some sort of tank positioned at x,y and it’s supposed to shoot shots at a enemy tank positioned at a,b you can simply:
g.setStroke(bulletStrokes[currentStroke]); // currentStroke is an index for animation purposes.
g.drawLine(x,y, a,b);
TA DA! That’s all the bullet code you need.
You can tweak around with the BasicStroke objects to create some nice effects, e.g. if you wish to create lasers or something like that.
Of course this doesn’t solve all problems, but for many this will help.
JApplet calls setRootPane(createRootPane()); in its constructor. JRootPane inherits from JComponent.
So… I will have to change my awt.Frame for swing.JFrame, to get the keyboard enabled?
This will work on the Sun JVM. Not sure about Mac, IBM, and others. Personally, I’ve played it safe and left the enableEvents call in.
ProGuard came out with a new version (4.3) just a few days ago http://proguard.sourceforge.net/
Not sure if update will help any 4K games, but still nice to have the latest.
I think I just decided I don’t want to do this anymore because every single obfuscater I try to use seems to get some error or another. They’re basically a ginormous pain to use, and nobody seems to have put any straight up clear examples of their use. Is there something I’m missing? You all are able to say “this saved X bytes!” etc. but I can’t do that because I don’t know how small it will get with all those optimization programs. :-\
So can anyone help me out? It doesn’t seem like it should take 20 minutes every single build to compress everything and see how small it actually is supposed to be. I mean my game is like 400 lines and I’m using 3,204 bytes, so my code is certainly written in a space-saving fashion but I still don’t have an obfuscater working. Hm.