This article or section may not have content matching Scratch Wiki editing standards. Please improve it according to Scratch Wiki:Guidelines and Scratch Wiki:Editing Conventions. (January 2020) Reason: Markup, superficial explanations, project examples given without explaining significance |
A non-Euclidean game is what game developers often term a game where the world space doesn't work the same way the real world works. It bypasses or ignores Euclidean's Postulates[1]. For example, fitting a huge room in a small space, or going up a set of stairs takes the player down a level.
Scripting
Sprites
First, two sprites need to be created: the Player and the Walls. Make the player a 27 x 27 cube. Then, make two costumes for the wall.
Note: | Copy the first wall costume and edit the left side so that the transition is seamless. |
Scripts
Now that these sprites have been created, there needs to be some logic. A basic scrolling engine will be used. First, create these global (for all sprites) variables:
(SCROLL X) (SCROLL Y)
Then, in the Player and Walls sprite, create these variables (for this sprite only):
(x) (y)
Note: | Using all caps for global variables helps to distinguish between global and local. |
Back to the Player sprite, create these scripts:
when green flag clicked //This is the only green flag block in the project. broadcast (init v) and wait //This is completed before the project starts. broadcast (game on v) when I receive [init v] //This allows the player to reset the positioning set [x v] to (0) set [y v] to (-50) set [SCROLL X v] to (0) set [SCROLL Y v] to (-50) when I receive [game on v] //This starts the only loop in the project. forever tick:: custom broadcast (tick v) and wait //This sends the loop over to the other sprites. end define tick //Run without screen refresh. if <key (up arrow v) pressed?> then change y by [5]:: custom //This is a custom block. end if <key (down arrow v) pressed?> then change y by [-5]:: custom //This is a custom block. end if <key (right arrow v) pressed?> then change x by [5]:: custom // this is a custom block end if <key (left arrow v) pressed?> then change x by [-5]:: custom // this is a custom block end position:: custom change [SCROLL X v] by (round(((x) - (SCROLL X)) / (5))) //These set the SCROLL X and SCROLL Y to the player's position, allowing the other sprites to move while the player is stationary. change [SCROLL Y v] by (round(((y) - (SCROLL Y)) / (5))) define position //Run without screen refresh. go to x: ((x) - (SCROLL X)) y: ((y) - (SCROLL Y)) define change x by (sx) //Run without screen refresh. change [x v] by (sx) position:: custom if <touching (walls v)?> then //Wall detection. repeat until <not<touching (walls v)?>> if <(sx) > (0)> then change [x v] by (-1) else change [x v] by (1) end position:: custom end end define change y by (sy) //Run without screen refresh. change [y v] by (sy) position:: custom if <touching (walls v)?> then //Wall detection. repeat until <not<touching (walls v)?>> if <(sy) > (0)> then change [y v] by (-1) else change [y v] by (1) end position:: custom end end
Now, in the Walls sprite, add this local (for this sprite only) variable:
(in/out?)
With this variable, the non-Euclidean logic can be created:
when I receive [init v] //Set the variables to the right values. set [x v] to (0) set [y v] to (0) set [int/out? v] to [out] switch costume to (short v) set rotation style [left-right v] point in direction (90) position ((x) - (SCROLL X)) ((y) - (SCROLL Y)):: custom when I receive [tick v] // run in the loop position ((x) - (SCROLL X)) ((y) - (SCROLL Y)):: custom define position (x) (y) //Run without screen refresh. set size to (200)% //Making the sprite bigger when it moves allows for smoother off screen scrolling. go to x: (x) y: (y) if <<(x) = (x position)> and <(y) = (y position)>> then in/out detection:: custom show else hide end set size to (100)% define in/out detection //Run without screen refresh. if <(in/out?) = [out]> then //Detect if the player is in, ONLY if it was previously out (helps with lag). if <<(x position) < [145]> and <([abs v] of (y position)) < [13]>> then switch costume to (long v) set [in/out? v] to [in] end end if <(in/out) = [in]> then //Detects if the player is out, ONLY if it was previously in (helps with lag). if <<(x position) < [145]> and <([abs v] of (y position)) > [12]>> then switch costume to (short v) set [in/out? v] to [out] end end
A non-Euclidean game has been created. This basic logic can be applied to any form changing tunnels.
Example Projects
Here are some examples of non-Euclidean games:
- Non Euclidean Game by maulerforminers53
- Non-Euclidean Lemon Grab Experiment by griffpatch
- Non-Euclidean Lemon Grab Raycaster by -Rex-
- Non-euclidean 100% pen platformer by magics47