project[2]
0344034.
BDCM
.Experiential Design
::project[2]
project[2]: Prototype
todo:
- Create a prototype of the proposal
implementation:
Interpreter
World to grid
This was the main algorithmic challenge brought up by Mr. Razif when discussing my proposal. My stubborn headass instead took it as a challenge. With game on, I took what I knew I could use for tokenisation from traditional compilers, & started my base — CardNode. Uniquely to Buddies’ One-of-a-kind Walking Language (BOWL), card tokens can actually appear in 2 dimensions. This means a simple doubly-linked node can't cut it — it's a job for the quadruply-linked node, linking top-bottom & left-right.
Actually constructing a grid from the nodes was the real meat of the challenge though. For this, after some silent thought, I came up with probably one of the worst algorithms for it. This is a simplified implementation:
- For each
nodesasnode- For each
edgesasedge- Let
nearestDistancebe Infinity - Let
nearestNodebe None - Let
prevDistancesbe all the distances of the surrounding nodes to this one, before thenodemoved - Move
nodelocally towards theedge - Let
currDistancesbe all the distances of the surrounding nodes to this one, after thenodemoved - For each [
currDistances,prevDistances] as [currDistance,prevDistance]- If
currDistanceis less thanprevDistance&currDistanceis less thannearestDistance- Set
nearestDistancetocurrDistance - Set
nearestNodeto node that iscurrDistanceaway fromnode
- Set
- If
- Link
nearestNodeatedge
- Let
- For each
NOTE
The above implementation makes a few assumptions:
1.nearestNodewill only ever appear once, & when linking, it's not present at otheredges 2. The distancenodemoves locally is the minimum distance between every node
For the full implementation, see Assets/Core/Card/CardGrid.cs
It's kind of, so stupid, that it wraps around to being elegant!
Tokenisation
After a lump of qudruply-linked card nodes, a proper data structure, more easily traversable, is required. Despite the heading, the card grid construction is definitely part of the overall tokenisation process... & I totally could've combined this with process with it. Whatever, I'm stupid, sue me.
Besides mapping over the card nodes' kinds into a jagged array, deduplication is also done if the tokeniser finds two of the same kinds stuck to each other, forming one card.
TODO
Yeah, that's a bug. If a player places two same top cards, the tokeniser will dedupe it into one card, & thus collapsing the two actions into one. Too bad, this a prototype & the repo is public, fix it yourself.
Interpreting
No ASTs or IRs, because that would be stupid for a card game; the tokens are all simply interpreted.
The interpretation itself is pretty straight forward as the cards map over to pretty simple logic in C# land. I used a few compiler-esque seeking functions here too like Eat & Until, not sure what they're supposed to be called thought, but I learnt them by combing through svelte's compiler. Why am I telling you this? Dunno.
There is one big thing of note here, which is the algorithm that detects when there is an infinite loop. The only reason the Turing Halting problem doesn't apply here is the simple assumption that if buddies' positions loop, they cannot ever reach the end. A simplified implementation of the algorithm can be described with a simple sentence — if the end of a set of sequential positions intersect with the start of the another set of sequential positions with the same combination, in a list of every single outputted position, then terminate. Elegant right?? Some little sh*t have probably written a whitepaper on this in the 60s, but I came up with it again alone in my bedroom, & I feel pretty proud of it.
Another notable implementation detail is also how parse errors are handled. They are thrown in the innards of the interpreter & caught from the public #Interpret* methods, which then bubble up to be displayed by whatever should handle it.
Targets
Behaviour
Every image target imported into Unity from the Vuforia database will have this TargetBehaviour component on it. It assigns them a kind & also propagates the events triggered by Vuforia into grid updates in TargetController.
Controller
The controller, implemented as TargetController is the central brain managing the targets. It keeps track of every target that is found & lost, updating the card grid as they change. A perpetual, per second tick is also fired from the controller to update the card grid.
Level
Field
The field holds the actual state of the level, & is the context object used by the interpreter. This includes the success states, events, & buddies positions.
Tiles
The tiles shown in the game are programmatically generated based on pre-defined levels.
Controller
The main brain controlling the level, constructing the objects as the game Awakens, spawning toasts as the game Starts, centre the level tiles on the card grids as the game Updates. The main grunt of the logic its responsible lies in OnGridUpdate which is invoked, when the grid updates (duh). It tokenises the level field, & runs the interpreter on it, handling any errors with a floating toast, & successes with an animation (using my own Bezier & Tween implementation!) + toast.
Scenes
FtueScene
The "First time user experience" (StrictPascalCase gang) houses the initial experience of a new player, with UIs that spawns each other using ReplaceSelfHook#ReplaceSelf().
MainScene
The main scene with the AR shenanigans. It contains all the potential targets objects, a canvas for the help & the programmatically generated minimap, & as well as all the required dummy objects which housed the controllers & toast canvas.
final:
Figure 1.2.2, Proposal video walkthrough, 6/7/2022
reflection:
The experience overall was, pretty fun. Was not expecting things to be pleasant at all, but I guess both C# & Unity's API are battle-tested enough to facilitate dummies! As I proceeded through setting scenes up & scripting them out, whilst there were bumpy spurts of road & high hilltop terrain, the ratio of easy to hard is quite baffling; great productivity is facilitated.
The main things I learnt here was definitely the ability to utilise Unity to create game-like prototypes that functioned with AR. The AR concept whilst still quite foreign & abstracted away via Vuforia, really does open up doors to potential new ways of game design & creation. I also learnt how much I surprisingly liked C#. Whilst it is very unfortunate Unity's runtime lags behind the bleeding edge of C# language features, like multiline strings & perhaps even the required keyword, it still provides a broad set of language features that put Java to pure-OOP shame.
At the end of the day, I know whatever I've learnt from this project will be used by me the future for game prototypes & even jams or jellies. Again, was a very challenging & taxing experience, but not one I would prefer to be without.





Comments