Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (121)
games submitted by our members
Games in WIP (577)
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
  ignore  |  Print  
  Links, tips and goodies  (Read 22390 times)
0 Members and 1 Guest are viewing this topic.
Offline appel

JGO Wizard


Medals: 51
Projects: 4


I always win!


« Posted 2008-11-24 02:38:30 »

Good site on 4K game design:
http://wiki.java.net/bin/view/Games/4KGamesDesign

Kevglass's site containing 4K games + SOURCE:
http://games.cokeandcode.com/index.php?page=source


moogie's tool:
Quote
I have made a tool in previous competitions to output the smallest jar from different obsfucators and zip programs.

see http://www.java-gaming.org/topics/4kjo-4k-java-optimiser-version-3-released/18085/view.html

description and command line options here http://www.java-gaming.org/topics/4kjo-four-kilobyte-game-jar-optimiser/15497/view.html



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

JGO Knight


Medals: 2
Projects: 10


I'm Dragonene on IRC.


« Reply #1 - Posted 2008-11-24 12:39:51 »

I don't know if it's of any use, but here's the template I use for my 4k games:
Template4k

The strategy for handling events was originally taken from the Miners4k source that Markus_Persson was kind enough to provide, and the timing code was provided by oNyx a few contests ago.

EDIT: Oops, made a mistake. Reuploading shortly.
EDIT2: Fixed. I made a few changes to my original template, but I think it'll be fine.

Offline tom
« Reply #2 - Posted 2008-11-24 14:27:32 »

Nice template. However you'll save a bunch of bytes if you just use the nano timer instead of the rolling average implementation. I think oNyx used the rolling average because Java 1.5 was not allowed at that time.

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

JGO Knight


Medals: 2
Projects: 10


I'm Dragonene on IRC.


« Reply #3 - Posted 2008-11-24 17:51:49 »

I'm not sure I understand what you mean. Using nanoTime would give me more exact time, but if one removed the rolling average, the framerate would be more jumpy in either case. The advantage to having a sleep that varies in length, of course, that it'll stay around your desired FPS (in the case of the template, 62), while giving your calculations some freedom (they might not take the same amount of time each frame). Calculating the sleep time based on an average over the last few frames smooths it out.

Offline tom
« Reply #4 - Posted 2008-11-24 20:56:36 »

I believe the rolling average was made to hide the inacuracy of currentTimeMillis. You don't have to do that with nanoTime. As long as you've got cycles to spare you can cap the framerate perfectly. Here is the code to cap the framerate to 60 fps:
1  
2  
3  
4  
5  
          // wait 16 milliseconds to cap frame rate to 60 fps
          while (System.nanoTime() < lastFrame + 16000000) {
             Thread.yield();
          }
          lastFrame = System.nanoTime();


Edit: I saved 49 bytes when I rewrote Pinball4K from rolling averate to nanoTime

Offline Abuse

JGO Knight


Medals: 13


falling into the abyss of reality


« Reply #5 - Posted 2008-11-24 21:20:15 »

I believe the rolling average was made to hide the inacuracy of currentTimeMillis. You don't have to do that with nanoTime. As long as you've got cycles to spare you can cap the framerate perfectly. Here is the code to cap the framerate to 60 fps:
1  
2  
3  
4  
5  
          // wait 16 milliseconds to cap frame rate to 60 fps
          while (System.nanoTime() < lastFrame + 16000000) {
             Thread.yield();
          }
          lastFrame = System.nanoTime();


Edit: I saved 49 bytes when I rewrote Pinball4K from rolling averate to nanoTime

Changing it to a "do{...}while" should save you 2 or 3 more bytes, as it gets rid of the unconditional branch instruction (goto) at the end of the while Wink

And the behavioural side-effect might even be considered beneficial!

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

JGO Knight


Medals: 2
Projects: 10


I'm Dragonene on IRC.


« Reply #6 - Posted 2008-11-24 22:27:43 »

Alright - so let me know if you'll be aiming for 1.4.2 or 1.5. If there's a clear majority for 1.5, I'll change it Smiley

Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #7 - Posted 2008-11-25 19:57:49 »

Ye, the old timing code is pure voodoo. It even works reasonable well with a timer resolution of 250msec if the time per frame is pretty consistent (~changes slowly).

>I think oNyx used the rolling average because Java 1.5 was not allowed at that time.

I invented it because nanoTime didn't work on my old machine anymore after I installed an ATI graphics card. It caused a different bus load than the Nvidia card which in turn triggered QPC leaping. I really wish there were some 1msec timer (TGT) in Java. LWJGL for example uses TGT on Windows and currentMillis elsewhere (=1msec - except for Windows, of course).

With 1.5+ I'd use (now that I got a better machine haha) a simple min-cap loop such as the one tom posted. Just with sleep instead of yield. The RADYTT (rolling average damped yield throttling thingy Grin) only uses yield, because there can be so many of them. If 1% of them take 100 times longer than usual you won't notice it, because it would be averaged out in that gigantic pile of yield calls.

