cottontshirtz

LD 38

P L A N E T O R U S Retrospective

"Wait, how did you ...?"

My approach to making games has always been focused on solving problems I consider interesting. In that same vein, this post is focused on those aspects of my entry P L A N E T O R U S that I found interesting and enjoyed solving. As a disclaimer, a lot of the code in this post can no doubt be optimized or in some cases replaced with analytic solutions; but that's how game jams go.

Before reading on, I suggest you take a chance to play my entry so this post has context.

https://ldjam.com/events/ludum-dare/38/planetorus

How to Address the Torus Surface

The surface of a torus can be represented as a 2D surface which wraps around at the seams. Towards this end we can define a rectangular map with an arbitrary MAP_WIDTH and MAP_HEIGHT. These lead to a MAJOR_RADIUS and MINOR_RADIUS for the torus as calculated below. MAJOR_RADIUS = MAP_WIDTH * Mathf.PI * 2 MINOR_RADIUS = MAP_HEIGHT * Mathf.PI * 2 A 2D location on this map can be converted to a location in 3D on the surface of the torus with the following procedure.

``` public static Vector3 get3DLocationFor2DLocation (Vector2 mapLocation) {

    float vertAsRad = (mapLocation.y / MAP_HEIGHT) * (2 * Mathf.PI);
    Vector2 minorCircle = new Vector2 (Mathf.Cos(vertAsRad), Mathf.Sin(vertAsRad));
    minorCircle *= MINOR_RADIUS;

    float horzAsRad = (mapLocation.x / MAP_WIDTH) * (2 * Mathf.PI);
    Vector2 majorCircle = new Vector2 (Mathf.Cos (horzAsRad), Mathf.Sin (horzAsRad));
    majorCircle *= MAJOR_RADIUS;

    Vector3 result = new Vector3 
        ( majorCircle.x + (Mathf.Cos(horzAsRad) * minorCircle.x),
          minorCircle.y,
          majorCircle.y + (Mathf.Sin(horzAsRad) * minorCircle.x)
        );

    return result;

} ```

Essentially, we find the x,y map location as a ratio of the map width and height; which are then converted to radians, horzAsRad and vertAsRad. These two ratios can then be turned into separate 2D locations on the major circle and minor circle respectively. These two 2D circle locations are then added together. The major circle is treated as laying flat in the xy plane. Note that the x component of the minor circle is transformed before addition, as the position along the major circle determines its orientation in 3D space.

Torus_Diagram.PNG

To correctly orient objects along the surface of the torus we also need to know the normal vector for a given location on the torus map. This was achieved by normalizing the offset from the 3D location retrieved from the function above and a 3D location on the major circle; though in retrospect there are more efficient methods by which to calculate the surface normal.

Moving objects along the surface of the was achieved using a simple 2D RK4 integrator; the details of which I won’t include here, but see the link below for more details.

http://gafferongames.com/game-physics/integration-basics/

This however lead to an issue: moving horizontally on the torus map would give different 3D velocities depending on the vertical component of the 2D location. Mapping from the 2D rectangle to the 3D torus introduced distortion which affected the horizontal components of distances; luckily this distortion could be represented and corrected in the evaluation step of the RK4 integrator by scaling the x component of the entity’s torus map velocity by a factor given by the following function:

``` public static float getHorizontalMapDistortion (float verticalPosition) { float vertAsRad = (verticalPosition / MAP_HEIGHT) * (2 * Mathf.PI); float offset = Mathf.Cos(vertAsRad);

return 1 - (offset * (MINOR_RADIUS / MAJOR_RADIUS));

} ```

In effect, this function returns the ratio between the radius of the major circle and the radius of the circle created by a horizontal line placed at the given vertical position on the torus map.

With these functions available it became easy to orient entities on the torus surface along their direction of travel. This was handled by the inbuilt Unity function Transform.LookAt(Transform target, Vector3 worldUp), which rotates the operand transform so its forward vector aims at the target transform and then rotates the operand transform so its up vector aims in the direction given by the worldUp parameter. The target transform was an empty object whose position was set by the get3DLocationFor2DLocation function; the parameter to which was the entity's 2D position plus its normalized velocity. The value of the worldUp parameter is the surface normal for the entity's position on the torus surface.

Positioning the camera above the player object was done by directly setting the camera’s position to be some distance along the normal vector from the player’s current position. The camera’s orientation was set by the Transform.LookAt() function; though the camera’s own up vector, transformed into world space, was used as the worldUp parameter. This allows the camera to smoothly follow the player around the surface without any jarring discontinuities in orientation or position.

Controlling Entities on the Torus Surface

One problem which gave me considerable trouble was that of relating camera local directions to directions on the torus surface. After a few dead ends, the procedure that is present in the final game is as follows: find a local 3D basis for the torus surface in world space, take a camera local direction and transform it into world space, and find the projection of this camera local direction onto the local 3D basis for the torus surface. This local 3D basis for the torus surface is constructed for a given location on the torus map and is comprised of the surface normal at the given location, and two 3D offsets found by adding to the horizontal and vertical components of the given torus map location. This set of vectors is then orthonormalized with the inbuilt Vector3.Orthonormalize() function. In effect, this set is used to describe the 3D directions which correspond to the up and right directions on the torus map.

There is a useful assumption that can be made; the camera is positioned along the surface normal and is oriented so that its forward vector is parallel with the surface normal. Due to this assumption, we can ignore the z direction of the camera and the vector in the local 3D torus surface basis which corresponds to the surface normal. This means that our directional input is constrained to the camera local xy plane. We use the inbuilt Transform.TransformDirection() function, which maps the input direction from camera local space to world space. From here we can project this direction onto the two remaining vectors in the local 3D torus surface basis by taking the dot products of this world space vector against the right and up vectors respectively.

