Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (491)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (556)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2] 3 4
  ignore  |  Print  
  Preliminaries (tentative)  (Read 19674 times)
0 Members and 1 Guest are viewing this topic.
Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #30 - Posted 2009-10-26 19:11:33 »

@Kapta; Markus,

Thanks for your help, and clarification on why applets have become more popular.  I'll use start() rather than init() in my template and start coding from there. Smiley

Alan

Time flies like a bird. Fruit flies like a banana.
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #31 - Posted 2009-10-26 23:58:59 »

My applets have always ended up smaller than my stand-alone 4k games. You get a free component to paint on just by inheriting from Applet, no need to create it or set up any size or even make it visible.
You can check the source code for Left 4k Dead if you wish: http://www.mojang.com/notch/j4k/l4kd/G.java

I wouldn't recommend running much logic in start() or init() as those are supposed to return as fast as possible, so you pretty much HAVE to create a Thread. I do this in start() instead of init() to be able to rely on isActive(). This means that the game could in theory stop and restart when someone opens another tab in some obscure browser or something, but in reality I've never seen it. (and it's not a HUGE problem anyway imo, people tend to stay on the game page)

Maybe we should offer some template code so that participants can get easily started with applets. I'm guessing some will have difficulties getting started with Applets, and I surely would like everyones Applets to work well in browsers.

On the todo list Smiley

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #32 - Posted 2009-10-27 02:09:41 »

I don't think you need to implement any of the Applet signalling methods start(), init(), stop() or destroy().

Spawn the Thread in the constructor.
As you always have a constructor (even if none is declared), you might as well make use of the method signature being in the constants pool.
Then, just use isActive() to control the behaviour of the Thread.

Something like this :-

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;

public class H extends Applet implements Runnable {

   public H() {
      new Thread(this).start();
   }
   
   public void run() {
      boolean started = false; //this latch prevents the Thread immediately terminating (as isActive() will return false for the period between the constructor call & start() call)
     do {
         if(isActive()) {
            started = true;
           
            Graphics g = getGraphics();
            g.setColor(new Color((int)(Math.random()*0xFFFFFF)));
            g.fillRect(0, 0, getWidth(), getHeight());
           
         }
         else {
            if(started) {
               return;
            }
         }
         
      }
      while(true);
   }
}

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #33 - Posted 2009-10-27 02:19:00 »

The only way I can think of improving upon this would be to eliminate the spawning of the Thread (along with Runnable interface and run() method).

Instead, you use the EDT to perform your animation loop by calling repaint() at the end of your overridden paint(Graphics) method.

It might work..... though you'd have to work out a way of throttling the frame time without halting the EDT for too long.
And you might run into problems with outside events interrupting the repaint cycle....
Big downside though is that you have to store all of your state in member variables rather than locals.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #34 - Posted 2009-10-27 06:53:52 »

I don't think you need to implement any of the Applet signalling methods start(), init(), stop() or destroy().

Ingenious , although I suspect that if you navigate away from the page  and then back again, you might get a blank page, as the 'run' thread will have terminated, but the applet may still be loaded.  Of course one could just leave the thread running, but I guessing it might not stop until the browser was shut down.

Alan

Time flies like a bird. Fruit flies like a banana.
Offline kappa
« League of Dukes »

JGO Kernel


Medals: 77
Projects: 15


★★★★★


« Reply #35 - Posted 2009-10-27 07:05:12 »

Ingenious , although I suspect that if you navigate away from the page  and then back again, you might get a blank page, as the 'run' thread will have terminated, but the applet may still be loaded.  Of course one could just leave the thread running, but I guessing it might not stop until the browser was shut down.

Alan


you could also just use the seperate_jvm parameter so (at least on the new applet plugin) every time you visit the applet it'll be in a different vm.
Offline pjt33
« Reply #36 - Posted 2009-10-27 08:39:06 »

Instead, you use the EDT to perform your animation loop by calling repaint() at the end of your overridden paint(Graphics) method.
You'd have to mark the whole applet as dirty as well, wouldn't you?
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #37 - Posted 2009-10-27 09:15:32 »

I don't think you need to implement any of the Applet signalling methods start(), init(), stop() or destroy().

Spawn the Thread in the constructor.
As you always have a constructor (even if none is declared), you might as well make use of the method signature being in the constants pool.
Then, just use isActive() to control the behaviour of the Thread.

I wouldn't recommend this, since the applet would only be able to run once.

Play Minecraft!
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #38 - Posted 2009-10-27 10:32:50 »

Ingenious , although I suspect that if you navigate away from the page  and then back again, you might get a blank page, as the 'run' thread will have terminated, but the applet may still be loaded.  Of course one could just leave the thread running, but I guessing it might not stop until the browser was shut down.

Alan

Ah. hadn't considered that; I only tested it in the Applet viewer.

Well.... leaving the Thread running isn't *that* nasty =) (and infact, makes the code even smaller!)

:edit:

Or, instead of spawning the Thread in the constructor, spawn it from the EDT when the first Event is received.
It can then safely be discarded when isActive() begins returning false, and re-animated if the Applet starts receiving Events again.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #39 - Posted 2009-10-27 12:06:21 »

Or, instead of spawning the Thread in the constructor, spawn it from the EDT when the first Event is received.
It can then safely be discarded when isActive() begins returning false, and re-animated if the Applet starts receiving Events again.

You, sir, are a genius.

Play Minecraft!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #40 - Posted 2009-10-27 14:24:31 »

You, sir, are a genius.

I discovered something else last-night, and while I should probably keep it to myself for the competitive advantage.....
I just can't bare to see other peoples fantastic games reaching less than their full potencial because they were a few bytes short.


So, if you use the old Java1.0 event model, you significantly reduce the number of class and method references in the constants pool.

1  
Component#handleEvent(Event)


1) It receives all events (no filtering), so you completely eliminate the call to Component#enableEvents(long).
2) The Event class is general purpose (used for all Event types), so it completely eliminates references to java.awt.event.KeyEvent & java.awt.event.MouseEvent.
3) The Event class even has public members, rather than getters! (eliminating references to getKeyCode(), getID(), getButton(), getX() and getY() !!!)
5) "java.awt.Event" is 3 chars shorter than "java.awt.AWTEvent" =)
4) "handleEvent" is 1 char shorter than "processEvent" =))))

