11 Replies Latest reply: Jan 21, 2010 1:22 PM by 843853 RSS

    Memory, processing or another problem with my game engine

    843853
      Hey everyone,

      I have managed to get a server for my game engine and finally I have managed to put the applet in my host.
      But there is a problem that is not occuring to me when I'm running it directly from Eclipse... Character seems to be freezing when passing from tile to tile.. I don't have an idia why this happens? Any sugesstions? Maybe this is processing issue(browsers limit applets in processing, maybe it's limited memory issue?). Is there any work around to this problem?
      Applet can be found here: [http://game2dei.com/demo/hoonline.html|http://game2dei.com/demo/hoonline.html]
      Accounts to enter: test01/test01, test02/test02, test03/test03, test04/test04, test05/test05.

      Thnaks for any help!

      Edited by: patriot87 on Dec 13, 2009 2:17 PM
        • 1. Re: Memory, processing or another problem with my game engine
          gimbal2
          Try running the applet on your local system, but not from eclipse. Create a simple HTML file and load the applet in there, then open the html file in a browser. Do you get the same issue then?

          The host shouldn't matter, as the applet is downloaded and run on the local system. So the problem must lie in the applet not working correctly in a sandboxed browser environment. I would suggest putting a little study into what limitations applets have and then comparing that to what you are doing in your game, to see if you are doing anything illegal (or something that needs the applet to be signed for example).

          edit: and a side note, I would also put some study into Java Webstart as an alternative to running it as an applet.
          • 2. Re: Memory, processing or another problem with my game engine
            843853
            Thanks a lot for the advices!

            I'll need follow them step by step ;)

            So I have tried to run applet using from html page in my local system and I don't got this issue... The thing is that only happens sometimes and I can't understand when.. Sometimes it happens right after I have restarted my PC, sometimes it all nice and smooth... I have a distant feeling that maybe some server communication problem(I think I got somewhere sending some message not in a Thread apart), when beacause of latency, it block while waiting for ACK(dunno if this can be)...

            I'm going to study little bit about Sandboxes.. I have never heart about them.. But seems like very important thing when programming applets...

            As about Java Webstart... I have to learn more about this, I have already heart about this technology, but never used..
            • 3. Re: Memory, processing or another problem with my game engine
              843853
              I'm my JVM I have turned on the logging... Strange thing, everytime I'm making the character move, before sending XML I get this message from JVM logger:
              network: Cache entry not found [url: http://game2dei.com/demo/META-INF/services/javax.xml.stream.XMLOutputFactory, version: null]
              network: Connecting http://game2dei.com/demo/META-INF/services/javax.xml.stream.XMLOutputFactory with proxy=DIRECT
              network: Connecting http://game2dei.com:80/ with proxy=DIRECT

              What can it mean?
              • 4. Re: Memory, processing or another problem with my game engine
                794069
                That's a lot of xml for a very simple message:
                18/12/2009 10:19:46     [0x0-0x238238].com.apple.Safari[92324]     <?xml version="1.0"?><update_destination_request><destination><line>6</line><column>17</column></destination></update_destination_request>
                18/12/2009 10:19:47     [0x0-0x238238].com.apple.Safari[92324]     <?xml version="1.0"?><update_position_request><position><line>6</line><column>17</column></position></update_position_request>
                Do you really need to use xml for this?
                • 5. Re: Memory, processing or another problem with my game engine
                  843853
                  All that XML is for debug purposes. I thought that for now it's ok, but after I'm going to reduce it to one letter, for example instead of having:
                  <?xml version="1.0"?><update_destination_request><destination><line>6</line><column>17</column></destination></update_destination_request>
                  I would have:
                  <?xml version="1.0"?><udr><d><l>6</l><c>17</c></d></udr>
                  • 6. Re: Memory, processing or another problem with my game engine
                    gimbal2
                    show the code where you perform the move, especially the part where you send the XML.
                    • 7. Re: Memory, processing or another problem with my game engine
                      843853
                      Ok here goes the part where I draw changes to the screen:
                      public void paint(Graphics g) 
                          {     
                              Graphics2D g2d = (Graphics2D)g;
                              
                              g2d.clearRect(0, 0, this.getWidth(), this.getHeight());
                              
                              this.updateFrameRate();
                              
                              /* *** DRAW MAP ON SCREEN *** */
                              g2d.drawImage(Map.getMapImage(), -Map.getMAP_OFFSET_X(), -Map.getMAP_OFFSET_Y(), this); 
                              
                              /* *** DRAW GRID(Debug purposes) *** */
                              this.displayGrid(g2d);
                              
                              /* *** DRAW RENDERED ELEMENTS *** */
                              g2d.setFont(world_window_text_font);
                              
                              HashMap <Integer, TreeMap> rendered_objects = this.render2DMapElements(g2d);
                              
                              /* *** Draw rendered objects *** */
                              TreeMap <Long, BufferedImage> rendered_object_list = rendered_objects.get(2);
                              
                              Collection <Long> rendered_object_collection = rendered_object_list.keySet();
                              Iterator <Long> rendered_object_iterator = rendered_object_collection.iterator();
                      
                              while(rendered_object_iterator.hasNext())
                              {
                                   Long rendered_object_key = rendered_object_iterator.next();
                                   BufferedImage rendered_object_value = rendered_object_list.get(rendered_object_key);
                                   g2d.drawImage(rendered_object_value, Integer.valueOf(String.valueOf(rendered_object_key/100000)), Integer.valueOf(String.valueOf(rendered_object_key%100000)) - 40, this);
                              }
                              
                              // *** Draw rendered strings ***
                              TreeMap <Long, String> rendered_string_list = rendered_objects.get(1);
                              
                              Collection <Long> rendered_string_collection = rendered_string_list.keySet();
                              Iterator <Long> rendered_string_iterator = rendered_string_collection.iterator();
                      
                              while(rendered_string_iterator.hasNext())
                              {
                                   Long rendered_string_key = rendered_string_iterator.next();
                                   String rendered_string_value = rendered_string_list.get(rendered_string_key);
                                   g2d.drawString(rendered_string_value, rendered_string_key/100000, rendered_string_key%100000 - 40);
                              }
                               
                              /* *** INCREASE FPS COUNTER *** */
                              this.frames_per_second ++;
                              
                              Toolkit.getDefaultToolkit().sync();
                              g.dispose();
                          }
                          
                          public void updateMapCharacters(long timestamp)
                          {
                               Collection <MapCharacter> collection = Data.visible_character_list.values();
                               Iterator <MapCharacter> iterator = collection.iterator();
                               
                               while(iterator.hasNext())
                               {
                                    MapCharacter tmp_character = iterator.next();
                                    
                                    if (!tmp_character.getName().equals(Character.getCharacterName()))
                                   {
                                         if ((((tmp_character.getDestinationUpdateTimestamp() + 100) < timestamp) ||
                                                   tmp_character.getDestinationUpdateTimestamp() == -1) &&
                                                   tmp_character.getAction() == Constants.ACTION_WALK)
                                         {
                                              int x = tmp_character.getCharacterX();
                                              int y = tmp_character.getCharacterY();
                                              tmp_character.setCharacterX(tmp_character.calculateNextX(tmp_character.getCharacterX(), tmp_character.getDirection()));
                                              tmp_character.setCharacterY(tmp_character.calculateNextY(tmp_character.getCharacterY(), tmp_character.getDirection()));
                                              tmp_character.setDestinationUpdateTimestamp(System.currentTimeMillis());
                                              if (x != tmp_character.getCharacterX() || y != tmp_character.getCharacterY())
                                                   tmp_character.updateStep();
                                              Data.visible_character_list.put(tmp_character.getName(), tmp_character);
                                         }
                                         else if ((((tmp_character.getDestinationUpdateTimestamp() + 200) < timestamp) ||
                                                   tmp_character.getDestinationUpdateTimestamp() == -1) &&
                                                   tmp_character.getAction() == Constants.ACTION_PAUSE)
                                         {
                                              tmp_character.setDestinationUpdateTimestamp(System.currentTimeMillis());
                                              tmp_character.updateStep();
                                              Data.visible_character_list.put(tmp_character.getName(), tmp_character);
                                         }
                                   }
                               }
                               
                               repaint();
                          }
                          
                          private HashMap <Integer, TreeMap> render2DMapElements (Graphics g2d)
                          {
                               HashMap <Long, BufferedImage> object_list = new HashMap <Long, BufferedImage> ();
                               HashMap <Long, String> string_list = new HashMap <Long, String> ();
                               
                               /*
                                *           Render "foreign" characters and their strings
                                */
                               Collection <MapCharacter> collection = Data.visible_character_list.values();
                              Iterator <MapCharacter> iterator = collection.iterator();
                              
                              while (iterator.hasNext())
                              {
                                   MapCharacter map_character = iterator.next();
                                   if (!map_character.getName().equals(Character.getCharacterName()))
                                   {
                                        Rectangle2D bounds = g2d.getFontMetrics().getStringBounds(map_character.getName(), g2d);
                                        
                                        Long string_key = (long)((map_character.getCharacterX() - Map.getMAP_OFFSET_X() + 20 - (int)(bounds.getWidth()/2)) * 100000) + (map_character.getCharacterY() - Map.getMAP_OFFSET_Y());
                                        String string_value = map_character.getName();
                                        
                                        string_list.put(string_key, string_value);
                      
                                        Long image_key = (long)((map_character.getCharacterX()- Map.getMAP_OFFSET_X()) * 100000) + map_character.getCharacterY() - Map.getMAP_OFFSET_Y();
                                        BufferedImage image_value = Character.getCharacterActionImage(map_character.getAction(), map_character.getDirection() , map_character.getStep());
                                        
                                        object_list.put(image_key, image_value);
                                   }
                              }
                              
                              
                              /*
                               *           Render main character
                               */
                              Long image_key = (long)((Character.getCharacterX() - Map.getMAP_OFFSET_X()) * 100000) + Character.getCharacterY() - Map.getMAP_OFFSET_Y();
                                BufferedImage image_value = Character.getCharacterActionImage(Character.getCurrentCharacterAction(), Character.getPreviousDirection(), Character.getCharacterStepCount());
                                
                                object_list.put(image_key, image_value);
                               
                               
                               TreeMap <Long, BufferedImage> ordered_object_list = new TreeMap<Long, BufferedImage>(object_list);  
                               TreeMap <Long, String> string_object_list = new TreeMap <Long, String>(string_list);
                               
                               HashMap <Integer, TreeMap> rendered_objects = new HashMap <Integer, TreeMap> ();
                               
                               rendered_objects.put(1, string_object_list);
                               rendered_objects.put(2, ordered_object_list);
                               
                               return rendered_objects;
                          }
                      • 8. Re: Memory, processing or another problem with my game engine
                        843853
                        The part where I send XML:
                        Here I think should be only one thread waiting for message, but problem should not lie here anyways?
                        public static void send(String msg)
                             {
                                  message = msg;
                                  
                                  Thread tmp_sender_thread = new Thread(new Runnable()
                                 {
                                      public void run()
                                      {
                                           try {
                                                System.out.println(message);
                                                 ous.writeObject(message);
                                                 ous.flush();
                                            } catch (IOException e) {
                                                 e.printStackTrace();
                                            }
                                      }
                                 });
                                  
                                  tmp_sender_thread.start();
                             }
                        Here I generate XML:
                        public static String XMLUpdateCharacterDestinationRequest (int destination_line, int destination_column)
                             {
                                  StringWriter request = new StringWriter();
                                  
                                  try
                                  {
                                       XMLOutputFactory factory = XMLOutputFactory.newInstance();
                                      XMLStreamWriter writer = factory.createXMLStreamWriter(request);
                             
                                      writer.writeStartDocument("1.0");
                                       
                                      writer.writeStartElement("update_destination_request");
                             
                                      writer.writeStartElement("destination");
                             
                                      writer.writeStartElement("line");
                                      writer.writeCharacters(String.valueOf(destination_line));
                                      writer.writeEndElement();
                                      
                                      writer.writeStartElement("column");
                                      writer.writeCharacters(String.valueOf(destination_column));
                                      writer.writeEndElement();
                             
                                      writer.writeEndDocument();
                                      
                                      writer.writeEndDocument();
                             
                                      writer.flush();
                                      writer.close();
                                  }
                                  catch(Exception e)
                                  {
                                       request.flush();
                                       return null;
                                  }
                                  
                                  return request.toString();
                             }
                        Then I have a function in my ServerCommunicationController class
                        public static void update_CharacterDestination (int destination_line, int destination_column)
                             {
                                  String request = XMLWriter.XMLUpdateCharacterDestinationRequest(destination_line, destination_column);
                                  send(request);
                             }
                        And then I call this function from some other functions in World class..
                        • 9. Re: Memory, processing or another problem with my game engine
                          843853
                          Hey, after having some more searches I have made some conclusion.

                          The problem is that applet only should connect via TCP to the same host where if was downloaded from. So the machine with the TCP server, must also be a Web Server where the page with an applet will be available(I guess that TCP server could be in some kind of sub-network with the machine where web server is running).

                          After reading a lot of information I can affirm that there are ways to overpass this issue. One of them is using WebServices instead of TCP, but the question is: isn't it some kind of spaghetti? This approach can make simple solution with TCP server to complex one with storing states of messages. Another solution is using Message Queues, but this can not be a solution in my case, bacause what I want is real time RPG.

                          I haven't used any of these solutions. I evalueted the complexity and after knowing what is happening, I prefered to talk with the guy with whom I'm sharing the server and he allowed me to have one page, where the demo is running now and has one problem. But I think I will post it in another topic.

                          Thanks everyone who helped.
                          • 10. Re: Memory, processing or another problem with my game engine
                            gimbal2
                            so it WAS a problem with a sandboxed environment. That confuses me as you earlier stated that it only happens sometimes, while this issue should have occurred always.

                            Well, I'm glad you resolved it.
                            • 11. Re: Memory, processing or another problem with my game engine
                              843853
                              Well this issue wasn't happening when I was using very fast network(at night in the univercity, 2Gbits vtf :P, and I think I was getting a nice share at 4-5am of bandwidth + server is situated in uni).. But things were worth when I was connecting with my 3G modem or from some slower networks.

                              Yes, you were completely right, the problem was sandbox. Thanks again! :-)