Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (475)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (530)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Rendering problem and possible Life-Cycle bug  (Read 487 times)
0 Members and 1 Guest are viewing this topic.
Offline Kyactus

Junior Newbie





« Posted 2013-11-20 12:28:17 »

Hello, we're a group of four students actually trying to develop a clone of Super Mario with the LibGDX due to a university project.
We've implemented all the basic features, such as movement, collisions (both with powerups, enemies and blocks/obstacles), enemies (they all extend Sprite) and so on, while using Tiled for the maps. We've followed DermetFan tutorials ("Java Tiled Map Game" series) so, generally, the scheme of our project is like this:
1) A main calls a new LwjglApplication(new SuperMario(), cfg);
2) The super mario class is defined this way:

1  
2  
3  
4  
5  
6  
7  
8  
9  
public class SuperMario extends Game {

   @Override
   public void create() {
      setScreen(new Play());
     
   }

//the rest of the class is omitted 'cause it's just an overriding of all the the other metods of Game


3) Play is our main screen (for the first -and only level- we've created yet) and it implements Screen.


THE PROBLEM

So our problem is:
 While the game is running, sometimes (actually really often) ALL the sprites just completely disappear, resulting in the Mario Sprite "dying" (and respawning at the location we've set) as well as the enemies and the power-ups (mushrooms and Fire flowers), which won't be rendered anymore.
The fact is that we have NO idea what the problem is. We assume it's something related to the life cycle of the game, such as the fps skyrockets or gets at such a down value that the game doesn't actually know WHERE to render the sprites and just... puts them elsewhere (?). We really have no idea how to explain the problem properly, as we are kinda new to the libgdx and this is our second uni year. What's weirder/funnier is that in Windows Systems, this problem happens basically everytime. In Mac Systems, instead, it doesn't actually happen (just sporadically). For these reasons, here we put an executable jar file:

https://www.dropbox.com/s/vqrbp596xjd4srz/executableSuperMario.jar#

Just try and open it more than once and problem should occurs.

This is how it should appear when started (actually there is one less Goomba 'cause it died ALONE before we could actually click on print/stamp):

http://www.dropbox.com/s/5uwiv5gl8j8eq17/HowItShouldAppear.png

and here is the render code of the class Play:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
@Override
   public void render(float delta) {
      if (!isPaused){
         Gdx.gl.glClearColor(0, 0, 0, 1);
         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

         renderer.setView(camera);
         renderer.render();

                        //just some camera setting
        if( player.getX()<=149 && player.getY()<200 )
            camera.position.set((float)149, player.getHeight() /2 + 93, 0);
         else  if( player.getX()>149 )
            if( player.getY()<=130)
               camera.position.set(player.getX() + player.getWidth() /2, player.getHeight() /2 + 93, 0);
            else
               camera.position.set(player.getX() + player.getWidth()/2, player.getY()+ player.getHeight()/+60,0);
         if( player.getX()>=640 && player.getY()<120 )
            camera.position.set((float)640, player.getHeight()/2+93 ,0);
         else if( player.getX()>640 && player.getY()>=120 )
            camera.position.set((float)640,player.getY()+player.getHeight()/2+60,0);
         camera.update();

                        //rendering "wallpaper", background, sprites in background, and then foreground
        renderer.render(sfondo);
         renderer.render (background);  
         renderer.getSpriteBatch().begin();

         //GOOMBA NUMBER 1
        if (! goomba.getDeadState() || !disappear){
            goomba.draw (renderer.getSpriteBatch());
         }//goomba still alive
        if (goomba.getDeadState()){
            if (goomba.getTime().getTime()<0){
               goomba.setPosition(-2 * goomba.getCollisionLayer().getTileWidth(), -2 *player.getCollisionLayer().getTileHeight());
               disappear = true;
            }
         }// gomba dead

         //GOOMBA NUMERO 2
        if (! goomba2.getDeadState() || !disappear2){
            goomba2.draw (renderer.getSpriteBatch());
         }//goomba still alive
        if (goomba2.getDeadState()){
            if (goomba2.getTime().getTime()<0){
               goomba2.setPosition(-2 * goomba2.getCollisionLayer().getTileWidth(), -2 *goomba.getCollisionLayer().getTileHeight());
               disappear2 = true;
            }
         }//goomba dead
       
         //KOOPA
        if(! koopa.getDeadState() ){
            koopa.draw(renderer.getSpriteBatch());
         }
         
         //FUNGO 1UP
        if (! fungo.getDeadState()){
            fungo.draw(renderer.getSpriteBatch());
         }
         
         //FUNGO MUSH
        if( !mush.getDeadState()){
            mush.draw(renderer.getSpriteBatch());
         }

         //FIREFLOWER 1 & 2
        if (! fireFlower.getDeadState()){
            fireFlower.draw(renderer.getSpriteBatch());
         }//flower1
        if (! fireFlower2.getDeadState ()){
            fireFlower2.draw(renderer.getSpriteBatch());
         }//flower2

         if (player.getDeadState()){
            bgm.stop();
            Time MDTime = player.getMarioDeathTime();
            if (MDTime.getTime()<0){
               bgm = Gdx.audio.newMusic(Gdx.files.internal("com/me/sounds/overworld.mp3"));
               bgm.setLooping(true);
               bgm.play();
               player.setDeadState(false);
               player.decreaseLife();
               try {
                  player.setMarioDeathTime();
               } catch (InterruptedException e) {}
               //setposition
              player.setPosition(10 * player.getCollisionLayer().getTileWidth(), 3 * player.getCollisionLayer().getTileHeight());

            }
         }
         if (player.getInvulnerability()){
            if (!player.getInvulnerableTime().isAlive()){
               player.createInvulnerableTime();
            }

            if (player.getInvulnerableTime().getTime()<0){
               player.setInvulnerability(false);
               if(!player.getFireMario() && !player.getBigMario()){
               player.setNormalAnimation();
               }
               player.setInvulnerableTime();
            }
         }

         

         for( int i =0;i<3;i++ )
            if (fireballs.get(i)!=null && player.getSpara() && !fireballs.get(i).getDeadState() ){
               fireballs.get(i).draw(renderer.getSpriteBatch());
            }  

         if (!player.getDeadState()){
            player.draw (renderer.getSpriteBatch());
         }

         renderer.getSpriteBatch().end();      
         renderer.render(foreground);
   
         renderer.getSpriteBatch().begin();

                        //the upper region where life number, time and coin number are shown
        renderer.getSpriteBatch().draw(coin, camera.position.x+100, camera.position.y+77, 0, 0, 12, 12, 1,1, 0);
         renderer.getSpriteBatch().draw(life, camera.position.x-140, camera.position.y+77, 0, 0, 12, 12, 1,1, 0);
         renderer.getSpriteBatch().draw(time, camera.position.x, camera.position.y+77, 0, 0, 12, 12, 1,1, 0);
         font.draw(renderer.getSpriteBatch(), ""+player.getCoin(), camera.position.x+120, camera.position.y+ 90);
         font.draw(renderer.getSpriteBatch(), ""+player.getLife(), camera.position.x-130, camera.position.y+ 90);
         if( timer.getTime()<0 ){
            player.timedOut();
            timer.setTime(200);
         }
         font.draw(renderer.getSpriteBatch(), ""+timer.getTime(), camera.position.x+20, camera.position.y+ 90);
         //System.out.println("camera x: "+camera.position.x+" camera y: "+camera.position.y );
        renderer.getSpriteBatch().end();
         
      }//if(!isPaused)
  }//render


In case you need the whole project, we can share it with you, but we really need your help, because this problem is driving us mad, and it may affects the result of our exam.
Thanks in advance.  Cheesy
Offline trollwarrior1
« Reply #1 - Posted 2013-11-20 12:41:03 »

I tried playing this game and I can tell you one thing. You need to improve collision. For example:
*If I hold W key to keep jump and bump into the wall, I need to press D key again, because I don't move for some reason into the direction  I want.
*Also camera jumps around really a lot. It is really annoying.

I couldn't reproduce the bug, but if you die, it is probably because your camera is doing something wrong. You might be getting out of map bounds or something and your camera renders what it sees (nothing) and your character dies. Just some ideas..

EDIT:

Offline Kyactus

Junior Newbie





« Reply #2 - Posted 2013-11-20 21:39:14 »

I tried playing this game and I can tell you one thing. You need to improve collision. For example:
*If I hold W key to keep jump and bump into the wall, I need to press D key again, because I don't move for some reason into the direction  I want.
*Also camera jumps around really a lot. It is really annoying.

I couldn't reproduce the bug, but if you die, it is probably because your camera is doing something wrong. You might be getting out of map bounds or something and your camera renders what it sees (nothing) and your character dies. Just some ideas..

Thanks, I appreciate your feedbacks ^_^
As for the collisions, we kinda had some problems with them, yeah Tongue We tried to fix a bunch of things, and the results as now is much better than how it was before (days/weeks ago). We are currently aware about the fact the movements seem kinda... broken. We'll try and fix them later on Smiley And in the image  you posted you're standing in that spot just fine because, since tiles are squares, the game actually detects you're on a tile with a "blocked" property (which is actually true). In the old NES/SNES games, this happened kinda often too. I remember trying to get to the utter most corner of a ledge in order to jump as far away as possible ahah. (no, i'm not justifying ourselves, just saying XD)

The camera issue is another "bad point" of the game right now. It seems like all the solutions we find on the internet doesn't work properly. But we WILL do our best to fix it Cheesy
 
As for the actual problem of the topic, the fact that you couldn't reproduce the bug kinda worries me, since on my computer the problem is kinda persistent, while on my teammate's one it doesn't reproduce at all (just sporadically). We've tried to not put any "new" inside the render method, tried to see if it was a problem of the resize method but nothing helped.
Can it be a memory problem? Something like the game running out of memory very fast? Or something related to the life cicle?

As long as they are knowable problems, we can try and fix them perfectly fine. But when we stuck into problems that we have no idea how and WHY they occur, we are kinda "blind" :/
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 742
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2013-11-21 18:48:15 »

Flaky collision code might be the cause of your rendering issues. If you use floating point numbers and divide by (near) zero, your coordiates will explode, or simply reach NaN/infinity. If you then position your camera to these 'corrupt' coordinates, you'll most likely see nothing, potentionally not even the sprite your camera is pointing at, because the modelview matrix can't handle these kinds of numbers.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Kyactus

Junior Newbie





« Reply #4 - Posted 2013-11-23 15:49:17 »

Flaky collision code might be the cause of your rendering issues. If you use floating point numbers and divide by (near) zero, your coordiates will explode, or simply reach NaN/infinity. If you then position your camera to these 'corrupt' coordinates, you'll most likely see nothing, potentionally not even the sprite your camera is pointing at, because the modelview matrix can't handle these kinds of numbers.

I don't really get what you mean by that, sorry Sad
Our collision code is basically this one:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
private void checkCollectable(float x, float y) {
      Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
      if (cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(collectableKey)){
         ++coin;
         Suoni.riproduciCoin();
         collisionLayer.setCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()), null);
      }
   }//checkCollectable

   private boolean isCellBlocked(float x, float y) {
      Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
      return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(blockedKey);
   }//isCellBlocked

   private boolean isCellTopBlocked(float x, float y) {
      Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
      return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(topBlockedKey);
   }//isCellTopBlocked

   public boolean collidesRight() {
      for(float step = 0; step < getHeight(); step += 8){
         if(isCellBlocked(getX() + getWidth(), getY() + step )){
            return true;
         }
         checkCollectable(getX() + getWidth(), getY() + step);
      }
     
      return false;
   }//collidesRight

   public boolean collidesLeft() {
      for(float step = 0; step < getHeight(); step += 8){
         if(isCellBlocked(getX() , getY() + step  )){
            return true;
         }
         checkCollectable(getX() , getY() + step );
      }
     
      return false;
   }//collidesLeft

   public boolean collidesTop() {
      for(float step = 0; step < getWidth(); step += 8){
         if(isCellBlocked(getX() + step, getY() + getHeight())){
            hit(getX() + step, getY() + getHeight());
            return true;
         }else if(isCellTopBlocked(getX() + step, getY() + getHeight())){
            hit(getX() + step, getY() + getHeight());
            return true;
         }
         checkCollectable(getX() + step, getY() + getHeight());
      }
      return false;
   }//collidesTop

   public boolean collidesBottom() {
      for(float step = 0; step < getWidth(); step += 8){
         if(isCellBlocked(getX()+step, getY() )){
            return true;
         }
         checkCollectable(getX()+step, getY() );
      }      
      return false;
   }//collidesBottom


The only methods where we actually do a division is in the "isCellBlocked" and such methods. Can they be the culprits of our problems?
I may try and change the collision "engine" at all and see if the problem still occurs or not :/

Also, @trollwarrior1, were you using a Mac or where you playing on Windows? Because in my teammmate Mac, the problem basically never occurs!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

ctomni231 (34 views)
2014-07-18 06:55:21

Zero Volt (30 views)
2014-07-17 23:47:54

danieldean (25 views)
2014-07-17 23:41:23

MustardPeter (27 views)
2014-07-16 23:30:00

Cero (42 views)
2014-07-16 00:42:17

Riven (44 views)
2014-07-14 18:02:53

OpenGLShaders (33 views)
2014-07-14 16:23:47

Riven (34 views)
2014-07-14 11:51:35

quew8 (30 views)
2014-07-13 13:57:52

SHC (66 views)
2014-07-12 17:50:04
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!