By my guesstimates, that should save ~50-100 bytes of compressed code!
Just think what Left4KDead could have done with that space! You could have made it a full-on 3D FPS no problemo  Wink

It's like the Java1.0 event model was written specifically for the 4K contest!!

Only problem (sounded too good to be true) is it's deprecated (obviously), and while it appears to work in Windows, there's no guarantee it'll work correctly on Mac or Linux.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline pjt33
« Reply #41 - Posted 2009-10-27 16:34:31 »

It's like the Java1.0 event model was written specifically for the 4K contest!!

Only problem (sounded too good to be true) is it's deprecated (obviously), and while it appears to work in Windows, there's no guarantee it'll work correctly on Mac or Linux.
Works on Linux with 6.0.14, but two additional caveats for people handling key input:
1. You may need to process 4 key event types, not 2, because "action" keys get different types.
2. Some keys (meta, shift, ctrl) don't fire events. (Particular nuisance for me because I was thinking of making a Shift-like).
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #42 - Posted 2009-10-27 17:07:52 »

1. You may need to process 4 key event types, not 2, because "action" keys get different types.

Nothing a little &1 can't fix!
1  
inputs[e.key] = e.id&1;


The lack of events for modifier keys sux a bit; Java1.0 must have been completely rubbish!
Looks like it's going to be WASD+Space - sorry to those with 'wrong' key layouts  Grin

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline pjt33
« Reply #43 - Posted 2009-10-27 22:10:23 »

Shudder. You're going to lose key presses that way.
Offline pjt33
« Reply #44 - Posted 2009-10-27 23:08:52 »

Or, instead of spawning the Thread in the constructor, spawn it from the EDT when the first Event is received.
It can then safely be discarded when isActive() begins returning false, and re-animated if the Applet starts receiving Events again.
Tested and it increases code size. You need a field to be able to determine whether the event is the first one, so there go most of the savings from removing the start() method. Then you need additional logic to handle isActive() potentially being false when you enter run(). I tried two different approaches to the latter and they added respectively 18 and 27 bytes after proguard and kzip optimisation.

Of course, you might be able to argue that you shouldn't get events before start(), and so isActive() should be true. I tried that too, and it added 11 bytes. Instead of a method which unconditionally calls "new Thread(this).start()" you need a guard on isRunning==0 and to set isRunning to 1; and you also need to reset isRunning to 0 at the end of the run() method.

