Improving Digger Part 2
The main reason that I started this blog was to showcase my audio skills. So let's add some sound to digger.
Before we do that, then a little bit about graphics and scaling and coordinates and stuff. If you are only interested in the audio part then scroll down a bit.
I have spent a good few hours trying to get the game to scale so it fits nicely in the webpage. The first version always created a canvas that was the same dimensions as the game.
let SPRITE_W = 20;
let SPRITE_H = 20;
let X_MAX = 20; // number of grid columns
let Y_MAX = 15; // number of grid rows
createCanvas( SPRITE_W * X_MAX, SPRITE_H * Y_MAX);
So the canvas is created with dimensions 400 x 300
The number's don't really matter as long as you can scale and I thought I could do that by using the width and height attributes in the iframe that embedded the sketch. But it just didn't work perfectly. I tried everything.
Here is the iframe from Part 1
<iframe
src="https://openprocessing.org/sketch/2328338/fullscreen"
width="100%"
height="300">
</iframe>
It kind of works, but sometimes the canvas is bigger than the iframe and you need to scroll to see the whole game, not a good experience.
Originally in java processing then you had to have a fixed window size and it was set once and only once in the setup() function. Like this.
void setup() {
size( 640, 480 );
}
You couldn't even use variables or even a named constant when you called size() because it was not really a function but some kind of macro that was expanded when you compiled.
In p5js you can create a canvas so that it fits exactly it's parent container and you do it like this
function setup() {
createCanvas( windowWidth,windowHeight );
}
You can even resize the canvas if the window size changes, say you resize the browser window or tilt your phone so it changes from landscape to portrait
function windowResized() {
resizeCanvas( windowWidth,windowHeight );
}
That's more or less the easy part because now you need to scale the game which is still a fixed size onto the canvas. I've added helper functions to do that. You can start with this function if you are interested now.
function centerGameInCanvas() {
let gameAspect = gameWidth() / gameHeight();
let canvasAspect = windowWidth / windowHeight;
if ( gameAspect > canvasAspect ) {
gameScale = windowWidth / gameWidth();
}
else {
gameScale = windowHeight / gameHeight();
}
gameTranslateX = 0.5 * ( windowWidth-gameWidth()*gameScale );
gameTranslateY = 0.5 * ( windowHeight-gameHeight()*gameScale );
}
gameScale, gameTranslateX and gameTranslateY are used to position so it scales, maintaining aspect ratio and is as big as it can be and completely fit in the canvas.
function draw() {
push( );
translate( gameTranslateX, gameTranslateY );
scale( gameScale );
let coins = draw_tiles();
if ( coins == 0 || ( dig_pos_x == enemy_pos_x &&
dig_pos_y == enemy_pos_y ) ) {
initGame();
}
if ( (frameCount%speed)==0 ) {
updatePlayer( );
updateEnemy( 1 );
}
pop( );
}
The draw function now uses the translate and scale to fit the game into the available space.
Adding Sound
Lets start by adding a sound some sound effects. We could just play some sounds in the form of small audio samples. This is quite easy but lets use simple oscillators and noise generators instead. As this is a kind of retro game, beeps and white noise would work very well.
First of all we need to enable the p5js sound library. There is a menu in openprocessing for this.
let osc;
function initSound( ) {
if ( osc )
return;
osc = new p5.Oscillator( 'square' );
osc.amp( 0.0 );
osc.start( );
}
function playBeep( frames, freq ) {
if ( !osc )
return;
osc.freq( freq );
osc.amp( 0.2 );
osc.amp( 0, 0.0, 0.1 );
}
We can use a simple square wave oscillator for an old skool vibe. It's important to call initSound( ) from a user interaction if you want it to work in a browser. Otherwise it will be muted.
function keyPressed() {
initSound( );
digger.turnRight( );
}
function mousePressed() {
initSound( );
digger.turnRight( );
}
We can trigger the sound in when we update the player and enemy.
if ( ( ( frameCount - 3 ) % speed ) == 0 ) {
updatePlayer( );
updateEnemy( 1 );
playBeep( 2, 64 + frameCount % ( speed * 2 ) );
}
Subscribe to my newsletter
Read articles from Alexis Farmer directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by