Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Pop at the end of playback  (Read 3315 times)
0 Members and 1 Guest are viewing this topic.
Offline TheAnalogKid

JGO Coder


Projects: 2



« Posted 2004-10-19 17:57:56 »

Hi.

I use java sound (with VorbisSPI and Jorbis) for OGG playback using a SourceDataLine to play a byte array. The problem is that at the end of playback of any sound, there is always a kind of "pop" noise. And I can assure you that I doesn't stop or flush the line before playback ends. This noise makes sound not really good.

What's weird is that even when I test the OGG using a Clip object, the same problem occurs and you know that I can't control line feeding in this situation so it shouldn't be a buffer underrun/overflow problem.

One interesting thing is that when I test the same sound but in the wav format then the problem simply disapear.

So my guess is that the problem seems to be in either VorbisSPI or Jorbis.

Any help or ideas would be greatly appreciated otherwise the playback isn't great.

Thanks

Online princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2004-10-20 09:51:30 »

Is the sample at 0 at the end? You can fix pops with a tiny 0.1ms fadeout at the end of the sample.

Cas Smiley

Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #2 - Posted 2004-10-20 10:44:09 »

Quote
Is the sample at 0 at the end?
What doyou mean by sample?

Yes I could do a kind of fade out but to me it's a patch and not a real solution but thanks anyway.



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

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #3 - Posted 2004-10-20 12:20:36 »

It's not a patch, that IS the solution! If your samples stop dead at, say a PCM level of 3234, then the next thing they have to do is to straight to zero when the sample stops - Pop!

Cas Smiley

Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #4 - Posted 2004-10-20 12:27:46 »

If the sample doesn't end with 0, the result would indeed be little pop (abeit usually a small one) and it's generally better to *always* have samples end with 0 like Cas described. This is not a patch, it's just good practice.
However, I guess you'd have the same problem with the wav version if a non-zero value at the end would be the cause.
Did you create the ogg from the wav file or the other way around (the latter to test the wav output)?
Does the ogg sound correctly in any other ogg player?
Could you post the source?

Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #5 - Posted 2004-10-20 14:57:10 »

Sorry Cas! I didn't want to offense you.

Actually if I play the OGG in Winamp everything is fine (no pop at the end) so to me it's not a fading issue. And I have to say that I've already faded out the OGG at the end to prevent this problem. In summary eveything seems to be ok but the problem still persists. And yes the playback of the wav is always good. Anyway here is the source code: I have an entity class (StreamedSound which extends AbstractSound) that holds the data and has the capability to render it and another class to control playback (Player).

AbstractSound.java
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  
package sound;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

public abstract class AbstractSound implements Sound {

  private File file;
  private AudioInputStream sourceStream;
  private AudioFormat sourceFormat;
  private AudioInputStream decodedStream;
  private AudioFormat decodedFormat;
  private boolean decoded;
  private boolean cached;
  private String id;
  private boolean open;
 
 
  /**
   *  
   */

  protected AbstractSound() {
    id = "";
    open = false;
  }
 
  public void setFileName(String fileName) {
    file = new File(fileName);
    if (id.length() == 0) {
      id = fileName;
    }
  }
 
  public void setDecoded(boolean decoded) {
    this.decoded = decoded;
  }
 
  /**
   * @return Returns the decoded.
   */

  boolean isDecoded() {
    return decoded;
  }
 
  public void setCached(boolean cached) {
    this.cached = cached;
  }
 
  /**
   * @return Returns the cached.
   */

  public boolean isCached() {
    return cached;
  }

  /**
   * @return Returns the id.
   */

  public String getId() {
    return id;
  }
 
  /**
   * @param id The id to set.
   */

  public void setId(String id) {
    this.id = id;
  }
 
  protected void load() throws Exception {
    System.out.println("Loading audio data for sound " + id);
   
    // Open the source input stream on the targeted sound file.
    sourceStream = AudioSystem.getAudioInputStream(file);
    if (sourceStream == null) {
      throw new Exception("Got null AudioInputStream for given sound file.");
    }
    sourceFormat = sourceStream.getFormat();
   
    if (decoded) {
          // Open the decoded input for the specified targeted format and from the source input stream.
          decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, sourceFormat.getSampleRate(),
              16, sourceFormat.getChannels(), sourceFormat.getChannels() * 2, sourceFormat.getSampleRate(), false);
          decodedStream = AudioSystem.getAudioInputStream(decodedFormat, sourceStream);
    }
   