Sleep, however, is a different thing. There are only a few calls. If one takes a tad too long you gotta quit the loop right away, but with imprecise timing you wouldn't know and there is a fixed amount of iterations. So, that wasn't an option.

Would be great if sleeps for longer durations than 0 or 1 msec would be as accurate as calling 0 or 1 msec sleeps in a loop, but even that isn't the case. Otherwise sleeping the full amount in one go would have been a good solution.

edit: What's really bad about RADYTT is that the over-/under-steering effects get pretty big if two instances of it are running at the same time (e.g. having 2 games running which use this timing method).

弾幕 ☆ @mahonnaiseblog
Offline ulfjack

Junior Duke





« Reply #8 - Posted 2008-11-25 20:23:35 »

The source for my games is also online, here:

http://ulf.ofahrt.de/4kgames/
Offline Morre

JGO Knight


Medals: 2
Projects: 10


I'm Dragonene on IRC.


« Reply #9 - Posted 2008-11-25 20:50:51 »

I just updated the template some as suggested by oNyx on irc; it no longer reuses the graphics object, as that's supposedly troublesome on certain macs. Thanks oNyx Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online moogie

JGO Knight


Medals: 13
Projects: 6
Exp: 10 years


Java games rock!


« Reply #10 - Posted 2008-11-25 21:26:36 »

The source code for my last two submissions are located:

SupPar (space shooter)
Rally4k (rally racing game)
Offline rdcarvallo

Senior Duke


Projects: 5
Exp: 15 years


2D Java games forever!


« Reply #11 - Posted 2008-11-27 20:26:12 »

Here is my page a bit outdated (doesn't include my j4k2007 entries) for the 4k games from years past...

Juegos en 4K

The Webstart links may not work, the jar and source links are working.

For the non spanish:
Baja el juego -> Download the game
Baja el source -> Download the source.



Offline Markus_Persson

JGO Wizard


Medals: 16
Projects: 19


Mojang Specifications


« Reply #12 - Posted 2008-12-02 18:49:20 »

Here's an optimized processEvent:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
    public void processEvent(AWTEvent e)
    {
        boolean down = false;
        switch (e.getID())
        {
            case KeyEvent.KEY_PRESSED:
                down = true;
            case KeyEvent.KEY_RELEASED:
                k[((KeyEvent) e).getKeyCode()] = down;
                break;
            case MouseEvent.MOUSE_PRESSED:
                down = true;
            case MouseEvent.MOUSE_RELEASED:
                k[((MouseEvent) e).getButton()] = down;
            case MouseEvent.MOUSE_MOVED:
            case MouseEvent.MOUSE_DRAGGED:
                x = ((MouseEvent) e).getX();
                y = ((MouseEvent) e).getY();
        }
    }


Mouse buttons states are in low k[]-values, keys in higher. This has some side effects, but it shouldn't be too bad (some obscure keys might act as mouse buttons).

Play Minecraft!
Offline appel

JGO Wizard


Medals: 51
Projects: 4


I always win!


« Reply #13 - Posted 2008-12-02 20:43:24 »

If you have an image of, let's say a top down view of a car, then you can split that image in HALF, saving 50% of the bytes!

You simply cut it from the top-center and down through the bottom-center, throw away either half. Then you load up your half image and then you can recreate the full image by mirroring the half you kept!


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

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #14 - Posted 2008-12-05 19:21:58 »

then you can recreate the full image by mirroring the half you kept!
What's the best algorithm/object to use for loading images/mirroring them? BufferedImage? ImageIcon? drawImage? Change the Graphics2D transform? Also, what about image rotations?

It would be nice if you could show a little tiny code snippet.

These are sort of combo 4k questions and Java2D questions, I know, but I haven't had much success with Java2D's speed so I usually use LWJGL.

See my work:
OTC Software
Offline Abuse

JGO Knight


Medals: 13


falling into the abyss of reality


« Reply #15 - Posted 2008-12-05 20:18:35 »

I think the smallest way would be to draw the image twice (with appropriately modified parameters) using:
1  
public abstract boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer)


Storing the image + flip would require accessing many different api calls, which will bloat up the constants pool with lots of class & method signatures - something you should always be aware of when trying to keep code size to a minimum.

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

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #16 - Posted 2008-12-05 20:22:55 »

Yeah, I should have said smallest, not best.

So like:
1  
g.drawImage(img,x,y,x+width,y+height,x+width,y,x,y+height,null);


Basically is it width/height based or coordinate based?

See my work:
OTC Software
Offline Abuse

JGO Knight


Medals: 13


falling into the abyss of reality


« Reply #17 - Posted 2008-12-05 20:33:23 »

Yeah, I should have said smallest, not best.

So like:
1  
g.drawImage(img,x,y,x+width,y+height,x+width,y,x,y+height,null);


Basically is it width/height based or coordinate based?

Coordinate,
so what you have above will draw the image in the same location as g.drawImage(img, x, y, null), but flipped.

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