Edit: also, note that I've just discovered that with appletviewer 1.6.0_14 the stuff in the API doc about "An applet is marked active just before its start method is called. It becomes inactive just before its stop method is called." is not true. Printing isActive() in the start() method prints "false". This explains a problem I've observed in the past... (Addendum: having added a workaround for it, I've finally got Gravitational Fourks to work reliably in the browser). Anyway, the prudent thing is to assume that !isActive() when entering run.

Relevant code is in AppletPanel.run lines 457 to 492:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
                  case APPLET_START:
                  {
                      if (status != APPLET_INIT && status != APPLET_STOP) {
                          showAppletStatus("notinited");
                          break;
                      }
                      applet.resize(currentAppletSize);
                      applet.start();

                      // Validate and show the applet in event dispatch thread
                     // to avoid deadlock.                      
                     try {                          
                          final AppletPanel p = this;
                          final Applet a = applet;

                          EventQueue.invokeAndWait(new Runnable() {
                                  public void run() {
                                      p.validate();
                                      a.setVisible(true);

                                      // Fix for BugTraq ID 4041703.
                                     // Set the default focus for an applet.
                                     if (hasInitialFocus())
               setDefaultFocus();
                                  }
                              });
                      }
                      catch(InterruptedException ie) {
                      }
                      catch(InvocationTargetException ite) {
                      }

                      status = APPLET_START;
                      showAppletStatus("started");
                      break;
                  }

The setting of status to APPLET_START constitutes setting isActive() to true, so after Applet.start() is called it's almost guaranteed to yield to another thread before isActive().
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #45 - Posted 2009-10-27 23:39:09 »

This seems to work for me.
Granted I still haven't bothered trying it in a browser yet  Roll Eyes

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
import java.applet.Applet;
import java.awt.Color;
import java.awt.Event;
import java.awt.Graphics;

public class H extends Applet implements Runnable {

   private static final int MOUSE_EVENTS = 500;
   private static final int MOUSE_X = 1, MOUSE_Y = 2, MOUSE_DOWN = 3;
   int[] input;
   
   public boolean handleEvent(Event e) {
      if(input==null) {
         // use the presence of the input [] to indicate whether the Thread has been started.
        input = new int[0xFFFF]; //TODO, change the dimension of the array to be a value used elsewhere in the program.
        new Thread(this).start();
      }
      final int id = e.id;
      if((id&~3)==MOUSE_EVENTS) {
         input[MOUSE_X] = e.x;
         input[MOUSE_Y] = e.y;
         //input[MOUSE_DOWN] = blahblah TODO
     }
      input[e.key] = id&1;
      return true;
   }
   
   public void run() {
      boolean started = false;
      do {
         if(isActive()) {
            started = true;
           
            Graphics g = getGraphics();
            g.setColor(new Color((int)(Math.random()*0xFFFFFF)));
            g.fillRect(0, 0, getWidth(), getHeight());
         }
         else {
            if(started) {
               input = null;
               return;
            }
         }
      }
      while(true);
   }
}

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline pjt33
« Reply #46 - Posted 2009-10-27 23:44:38 »

This seems to work for me.
Nice trick to reuse a field - I should have thought of that. However, you might get away with your implementation, but it's certainly not thread-safe. Make it thread-safe with
1  
2  
3  
4  
5  
6  
      int[] input = this.input;
      if (input == null)
      {
         this.input = input = new int[NUM_KEYS];
         new Thread(this).start();
      }
and (with my skeleton class, at least) it uses exactly the same number of bytes as the version with a start() method. (It's slightly larger uncompressed, but compresses better).
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #47 - Posted 2009-10-28 00:06:57 »

Nice trick to reuse a field - I should have thought of that. However, you might get away with your implementation, but it's certainly not thread-safe. Make it thread-safe with
1  
2  
3  
4  
5  
6  
      int[] input = this.input;
      if (input == null)
      {
         this.input = input = new int[NUM_KEYS];
         new Thread(this).start();
      }
and (with my skeleton class, at least) it uses exactly the same number of bytes as the version with a start() method. (It's slightly larger uncompressed, but compresses better).

I don't think that is necessary.
The Thread I spawn only ever sets the input [] to null.
The EDT Thread only ever assigns a value to the input [] if it is already null.

Multiple Threads can never be concurrently executing the EDT method handleEvent(...).
Multiple Threads can only be concurrently executing run(...) in the code immediately proceeding the 'input = null' assignment. (and as this assignment is the last action the Thread takes, it's safe)

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline pjt33
« Reply #48 - Posted 2009-10-28 00:20:03 »

There's a risk of NPE if the run thread sets input to null between the EDT starting the run thread and finishing the handleEvent call, and Murphy's law says that it will happen when the judges are testing your game...
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #49 - Posted 2009-10-28 00:33:24 »

There's a risk of NPE if the run thread sets input to null between the EDT starting the run thread and finishing the handleEvent call, and Murphy's law says that it will happen when the judges are testing your game...

Ahhhhhhh, NPEs in the EDT handleEvent(...).....yeah, IAOOB is possible in there too; but who cares - the EDT isn't killed by Exceptions.
The one thing that mustn't happen is the application Thread dying to an Exception, as it'll exit without the input [] being set to null. Consequently preventing the app. ever restarting (until the Browser is restarted).

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #50 - Posted 2009-10-28 06:13:10 »

Edit: also, note that I've just discovered that with appletviewer 1.6.0_14 the stuff in the API doc about "An applet is marked active just before its start method is called. It becomes inactive just before its stop method is called." is not true. Printing isActive() in the start() method prints "false". This explains a problem I've observed in the past... (Addendum: having added a workaround for it, I've finally got Gravitational Fourks to work reliably in the browser). Anyway, the prudent thing is to assume that !isActive() when entering run.

I checked the JavaDoc for start() and it suggests that the component may not be showing when start() is called, which potentially means that it still might not be showing when run() starts, in which case a call to getGraphics() will probably return null.  I found the following article which suggests this can happen
http://java.sun.com/j2se/1.4.2/docs/guide/deployment/deployment-guide/upgrade-guide/article-09.html

Supposing I want to grab the graphics context once (before entering the main game loop), it may be worth doing the following:
1  
2  
3  
4  
5  
6  
7  
run() {
// Game Initialisation
while((g=getGraphics())==null)); // Wait for a valid graphics context
do {
// Game Loop
yield(); // Allow the other threads some execution time
} while (isActive()); // Possibly leave this test to the end of the game loop and hope it is set by now.

Edit: I wonder if the graphics context can go invalid, before I catch isActive() going inactive.  Not a nice thought.

Time flies like a bird. Fruit flies like a banana.
Offline pjt33
« Reply #51 - Posted 2009-10-28 07:49:03 »

I checked the JavaDoc for start() and it suggests that the component may not be showing when start() is called, which potentially means that it still might not be showing when run() starts, in which case a call to getGraphics() will probably return null.  I found the following article which suggests this can happen
It does happen. I've seen it, and now check for it.

Edit: I wonder if the graphics context can go invalid, before I catch isActive() going inactive.  Not a nice thought.
Yes. Minimise and maximise the browser. If you're holding onto the graphics object you can get some serious weirdness, especially with Windows (due to Sun deliberately violating the contract with DirectX).

Updated: Here's my current skeleton for keyboard-only games, using various of Abuse's suggestions from this thread. 934 bytes compressed with Proguard 4.2 and kzip.
Updated again following criticism of starting the thread in the ctor and making run() contain an infinite loop.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;

/**
 * Testbed for the basics.
 */

public class Skeleton extends Applet implements Runnable
{
   // Constants.
  // Must be at least 1026 if using Java 1.0 event model or someone accidentally
  // hitting Ins will get AIOOBE. Pick a number used elsewhere and reuse it to
  // save a constant pool entry.
  private static final int NUM_KEYS = 1026;

   private static final int WIDTH = 640;
   private static final int HEIGHT = 480;

   // Shared state. In the spirit of lock-free synchronisation, this is written
  // only by the event thread, and it advances values rather than setting /
  // resetting. This ensures that quick key presses aren't lost.
  private int[] keyEventCount = new int[NUM_KEYS];

   @Override
   public void start()
   {
      new Thread(this).start();
   }

   public void run()
   {
      // Set up event handling. Note: keyDown[key] and keyPressed[key] are 0
     // for false; any other value should be interpreted as true.
     int[] prevKeyEventCounts = new int[NUM_KEYS];
      int[] keyDown = new int[NUM_KEYS];
      int[] keyPressed = new int[NUM_KEYS];

      // Game state.
     int x = 320;
      int y = 320;

      // Set up backbuffer for rendering.
     BufferedImage buf = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
      // Uncomment if you want to set pixels directly.
     //int[] ibuf = ((DataBufferInt)buf.getRaster().getDataBuffer()).getData();

      while (!isActive()) /* Busy-wait */;
      while (isActive())
      {
         try
         {
            long now = System.currentTimeMillis();

            // Events.
           for (int i = 0; i < NUM_KEYS; i++)
            {
               int eventCount = keyEventCount[i];
               // An odd number of events means that it's down. Simple!
              // NB If you're worried about key repeat you might want
              // instead to say
              //     keyDown[i] = (delta >> 1) + (eventCount & 1);
              keyDown[i] = eventCount & 1;
               // The key was pressed since the last loop if the number of events
              // since then is at least two, by the pigeonhole principle, or if
              // the number of events since then is positive and the key is down.
              // Since we only need to catch the second case when delta == 1,
              // we can simplify the key-is-down test a bit.
              int delta = eventCount - prevKeyEventCounts[i];
               keyPressed[i] = (delta >> 1) + (delta & eventCount);
               prevKeyEventCounts[i] = eventCount;
            }

            // Logic.
           if (keyDown[Event.LEFT] != 0) x--;
            if (keyDown[Event.RIGHT] != 0) x++;
            if (keyDown[Event.UP] != 0) y--;
            if (keyDown[Event.DOWN] != 0) y++;

            // Render to backbuffer.
           Graphics g = buf.getGraphics();
            g.setColor(new Color(0x000000));
            g.fillRect(0, 0, WIDTH, HEIGHT);
            g.setColor(new Color(0xffffff));
            g.drawString("Score", x, y);

            // Render backbuffer to front buffer and tidy.
           Graphics gapp = getGraphics();
            if (gapp != null)
            {
               gapp.drawImage(buf, 0, 0, this);
               gapp.dispose();
            }
            g.dispose();

            // Sleep. There are various ways of doing this, but IME you need to
           // sleep rather than yield under Linux.
           long t = System.currentTimeMillis();
            long sleep = 20 - (t - now);
            now = t;
            if (sleep > 0)
            {
               Thread.sleep(sleep);
            }
         }
         catch (Throwable ie)
         {
               
         }
      }
   }

   @Override
   public boolean handleEvent(Event evt)
   {
      // Non-key events have 0 for their key field.
     keyEventCount[evt.key]++;
      return false;
   }
}
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #52 - Posted 2009-10-28 19:45:46 »

So in your Skeleton example you've opted for leaving the Thread running forever (until the browser is killed)?
If everyone does that, the judges machines might start to choke by the time they come to play the 30th entrant =D



Other than that, worth highlighting these two:

1) If you arn't interested in preventing crashes as a result of erroneous Exceptions

1  
public void run() throws Exception
instead of try/catch.

2) As far as i'm aware calling g.dispose() is unnecessary for Graphics objects that draw onto offscreen images (BufferedImage in your Skeleton example)
As you are calling dispose() anyway, the saving will be minimal. Though you could always be naughty and not call dispose() on your onscreen Graphics object too; that'd reap more significant size savings, with only a small chance of it blowing up someones machine  Cheesy

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline appel

JGO Wizard


Medals: 50
Projects: 4


I always win!


« Reply #53 - Posted 2009-10-28 20:43:29 »

So in your Skeleton example you've opted for leaving the Thread running forever (until the browser is killed)?
If everyone does that, the judges machines might start to choke by the time they come to play the 30th entrant =D

I am very worried about this. Some programmers might bypass some formalities to make _their_ game work, not caring about what effect leaving idle resources running in the browser will cause, or they might do so inadvertently.

I guess we'll need a rule to ensure this doesn't happen, and also some code templates to help programmers to make sure their applet works right.


Maybe there's a way to define this in the html applet tag?


Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #54 - Posted 2009-10-28 20:45:21 »

Quote
I guess we'll need a rule to ensure this doesn't happen, and also some code templates to help programmers to make sure their applet works right.
+1

Offline pjt33
« Reply #55 - Posted 2009-10-28 22:12:28 »

So in your Skeleton example you've opted for leaving the Thread running forever (until the browser is killed)?
If everyone does that, the judges machines might start to choke by the time they come to play the 30th entrant =D
I was rather assuming that the plugin was more intelligent than that. Bah.

Quote
2) As far as i'm aware calling g.dispose() is unnecessary for Graphics objects that draw onto offscreen images (BufferedImage in your Skeleton example)
As you are calling dispose() anyway, the saving will be minimal. Though you could always be naughty and not call dispose() on your onscreen Graphics object too; that'd reap more significant size savings, with only a small chance of it blowing up someones machine  Cheesy
You're probably correct on the first, but it's only about 3 bytes. On the second, I believe I have had issues with this also in the past.
Offline Alan_W

JGO Knight


Medals: 8
Projects: 3


Java tames rock!


« Reply #56 - Posted 2009-10-29 05:35:49 »

I wrote a demo Applet and tried to break it...

Using Appletviewer, isActive() is still false about 50% of the time on entry to run();  Internet Explorer, Firefox and JNLP Applet seem to set isActive() earlier.  Adding a yield() before checking isActive() improves matters, although sometimes it takes more than one yield().  Adding while(!isActive()) Thread.yield(); at the start of run() makes AppletViewer work 100%, but is it worth the overhead to fix what is predominantly an Appletviewer problem.

If you grab the Graphics context on Internet Explorer at the start of run(), it doesn't return null (so no exception), but it isn't linked to the native peer, so nothing displays.  Also Internet Explorer changes the device context everytime you minimise and then maximise the browser.  Thus we must do getGraphics() inside the game loop.  While you can skip the dispose(), this means that unreleased graphics contexts build up until a garbage collection occurs.  The question is whether it is worth including the overhead of dispose() to add robustness to the applet.

Lastly, if the browser navigates away from the page containing the applet or you close the browser, then the graphics context obtained at the start of the loop becomes null, even if it wasn't null when you performed getGraphics().  The probability of this can be reduced by postponing getGraphics() until just before you need it, testing for null and only drawing on the device if it's valid.  However I found that occasionally, even this isn't sufficient as windows manages a context switch between the test for null and the draw.  i.e. the operation is not atomic.  Using try {...} catch (Exception e){} around the draw routine catches the exception, but costs more bytes.  The question is whether it is worth adding the overhead of try/catch to catch an exception that only occurs when the user is navigating away from your applet.  As far as I can see this error doesn't actually matter, provided you recreate the Thread when the page is revisited.  This suggests creating the thread in start() and terminating it when isActive() goes false is prudent.  I'm tempted to omit the try/catch and accept the exception occurs.

If we don't try to catch exceptions when the graphics context goes null, it becomes more important to postpone grabbing the context to as late as possible in the main loop, just in case some browser returns null the first time through the loop.  I haven't seen this, but haven't tried every possible browser.

Thus there are tradeoffs between robustness and code size.  If you don't care about appletviewer and null pointer exceptions, then IMO a minimum size template would: create the thread in start(); grab the graphics context as late as possible within the game loop and use it immediately; testing for inActive() at the end of the game loop and terminating the thread if it is false.  If the game spends a fair bit of time initialising it may even work in Appletviewer.

Time flies like a bird. Fruit flies like a banana.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #57 - Posted 2009-10-30 02:42:06 »

Thanks for the awesome and in depth post.

See my work:
OTC Software
Offline rdcarvallo

Senior Member


Projects: 5
Exp: 15 years


2D Java games forever!


« Reply #58 - Posted 2009-11-02 04:00:37 »

 Last year I tried to make my games applets, but i didn't work. So I need to find and "borrow" some 4k applet base.

Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #59 - Posted 2009-11-02 10:08:46 »

Several applet base source codes have been posted in this thread. Wink

Play Minecraft!
Pages: 1 [2] 3 4
  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.

Nickropheliac (15 views)
2014-08-31 22:59:12

TehJavaDev (23 views)
2014-08-28 18:26:30

CopyableCougar4 (29 views)
2014-08-22 19:31:30

atombrot (41 views)
2014-08-19 09:29:53

Tekkerue (38 views)
2014-08-16 06:45:27

Tekkerue (35 views)
2014-08-16 06:22:17

Tekkerue (25 views)
2014-08-16 06:20:21

Tekkerue (35 views)
2014-08-16 06:12:11

Rayexar (72 views)
2014-08-11 02:49:23

BurntPizza (48 views)
2014-08-09 21:09:32
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
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!