mill
Junior Member  
popcorn freak
|
 |
«
Posted
2003-04-17 10:57:03 » |
|
i don't know anything about sounds so how would i go about to stream a wav-file since apparently AudioClip.loop() loads the whole wav-file into memory. i use mp3s at the moment and convert them into wav-files at startup and they tend to get very big, say 40 mbs, and that's too much to keep in memory.
|
|
|
|
jbanes
|
 |
«
Reply #1 - Posted
2003-04-17 14:13:45 » |
|
AudioClip is an old API and really shouldn't be used anymore. Look up the javax.sound API form info on streaming sound data. You can also take a look at the GAGESound source for an example of how to stream manually. GAGESound does stream from memory, but the basic concept is the same.
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #2 - Posted
2003-04-20 09:19:02 » |
|
yeah i had a look at javax.sound.sampled but i didn't understand much of it. i kept looking for something like play() but found nothing. i haven't experimented though so it might be simpler than i think  EDIT: typos
|
|
|
|
Games published by our own members! Check 'em out!
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #4 - Posted
2003-04-21 14:57:37 » |
|
the first article didn't help much since that's the way i do it now.
the second was atleast about javax.sound.sampled but unfortunately "The next step is to read the entire file into memory". that's what i want to avoid.. i'll check out the GAGE-thing.. the gage-timer didn't work (or i did something wrong since the timer slowed down when in fullscreen -- odd behaviour)
|
|
|
|
jbanes
|
 |
