Document stub.png 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
An example of such game.

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. For example, fitting a huge room in a small space, or going up a set of stairs takes the player down a level. The possibilities are endless.

Scripting

Sprites

Non euclidean player.png
Non euclidean short wall.png
Non euclidean long wall.png

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 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 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: