Java-Gaming.org
Play Revenge of the Titans! The situation is critical. We need fancy commanders to defend Earth, the moon, Mars!
Featured games (78)
games approved by the League of Dukes
Games in Showcase (416)
games submitted by our members
Games in WIP (306)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
   Home   Help   Search   Login   Register   
  Show Posts
Pages: [1]
1  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-05-22 21:09:49
I like to play the game of elimination before I spend $$ on new stuff.

Is the site just PHP backed by MySQL or something like that?  If so, you could switch to a free host.  There are a number of hosts like www.000webhost.com that provide PHP, MySQL and a decent amount of space and bandwidth/data transfer for free.  Not that bandwidth is much of a problem I suppose, with the jars being only 4KB!  Wink
2  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-05-22 20:45:46
Just FYI @appel - the site has been down for the past 7 hours.
3  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-05-01 19:07:46
It was misbehaving some time ago, and I almost gave up on it, then it became stable. Now in recent days it's been bad. I've replaced hardware in the server to pinpoint the hardware error. Hopefully this time around it's going to behave. If not I'll fix it by getting another box, because the current one is obviously flawed.

Sorry about it, it's a bit tricky to pinpoint which hardware module is flawed, and I like to play the game of elimination before I spend $$ on new stuff. You have to wait and see.

No worries, it performed well for the contest period, that's the most important part of the year.  Smiley  I just wanted to make sure someone knew.

