I'm creating an Android game (basic game), and got stuck with displaying certain image on a canvas.
The game intention is to press the image and the image will change it's location.
I've made sure all the methods are written properly and image resource does exist.
The other questions which relates to "canvas isn't showing" here didn't assist me because my game doesn't involve any XML (yet).
I've followed this guide:
https://www.androidauthority.com/android-game-java-785331/
This is the my GameView class which suppose to create the image:
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
public GameView(Context context) {
super(context);
getHolder().addCallback(this);
thread = new MainThread(getHolder(), this);
setFocusable(true);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas=new Canvas();
thread.setRunning(true);
thread.start();
characterSprite = new CharacterSprite(BitmapFactory.decodeResource(getResources(),R.drawable.avdgreen));
characterSprite.draw(canvas);
}
#Override
public void draw(Canvas canvas){
super.draw(canvas);
characterSprite.draw(canvas);
}
}
My CharacterSprite class:
public CharacterSprite(Bitmap png) {
image = png;
x=100;
y=100;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(image, 100, 100, null);
}
The Image should appear on the screen, yet all I get is blank screen.
Thanks.
Related
I am having an issue when switching screens in libgdx. I am building a asteroids game clone. So first my MainMenuScreen class (which uses a Fitviewport) is rendered and then I call setScreen() to GameScreen (GameScreen doesn't use a Fitviewport) and that works except that the second screen renders as if its using a Fitviewport. If I resize the second screen then the whole window is used for rendering. Why is this happening? Here are some pictures:
MainMenuScreen class:
GameScreen class after switching screens, the screen has black bars on the side (I colored the boundary in red for you) which I don't want:
I want the GameScreen to use all the window area for rendering, and not have black bars like the MainMenu. I am not using any Fitviewport in GameScreen also.
Here are relevant parts of my MainMenuScreen class:
public class MainMenuScreen implements Screen
{
private static final String TAG = "MainMenu";
private static final int VIRTUAL_WIDTH = 400;
private static final int VIRTUAL_HEIGHT = 400;
MyGdxGame game;
...
public MainMenuScreen(MyGdxGame game)
{
this.game = game;
viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
stage = new Stage(viewport);
// Play button listener
btnPlay.addListener( new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(TAG, "PLAY");
MainMenuScreen.this.game.setScreen(MainMenuScreen.this.game.gameScreen);
};
});
....
}
Here is my GameScreen class:
MyGdxGame game;
OrthographicCamera guiCam;
World world;
WorldRenderer renderer;
public GameScreen(MyGdxGame game, SpriteBatch batch)
{
this.game = game;
guiCam = new OrthographicCamera(400, 400);
guiCam.position.set(400 / 2, 400 / 2, 0);
world = new World();
renderer = new WorldRenderer(game, batch, world);
}
public void draw()
{
GL20 gl = Gdx.gl;
gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
}
#Override
public void show()
{
world.createLevel();
}
#Override
public void render(float delta)
{
draw();
}
#Override
public void resize(int width, int height)
{
}
#Override
public void pause()
{
}
#Override
public void resume()
{
}
#Override
public void hide()
{
}
#Override
public void dispose()
{
}
The problem is this line of code:
public void resize(int width, int height)
{
viewport.update(width, height, true);
}
Whenever you update the viewport, you are also updating the underlying opengl viewport and this causes the black bars to persist to the second screen (https://github.com/libgdx/libgdx/wiki/Viewports). Thus if you want to reset it back to normal you must use the following line of code in your second screen show() method (https://github.com/libgdx/libgdx/wiki/Scene2d):
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
I store all of my assets in a class and load them at the start of my game, I am trying to create a loading screen in a separate class.
Asset manager class:
public class Assets {
public static AssetManager manager = new AssetManager();
public static void queueLoading() {
(..)
manager.load("sound/buttonpress.mp3", Sound.class);
(..)
while(!manager.update())
{
System.out.println("Loaded: " + manager.getProgress() *100 + "%");
}
}
public static boolean update() {
return manager.update();
}
}
Loading screen class:
public class LoadingScreen implements Screen{
final Game1 game;
Sprite LdScreen;
OrthographicCamera camera;
public LoadingScreen(Game1 gam){
game=gam;
camera = new OrthographicCamera();
camera.setToOrtho(false, 1920, 1080);
}
public void show() {
Texture LdscreenTexture = new Texture(Gdx.files.internal("data/Background.png"));
LdScreen = new Sprite (LdscreenTexture);
Assets.queueLoading();
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
game.batch.draw(LdScreen, 0,0);
game.batch.end();
// Assets.queueLoading();
if(Assets.update()){
game.setScreen(new MainMenuScreen(game));
System.out.print("hllasgsgsag");
}
Assets.update();
}
#Override
public void resize(int width, int height) {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
Problem:
When i run it in the console i get the progress percentage, but the screen stays black whilst it is loading (stuck at Assets class), then it flashes to the loading screen, and changes to MainMenuScreen.
How do I stop the black screen when the assets are loading?
The problem that you are having is because you are loading all the Assets straight away and this isn't done in a different thread and is run whilst the screen is being shown. I would advise using manager.update(delta) which should be called during your game loop and getting the update percentage. The full source would be a bit difficult for me to explain but I have done something similar in my previous projects, the sources are available on GitHub below:
The Assets class:
https://github.com/basimkhajwal/NinjaTower/blob/master/NinjaTower/core/src/net/net63/codearcade/NinjaTower/utils/Assets.java
The Loading Screen:
https://github.com/basimkhajwal/NinjaTower/blob/master/NinjaTower/core/src/net/net63/codearcade/NinjaTower/screens/MainMenuScreen.java
While i was learning about Libgdx i came across this problem of adding a child sprite to parent sprite in Libgdx as i did the same in Cocos2d it had no problem of doing it.
How can the same be achieved in Libgdx, so that i can perform operation on parent sprite and it will be followed by the child added to it.
EDIT : I have seen at https://github.com/libgdx/libgdx/wiki/Scene2d of scene2d, but they havn't mentioned how to make use of Group.
This is what i tried earlier but its coming white screen
public class TestScreen implements Screen{
private MainGame game;
private Sprite sprite;
public Group group;
private Stage stage;
private SpriteBatch batch;
public TextureAtlas atlas1;
public Skin skin;
public Image bg;
public Sprite sprite1;
public TestScreen(MainGame game)
{
this.game=game;
group = new Group();
batch = new SpriteBatch();
circle=AssestLoader.circle1;
}
#Override
public void render(float delta)
{
// TODO Auto-generated method stub
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(delta);
batch.begin();
stage.addActor(group);
batch.end();
}
#Override
public void show() {
// TODO Auto-generated method stub
atlas1 = new TextureAtlas("test/gamescreentest.pack");
skin = new Skin();
skin.addRegions(atlas1);
bg = new Image();
bg.setDrawable(skin, "playbg_hdpi");
bg.setHeight(460f);
bg.setWidth(460f);
group.addActor(bg);
}
#Override
public void hide() {}
#Override
public void resize(int width, int height) {}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void dispose() {}}
Its coming white screen without image
You could use scene2d and actors (https://github.com/libgdx/libgdx/wiki/Scene2d). But this would require you to (maybe) rewrite parts of your application.
If your images are static and don't change I'd recommend you to draw the child ontop of the parent using a framebuffer. That'd be best in case of performance.
EDIT: The blog post at http://www.gamefromscratch.com/post/2013/12/11/LibGDX-Tutorial-3C-Scene-management.aspx has a very good example of groups.
I wanted to use a SurfaceView with a "sticky" canvas. i.e. one that preserves its state and does not get ivalidated. I followed an example that showed how to set up a holder and use a separate thread for the drawing. The idea is that when touching anywhere on the SurfaceView, drawStuff will be called, given some paint, and a random rectangle should be drawn.
Although the code executes perfectly, nothing is drawn at the end.
public class DrawingView extends SurfaceView implements Callback {
Paint currentPaint;
float verts[];
private Boolean drawing = false;
class DrawingThread extends Thread {
private SurfaceHolder surfaceHolder;
private SurfaceView surfaceView;
private Boolean isRunning = false;
public void setIsRunning(Boolean isRunning) {
this.isRunning = isRunning;
}
public DrawingThread(SurfaceHolder surfaceHolder, SurfaceView surfaceView) {
super();
this.surfaceHolder = surfaceHolder;
this.surfaceView = surfaceView;
}
#Override
public void run() {
while(isRunning) {
Canvas c = surfaceHolder.lockCanvas();
surfaceView.draw(c);
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
DrawingThread thread;
public DrawingView(Context context) {
super(context);
this.setWillNotDraw(false);
this.setBackgroundColor(Color.WHITE);
this.getHolder().addCallback(this);
this.thread = new DrawingThread(getHolder(), this);
}
#Override
protected void onDraw(Canvas canvas) {
if (drawing) {
// TEST CODE. WILL NEVER USE THIS IN PRODUCTION
canvas.drawRect(new Rect(new Float(Math.random()*200).intValue(), 20, new Float(Math.random()*200).intValue(), 30), currentPaint);
drawing = false;
}
}
public void drawStuff(Paint paint) {
currentPaint = paint;
drawing = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setIsRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.setIsRunning(false);
}
}
and the paint set up:
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
paint.setAlpha(55);
((DrawingView) v).drawStuff(paint);
//v.invalidate();
return false;
}
});
In the end, you're not actually drawing things when you think you are. Calling draw() schedules the draw on your UI thread, but doesn't actually call onDraw from your background thread so your Canvas is no longer valid with respect to the surface. You should render whatever you are doing into a Bitmap object and when you are ready to write to the surface, notify the UI thread. The UI thread can then lock the surface, draw the bitmap into the Canvas, then unlock and post the Canvas to the surface.
I just started learning libGDX, and was following the example from http://steigert.blogspot.in/2012/02/2-libgdx-tutorial-game-screens.html (the second link on libGdx help page).
As of now, I just display a logo of 512x512. There is nothing else happening in the application but when I run the application in desktop mode,I get a FPS of 15-16. When I remove the image, I get 60fps for the blank screen. For android its even worse, I get 3-4 fps in Galaxy SL - GT-i9003 (Temple Run runs on playable speed on the device).
My laptop plays World of Warcraft without any hiccups in high quality so its baffling that such a small app would only achieve 15fps.
public class SplashScreen extends AbstractScreen {
private Texture splashTexture;
private TextureRegion splashTextureRegion;
public SplashScreen(MyGDXGame game){
super(game);
}
#Override
public void show()
{
super.show();
// load the splash image and create the texture region
splashTexture = new Texture("splash.png");
// we set the linear texture filter to improve the stretching
splashTexture.setFilter( TextureFilter.Linear, TextureFilter.Linear );
// in the image atlas, our splash image begins at (0,0) at the
// upper-left corner and has a dimension of 512x301
splashTextureRegion = new TextureRegion( splashTexture, 0, 0, 512, 382 );
}
#Override
public void render(float delta ) {
super.render( delta );
// we use the SpriteBatch to draw 2D textures (it is defined in our base
// class: AbstractScreen)
batch.begin();
// we tell the batch to draw the region starting at (0,0) of the
// lower-left corner with the size of the screen
batch.draw( splashTextureRegion, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight() );
// the end method does the drawing
batch.end();
}
#Override
public void dispose()
{
super.dispose();
splashTexture.dispose();
}
}
Here is the relevant section of AbstractScreen class:
public class AbstractScreen implements Screen {
protected final MyGDXGame game;
protected final BitmapFont font;
protected final SpriteBatch batch;
public AbstractScreen(MyGDXGame game ){
this.game = game;
this.font = new BitmapFont();
this.batch = new SpriteBatch();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor( 0f, 0f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
}
...
}
And the desktop app:
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "First Game";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(new MyGDXGame(), cfg);
}
MyGDXGame is as follows:
public class MyGDXGame extends Game {
private FPSLogger fpsLogger;
public SplashScreen getSplashScreen() {
return new SplashScreen( this );
}
#Override
public void create() {
fpsLogger = new FPSLogger();
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
super.render();
setScreen(getSplashScreen());
fpsLogger.log();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
I have read so many good things about libGdx, so this issue seems baffling to me. What am I doing wrong to get such a low frame rate?
I think setScreen(getSplashScreen()); in your render() method might be the problem. Move it to the create() method of MyGDXGame.
Right now you are switching the screen in every single frame and recreate a SpriteBatch every single time which is a very heavy object (see my comment to your question).