google-code-export / los-cocos

Automatically exported from code.google.com/p/los-cocos
Other
1 stars 0 forks source link

ScrollingManager bad behavoir when resizing #153

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
bugdemos attached:

test_scroll_manager_resize.py : for windowed resize
test_scroll_manager_ctrl-f.py : resize to fullscreen with ctrl-f

cocos r960, pyglet 1.1.4

You will need grossinis_sister1.png , to be found in the test directory.

  i. run, verify that as you move the player with arrows keys you can
     make the view scroll to show all the world, and not more
 ii. Move the player to bottom left corner and do resize-up the window
     The world area you view seems to be correct, that is,
     the same as before resize but scaled up
     But moving the player you cannot scroll all the view
     And an out of world area at left is shown when player is far right
iii. doing a resize-down can let the player out of view (but the first move
     keystroke will scroll the map to show the player)

Original issue reported on code.google.com by ccanepacc@gmail.com on 28 May 2010 at 3:48

Attachments:

GoogleCodeExporter commented 9 years ago
Tests updated and expanded:
    test_0_scroll_manager_ctrl-f.py
    test_1_resize_other_then_push_scroll_manager.py
    test_2_scroll_manager_push_other_resize_pop.py

You will need grossinis_sister1.png , to be found in the test directory.

You will need cocos r966+ or comment out in cocos\layer\scolling.py
the line that raises NotImplementedError

Exercises ScrollingManager when the world is not a tile map, verifying:

    scroll constraints works, ie by scrolling you can view all the word but not more 
than the world.

    the former is valid when resize or zooming (scale)  is applied

    coordinate changes 'screen to world' (aka pixel_from_screen) consistent when 
resize and or zoom and or scroll

    coordinate changes 'world to screen' (aka pixel_to_screen) correct at any zoom 
factor, resize, scroll amounts

    good behavior when world size less than the view-size

See details and instructions in the console output and comments.

Original comment by ccanepacc@gmail.com on 6 Jun 2010 at 4:10

Attachments:

GoogleCodeExporter commented 9 years ago
Tests, new and upgraded:
    test_a0_scrolling_manager_ctrl-f.py
    test_a1_resize_other_then_push_SM.py
    test_a2_SM_push_other_resize_pop.py

    test_b0_tiles_scrolling_manager.py
    test_b1_resize_other_then_push_SM.py
    test_b2_SM_push_other_resize_pop.py

Solutions, meaning alternate versions for scrolling.py:
    scrolling_autoscale_pre.py
    scrolling_no_autoscale_pre.py

    scrolling_autoscale.py
    scrolling_no_autoscale.py

    scrolling_fusion.py
    scrolling_fusion_refactored.py

All files plus resources and text in a zip file:
    issue_153_scrolling_manager_1.zip

Note:
In some browsers the issues page looks very bad.
Into the zip, the file follow_up_2a.rtf contans this same text.   

The tests:

The test_ax_... exercises a simple scene which dont uses anything in tiles.py
a1, a2 are variations on a0 meanng to test correct behavior when resizes 
happens while the scene with the scrolling manager is not the active scene.

Similary, the test_bx... exercises a scene when tiles.py is in use, based on 
the stock test_tiles.py.
Variations have the same meaning as in the previous group.

All test can be run in two modes:
    mode 1 (autoscale): we expect autoscale when resized so that the same area is shown at any viewport size
    mode 2 (no autoscale): we expect that when resized the worldview shows more or less from the world, at the same scale before and after the resize.
The former usually is used when in-game, the later in a game level editor or 
tool.

Tests Succes:

A proper scrolling.py should allow to run all the interactive tests, in both 
modes, without glitches.
You will need cocos trunk r966+ to run the tests.
You will need some resources to run the test; you can find them in the standart 
cocos test directory; they are also included in the attached zip.

Each test aims to verify that:

    scroll constraints works, ie by scrolling you can view all the word but not more than the world.

    the former is valid when resize or zooming (scale)  is applied

    coordinate changes 'screen to world' (aka pixel_from_screen) consistent when resize and or zoom and or scroll

    coordinate changes 'world to screen' (aka pixel_to_screen) correct at any zoom factor, resize, scroll amounts

    good behavior when world size less than the view-size

See details and instructions in the console output and comments.

Refinning Solutions:
solution == alternative scrolling.py