«
Reply #5 - Posted
2003-04-21 15:21:40 » |
|
Hi mill! The way I do it in GAGESound should be no different than how you'd do it to stream from disk. The only difference is that you'd read directly from the AudioInputStream and write it out to the SourceDataLine. Both of these are obtained via the AudioSystem object. Here's some psuedo-code for you. It won't compile (since this is a rough estimate pulled from memory), but it should give you an idea: AudioInputStream in = AudioSystem.getAudioInputStream("myfile.wav"); Line.Info info = AudioSystem.getSourceLineInfo(new Line.Info(SourceDataLine.class)); SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
byte[] data = new byte[1024]; int length = 0;
line.open();
while((length = in.read(data, 0, data.length) > 0) { line.write(data, 0, length); }
Also, can you explain what you mean about the timer slowing down when in full screen? It should be impossible for the timer to return anything but the current and correct time. Thanks.
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #6 - Posted
2003-04-21 15:41:03 » |
|
thanks a lot. i managed to get it to work now.
some questions though..
is 1024 a good buffer size btw? i haven't gor the faintest idea.
i put the stream in a separate thread.. is that a good idea?
about the timer.. nevermind what i said. i figured out what was wrong!
i used to store the dt in a float and since the main loop was so fast the dt was set to 0 and not to 0.00000000000000000000000000000001 or whatever. since the dt was 0 most of the time, everything moved slowly! solution? use a double instead or multiply the dt with some constant. i'll give it a go right away!
btw, does the timer only work on win32? (i tried like ten timers that day so i didn't exercise it thoroughly)
EDIT: typos
|
|
|
|
jbanes
|
 |
«
Reply #7 - Posted
2003-04-21 16:01:40 » |
|
It's hard to come up with a good buffer size. What I do with GAGESound is I keep filling the buffer with enough to play the length of the last rendering loop. This way, my sound lags about 1 or 2 frames behind.
The GAGETimer works on all OSes with a 1/1000 sec resolution. Windows is special because it has a resolution of either 10ms or 50ms without the DLL or better than 1/1000 sec with the DLL. If you're not sure if the DLL is getting loaded, check the console. It should throw a stack trace if it doesn't load.
|
|
|
|
GergisKhan
Junior Member  
"C8 H10 N4 O2"
|
 |
«
Reply #8 - Posted
2003-04-21 18:52:46 » |
|
jbanes,
I checked the docs, and I'm still not sure how to do this.... if you want to load the dll in Windows, what do you have to do as far as deployment goes? What about if using JavaWebStart?
|
gK
"Go. Teach them not to mess with us." -- Cao Cao, Dynasty Warriors 3
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #9 - Posted
2003-04-22 07:46:20 » |
|
umm the gage timer makes my game behave oddly. i'll try to explain.
I don't use any threads and only use the timer and use that to time motions. this results in 100% cpu usage and it seems like events like KeyPressed lags behind.
i looked at your example and you don't sleep at all. no AdvancedTimer.sleep(...) or Thread.sleep(...) at all.
If i use AdvancedTimer.sleep(...) i don't see any difference. If I use Thread.sleep(...) cpu usage goes down to like 1% and the fps goes down to around 50 from 450 which i had when i didn't use Thread.sleep(...). It doesn't matter if I sleep 1 ms or 10 ms, I always get 50 fps or below. I have no clue why your game runs just fine and mine lags behind. Loading images are also slowed down by two or three times.
any ideas? i feel so stupid.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
erikd
|
 |
«
Reply #10 - Posted
2003-04-22 11:54:22 » |
|
GergisKhan, I guess just putting the DLL in the directory where you run the app should do (I don't know GAGE though, maybe it's different there). Regarding Web Start, I loaded the windows DLL from lwjgl by adding the following element in the jnlp file: 1 2 3
| <resources os="Windows"> <nativelib href="lwjgl_win.jar"/> </resources> |
where lwjgl_win.jar is the jarred dll. Something like this will probably work with GAGE as well. Erik
|
|
|
|
jbanes
|
 |
«
Reply #11 - Posted
2003-04-22 14:41:07 » |
|
Mill, Are you using Java2D? You shouldn't be able to get 450 fps using a bufferstrategy. The reason why my code doesn't need sleeps is that the strategy.show() line allows other threads to get some work done. If you're running flat out at 450 fps, other threads aren't getting any time. You should be able to fix this by using the AdvancedTimer sleep methods or a Thread.sleep() method. Can you tell me how you were using AdvancedTimer.sleep(...)? Usually, it's better to use AdvancedTimer.sleepUntil(...) like this: AdvancedTimer timer = new AdvancedTimer(); long sleepTime = timer.getTicksPerSecond()/60; //60 fps long ticks = 0;
timer.start();
while(true) { //draw stuff timer.sleepUntil(ticks+sleepTime); ticks += sleepTime; }
The beautiful part about this algo is that it automatically catches up if the game falls behind. Gergis, erikd had the right answer for you. Keep the DLL within the same directory you launch from and you should be fine. And his webstart example is correct as well. You can find more info on this in the Webstart developer docs.
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #12 - Posted
2003-04-22 15:19:15 » |
|
here's how i use it: 1 2 3 4 5 6 7 8 9 10
| public void run() { while (running) { calcDeltaTime(); raceManager.performGameTick(dt); if (fullscreen) renderFullscreen(); else renderWindow(windowGraphics); } } |
1 2 3 4 5 6
| private void calcDeltaTime() {
dt = (float) (atimer.getClockTicks() - lastGameTick); dt = dt * 0.000001f; lastGameTick = atimer.getClockTicks(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public void renderFullscreen() { if (!strategy.contentsLost()) { backgroundGraphics = strategy.getDrawGraphics();
switch (gameState) { case RACING : raceManager.updateGfx(backgroundGraphics); break; }
try { strategy.show(); } catch (IllegalStateException e) { return; } backgroundGraphics.dispose(); } calcFPS(); } |
1 2 3 4 5 6 7 8 9 10 11 12
| private void calcFPS() { currTime = System.currentTimeMillis(); frameCount++; if ((currTime - prevTime) >= fpsUpdateInterval) { System.out.println(dt + "\t\t" + fps + "\t\t" + (dt * fps)); fps = (float) frameCount / (currTime - prevTime) * 1000; frameCount = 0; prevTime = currTime; } } |
if i put try {Thread.sleep(1);} catch (InterruptedException e) {} it behaves correctly, but the fps drops to like 50 and cpu utilization is around 3%
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #13 - Posted
2003-04-22 15:22:19 » |
|
usually one would want cpu utilization to be ~100% since if you have a fast machine you want smooth graphics.
anyhow, i'll try what you suggested. hope the code above makes sense btw. hard to cut and paste only the relevant parts of the code.
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #14 - Posted
2003-04-22 15:40:13 » |
|
hah way cool! i get exactly 85 fps when i request that! it's super smooth now. the code below will produce 500 fps btw: 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
| import java.awt.AWTException; import java.awt.BufferCapabilities; import java.awt.Color; import java.awt.DisplayMode; import java.awt.Frame; import java.awt.Graphics; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.ImageCapabilities; import java.awt.Panel; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.image.BufferStrategy;
import com.dnsalias.java.timer.AdvancedTimer;
public class Main extends Frame { static GraphicsDevice defaultDevice; DisplayMode oldDisplayMode; private TestPanel testPanel;
public static void main(String[] args) { GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); defaultDevice = env.getDefaultScreenDevice(); Main main = new Main(); }
public Main() { testPanel = new TestPanel(this); add(testPanel);
oldDisplayMode = defaultDevice.getDisplayMode(); DisplayMode newDisplayMode = new DisplayMode(640, 480, 32, 85); setUndecorated(true); defaultDevice.setFullScreenWindow(this); defaultDevice.setDisplayMode(newDisplayMode); validate(); setIgnoreRepaint(true);
testPanel.start(); }
private void quit() { testPanel.stop(); defaultDevice.setDisplayMode(oldDisplayMode); defaultDevice.setFullScreenWindow(null); System.exit(0); }
public class TestPanel extends Panel implements KeyListener { private float fps; private long fpsUpdateInterval; private long prevTime; private int frameCount; private long currTime; private float dt; private Main main; private boolean up, down, left, right; private boolean running; private AdvancedTimer timer; private float x, y; private long lastGameTick; private Graphics backgroundGraphics; private BufferStrategy strategy; private long sleepTime, ticks;
public TestPanel(Main main) { this.main = main; up = down = left = right = false; running = false; timer = new AdvancedTimer(); sleepTime = AdvancedTimer.getTicksPerSecond()/500; ticks = 0; prevTime = currTime = System.currentTimeMillis(); lastGameTick = 0; frameCount = 0; fps = 0.0f; fpsUpdateInterval = 1000; x = y = 10;
addKeyListener(this); }
public void start() { running = true; timer.start(); run(); }
public void stop() { running = false; timer.stop(); }
private void run() { BufferCapabilities cap = new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), BufferCapabilities.FlipContents.COPIED); try { main.createBufferStrategy(3, cap); } catch (AWTException e) {}
strategy = main.getBufferStrategy(); backgroundGraphics = strategy.getDrawGraphics();
while (running) { calcDeltaTime(); move(); render(); sleep(); } }
private void sleep() { timer.sleepUntil(ticks+sleepTime); ticks += sleepTime; }
private void move() { float speed = dt * 2.0f; if (up) y -= speed; if (down) y += speed; if (left) x -= speed; if (right) x += speed; }
private void calcDeltaTime() { dt = (float) (timer.getClockTicks() - lastGameTick); dt = dt * 0.00005f; lastGameTick = timer.getClockTicks(); }
public void render() { if (!strategy.contentsLost()) { backgroundGraphics = strategy.getDrawGraphics();
backgroundGraphics.setColor(Color.black); backgroundGraphics.fillRect(0, 0, 640, 480); backgroundGraphics.setColor(Color.white); backgroundGraphics.fillRect(Math.round(x), Math.round(y), 10, 10);
try { strategy.show(); } catch (IllegalStateException e) { return; } backgroundGraphics.dispose(); calcFPS(); } }
private void calcFPS() { currTime = System.currentTimeMillis(); frameCount++; if ((currTime - prevTime) >= fpsUpdateInterval) { System.out.println(dt + "\t\t" + fps + "\t\t" + (dt * fps)); fps = (float) frameCount / (currTime - prevTime) * 1000; frameCount = 0; prevTime = currTime; } }
public void keyTyped(KeyEvent arg0) {}
public void keyPressed(KeyEvent arg0) { int key = arg0.getKeyChar(); if (key == 97) left = true; if (key == 100) right = true; if (key == 119) up = true; if (key == 115) down = true; if (key == KeyEvent.VK_ESCAPE) main.quit(); }
public void keyReleased(KeyEvent arg0) { int key = arg0.getKeyChar(); if (key == 97) left = false; if (key == 100) right = false; if (key == 119) up = false; if (key == 115) down = false; } } } |
|
|
|
|
jbanes
|
 |
«
Reply #15 - Posted
2003-04-22 16:30:53 » |
|
Glad you've got it figured out mill.  BTW, the AdvancedTimer code never actually sleeps. It just uses Thread.yield() to give up some time to other threads. This way, your rendering thread gets returned to quickly without bogging down other threads. You said you had used AdvancedTimer.sleep() before and that it didn't help. Why I asked how you were using it was I figured you were probably doing something along the lines of: timer.sleep(1); This *won't work*. The timer runs so fast that the time will probably already have expired before the code even checks what time it is. 
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #16 - Posted
2003-04-22 16:42:36 » |
|
when do you get your own section here for GAGE just as LWJGL has?  just kidding hehe anyway.. yeah i had a look at the source before I tried sleepUntil(). perhaps the docs should mention something about this? why is it impossible to get 500+ fps using Java2D? i may of course calculate the fps incorrectly  if you incorporate the changes regarding sleepUntil in the example i posted you can easily get lots and lots of fps
|
|
|
|
jbanes
|
 |
«
Reply #17 - Posted
2003-04-22 17:03:34 » |
|
It's *supposed* to be impossible. That doesn't mean it is. :-) There have been bugs in the past where the VSync wouldn't happen and the game would run amok. My first revision of Duke Nukes Stuff had this problem. Apparently when I slept for a second or two while switching to full screen mode, the JDK would fail to acquire a VSync lock. Got 500 fps with good keyboard response. Pretty proud of myself, i was. I think they've fixed that particular problem since then. Jeff? Do you know if that one was fixed? edit: > when do you get your own section here for GAGE just as > LWJGL has? Don't tell me! Tell the admins! 
|
|
|
|
oNyx
|
 |
«
Reply #18 - Posted
2003-04-22 22:21:29 » |
|
[...]Duke Nukes Stuff[...] btw i'm currently porting the build engine (used by duke nukem, shadow warrior and bout 10 other games) to lwjgl  so far only the map loading is done and only the geometry of the walls is displayed (i need to figure some of the flags out - the format is somewhat strange) :> gonna GPL it when the core is done 
|
|
|
|
jbanes
|
 |
«
Reply #19 - Posted
2003-04-23 00:06:17 » |
|
> btw i'm currently porting the build engine (used by duke > nukem, shadow warrior and bout 10 other games) to lwjgl *chuckle* I'm sorry. DNS was something I discussed on the old boards. Duke Nukes Stuff was a simple game I made out of everyone's favorite Java mascot, Duke! It was really just a technology test for the (then new) 1.4 gaming APIs.
|
|
|
|
oNyx
|
 |
«
Reply #20 - Posted
2003-04-23 03:15:36 » |
|
> btw i'm currently porting the build engine (used by duke > nukem, shadow warrior and bout 10 other games) to lwjgl *chuckle* I'm sorry. DNS was something I discussed on the old boards. Duke Nukes Stuff was a simple game I made out of everyone's favorite Java mascot, Duke! It was really just a technology test for the (then new) 1.4 gaming APIs. oh... u mean that duke guy/thingy =) heh i know that demo thingy... i just forgot it  ah well... i just thought we r talkin bout the same duke. nevermind 
|
|
|
|
johtib
Senior Newbie 
|
 |
«
Reply #21 - Posted
2003-04-26 17:57:07 » |
|
The AdvancedTimer class isn't available in standard java library right? If I wanted my game to work at school (which has a typical installation of Java) I couldn't use it right? Is there any alternatives?
- Johan
|
|
|
|
|
mill
Junior Member  
popcorn freak
|
 |
«
Reply #22 - Posted
2003-04-26 18:17:02 » |
|
you can, of course, ship the additional classes with your game.
otherwise there is the timer hack someone posted here which works pretty good. someone else that remember where it can be found or who wrote it?
|
|
|
|
|
|
|