Let’s score your project
I compose original instrumental music and design sound for games, film, and TV — from full soundtracks to single trailer cues.
What I offer
- Original scoring:
Full soundtracks, single cues, or trailer music
- Sound design:
Unique SFX for games & animation
- Session recording:
Guitar, bass, keys, etc.
- Voice acting:
character voices, narration
How it works
- Tell me about your project
genre, mood references, scene or gameplay footage if you have it, and rough budget / timeline
- I send a sample sketch
a short original piece in the direction we discussed, so you know it’s the right fit before committing.
- Full delivery
mixed, mastered, stems included, with revisions built into the process.
Rates & turnaround
Every project’s different!
Rates depend on scope (single cue vs. full score), usage rights, and timeline.
| Service | Rate | Market Range | Notes |
|---|
| Single cue / trailer | $150 – 300 | $100 – 500 | One-off, fast turnaround, includes stems + 2 revisions |
| Small soundtrack (3-5 tracks) | $125 – 250 | $200 – 400 | Volume discount; includes alt mixes + 3 revisions |
| Full score + sound design | $3,000 – 8,000 flat | $3,000 – 15,000 | Complete audio package; scope-dependent |
| Sound design only | $35 – 60/hr | $25 – 100/hr | Per-asset or hourly; SFX libraries, UI sounds, ambience |
| Voice acting | $75 – 150/hr | $50 – 200/hr | Session rate; character voices, narration |
| Session guitar / multi-inst. | $50 – 100/hr | $40 – 150/hr | Remote recording, stems delivered |
| Add-on | Surcharge | Notes |
|---|
Rush Delivery (< 48hrs) | +25% | Tight dev milestones, trailer deadlines, etc. |
Exclusivity Rights (Own the track) | +50% | You want to sell an individual single separately |
Additional Revision Rounds | +$50/round | Beyond the included 2-3 |
| Live Musicians | Quoted per current musician rates | You want real strings, brass, etc. |
Middleware Integration (FMOD/Wwise) | +$500-1,000 Not offered at this time | Adaptive music systems to be implemented by devs |
Soundtrack / Album Release Rights | +$500-2,000 | You want to sell/stream the entire OST |
Payment structure:
- Under $1,000: 100% upfront
- $1,000–5,000: 50% upfront, 50% on delivery
- $5,000+: 33/33/33 across milestones
Featured work
Light Path of the Archmage
Original score & sound design — full game soundtrack
Ready to talk about your project?
I usually respond within 48 hours.
Base Defender: Neon Command
body {
margin: 0;
padding: 0;
background-color: #080810;
color: #fff;
font-family: ‘Courier New’, Courier, monospace;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
overflow: hidden;
user-select: none;
}
#game-container {
position: relative;
box-shadow: 0 0 30px rgba(0, 242, 254, 0.2);
border: 2px solid #00f2fe;
border-radius: 4px;
}
canvas {
display: block;
background: radial-gradient(circle at center, #101026 0%, #050510 100%);
cursor: crosshair;
}
.ui-text {
position: absolute;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 2px;
pointer-events: none;
}
#score-board {
top: 20px;
left: 20px;
color: #00f2fe;
font-size: 20px;
text-shadow: 0 0 10px rgba(0, 242, 254, 0.6);
}
#stats-board {
top: 20px;
right: 20px;
color: #9d4edd;
font-size: 16px;
text-align: right;
text-shadow: 0 0 10px rgba(157, 78, 221, 0.6);
}
#game-over-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(5, 5, 16, 0.85);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
display: none;
}
#game-over-screen h1 {
color: #ff007f;
font-size: 48px;
margin-bottom: 10px;
text-shadow: 0 0 20px rgba(255, 0, 127, 0.8);
}
#restart-btn {
background: transparent;
border: 2px solid #00f2fe;
color: #00f2fe;
padding: 12px 24px;
font-size: 18px;
font-family: ‘Courier New’, Courier, monospace;
font-weight: bold;
cursor: pointer;
box-shadow: 0 0 15px rgba(0, 242, 254, 0.3);
transition: all 0.2s ease;
text-transform: uppercase;
margin-top: 20px;
}
#restart-btn:hover {
background: #00f2fe;
color: #050510;
box-shadow: 0 0 25px rgba(0, 242, 254, 0.8);
}
Score: 0
Blast Radius Level: 1
GRID DOWN
const canvas = document.getElementById(‘gameCanvas’);
const ctx = canvas.getContext(‘2d’);
const scoreBoard = document.getElementById(‘score-board’);
const statsBoard = document.getElementById(‘stats-board’);
const gameOverScreen = document.getElementById(‘game-over-screen’);
const finalScoreText = document.getElementById(‘final-score’);
// Game State
let score = 0;
let explosionLevel = 1;
let baseRadius = 35;
let currentMaxRadius = baseRadius;
let gameOver = false;
let spawnRate = 1500; // ms between spawns
let lastSpawnTime = 0;
// Game Entities
let buildings = [];
let missiles = [];
let asteroids = [];
let explosions = [];
let particles = [];
let powerups = [];
// Turret origin point (center bottom)
const turretX = canvas.width / 2;
const turretY = canvas.height – 20;
class Building {
constructor(x, width, height) {
this.x = x;
this.y = canvas.height – height;
this.width = width;
this.height = height;
this.alive = true;
}
draw() {
if (!this.alive) return;
ctx.save();
ctx.shadowBlur = 15;
ctx.shadowColor = ‘#00f2fe’;
ctx.fillStyle = ‘#051e3e’;
ctx.strokeStyle = ‘#00f2fe’;
ctx.lineWidth = 2;
// Draw building body
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.strokeRect(this.x, this.y, this.width, this.height);
// Draw cyber-windows
ctx.fillStyle = ‘rgba(0, 242, 254, 0.4)’;
let winSize = 6;
for (let wx = this.x + 6; wx < this.x + this.width – 6; wx += 14) {
for (let wy = this.y + 8; wy < canvas.height – 10; wy += 16) {
ctx.fillRect(wx, wy, winSize, winSize);
}
}
ctx.restore();
}
}
class Missile {
constructor(startX, startY, targetX, targetY) {
this.x = startX;
this.y = startY;
this.targetX = targetX;
this.targetY = targetY;
this.speed = 7;
// Calculate velocity vector
let dx = targetX – startX;
let dy = targetY – startY;
let dist = Math.sqrt(dx * dx + dy * dy);
this.vx = (dx / dist) * this.speed;
this.vy = (dy / dist) * this.speed;
this.alive = true;
}
update() {
this.x += this.vx;
this.y += this.vy;
// Check if missile reached target destination (within proximity)
let dx = this.targetX – this.x;
let dy = this.targetY – this.y;
if (Math.sqrt(dx * dx + dy * dy) b.alive);
let targetX = Math.random() * canvas.width;
if (livingBuildings.length > 0) {
let targetB = livingBuildings[Math.floor(Math.random() * livingBuildings.length)];
targetX = targetB.x + targetB.width / 2;
}
this.speed = 1.2 + Math.random() * 1.5 + (score * 0.0005); // Scales slightly over time
let dx = targetX – this.x;
let dy = canvas.height – this.y;
let dist = Math.sqrt(dx * dx + dy * dy);
this.vx = (dx / dist) * this.speed;
this.vy = (dy / dist) * this.speed;
this.radius = 10 + Math.random() * 12;
this.alive = true;
}
update() {
this.x += this.vx;
this.y += this.vy;
// Hit floor or buildings check
if (this.y >= canvas.height – 10) {
this.alive = false;
triggerScreenShake();
createExplosionParticles(this.x, this.y, ‘#ffb703’, 15);
// Damage buildings it lands on
buildings.forEach(b => {
if (this.x > b.x && this.x
= this.maxRadius) {
this.state = ‘shrinking’;
}
} else if (this.state === ‘shrinking’) {
this.radius -= this.growthSpeed * 0.7;
if (this.radius canvas.height) this.alive = false;
}
draw() {
ctx.save();
ctx.shadowBlur = 15;
ctx.shadowColor = ‘#39ff14’;
ctx.strokeStyle = ‘#39ff14’;
ctx.fillStyle = ‘rgba(57, 255, 20, 0.3)’;
ctx.lineWidth = 2;
// Retro-neon diamond shape
ctx.beginPath();
ctx.moveTo(this.x, this.y – this.radius);
ctx.lineTo(this.x + this.radius, this.y);
ctx.lineTo(this.x, this.y + this.radius);
ctx.lineTo(this.x – this.radius, this.y);
ctx.closePath();
ctx.fill();
ctx.stroke();
ctx.restore();
}
}
class Particle {
constructor(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
this.radius = Math.random() * 2 + 1;
let angle = Math.random() * Math.PI * 2;
let speed = Math.random() * 4 + 1;
this.vx = Math.cos(angle) * speed;
this.vy = Math.sin(angle) * speed;
this.alpha = 1;
this.decay = Math.random() * 0.02 + 0.015;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.alpha -= this.decay;
}
draw() {
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.radius * 2, this.radius * 2);
ctx.restore();
}
}
// Sparkle particle burst helper
function createExplosionParticles(x, y, color, count) {
for (let i = 0; i !b.alive);
if (allDead) {
gameOver = true;
finalScoreText.innerText = `Final Score: ${score} | Power Level Reached: ${explosionLevel}`;
gameOverScreen.style.display = ‘flex’;
}
}
// User Action: Fire Missile or click PowerUp
canvas.addEventListener(‘click’, (e) => {
if (gameOver) return;
const rect = canvas.getBoundingClientRect();
const clickX = e.clientX – rect.left;
const clickY = e.clientY – rect.top;
// Check if player clicked directly on a Power-up Gem first
let customClickedPowerup = false;
for (let i = powerups.length – 1; i >= 0; i–) {
let p = powerups[i];
let dist = Math.sqrt((clickX – p.x) ** 2 + (clickY – p.y) ** 2);
if (dist 0) {
let dx = (Math.random() – 0.5) * 7;
let dy = (Math.random() – 0.5) * 7;
ctx.translate(dx, dy);
shakeRemaining–;
}
// Spawning Logic
if (timestamp – lastSpawnTime > spawnRate && !gameOver) {
asteroids.push(new Asteroid());
lastSpawnTime = timestamp;
// Accelerate spawns slightly as score builds
spawnRate = Math.max(500, 1500 – (score * 2));
}
// Draw Ground Grid Line
ctx.strokeStyle = ‘#9d4edd’;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(0, canvas.height – 10);
ctx.lineTo(canvas.width, canvas.height – 10);
ctx.stroke();
// Draw central defense core
ctx.fillStyle = ‘#ff007f’;
ctx.beginPath();
ctx.arc(turretX, turretY, 15, Math.PI, 0);
ctx.fill();
// Buildings
buildings.forEach(b => b.draw());
// Process Missiles
missiles.forEach((m, idx) => {
m.update();
m.draw();
if (!m.alive) missiles.splice(idx, 1);
});
// Process Explosions
explosions.forEach((exp, idx) => {
exp.update();
exp.draw();
// Check collision against falling Asteroids
asteroids.forEach(ast => {
if (ast.alive) {
let dx = ast.x – exp.x;
let dy = ast.y – exp.y;
let dist = Math.sqrt(dx * dx + dy * dy);
if (dist < exp.radius + ast.radius) {
ast.alive = false;
score += 100;
scoreBoard.innerText = `Score: ${score}`;
createExplosionParticles(ast.x, ast.y, '#00f2fe', 12);
// Chance to drop a green Power-Up crystal (15%)
if (Math.random() {
ast.update();
ast.draw();
if (!ast.alive) asteroids.splice(idx, 1);
});
// Process Powerups
powerups.forEach((p, idx) => {
p.update();
p.draw();
if (!p.alive) powerups.splice(idx, 1);
});
// Process Particles
particles.forEach((part, idx) => {
part.update();
part.draw();
if (part.alpha <= 0) particles.splice(idx, 1);
});
ctx.restore();
requestAnimationFrame(updateAndRender);
}
// Initial Launch
init();
requestAnimationFrame(updateAndRender);
NeoMon: Monster Battler
body {
margin: 0;
padding: 20px;
background-color: #0f111a;
color: #fff;
font-family: ‘Courier New’, Courier, monospace;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
user-select: none;
}
#game-boy {
background-color: #2b2d42;
border: 8px solid #1a1b26;
border-radius: 20px;
padding: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.6);
width: 480px;
}
#screen {
background: linear-gradient(180deg, #1e1e2f 0%, #11111b 100%);
border: 4px solid #4a4e69;
border-radius: 8px;
height: 320px;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* Battle Arena Setup */
#arena {
flex: 2;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 30px;
}
.platform {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.monster-sprite {
width: 80px;
height: 80px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
font-weight: bold;
box-shadow: 0 0 20px rgba(255,255,255,0.1);
position: relative;
}
/* Type Theme Colors */
.type-fire { border: 4px solid #ff4757; background: rgba(255, 71, 87, 0.2); color: #ff4757; }
.type-water { border: 4px solid #1e90ff; background: rgba(30, 144, 255, 0.2); color: #1e90ff; }
.type-grass { border: 4px solid #2ed573; background: rgba(46, 213, 115, 0.2); color: #2ed573; }
.hud {
background: rgba(0, 0, 0, 0.6);
border: 1px solid #4a4e69;
border-radius: 4px;
padding: 6px 12px;
width: 130px;
margin-top: 8px;
font-size: 11px;
}
.hp-bar-bg {
background: #444;
height: 6px;
border-radius: 3px;
margin-top: 4px;
overflow: hidden;
}
.hp-bar-fill {
background: #2ed573;
height: 100%;
width: 100%;
transition: width 0.4s ease;
}
/* Text Log Box */
#textbox {
flex: 1;
background: #f8f9fa;
color: #111;
border-top: 4px solid #4a4e69;
padding: 12px;
font-size: 14px;
line-height: 1.4;
overflow-y: hidden;
font-weight: bold;
}
/* Action Menu Panel */
#controls {
margin-top: 15px;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
button {
background-color: #4a4e69;
border: 2px solid #9a8c98;
color: white;
padding: 12px;
font-family: ‘Courier New’, Courier, monospace;
font-size: 14px;
font-weight: bold;
cursor: pointer;
border-radius: 6px;
transition: all 0.1s ease;
}
button:hover:not(:disabled) {
background-color: #9a8c98;
color: #2b2d42;
}
button:disabled {
opacity: 0.3;
cursor: not-allowed;
}
#switch-menu {
display: none;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin-top: 10px;
border-top: 2px dashed #4a4e69;
padding-top: 10px;
}
.type-badge {
font-size: 9px;
padding: 1px 4px;
border-radius: 3px;
font-weight: bold;
color: #fff;
text-transform: uppercase;
display: inline-block;
}
.badge-fire { background: #ff4757; }
.badge-water { background: #1e90ff; }
.badge-grass { background: #2ed573; }
NEOMON RATTLER
Fire > Grass > Water > Fire
An enemy Trainer wants to battle! Go, Pyromander!
// Type Advantage Definition Table
const TYPE_ADVANTAGES = {
fire: { grass: 2.0, water: 0.5, fire: 1.0 },
water: { fire: 2.0, grass: 0.5, water: 1.0 },
grass: { water: 2.0, fire: 0.5, grass: 1.0 }
};
// Complete roster database (6 unique specimens)
const ROSTER = [
// Player Starting Group
{ name: ‘Pyromander’, type: ‘fire’, icon: ‘🦖’, maxHp: 100, hp: 100, moves: { basic: ‘Scratch’, special: ‘Ember Flare’ } },
{ name: ‘Tadpool’, type: ‘water’, icon: ‘🐸’, maxHp: 110, hp: 110, moves: { basic: ‘Tackle’, special: ‘Hydro Jet’ } },
{ name: ‘Sproutlet’, type: ‘grass’, icon: ‘🌱’, maxHp: 95, hp: 95, moves: { basic: ‘Pound’, special: ‘Leaf Razor’ } },
// AI Rival Group
{ name: ‘Inferadillo’, type: ‘fire’, icon: ‘🛡️’, maxHp: 105, hp: 105, moves: { basic: ‘Rollout’, special: ‘Magma Burst’ } },
{ name: ‘Aquataur’, type: ‘water’, icon: ‘🧜’, maxHp: 100, hp: 100, moves: { basic: ‘Slam’, special: ‘Vortex Wave’ } },
{ name: ‘Florafox’, type: ‘grass’, icon: ‘🦊’, maxHp: 90, hp: 90, moves: { basic: ‘Bite’, special: ‘Solar Beam’ } }
];
let playerTeam = [];
let enemyTeam = [];
let pActiveIdx = 0;
let eActiveIdx = 0;
let isIntermission = false;
function initGame() {
// Deep copy roster datasets
playerTeam = JSON.parse(JSON.stringify(ROSTER.slice(0, 3)));
enemyTeam = JSON.parse(JSON.stringify(ROSTER.slice(3, 6)));
pActiveIdx = 0;
eActiveIdx = 0;
isIntermission = false;
document.getElementById(‘switch-menu’).style.display = ‘none’;
enableInput(true);
updateUI();
writeLog(`Trainer Battle initiated! Your rival sends out ${enemyTeam[eActiveIdx].name}!`);
}
function updateUI() {
let p = playerTeam[pActiveIdx];
let e = enemyTeam[eActiveIdx];
// Player Render Update
document.getElementById(‘p-name’).innerText = p.name;
document.getElementById(‘p-sprite’).innerText = p.icon;
document.getElementById(‘p-sprite’).className = `monster-sprite type-${p.type}`;
document.getElementById(‘p-badge’).className = `type-badge badge-${p.type}`;
document.getElementById(‘p-badge’).innerText = p.type;
let pHpPct = Math.max(0, (p.hp / p.maxHp) * 100);
document.getElementById(‘p-hp’).style.width = pHpPct + ‘%’;
document.getElementById(‘p-hp-text’).innerText = `${Math.max(0, p.hp)}/${p.maxHp}`;
// Change health bar color depending on status
document.getElementById(‘p-hp’).style.backgroundColor = pHpPct < 25 ? '#ff4757' : pHpPct < 50 ? '#ffa500' : '#2ed573';
// Enemy Render Update
document.getElementById('e-name').innerText = e.name;
document.getElementById('e-sprite').innerText = e.icon;
document.getElementById('e-sprite').className = `monster-sprite type-${e.type}`;
document.getElementById('e-badge').className = `type-badge badge-${e.type}`;
document.getElementById('e-badge').innerText = e.type;
let eHpPct = Math.max(0, (e.hp / e.maxHp) * 100);
document.getElementById('e-hp').style.width = eHpPct + '%';
document.getElementById('e-hp-text').innerText = `${Math.max(0, e.hp)}/${e.maxHp}`;
document.getElementById('e-hp').style.backgroundColor = eHpPct < 25 ? '#ff4757' : eHpPct idx !== pActiveIdx);
benchIndices.forEach((teamIdx, uiIdx) => {
let btn = document.getElementById(`bench-${uiIdx}`);
let targetMon = playerTeam[teamIdx];
btn.innerText = `${targetMon.name} (${targetMon.hp > 0 ? targetMon.hp + ‘ HP’ : ‘Fainted’})`;
btn.disabled = targetMon.hp 1) msg += ” It’s super effective! 💥”;
if (pResult.multiplier < 1) msg += " It wasn't very effective… 🛡️";
writeLog(msg);
updateUI();
// Check if Enemy fainted
if (e.hp handleEnemyFaint(), 1800);
return;
}
// 2. Enemy Turn Counter Attack (Delayed for Turn Cadence rhythm)
setTimeout(() => {
let eActionIsSpecial = Math.random() > 0.4;
let eResult = calculateDamage(e, p, eActionIsSpecial);
p.hp -= eResult.damage;
let eMoveName = eActionIsSpecial ? e.moves.special : e.moves.basic;
let eMsg = `Wild ${e.name} counterattacked with ${eMoveName}! Took ${eResult.damage} damage.`;
if (eResult.multiplier > 1) eMsg += ” It’s super effective! 💥”;
if (eResult.multiplier < 1) eMsg += " It wasn't very effective… 🛡️";
writeLog(eMsg);
updateUI();
// Check if Player fainted
if (p.hp handlePlayerFaint(), 1800);
} else {
enableInput(true);
}
}, 1800);
}
function switchActivePlayer(newIdx) {
document.getElementById(‘switch-menu’).style.display = ‘none’;
let oldName = playerTeam[pActiveIdx].name;
pActiveIdx = newIdx;
updateUI();
writeLog(`Retreated ${oldName}. Bring it on, ${playerTeam[pActiveIdx].name}!`);
enableInput(false);
// Enemy gets an immediate penalty strike turn for switching positions mid battle
setTimeout(() => {
let e = enemyTeam[eActiveIdx];
let p = playerTeam[pActiveIdx];
let eResult = calculateDamage(e, p, Math.random() > 0.5);
p.hp -= eResult.damage;
writeLog(`Enemy ${e.name} caught you switching assets and dealt ${eResult.damage} tracking damage!`);
updateUI();
if (p.hp = enemyTeam.length) {
writeLog(“VICTORY! You defeated the rival trainer and won the match!”);
enableInput(false);
} else {
setTimeout(() => {
writeLog(`Rival deployed ${enemyTeam[eActiveIdx].name}!`);
updateUI();
enableInput(true);
}, 1500);
}
}
function handlePlayerFaint() {
writeLog(`${playerTeam[pActiveIdx].name} fainted in combat!`);
// Scan if any viable members remain awake
let teamAlive = playerTeam.some(mon => mon.hp > 0);
if (!teamAlive) {
writeLog(“DEFEAT! All your monsters fainted. Whiteout grid down.”);
enableInput(false);
} else {
// Force pop-up the choice sub menu panel
writeLog(“Select an available team member to deploy back to battle positions!”);
document.getElementById(‘switch-menu’).style.display = ‘grid’;
}
}
function resetGame() {
initGame();
}
// Initial engine boot
initGame();