Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
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  
  passive rendering issue in a 2D RPG turn-based during battles type of game  (Read 1639 times)
0 Members and 1 Guest are viewing this topic.
Offline Tennie

Senior Newbie





« Posted 2007-03-19 20:14:42 »

Hello everyone !

I'm currently making a 2D RPG in the final fantasy/breath of fire style. It is turn-based during battles only, and the battle screen and the world map/village maps are different screens. I'm writing it using the swing and java2D APIs, and am having 2 problems, both related to passive rendering.
I've implemented it so that the player can walk around the world until a random encounter occurs. Then, the world map (represented in the code at the end of the post as gamePanel) is essentially put on "hold" and the battle screen (represent in the code at the end of the post as battPanel) is displayed. Once the battle is over, the battle screen is removed from the frame, and the world map is "unpaused."

The first problem is that the game sometimes freezes while the user is walking aroudn the world map, and sometimes doesn't know that it is time for a battle. I think that this problem is related to threading. See the code below.

The second problem is that the battle panel does not always render. I have a feeling that this is not an image-loading time related problem because i just ran the program with the following paintComponent method and it still did not work every time:
public void paintComponent(Graphics g) {
     super.paintComponent(g);
//I've done the following two lines with an explicitly casted graphics2D object and with the standard Graphics object that is passed in
     g.setFont(font);    //font was previously initialized like this: private Font font = new Font("SansSerif", Font.PLAIN, 15);
     g.drawString("Hello!", 20, 20);
}

I'm much more concerned with the second problem than the first, because if I have a game that only displays battles whenever it wants to... well... that's hardly a game at all. Here is the code for my main game loop. There are three different versions. One is the original version, the next was updated to follow a friend's advice (and it works quite well, actually), and the same for the third version. The second and third versions use threading, which I am a total stranger to.

Just so you know, i can get the world map displaying perfectly... just not the battle screen. Does that mean that the error is in the battlepanel class? Normally I would say yes, except for the paintComponent() test run that I did (see above). I also ran one with an almost empty constructor, and it still only rendered sometimes.

P.S. In battlepanel i hooked keyboard input into a repaint method, so if the user presses enter, a repaint method is dispatched. I only did this for debugging, and it doesn't work. I tried it with invalidate(), still didn't work.

Version 1:

public class CGame {
   public static void main(String[] args) {
      boolean battleRunning = false;
      ImageFrame frame = new ImageFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      frame.requestFocusOnSplashPanel();       //There is a splash panel that is initialized and displayed in the frame's constructor
      while(frame.timeToStartGameYet() == false) { //I.E. hasn't started yet, changed to true by pressing enter
         //do nothing
      }
      //When it is time to start the game, start it.
      frame.hideSplashPanel();
      frame.removeSplashPanel();
                                         
                                          //Put the game panel on the frame while there is no battle
                                          ImagePanel gamePanel = new ImagePanel();
                                          frame.add(gamePanel);
                                          frame.requestFocusOnPanel(gamePanel);
                                          frame.show();
                                          BattlePanel battPanel = null;
                                          while(battleRunning == false) {   //I think that the program is choking up because the while loop is too tight
                                                    if(gamePanel.getBattleMode() == true) {
                                                          System.out.println("battle mode == true");
                                                          frame.hidePanel(gamePanel);
                                                          battPanel = new BattlePanel(gamePanel.getPlayer());
                                                          frame.add(battPanel);
                                                          frame.showPanel(battPanel);
                                                          frame.requestFocusOnPanel(battPanel);
                                                    }
                                                    while(gamePanel.getBattleMode() == true) {
                                                            //do Nothing
                                                    }
                                                   //then, when it is over,
                                                  battleRunning = false;            //Should be false anyway, but just in case Smiley
                                                  if(battPanel != null) {
                                                          frame.hidePanel(battPanel);
                                                          frame.removePanel(battPanel);
                                                          frame.showPanel(gamePanel);
                                                          frame.requestFocusOnPanel(gamePanel);
                                                 }
                                      }
                       }
}