PS: Thanks for hosting the site, I just assumed we were using a free webhost somewhere.
4  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-04-29 18:55:01
If I understand this graph correctly (link to current Netcraft graph, the site has been down for the past 24 hours.
5  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-04-19 19:58:29
Next time maybe wait for one day or longer before making thread about this because sometimes it happens.

Well, I waited for 4 hours before starting the thread, which makes about 6 hours of downtime from the time I noticed it (no idea of total downtime.)  In fact, it's down again right now.

Above was posted at 9:05AM ADT.  As of right now (3:01PM ADT), the site is back up.  I've been checking once an hour all day, so downtime today was at least 5 hours.

Might be worth talking to the network host, as having 11 hours of downtime (at least that much) in a 48 hour period is pretty bad.
6  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-04-19 14:05:20
Next time maybe wait for one day or longer before making thread about this because sometimes it happens.

Well, I waited for 4 hours before starting the thread, which makes about 6 hours of downtime from the time I noticed it (no idea of total downtime.)  In fact, it's down again right now.
7  Games Center / 4K Game Competition - 2013 / Re: java4k.com website is down on: 2013-04-18 20:21:04
All good now, the site is back up.
8  Games Center / 4K Game Competition - 2013 / java4k.com website is down on: 2013-04-18 18:58:55
The site's currently down, confirmed using http://www.downforeveryoneorjustme.com/java4k.com.  DNS entries are still active, but it's not responding to pings.  That's about the extent of the investigating I can do, maybe appel or another admin can check it out?  It was up and running fine when I last visited at 3pm ADT yesterday.
9  Games Center / 4K Game Competition - 2013 / Re: Your top 3 of the most unappreciated games on: 2013-03-26 16:27:36
Underrated games this year:

  • In my opinion, B4llBasher got way too low a score.  I notice that one of the judges found a bug, but none of our community comments mentioned it (I'm townsendr on Java4K), which makes me think it's pretty isolated.  Not deserving of such a low grade.
  • tiny_world should have been in the top ten simply due to gameplay.  It could use better/simpler instructions perhaps, but it should have still made it to the top ten.  I suppose #11 is almost as good. Smiley
  • ApoSimple4K should have been rated much higher.  Clean graphics, slick animation, simple gameplay, and I found it fun.

I have actually bookmarked tiny_world and ApoSimple so I can play them during breaks at work.  They're that much fun.
10  Games Center / 4K Game Competition - 2013 / Re: Judging panel results. on: 2013-03-26 15:53:07
I would like to propose that we increase the size limit for next year's contest, so we can fit in all the missing/cut features. How about 4.1k? It has a nice ring to it  Grin

How about 4.01K?  401K has a nice ring to it. Wink

Regarding judging, I thought the giving the community the opportunity to give feedback with the points was great.  I hate to leave a comment on the game's page itself, since it's visible to everyone forever.  It's nice to have a way to give feedback to the developer that's associated more closely to the round of judging.

I'm looking forward to next year's contest.  I had 3 or 4 games in the works that were playable but needed work; however time is my scarcest resource these days.  A 1-year-old and a 3-year-old take up an awful lot of time and energy!  I guess I have a starting point for next year's contest.
11  Games Center / 4K Game Competition - 2013 / Re: [WIP] 4King & Country! on: 2013-02-28 22:24:56
Unzipping the file at that url and using gzip format + Ultra compressionin 7zip, it's coming up as 4,137 bytes.  Fiddling with the settings you should be able to bring that below the 4,096 threshold.
12  Games Center / 4K Game Competition - 2013 / Re: [WIP] 4King & Country! on: 2013-02-28 22:04:00
The game is up on: http://java4k.com/index.php?action=games&method=view&gid=471

But does not work, and I have no idea why!  Huh

My guess is because it's zip instead of gzip, but I don't know. Anyone take a look?

That's what the stack trace says.  I've used both 7zip and kzip (didn't end up more than 5 bytes different.)  Here's the stack trace from the Java console:

ava.util.zip.ZipException: Not in GZIP format
   at java.util.zip.GZIPInputStream.readHeader(Unknown Source)
   at java.util.zip.GZIPInputStream.<init>(Unknown Source)
   at java.util.zip.GZIPInputStream.<init>(Unknown Source)
   at com.sun.deploy.net.HttpDownloadHelper.download(Unknown Source)
   at com.sun.deploy.cache.Cache.downloadResourceToTempFile(Unknown Source)
   at com.sun.deploy.cache.Cache.downloadResourceToCache(Unknown Source)
   at com.sun.deploy.net.DownloadEngine.actionDownload(Unknown Source)
   at com.sun.deploy.net.DownloadEngine._downloadCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResourceCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResourceCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResource(Unknown Source)
   at sun.plugin.PluginURLJarFileCallBack$1.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at sun.plugin.PluginURLJarFileCallBack.retrieve(Unknown Source)
   at sun.net.www.protocol.jar.URLJarFile.retrieve(Unknown Source)
   at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source)
   at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
   at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.connect(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFileInternal(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFile(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.getJarFile(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.access$1000(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader$1.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.ensureOpen(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.<init>(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$3.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
   at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager.initAppletAdapter(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)
com.sun.deploy.net.FailedDownloadException: Unable to load resource: http://java4k.com/applet.php?gid=471
   at com.sun.deploy.net.DownloadEngine.actionDownload(Unknown Source)
   at com.sun.deploy.net.DownloadEngine._downloadCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResourceCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResourceCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResource(Unknown Source)
   at sun.plugin.PluginURLJarFileCallBack$1.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at sun.plugin.PluginURLJarFileCallBack.retrieve(Unknown Source)
   at sun.net.www.protocol.jar.URLJarFile.retrieve(Unknown Source)
   at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source)
   at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
   at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.connect(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFileInternal(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFile(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.getJarFile(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.access$1000(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader$1.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.ensureOpen(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.<init>(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$3.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
   at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager.initAppletAdapter(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)
Caused by:
java.util.zip.ZipException: Not in GZIP format
   at java.util.zip.GZIPInputStream.readHeader(Unknown Source)
   at java.util.zip.GZIPInputStream.<init>(Unknown Source)
   at java.util.zip.GZIPInputStream.<init>(Unknown Source)
   at com.sun.deploy.net.HttpDownloadHelper.download(Unknown Source)
   at com.sun.deploy.cache.Cache.downloadResourceToTempFile(Unknown Source)
   at com.sun.deploy.cache.Cache.downloadResourceToCache(Unknown Source)
   at com.sun.deploy.net.DownloadEngine.actionDownload(Unknown Source)
   at com.sun.deploy.net.DownloadEngine._downloadCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResourceCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResourceCacheEntry(Unknown Source)
   at com.sun.deploy.cache.ResourceProviderImpl.getResource(Unknown Source)
   at sun.plugin.PluginURLJarFileCallBack$1.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at sun.plugin.PluginURLJarFileCallBack.retrieve(Unknown Source)
   at sun.net.www.protocol.jar.URLJarFile.retrieve(Unknown Source)
   at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source)
   at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
   at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.connect(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFileInternal(Unknown Source)
   at sun.plugin.net.protocol.jar.CachedJarURLConnection.getJarFile(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.getJarFile(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.access$1000(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader$1.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.ensureOpen(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$JarLoader.<init>(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath$3.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
   at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
   at sun.plugin2.applet.Applet2ClassLoader.findClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass0(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at sun.plugin2.applet.Plugin2ClassLoader.loadCode(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager.initAppletAdapter(Unknown Source)
   at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
   at java.lang.Thread.run(Unknown Source)
13  Games Center / 4K Game Competition - 2013 / Re: [WIP] Limbo-inspired graphics on: 2012-11-15 19:04:00
Quote
I had an interesting idea for sound... Taking an alorithmic one-liner
If you find some that sound good in Java, could you share a link to them?  When I went looking last year, I couldn't find any that had a sound I liked and that could be easily implemented in Java.  The ones that sounded good relied on language specific quirks, like using JavaScript's loose variable typing or doing pointer manipulation in C++ (I think that's what it was doing.)

Quote
Might scale it up x2 using nearest neighbour scaling.
You could also use Graphics2D's scale() method, the two lines required would probably be less code than doing nearest neighbour yourself.  e.g.:
1  
2  
3  
g.scale(0.5f, 0.5f);
// existing drawing code here
g.scale(2f, 2f);
14  Games Center / 4K Game Competition - 2013 / Re: [WIP] Limbo-inspired graphics on: 2012-11-14 19:22:19
Personally, I've had an issue with sound effects through the javax.sound.sampled is the delay between writing to the audio buffer and hearing it.  I've seen some systems have up to about a half-second delay, which means it's really, really tough to synchronize the audio with the video.
Hmm, I haven't noticed that, although I can see how that would happen if you were continuously writing the bytes to a buffered input stream.  Instead of doing that, I pre-parse the music and load it into a Clip.  That way I can just use the loop() and stop() commands to start/stop the music, and as far as I can tell there's no lag.  Running at a fixed frame rate of 60fps, the Clip reports that it has already started playing by the time the next frame is ready.

I do the same with sound effects (one Clip object per type of sound effect), except that you have to set the frame position back to zero each time, like this:

1  
2  
3  
4  
5  
6  
// Play the level up sound
if (levelEnd) {
   levelUpSound.stop();
   levelUpSound.setFramePosition(0);
   levelUpSound.start();
}


PS: I forgot about the MIDI prohibition.  Makes sense, since we can't know what instruments are supported, although it's annoying.  Maybe I can figure out the waveform for a piano note and use that instead of a sign wave.
15  Games Center / 4K Game Competition - 2013 / Re: [WIP] Limbo-inspired graphics on: 2012-11-14 18:55:20
I love the lighting effects, but maybe it would work better as a fixed light-source that the user moved left/right relative to?  Like you were walking through the woods, towards a bright light.  For the "sound" in your ToDo list, are you thinking effects or soundtrack?  If you're interested, I've been working on ways to play soundtracks using minimal code.  Here's what I came up with for last year's contest: http://www.java-gaming.org/topics/music/25429/view.html

My maze entry last year included a full length, 8-bit version of the song "Music Box Dancer", where the full song was encoded in 203 bytes before compression.  It uses a 1-byte per note format that I created, which covers the 64 of the 88 keys on a standard piano keyboard (centered on middle C) and allows 4 note lengths.  Since most songs have a lot of repetition (eg: a repeated chorus), I found that when gzipped the soundtrack used only about 40-60 bytes in my final jar.  The code required to decode the soundtrack into pcm and then play it looks big, but there are lots of comments and constants, so proguard shrinks that down nicely.  Some sort of deep, slow music would go well with a wander through your spooky woods, maybe with some jarring high/fast chords when you get jumped by a creep.  And it wouldn't be hard to play the chord in the corresponding left/right channel based on the direction of the creep - I'm hoping to do that with one of my games.

The other way to do this is with javax.sound.midi, but I'm having trouble finding a way to figure out what instruments are supported on a given system.  For example, on my system the default instrument seems to be a piano, which would be great to use, but I can't figure out if that's the default for everyone or not.  (Imagine if the default for someone is drums or clarinet instead!)  If I can get it figured out, I'll start a new thread with example code, and all our games will sound a lot better (well, better than procedural PCM.)
16  Games Center / 4K Game Competition - 2013 / Re: Java4K 2013! on: 2012-11-06 19:35:05
I'd like your ideas on what we can do to shake things up a bit. I already have some ideas but nothing rock solid. Let's hear some ideas from you guys first, ideas on website, ideas on judging process, ideas on contest itself, etc.

Could we have a way to view a game's details without launching the game?  It's a small thing, but with the old web start games you could check out a game without it counting towards the download count (if I recall correctly.)  Also, I felt bad that going to my games' pages to check for comments artificially upped my dl counters.  Actually, email notification of comments on our games would be a nice feature too.

Judging seemed to work well last year.  I'm sure it was burdensome on the judges, but as a developer it was great to get that level of feedback.

I vote for Java 7 too, solely because I've gotten used to some of the new syntax, like generics type inference:
1  
Map<String, List<String>> myMap = new HashMap<>();


I've never looked closely at lwjgl, but Google reminds me that it provides support for game controllers.  I'd build a 4K space shooter sim if I could use my joystick to drive it!
17  Games Center / 4K Game Competition - 2012 / Re: Music on: 2012-03-07 21:48:06
As promised, my EncodeMusic class, which generates the "music" format that Sound4K plays.  I've tried to comment it so that you can understand what's going on, but you're welcome ask questions or just use it without understanding.  Smiley

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  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
package ca.townsends.games.templates;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.StringTokenizer;

/**
 * Takes a csv-like file of notes in {duration}{octave}{note} format, and outputs one byte per note.  The input
 * ignores all whitespace, including linefeeds and carriage returns, so you can group music as you please.  For example,
 * the first few stanzas of the song "Music Box Dancer" are:
 *
 * 13C,13E,13G,13E,14C,13G,13E,13G,
 * 13C,13E,13G,13E,14C,13G,13E,13G,
 * 13C,13E,13G,13E,14C,13G,13E,13G,
 * 13C,13E,13G,13E,14C,13G,13E,13G,
 *
 * 14C,13G,14C,14E,14C,14E,14G,14C,
 * 15C,15B,15A,34G,20R,
 * 14G,14F,14D,14B,13G,14C,14D,14F,
 * 14E,14C,15A,34G,20R,
 * 14C,13G,14C,14E,14C,14E,14G,14C,
 * 15C,15B,15A,34G,20R,
 *
 * Note that the input accepts notes in any mixed-case, and recognizes both sharps
 * and flats (e.g.: "A", "C#" and "Db" are all valid notes within an octave.)  "R" is used for a Rest note.
 *
 * I've named the output format "ca.townsends.music", with a ".music" extension, but that's purely arbitrary.
 *
 *
 * @author Rick Townsend
 * @version 1.1
 * 2012-02-25
 */

public class EncodeMusic {

   /** Notes are between 0 and 63:
    * - Shifting down by 40 gives a range of -40 to +22, with 23 reserved for silent beat.
    * - Since -9 is middle C, that leaves (-40 - -9) = 31 notes below middle C, and (22 - -9) = 31 notes above middle C
    * - This also means incoming, encoded notes should have 31 as middle C (so it translates to shifted value -9).
    */

   public static final int NOTE_SHIFT = -40;
   
   /**
    * Main method
    * @param args Not used
    */

   public static void main(String[] args) {
      HashMap<String,Integer> noteMap = new HashMap<String,Integer>();
     
      // The recognized notes within an octave
     noteMap.put("A",   0);
      noteMap.put("A#",   1);
      noteMap.put("Bb",   1);
      noteMap.put("B",   2);
      noteMap.put("C",   3);
      noteMap.put("C#",   4);
      noteMap.put("Db",   4);
      noteMap.put("D",   5);
      noteMap.put("D#",   6);
      noteMap.put("Eb",   6);
      noteMap.put("E",   7);
      noteMap.put("F",   8);
      noteMap.put("F#",   9);
      noteMap.put("Gb",   9);
      noteMap.put("G",   10);
      noteMap.put("G#",   11);
      noteMap.put("Ab",   11);
      noteMap.put("R",   63); // Rest note
     
      InputStream inStream = null;
      OutputStream outStream = null;
     
      // If we get an IO exception at any time, there's no point in continuing.
     try {
         // You could change these to be parameters from the args[] array, instead of hard-coded.
        inStream = EncodeMusic.class.getResourceAsStream("MusicBoxDancer.csv");
         outStream = new FileOutputStream("src/ca/townsends/games/templates/outputMusic.music");
         byte[] bytes = new byte[4096 * 4]; // 4K notes is a very, very long song... But if you overrun it, just make this bigger.
       
         // Grab all the bytes from the file
        inStream.read(bytes);
         
         // Dump it to a String so we can parse it more easily
        String data = (new String(bytes)).toUpperCase();
         
         // Split on commas
        StringTokenizer st = new StringTokenizer(data, ",");
           
         // Parse all the notes
          while(st.hasMoreTokens()) {
              // Trim off whitespace
             String token = st.nextToken().trim();
             
              // Skip any empty values (ie, where the input was only whitespace between two commas, or simply ",,")
             if (token.length() == 0) continue;
             
              // Grab the duration, octave and note
             int inDuration = Integer.parseInt(token.substring(0, 1));
              int inOctave = Integer.parseInt(token.substring(1, 2));
              String inNote = token.substring(2); // This grabs all text from the third character onward, so it will get both single ("C") and double ("C#) character notes
             
              //System.out.println(inNote);
             // Grab the notes value from the map
             int noteVal = noteMap.get(inNote);
             
              // Calculate the actual note value (0 - 62), by multiplying by the octave and shifting down by 7 so that middle C is dead center at note 31.
             int outNote = (byte)(inOctave * 12 + noteVal - 7);
              // Shift the duration up by 6 bits
             int duration = inDuration << 6;

              // Hard-code the Rest note as note 63.
             if (noteVal == 63) outNote = 63;
             
              // Write the note in the lower 6 bits and the duration in the top 2 bits to both the output stream and system.out
             outStream.write((byte)(outNote | duration));
              System.out.print((byte)(outNote | duration) + ",");
              //System.out.print((char)(outNote | duration));
             //System.out.print("0x" + Integer.toHexString(outNote | duration).toUpperCase() + ",");

           }
      } catch (IOException e) {
         e.printStackTrace();
      } finally {
           try {inStream.close();} catch (Exception e){};
           try {outStream.close();} catch (Exception e){};
      }
     
   }

}
18  Games Center / 4K Game Competition - 2012 / Re: Music on: 2012-03-07 21:24:45
If you don't mind 8-bit sound, below is a class I wrote to test my sound generation.  Note that it uses basic sine waves; I tried a few other wave forms, but either made mistakes with them or else they didn't sound very good.  I coded it to use the same frequencies as the Western standard (A440), so each note maps directly to a standard piano key (including sharps/flats.)  So Middle C is note -9.    The generateNote() method generates a given note of a given duration and appends it to the byte array.  It also extends the array as needed, so you can write very small code to generate a lot of notes very easily.  Notice the two commented out examples, one showing a simple three note sequence, and the other showing a repeating pattern that increases frequency and then in tempo.

The default, uncommented code uses another method I wrote, parseMusicStream(), to parse a byte stream in a format I created for the Java4K competition.  In it, each note is represented by 1 byte, with the top two bytes representing the duration (shifted up by one, it gives you a range of 1-4) and the bottom 6 bytes representing the note (giving you a range of 0 to 62, with 63 reserved for a Rest note.)  Those bytes compress really well in the final jar, probably because of repeated notes and repeated sequences within the music (eg: a chorus.)  I've got a second program that takes a comma-separated list of notes in {duration}{octave}{note} format and outputs the notes encoded in the previous byte format.  So I can write music like this:

14C,13G,14Eb,24C,00R,14A#,00R,14C,

And have those notes encoded into just 8 bytes before compression.  I'll paste the encoder code in another comment.

Rick

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  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224  
225  
226  
227  
228  
229  
230  
231  
232  
233  
234  
235  
236  
237  
238  
239  
240  
241  
242  
243  
244  
245  
246  
247  
248  
249  
250  
251  
252  
253  
254  
255  
256  
257  
258  
259  
260  
261  
262  
263  
264  
265  
266  
267  
268  
269  
270  
271  
272  
273  
274  
275  
276  
277  
278  
279  
280  
281  
282  
283  
284  
285  
286  
287  
288  
289  
290  
291  
292  
293  
294  
295  
296  
297  
298  
299  
300  
301  
302  
303  
304  
305  
306  
307  
308  
309  
310  
311  
312  
313  
314  
315  
package ca.townsends.games.templates;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.InputStream;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;

/**
 * Generate Sound
 *
 * Ideas:
 * - Pre-generate the sound so it doesn't slow down framerate.
 * - Loop notes in groups of 8
 * - add changes by:
 *   - increasing/decreasing tempo
 *   - adjusting notes up/down by a set amount
 *   - play up down scale
 *   - repeat two notes
 *
 * - Maybe pre-store some music in a byte string, using first six bits as the note, and the last two bits as the length?
 *
 * - Note that with the current implementation, note 0 is the lowest Treble A, so -9 is middle C.
 *
 * @author Rick Townsend
 * @version 1.0
 *
 */

public class Sound4K extends Applet implements Runnable {

   private static final int SCREEN_WIDTH = 800;
   private static final int SCREEN_HEIGHT = 600;
   private static final long LOOP_DELAY = 16; // 16 = approx 60 FPS

   // in hz, number of samples in one second
  private static final int SAMPLE_RATE = 44100;
   
   // this is the time BETWEEN Samples
  private static final double SAMPLE_PERIOD = 1.0 / SAMPLE_RATE;
   
   // volume
  private static int AMPLITUDE = 20;
   
   // Incoming notes are between 0 and 63:
  // - Shifting down by 40 gives a range of -40 to +22, with 23 reserved for silent beat.
  // - Since -9 is middle C, that leaves (-40 - -9) = 31 notes below middle C, and (22 - -9) = 31 notes above middle C
  // - This also means incoming, encoded notes should have 31 as middle C (so it translates to shifted value -9).
  private static final int NOTE_SHIFT = -40;
   
   // Incoming durations are between 0 and 3
  // - The code shifts them to be between 1 and 4
  // - This multiple is how many seconds a duration of 1 represents.
  private static final double DURATION_MULTIPLE = 0.2;
   
   /** array of keys (to detect which ones are currently being pressed */
   private boolean[] keys = new boolean[65536];
   private int mouseButton = MouseEvent.NOBUTTON;
   private int dMouseX = 0;
   private int dMouseY = 0;
   

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

   public void run() {
      // Turn on event handling
     this.enableEvents(
            AWTEvent.KEY_EVENT_MASK |
            AWTEvent.MOUSE_EVENT_MASK |
            AWTEvent.MOUSE_MOTION_EVENT_MASK);

      // Set the screen size
     setSize(SCREEN_WIDTH, SCREEN_HEIGHT); // For AppletViewer, TODO: remove later.

      // Set up the graphics stuff, double-buffering.
     BufferedImage screen = new BufferedImage(SCREEN_WIDTH, SCREEN_HEIGHT, BufferedImage.TYPE_INT_RGB);
      Graphics2D g = (Graphics2D) screen.getGraphics();
      Graphics appletGraphics = this.getGraphics();
     
      long fps = 0;

      int iteration = 0;
     
      byte[] pcmMusic = new byte[0];

      /* e.g.:
       * Play three fixed notes, each for 0.3 seconds
       */

      /*
      rawOutput = generateNote(rawOutput, -15, 0.3);
      rawOutput = generateNote(rawOutput, -17, 0.3);
      rawOutput = generateNote(rawOutput, -19, 0.3);
       */

     
      /* e.g.:
       * Generate a repeating sequence of:
       * - two notes
       * - played four times
       * - repeated three times, each time the two notes are three notes higher than the previous two
       * - repeated six times, each time the two notes are played for 0.1 seconds shorter than the previous time
       */

      /*
      for (int k = 0; k < 6; k++) {
         double duration = 0.6 - (k * 0.1);
         for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
               pcmMusic = generateNote(pcmMusic, i * 3 - 8, duration);
               pcmMusic = generateNote(pcmMusic, i * 3 + 4, duration);
            }
         }
      }
      */

     
      /* e.g.:
       * Load the music from a file (each byte is a note: top two bits are the duration, bottom 6 bits are the note to play.)
       */

      InputStream stream = this.getClass().getResourceAsStream("MusicBoxDancer.music");
      pcmMusic = parseMusicStream(stream);
     
      // Play the music
       AudioFormat audioFormat = new AudioFormat(SAMPLE_RATE, 8, 1, true, true);
        DataLine.Info info = new DataLine.Info(Clip.class, audioFormat);
        Clip music;
      try {
         music = (Clip) AudioSystem.getLine(info);
           music.open(audioFormat, pcmMusic, 0, pcmMusic.length);
           music.loop(Clip.LOOP_CONTINUOUSLY);
      } catch (LineUnavailableException e1) {
         // TODO Auto-generated catch block
        e1.printStackTrace();
      }
     
      // Game loop.
     while (isActive()) {
         iteration++;
         long lastTime = System.currentTimeMillis();
         
         // Clear the screen
        g.setColor(Color.WHITE);
         g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
         
         // TODO add some update logic here.

         
         // TODO: Animation goes here
       
         g.drawString("FPS: " + fps, 20, SCREEN_HEIGHT);
         
         // Game title
        g.setFont(new Font("Arial", Font.BOLD, 26));
         // Draw a drop-shadow first
        g.setColor(Color.GRAY);
         g.drawString("Sound 4K v1.0", SCREEN_WIDTH - 180, SCREEN_HEIGHT - 3);
         // Then the main title
        g.setColor(Color.BLUE);
         g.drawString("Sound 4K v1.0", SCREEN_WIDTH- 180, SCREEN_HEIGHT - 3);

         // Draw the entire results on the screen.
        appletGraphics.drawImage(screen, 0, 0, null);

         //Lock the frame rate
        long delta = System.currentTimeMillis() - lastTime;
         if(delta < LOOP_DELAY)
         {
            try {
               Thread.sleep(LOOP_DELAY - delta);
            } catch(Exception e) {
               // Nothing to do here
           }
         }
         if (iteration % 10 == 0) fps = 1000 / (System.currentTimeMillis() - lastTime);
      }
   }

   /**
    * Generates a new note, and appends it to the original array.
    *
    * @param originalArray An array of bytes representing pcm music (can be empty/zero length)
    * @param note The note to generate.  There are 12 notes per octave: -9 = middle C, -8 = C#/Db, -7 = D, etc.
    * @param duration How long to play the note, in seconds.
    * @return A new byte array containing the originalArray followed by the pcm bytes for the new note.
    */

   private byte[] generateNote(byte[] originalArray, int note, double duration){
     
      int durationInSamples = (int) Math.ceil(duration * SAMPLE_RATE) + 1;
     
      byte[] noteArray = new byte[durationInSamples * 2];
                                   
      double time = 0;
      int i = 0;
     
      // Put in a pause if this note is the max value
     if (note == 63 + NOTE_SHIFT) {
         i = durationInSamples;
         
      } else {
         
         double tone = 440 * Math.pow(2,note/12f);
         
         boolean finishedNote = false;
         
         // Generate the note using a SINE wave.
        for(int j = 0; j < durationInSamples || !finishedNote; j++, i++) {
            noteArray[i] = (byte) (AMPLITUDE * Math.sin(2 * Math.PI * tone * time));
            time += SAMPLE_PERIOD;
            // Keep going until the wave is finished at zero
           if (i > 0) finishedNote = (noteArray[i - 1] < 0 && noteArray[i] >= 0);
         }
     
      }

      // Append the note
     byte[] finalArray = new byte[originalArray.length + i];
      System.arraycopy(originalArray, 0, finalArray, 0, originalArray.length);
      System.arraycopy(noteArray, 0, finalArray, originalArray.length, i);
     
      return finalArray;
   }
   
   /**
    * Parses the bytes of an InputStream and returns a byte array containing the represented
    * notes in pcm format.
    *
    * - The InputStream must be in "ca.townsends.music" format, where each byte represents a note and its duration.
    * - For each byte, the top 2 bits are the duration, the bottom 6 bits are the note to play.
    * - The duration is multiplied by the duration multiple and shifted up by 0.1.  So a duration of 0 = 0.1, 1 = 0.1 + (duration * multiple), etc.
    * - The note is shifted up by NOTE_SHIFT, which lets you adjust the note range up or down as desired. For example,
    *   to shift the music being parsed up by an octave, just increase NOTE_SHIFT by 12 (the number of notes in an octave.)
    *
    * See ca.townsends.games.templates.EncodeMusic for a "music" encoder.
    *
    * @param stream An InputStream in "music" format.
    *
    * @return A byte array with the parsed music in pcm format.
    */

   private byte[] parseMusicStream (InputStream stream) {
      byte[] music = new byte[0];
     
      int b;
      try {
         while((b = stream.read()) != -1) {
            double duration = (b >> 6) * DURATION_MULTIPLE + 0.1;
            int note = (b & 63) + NOTE_SHIFT;
            // XXX: System.out.println(note + ", " + duration + ", " + (byte)b);
           music = generateNote(music, note, duration);
         }
      } catch (Exception e) {
         // TODO: Handle an error here
        e.printStackTrace();
      } finally {
         try {
            stream.close();
         } catch (Exception io) {
            // Can't do anything here
           io.printStackTrace();
         }
      }
     
      return music;
   }
   
   /**
    * Just standard key handling for a Java4K applet.
    */

   public void processKeyEvent(KeyEvent e) {
      switch (e.getID()) {
         case Event.KEY_PRESS:
         case Event.KEY_ACTION:
            // skip keypresses more than 0.1 seconds old, because they indicate bad lag time
           if (System.currentTimeMillis() - e.getWhen()  > 100)
               break;
            keys[e.getKeyCode()] = !keys[e.getKeyCode()];
            break;
      }
     
   }
   
   /**
    * Just standard mouse handling for a Java4K applet.
    */

   public void processMouseEvent(MouseEvent e) {
      dMouseX = e.getX();
      dMouseY = e.getY();

      switch (e.getID()) {
         case MouseEvent.MOUSE_PRESSED:
            // mouse button pressed
           mouseButton = e.getButton();
            break;
         case MouseEvent.MOUSE_RELEASED:
            // mouse button released
           mouseButton = MouseEvent.NOBUTTON;
            break;
         case MouseEvent.MOUSE_MOVED:
            break;
         case MouseEvent.MOUSE_DRAGGED:
            break;
      }
     
   }
   /**
    * Just standard mouse handling for a Java4K applet.  Delegates to processMouseEvent().
    */

   public void processMouseMotionEvent(MouseEvent e){
      processMouseEvent(e);
   }
}
Pages: [1]
Play Revenge of the Titans! The situation is critical. We need fancy commanders to defend Earth, the moon, Mars!
 
Browse for soundtracks for your game!

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

The first screenshot will be displayed as a thumbnail.

The invasion has landed! On Mars! And you're there to beat 'em!
BrassApparatus (7 views)
2013-06-19 08:52:37

NegativeZero (11 views)
2013-06-19 03:31:52

NegativeZero (14 views)
2013-06-19 03:24:09

Jesse_Attard (19 views)
2013-06-18 22:03:02

HeroesGraveDev (60 views)
2013-06-15 23:35:23

Vermeer (59 views)
2013-06-14 20:08:06

davedes (59 views)
2013-06-14 16:03:55

alaslipknot (53 views)
2013-06-13 07:56:31

Roquen (74 views)
2013-06-12 04:12:32

alaslipknot (58 views)
2013-06-10 19:30:18
Smoothing Algorithm Question
by UprightPath
2013-05-28 02:58:26

Smoothing Algorithm Question
by UprightPath
2013-05-28 02:57:33

Complex number cookbook
by Roquen
2013-04-24 12:47:31

2D Dynamic Lighting
by Oskuro
2013-04-17 16:46:12

2D Dynamic Lighting
by Oskuro
2013-04-17 16:45:57

2D Dynamic Lighting
by Oskuro
2013-04-17 16:23:20

Noise (bandpassed white)
by Roquen
2013-04-05 17:36:01

Noise (bandpassed white)
by Roquen
2013-04-03 16:17:38
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!