This site requires JavaScript, please enable it in your browser!
Greenfoot back
Super_Hippo
Super_Hippo wrote ...

2017/2/20

[@danpost] How to center the "camera" in a scrolling world

Super_Hippo Super_Hippo

2017/2/20

#
Hi danpost, it's me again with another question on your Scrolling SuperWorld because I am still not really familiar with it... I add a main actor to the world (an actor which is always following the mouse). So this actor is added in the middle of the visible world which is the top left corner. Then I add the starting buildings for each player randomly across the world. How can I make the main actor and with it the visible world area to jump to this starting building? I tried to simply use 'mainActor.setLocation(d.getX(), d.getY())' with d being the object which should be centered. However, this is not really working. I hope you can help me! Sorry for double post. Right after posting it the first time, I thought I had it and removed the discussion again, but it seems like it was only coincidence...
danpost danpost

2017/2/21

#
I will presume that you are coding this (the setLocation line, in particular) in your SWorld subclass constructor (or prepare method). At the end of that method, you should add the following line:
super.act();
to initialize the "camera" location. The was mentioned in the description of the SWorld class.
Super_Hippo Super_Hippo

2017/2/21

#
I already tried to make it act once, but it is not doing what it should. Maybe there is something else which is done wrong, I don't know... This is the code in the SWorld's subclass: (commented out everything which is not important here).
public Welt(Menü w)
    {
        super(Menü.X, Menü.Y, 1, (int)(Math.sqrt(w.spielerAnzahl()*20000000)), (int)(Math.sqrt(w.spielerAnzahl()*20000000)));
        
        //setBackground("sand2.jpg");
        //setPaintOrder(Leiste.Status.class, Leiste.Knopf.class, Leiste.Ress.class, Leiste.class);
        size = getScrollingWidth();
        m = w;
        //sprache = w.getSprache();
        int num = w.spielerAnzahl();
        spieler = new Spieler[num];
        for (int i=0; i<num; i++)
        {
            spieler[i] = new Spieler(this, w.farbe[i], w.team[i], w.diff[i]);
        }
        //spielerFarbe = spieler[0].getID();
        createObjects();
        
        startpunkte(num);
        //erstelleRohstoffe();
        
        Actor d = getObjects(Dorfzentrum.class).get(0);
        System.out.println("Town Center: " + d.getX() + " " + d.getY());
        System.out.println("mainActor: " + mainActor.getX() + " " + mainActor.getY());
        System.out.println("Scrolled: " + getScrolledX() + " " + getScrolledY());
        mainActor.setLocation(d.getX(), d.getY());
        super.act();
        System.out.println("act");
        System.out.println("Town Center: " + d.getX() + " " + d.getY());
        System.out.println("mainActor: " + mainActor.getX() + " " + mainActor.getY());
        System.out.println("Scrolled: " + getScrolledX() + " " + getScrolledY());
        //Greenfoot.stop(); - for testing
    }


    private void createObjects()
    {
        leiste = new Leiste(0, spieler[0]);
        //Einheit.setLeiste(leiste);
        Maus maus = new Maus(leiste);
        setMainActor(maus, m.X-50, m.Y-50);
        //addObject(leiste, m.X/2, m.Y-100, false);
    }



    private void startpunkte(int num)
    {
        TravelHelper t = new TravelHelper();
        addObject(t, 0, 0);
        for (int i=0; i<num; i++)
        {
            int x = r(size-200)+200;
            int y = r(size-200)+200;
            t.setLocation(x, y);
            if (abstand(x, y, size/2, size/2)>400 && t.keinAnderesDorfzentrum())
            {
                spieler[i].setStartPoint(x, y);
                System.out.println("placed: " + x + " " +y);
            }
            else
            {
                i--; //do it again
            }
        }
        removeObject(t);
    }
In the Spieler (=Player) class, there is this method to create the starting building:
    public void setStartPoint(int x, int y)
    {
        Gebäude dorfzentrum = new Dorfzentrum(this);
        welt.addObject(dorfzentrum, x, y);
        //gebäudeGebaut(dorfzentrum);
        //startpunkt[0] = x;
        //startpunkt[1] = y;
    }
Two examples of the outcome (Town Center is not in the visible area):
placed: 2632 5910
placed: 5231 1206 //second town center, not important
Town Center: 2632 5910
mainActor: 400 350
Scrolled: 0 0
act
Town Center: 775 3098
mainActor: 775 699
Scrolled: 1857 2812
placed: 6225 6284
placed: 4998 1820 //second town center, not important
Town Center: 6225 6284
mainActor: 400 350
Scrolled: 0 0
act
Town Center: 3463 3472
mainActor: 799 699
Scrolled: 2762 2812
Oh and in Menü, there are X and Y:
public static final int X = 800, Y = 700;
danpost danpost

2017/2/24

