I recently started to learn about android and java and to practice I started to make a space invader-type game.
In order to draw all the images(player/enemy/etc) I've been using an overridden onDraw method and canvas.DrawBitmap(..). This is where my problem starts. Whenever I draw the images with their new X,Y coordinates, the previous bitmap is still on the canvas which makes everything overlap. Is there some way to refresh the canvas or just get rid of the "leftovers"(I don't even know what to call them). When I made this I was under the impression that I just move the 1 image across the screen but it looks like I was wrong.
This is the code I use to draw the player bitmap:
public void render(Canvas canvas){
//draw the player image
canvas.drawBitmap(_bmPlayerImg, (float) (_dX - (_iHalfWidth)),
(float)(_dY - (_iHalfHeight)), null);
}
The onDraw() method:
#Override
protected void onDraw(Canvas canvas) {
//draw the player
_player.render(canvas);
}//end method
The onDraw() method is called in a thread I use as my game timer every 50ms:
public Runnable runnable = new Runnable() {
#Override
public void run() {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized(surfaceHolder){
//update the state of all objects in the game
gamePanel.update(canvas);
gamePanel.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}//end if
}//end finally
handler.postDelayed(this, _iRepeatTime);
}
};
Any help is appreciated...I tried looking it up but I couldn't find anything.
Before you draw anything on the canvas:
//clear the canvas
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
And now your canvas is clear and you can draw your character.
If your onDraw method was in an expanded view class and was triggered by you calling invalidate(), then the canvas would automatically clear itself. But you are manually calling it (looks like you are using a surface/texture view?), so you have to clear it manually.
Related
i am newbie for libgdx,
How to create very simple pause/resume game in libgdx??
I'm trying to implement simple game using libgdx. I have want to create pause the game but don't know how to pause and resume game based on user input.Kindly suggest idea as well as some practical code to implement the same.I am using simple game code demonstrated in libgdx library. Thank you.
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
float x;
float y;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
x= x+4;
if(Gdx.input.isKeyPressed(Input.Keys.P)){
// pause
}
batch.begin();
batch.draw(img, x, y);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
img.dispose();
}
}
Press P key to press the game
if(Gdx.input.isKeyPressed(Input.Keys.P)){
// if(game.pause()){
game.resume();
}else{
game.pause();
}
}
any idea??? thanks
Your render method is called repeatable and what "paused" means is up to you. You have to implement your logic that handles "paused" state because that doesn't mean anything to libGDX.
If you want everything to freeze when game is paused but still to be drawn best way is (IMHO) to fully separate drawing from calculating (movements and stuff). So i.e. when your render method is called you will call your drawing method once (to draw the graphics) but you will also calculate how many times your calculation method should be call (to have same game speed independently on frame rate) and call it that many times.
Then when your game is paused you will just skip calling your calculation method and call only drawing method. So nothing will move and until you end your pause the same graphics will be drawn.
And to keep paused state you can have some boolean variable. Every time p key is pressed you should invert it, like:
if(Gdx.input.isKeyPressed(Input.Keys.P)){
paused = !paused;
}
or something (as #Tenfour04 suggested).
I'm trying to understand if onDraw method of the same View/Custom View object runs with exactly the same Canvas object?
I tried to examine an implementation when from my code i'm calling onDraw method (and without using invalidate method). in the onDraw method i'm saving the Canvas object that is an input parameter of this method as an object member, and than using this object. I can't understand if it a valid operation, or a Canvas object is different between two different runs of onDraw method and saving it won't serve me?
Code (can be an inner Class):
private class CustomView extends View
{
Canvas canvas;
#Override
public void draw(#NonNull Canvas canvas)
{
this.canvas = canvas;
Path path = new Path();
if (Utils.isLangRTL())
{
path.moveTo(lineColor.getWidth(), 0);
path.lineTo((float) 0.9 * lineColor.getWidth(), lineColor.getHeight());
path.lineTo(0, lineColor.getHeight());
path.lineTo((float) 0.1 * lineColor.getWidth(), 0);
path.lineTo(lineColor.getWidth(), 0);
canvas.drawPath(path, new paint());
}
}
and than calling the code from somewhere (UI Thread):
customView.onDraw(customView.canvas);
Hello I am working out a game and I wonder how to dispose resources as I am experiencing memory problems.
I have something like this:
public SplashScreen implements Screen {
#Override
public void render(float delta) {
}
#Override
public void dispose() {
if (batch != null)
batch.dispose();
batch = null;
}
}
public MapScreen implements Screen {
#Override
public void render(float delta) {
}
#Override
public void show() {
splashScreenInstance.dispose();
}
#Override
public void dispose() {
if (mesh != null)
mesh.dispose();
mesh = null;
}
}
And I am disposing the splash screen as soon as the show method of MapScreen is called. Previously I'd settled the screen to the MapScree. Still the render method of the splashScreenInstance is called and I'd received null pointer exceptions. Why this is so?
I'd expect that once I set another screen, the previous one is no longer rendered. This is not seemingly so. I'd tried disposing right after setting the screen using the game instance, right after the hide method is called on the screen I want to dispose and finally on the show method of the next screen. All of these cases still renders the previous screen a few times before rendering the current one.
I really need to recover memory and also I don't want to test each time (On the render method) for null pointers as this has performance penalties.
Any suggestions?
Thanks
This is how I usually handle this problem:
public SplashScreen implements Screen {
#Override
public void render(float delta) {
// I assume that you have a reference to the game somewhere to switch the screen
game.setScreen(new MapScreen());
dispose();
return;
}
}
I first set the new Screen, then dispose() the current one and then immediately stop any further execution of the current screen via return. This way the current render cycle should be stopped and in the next cycle the render() of your next screen will be called.
Another approach might be to call dispose() in your hide() method of the Screens, because that is going to be the last method being called before the Game will use the next screen. This is especially useful when there could be several different next screens. In that case there will still be only a single place of dispose() and that will be in the hide() method.
Where are you calling setScreen? Since everything should be happening in the rendering thread (even InputListeners) you should be able to call setScreen in your first Screen and then return from the render method. The Game instance will automatically call hide on your first Screen which is where you can call dispose.
I'm developing a Tower Defense game using libGDX. I've just started and I am able to display the path, the "environment" and the enemies walking along the path.
I displayed the environment using a SpriteBatch-Object, like this:
public LevelController(Level level) {
spriteBach = new SpriteBach();
atlas = new TextureAtlas(Gdx.files.internal("images/textures/textures.pack"));
}
public void setSize() {
spriteBatch.setProjectionMatrix(this.cam.combined);
}
public void render() {
spriteBatch.begin();
drawTowerBases();
spriteBatch.end();
}
private void drawTowerBases() {
// for each tower base (=environment square)
TextureRegion towerBaseTexture = atlas.findRegion("TowerBase");
if(towerBaseTexture != null) {
spriteBatch.draw(towerBaseTexture, x, y, 1f, 1f);
}
}
This is working properly and the textures are displayed well: Tower Defense using spriteBatch
Now, I was wondering if it is possible to cache the background. Because it stays the same, there is no need to calculate it every time. I've found the SpriteCache through Google-Search. So I changed the code as follows:
public LevelController(Level Level) {
spriteCache= new SpriteCache();
atlas = new TextureAtlas(Gdx.files.internal("images/textures/textures.pack"));
spriteCache.beginCache();
this.drawTowerBases();
this.spriteCacheEnvironmentId = spriteCache.endCache();
}
public void setSize() {
this.cam.update();
spriteCache.setProjectionMatrix(this.cam.combined);
}
public void render() {
spriteCache.begin();
spriteCache.draw(this.spriteCacheEnvironmentId);
spriteCache.end();
}
private void drawTowerBases() {
// for each tower base (=environment square)
TextureRegion towerBaseTexture = atlas.findRegion("TowerBase");
if(towerBaseTexture != null) {
spriteCache.add(towerBaseTexture, x, y, 1f, 1f);
}
}
And now the game looks like this: Tower Defense using spriteCache
For me it seems as if the transparency is not rendered properly. If I take images without transparency, everything works fine. Does anyone have an idea, why this happens and how I can fix this?
Thank you in advance.
Taken from the SpriteCache documentation:
Note that SpriteCache does not manage blending. You will need to enable blending (Gdx.gl.glEnable(GL10.GL_BLEND);) and set the blend func as needed before or between calls to draw(int).
I guess there is not much more to say.
I have to write a simple Java app which can load pictures, show it in a GUI form, allow the user to apply some transformation, and show the transformed picture.
My solution is working fine, but the UI is flickering a bit, because the repaint method called too often (for example when the user scaling the image with a JSlider)
My code looks like this:
public class ImageCanvas extends Canvas
{
private BufferedImage image;
// ...
#Override
public void paint(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
if(image != null)
{
// I draw out the image...
}
}
public void setImage(BufferedImage image)
{
this.image = image;
this.repaint();
}
public void setRotation(double rotation)
{
this.rotation = rotation;
this.repaint();
}
public void setScale(double scaleX, double scaleY)
{
//set the scaling field, then repaint ....
}
// and so on...
}
And, of course, I have an ImageCanvas control on my main UI, and I simply call the public methods (see for example the "setRotation" method above) which repaint the canvas area. I know it's a simple question, but I don't even find a DoubleBuffered property on the Canvas...
Any help appreciated.
Double buffering is built-in for Swing (i.e. JComponent derived) classes.
If you want built-in double-buffering, you should extend JPanel rather than Canvas, and override paintComponent, not paint.
If you can use JPanel than go for it. Please make sure you are not overriding the JPanel.paint method, override JPanel.paintComponent instead.
See this link for details.
Usually graphic lags in these applications can be caused by setting a empty variable at the top of the script, then changing its value, then waiting for the repaint to update it. You could try changing the:
setRotation(double rotation);
so that it rotates the image in that method.
Just a general thing I happen to see while dealing with graphics.