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

2015/5/29

Problem with implementation of scrolling world and fullscreen

lighoa lighoa

2015/5/29

#
I've been trying to combine a scrolling world library (http://www.greenfoot.org/scenarios/5806) and a fullscreen library (http://www.greenfoot.org/scenarios/7404) for a major section of my end of year project. Multiple problems have arisen from this attempt, including: -Scrolling non-camera followers staying in a fixed place -The background glitching out several times -The scrolling camera follower staying in a fixed place (seems to be "fixed" if I enlarge the size of the world about 5000x5000) Any fixes for these bugs would be greatly appreciated. Scource code: http://www.greenfoot.org/scenarios/14029
danpost danpost

2015/5/29

#
I commented on the scenario itself. However, responses to my comment can be posted in this thread.
lighoa lighoa

2015/5/29

#
Thank you, danpost. I am aware that both were not meant to interact with each other- as soon as I wrapped my head around their mechanics I was able to tell that it would be a painfull process. Is their any other full-screen methodology that doesn't interact with the same mechanics of a scrolling world? As long as they don't overlap mechanically, in theory they should work.
danpost danpost

2015/5/29

#
I was thinking that you may have better luck in implementing both behaviors by using a scrolling engine that is less elaborate. First, it is not necessary for a scrolling engine to be a superclass of your World subclass; secondly, it is not necessary to have classes of your scrolling actors subclass a special class to implement their scrolling. To illustrate this, download my Bee Quick (ImgScroll Demo) scenario and check out how scrolling was done in it. The ImgScroll class should not be modified; all set-up and usage would be done in your world class (your DemoWorld).
lighoa lighoa

2015/5/30

#
Alright then, I'm working on revising both the fullscreen and scrolling functionalities for optimization and simplicity. I'll update the scenario when I finish this part, and thank you for your guidance.
danpost danpost

2015/5/30