Version 2:

public class CGame {
   public static void main(String[] args) {
      boolean battleRunning = false;
      ImageFrame frame = new ImageFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      frame.requestFocusOnSplashPanel();              //There is a splash panel that is initialized and displayed in the frame
      while(frame.timeToStartGameYet() == false) { //I.E. hasn't started yet, changed to true by pressing enter
         //do nothing
      }
      //When it is time to start the game, start it.
      frame.hideSplashPanel();
      frame.removeSplashPanel();

       ImagePanel gamePanel = new ImagePanel();
       frame.add(gamePanel);
       frame.requestFocusOnPanel(gamePanel);
       frame.show();
       BattlePanel battPanel = null;
       while(battleRunning == false) {
          if(gamePanel.getBattleMode() == true) {
          System.out.println("battle mode == true");
          frame.hidePanel(gamePanel);
          battPanel = new BattlePanel(gamePanel.getPlayer());
          frame.add(battPanel);
          frame.showPanel(battPanel);
          frame.requestFocusOnPanel(battPanel);
       }
       while(gamePanel.getBattleMode() == true) {
          //do Nothing
         Thread.yield();
       }
       //then, when it is over,
       battleRunning = false;
        if(battPanel != null) {
         frame.hidePanel(battPanel);
         frame.removePanel(battPanel);
         frame.showPanel(gamePanel);
         frame.requestFocusOnPanel(gamePanel);
       }
       try  {
          Thread.sleep(10);
       }
       catch (InterruptedException e) {
          System.out.println("E messed up in main!");
         }
   } 
}

Version 3:

public class CGame {
   public static void main(String[] args) {
      boolean battleRunning = false;
      ImageFrame frame = new ImageFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      frame.requestFocusOnSplashPanel();
      while(frame.timeToStartGameYet() == false) { //I.E. hasn't started yet
         //do nothing
      }
      //When it is time to start the game, start it.
      frame.hideSplashPanel();
      frame.removeSplashPanel();
      
      //Put the game panel on the frame while there is no battle
      ImagePanel gamePanel = new ImagePanel();
      frame.add(gamePanel);
      frame.requestFocusOnPanel(gamePanel);
      frame.show();
      BattlePanel battPanel = null;
      synchronized(gamePanel) {
         while(gamePanel.getBattleMode() != true) {
            try {
               System.out.println("in while gamepanel's battleMode == false, current battle mode is: " +                      gamePanel.getBattleMode());
               if(gamePanel.getBattleMode()) {
                  System.out.println("About to wait all threads!");
                  System.out.println("battle mode == true");
                  frame.hidePanel(gamePanel);
                  battPanel = new BattlePanel(gamePanel.getPlayer());
                  frame.add(battPanel);
                  frame.showPanel(battPanel);
                  frame.requestFocusOnPanel(battPanel);
                  gamePanel.wait();
               }
            }
            catch (InterruptedException e) {
               System.out.println("Error in waiting frame thread.");
            }
               //do Nothing
         }
      }
      //then, when it is over,
      synchronized(gamePanel) {
         gamePanel.notifyAll();
         gamePanel.setBattleMode(false);
      }
      //battleRunning = false;
      if(battPanel != null) {
         frame.hidePanel(battPanel);
         frame.removePanel(battPanel);
         frame.showPanel(gamePanel);
         frame.requestFocusOnPanel(gamePanel);
         battPanel = null;
      }
   }
          }
}





Some people become relaxed and/or feel at peace with themselves/the universe because they smoke, pray, or meditate. Me, I code.
Offline fletchergames

Senior Member





« Reply #1 - Posted 2007-03-19 23:25:52 »

Whenever you do something in Swing, you have do it in the AWT Event Thread.  You're supposed to do this even when initializing Swing components, but it's essential when you're changing them on the fly (like you're doing).  Here's an example of some of my own code that uses it:

