I'm new to AndEngine and programming in general. I'm using ADT.
I have refactored some code into my Resource Manager, so it will load an animated sprite for me.
The image file is in the correct asset folder, and animated fine before I moved the code into the ResourceManager.java file.
Inside my onCreateResources (in GameActivity.java), I have this:
ResourceManager.getInstance().loadSpriteSheetTextures(mEngine, this);
pOnCreateResourcesCallback.onCreateResourcesFinished();
In the onCreateScene method of my GameActivity.java file, I have this:
animatedSprite = new AnimatedSprite(positionX,positionY,mTiledTextureRegion,mEngine.getVertexBufferObjectManager());
animatedSprite.animate(25);
mScene.attachChild(animatedSprite);
In my ResourceManager.java, I have this method:
public synchronized void loadSpriteSheetTextures(Engine engine, Context context){
//set our gfx asset folder
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
//create a animated sprite
BuildableBitmapTextureAtlas mBitmapTextureAtlas = new BuildableBitmapTextureAtlas(engine.getTextureManager(),512,512,TextureOptions.BILINEAR);
mTiledTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBitmapTextureAtlas, context, "plus.png", 6, 4);
try{
//
mBitmapTextureAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource,BitmapTextureAtlas>(0,0,0));
mBitmapTextureAtlas.load();
}catch(TextureAtlasBuilderException e){Debug.e(e);}
}
I should get a spinning top, but I get the spritesheet printed to screen, with the top right borders cut off, no animation..
In LogCat, I get an error about Null pointer exception (I guess it's related).
It worked fine until I 'refactored' it into a mess ...
Please help.. What am I doing wrong?
(edited typos)
.
Related
In school I am working on a project using JavaFx. I would like to make it special and use a GIF as background.
It works and displays my GIF, but it makes my program and GIF run realy slow.
Is there a way to fix this using Threads?
(I am new to using threads and don't realy know how to use them here).
this is my code for the background:
public class WelkomScherm extends StackPane
{
private final screenControl sCtrl;
public WelkomScherm(screenControl sCtrl)
{
this.sCtrl = sCtrl;
//Image backgroundImage = new Image("/img/startBG.gif");
Image backgroundImage = new Image("/img/Welkom.png");
ImageView background = new ImageView(backgroundImage);
background.setFitHeight(height);
background.setFitWidth(width);
...some buttons and labels...
this.getChildren().addAll(background,...,...);
}
I am also new to working on bigger projects, all tips are welcome!
I know most questions on the community should be done with at least some code. But I´m totally lost here, I don´t even know where to start. What I want to do is use the Vuforia AR Library to render LibGDX 3D modelInstances. However, I don't know how can I make Vuforia render the modelInstances or use a libGDX camera as it´s camera.
I've done external research but I have not been able to find useful information. Is there anyone who can help me get started with this?
Please note that I am not versed in Vuforia AR specifically, but the question has gone unanswered for a while, so I will give it a shot.
The Camera in LibGDX is essentially just a wrapper for two 4x4 matrices, the view matrix Camera#view, and the projection matrix Camer#projection (there is another Matrix, the model matrix, used for world space transformations, however I believe [but am not 100% certain] that in LibGDX, this matrix is already incorporated into the view matrix [so Camera#view is actually the model-view matrix]).
Anyway, following on from this, unless there is a simpler solution that I am not aware of, you should be able to use these underlying matrices to deal with projections between the the Vuforia and LibGDX apis.
(recommended further reading: Model, View, Projection matrices in 3D graphics)
Next is rendering LibGDX 3D ModelInstances using Vuforia. A general solution to this problem, would be to convert the ModelInstance into something that Vuforia can recognize. This would be done by taking the mesh/vertex data represented by the LibGDX model, and feeding it directly into Vuforia.
IMO, the best way of going about this, would be to use a a core representation of the model data which can easily be given to both Vuforia and LibGDX (for example, a certain file format that both can recognize, or as raw FloatBuffers which should be easy to wrap up and give to either API). For reference, LibGDX stores models as vertex information in a collection of FloatBuffers, accessible through Model#meshes or ModelInstance#model#meshes.
Ok. So I finfally managed to combine both libraries. I´m not sure if what I´m doing is the most efficient way of working but it has worked for me.
First of all I´m basing myself on the Sample Apps from Vuforia. Specifically using the FrameMarkers example.
I opened an empty LibGDX project, imported the Vuforia jar and copied the SampleApplicationControl, SampleApplicationException, SampleApplicationGLView, SampleApplicationSession, FrameMarkerRenderer and FrameMarker.
Next, I created some attributes on the AndroidLauncher class of LibGDX and initialized all the Vuforia Stuff:
public class AndroidLauncher extends AndroidApplication implements SampleApplicationControl{
private static final String LOGTAG = "FrameMarkers";
// Our OpenGL view:
public SampleApplicationGLView mGlView;
public SampleApplicationSession vuforiaAppSession;
// Our renderer:
public FrameMarkerRenderer mRenderer;
MyGDX gdxRender;
// The textures we will use for rendering:
public Vector<Texture> mTextures;
public RelativeLayout mUILayout;
public Marker dataSet[];
public GestureDetector mGestureDetector;
public LoadingDialogHandler loadingDialogHandler = new LoadingDialogHandler(
this);
// Alert Dialog used to display SDK errors
private AlertDialog mErrorDialog;
boolean mIsDroidDevice = false;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
vuforiaAppSession = new SampleApplicationSession(this);
vuforiaAppSession.setmActivity(this);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
// Load any sample specific textures:
mTextures = new Vector<Texture>();
loadTextures();
startLoadingAnimation();
vuforiaAppSession.initAR(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
gdxRender = new MyGDX (vuforiaAppSession);
gdxRender.setTextures(mTextures);
initialize(gdxRender, config);
mGestureDetector = new GestureDetector(this, new GestureListener());
mIsDroidDevice = android.os.Build.MODEL.toLowerCase().startsWith(
"droid");
}
I needed to set the activity so I created the setmActivity() on the SampleApplicationSession.
After that I implemented the Libgdx ApplicationAdapter class and passed the vuforiaAppSession as an attribute to access all the stuff I initialized.
public class MyGDX extends ApplicationAdapter {
ModelInstance modelInstanceHouse;
private AnimationController controller;
Matrix4 lastTransformCube;
// Constants:
static private float kLetterScale = 25.0f;
static private float kLetterTranslate = 25.0f;
// OpenGL ES 2.0 specific:
private static final String LOGTAG = "FrameMarkerRenderer";
private int shaderProgramID = 0;
private Vector<com.mygdx.robot.Texture> mTextures;
//SampleApplicationSession vuforiaAppSession;
PerspectiveCamera cam;
ModelBuilder modelBuilder;
Model model;
ModelInstance instance;
ModelBatch modelBatch;
static boolean render;
public SampleApplicationSession vuforiaAppSession;
public MyGDX ( SampleApplicationSession vuforiaAppSession){
super();
this.vuforiaAppSession = vuforiaAppSession;
}
The last important thing to keep in mind is the render() method. I based myself on the the render method of the FrameMarkerRenderer. It has a boolean that gets activated when the camera starts. So I simple changed the variable both on the vuforia AR initialization and the render() method. I had to put the camera on and identity matrix and multiply the model by the modelViewMatrix.
#Override
public void render() {
if (render) {
// Clear color and depth buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Get the state from Vuforia and mark the beginning of a rendering
// section
State state = Renderer.getInstance().begin();
// Explicitly render the Video Background
Renderer.getInstance().drawVideoBackground();
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// We must detect if background reflection is active and adjust the
// culling direction.
// If the reflection is active, this means the post matrix has been
// reflected as well,
// therefore standard counter clockwise face culling will result in
// "inside out" models.
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glCullFace(GLES20.GL_BACK);
cam.update();
modelBatch.begin(cam);
if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() == VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON)
GLES20.glFrontFace(GLES20.GL_CW); // Front camera
else
GLES20.glFrontFace(GLES20.GL_CCW); // Back camera
// Set the viewport
int[] viewport = vuforiaAppSession.getViewport();
GLES20.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Did we find any trackables this frame?
for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
{
// Get the trackable:
TrackableResult trackableResult = state.getTrackableResult(tIdx);
float[] modelViewMatrix = Tool.convertPose2GLMatrix(
trackableResult.getPose()).getData();
// Choose the texture based on the target name:
int textureIndex = 0;
// Check the type of the trackable:
assert (trackableResult.getType() == MarkerTracker.getClassType());
MarkerResult markerResult = (MarkerResult) (trackableResult);
Marker marker = (Marker) markerResult.getTrackable();
textureIndex = marker.getMarkerId();
float[] modelViewProjection = new float[16];
Matrix.translateM(modelViewMatrix, 0, -kLetterTranslate, -kLetterTranslate, 0.f);
Matrix.scaleM(modelViewMatrix, 0, kLetterScale, kLetterScale, kLetterScale);
Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession.getProjectionMatrix().getData(), 0, modelViewMatrix, 0);
SampleUtils.checkGLError("FrameMarkers render frame");
cam.view.idt();
cam.projection.idt();
cam.combined.idt();
Matrix4 temp3 = new Matrix4(modelViewProjection);
modelInstanceHouse.transform.set(temp3);
modelInstanceHouse.transform.scale(0.05f, 0.05f, 0.05f);
controller.update(Gdx.graphics.getDeltaTime());
modelBatch.render(modelInstanceHouse);
}
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
modelBatch.end();
}
It´s a lot of code, but I hope it helps the people that try to start integrating both libraries. I don´t think this is efficient but it´s the only solution I´ve come with.
Pablo's answer is pretty good, however, if you are interested in a bit different approach (Calling Vuforia from LibGDX, not the other way) and a more complete example, here is a github repo with a simple 3D model renderer.
I'm using Libgdx and AssetManager to load assets into memory. First I thought that something is wrong with my project so I made a new clean one, and the problem persists.
The Sound is not playing even if I use "IsLoaded" method and is not playing the first time (if you jump really quick into the game). The sound is small , like 40KB, and this happens only on Android (works on Desktop/iOS). The device I'm testing on Android is HTC One M7 with Lolipop. Here is the code of a clean project.
package com.mygdx.game;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.audio.Sound;
public class MyGdxGame extends ScreenAdapter {
private AssetManager assetManager;
#Override
public void show() {
super.show();
assetManager = new AssetManager();
assetManager.load("sound/jump.mp3", Sound.class);
}
Sound jump;
boolean isLoaded;
#Override
public void render(float delta) {
super.render(delta);
if(isLoaded) return;
assetManager.update();
if(assetManager.isLoaded("sound/jump.mp3", Sound.class)) {
assetManager.finishLoading();
jump = assetManager.get("sound/jump.mp3", Sound.class);
isLoaded = true;
System.err.println("LOADED");
jump.play();
}
}
}
In LOGCAT I'm getting "soundpool sample 1 not ready" error.
Any ideas?
NOTE: The sound is playing as normal if I give it a little time (If I don't press "play" right away).
The question is why does Libgdx thinks that the sound is loaded into memory even if its not.
Have you tried using .ogg instead?
On my libgdx projects i always used .ogg, since its license -free and well, it never gave me issues!
You should also be careful with the different Sound imports. I remember that you can sometimes import directly .ogg .mp3 classes from libgdx and that causes issues.
Also, i think the problem is that, even if the audio file was loaded, the assetmanager is still loading other resources.. so its busy doing another task.
I would either :
a) Play that sound without the assetmanager, since its just for the loading, right?
b) (This needs to be checked) But Maybe use a different assetmanager for that audio? Unsure how much resource would it waste by having 2 assetmanagers..
But, i would try that. Change to .ogg first, be sure the audio starts at exactly 0:00 and update to the last libgdx version.
I'm experiencing the same issue. I am using libgdx version 1.9.2. So far, I tried:
changing mp3 to ogg
using different asset manager for sounds
and it didn't help.
I replaced Sound object with Music object and it did help. But I'm not sure if this is the right approach, because I have a lot of short sounds in my app.
I know this is an old thread but I just ran into this same problem and I solved it like this..
private Sound sound;
private float soundVolume;
public void playSound(String path, float volume) {
sound = assetManager.get(path, Sound.class);
soundVolume = volume;
}
#Override
public void render () {
super.render();
// Because of some weird Android bug
if (sound != null) {
sound.play(soundVolume);
sound = null;
}
}
This is in my main game class and I can call the playSound() method from any other class.
It's probably caused by Gdx.audio.newSound() method is loading the sound by asynchronously instead asserting sound loading process to processor. I solved this by adding a "delay" to the playing sound process only for the first playing. That solved my problem.
private static void soundBugFixer(Sound sfx, float volume)
{
Timer x = new Timer();
x.scheduleTask(new Timer.Task() {
#Override
public void run() {
sfx.play(volume);
}
}, 0.1f );
}
public static void remove(float volume) {
if(sfxRemove == null)
{
sfxRemove = Gdx.audio.newSound(Gdx.files.internal("sfx/sfx_remove.wav"));
soundBugFixer(sfxRemove, volume);
}
else
{
sfxRemove.play(volume);
}
}
So for my 2D game I want to use an image to represent a player but when I try to use an image, it tells me that it couldn't be "instantiated". I don't know what that means:
public class PlayerOne extends Entity{
private Image img = new Image();
[...]
#Override
public void render(Graphics g){
g.drawImage( img , x, y, Color.BLUE, new ImageObserver());
}
}
I tried it in another class with BufferedImages but that somehow doesn't work.
So it can't create Objects of neither Image nor the ImageObserver. Does anyone know a fix for this error ?
You cannot instantiate an abstract class. Please see link.
Following syntax would be operational:
private Image image = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
Also see link for more information on BufferedImage. Additionally, here is a tutorial which ilustrates an example implementation;
You should have an image file (*.png for example ) to start with. Then use
Image img = new ImageIcon("img.png").getImage();
I'm not sure where the problem is. Is it in the path? The image doesn't show although there are no errors at all in the code syntax. Should I provide the whole path or just place the image in the directory and call its name? Thank you.
public class NetworkingGame {
private JFrame jfrm;
NetworkingGame(){
jfrm = new JFrame("Angry Painters");
jfrm.setSize(800, 480);
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jfrm.setVisible(true);
}// end of constructor
public void ImageLoading(){
ImageIcon i = new ImageIcon("C:/Users/TOSHIBA/Documents/NetBeansProjects/NetworkingGame/build/classes/angry-painters.jpeg");
JLabel jl = new JLabel(i);
jfrm.add(jl);
}
public static void main(String[] args) throws Exception{
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
NetworkingGame ng = new NetworkingGame();
ng.ImageLoading();
} // end of run method
}); // end of Runnable
}//end of main method
}//end of class NetworkingGame
Do not use the file path as icon location as this will only work on your computer. You really cannot expect all machines in the world to have C:/Users/TOSHIBA ...angry-painters.jpeg in the right place!
Copy the file next to the source code (.java) class you use and then call
new ImageIcon(getClass().getResource("angry-painters.jpeg"));
The builder should copy the image resource to the class folder itself.
Try to use path something like this :
jLabel1.setIcon(new ImageIcon("c:\\Users\\xyz\\Documents\\NetBeansProjects\\game\\src\\images.jpg"));
Update
If dis also does not work, then
jLabel.setIcon(new ImageIcon(getClass().getResource("/image.jpg")));
jLabel.setText("jLabel");
should.The image.jpg should be inside your project folder.
I think your code doesn't like the way your binding the image.
assumes that your put the images/icons in the source folder
ImageIcon i=new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg"))
or if you create a folder in the source folder
InputStream stream = this.getClass().getClassLoader().getResourceAsStream("/images/image.jpg");
BufferedImage bufferedImage=ImageIO.read(stream);
ImageIcon icon= new ImageIcon(bufferedImage);
in IntellijIdea. 2021
In my case it just didn't read image files.
To fix that:
1. make res folder in project root('src's folder sibling)
2. Handle artifact in File->Project Structure->artifacts by + , -
3. File->Project Structure->artifacts->output layout tab make structure of final jar as 'res' folder , app root package folder(say 'com'), and 'META-INF' folder. Fill out them with content from yourapp/output folder and 'res's content from mentioned in 1. step 'res'.
4. After that in 'project structure' 'Modules' rightclick on 'res' and mark it as resources.
5. Declare images like this:
ImageIcon loadingLcl = new ImageIcon(this.getClass().getResource("/res/32.gif"));
before putting into JLabel.
Also it s preferable to read image once when initializing the app. Otherwise sometimes it can throw IOException. So if possible handle that at start. Like they do in gamemaking.