    open = true;
  }
 
  /**
   * @return Returns the open.
   */

  public boolean isOpen() {
    return open;
  }
 
  /**
   * @param open The open to set.
   */

  protected void setOpen(boolean open) {
    this.open = open;
  }
 
  /**
   * @return Returns the decodedFormat.
   */

  protected AudioFormat getFormat() {
    if (decoded) {
      return decodedFormat;
    } else {
      return sourceFormat;
    }
  }
 
  /**
   * @param format The sourceFormat to set.
   */

  void setSourceFormat(AudioFormat format) {
    sourceFormat = format;
  }
 
  /**
   * @param format The decodedFormat to set.
   */

  void setDecodedFormat(AudioFormat format) {
    decodedFormat = format;
  }
 
  protected AudioInputStream getAudioInputStream() {
    if (decoded) {
      return decodedStream;
    } else {
      return sourceStream;
    }
  }
 
  public void dispose() {
    close();
  }
 
  protected void close() {
    boolean closedStream = false;
    try {
      if (sourceStream != null) {
        sourceStream.close();
        closedStream = true;
      }
          if (decoded && decodedStream != null) {
            decodedStream.close();
        closedStream = true;
          }
    } catch (IOException e) {
      throw new RuntimeException("Unable to dispose AudioInputStream.", e);
    }
    if (closedStream) {
      System.out.println("Closed streams for sound " + id);
    }
   
    open = false;
  }
 
  /**
   *
   */

  public abstract Object clone() throws CloneNotSupportedException;
 
  /**
   *
   * @param newSprite
   */

  protected void copy(AbstractSound sound) {
    sound.setId(id);
    sound.setFileName(file.getAbsolutePath());
    sound.setDecoded(decoded);
    sound.setCached(cached);
    sound.setSourceFormat(sourceFormat);
    sound.setDecodedFormat(decodedFormat);
    sound.setOpen(open);
  }
}



Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #6 - Posted 2004-10-20 14:59:31 »

And here is the rest of the code:

StreamedSound.java
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  
package sound;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;

public class StreamedSound extends AbstractSound {

  private SourceDataLine line;
  private Player player;
  private PlaybackStrategy playbackStrategy;
  private boolean playing;
  private boolean writing;
  private int maxLineBufferSize;
 
 
  public StreamedSound() {
    playing = false;
    writing = false;
    maxLineBufferSize = 30000;
  }
 
  public void open() throws Exception {
    player = Player.getInstance();
    if (!isOpen()) {
      load();
      openLine();

      // Initialize the playback strategy.
      if (playbackStrategy == null) {
            if (isCached()) {
              playbackStrategy = new CachingStrategy();
            } else {
              playbackStrategy = new StreamingStrategy();
            }
            playbackStrategy.load();
      }

      player.start();
    } else {
      openLine();
    }
  }
 
  void openLine() throws Exception {
    DataLine.Info srcDataInfo = new DataLine.Info(SourceDataLine.class, getFormat());
    line = (SourceDataLine) AudioSystem.getLine(srcDataInfo);
    line.open(getFormat());
    int frameSize = getFormat().getFrameSize();
//    maxLineBufferSize = (line.getBufferSize() / frameSize / 2) * frameSize;
    if (line == null) {
      throw new Exception("SourceDataLine is null.");
    }
    line.start();
  }
 
  public void play() throws IOException {
    stop();
    while (writing) {
      Thread.yield();
    }
    line.flush();
    line.stop();
    playbackStrategy.rewind();
    playing = true;
    line.start();
    player.add(this);
  }

  /**
   *
   */

  public void stop() {
    playing = false;
  }

  /**
   * @return
   */

  public boolean isPlaying() {
    return playing;
  }
 
  public Object clone() throws CloneNotSupportedException {
    StreamedSound sound = new StreamedSound();
    copy(sound);
    PlaybackStrategy strategy = (PlaybackStrategy) playbackStrategy.clone();
    sound.setPlaybackStrategy(strategy);
    return sound;
  }
 
  void setAudioData(byte[] data) {
    if (isCached()) {
      ((CachingStrategy) playbackStrategy).setDataBuffer(data);
    }
  }
 
  /**
   * @throws IOException
   *
   */

  public void dispose() {
    player.stop();
    close();
  }
 
  protected void close() {
    super.close();
    line.close();
  }

  /**
   * @return Returns the playbackStrategy.
   */

  PlaybackStrategy getPlaybackStrategy() {
    return playbackStrategy;
  }
 
  /**
   * @param playbackStrategy The playbackStrategy to set.
   */

  void setPlaybackStrategy(PlaybackStrategy playbackStrategy) {
    this.playbackStrategy = playbackStrategy;
  }

  /**
   * @author Jerome Blouin
   */

  abstract class PlaybackStrategy {
    abstract void load() throws IOException;
    abstract void play() throws IOException;
    abstract void rewind();
    abstract public Object clone();
  }
 
 
  /**
   * @author Jerome Blouin
   */

  private class CachingStrategy extends PlaybackStrategy {
   