1  
2  
3  
4  
5  
6  
7  
8  
//if this is in the AWT event thread, just paint the components
if(EventQueue.isDispatchThread())
   layeredPane.paintComponents(g2);
else { //else this isn't in the AWT event thread, so invokeAndWait
  EventQueue.invokeAndWait(new Runnable() {
      public void run() {layeredPane.paintComponents(g2);}
   });
} //end else this isn't in the AWT event thread


Any methods that are called as the result of a button press, key press, mouse press, etc. will already be in the AWT event thread because the AWT event thread is what generates events for those occurrences.

Also, you shouldn't add and remove the panels all the time.  Instead, use a CardLayout, and switch between the different panels.  Some old versions of Java have a bug in CardLayout, so make sure you use the newest version.
Offline Tennie

Senior Newbie





« Reply #2 - Posted 2007-03-20 03:42:52 »

Thank you very much. I understand the majority of your advice, but not this:
Whenever you do something in Swing, you have do it in the AWT Event Thread.  You're supposed to do this even when initializing Swing components, but it's essential when you're changing them on the fly (like you're doing). 

does that mean that I should put a while loop outside of the if in your code so that the things that I want to display will eventually display?

what's burning me up is that the battle panel will sometimes render, and will sometimes be blank. I have even done test runs where I've commented out all of the switching back and forth in between panels, and haven't loaded the game map. Frankly, this bug is really confusing me.


Thanks in advance Smiley

Some people become relaxed and/or feel at peace with themselves/the universe because they smoke, pray, or meditate. Me, I code.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline fletchergames

Senior Member





« Reply #3 - Posted 2007-03-20 16:45:15 »

Thank you very much. I understand the majority of your advice, but not this:
does that mean that I should put a while loop outside of the if in your code so that the things that I want to display will eventually display?
The code I posted was actually for active rendering, not passive rendering.  If you want to learn more about active rendering, buy Killer Game Programming in Java and Developing Games in Java.  Or look around on this forum.  With passive rendering, you don't have to call paintComponents.

My point is that whenever you do something in Swing, you have to do it in the AWT Event Thread.

what's burning me up is that the battle panel will sometimes render, and will sometimes be blank. I have even done test runs where I've commented out all of the switching back and forth in between panels, and haven't loaded the game map. Frankly, this bug is really confusing me.


Thanks in advance Smiley
You might want to put a try-catch block around the contents of your main method and use System.out.print to output the Exception's message.  There's a pretty good chance that the blank screen is caused by your program throwing an Exception.

Also, use the newest version of Java if you aren't already.

It's hard to debug your code because it's strange.  Try using CardLayout like I mentioned before.

By the way, Java 6 has built-in splash screen support, though I prefer the splash screen included in the .exe by Exe4J (a cheap program that creates .exe files for Java programs).
Offline Kova

Senior Member





« Reply #4 - Posted 2007-03-20 17:10:00 »

As fletcher said, CardLayout is best choice here... CardLayout only shows one component at the time, and it's simple to use.
I see that you're adding / removing panels during play. I would advise adding battle panel at start of the game and hiding it. When time comes then show it, without removing or adding components. Don't know if it is better, but it is more logical to me. Again this can be easily done with CardLayout.

you said your repaint on enter pressed doesn't work... do game even registeres that enter has been pressed? Do println() to check it out, maybe with all that adding / removing components your focus changes also and disables all keyboard input.

Although code is kind of strange, version 2 is I think the best option. Why are things synchronized in version 3 btw? What other threads are you running?
Offline Tennie

Senior Newbie





« Reply #5 - Posted 2007-03-20 22:08:35 »

The code is probably strange because I've never worked with Swing before, and I wanted to get a working demo up and running before going back and cleaning up the code. For instance, I will go back and take the splash panel out of the frame class.