Level 1:
A minimal change to ensure scroll constraits works. The other constraits are 
not meet in one or more situations.
With some zoom factors you can see a strange flicker; it is an artifact comming 
for the not addressed constraits.
Secondary goal: make it easy to compare with the original scrolling.py, and 
between the alternate solutions.

The only meaningful tests here are the a0 and b0.
Two solutions generated, one for each mode:
     scrolling_autoscale_pre.py
     scrolling_no_autoscale_pre.py 

Notes:
    I don't followed in deep the interaction between scrolling and tiles; I have some doubts about if the intify of tiles coords are equivalent. Scrolling with a 5x zoom shows similar behavoir with the original scrolling.py

Level 2:
Address the remaining constraits.
All tests pass when you use the solution adequate for the test mode.

Two solutions generated, one for each mode:
    scrolling_autoscale.py
    scrolling_no_autoscale.py

Level 3:
Made available both behaviors (autoscale and not autoscale) in the same 
solution.

Some facts:
   if you do director.init with do_not_resize=True, is a strong hint that you want a scrolling without autoscale.
   if you do director.init with do_not_resize=False (the default), most probably you want autoscale. But in some cases like using sizers you do not want autoscale; the sizer will manage real state.

Aproach selected:
ScrollingManager combines the two solutions with conditional code.
Desired behavior is selected with a new kwarg, do_not_scale

Added the do_not_scale kwarg to ScrollingManager constructor, with default None
The default value None means that you will get autoscale if used director.init 
with do_not_scale=False, and not autoscale if used director.init with 
do_not_scale=True.
It is imposible to specify autoscale behavior if director.init was called with 
do_not_scale=True

        self.autoscale = not do_not_scale and not director.do_not_scale_window

Generated solutions:
    scrolling_fusion.py
    scrolling_fusion_refactored.py
Note that each file is a complete solution: any test runs ok with any one 
solution, in any test mode.
The first solution combines the Level2 solutions with minimal code changes
The second refactored the first for better looking code.

Note 1:
fusion can be achieved with other techniques:
    Make two separate classes:
 like ScrollingManagerAutoscale and ScrollingManagerNoAutoscale, user selects behavior by choosing wich class to use
 pros: totally clear, no conditional code
 cons: classes differs in a few lines, so good design calls for a base class with the common code -> Classes proliferation.

    One class, but using a strategy to get rid of conditional code: receive a parameter holding a function to call when the
view_w, view_h needs refresh. The module will provide the two basic strategies: 
fn_autoresize, fn_follow_phys_size; the user is free to provide custom 
strategies or pass one provided in the module.
pros: probably the most clear and powerfull
cons: more investiment in design, more docs to explain the requeriments for a 
strategy

Note 2:
The case hen you pass a parameter 'viewport' to ScrollingManager was not 
handled here; I will follow up later.

Coments wellcomed. Thanks Devon for the scaling coords patch, it was merged at 
the Level2 solutions.

Original comment by ccanepacc@gmail.com on 10 Jun 2010 at 2:48

Attachments:

GoogleCodeExporter commented 9 years ago
new tests:
   test_a3_scrolling_manager_rect.py
   test_a4_scrolling_manager_force.py
   test_a5_scrolling_manager_rect_force.py

   test_b3_tiles_scrolling_manager_rect.py
   test_b4_tiles_scrolling_manager_force.py

Solutions, meaning alternate versions for scrolling.py
   scrolling_fusion_w_glScissor_8.py

All files plus text, news and olds in a zip file: 
issue_153_scrolling_manager_2.zip

The tests:

ax are variations on a0, a simple world where no tiles are used.
a3 is the case where an explicit viewport is provided to ScrollingManager 
constructor.
a4, a5 exercises force_focus.

bx are variations on b0, a simple world where tiles are used.
b3 exercises the case where an explicit viewport s provided
b4 exercises force focus

All test can be run in two modes:
    mode 1 (autoscale): we expect autoscale when resized so that the same area is shown at any viewport size
    mode 2 (no autoscale): we expect that when resized the worldview shows more or less from the world, at the same scale before and after the resize.
The former usually is used when in-game, the later in a game level editor or 
tool.

Test success:
A proper scrolling.py should allow to run all the interactive tests, in both 
modes, without glitches.
You will need cocos trunk r966+ to run the tests.
You will need some resources to run the test; you can find them in the standart 
cocos test directory; they are also included in the attached zip.

