I've been trying to create a loading screen, so that the game doesn't freeze when I go from a screen to another, I use this loading screen to load one asset (which is the background image).
My Assets class is defined as following:
public class Assets {
public static final AssetManager manager = new AssetManager();
public static void load(){
manager.load("images/ObservatoryScreenBackground.jpg", Texture.class);
}
public static void dispose(){
manager.dispose();
}
}
I have the following code in my LoadingScreen:
public LoadingScreen(ProjectSurvival game){
super();
this.game = game;
Assets.load();
while(!Assets.manager.update()){
System.out.println("not loaded yet");
}
game.setScreen(new ObservatoryScreen(game));
}
The problem is that the game never exists from this while tread and keeps running, printing "not loaded yet"...
I also tried this in the render method:
if(manager.update()) {
game.setScreen(new ObservatoryScreen(game));
}
The loading screen shows up for 1 second and just after that, the game crashes giving me this error:
Exception in thread "LWJGL Application" com.badlogic.gdx.utils.GdxRuntimeException: Asset not loaded: images/ObservatoryScreenBackground.jpg
I know there are similar topics, I did exactly what was told, but it doesn't seem to work to me...
Any help would be much appreciated.
Thank you.
Related
Here is my Desktop Launcher code:
public class DesktopLauncher {
public static void main (String[] arg) {
Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
config.setForegroundFPS(60);
config.setTitle("Game10");
config.setWindowedMode(1240, 760);
config.forceExit = false; // ERROR!!!
new Lwjgl3Application(new GdxGame10(), config);
}
}
In new LWJGL3 config.forceExit not working. I can't find any solution so far. Any help is appreciated.
There is no forceExit in config. So presumably you have a master application that runs a child libGDX component and when you end that child component you find that the entire application shuts down, when you want the master application to continue. I guess you are on desktop because Android would be OK. So you must want to avoid a full System.exit
i.e.
Gdx.app.exit()
shuts down everything.
So when you instantiate a libGDX application you instantiate based on the application type, so for me, I use the same as you
final Lwjgl3Application application = new Lwjgl3Application(Services.GAME_CONTROLLER,config);
and the implementation for exit is
#Override
public void exit () {
running = false;
}
This finished the while loop that drives the application i.e. kills the main thread. If you have -other threads- running in the background they keep going.
If on the other hand you were instantiating LwglAWTCanvas then your shutdown would be this.
#Override
public void exit () {
postRunnable(new Runnable() {
#Override
public void run () {
stop();
System.exit(-1);
}
});
}
which would shut down the entire application. Anyway so forceExit being -false- was to stop a full system exit killing all your threads. The forceExit was to "force" the other threads to finish. It doesn't do that anymore so the fact it is now missing should not matter, your background threads should keep going.
In other words, config.forceExit = false; is now the default behaviour for your application type so you don't need it.
Because of I had problems with Bluetooth on Android Lollipop, I have tried to change the scanner method.
So I have tried to use the new package.
In the previous version, I called startScan(mLeScanCallback) and everything works but now, when I call startScan(mScanCallback) I have the error: "D/BluetoothLeScanner: could not find callback wrapper".
No devices are found and the ListAdapter, I use to show the devices, is empty.
The comment lines are the previous code (and it worked!).
This my code:
public class Selection extends ListActivity implements ServiceConnection {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
// Initializes a Bluetooth adapter through BluetoothManager.
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
getApplicationContext().bindService(new Intent(this, MetaWearBleService.class), this, Context.BIND_AUTO_CREATE);
}
private void scanLeDevice(final boolean enable) {
final BluetoothLeScanner bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
if (enable) {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
//mBluetoothAdapter.stopLeScan(mLeScanCallback);
bluetoothLeScanner.stopScan(mScanCallback);
setListAdapter(listAdapter);
}
}, SCAN_PERIOD);
//mBluetoothAdapter.startLeScan(mLeScanCallback);
bluetoothLeScanner.startScan(mScanCallback);
} else {
//mBluetoothAdapter.stopLeScan(mLeScanCallback);
bluetoothLeScanner.stopScan(mScanCallback);
setListAdapter(listAdapter);
}
}
private ScanCallback mScanCallback =
new ScanCallback() {
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
listAdapter.addDevice(device);
}
});
}
};
Instead the ListAdapter extends BaseAdapter and use a ViewHolder. If it necessary, I post it.
So what does it mean "D/BluetoothLeScanner: could not find callback wrapper"? What is it wrong?
Otherwise how I can't resolve the problem of scanning with the Android Lollipop?
In Lollipop I have often errors about BluetoothGatt. I don't know to minized it (or solve it).
Thanks
The log message D/BluetoothLeScanner: could not find callback wrapper appears whenever Android's bluetooth scanning APIs are told top stop scanning for an app when they think scanning has not started. You can see this by looking at the source code of Android's BluetoothLeScanner here.
This is usually safe to ignore as there are lot of reasons that scanning my not have actually started (it was already stopped, bluetooth is off, permissions have not been granted, etc.) Client software that does scanning often stops scanning on a timer regardless of whether it has been successfully started, or whether it was manually stopped before the timer goes off. Android's example code (and the code shown above) does exactly this, often causing these log messages to show up.
If you really want to minimize these messages, you need to keep track of whether scanning actually started and only stop scanning if it actually did. Unfortunately, you don't get a return code if scanning starts successfully, and you only get an asynchronous callback to onScanFailed(errorCode) if you cannot start successfully. So one approach would be to set scanStartCount++; when you call start scan, and set scanStartCount--; when you get a callback to onScanFailed(errorCode). Then when your timer goes off to stop the scan, only actually stop it if the scanStartCount > 0.
Keep in mind that you can only minimize these messages coming from your application. Other applications on the phone doing bluetooth scanning may be causing these messages to be emitted as well.
for the same problem
I had just add permissions :
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.
Manifest.permission.
Manifest.permission.BLUETOOTH_PRIVILEGED,
in your activity call this methods :
checkPermissions(MainActivity.this, this);
public static void checkPermissions(Activity activity, Context context){
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.BLUETOOTH_PRIVILEGED,
};
if(!hasPermissions(context, PERMISSIONS)){
ActivityCompat.requestPermissions( activity, PERMISSIONS, PERMISSION_ALL);
}
}
public static boolean hasPermissions(Context context, String... permissions) {
if (context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
hope it's help
I had the same problem with android m.It was due to lack of permissions.Make sure you go to settings and grant location permission to your app
for location permission, only ACCESS_FINE_LOCATION worked. ACCESS_COARSE_LOCATION had the same problem.
I've created a "snow" particle effect using LibGDX's ParticleEditor, and exported the effect to a snow.p file.
When I load the file in my game it looks completely different.
As seen in the editor:
As seen in game:
As you can see the editor shows the snow falling throughout the space. Can't tell from the image, but it's falling downwards.
In the game, the snow "falls" along a line and to the right. I opened the p file in a text editor, and it looks fine so I'm not sure what is wrong.
In case it's needed, here is how I load and use the particle effect.
ParticleEffect p = new ParticleEffect();
p.load(Gdx.files.internal("snow.p"), Gdx.files.internal(""));
p.setPosition(0, DonutsGame.WORLD_HEIGHT / 2);
addActor(new ParticleEffectActor(p));
The actor class:
public class ParticleEffectActor extends Actor {
ParticleEffect effect;
public ParticleEffectActor(ParticleEffect effect) {
this.effect = effect;
effect.start();
}
public void draw(SpriteBatch batch, float parentAlpha) {
effect.draw(batch); //define behavior when stage calls Actor.draw()
}
public void act(float delta) {
super.act(delta);
effect.update(delta); //update it
}
}
I can post the snow.p file, but it's a bit large, if there's a particular section that would be helpful let me know and I will post it.
I started a project with libgdx and I have a GameStateManager for my GameStates Menu and Play.
If I run the project it shows the Menu and then I can click a button to open the Play GameState.
The Problem is, that when I ended the Game it should show the Menu State again, but I get a black screen. I tested if the render() method is started (with System.out...) and the render() method in Menu is starting.
I am not shure why I get a black screen when I "reopen" the Menu state. Maybe its not working because I use Box2D in Play but I dont know.
Here some code:
This is the method in Play which should open the Menu if the player is at the end:
public void playerEnded() {
gsm.setState(GameStateManager.MENU);
}
Maybe you can tell me, if I have to end box2d things or so.
I hope someone can help me, and if you want more code - no problem.
Your custom GameStateManager should extend this class:
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Game.html
To change screens you should be using Game.setScreen(Screen screen)
Each different screen should be an implementation of Screen.
So the way it works in my libGDX projects is such that GameScreen extends Screen, and MenuScreen extends Screen. That way I can change what draws on what screen.
This all goes back to interfaces and polymorphism, so if you don't get those concepts, just give it a quick google and you'll get an idea what you need to do.
Chances are that your are defining a
Stack<GameState> gameStates
in your GameStateManager to manage your GameStates.
If so, you could do some reading on using a Stack. Anyway, here's what could do to solve your problem:
I'm assuming you have the following structure in your GamestateManager;
public void setState(int state){
popState();
pushState(state);
}
public void pushState(int state){
gameStates.push(getState(state));
}
public void popState(){
GameState g = gameStates.pop();
g.dispose();
}
private GameState getState(int state){
if(state == MENU) return new Menu(this);
if(state == PLAY) return new Play(this);
return null;
}
When you click your start button in your Menu-GameState, you'll want to launch the Play-GameState.
Now, instead of using the setState method, which removes the top state (pop) and then pushes the new state. Try using only the pushState method. This will put your new Play-GameState on top of your Menu-GameState in the GameState-Stack.
When you're done playing, you can pop your Play-GameState and the Menu-GameState should reappear. But this time it won't instantiate a new Object, but reuse the one you used when you started the game.
// in the Menu-GameState:
public void startPlay() {
gsm.pushState(GameStateManager.PLAY);
}
// in the Play-GameState:
public void playerEnded() {
gsm.popState();
}
This won't affect gameplay performance as you would render and update your game with only the GameState that is on top of the Stack, like this:
public void update(float dt) {
gameStates.peek().update(dt);
}
public void render() {
gameStates.peek().render();
}
The peek method takes the GameState from the top of the Stack, but leaves it there.
The only downside is that the Menu-Gamestate would stay in-memory during your Play-State.
Also, if this method works, you could still do it your way, but you should check the way your Menu-GameState is instantiated and identify problems when it's instantiated twice.
I implemented a similar StageManager in my game. If you are using viewports/cameras in your game, then it is likely that when you go back to your menu state, the viewport is still set to the Game state's viewport.
For my app, I had my State class have an activate() method which would be called whenever a state became the active state:
public void activate(){
stage.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
I have a client-server application and i am using swing in the client side. My swing client has one main window (jframe) and lots of panels, toolbars and menubar in it.
I want to remove all client action/mouse events (or simply grab and do nothing) while client is waiting response from server by means of glasssPane.
Here is the code i wrote:
private final static MouseAdapter mouseAdapter = new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
System.out.println("MouseClicked..!");
}
};
private static Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
private static Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
and
public static void startWaitCursor(JComponent comp)
{
MainWindow root = ((MainWindow) comp.getTopLevelAncestor());
root.getGlassPane().setCursor(WAIT_CURSOR);
root.getGlassPane().addMouseListener(mouseAdapter);
root.getGlassPane().setVisible(true);
}
public static void stopWaitCursor(JComponent comp)
{
MainWindow root = ((MainWindow) comp.getTopLevelAncestor());
root.getGlassPane().setCursor(DEFAULT_CURSOR);
root.getGlassPane().setVisible(false);
}
but i am not able to manage the grab mouse events. Changing cursors at the glassPane is working fine but either i am not able to add mouseAdapter or am not able to make glasssPane become to the top level component.
Any idea?
Thanks.
I realized that my code is working but my problem is threading related. My code was something like:
startWaitCursor();
work(); // server request that takes time
stopWaitCursor();
and changed it to:
startWaitCursor();
SwingUtilities.invokeLater(new Runnable() {
poblic void run() {
try
{
work(); // server request
}
finally
{
stopWaitCursor();
}
by doing this modification i could see the settings i made in the startWaitCursor() method while client is waiting response from the server.
But stil there is a small problem. In startWaitCursor() method i desabled key, mouse and focus events for the glass pane but events are still captured by main frame even glassPane is displayed.
addMouseListener(new MouseAdapter() {});
addMouseMotionListener(new MouseMotionAdapter() {});
addKeyListener(this);
setFocusTraversalKeysEnabled(false);
After server response reached to client and stopWaitCursor() method is invoked the events handled in the main frame.
If i disable the main frame of my application while client is waiting than cursor is not being changed to wait_cursor, if i am not disable the main frame then cursor is being changed but the events are queued.
cheers...
After digging swing threads issues couple of days, i finally found the real answer: SwingWorker
Now my final code is something like,
startWaitCursor();
SwingWorker worker = new SwingWorker() {
public Object doInBackground()
{
doWork(); // time consuming server request
return null;
}
public void done()
{
stopWaitCursor();
}
};
worker.execute();
In startWaitCursor() method i set the glasspane visible (with alpha valued background), display a message to warn the user time consuming job is doing, set the cursor to wait_cursor (hourglass) and consume all the key, mouse events. That is it.
And by using SwingWorker my client is actually responsive (it is working as if no server request is made) but since i display the glasspane and consume all key and mouse events it feels like irresponsive.
What a relief.. SwingWorker rocks...
cheers..