Skip to content

Commit

Permalink
Merge branch 'nighthawkcoders:main' into VeErA
Browse files Browse the repository at this point in the history
  • Loading branch information
VeeraKalakota authored Feb 11, 2025
2 parents ca756b7 + ddf7e10 commit 7e4c171
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 40 deletions.
172 changes: 172 additions & 0 deletions _notebooks/2024-02-10-music.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "yaml"
}
},
"outputs": [],
"source": [
"---\n",
"author: Lucas Masterson\n",
"layout: post\n",
"title: So you want to add music?\n",
"description: Adding music to platformer\n",
"permalink: /music\n",
"categories: [Miscellaneous]\n",
"toc: true\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What am I doing here?\n",
"\n",
"You may have noticed a few levels have music (my personal favorite being the \"Regicide\" track from the Destiny: The Taken King OST, but I digress), and maybe you want to add that. I had the pleasure of figuring that out and now I may share my knowledge. See this [Pull Request](https://github.com/nighthawkcoders/platformer4x/pull/18)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Introduction\n",
"\n",
"Most of this capability comes from `GameEnv.js` with these static methods:\n",
"\n",
"```js\n",
"// ~/assets/js/platformer/GameEnv.js\n",
"// Play a sound by its ID\n",
"static playSound(id) {\n",
" const sound = document.getElementById(id);\n",
" sound.play();\n",
"}\n",
"\n",
"// Play a sound by its ID in a loop\n",
"static loopSound(id) {\n",
" const sound = document.getElementById(id);\n",
" sound.loop = true;\n",
" sound.play();\n",
"}\n",
"\n",
"// Stop all sounds\n",
"static stopAllSounds() {\n",
" const sounds = document.getElementsByTagName('audio');\n",
" for (let sound of sounds) {\n",
" sound.pause();\n",
" sound.currentTime = 0;\n",
" }\n",
"}\n",
"```\n",
"\n",
"I wrote the bottom two methods if you're curious. Anyway, I noticed that sound is played by its \"ID\". Well, what the heck is the id and why is it loaded from HTML (notice the `document.GetElementByID`). Took me a but longer than I should, but these IDs are loaded into HTML itself in `index.md`:\n",
"\n",
"```html\n",
"<!--Index.md-->\n",
"<!--Audio for music -->\n",
"\n",
" <!--Audio for Everlong by Foo Fighters (Winter) -->\n",
" <audio id=\"everlong\" src=\"{{site.baseurl}}/assets/audio/everlong.mp3\" preload=\"auto\"></audio>\n",
"```\n",
"\n",
"Ok, what does that do? Well, it loads a file from the filepath `{{site.baseurl}}/assets/audio/evelong.mp3` and assigns it the id `everlong`. Boom.\n",
"\n",
"Now, to play it on levels, I had to do a bit of a workaround. I didn't know where to load it to be unique to levels, so in a VERY jank workaround, I played it in upon loading the background.... Yeah not the best practice, but who'll know?\n",
"\n",
"```js\n",
"// ~/assets/js/platformer/BackgroundSnow.js\n",
"import Background from './Background.js';\n",
"import GameEnv from './GameEnv.js';\n",
"\n",
"export class BackgroundSnow extends Background {\n",
" constructor(canvas, image, data) {\n",
" super(canvas, image, data);\n",
"\n",
" // Start the background music in loop\n",
" GameEnv.loopSound('everlong');\n",
"\n",
" this.parallaxSpeed = 0.3; // Speed for vertical parallax scrolling\n",
" }\n",
"```\n",
"\n",
"Just import `GameEnv` and play the sound using `loopSound` to loop it or `playSound` if you just want to play it once."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## I want it FAST\n",
"\n",
"OK, OK, sorry for boring you with my frankly uninteresting story. Where's the code?\n",
"\n",
"1. Add an audio file to `~/assets/audio/`. For example:\n",
"\n",
"```js\n",
"// ~/assets/audio/everlong.mp3\n",
"```\n",
"\n",
"2. Load this audio file into HTML:\n",
"\n",
"```html\n",
"<!-- ~/index.md -->\n",
"<!--Audio for Everlong by Foo Fighters (Winter) -->\n",
"<audio id=\"everlong\" src=\"{{site.baseurl}}/assets/audio/everlong.mp3\" preload=\"auto\"></audio>\n",
"```\n",
"\n",
"3. Play the sound (here we use a music example):\n",
"\n",
"```js\n",
"// ~/assets/js/platformer/BackgroundSnow.js\n",
"import Background from './Background.js';\n",
"import GameEnv from './GameEnv.js';\n",
"\n",
"export class BackgroundSnow extends Background {\n",
" constructor(canvas, image, data) {\n",
" super(canvas, image, data);\n",
"\n",
" // Start the background music in loop\n",
" GameEnv.loopSound('everlong');\n",
"\n",
" this.parallaxSpeed = 0.3; // Speed for vertical parallax scrolling\n",
" }\n",
"```\n",
"\n",
"4. Done! Should work.\n",
"\n",
"\n",
"Some caveats though.\n",
"- All game sounds are automatically stopped upon level transition (I placed a `GameEnv.stopAllSounds();` inside the `transitionToLevel()` function)\n",
"- You can loop sounds using `loopSounds()` which is recommended! I used `playSound()` just for sake of example (which is more applicable to other sounds)\n",
"- Choose good sounds/music please!\n",
"\n",
"> Potentia ex nihilo.\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
8 changes: 7 additions & 1 deletion assets/js/platformer/GameEnv.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ export class GameEnv {
* @property {number} timerInterval - Variable to hold the interval reference, used by timer objects
* @property {boolean} keyCollected - Checks whether the key has been collected my Mario or not
* @property {boolean} powerUpCollected - Checks whether the powerup has been collected by the escaper sprite
*/
* @property {boolean} wandColleted - Chekcs whether the wand has been collected by the player
* @property {boolean} spellUsed - Chekcs whether the wand has been used by the player
*/
static userID = "Guest";
static player = null;
static levels = [];
Expand All @@ -78,6 +80,7 @@ export class GameEnv {
static bottom;
static prevBottom;
static invincible = false;
static visible = false;
static goombaInvincible = false;
static goombaBounce = false;
static goombaBounce1 = false;
Expand All @@ -97,6 +100,9 @@ export class GameEnv {

static trashCount = []

static wandCollected = false;
static spellUsed = false;


// Make the constructor throws an error, or effectively make it a private constructor.
constructor() {
Expand Down
9 changes: 2 additions & 7 deletions assets/js/platformer/GameSetterQuidditch.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ const assets = {
height: 6000, // 204
scaleSize: 10, // 80
speedRatio: 0.7,
opacity: 0,
hitbox: { widthPercentage: 0.4, heightPercentage: -0.2 }
},
},
Expand Down Expand Up @@ -129,10 +128,6 @@ const assets = {

};

setTimeout(() => {
alert("Collect wand to progress to next level!");
}, 2000);

// Quidditch Game Level defintion...
const objects = [
// GameObject(s), the order is important to z-index...
Expand Down Expand Up @@ -183,7 +178,7 @@ const assets = {
{ name: 'coin', id: 'coin', class: Coin, data: assets.obstacles.snitch, xPercentage: 0.375, yPercentage: 0.7 },
{ name: 'coin', id: 'coin', class: Coin, data: assets.obstacles.snitch, xPercentage: 0.409, yPercentage: 0.7 },
{ name: 'coin', id: 'coin', class: Coin, data: assets.obstacles.snitch, xPercentage: 0.295, yPercentage: 0.46 },
{ name: 'itemBlock', id: 'JumpPlatform', class: JumpPlatform, data: assets.platforms.itemBlock, xPercentage: 0.5999, yPercentage: 0.6}, //item block is a platform
{ name: 'wand', id: 'JumpPlatform', class: JumpPlatform, data: assets.platforms.itemBlock, xPercentage: 0.5999, yPercentage: 0.6}, //item block is a platform
{ name: 'chocoFrog', id: 'chocoFrog', class: ChocoFrog, data: assets.enemies.chocoFrog, xPercentage: 0.30, yPercentage: 0.45},

{ name: 'magicBeam', id: 'magicBeam', class: MagicBeam, data: assets.enemies.magicBeam, xPercentage: 0.623, yPercentage: 0.72 },
Expand All @@ -196,9 +191,9 @@ const assets = {
{ name: 'tube', id: 'finishline', class: FinishLine, data: assets.obstacles.tube, xPercentage: 0.85, yPercentage: 0.855 },
{ name: 'tubeU', id: 'minifinishline', class: FinishLine, data: assets.obstacles.tubeU, xPercentage: 0.69, yPercentage: 0.9 },
{ name: 'waterEnd', id: 'background', class: BackgroundTransitions, data: assets.transitions.waterEnd },

];



const GameQuidditch = {
tag: 'Quidditch',
Expand Down
15 changes: 9 additions & 6 deletions assets/js/platformer/GameSetterSkibidi.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,19 @@ const assets = {
island: { src: "/images/platformer/platforms/island.png" },
island: { src: "/images/platformer/platforms/island.png" },
block: { src: "/images/platformer/platforms/brick_block.png" }, //MAY need 3 new variables: sizeRatio, widthRatio, and heightRatio


itemBlock2: { //power-up
src: "/images/platformer/sprites/jumppowerup.png", //spritesheet
sizeRatio: 2.0,
sizeRatio: 0.000000001,
widthRatio: 1.0,
heightRatio: 1.0,
width: 205, // 205
height: 246, // 246
scaleSize: 1, // 1
width: 0, // 205
height: 0, // 246
scaleSize: 0, // 1
speedRatio: 0.7, // framerate, how fast it goes through between displaying each frame or animation
hitbox: { widthPercentage: 0.4, heightPercentage: -0.2 }
hitbox: { widthPercentage: 0, heightPercentage: 0 }

},
},
backgrounds: {
Expand Down Expand Up @@ -518,7 +521,7 @@ const assets = {
{ name: 'SkibidiToilet', id: 'SkibidiToilet', class: SkibidiToilet, data: assets.enemies.skibidiToilet, xPercentage: 0.75, minPosition: 0.5 },
{ name: 'escaper', id: 'player', class: PlayerSkibidi, data: assets.players.escaper },
{ name: 'laser', id: 'Laser', class: Laser, data: assets.obstacles.laser, xPercentage: 0.75, yPercentage: 0.5 },
{ name: 'tolietfinish', id: 'finishline', class: FinishLine, data: assets.obstacles.toiletfinish, xPercentage: 0.85, yPercentage: 0.77 },
{ name: 'tolietfinish', id: 'finishline', class: FinishLine, data: assets.obstacles.toiletfinish, xPercentage: 0.85, yPercentage: 0.77, isVisible: false },
{ name: 'complete3', id: 'background', class: BackgroundTransitions, data: assets.backgrounds.complete3 },
];

Expand Down
2 changes: 2 additions & 0 deletions assets/js/platformer/PlatformJump.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export class JumpPlatform extends GameObject {
this.isVisible = false;
// Update status of key
GameEnv.keyCollected = true
//Update status of the wand
GameEnv.wandCollected = true
// Remove the block from the display
this.canvas.style.display = 'none';
}
Expand Down
3 changes: 3 additions & 0 deletions assets/js/platformer/PlayerBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export class PlayerBase extends Character {
} else if (key === 'd') {
this.state.direction = 'right';
}
if (key === 'b' && GameEnv.wandCollected) {
GameEnv.spellUsed = true
}
this.pressedKeys[event.key] = true;
this.updateAnimationState(key);
GameEnv.transitionHide = true;
Expand Down
2 changes: 1 addition & 1 deletion assets/js/platformer/PlayerQuidditch.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class PlayerQuidditch extends PlayerBase {
break;
case "finishline":
// 1. Caught in finishline
if (this.collisionData.touchPoints.this.top && this.collisionData.touchPoints.other.bottom) {
if (this.collisionData.touchPoints.this.top && this.collisionData.touchPoints.other.bottom && GameEnv.wandCollected && GameEnv.spellUsed) {
// Position player in the center of the finishline
this.x = this.collisionData.newX;
// Using natural gravity wait for player to reach floor
Expand Down
Loading

0 comments on commit 7e4c171

Please # to comment.