Difference between revisions of "Dealing with multiple Modules and Screens"
Line 30: | Line 30: | ||
} | } | ||
} | } | ||
+ | |||
+ | CubeOS maintains a concept of "places" which consist of a cube face (numbered 0-5) and a position on the face (numbered 0-3). The screen capture below from the emulator shows the relationships on starting an app after clicking on "0" at the upper right in the emulator to reset the cube geometry to default. | ||
+ | |||
+ | [[File:CubeMapping.jpg|border|Cube Layout]] | ||
Here I will soon explain | Here I will soon explain |
Revision as of 17:58, 21 May 2023
This page covers various topics in dealing with the eight different modules, each with three screens, in a WOWCube. Remember that each module has its own processor and screens and generally does not have a "direct connection" to any of the other modules.
Contents
Physical cubelets and "virtual" mapping to them
For this exercise:
- Start the WOWCube Emulator manually
- Left click the "0" at the upper left of the emulator screen to ensure the cube is arranged back to its default topology
- Start a new empty Pawn program (step by step how to in VSCode)
- Insert the code below into the ON_Render() routine (no other code is needed)
- Build and run the program so it loads and runs in the emulator
public ON_Render() { new screen; new facelet[TOPOLOGY_FACELET]; new place[TOPOLOGY_PLACE]; for (screen = 0; screen <=2; screen++) { facelet.module = SELF_ID; // module on which this code is running facelet.screen = screen; place = TOPOLOGY_getPlace(facelet); GFX_setRenderTarget(screen); GFX_drawText([ 40,40 ], 8, 0, 0, TEXT_ALIGN_LEFT_TOP_CORNER, 0xFF0000FF, "module: %d", SELF_ID); GFX_drawText([ 40,80 ], 8, 0, 0, TEXT_ALIGN_LEFT_TOP_CORNER, 0xFF0000FF, "screen:%d",screen); GFX_drawText([ 40,120 ], 8, 0, 0, TEXT_ALIGN_LEFT_TOP_CORNER, 0xFF00FF00, "face: %d", place.face); GFX_drawText([ 40,160 ], 8, 0, 0, TEXT_ALIGN_LEFT_TOP_CORNER, 0xFF00FF00, "position:%d",place.position); GFX_render(); } }
CubeOS maintains a concept of "places" which consist of a cube face (numbered 0-5) and a position on the face (numbered 0-3). The screen capture below from the emulator shows the relationships on starting an app after clicking on "0" at the upper right in the emulator to reset the cube geometry to default.
Here I will soon explain
- module/screen vs face/position
- how face/position changes as you rotate slices of the cube and when a program is started on the cube
- a strategy using these to code a map of what should appear on each cube screen at startup, that using the "place" functionality is guaranteed to show up the same way at application startup no matter how the cubelets have been repositioned
The magic of TOPOLOGY_getAdjacentFacelet()
In my RPG, the "party" moves through a maze of roads or tunnels. As the party approaches the edge of a screen, it will try to go off the edge, to the screen adjacent to that edge. How can we determine where the party is "going"?
We assume you know, based on the coordinates of the party, which edge it is going to go off of.
- If the X coordinate is approaching 240 from an original lower number, you are going to go off the RIGHT edge
- If the X coordinate is approaching 0 from an original higher number, you are going to go off the LEFT edge
- If the Y coordinate is approaching 240 from an original lower number, you are going to go off the BOTTOM edge
- If the Y coordinate is approaching 0 from an original higher number, you are going to go off the TOP edge
Accordingly, you can use the routine TOPOLOGY_getAdjacentFacelet() to determine the new module # and screen # you will be moving to, using the appropriate NEIGHBOR_xxx parameter.
Example handling for moving off the bottom edge:
new facelet[TOPOLOGY_FACELET] new facelet1[TOPOLOGY_FACELET_INFO];
if (partyLocation.y > 230) { facelet.module = partyLocation.module; facelet.screen = partyLocation.screen; facelet1 = TOPOLOGY_getAdjacentFacelet(facelet,NEIGHBOR_BOTTOM); partyNewLocation.module = facelet1.module; partyNewLocation.screen = facelet1.screen; }
After this code executes, partyNewLocation will contain the module and screen of the "destination" and I can erase the party marker at partyLocation and redraw it at partyNewLocation.
If the new module is the same as the old/current module, the code on this module can perform those redraws. If the new module is different than the old/current module, the current module can erase the party marker at partyLocation, but must send a message to the new module to tell it to take over managing the party location and draw the party marker on the new screen.
In the RPG, I also need to know if the receiving edge of the new module/screen has a tunnel opening for the party to enter, if not it can't leave the edge of the screen! How do I determine this?
By using TOPOLOGY_getAdjacentFacelet(facelet,NEIGHBOR_BOTTOM) again!
In the above case, knowing I am moving off the BOTTOM of the current screen/module, I can check if there is a tunnel opening on the top of the receiving screen/module. Some trickiness is involved because that screen is likely rotated with respect to the current module, so I can't just use NEIGHBOR_TOP on the receiving screen. Instead, using the NEW screen and module as the starting point, I can find which edge of that screen takes me "back" to the original screen. Once this is determined, I can verify the appropriate cell on that screen has an "open tunnel":
entryIsPossible() { // assumes validBoundsOnScreen has been set with the cell map for the destination screen facelet.module = partyNewLocation.module; facelet.screen = partyNewLocation.screen;
facelet1 = TOPOLOGY_getAdjacentFacelet(facelet,NEIGHBOR_LEFT); if ((facelet1.module == partyLocation.module) && (facelet1.screen == partyLocation.screen)) { // left entry on dest return validBoundsOnScreen[3];; } facelet1 = TOPOLOGY_getAdjacentFacelet(facelet,NEIGHBOR_RIGHT); if ((facelet1.module == partyLocation.module) && (facelet1.screen == partyLocation.screen)) { // right entry on dest return validBoundsOnScreen[5]; } facelet1 = TOPOLOGY_getAdjacentFacelet(facelet,NEIGHBOR_TOP); if ((facelet1.module == partyLocation.module) && (facelet1.screen == partyLocation.screen)) { // top entry on dest return validBoundsOnScreen[1]; } facelet1 = TOPOLOGY_getAdjacentFacelet(facelet,NEIGHBOR_BOTTOM); if ((facelet1.module == partyLocation.module) && (facelet1.screen == partyLocation.screen)) { // bottom entry on dest return validBoundsOnScreen[7]; } }
How to handle moving from one screen to another (on the same or a different cubelet)
Content coming soon!
Dealing with differing orientation of the screens
Content coming soon!