    private byte[] buffer;
    private int offset;
   
    CachingStrategy() {
      buffer = null;
      offset = 0;
    }
   
    void load() throws IOException {
      AudioInputStream stream = getAudioInputStream();
      ByteArrayOutputStream outStream = new ByteArrayOutputStream();
      byte[] data = new byte[maxLineBufferSize];
      int bytesRead = 0;

      while (bytesRead != -1) {
        bytesRead = stream.read(data, 0, data.length);
        if (bytesRead != -1) {
          outStream.write(data, 0, bytesRead);
        }
      }
     
      buffer = outStream.toByteArray();
      outStream.close();
//      System.out.println("" + buffer.length);
     
      rewind();
    }
   
    void play() throws IOException {
      writing = true;
      if (offset < buffer.length) {
        int lineBufferSize = maxLineBufferSize;
        if (offset + lineBufferSize >= buffer.length) {
          lineBufferSize = buffer.length - offset;
        }
        line.write(buffer, offset, lineBufferSize);
        offset += lineBufferSize;
      } else {
        playing = false;
      }
      writing = false;
    }
   
    void rewind() {
      offset = 0;
    }
   
    byte[] getDataBuffer() {
      return buffer;
    }
   
    public Object clone() {
      CachingStrategy strategy = new CachingStrategy();
      strategy.setDataBuffer(buffer);
      return strategy;
    }
   
    void setDataBuffer(byte[] data) {
      buffer = data;
    }
  }
 
 
  /**
   * @author Jerome Blouin
   */

  private class StreamingStrategy extends PlaybackStrategy {

    private AudioInputStream stream;
    private int bytesRead;
    private byte[] buffer;
   
    StreamingStrategy() {
      stream = null;
      buffer = new byte[maxLineBufferSize];
      bytesRead = 0;
    }
   
    void load() throws IOException {
      rewind();
    }
   
    void play() throws IOException {
      writing = true;
      bytesRead = stream.read(buffer, 0, buffer.length);
      if (bytesRead != -1) {
        line.write(buffer, 0, bytesRead);
      } else {
            playing = false;
      }
      writing = false;
    }
   
    void rewind() {
      close();
      try {
        open();
      } catch (Exception e) {
        e.printStackTrace();
      }
      stream = getAudioInputStream();
      bytesRead = 0;
    }

    public Object clone() {
      return new StreamingStrategy();
    }
  }
}


Player
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  
package sound;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

class Player {

  private SoundThread thread;
  private boolean running;
 
  private static Player instance = null;
 
 
  private Player() {
    running = false;
  }
 
  static Player getInstance() {
    if (instance == null) {
      instance = new Player();
    }
    return instance;
  }
 
  void start() {
    if (!running) {
      thread = new SoundThread();
      thread.start();
      running = true;
    }
  }
 
  void add(StreamedSound sound) {
    thread.add(sound);
  }
 
  /**
   * @param running The running to set.
   */

  void stop() {
    thread.stop();
    running = false;
  }
 
 
  private class SoundThread implements Runnable {

    private Thread thread;
    private List sounds;
    private int soundCount;
    private boolean running;

   
    SoundThread() {
      sounds = new ArrayList();
      soundCount = 0;
      running = false;
    }
   
    void start() {
      if (!running) {
        thread = new Thread(this);
        thread.start();
      }
    }
   
    void add(StreamedSound sound) {
      sounds.add(sound);
      soundCount++;
    }
   
    void remove(StreamedSound sound) {
      if (isRunning()) {
        throw new IllegalStateException("Can not unregister sound while this thread running.");
      }
      sounds.remove(sound);
      soundCount--;
    }
   
    /**
     * @return Returns the soundCount.
     */

    int getSoundCount() {
      return soundCount;
    }
   
    public void run() {
      running = true;
      StreamedSound sound;
     
      while (running) {
        for (int i = 0; i < soundCount; i++) {
          sound = (StreamedSound) sounds.get(i);
          if (sound.isPlaying()) {
                try {
                  sound.getPlaybackStrategy().play();
                } catch (IOException e) {
                  throw new RuntimeException("Unable to play streamed sound.", e);
                }
            if (!sound.isPlaying()) {
              sounds.remove(i);
              soundCount--;
              i--;
            }
          }
          Thread.yield();
        }
        if (soundCount == 0) {
          Thread.yield();
        }
      }
    }
   
    /**
     * @return Returns the running.
     */

    boolean isRunning() {
      return running;
    }
   
    /**
     * @param running The running to set.
     */

    void stop() {
      running = false;
      while (thread.isAlive()) {
        Thread.yield();
      }
    }
  }
}

Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #7 - Posted 2004-10-20 15:12:18 »

Me again.

