I've been playing with libGDX, because I want to develop a multiplayer game with my friend. My recent problem did come up while testing the communication with multiple clients. I run all the clients and the server from one computer. If I run 'n' clients, all the clients run on exactly 60/'n' fps. Why?
The source code of the project is available at: http://github.com/FBalazs/Yellow
The game loop that libgdx uses by default renders at a fixed rate I find it to be about 60fps if you are running on desktop you can set the foreground and background FPS in the desktop application main method.
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "Game Name";
cfg.fullscreen = false;
cfg.vSyncEnabled = false;
cfg.foregroundFPS = 120; // Change the FPS
cfg.width = 1280;
cfg.height = 720;
new LwjglApplication(new MyGdxGame(), cfg);
}
I believe you can also use Continuous & non continuous rendering but I have not tried it as of yet.
Related
I am currenty doing a small game. But my application does not work properly. Program does not stop with error, but firstly it playes part of track, and after that (around 5-10 seconds) it stops and drawing begins.
Without audio added, code works absolutely fine.
I also tested app on several different devices and emulators, but issue keeps occuring.
Here are some methods from class "Game.java", where I am trying to implement audio.
public class Game {
Plane background;
Plane playfield;
Context context;
List<SingleNote> notes = new ArrayList<SingleNote>();
List<SingleNote> notes_to_compute = new ArrayList<SingleNote>();
Date date = new Date();
long time_initial;
float[] touch_coord = new float[2];
private int mStreamId;
public Game(Context context){
this.context = context;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
public void load(){
background = new Plane(context, R.raw.vertex_shader, R.raw.fragment_shader, R.drawable._map1);
playfield = new Plane(context, R.raw.vertex_shader, R.raw.fragment_shader, R.drawable.s_playfield);
InitNotes(R.raw._map1);
time_initial = date.getTime();
MyThread m = new MyThread();
m.context = context;
m.start();
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
public void draw(){
background.draw();
playfield.draw();
update();
}
}
class MyThread extends Thread {
Context context;
public void run(){
SoundManagement.playSoundPool(context, R.raw._map1_a);
}
}
And static PlaySondPool method in class
public static void playSoundPool(Context context, int soundID) {
int MAX_STREAMS = 20;
int REPEAT = 0;
SoundPool soundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, REPEAT);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int soundId, int status) {
int priority = 0;
int repeat = 0;
float rate = 1.f; // Frequency Rate can be from .5 to 2.0
// Set volume
AudioManager mgr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
float streamVolumeCurrent =
mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
float streamVolumeMax =
mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float volume = streamVolumeCurrent / streamVolumeMax;
// Play it
soundPool.play(soundId, volume, volume, priority, repeat, rate);
}
});
soundPool.load(context, soundID, 1);
}
I thought using separate thread would help, but same issue occurs.
What should I do in order to avoid this error? Maybe use another library, or play sound from other class?
Whole code here: https://github.com/arthur100500/AndroidProject
Additional debug ingormation from android studio
Logcat: https://pastebin.com/MQSaWw8R
Run: https://pastebin.com/5D4AGuHZ
How it looks: https://youtu.be/X7IBquHs1jA
I think there is every likelihood that the choice of SoundPool for playback is the source of the problem you are experiencing. SoundPool is designed for the handling of audio files that are short (a couple seconds) and can be held in memory. You've indicated that you are trying to use it to play a 5-minute long file. According to the documentation in the API, only the first MB of the 5-minute file is being handled.
Soundpool sounds are expected to be short as they are predecoded into
memory. Each decoded sound is internally limited to one megabyte
storage, which represents approximately 5.6 seconds at 44.1kHz stereo
(the duration is proportionally longer at lower sample rates or a
channel mask of mono). A decoded audio sound will be truncated if it
would exceed the per-sound one megabyte storage space.
Streaming via an AudioTrack should be a more fitting alternative for this sound file.
An AudioTrack instance can operate under two modes: static or
streaming. In Streaming mode, the application writes a continuous
stream of data to the AudioTrack, using one of the write() methods.
These are blocking and return when the data has been transferred from
the Java layer to the native layer and queued for playback. The
streaming mode is most useful when playing blocks of audio data that
for instance are:
too big to fit in memory because of the duration of the sound to play,
too big to fit in memory because of the characteristics of the audio data (high sampling rate, bits per sample ...)
received or generated while previously queued audio is playing.
I am using Intellij to program Java.
I am currently trying to make a top down tile based shooter.
My issue is that my game, after approximately 2 minutes, crashes with a popup saying "Java(TM) Platform SE Binary has stopped working. I recorded the time it took for it to crash 3 times: 1m57s, 1m59s, 1m58s.
The game is in a very simple state right now and I am not sure what could be causing the crash. All of the relevant code is in just two classes: GameFrame.java (extends JFrame) and GamePanel.java (which extends JPanel).
GameFrame.java:
package net.magnusfrater.tds.game;
import javax.swing.*;
public class GameFrame extends JFrame {
public static final int width = 1000;
public static final int height = width / 16 * 10;
private GamePanel gp;
public GameFrame () {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(width,height);
setResizable(false);
setLocationRelativeTo(null);
setTitle("Time Based Fast Paced Top Down Shooter Demo");
gp = new GamePanel();
add(gp);
setVisible(true);
}
public static void main (String[] args) {
GameFrame gf = new GameFrame();
}
}
GamePanel.java
package net.magnusfrater.tds.game;
import net.magnusfrater.tds.input.Keyboard;
import javax.swing.*;
import java.awt.*;
public class GamePanel extends JPanel implements Runnable {
//panel
private Thread thread;
private static boolean running;
private boolean fpsLock;
//input
private Keyboard kb;
//game
private Game game;
public GamePanel () {
//panel
thread = new Thread(this, "Time Based Fast Paced Top Down Shooter Demo");
running = true;
fpsLock = true;
//input
//kb = new Keyboard();
//addKeyListener(kb);
//game
//game = new Game(1);
thread.start();
}
public void run () {
long iTimeNS = System.nanoTime();
int tickRate = 60;
long ns = 1000000000 / tickRate;
int ups = 0;
int fps = 0;
long iTimeS = System.nanoTime();
long s = 1000000000;
while (running) {
long fTimeNS = System.nanoTime();
if (fTimeNS - iTimeNS >= ns){
iTimeNS = System.nanoTime();
tick();
ups++;
if (fpsLock){
repaint();
fps++;
}
}
if (!fpsLock){
repaint();
fps++;
}
long fTimeS = System.nanoTime();
if (fTimeS - iTimeS >= s){
iTimeS = System.nanoTime();
System.out.println("ups: " + ups + "\tfps: " + fps);
ups = 0;
fps = 0;
}
}
System.exit(0);
}
public void tick () {
if (kb != null)
kb.tick();
if (game != null)
game.tick();
}
#Override
public void update (Graphics g) {
paint(g);
}
#Override
public void paint (Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0,0,GameFrame.width, GameFrame.height);
//if (game != null)
//game.paint(g);
}
public static void quitGame () {
running = false;
}
}
I originally thought that the issue was because of the way that I was loading images for spritesheets or maybe the way I was loading text files for the level design but after reworking both of those, the issue remained.
That left me curious and a little bit fed up so I tried finding out more about the explanation for the crash. First I read more from the popup but it didn't say anything useful: (See below)
Second I looked at the exit code given by Intellij: (See below)
I looked up what exit code 255 was but there wasn't anything useful. The best explanation I could find was that exit code 255 meant that the real exit code was out of range: (See below)
I was out of ideas at this point so I just started plain old googling everything I could think of. The problem with googling "Java(TM) Platform SE Binary has stopped working" is that almost every suggested link is a question about Minecraft. Limiting my search to Stack Overflow yielded me some results, but nothing conclusive. Some of the fixes I found were stuff I already tried (such as not handling input streams properly, not handling buffered reader properly, not disposing of elements, etc). I found these links but none of them were truly related to my issue:
(See below)
(See below)
(See below)
(See below)
(See below)
(See below)
The last fix I tried was to re-install Java SE Development Kit 8u101 AND Java SE Development Kit 8u102. I then restarted Intellij. I then restarted my computer.
Nothing worked.
At this point I think I'm just dumb. I've overlooked something easy I can tell. What am I missing?
(ps~ This is a possibly related issue. So if I run my game with almost no content in it with the fps not locked to 60, I get really absurd numbers of frames per second. I didn't think that fps as high as 7,000,000 was possible. I think. I don't know. Have I programmed that wrong as well? Here is a related picture of my ups/fps output: [see below])
(SEE HERE) So Stack Overflow doesn't allow members with a score within a certain threshold post more than 2 links and allows absolutely no posting of images. So here is a link to a google doc with all of the links and images I mentioned above:
https://docs.google.com/document/d/1XrBuVio19GmkFz0EfRzXVp5AJmM5zPfVO6vK3oS3Eaw/edit?usp=sharing
Try and set your -Xmx to something like 2G and see if it runs longer. If so, something is allocating memory and maybe you have that other setting set that exits instead of garbage collecting for some reason.
Also, try changing your code to limit things using Guava's RateLimiter.
…
// class level
final RateLimiter frameLimiter = RateLimiter.create(60.0);
final RateLimiter outputLimiter = RateLimiter.create(1.0);
…
// in run method
while (running) {
frameLimiter.acquire();
repaint();
fps++;
if (outputLimiter.tryAcquire()){
System.out.println("fps: " + fps);
fps = 0;
}
}
I've removed ups and tick(). You should do your work after repainting and I don't think you want to do more work than needed for the next frame, which at the soonest should be at your max rate. Later you'll need to add logic to handle skipping work when frames are being skipped. I might make more sense to increment the fps within repaint.
You could put the output in its own thread and only acquire that limiter if you synchronized the increments and resetting of fps.
Hello guys I'm trying to implement a restart function but its not working I would like to know if u could help me find a good way to restart this game.
World world;
PImage space;
void setup()
{
size(800,600);
space = loadImage("SpaceBuracos.jpg");
space.resize(800,600);
world = new World(8);
}
void draw()
{
background(space);
if(world.run()){restart();} //if boolean == true restarts the game
}
void restart(){
world = new World(8);
}
world = new world(8); creates 8 planets, but when i restart() the game itself resets but non of the planets appear.
I would like to completely kill the previews game and start anew but I dunno if it can be done.
I am running into issues with LibGDX on Desktop. I keep getting the following error when trying to launch the application:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.badlogic.gdx.utils.BufferUtils.newDisposableByteBuffer(I)Ljava/nio/ByteBuffer;
at com.badlogic.gdx.utils.BufferUtils.newDisposableByteBuffer(Native Method)
at com.badlogic.gdx.utils.BufferUtils.newUnsafeByteBuffer(BufferUtils.java:288)
at com.badlogic.gdx.graphics.glutils.VertexArray.<init>(VertexArray.java:62)
at com.badlogic.gdx.graphics.glutils.VertexArray.<init>(VertexArray.java:53)
at com.badlogic.gdx.graphics.Mesh.<init>(Mesh.java:148)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.<init>(SpriteBatch.java:173)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.<init>(SpriteBatch.java:142)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.<init>(SpriteBatch.java:121)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.<init>(SpriteBatch.java:115)
I have the following libraries added to my project:
gdx.jar
gdx-sources.jar
gdx-natives.jar
gdx-backend-lwjgl.jar
gdx-backend-lwjgl-natives.jar
Am I missing something?
I have searched high and low, but everything I find is for Android and tells me to add the .so libs from the arm folders to my project, but that doesn't make sense to me for a desktop project on wintel platform.
I'd advise you to setup your projects with this GUI. It should provide you with a valid setup for all platforms. You may also use the latest nightly builds and check if the problem still occurs. The problem might be that the native libraries do not match the other jars.
Another problem might be that you instantiate a SpriteBatch (or something else which internally uses a SpriteBatch) too early (looked a bit like this in the stacktrace). For example statically like this:
private static SpriteBatch batch = new SpriteBatch();
This won't work, since libgdx wasn't setup correctly at this point in time. Instead, create such things in the create/show methods of your game.
Use the following main method body to launch the object:
static public void main(String[] args) throws Exception {
// SkeletonViewer.args = args;
String os = System.getProperty("os.name");
float dpiScale = 1;
if (os.contains("Windows")) {
dpiScale = Toolkit.getDefaultToolkit().
getScreenResolution() / 96f;
}
if (os.contains("OS X")) {
Object object = Toolkit.getDefaultToolkit().getDesktopProperty(
"apple.awt.contentScaleFactor");
if (object instanceof Float && ((Float) object).intValue() >= 2) {
dpiScale = 2;
}
}
if (dpiScale >= 2.0f) {
uiScale = 2;
}
LwjglApplicationConfiguration.disableAudio = true;
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.width = (int) (800 * uiScale);
config.height = (int) (600 * uiScale);
config.title = "Skeleton Viewer";
config.allowSoftwareMode = true;
config.samples = 2;
new LwjglApplication(new SampleApplication(), config);
}
I need to fix the screen location of the Open Source Java Application "Angry IP Scanner" on OSX (https://sourceforge.net/projects/ipscan/) at startup.
If you start the application and move it to the extended space of a secondary monitor (Non mirrored) and do one of two things: 1) Unplug your secondary monitor with the app running or 2) quit the app while it is located on the secondary monitor.
If you unplug the second monitor and then start the app, the app loads and places the screen on the now nonexistent 2nd monitor, even though it is not plugged in.
To get to the screen back to the main screen area you MUST plug in a 2nd monitor and move it back to the main screen. Then you can unplug the second monitor and have no problems.
When the app is starting, I think the app needs to check the current screen size verses the previous screen size and if it has changed, place the screen near the 10,10 location so it will show up on the main, hopefully active screen.
In my searching on Stack Overflow, it appears you can find the current screen information like this:
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
How could I save this to a file and recall/compare the previous to the current data, if it has changed, move the application's window to the 10,10 location?
I am a beginner writing iOS and Ruby on OSX, but have not done any Java. I love the program, but this bug is killing me and there doesn't appear to be anyone actively working on the code.
Anyone want to help?
BTW ... It is bug 84 at the Angry IP Scanner website.
Maybe someone could explain how I could run the following code snippet from the cli?
int resolution =Toolkit.getDefaultToolkit().getScreenResolution();
System.out.println(resolution);
Thanks,
padapa
Something like:
public class ShowMeTheScreenSize {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println("VirtualBounds = " + getVirtualBounds());
for (int index = 0; index < getScreenDeviceCount(); index++) {
System.out.println("[" + index + "] Device bounds = " + getScreenDeviceBounds(index));
}
System.exit(0);
}
});
}
public static int getScreenDeviceCount() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
return ge.getScreenDevices().length;
}
public static Rectangle getVirtualBounds() {
Rectangle bounds = new Rectangle(0, 0, 0, 0);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
for (GraphicsDevice gd : lstGDs) {
bounds.add(gd.getDefaultConfiguration().getBounds());
}
return bounds;
}
public static Rectangle getScreenDeviceBounds(int index) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice lstGDs[] = ge.getScreenDevices();
return lstGDs[index].getDefaultConfiguration().getBounds();
}
}
Which outputs...
VirtualBounds = java.awt.Rectangle[x=0,y=0,width=3840,height=1200]
[0] Device bounds = java.awt.Rectangle[x=0,y=0,width=1920,height=1200]
[1] Device bounds = java.awt.Rectangle[x=1920,y=0,width=1920,height=1200]
On my machine
As discussed here, Mac OS X helpfully prevents a visible window from being moved offscreen. One expedient would be a command to move the window to a forbidden location, which will force it into reach.
polo.setLocation(Short.MIN_VALUE, Short.MIN_VALUE);