This is an attempt to write a guide I wish I had access to when I was working on my 1st fxhash project in May this year. While there are already some great resources/articles available (that I will share links to below), I will focus on p5.js here and share some important tips that will ensure a successful release.
Where to begin ?
The official fxhash ‘Guide to mint a Generative Token’ is definitely the place to start. It captures all the steps to mint and publish your 1st project and provides a boilerplate template as well. However, the template is generic, and I found a p5js-specific template by TengilLejonhjarta that does some further groundwork for you so that you can just focus on p5-specific code. Having said that, this is what worked well for me (I used this template for my 2 projects on fxhash so far), and I am sure there are other (and possibly better) ways to go about it.
How to incorporate fxrand() ?
If you have been creating sketches on p5.js Web editor, the 1st challenge when transitioning your code to an fxhash project is to make it work with fxrand().
Your fxhash project must use pseudorandom number generation with a seed, where the seed is the fxhash variable. You might already have a bunch of random() and noise() calls in your script, & you don’t need to replace them all with fxrand().
One way to manage this is to define the seeds for random() and noise() based on the fxrand() value. Below is the snippet of code where I handled this in StairWaves :
console.log(fxrand()) // deterministic PRNG function
const seed = ~~(fxrand()*123456789);
p5.randomSeed(seed);
p5.noiseSeed(seed);
So for each iteration of your token, fxrand() will be value between between 0 and 1 specific to the fxhash value of that iteration. In the above code, we created a seed as a derived value of fxrand() & then made it the seed for all subsequent calls to random() and noise(). This will ensure that the same hash will always generate the same output, & different hashes will generate different outputs.
Note: The ‘p5.’ syntax prior to p5.js functions is only required if you are using the template I mentioned earlier. If not, you can just ignore the ‘p5.’ from the code snippets in this article
How to ensure outputs are consistent across screen resolutions ?
To ensure that your artwork resizes based on the screen size, you can create your canvas based on the window size in the setup() function:
p5.setup = function() {
s = p5.min(p5.windowWidth, p5.windowHeight);
p5.createCanvas(s, s);
};
In p5.js, by default pixel density is set to match display density & you can call pixelDensity(1) to turn this off in the draw() function. In my projects so far, that’s how I have approached it.
Finally, to ensure that the output re-renders correctly when window size changes, you can add in the below function:
p5.windowResized = function() {
s = p5.min(p5.windowWidth, p5.windowHeight);
p5.resizeCanvas(s, s);
}
An alternate approach that is easier to implement is that you just fix your canvas size, like below:
p5.createCanvas(1000,1000);
While this is a quick way to get started on your 1st project, this is not the recommended approach if you want your artwork to auto-scale when opened in higher resolution screens.
How to enable high resolution downloads ?
You can incorporate logic that resizes the canvas based on a key pressed by the user. The below ‘keyTyped’ function will trigger a download when ‘s’ is pressed and resize canvas to 2000px by 2000px (or 4000px by 4000px) by pressing ‘2’ (or ‘4’):
p5.keyTyped = function() {
if (p5.key == 's' || p5.key == 'S') p5.saveCanvas('name', 'png')
else if(p5.key == '2' ) {
p5.resizeCanvas(2000,2000);
}
else if(p5.key == '4' ) {
p5.resizeCanvas(4000,4000);
}
}
How to incorporate features ?
While features are not compulsory for publishing a project, they are useful in communicating how the output is designed and enable exploration of outputs by filtering certain features.
To implement them in StairWaves, I first defined some random variables that will determine what values each feature will take:
let randomness = p5.random(0,1);
let randomness2 = p5.random(0,1);
let randomness3 = p5.random(0,1);
I will explain further steps with one feature in StairWaves that determined the number of waves:
let wave_count = getWaveCount(randomness);
function getWaveCount(value) {
if (value < 0.25) return "Low"
else if (value < 0.75) return "Medium"
else return "High"
Based on the above logic, there will be a 25% probability for the wave count to be ‘Low’ or ‘High’ and 50% probability to be ‘Medium’.
Finally, you can include these features by using the below code snippet:
window.$fxhashFeatures = {
"Wave count": wave_count,
"Turbulence": bumps_category,
"Palette": palette.name,
"Uneven Surface": uneven_surface
}
How to approach testing ?
Testing is key to ensuring that your artwork loads as intended in all resolutions and scenarios. While you can extensively on your local environment, I will recommend to start testing in the fxhash Sandbox environment when core aspects of your project are completed and not leave it to the end.
While you can test different device resolutions in most browsers, there can often be gaps in how these simulators work vs the actual devices. My approach has so far has been to test the project across:
Different browsers (Chrome, Firefox, Edge), and
Different devices (Windows laptop, iPhone, iPad etc.)
Checklist for a successful drop
Apart from ensuring that technical aspects of your project work fine, there are lot of other things to consider like updating your profile on fxhash, sharing project details on Twitter and deciding your pricing strategy.
Generative artists Camille & Matthieu have put together a very thorough checklist, so I will not repeat them and recommend you to read it here.
Hopefully, the above pointers give you a good starting point. Let me know if there are any other areas that I have not covered as I intend to refine & add to this article over time.
Good luck & happy minting !
Link to my projects on fxhash here
great tips for beginners!
Thanks :)