``` Vector3 torusHorz = ToroidMap.getTorusMapRightDirection (this.torusMapPos); Vector3 torusVert = ToroidMap.getTorusMapUpDirection (this.torusMapPos); Vector3 torusNorm = ToroidMap.getNormalVectorForMapLocation (this.torusMapPos);

Vector3.OrthoNormalize (ref torusNorm, ref torusVert, ref torusHorz);

Vector2 torusMapDirection = new Vector2 
(   Vector3.Dot (worldSpaceDirection, torusHorz), 
     Vector3.Dot (worldSpaceDirection, torusVert));

```

This procedure allows the player to indicate directions for movement and weapons fire in 2D intuitively. In retrospect, there is an analytic solution to finding the local 3D surface basis.

Summary

I very much enjoyed LD 38, and I was pleased with the end result of my entry. As with any game jam, there are always things I would have approached differently if I were to create this again. I hope this post has answered any questions about the implementation of this game you may have had.

LD 42

LD 42 Entry

Seems to be that putting a blog post first of the way to go, and it's a good way to get some things out of the way in regards to my project.

I'm entering into the jam solo with an idea and design in mind. It's likely that the theme won't align with this idea, but I will be moving forward with it regardless. Some early experiments have been conducted to make sure it's possible, but the code itself will be written I've this weekend.

I'm looking forward to working on this project and sharing feedback with other game nerds!

Well, that wasn't a good time

After fighting dumb concurrency issues all weekend I'm going to call it. The resulting code works quite well (despite being more convoluted than a Kojima plotline), but it almost entirely lacks features that make it a game. You can't do anything but move the camera and admire that the nothing that you can do is at a pretty solid 60fps (occasional stutter due to GC though). I don't plan on uploading anything, though I may work on it for a while longer to get a real game out of it. Maybe I can trick people into reviewing it some other time.

Ludum Dare 45

Is anyone else planning on using Tobii eye tracking for their game?

Is anyone else planning on using Tobii eye tracking for their game? We could review each other's games!

If you are planning on using Tobii eye tracking for your game I will gladly review your game, including those features that require use of the eye tracker. I am planning oun using Tobii eye tracking for my game, and while I plan to have a backup for those features that require eye tracking, I am hoping other people with the necessary peripherals are participating in this LD.

Please comment on this post of you're interested in sharing reviews. Hopefully we can get a whole group of people!

Is anyone else planning on using Tobii eye tracking for their game?

Is anyone else planning on using Tobii eye tracking for their game? We could review each other’s games!

If you are planning on using Tobii eye tracking for your game I will gladly review your game, including those features that require use of the eye tracker. I am planning oun using Tobii eye tracking for my game, and while I plan to have a backup for those features that require eye tracking, I am hoping other people with the necessary peripherals are participating in this LD.

Please comment on this post of you’re interested in sharing reviews. Hopefully we can get a whole group of people!

Tobii Review Swap!

If your game uses Tobii eye tracking I will review it! Similarly, if you have the Tobii eye tracking device, I have a game that tries to make the best of it!

https://ldjam.com/events/ludum-dare/45/all-but-starlight-here

Comment some links and I'll review your game!

Include your game link and a short description and I'll be sure to review.

In the meantime, check this one out!

https://ldjam.com/events/ludum-dare/45/all-but-starlight-here

28bb1.png

Ludum Dare 46

LD: Nice reason to make something!

Been in quarantine for 5 weeks so far, any excuse to make something is welcomed. Can't guarantee I'll follow the theme, but who knows.

Trade Reviews?

Add a link to your LD entry in a comment and I'll review it!

In the meantime, give this a shot!

https://ldjam.com/events/ludum-dare/46/planetorus2

Ludum Dare 47

I'm in

Glad to have something to distract from everything else for a bit.

Going to try something grid-based and turn-based to avoid the trap of game feel polishing I always fall into.

Pretty good first day

DayOneDev.png

There's not much logic behind it at the moment, but the foundation is in place! (The color palette is also a placeholder, but it's growing on me)

Abstract Local Multiplayer Competitive Strategy Game! Playable in Browser!

Cover.png

Woodstone_02 is a local multiplayer competitive strategy game where you strive to control the board and deliver devastating blows to your opponent!

As this is a local multiplayer game, players will have to pass the mouse back and forth based on whose turn it is. Also, the tutorial is on the itch page, not in the game itself.

https://ldjam.com/events/ludum-dare/47/woodstone-02

Still need reviews? Me too! Let's do a review swap!

Add your game in a comment below and I'll be sure to get to them all before the rating period ends.

In the meantime, please check out my game:

https://ldjam.com/events/ludum-dare/47/woodstone-02

0wYXKx.png

Still need reviews? Me too! Let's do a review swap!

Add your game in a comment below and I'll be sure to get to them all before the rating period ends.

In the meantime, please check out my game:

https://ldjam.com/events/ludum-dare/47/woodstone-02

Tut_UI.png

Ludum Dare 48

Theme-ing

Picked themes that should leave space for creativity and may lead to some interesting submissions!

Screenshot_20210305-110907.png

Ludum Dare 49

Orthoptera!

After a grueling 72 hours of free pizza and ignored obligations, Orthoptera is finished!

Jump and glide your way between bug villages to save everyone!

IntroScreenshot.png

Ludum Dare 50

Soon

CrabBattle.png

Sooner

BonkResized.gif CrabBattle.png

Soonest (now)

CrabBattle.png

https://www.youtube.com/watch?v=NYYzy6I1Anc

https://ldjam.com/events/ludum-dare/50/crab-battle

https://cottontshirtz.itch.io/crab-battle