How is the population in SimCity 4 and Cities: SkyLine is 100?



  • Everyone saw in SimCity and Cities: Skyline and similar to them that in the city, you can clap on the pedestrian/car and you will have an interface that has: Name of characterresidenceplace of work and Where is he going?♪ I understand these people are just objects of one, maybe a few classes, and it's not hard to create. When are the cities 100? So the question is for experienced programmers: I think it's a very heavy one for the resources of my nose. 100k + objects? and normal system requirements? ♪ What's the catch? Or I'd rather say my invisibility.



    1. The fact that there are 100 kilos of objects in the city doesn't mean that they all have facilities.
    2. 100 of the objects that, say, weigh 200 Byte are 20 megabytes. It fits. Problems will be with GC, most likely. But I think it's possible for generations to be built so that there's no big fries for assembly.

    As a matter of fact, it's doubtful that all 100 objects are always remembered. At least I see a few ways of optimizing:

    1. Area/location crash. Loading facilities only within this zone. Remember the old games, there was a downloading window between the locations. If my memory doesn't change, it was in the same WoW'ca in time for the interlocations. It's now that they've optimized that they don't have to wait and create the illusion of a world of dish.

    2. Use site bullets. To keep up with the GC, and simply not to waste resources on facilities, bullets are used. Let's just say, start a bullet of 100 objects. As necessary, complete their properties with the necessary data (when man/creation/machine is in sight). When the object comes out of sight, clean the object and put it back in the pool. Then this object from the bullet will take another character of the game world. I used such bullets for objects that are often created: bullets, spells, etc.

      I can bring the code from our current project. I'm using it. org.apache.commons.pool2 for the creation of a database connector:

      For example, a method that loads meta data for service from the base:

      public void loadMetaInfo(){
          LOG.debug("load meta info");
          DB db = null;
          try{
              db = mDB.getResource(); // получаем подключение из пула
              String reqId =  getRequestId();
              db.send(new CommandRequest(Command.INFO.toString(), reqId), this);
              mRequests.put(reqId, new CacheItem("load info"));
          }
          catch(Exception ex){
              LOG.error("loadMetaInfo: db_problem");
          }
          finally{
              if(db != null)
                  db.close();  // после окончания работы возвращаем объект в пул, 
                               // чтоб им могли воспользоваться другие клиенты
          }
      }
      
    3. As noted in the commentaries, in order to optimize memory work, it is possible to prevent the creation of copies of classes with a common essence, using Pattern (Flyweight pattern). You can read it (yes and many other paths) http://dofactory.com/net/flyweight-design-pattern Let's go. It's basically like a p.2. Typical example of using this template - Buffer pools.

    Pattern adaptor (Flyweight)

    That's it. structural A design template that allows shared facilities to be used in several contexts. This pathterne is used primarily to optimize memory work.

    Let's just say if we want to write a text editor. For simplicity, only the letters of the Russian alphabet are used. Creating an object on every letter is very good. We can identify a dictionary consisting of 33 objects that we will reuse. Ultimately, for example, for a 330-letter text, we have reduced the number of facilities constructed 10 times. If it's a book, it's a thousand.

    A key point is the internal and external separation. The internal state of context does not depend. In the example of symbols, the internal condition is described by the symbol code from the coding table. Since the internal state is not subject to context, it can be shared and is therefore placed in shared facilities.

    External status depends on context and is variable. In the application to the symbols, the external condition may represent the symbol position on the page (line + column). So the symbol code can be used by many symbols, while the position on the page will be individual to each symbol.

    On your question. Each facility may have an internal condition of the object size, its material, some physical values, the parameters of the collider. External status: name of the person, place of residence, place of work and where he is headed.

    We can show the UML diagram with Wiki: введите сюда описание изображения

    With regard to your question, I suggest a fast-track implementation for Java. There's no way to check the code now, but I think it's important to catch the point.

    Let's say we have two characters, fat and skinny. Then there'll be something like that.

    Base class defining object-person:

    public abstract  class Character{
    
    protected String mTitle;
    
    protected String getTitle() {
        return mTitle;
    }
    
    protected void setTitle(String mTitle) {
        this.mTitle = mTitle;
    }
    
    protected int getWidth() {
        return mWidth;
    }
    
    protected void setWidth(int mWidth) {
        this.mWidth = mWidth;
    }
    
    protected int getHeight() {
        return wHeight;
    }
    
    protected void setHeight(int wHeight) {
        this.wHeight = wHeight;
    }
    
    protected int mWidth;
    
    protected int wHeight;
    
    public abstract void printCharacter();      
    

    }

    Two of them:

    public class FatCharacter extends Character {

    public FatCharacter(){
        setTitle("Я толстяк");
        setWidth(20);
        setHeight(40);
    }
    
    
    @Override
    public void printCharacter() {
        System.out.println("Title: " + getTitle() + ", width:" + getWidth() + ", height: " + getHeight());
    }
    

    }

    public class ThinCharacter extends Character {

    public ThinCharacter(){
        setTitle("Я худой");
        setWidth(10);
        setHeight(40);
    }
    
    @Override
    public void printCharacter() {
        System.out.println("Title: " + getTitle() + ", width:" + getWidth() + ", height: " + getHeight());
    }
    

    }

    The factory, in fact, which is responsible for the creation of facilities:

    public class FlyweightFactory {

    public static enum Code{ Thin, Fat};
    
    private Map<Code, Character> mCharacters = new EnumMap<Code, Character>(Code.class);
    
    public Character getCharacter(Code characterCode){
        Character character = mCharacters.get(characterCode);
    
        // если такого объекта ещё нету, то создаём
        if (character == null){
            switch (characterCode){
                case Fat : 
                    character = new FatCharacter();
                    break;
                case Thin : 
                    character = new ThinCharacter();
                    break;  
            }
    
            // добавляем в пул
            mCharacters.put(characterCode, character);
        }
        return character;
    } 
    

    }

    Use this:

    Character character = factory.getCharacter(Code.Fat);
    character.printCharacter();




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2