Would it be possible that faded out samples is not supported by VorbisSPI or Jorbis? That would explain my problem. Maybe the question is irrelevant.

Offline Mac_Systems

Junior Duke




I love my Java


« Reply #8 - Posted 2004-10-22 13:26:04 »

Well, as we cannot look into winamp's sourcecode, im quite sure
that winamp will do a fadeout by itself. At least winamp 0's
the last byte it plays - this is not hearable even in a samplerate
of 8KHZ. I do not know why you flood the forum with you code, simple
write a small testcase for your needs - and judge for yourself.

Stay Tuned,
Jens

The Network is the Music
http://www.mac-systems.de
Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #9 - Posted 2004-10-22 13:41:59 »

Quote
I do not know why you flood the forum with you code...
Because I was asked for. Anyway, does it cause you a problem?

Thanks for your answer about the Winamp explication.

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

Junior Duke




Hoping to become a Java Titan someday!


« Reply #10 - Posted 2004-10-22 20:02:02 »

Do you have a sound editor that you can use to view the actual sound?

You can get a great one from sourceforge - Audacity

This should tell you for sure if you have a problem with the audio going from some high - non zero value at the end.

Dr. A>
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #11 - Posted 2004-10-25 06:48:21 »

Quote
Because I was asked for.

Yes, I asked for the source although the source is a bit larger than what I hoped for Smiley. Sorry for not having replied yet (I'm a bit busy these days), but as far as I could tell there's no main method in there so if you could add a little test case (preferrably with a test sound uploaded somewhere) that would help a lot given my current time constraints.

BTW, does the problem also occur with a sample with only silence?

Offline dranonymous

Junior Duke




Hoping to become a Java Titan someday!


« Reply #12 - Posted 2004-10-25 18:19:07 »

Here's another link to an Ogg Vorbis decoder that a friend passed on to me -

JOgg

I had a problem yesterday getting to the site, but today it was fine.

You might try using this one and see if it meets your needs as well.  It may not fix your pop, but if it is the decoder, you'd know.

Dr. A>
Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #13 - Posted 2004-10-27 11:47:03 »

Thanks all for your help.

I think Jogg is already used by Jorbis (the jar at least).

I already use Audacity. I used it to fade out the OGG at the end.

I've uploaded a zip that will let you test it and check the code just in case you could find out something. You can download it at http://www.myjavaserver.com/~theanalogkid/servlets/app/soundtest.zip

You just have to run test.bat to run the test. The java path is hardcoded to jdk1.4. I recommend running the test with Java 1.4 because in version 5 I'm not sure if the problem presists.

Just a note concerning Java 5: Like many of you I noticed that the sound is offen chopped (at the begining) and the volume is higher than in 1.4.

Thanks again to all of you.

Offline dranonymous

Junior Duke




Hoping to become a Java Titan someday!


« Reply #14 - Posted 2004-10-28 16:40:33 »

I'm not sure why JOrbis has the jogg jar in it.  You can compile the jcraft sources and run them without any jogg stuff.

The code in the jogg stuff is very clean and well commented as well.  It took me almost no time to get the encoder installed in my code and running.

Regards,
Dr. A>
Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #15 - Posted 2004-10-28 17:47:45 »

Is Jogg compatible with VorbisSPI?

Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #16 - Posted 2004-10-30 16:57:56 »

Click to Play


end at green line=ok
end at red line=plop

Just found that image, while skimming through my hdd (searched something completely different). Well, thought it's cool as visualisation thingy. The transparent line in the middle should have been black... oh well... but I guess it's still ok, since this post is going to end up on a dark stripe Tongue

弾幕 ☆ @mahonnaiseblog
Offline dranonymous

Junior Duke




Hoping to become a Java Titan someday!


« Reply #17 - Posted 2004-11-02 13:58:31 »

You'll need to check.  I didn't need to worry about the SPI interface, it only took about 10 lines of code to get things playing.  I remember the documentation mentioning SPI, but that's about it.

HTH -
Dr. A>
Offline TheAnalogKid

JGO Coder


Projects: 2



« Reply #18 - Posted 2004-11-08 17:32:16 »

Quote

Yes, I asked for the source although the source is a bit larger than what I hoped for Smiley. Sorry for not having replied yet (I'm a bit busy these days), but as far as I could tell there's no main method in there so if you could add a little test case (preferrably with a test sound uploaded somewhere) that would help a lot given my current time constraints.

BTW, does the problem also occur with a sample with only silence?

Have you figured out something? The problem only occurs with the provided sound in the test jar (http://www.myjavaserver.com/~theanalogkid/servlets/app/soundtest.zip)

Pages: [1]
  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.

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

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

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

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

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

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

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

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

BurntPizza (39 views)
2014-10-11 23:10:45

BurntPizza (81 views)
2014-10-11 22:30:10
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!