UltraStar-Deluxe / Play

Free and open source singing game with song editor for desktop, mobile, and smart TV
https://ultrastar-play.com
MIT License
398 stars 74 forks source link

Screen division algorithm #33

Open barbeque-squared opened 6 years ago

barbeque-squared commented 6 years ago

Do you want to request a feature or report a bug?

Feature

What did you expect to see?

In theory, we could support m different Voices across n Players. In the best case, and assuming Players do not get to choose which Voice they get to sing, you basically have to make a bunch of rectangles and then cluster them in a visually pleasing way inside a bigger rectangle (ie, the screen).

For the case of making this as generic as possible yet at least somewhat doable, we will assume that the actual number of screens, p, is variable as well, but that all screens are the same width and height. Whether menus/background image/video is repeated on all screens or stretched across is outside the scope of this algorithm (could be just a setting), as is the configuration of the screens itself (3x1, 2x2, etc).

So: Input:

Step 1: assign Players to Voices

Step 2: distribute the Voices and their Players across the screens To make optimal use of screen estate, spreading 6 players across 3 screens for a duet song should be possible. Therefore:

Step 3: compute the optimal distribution per screen Note: this algorithm will give each Player an equally sized rectangle to put their Notes in, aka if you're with 3 players across 2 screens, the third Player will not get a bigger notes area. If running the algorithm for every screen, for every voice, for every player is okay, then go ahead and do that, otherwise you only need to compute it once for the first screen, the first of its voices, and the first of its players.

Step 3.1: decide where to place each Voice and its players Essentially, this results in a grid. On a portrait screen, it's probably best to have 4 Voices as a column, 2x2 on square-ish monitors, or even as a row if your screen is mega wide. It's probably a function that depends on the aspect ratio of the screen and the number of Voices it needs to fit.

Just make a function that returns the sort-of heuristic optimal number of rows when given the screen aspect ratio and the number of voices. From there you'll know the number of columns required, and then it's just a simple grid and assigning stuff. This can be tweaked later on if necessary.

Step 3.2: decide where to align the lyrics By default, lyrics will be placed at the bottom of the Voice, unless the grid has two rows, in that case lyrics for the top row will be placed at the top. Lyrics will take up some (fixed) amount of space from the rectangle this Voice can place its stuff in.

Step 3.3: decide where the players go This is where it becomes easy. Essentially, you have some subspace x by y pixels left for drawing notes for some number of players. Either we make this into a grid again (see above) or each note area needs to have a specific aspect ratio (can be changed later on or even made an option) which for now we'll set at 10:4. Either it's some heuristic, or it's a maximization problem that is easy to solve. In case of the latter:

At the end, you have either one or two possible candidate rectangle sizes, just take the biggest. The optimal rectangle grid will always either cover the entire x or the entire y (or both if x:y is also 10:4).

Todo / Decisions that still need to be made

achimmihca commented 5 years ago

UI Scaling is defined by Unity RectTransform's anchor and corner positions. Anchor values are relative to the parent RectTransform (values from 0 to 1). It's better not to think in pixels, but as percentage of the parent's drawing area. If you place UI objects in the scene and configure the anchors correctly, then it will adapt to other screen sizes as well. See also: https://docs.unity3d.com/Manual/UIBasicLayout.html

For the concrete layout, I would just re-implement what USDX is doing. No need to change what has been working great for so long.

Furthermore, I would always keep it simple and then build on that for a more general solution. I would not calculate with n players, where n is unbounded. USDX supports up to 6 players and more seems unlikely to me. One can take a look at the screen layout of 1, 2, 3, 4, 6 players singing in USDX for a reference.

The layout of the results scene is also different for 1,2,3,4 and 6 players in USDX. They use the available space in a very good way. I would just re-implement this design.

basisbit commented 5 years ago

What USDX was doing regarding the local multiplayer display for the singing screen was to require a theme that contained all the single graphics element positions for 1 player mode, for 2 players mode, 3, 4, 6 and then for the second screen it would just hard-coded use the theme 3 player mode layout for 6 players and duplicate it on the second screen plus hard-coded change some colors. That part of USDX is really "ugly", requires manually changing theme positions for all the variations if you want to improve the theme and does not work well for different screen formats...

Of course, the layout result itself can be copied - yes, that worked well in USDX. Just please don't copy how that layout was created in USDX. 😄 Would be nice if the sing-screen-layout is a easily replaceable / changeable code class so that in the future other styles could also be implemented. (lots of people seem to like the rock-band style: see https://youtu.be/4-9MUD-Ms80?t=39 )

achimmihca commented 4 years ago

The naive appraoch that is implemented now is adding all player UIs in a vertical list. So every player's UI uses the full width and the height is evenly distributed. This works good enough for one and two players, so I think it is enough for a first minmal release.

achimmihca commented 4 years ago

The new version that came with #180 implements the layout similar to USDX but using LayoutGroups.

The grid sizes are (rows columns) 1 player: 2 1 (first player is at bottom) 2 players: 2 1 (first player is at top, second at bottom) 3 players: 3 1 4 payers: 2 2 5 players: 3 2 (one empty space in lower right corner) 6 players 3 * 2

I think more than 6 players singing individually does not make much sense because the singing will disturb each other. When using more then 6 players, people could share their mic and sing in a choir.

basisbit commented 4 years ago

8 or 12 players using two screens or a 4k hd projector works fine. We tested this with USDX a couple of times end of last year (the time before Covid19 cancelled all those conventions and meetups 😢 ). Also, as suggested in the above posts and previous discussionss, it would be nice if the screen is splitted more intelligently depending on user count and screen aspect ratio. On a 21:9 maybe a three by two layout would be better than a two by three layout. For a 9:21 screen, or even for a 9:16 screen surface, a 1 by 4 layout would work nicely. Of course this depends on amounts of player and it the top of the screen is used for duet player lyrics. Would be nice if this is implemented to just take the screen resolution minus parts for lyrics and then use that to optimize the layout for whatever screen surface ratio there is to be used.

achimmihca commented 2 years ago

The current layout using UIToolkit and flex-box layout supports 16 players. It may not be optimal from a theoretical point of view, but it gets the job done IMO.