bberak / react-native-game-engine

A lightweight Game Engine for React Native 🕹⚡🎮
MIT License
2.87k stars 172 forks source link

Handle non-fullscreen games #38

Closed VBT-BB closed 4 years ago

VBT-BB commented 4 years ago

Currently the lib only supports fullscreen games, but what if we don't want the game to be fullscreen and display for example a bottom or top bar ? This section could look more like:

  onLayoutHandler = ({ nativeEvent: { layout: { width, height }}}) => {
    this.screen = { ...Dimensions.get("window"), width, height, layout: true };
    this.forceUpdate();
  };

I would add something like this layout variable because between initialization and layout, screen is still equal to Dimensions.get("window") so you can check the variable to know if you must hide entities while it doesn't have the final dimensions

bberak commented 4 years ago

Hi @VBT-BB,

Good point regarding the screen variable. Are you thinking that the screen variable should ideally reflect the size of the playable game screen and not the entire phone screen? I feel like that makes sense.. We could also introduce a new variable called layout that will get passed into the systems alongside screen - that might be more backwards-compatible actually..

Regarding your other comment about adding a top and bottom bar and / or resizing the game screen.. You should be able to style the game view as needed..

<GameEngine style={{ height: 200 }} />

You can also render children or siblings as required

<GameEngine>
   <TopBarInsideGameEngine />
   <BottomBarInsideGameEngine />
</GameEngine>

//-- OR

<View style={{ flex: 1 }}>
   <TopBarOutsideGameEngine />
   <GameEngine /> //-- But in this case, screen reflects the entire screen
   <BottomBarOutsideGameEngine />
<View>

Please let me know if I've misunderstood the point you were making :)

VBT-BB commented 4 years ago

Yes I think the screen variable should reflect more the playable View, but the name "screen" would make less sense then, I currently replaced the onLayoutHandler function with my example above during a postinstall script.

Concerning the usage, I'm using the GameEngine with a top and bottom bar more like the second example you have given. Imagine being inside a SafeAreaView (from the renowned package react-native-navigation), you can see where this would cause problems, with the area behind the notches not being playable, you would add typically add margins to the game to solve the issue, but the game dimensions would then be wrong because screen uses Dimensions and not the layout sizes.

Maybe the GameEngine component could have a prop called (for example) fullscreen and a callback called onReady that would be called instantly if fullscreen (and screen would use Dimensions) and if not fullscreen, wait before calling any system and then call onReady when layout is ready and the call the systems, tell me your position on this :)

bberak commented 4 years ago

Yep, that makes total sense.. I'm leaning towards leaving screen as is, and supplying an additional layout arg to the systems and renderer.

The question is should we delay calling the systems (and renderers) until layout is determined.. I think this will be fine, because it's almost instant - and will avoid users having to check for layout and performing evasive actions:


//-- I imagine this will be error-prone.
if (layout)
    return null; 

return <View style={{ width: layout.width * 0.2, height: layout.height * 0.2 }} />
bberak commented 4 years ago

Hi @VBT-BB,

I've just pushed a branch with my initial code for this branch.. I'll need to do some testing, but if it goes well - I'll publish to npm. The renderers and systems will receive an additional layout prop.

You can give it a go using:

npm install --save git+https://github.com/bberak/react-native-game-engine.git#layout

Let me know if you happen to notice anything strange.

I'll work on remove the componentWillReceiveProps warnings after this is released.

Cheers!

bberak commented 4 years ago

Hi @VBT-BB,

I've just released version 0.14.0 that addresses this issue.

Cheers!