#
Sorry that I have not gotten back to you on this. I started looking into it, but was side-tracked before figuring anything out. The 'setMainActor' method requires the camera followed character and the range of movement along the x and y from center screen. There is no location fields in that method. This, (m.X-50, m.Y-50), appears to be a location, not a set of range values. You will need to set the location of the main actor after setting it as the main character. A line immediately following line 41 maybe should be:
mainActor.setLocation(m.X-50, m.Y-50);
If the main actor is to be centered when possible, then line 41 should be:
setMainActor(maus, 0, 0);
After looking at your code more closely, it appears that they are ranges and line 41 was okay as you had it. But a 'mainActor.setLocation' line would be needed to change the location of the main actor.
Super_Hippo Super_Hippo

2017/2/24

#
Yes, the range with 50 less than width/height of the world is used so the world scrolls when the mouse is at the edge. Line 26 tries to set the location of the mainActor (the mouse) to the town center (Dorfzentrum). However, this sometimes work as I think it would (the town center is shown at the bottom right corner, -25/-25 from the corner because of the range), but sometimes even that is not happening (town center still far away). In the end, I want to have the own town center to be centered in the middle. I am not sure if I should set the range to 0/0 and then later change it to -50 thing, but can't really test it before the town center is always doing the same thing right now. This is the output of one where the town center ended up in bottom right corner
placed: 2777 2440
placed: 4817 1302
Town Center: 2777 2440
mainActor: 400 350
Scrolled: 0 0
act
Town Center: 775 675 ← bottom right corner
mainActor: 775 675
Scrolled: 2002 1765
... and one where it wasn't:
placed: 4976 3462
placed: 1724 6065
Town Center: 4976 3462
mainActor: 400 350
Scrolled: 0 0
act
Town Center: 2214 675 ← not bottom right corner
mainActor: 799 675
Scrolled: 2762 2787
The mainActor is also at 799 (the edge) and not 775 (edge-25). scrollingWidth and scrollingHeight are 6324.
danpost danpost

2017/2/24

#
Add another printout line after line 31:
System.out.println("Scroll Area: "+getScrollingWidth()+" "+getScrollingHeight());
Super_Hippo Super_Hippo

2017/2/24

#
Town Center at the bottom right edge:
placed: 3283 2726
placed: 2628 1855
Town Center: 3283 2726
mainActor: 400 350
Scrolled: 0 0
act
Town Center: 775 675
mainActor: 775 675
Scrolled: 2508 2051
Scroll Area: 6324 6324
Town center not there:
placed: 4253 1743
placed: 3504 5530
Town Center: 4253 1743
mainActor: 400 350
Scrolled: 0 0
act
Town Center: 1491 675
mainActor: 799 675
Scrolled: 2762 1068
Scroll Area: 6324 6324
danpost danpost

2017/2/24

#
Sorry, add one more thing:
System.out.println("World Area: "+getWidth()+" "+getHeight());
Super_Hippo Super_Hippo

2017/2/24

#
Added after the last added print out line As the scroll area, not depending on the town center in corner (last post edge should also be corner) or not:
World Area: 800 700
danpost danpost

2017/2/24

#
I think your problem is that you did not understand that the main actor is not only placed in the center of the viewed world, but also in the center of the scrolling area. That means that 2762 is the maximum scrolled amount to the right and -2762 is the maximum scrolled amount to the left (or your initial scrolling area is from (-3162, -3162) to (3162, 3162) in world coordinates). Since your town center was placed at world coordinates (4253, 1743) in your last test, which would be 2762+4253 = 7015 in (or, rather, outside) the scrolling area. The scrolling did what it was supposed to do -- stop scrolling at 2762 and move the actor as far right as possible to the x-coordinate of 799. The initial world coordinate of (0, 0) is at ((scrollingWidth-getWidth())/2, (scrollingHeight-getHeight())/2) in the scrolling area.
Super_Hippo Super_Hippo

2017/2/24

#
Oh ok, yes, I did not see that. I will report back if I can make it work now. Thank you!
danpost danpost

2017/2/24

#
Super_Hippo wrote...
Oh ok, yes, I did not see that. I will report back if I can make it work now. Thank you!
You should be able to just subtract 3162 from all your coordinate values before you use 'super.act();' (if I am not mistaken).
Super_Hippo Super_Hippo

2017/2/24

#
Subtracting half of the size when adding the objects and using the following to actually center the town center in the world rather than just being visible works perfectly!
Actor d = getObjects(Dorfzentrum.class).get(0);
mainActor.setLocation(d.getX(), d.getY());
super.act();
int dx=d.getX(), dy=d.getY(), mx=m.X/2, my=m.Y/2;
mainActor.setLocation(mx+2*(dx-mx), my+2*(dy-my));
super.act();
danpost danpost

2017/2/25

#
danpost wrote...
You should be able to just subtract 3162 from all your coordinate values before you use 'super.act();' (if I am not mistaken).
I probably was mistaken and you need to subtract 2762, not 3162. I was trying to find an easier way to center the town in the viewer. Experimenting with 'setMainActor(dorfzentrum, 0, 0)' followed by 'dorfzentrum.setLocation...' and 'super.act'; then 'setMainActor(maus...'. You would then have to 'addObject(dorfzentrum...' to add the object to the list of scrolling objects in the SWorld object.
You need to login to post a reply.