can you make a game were your charicter gets differint spells like fire ball and you can line up spells
Let's make a cool spell game! I built a first version: you're a wizard who can move around, shoot a Fireball, an Ice Bolt, or a triple Magic Arrow, and blast slimes before they reach you. Try lining up spells to hit lots of enemies at once! Next, I could add a shop where you spend points to unlock even more spells - want that?
but you evplor like terarya
Ooh I love that idea! Let's turn Spell Caster into a Terraria-style world where you walk left/right and jump on the ground, instead of just dodging things falling from the sky. I gave you a green ground to stand on, jumping with the Up arrow or W, and gravity so you fall back down. Your spells now shoot sideways in the direction you're facing, like a real side-scrolling explorer game! Next, we could add blocks you can dig and place, like real Terraria!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>Spell Caster</title> <style> * { margin:0; padding:0; box-sizing:border-box; } body { background: linear-gradient(#0b0b2a, #1a1a4a); display:flex; flex-direction:column; align-items:center; font-family: 'Trebuchet MS', sans-serif; color: white; overflow:hidden; height:100vh; } h1 { margin:10px 0 4px 0; text-shadow: 0 0 8px #8888ff; } #hud { display:flex; gap:20px; margin-bottom:6px; font-size:18px; } #hud span { background:rgba(255,255,255,0.1); padding:4px 10px; border-radius:8px;} #spellBar { display:flex; gap:10px; margin-bottom:8px; } .spellBtn { padding:8px 14px; border-radius:10px; border:2px solid #fff4; cursor:pointer; font-weight:bold; font-size:15px; color:white; user-select:none; } .spellBtn.selected { border-color:#fff; box-shadow:0 0 12px white; } #fire { background:#ff5722; } #ice { background:#03a9f4; } #arrow { background:#8bc34a; } canvas { background: radial-gradient(circle at center, #222255, #050515); border:3px solid #444488; border-radius:12px; touch-action:none; } #msg { margin-top:6px; font-size:16px; height:20px; color:#ffdd88; } </style> </head> <body> <h1>✨ Spell Caster ✨</h1> <div id="hud"> <span>Score: <span id="score">0</span></span> <span>Lives: <span id="lives">3</span></span> <span>Wave: <span id="wave">1</span></span> </div> <div id="spellBar"> <div class="spellBtn selected" id="fire" data-spell="fire">🔥 Fireball</div> <div class="spellBtn" id="ice" data-spell="ice">❄️ Ice Bolt</div> <div class="spellBtn" id="arrow" data-spell="arrow">🏹 Magic Arrow</div> </div> <canvas id="game" width="800" height="500"></canvas> <div id="msg">Move with ← → , jump with ↑ or W. Click/tap to cast! Line up enemies for big combos!</div> <script> const canvas = document.getElementById('game'); const ctx = canvas.getContext('2d'); let score = 0, lives = 3, wave = 1; const scoreEl = document.getElementById('score'); const livesEl = document.getElementById('lives'); const waveEl = document.getElementById('wave'); const msgEl = document.getElementById('msg'); let selectedSpell = 'fire'; document.querySelectorAll('.spellBtn').forEach(btn=>{ btn.addEventListener('click', ()=>{ document.querySelectorAll('.spellBtn').forEach(b=>b.classList.remove('selected')); btn.classList.add('selected'); selectedSpell = btn.dataset.spell; }); }); // player const groundY = canvas.height - 60; const player = { x: 400, y: groundY, w: 40, h: 40, speed: 5, vy:0, onGround:true, facing:1 }; const GRAVITY = 0.6; const JUMP_POWER = -12; // controls const keys = {}; window.addEventListener('keydown', e=>{ keys[e.key]=true; }); window.addEventListener('keyup', e=>{ keys[e.key]=false; }); // spells (projectiles) let spells = []; function castSpell(){ const dir = player.facing; if(selectedSpell === 'fire'){ spells.push({x:player.x, y:player.y-10, vx:9*dir, vy:0, r:12, type:'fire', pierce:false}); } else if(selectedSpell === 'ice'){ spells.push({x:player.x, y:player.y-10, vx:7*dir, vy:0, r:14, type:'ice', pierce:true}); } else if(selectedSpell === 'arrow'){ spells.push({x:player.x, y:player.y-24, vx:10*dir, vy:0, r:6, type:'arrow', pierce:false}); spells.push({x:player.x, y:player.y-10, vx:10*dir, vy:0, r:6, type:'arrow', pierce:false}); spells.push({x:player.x, y:player.y+4, vx:10*dir, vy:0, r:6, type:'arrow', pierce:false}); } } canvas.addEventListener('click', castSpell); window.addEventListener('keydown', e=>{ if(e.key === ' ') { castSpell(); e.preventDefault(); } if(e.key === '1') selectSpellByIndex(0); if(e.key === '2') selectSpellByIndex(1); if(e.key === '3') selectSpellByIndex(2); }); function selectSpellByIndex(i){ const btns = document.querySelectorAll('.spellBtn'); btns.forEach(b=>b.classList.remove('selected')); btns[i].classList.add('selected'); selectedSpell = btns[i].dataset.spell; } // enemies let enemies = []; let spawnTimer = 0; let spawnInterval = 90; function spawnEnemy(){ const side = Math.random() < 0.5 ? -1 : 1; const x = side === -1 ? -20 : canvas.width+20; const speed = (0.8 + wave*0.15 + Math.random()*0.5) * -side; enemies.push({x, y:groundY, r:18, speed, hp:1}); } function colorForSpell(type){ if(type==='fire') return '#ff5722'; if(type==='ice') return '#03a9f4'; return '#8bc34a'; } function update(){ // player movement if(keys['ArrowLeft']){ player.x -= player.speed; player.facing = -1; } if(keys['ArrowRight']){ player.x += player.speed; player.facing = 1; } if((keys['ArrowUp'] || keys['w'] || keys['W']) && player.onGround){ player.vy = JUMP_POWER; player.onGround = false; } player.vy += GRAVITY; player.y += player.vy; if(player.y >= groundY){ player.y = groundY; player.vy = 0; player.onGround = true; } player.x = Math.max(20, Math.min(canvas.width-20, player.x)); // spawn spawnTimer++; if(spawnTimer > spawnInterval){ spawnTimer = 0; spawnEnemy(); if(spawnInterval > 35) spawnInterval -= 1; } // update spells spells.forEach(s=>{ s.x += s.vx; s.y += s.vy; }); spells = spells.filter(s=> s.y > -30 && s.x > -30 && s.x < canvas.width+30); // update enemies enemies.forEach(en=> en.x += en.speed); // collisions for(let i=enemies.length-1;i>=0;i--){ const en = enemies[i]; let hit = false; for(let j=spells.length-1;j>=0;j--){ const s = spells[j]; const dx = en.x-s.x, dy = en.y-s.y; if(Math.sqrt(dx*dx+dy*dy) < en.r+s.r){ hit = true; score += 10; if(!s.pierce) spells.splice(j,1); } } if(hit){ enemies.splice(i,1); scoreEl.textContent = score; continue; } if(en.x < -40 || en.x > canvas.width+40){ enemies.splice(i,1); lives--; livesEl.textContent = lives; if(lives<=0){ msgEl.textContent = "Game Over! Refresh to play again. Final score: " + score; gameOver = true; } } } // wave progression if(score > wave*150){ wave++; waveEl.textContent = wave; msgEl.textContent = "Wave " + wave + "! Enemies are faster now!"; } } function draw(){ ctx.clearRect(0,0,canvas.width,canvas.height); // player (wizard) ctx.save(); ctx.translate(player.x, player.y); ctx.fillStyle = '#7e57c2'; ctx.beginPath(); ctx.moveTo(0,-25); ctx.lineTo(20,20); ctx.lineTo(-20,20); ctx.closePath(); ctx.fill(); ctx.fillStyle = '#ffe082'; ctx.beginPath(); ctx.arc(0,-25,8,0,Math.PI*2); ctx.fill(); ctx.restore(); // spells spells.forEach(s=>{ ctx.beginPath(); ctx.fillStyle = colorForSpell(s.type); ctx.shadowColor = colorForSpell(s.type); ctx.shadowBlur = 15; ctx.arc(s.x, s.y, s.r, 0, Math.PI*2); ctx.fill(); ctx.shadowBlur = 0; }); // enemies (slimes) enemies.forEach(en=>{ ctx.beginPath(); ctx.fillStyle = '#e91e63'; ctx.arc(en.x, en.y, en.r, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = 'white'; ctx.beginPath(); ctx.arc(en.x-6, en.y-4, 3, 0, Math.PI*2); ctx.arc(en.x+6, en.y-4, 3, 0, Math.PI*2); ctx.fill(); }); } let gameOver = false; function loop(){ if(!gameOver){ update(); draw(); } requestAnimationFrame(loop); } loop(); </script> </body> </html>
No pictures yet. Add one, then ask your buddy to put it in your app!