The reason version 3 contains blocks of synchronized code is that I was told to put those blocks in by Jeff. Those blocks, combined with the system.out.println directly follows the try:    System.out.println("in while gamepanel's battleMode == false, current battle mode is: " + gamePanel.getBattleMode());        stopped the program from lagging/choking itself when on the world map. I.E. they solved the first problem but did not solve the rendering problem. Both version 2 and version 3 solved the choking problem, at least on the whole, but not the rendering issue, which is really bugging me. I posted all three versions in case someone could tell me if I had accidently done something wrong with them, and they were preventing the rendering issue from being solved. 

With regards to:
you said your repaint on enter pressed doesn't work... do game even registeres that enter has been pressed? Do println() to check it out, maybe with all that adding / removing components your focus changes also and disables all keyboard input.

There is a println() in my input handling code. I put it in there because I thought the problem was focus too, but the println works 100% of the time, even when the rendering doesn't.

Kova, you asked about what other threads I'm running, and I must admit that I don't know. Threading is probably the only elementary topic that I have very, extremely little experience with, but I'm reading a book right now about them. Well, actually three: Just Java 2, Core Java Volume I, and Core Java Volume II.

With regard to Killer Game Programming in Java and Developing Games in Java, I've read most of both of them, and will go back to reread the sections on active rendering asap.

Thanks again to both of you, I'll be sure to implement the CardLayout idea.


Update: If you notice I have a function called showPanel(JPanel panelToShow)... I invoke it when I'm showing battPanel later in the code. The implementation for that method is: panelToShow.setVisible(true);    I have a feeling that this is the problem.

Update: Ran another test run, that was the problem. For the demo I'm working on I'll just hide the other panel and then do frame.show() with the battlePanel. This causes it to render 100% every time. Thanks for your patience guys. After this friday I'm going to completely overhaul the code to do active rendering and to use CardLayout. I'm not sure why setVisible didn't work, especially since sun deprecated show in favor of setVisible, but oh well I figured out how to make my program run and that's all that matters to me because the demo deadline is friday... After that I'll do a search into it. Thanks a ton Smiley

P.S. I don't know how setVisible works, but I do know how show works. Perhaps setvisible causes ALL of the panels to show? hence the rendering problem, they would be "fighting" for dominance??



Some people become relaxed and/or feel at peace with themselves/the universe because they smoke, pray, or meditate. Me, I code.
Offline Kova

Senior Member





« Reply #6 - Posted 2007-03-21 01:05:02 »

about threading... synchronizing is used only when you have multiple threads, that is multiple "sub programs" running at same time. One thread is your program, other for example is swing's EDT, where swing renders it's graphics. Jeff probably told you to synchronize on panels so EDT can't mess up your panel while you work with it  (and vice versa) at same time.

Chocking was because your app was in a loop with no pause, that is CPU is very fast and could done thousands of loops in a second. Since there was no pause, it worked only on your game (your thread) so other processes seemed unresponsive. Let's say your goal is 10 updates (passes through main loop) in a second, then you need to pause after each one so you get 10 ups at the end. You do that with Thread.sleep(x) which pauses the thread for x ms (and running other processes in meantime)... You should really read some books about programming games, and do programming as you read step by step as it is in the book.

EDIT: synchronizing "solved" your choking problem but only in your app, and only as a side effect,  this is not what synchronizing is about

EDIT2:  you may read the books, but you didn't understand them, Killer Game Programmin in Java covers all the basics, like your choking problem and such...
Offline Tennie

Senior Newbie





« Reply #7 - Posted 2007-03-21 21:22:33 »

Thanks  a ton for clearing that up Smiley, I will do exactly what you said.


Some people become relaxed and/or feel at peace with themselves/the universe because they smoke, pray, or meditate. Me, I code.
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.

pw (22 views)
2014-07-24 01:59:36

Riven (21 views)
2014-07-23 21:16:32

Riven (17 views)
2014-07-23 21:07:15

Riven (20 views)
2014-07-23 20:56:16

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

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

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

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

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

Riven (53 views)
2014-07-14 18:02:53
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!