Senior Newbie





« Reply #18 - Posted 2008-12-07 15:03:16 »

Quick question if it's ok.

In an Applet, is it most efficient to start your game loop from the init method, and stop it from the destroy method?  I would like to save some bytes and not worry about the destroy method, however, if I do this, the game starts up multiple game loops if the page is refreshed.

Thanks!

There are several ways to make an applet run.
How does your Applet look like? Which methods have you written?
I never used the destroy method, but Applet needs more overhead than Frame, but maybe I am wrong?
Offline Ranger
« Reply #19 - Posted 2008-12-07 16:07:24 »

How does your Applet look like? Which methods have you written?
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?

I never used the destroy method, but Applet needs more overhead than Frame, but maybe I am wrong?
I think you are correct.  With a Frame you can have everything in the constructor, and update your screen like this:
1  
2  
3  
4  
5  
6  
this.createBufferStrategy(2);
BufferStrategy bufStrat = this.getBufferStrategy();
do {
    ... do stuff ...
    bufStrat.show();
} while (isVisible());

In an Applet, the createBufferStrategy and getBufferStrategy are not accessible.   Cry  I'm hoping there is an alternative.  Anyone know of one?   Huh
Offline Abuse

JGO Knight


Medals: 13


falling into the abyss of reality


« Reply #20 - Posted 2008-12-07 16:27:03 »

Don't use BufferStrategy, or add a Canvas to the Applet.

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

Junior Duke


Projects: 2



« Reply #21 - Posted 2008-12-07 17:51:49 »

Here's an optimized processEvent:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
    public void processEvent(AWTEvent e)
    {
        boolean down = false;
        switch (e.getID())
        {
            case KeyEvent.KEY_PRESSED:
                down = true;
            case KeyEvent.KEY_RELEASED:
                k[((KeyEvent) e).getKeyCode()] = down;
                break;
            case MouseEvent.MOUSE_PRESSED:
                down = true;
            case MouseEvent.MOUSE_RELEASED:
                k[((MouseEvent) e).getButton()] = down;
            case MouseEvent.MOUSE_MOVED:
            case MouseEvent.MOUSE_DRAGGED:
                x = ((MouseEvent) e).getX();
                y = ((MouseEvent) e).getY();
        }
    }


Mouse buttons states are in low k[]-values, keys in higher. This has some side effects, but it shouldn't be too bad (some obscure keys might act as mouse buttons).

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.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
    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.

Offline michael bliem

Senior Newbie





« Reply #22 - Posted 2008-12-07 18:23:39 »

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:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
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...
Offline Ranger
« Reply #23 - Posted 2008-12-07 18:43:24 »

Don't use BufferStrategy, or add a Canvas to the Applet.
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.   Roll Eyes

this is my best working applet-structure:
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.
Offline michael bliem

Senior Newbie





« Reply #24 - Posted 2008-12-07 19:35:33 »

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)
Offline Markus_Persson

JGO Wizard


Medals: 16
Projects: 19


Mojang Specifications


« Reply #25 - Posted 2008-12-07 19:43:56 »

I got an email asking me how I dealt with destroy() calls in my L4kD applet, and here it is:

1  
2  
3  
4  
5  
6  
7  
8  
9  
public void run()
{
    // Set up
    while (true)
    {
        // Game logic
        if (!isActive()) return;
    }
}

Play Minecraft!
Offline Ranger
« Reply #26 - Posted 2008-12-07 19:54:11 »

I got an email asking me how I dealt with destroy() calls in my L4kD applet, and here it is:

1  
        if (!isActive()) return;

Ah!  Never realised the isActive method existed, and it is exactly what I was after!  Thank you!!!
Offline Ranger
« Reply #27 - Posted 2008-12-10 20:40:54 »

I'm so desperate for bytes, I'm questioning the masters!   Shocked

FYI:  The template listed on http://wiki.java.net/bin/view/Games/4KGamesDesign says:
1  
2  
3  
    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:
1  
2  
3  
4  
    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?
Offline EnderGT

Junior Duke





« Reply #28 - Posted 2008-12-10 23:58:58 »

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.
Offline Abuse

JGO Knight


Medals: 13


falling into the abyss of reality


« Reply #29 - Posted 2008-12-12 16:46:21 »

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?

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Pages: [1] 2
  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.

theagentd (20 views)
2014-10-25 15:46:29

Longarmx (53 views)
2014-10-17 03:59:02

Norakomi (47 views)
2014-10-16 15:22:06

Norakomi (35 views)
2014-10-16 15:20:20

lcass (39 views)
2014-10-15 16:18:58

TehJavaDev (69 views)
2014-10-14 00:39:48

TehJavaDev (69 views)
2014-10-14 00:35:47

TehJavaDev (61 views)
2014-10-14 00:32:37

BurntPizza (74 views)
2014-10-11 23:24:42

BurntPizza (47 views)
2014-10-11 23:10:45
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

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
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!