Each test aims to verify that:

    scroll constraints works, ie by scrolling you can view all the word but not more than the world (except for the force_focus tests, a4, a5, b4, where you can view all the world and out of the world)

    the former is valid when resize and/or zooming (scale)  is applied

    coordinate changes 'screen to world' (aka pixel_from_screen) consistent when resize and or zoom and or scroll

    coordinate changes 'world to screen' (aka pixel_to_screen) correct at any zoom factor, resize, scroll amounts

    good behavior when world size less than the view-size

    additionally, for tests using an explicit viewport (a3, b3): viewport placemment and size must behave as:

        in mode 1 (autoscale): viewport position and size are interpreted as in virtual coordinates, so it will reposition and resize like a normal standard square in the scene.

    in mode 2 (no autoscale): viewport position and size are interpreted as physical screen coords, so in a resize will not change. It will look as if the viewport translated in the resize. Your app will need to override ScrollingManager.on_cocos_resize to change this behavior.

See details and instructions in the console output and comments.

The code

 scrolling_fusion_w_glScissor_8.py builds over the scrolling_fusion_refactored.py solution.
Adds support for explicit viewport and fixes force_focus

Passing an explicit viewport param

Sometimes we don't want our scrolling scene to take all the window surface, 
that is, we want ScrollingManager to limit its draws to a specified rectangle 
in the window.

Examples:
Wonderboy, a side scroller platformer. The upper screen is used for game stats, 
the lower screen shows the scrolling world. 
Warcraft 3, a real time strategy game. Upper screen shows a world sliding in 
two directions, lower screen used for stats and some management.

To allow this functionality ScrollingManager accepts an explicit viewport 
parameter, which represents a rectangle in the window. It is a cocos.rect.Rect 
instance.

The current implementation distinguishes two viewport interpretations:

1. If ScrollingManager is in autoscale mode, the viewport is seen as specified 
in virtual coordinates. When the window is resized, the viewport will be 
proportionally resized and positioned, just as a simple quad would be.

2. Otherwise, the viewport is seen as specified in physical screen coordinates. 
Here ScrollingManager will not adjust viewport in a resize. You should override 
ScrollingManager.on_cocos_resize if you want custom viewport resize.

ScrollingManager will take care not to draw outside the specified viewport.

Using force_focus instead of set_focus
This tells ScrollerManager to ignore the restriction: dont show areas 
out-of-limits

set_focus is the first class, useful method to handle focus.

I don't see a use case for force_focus, except in development.
So I don't upgraded the code to handle some small temporal glitches with 
force_focus:
    when resizing or scaling, the view will redraw as if a set_focus was issued
    same when adding a node.
    You need to call force_focus directly or indirectly to regain the force_focus rendering; in the test that happens when you move after a resize or scaling.

An upgrade to fix those glitches is not complicated:
    make set_focus and force_focus set a flag telling which one was used to manage the last focus
    make refresh_focus use this flags
    add a flag parameter in the .add method to tell which one to use for refresh the focus after the add.

If someone want this upgrade, let me know.

Test Results

The tests a0 to a5 and b0 to b4 runs ok in both modes, except for the mentioned 
glitches in force_focus, and there is a problem when using tiles with an 
explicit viewport: not all tiles will draw. Run test b4 to see the later.

Resolution

Commit this scrolling.py version to get some feedback -> r967
Later upgade the docstrings, investigate the tiles - viewport problem.

Original comment by ccanepacc@gmail.com on 14 Jun 2010 at 4:26

Attachments:

GoogleCodeExporter commented 9 years ago
note that for r971 or better you must replace the file road-map.xml with an 
updated version attached; is the same as the one committed in r972

Original comment by ccanepacc@gmail.com on 16 Jun 2010 at 11:55

Attachments:

GoogleCodeExporter commented 9 years ago
upgraded scrolling.py and tiles.py to fully work with viewports, r977

origin_x, origin_y probably don't plays fair: changing this params don't 
changes the view.
Commenting out the two lines in scrolling ScrolledLayer.set_view that uses 
origin_x, origin_y does offset the view, but probably will broke other things.
Wont fix at this time, use origin_x, origin_y set to 0 for future 
compatibility.     

Original comment by ccanepacc@gmail.com on 21 Jun 2010 at 3:59