#
There are some issues with the full screen implementation that may be of concern. (1) The background image is not dealt with properly when the world is expanded to full screen; (a) if tiled, the tiling is continued (not scaled); (b) if a world-sized image is set as default, it would not fit the full screen world (no code provided to deal with this situation) (2) the horizontal and vertical scaling are virtually never proportional (which can cause distorted actor images); (3) because everything is rounded to int values in the full screen implementation, there is a lack of precision in the scaled movement of the actors (for example, what may move continuously in a circular path in a standard world could have the circular path slowly migrate up and to the left (toward zero horizontally and vertically) because fractional parts of the movement are being disregarded; Unfortunately, the 'setBackground' method is declared as 'final'; so, one cannot even skirt issue (1) gracefully by overriding the method in the ModWorld class. The code must be modified in the subclass of ModWorld to deal with the background image (the image needs to be scaled properly before being set). My solution to issue (2) was to get the smaller of the scale factors, horizontal and vertical, and use it universally. For issue (3), double values for the x and y coordinates of the actors would be required to have the actors in the full screen act in like fashion to a non-full screen world;
lighoa lighoa

2015/5/30

#
I was looking at your code for "World Scaling Demo", where the output of the world is displayed by itself and can be modified afterwards. Do you think this approach would work? In hindsight, it would seem to solve the issues you listed. The scaling not acting on the world itself would save from a lot of compatibility issues between these two goals, but again- this is theoretical (not for long though). I'll update once I get working scenario. *A note: all worlds will have the same window ratio, e.g. "super(960, 540, 1);"
danpost danpost

2015/5/31

#
The World Scaling Demo scenario (1) does scale proportionally (2) is not prone to excessive fractional rounding and (3) will not present issues with the background image; I believe that it may do quite nicely as far as what you are trying to accomplish. All worlds should be scalable with the system, regardless of what type they are (the fact that you are using a scrolling world should not matter). If you run into any issues with my scaling system, please to not hesitate to let me know what they are.
danpost danpost

2015/5/31

#
lighoa wrote...
*A note: all worlds will have the same window ratio, e.g. "super(960, 540, 1);"
Maybe for you. Keep in mind, that the ratio given is specific to you (and to some others) -- but, not to all. Most will have different (and various) ratios. Do not specifically use that ratio; but, continue to utilize the Toolkit values to maintain portability of the project.
lighoa lighoa

2015/5/31

#
I updated the scenario- I used both of your systems, so if you would not like me to use them please let me know and I will take it down. I made some minor adjustments to your code: -The variable zoom was replaced with zoomW and zoomH -The method to change the world scale was removed -Surrounded mouse variables in try-catch statements to keep from breaking the program (sloppy, but it's on my TODO list) -Code rewritten, variables renamed (for my sake, so I could understand what was going on)
danpost danpost

2015/5/31

#
I do not mind you using them. However, my authorship should not be removed. If you must alter the class codes, add a comment line that indicates that you did so
/**
 *  AUTHOR: danpost (greenfoot.org username)
 *  MODIFIED BY: lighoa (greenfoot.org username)
 */
However, I would rather you did not alter them at all. They were all created so that no modifications would be required for their use. All the classes were well documented and you should have little problem in following and understanding what goes on. Notify me if you find any bugs or inherent issues with any of the classes. These classes include 'ImgScroll' (MapScroller), 'PIP' (Display), 'MouseInfo' and 'Zoomer' (WorldDisplay).
lighoa lighoa

2015/5/31

#
Alright, will do. Thank you for your help, and I will make these corrections to the classes.
danpost danpost

2015/6/1

#
I was finally able to implement both behaviors using a ModWorld/ModActor type system with my ImgScroll class. I basically had to re-build the ModWorld and ModActor classes. I did have to change one command in the ImgScroll class (the one that adjusts all the actor locations) as well as add a line in the subclass of ModWorld to properly scale the image that is set for the scrolling background. I did incorporate a semi-smooth moving system to reduce the amount of fractional movement that is disregarded. Unfortunately, 'getX' and 'getY' were forced out of use for movement (i.e. 'setLocation(getX()+1, getY()+0)') because those methods do not return the same values as those now used for moving. So, I added an extra movement method in the ModActor class as a substitute called 'scroll(int dx, int dy)' (i.e. 'scroll(1, 0)' as the replacement for the previous statement). Everything is scaled proportionally and the base (i.e. '(400, 400)')world can be scaled using either the larger or smaller ratio of dimensions between the base and full screen. The difference is that using the smaller ratio, the entire viewed base world is still visible, while using the larger one, only the breadth of one dimension is completely visible. To keep in line with a "full screen" transform, I felt that what was visible in the base world should also be visible in the full screen view; so, I chose the smaller ratio to work with (even though the window may not actually fill the screen). My goal was to have the same exact visual as the base world -- only zoomed to the max as far as what the screen allowed.
lighoa lighoa

2015/6/1

#
That is amazing! A couple questions so I can learn from this: 1. What changes did you make to the ModWorld and ModActor classes? 2. How did you incorporate a semi-smooth moving system? I am extremely impressed. Thank you for all of your help danpost.
danpost danpost

2015/6/2

#
lighoa wrote...
1. What changes did you make to the ModWorld and ModActor classes?
Like I said, I had to totally re-write those classes; I ended up with this for the super world class ('ModWorld' is now named 'FullScreen'):
import greenfoot.*;
import java.awt.Toolkit;

public class FullScreen extends World
{
    static int screenWidth = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    static int screenHeight = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    
    private int zPct; // percentage used in full screen scaling
    
    public FullScreen(int w, int h, boolean bounded)
    {
        super((int)(w*calcZoomPct(w, h)/100), (int)(h*calcZoomPct(w, h)/100), 1, bounded);
        zPct = calcZoomPct(w, h);
    }
    
    // added to calculate the zoom percentage value that will be used
    private static int calcZoomPct(int w, int h)
    {
        return (int)(Math.min(1.0*screenWidth/w, 1.0*screenHeight/h)*100);
    }
    
    // added to allow access to the zoom percentage used
    public int getZoomPct()
    {
        return zPct;
    }
    
    // overriding to allow fine-tuned coordinate values of actors to be set properly
    public void addObject(Actor actor, int x, int y)
    {
        super.addObject(actor, 0, 0);
        ((ModActor)actor).setLocation(x, y);
    }
    
    // added to allow easy conversion of base distances to full screen distances
    public int scale(int n)
    {
        return n*zPct/100;
    }
}
and this for the super ModActor class:
import greenfoot.*;

public abstract class ModActor extends Actor
{
    private GreenfootImage baseImage; // normal sized image set to actor
    private int fineX, fineY; // fine-tuned location coordinates (1/100 of pixel units)
    private int fsPct; // percent value used for full screen scaling
    
    /** ***************   methods to maintain properly scaled images   *************** */
    // added to allow acceess to base image
    public GreenfootImage getBaseImage()
    {
        return baseImage;
    }
    
    // overriding to maintain properly scaled image
    public void setImage(String filename)
    {
        setImage(new GreenfootImage(filename));
    }
    
    // overriding to maintain properly scaled image
    public void setImage(GreenfootImage image)
    {
        baseImage = image;
        scaleImage();
    }
    
    // scales the image of the actor
    private void scaleImage()
    {
        if (baseImage == null || getWorld() == null) return;
        GreenfootImage fullImage = new GreenfootImage(baseImage);
        fullImage.scale(fsPct*baseImage.getWidth()/100, fsPct*baseImage.getHeight()/100);
        super.setImage(fullImage);
    }
    
    // overriding to get scale percentage and scale image of the actor
    protected void addedToWorld(World world)
    {
        fsPct = ((FullScreen)world).getZoomPct();
        scaleImage();
    }
    /** ****************************************************************************** */
    
    /** ******************   methods to maintain proper location   ******************* */
    // overriding to use 1/100 of a pixel units in movement
    public void setLocation(int x, int y)
    {
        fineX = x*fsPct;
        fineY = y*fsPct;
        super.setLocation(fineX/100, fineY/100);
    }
    
    // added to replace normal setLocation method
    public void scroll(int dx, int dy)
    {
        fineX += dx*100;
        fineY += dy*100;
        super.setLocation(fineX/100, fineY/100);
    }
    
    // overriding to use 1/100 of a pixel units in movement
    public void move(int dist)
    {
        fineX += (int)(1.0*dist*fsPct*Math.cos(getRotation()*Math.PI/180));
        fineY += (int)(1.0*dist*fsPct*Math.sin(getRotation()*Math.PI/180));
        super.setLocation(fineX/100, fineY/100);
    }
}
2. How did you incorporate a semi-smooth moving system?
As you can see in the ModActor class, I divided each pixel into 1/100 and kept track of the actors coordinates in 100 times its actual position.
You need to login to post a reply.