Represents meteor impact recordings across the globe, each hit represented as a point of varying size and colour, corresponding to its mass. Allows users to hover each point to view more information. Data is provided by a TOPOJSON API and is scalable in that the size variations are evened out by a logarithmic function.
A Force Directed Graph showing state contiguity for all countries in the world. Force directed graphs (FDG’s) represent data as nodes on a meshwork and give the user the ability to drag and hover individual nodes to see the country name.
The Game of Life by the mathematician John Horton Conway in 1970 is a zero-player game based on replicating cellular autonoma. this post details three different versions I made and the reason why for each.
The Game of Life presents an N sized grid where each cell has two possible states, alive or empty (dead). With each game tick, the cell can change state or remain as it is based on the number of cells around it. A cell with too many neighbours will die of overpopulation, a cell with too few will die without ‘civilisation’ to sustain it. Cells with the right amount of neighbours will come alive and so on.
In this way, the Game of Life, a Turing Complete model in which each generation is a direct result of the previous state, is the perfect challenge for a state-building exercise.
My first version took a number of weeks, built in React, it helped me learn fundamental algorithm concepts and state-management techniques which would come in useful later.
I revisited this project again years later, reproducing it in a couple of hours, determined to make a cleaner, more robust rendition. At the time I was working with WebGL and three.js, so went back one more time to create a 3D game inspired by the 2D Game of Life.
I’m going to take a ‘poking fun’ approach to talking about these, I believe a little bit of mocking you’re old work is good for illustrating how much has changed since then, and appreciating the quirks of the learning process.
Remember kidos, in learning, there’s no such thing as “bad code”, just code that hasn’t seen growth yet.
Version One: October 2017
This original game, submitted as part of the freeCodeCamp challenge, came straight after the Recipe List and came with a steep learning curve for me.
I knew that I needed a table-like layout for rows and columns, I was familiar with using array’s and .map() but was yet to learn that you could make arrays of JSX and just… dump them in where you need them. I thought there was something magical about an inline array.map. 🤷♀️ This lead to some interesting patterns such as creating an N-sized row or column with and N-sized array in state.
<Table /> acted as the game renderer and controller, a pattern which would stick in future projects. It’s state held a ticker which would advance by one with each generation. It rendered a table by looking over the arr state item above twice (you were locked into square layouts) and rendered <Cell /> components.
Following the idea that “components should be self contained”, each <Cell /> had it’s own internal life state (nice)… and then on mount, writes this state to a ‘global’ object (i.e. outside the react tree) (not nice) with the following format string as a key: ‘”‘ + “col-” + this.props.colId + “-row-” + this.props.rowId + ‘”‘. 🤮 Don’t ask me why the quote marks are in double brackets because I cant remember.
Cells each had a method to look at adjacent cells in this global object and calculate their next state, which was hard coded because ofcourse.
The last anti pattern was that this function was called when the lifecycle method componentWillReceiveProps was called, i.e. when the ‘tick’ being passed down from the board went up.
Now this idea to tick a game forward in itself isn’t too bad, though it should have used componentShouldUpdate and checked that the new tick was changed. The issue here was that every cell, updating itself, was reading and writing from the same object. The cell does not know how much of the board is from the previous generation and how much form the last. Also, the fact that the globalObject existed outside the react app meant that it existed outside of the application lifecycle structure which could exacerbate this issue.
Remarkably though, it works most of the time.
Somehow, unless my machine is running slower than usuual, the cell updates sync in such a way that the game behaves as it should. the submission was accepted but this always bugged me, it haunted me, it’s remaking was inevitable.
A big thing I took away from this project that I hope could benifit others who may read this is that this potential cell de-sync issue was not enough to wreck the project. The code is duck-taped together in so many ways, its highly innefficient and jumbled but it works.
Often times I see people who achieve things and don’t allow themselves credit becuase they believe they somehow cheated or missed the point of the project. Its a part of imposter syndrome; they think that there is some sort of universally accepted correct structure that they were supposed to find but didn’t and are soon to be revealed as a fraud.
In my view this is how we get into innane discources such as “is HTML a programing language” or “this site design is invalid becuse you used a CSS framework”. In industry, clients generally don’t care whats gone on behind the scenes, they just care about the specification and the end result. To quote my favourite TV show, if you are asked to make somthing which behaves in a certain way then…
Coding isn’t the thing, its the thing that gets us to the thing.
Version Two: April 2019
It took longer than I thought for the urge to remake the game to finally take hold (other stuff took precedent).
This new game was built with create-react-app and included Redux. This time, the store had a two main keys board which contained data relating to the board display and control which controlled UI elements (in the end this was only used for the ‘paint’ mode, allowing users to write to the board).
The board was a two dimensional array with cell objects inside. Each cell object stored its x-y position and an ‘alive’ property. The reducer for this section only had two actions, one to manually change the state of a cell (for painting) and one which would loop over the whole board, calculate the new state for each cell, then write this new state to an entrely new board array, thus achieving feed-forward imutability.
The <Board /> class had two properties, one to generate rows by calling the next which would generate cells. <Cell /> classes still performed the check individually to see how they should render and would listen for mouse events to paint the board.
And that’s it, cells update when they need to, React takes care of that, the controller component dispatches to tick the game forward, and the files are simple and light apart from the enormous bundle size of create react app.
There were still questions as to whether performing the board loop calculation within the reducer violated Redux’s pure function policy; that reducers should be pure functions and do little work. Despite this, the function would produce the same outcome every time and has no side affects so it is still pure in that sense.
Regardless, this was the remake that I had wanted to do since forever, and it only took a couple of hours, as opposed to approximately a week for the previous.
But I wasn’t finished.
Version Three: May 2019
Around this time I had been investigating WebGL and three.js for a potential project with Matter of Stuff, where I was an intern for my Diploma in Professional Studies (DPS).
One of my little experiments involved creating a ‘voxel builder’, a simple grid space where you can place blocks in 3D.
I took the board state, extended it to a three dimensional array and wrote a function to map to the 3D grid space. I extracted the looping function and created a simple adaptation to run outside of React-Redux (which this project does not use). Lastly, I modified the rule set to return an alive cell if the number of neighbours was as follows: 5 <= num <= 9.
The result is this, a fully 3d rendition of the Game of Life. The rule set could use tweaking given that the cells tend to bubble outwards and oscillate around the edges. And of course you do not benefit from Redux’s immutable patterns.
Never the less I was pleased with the result which went on to influence a range of projects which took place thanks to Matter of Stuff.
The app replicates Pinterest’s masonry layout using react-masonry, allowing cards to create that cobblestone look, slotting into one another. Pins can be re-pined by new users, added to boards and have likes and comments posted.
The front-end was built using React-Router for pagination and to split the various aspects of functionality.
The name was a joking placeholder on the observation that Pinterest’s once usable format was heavily modified and moved from it’s original format in the name of increased advertising and ‘engagement’. “Interest” meaning more click through’s instead of meaningful curation is replaced with “Apathy”.
The Zugriff (German word for bridge) is a conceptual product imagining if the opto-electronics Goliath Carl Zeiss AG moved into the field of portable audio.
Carl Zeiss AG has been a sector leader for over 100 years, manufacturing lenses, optical products and specialising in the manufacture of micro-electronics (by way of their optics). A large and sterile brand, their ‘image’ is quite hard to place, certainly they wish to put forward an image of loyalty, stability and enabling but how much of that actually shines through their work?
I decided that in the highly unlikely case that Zeiss broke form their optics-only model, such a speaker would want to embody the values of versatility, perhaps linking to their large sports-optics range. It should embody a ‘quirky’ high technology functionality and should embody the stability, balance and engineering associated with other Zeiss products.
The final designed carried through a mirrored 360 hinge mechanism to allow differing modes of sound output (direction vs ambient). The unit is highly durable, made of an experimental fibre mesh aluminium and designed to compliment Zeiss’s sports optics range.
In reflection I found this project very challenging, after all Zeiss isn’t what I’d call a flexible brand. I enjoyed the chance to broaden my scope on branding and to consider the semiotic meanings and associations embodied by brands beyond simple aesthetic surface-level messaging.
The Margate Art tour is a conceptual piece of service design to link cultural hubs along the Kent coast.
Intended to strengthen the growing artistic trend, it is hoped to provide economic opportunity and regeneration.
The Margate Experience Project was a broad speculative piece, focusing on the design process as applied to a real world context.
Unit four of the course is the last unit in stage one and focuses on applying the design process to a real world context by asking us to consider the situation of Margate and how it, through design, could be improved.
The brief for this project was much more open than anything considered previously and offered a great scope for creativity, experimentation and consideration of wider socio-political factors.
I was very excited for this project, not only was it the first structured project of my return to the course but it was a chance to act on the idea of using design to effect positive change in a real-life context, to break away from the established idea of physical, consumer-based product design.
In addition, I personally had a bit of a head start in that I had visited Margate before and given some amount of thought to the basic premise of this project.
Research formed the backbone of this project to arguably a larger degree than some other past projects. This involved interviews, primary and secondary research, the creation of a ‘cultural map’ in groups, a three-day site visit and personal observations and anecdotes.
My design solution was a conceptual ferry service operating an ‘Art Tour’ around Margate, connecting visitors to key areas of cultural and artistic significance around the east coast.
The core of this idea is to place Margate at the centre of a broader artistic context and culture.
Margate has a rising art scene as personified by the greatly successful Turner Contemporary gallery but is somewhat stunted by its remote location and lack of other attractions. By offering figurative and literal links to other such locations, a coherent experience can be created centred around Margate with connections to London and Dover to entice tourists.
Reflecting back on the project I would have liked to delve deeper into specific aspects of the design like what the onboard commentary would have consisted of, more detail put into the design of the vessels and in general, added more user touch points to make the idea more unique.
In addition I think the project could have benefited from more primary research mid-way through but overall it was a greatly interesting brief to tackle.