设计思路
这个游戏需要实现:
- 多种古风场景切换(神魔大战、比武台、炼丹等)
- 用户弹幕转化为角色形象入场
- 礼物特效与压制机制
- 大能NPC的特殊互动
- 动态场景与动作音效
下面是完整的实现方案:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>神魔大战 - 抖音弹幕游戏</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Microsoft YaHei', sans-serif;
background: #0a0a1a;
color: #fff;
overflow: hidden;
height: 100vh;
}
#game-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
#scene {
position: absolute;
width: 100%;
height: 100%;
background-size: cover;
background-position: center;
transition: background-image 1s ease;
}
#battlefield {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="800" height="600" viewBox="0 0 800 600"><rect width="800" height="600" fill="%230d1b2a"/><path d="M0,450 Q200,300 400,450 T800,450 L800,600 L0,600 Z" fill="%233a5f5f"/><circle cx="200" cy="200" r="50" fill="%23ffcc00"/><circle cx="600" cy="250" r="40" fill="%23ffcc00"/><path d="M100,350 L150,300 L200,350 L250,300 L300,350 L350,300 L400,350 L450,300 L500,350 L550,300 L600,350 L650,300 L700,350" stroke="%23a67c52" stroke-width="5" fill="none"/></svg>');
}
#character-container {
position: absolute;
bottom: 0;
width: 100%;
height: 70%;
display: flex;
justify-content: center;
align-items: flex-end;
}
.character {
position: absolute;
transition: all 0.5s ease;
display: flex;
flex-direction: column;
align-items: center;
}
.avatar {
width: 60px;
height: 60px;
border-radius: 50%;
border: 3px solid #fff;
background-size: cover;
background-position: center;
margin-bottom: 5px;
box-shadow: 0 0 10px rgba(255,255,255,0.5);
}
.username {
background: rgba(0,0,0,0.7);
padding: 2px 8px;
border-radius: 10px;
font-size: 12px;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.character-img {
width: 80px;
height: 100px;
background-size: contain;
background-repeat: no-repeat;
background-position: bottom;
transition: transform 0.3s;
}
.message-bubble {
position: absolute;
top: -30px;
background: rgba(255,255,255,0.9);
color: #333;
padding: 5px 10px;
border-radius: 15px;
font-size: 14px;
max-width: 200px;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
animation: floatUp 3s forwards;
}
@keyframes floatUp {
0% { opacity: 0; transform: translateY(10px); }
10% { opacity: 1; transform: translateY(0); }
90% { opacity: 1; transform: translateY(-20px); }
100% { opacity: 0; transform: translateY(-30px); }
}
.effect {
position: absolute;
pointer-events: none;
z-index: 100;
}
.scene-title {
position: absolute;
top: 20px;
left: 0;
right: 0;
text-align: center;
font-size: 28px;
font-weight: bold;
text-shadow: 0 0 10px #ff00ff, 0 0 20px #ff00ff;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
#controls {
position: absolute;
bottom: 20px;
left: 20px;
display: flex;
gap: 10px;
z-index: 10;
}
.scene-btn {
background: rgba(255, 215, 0, 0.8);
border: none;
border-radius: 20px;
padding: 8px 15px;
color: #8b0000;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
}
.scene-btn:hover {
background: rgba(255, 255, 255, 0.9);
transform: scale(1.05);
}
#chat-container {
position: absolute;
right: 20px;
bottom: 20px;
width: 300px;
background: rgba(0,0,0,0.7);
border-radius: 10px;
padding: 10px;
max-height: 300px;
overflow-y: auto;
}
.chat-message {
margin-bottom: 8px;
padding: 5px;
border-radius: 5px;
background: rgba(255,255,255,0.1);
}
.chat-username {
color: #ffcc00;
font-weight: bold;
margin-right: 5px;
}
#input-container {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 10;
}
#message-input {
width: 300px;
padding: 10px;
border-radius: 20px;
border: 2px solid #ffcc00;
background: rgba(0,0,0,0.7);
color: white;
outline: none;
}
#send-btn {
background: #ffcc00;
border: none;
border-radius: 20px;
padding: 10px 20px;
color: #8b0000;
font-weight: bold;
cursor: pointer;
}
.powerful {
transform: scale(1.5);
filter: drop-shadow(0 0 10px gold);
}
.suppressed {
transform: scale(0.7) translateY(20px);
filter: grayscale(1);
opacity: 0.7;
}
.counter {
animation: counterEffect 1s;
}
@keyframes counterEffect {
0% { transform: scale(1); }
50% { transform: scale(1.8); }
100% { transform: scale(1); }
}
.gift-effect {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
pointer-events: none;
opacity: 0;
z-index: 50;
}
.fireworks {
background: radial-gradient(circle, rgba(255,50,50,0.3) 0%, transparent 70%);
animation: fireworks 2s;
}
@keyframes fireworks {
0% { opacity: 0; transform: scale(0.5); }
30% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(1.5); }
}
.golden-aura {
background: radial-gradient(circle, rgba(255,215,0,0.4) 0%, transparent 70%);
animation: goldenAura 3s;
}
@keyframes goldenAura {
0% { opacity: 0; }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; }
}
</style>
</head>
<body>
<div id="game-container">
<div id="scene" id="battlefield">
<div class="scene-title">⚔️ 神魔古战场 ⚔️</div>
<div id="character-container">
<!-- 角色将通过JS动态添加 -->
</div>
<div id="effects-container">
<!-- 特效将通过JS动态添加 -->
</div>
</div>
<div id="controls">
<button class="scene-btn" data-scene="battlefield">神魔战场</button>
<button class="scene-btn" data-scene="arena">比武擂台</button>
<button class="scene-btn" data-scene="alchemy">炼丹仙炉</button>
<button class="scene-btn" data-scene="meditation">打坐悟道</button>
<button class="scene-btn" data-scene="tribulation">渡劫天雷</button>
<button class="scene-btn" data-scene="marriage">比武招亲</button>
</div>
<div id="chat-container">
<div class="chat-message"><span class="chat-username">系统:</span> 欢迎来到神魔大战!发送消息加入战场</div>
</div>
<div id="input-container">
<input type="text" id="message-input" placeholder="输入消息参与战斗...">
<button id="send-btn">发送</button>
</div>
</div>
<script>
// 游戏状态
const gameState = {
currentScene: 'battlefield',
characters: [],
npcs: [],
messages: [],
nextId: 1,
powerfulNpcs: ['太上老君', '魔尊重楼', '九天玄女', '东华帝君']
};
// 场景配置
const scenes = {
battlefield: {
title: '⚔️ 神魔古战场 ⚔️',
background: 'battlefield',
actions: ['攻击', '防御', '法术', '召唤', '撤退']
},
arena: {
title: '🥋 比武擂台 🥋',
background: 'arena',
actions: ['挑战', '观战', '助威', '偷袭', '认输']
},
alchemy: {
title: '🔥 炼丹仙炉 🔥',
background: 'alchemy',
actions: ['投药', '控火', '注灵', '开炉', '护法']
},
meditation: {
title: '🧘 打坐悟道 🧘',
background: 'meditation',
actions: ['入定', '顿悟', '走火', '护法', '论道']
},
tribulation: {
title: '⚡ 渡劫天雷 ⚡',
background: 'tribulation',
actions: ['抗雷', '避劫', '护法', '干扰', '观劫']
},
marriage: {
title: '💘 比武招亲 💘',
background: 'marriage',
actions: ['挑战', '求亲', '助威', '抢亲', '祝福']
}
};
// 角色形象库
const characterImages = [
'warrior', 'mage', 'archer', 'monk', 'rogue',
'demon', 'angel', 'dragon', 'phoenix', 'turtle',
'fox', 'tiger', 'bear', 'deer', 'rabbit'
];
// 表情库
const expressions = ['happy', 'angry', 'surprised', 'confused', 'sad', 'cool'];
// 初始化游戏
function initGame() {
// 创建NPC角色
createNpc('太上老君', 'alchemy');
createNpc('魔尊重楼', 'battlefield');
createNpc('九天玄女', 'tribulation');
createNpc('东华帝君', 'meditation');
// 设置场景切换事件
document.querySelectorAll('.scene-btn').forEach(btn => {
btn.addEventListener('click', () => {
const scene = btn.dataset.scene;
switchScene(scene);
});
});
// 设置消息发送事件
document.getElementById('send-btn').addEventListener('click', sendMessage);
document.getElementById('message-input').addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage();
});
// 模拟用户加入
setTimeout(() => simulateUserJoin(), 2000);
setTimeout(() => simulateUserJoin(), 3500);
setTimeout(() => simulateUserJoin(), 5000);
// 模拟NPC动作
setInterval(simulateNpcAction, 8000);
}
// 切换场景
function switchScene(sceneType) {
gameState.currentScene = sceneType;
const sceneConfig = scenes[sceneType];
// 更新场景标题
document.querySelector('.scene-title').textContent = sceneConfig.title;
// 移动角色到新场景
gameState.characters.forEach(char => {
if (char.scene === sceneType) {
showCharacter(char);
} else {
hideCharacter(char);
}
});
// 移动NPC到新场景
gameState.npcs.forEach(npc => {
if (npc.scene === sceneType) {
showCharacter(npc);
} else {
hideCharacter(npc);
}
});
// 添加场景音效
playSceneSound(sceneType);
}
// 创建NPC
function createNpc(name, scene) {
const npc = {
id: `npc-${name}`,
name: name,
username: name,
scene: scene,
isNpc: true,
isPowerful: gameState.powerfulNpcs.includes(name),
position: getRandomPosition(),
image: characterImages[Math.floor(Math.random() * characterImages.length)],
expression: expressions[Math.floor(Math.random() * expressions.length)]
};
gameState.npcs.push(npc);
if (scene === gameState.currentScene) {
showCharacter(npc);
}
}
// 模拟用户加入
function simulateUserJoin() {
const users = [
{ name: '修仙小萌新', avatar: 'avatar1' },
{ name: '魔道祖师', avatar: 'avatar2' },
{ name: '剑仙李逍遥', avatar: 'avatar3' },
{ name: '炼丹小能手', avatar: 'avatar4' },
{ name: '渡劫专业户', avatar: 'avatar5' }
];
const user = users[Math.floor(Math.random() * users.length)];
const scene = Object.keys(scenes)[Math.floor(Math.random() * Object.keys(scenes).length)];
addCharacter(user.name, user.avatar, scene);
}
// 添加角色
function addCharacter(username, avatar, scene) {
const character = {
id: `char-${gameState.nextId++}`,
username: username,
avatar: avatar,
scene: scene,
position: getRandomPosition(),
image: characterImages[Math.floor(Math.random() * characterImages.length)],
expression: expressions[Math.floor(Math.random() * expressions.length)],
isSuppressed: false
};
gameState.characters.push(character);
if (scene === gameState.currentScene) {
showCharacter(character);
}
// 添加加入消息
addMessage('系统', `${username} 加入了${scenes[scene].title}`);
}
// 显示角色
function showCharacter(character) {
let charElement = document.getElementById(character.id);
if (!charElement) {
charElement = document.createElement('div');
charElement.id = character.id;
charElement.className = 'character';
charElement.style.left = `${character.position.x}%`;
charElement.style.bottom = `${character.position.y}%`;
const avatarDiv = document.createElement('div');
avatarDiv.className = 'avatar';
avatarDiv.style.backgroundImage = `url(https://i.pravatar.cc/150?img=${Math.floor(Math.random() * 70) + 1})`;
const usernameDiv = document.createElement('div');
usernameDiv.className = 'username';
usernameDiv.textContent = character.username;
const charImg = document.createElement('div');
charImg.className = `character-img ${character.isSuppressed ? 'suppressed' : ''}`;
charImg.style.backgroundImage = `url(https://placekitten.com/80/100)`;
charElement.appendChild(avatarDiv);
charElement.appendChild(usernameDiv);
charElement.appendChild(charImg);
document.getElementById('character-container').appendChild(charElement);
}
// 更新状态
if (character.isSuppressed) {
charElement.querySelector('.character-img').classList.add('suppressed');
} else {
charElement.querySelector('.character-img').classList.remove('suppressed');
}
if (character.isPowerful) {
charElement.querySelector('.character-img').classList.add('powerful');
}
charElement.style.display = 'block';
}
// 隐藏角色
function hideCharacter(character) {
const charElement = document.getElementById(character.id);
if (charElement) {
charElement.style.display = 'none';
}
}
// 获取随机位置
function getRandomPosition() {
return {
x: 10 + Math.random() * 80,
y: 10 + Math.random() * 30
};
}
// 发送消息
function sendMessage() {
const input = document.getElementById('message-input');
const message = input.value.trim();
if (message) {
// 模拟用户加入(如果尚未加入)
if (gameState.characters.length < 3) {
addCharacter('抖音用户', 'user', gameState.currentScene);
}
// 添加消息
addMessage('抖音用户', message);
// 创建消息气泡
createMessageBubble('抖音用户', message);
// 处理特殊命令
processCommand(message);
input.value = '';
}
}
// 添加消息
function addMessage(username, text) {
const chatContainer = document.getElementById('chat-container');
const messageElement = document.createElement('div');
messageElement.className = 'chat-message';
messageElement.innerHTML = `<span class="chat-username">${username}:</span> ${text}`;
chatContainer.appendChild(messageElement);
chatContainer.scrollTop = chatContainer.scrollHeight;
// 限制消息数量
if (chatContainer.children.length > 20) {
chatContainer.removeChild(chatContainer.children[0]);
}
}
// 创建消息气泡
function createMessageBubble(username, text) {
const characters = gameState.characters.concat(gameState.npcs);
const character = characters.find(char => char.username === username);
if (character) {
const charElement = document.getElementById(character.id);
if (charElement) {
const bubble = document.createElement('div');
bubble.className = 'message-bubble';
bubble.textContent = text;
// 随机水平位置
const offset = -20 + Math.random() * 40;
bubble.style.left = `${offset}px`;
charElement.appendChild(bubble);
// 移除气泡
setTimeout(() => {
if (bubble.parentNode) {
bubble.parentNode.removeChild(bubble);
}
}, 3000);
}
}
}
// 处理特殊命令
function processCommand(message) {
const sceneActions = scenes[gameState.currentScene].actions;
// 检查是否是动作命令
const action = sceneActions.find(a => message.includes(a));
if (action) {
performAction('抖音用户', action);
return;
}
// 检查礼物命令
if (message.includes('火箭')) {
applyGiftEffect('抖音用户', 'rocket');
} else if (message.includes('跑车')) {
applyGiftEffect('抖音用户', 'sportsCar');
} else if (message.includes('嘉年华')) {
applyGiftEffect('抖音用户', 'carnival');
}
}
// 执行动作
function performAction(username, action) {
const character = [...gameState.characters, ...gameState.npcs].find(char => char.username === username);
if (!character) return;
const charElement = document.getElementById(character.id);
if (!charElement) return;
// 添加动作效果
const charImg = charElement.querySelector('.character-img');
charImg.style.animation = 'none';
setTimeout(() => {
charImg.style.animation = 'jump 0.5s';
}, 10);
// 添加动作音效
playActionSound(action);
// 特殊场景效果
if (gameState.currentScene === 'tribulation' && action === '抗雷') {
createLightningEffect();
}
// 如果是大能NPC,可能反制
if (character.isNpc && character.isPowerful && Math.random() > 0.7) {
setTimeout(() => {
counterAction(character);
}, 1000);
}
}
// 应用礼物效果
function applyGiftEffect(username, giftType) {
const character = gameState.characters.find(char => char.username === username);
if (!character) return;
// 添加礼物特效
createGiftEffect(giftType);
// 压制其他角色
suppressOtherCharacters(username);
// 大能NPC可能无视或反制
gameState.npcs.forEach(npc => {
if (npc.scene === gameState.currentScene && npc.isPowerful) {
if (Math.random() > 0.5) {
setTimeout(() => {
counterSuppression(npc, username);
}, 1500);
}
}
});
}
// 压制其他角色
function suppressOtherCharacters(excludedUsername) {
gameState.characters.forEach(char => {
if (char.username !== excludedUsername && char.scene === gameState.currentScene) {
char.isSuppressed = true;
const charElement = document.getElementById(char.id);
if (charElement) {
charElement.querySelector('.character-img').classList.add('suppressed');
}
}
});
// 5秒后解除压制
setTimeout(() => {
gameState.characters.forEach(char => {
if (char.isSuppressed) {
char.isSuppressed = false;
const charElement = document.getElementById(char.id);
if (charElement) {
charElement.querySelector('.character-img').classList.remove('suppressed');
}
}
});
}, 5000);
}
// 反制压制
function counterSuppression(npc, targetUsername) {
const npcElement = document.getElementById(npc.id);
if (npcElement) {
npcElement.querySelector('.character-img').classList.add('counter');
// 添加反制消息
addMessage(npc.username, `区区压制,也敢在本尊面前放肆!`);
// 播放反制音效
playSound('counter');
// 移除反制动画
setTimeout(() => {
npcElement.querySelector('.character-img').classList.remove('counter');
}, 1000);
}
// 压制发送者
const targetChar = gameState.characters.find(char => char.username === targetUsername);
if (targetChar) {
targetChar.isSuppressed = true;
const charElement = document.getElementById(targetChar.id);
if (charElement) {
charElement.querySelector('.character-img').classList.add('suppressed');
// 3秒后解除
setTimeout(() => {
targetChar.isSuppressed = false;
charElement.querySelector('.character-img').classList.remove('suppressed');
}, 3000);
}
}
}
// 反制动作
function counterAction(npc) {
const actions = scenes[gameState.currentScene].actions;
const counterAction = actions[Math.floor(Math.random() * actions.length)];
addMessage(npc.username, `${counterAction}!`);
createMessageBubble(npc.username, counterAction);
const npcElement = document.getElementById(npc.id);
if (npcElement) {
npcElement.querySelector('.character-img').classList.add('counter');
setTimeout(() => {
npcElement.querySelector('.character-img').classList.remove('counter');
}, 1000);
}
playActionSound(counterAction);
}
// 创建礼物特效
function createGiftEffect(type) {
const effect = document.createElement('div');
effect.className = 'gift-effect';
switch (type) {
case 'rocket':
effect.classList.add('fireworks');
playSound('fireworks');
break;
case 'sportsCar':
effect.classList.add('golden-aura');
playSound('gold');
break;
case 'carnival':
effect.classList.add('fireworks');
effect.classList.add('golden-aura');
playSound('carnival');
break;
}
document.getElementById('effects-container').appendChild(effect);
setTimeout(() => {
effect.remove();
}, 3000);
}
// 创建闪电效果
function createLightningEffect() {
const effect = document.createElement('div');
effect.className = 'gift-effect';
effect.style.background = 'linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.8) 50%, rgba(255,255,255,0) 100%)';
effect.style.animation = 'lightning 0.2s';
document.getElementById('effects-container').appendChild(effect);
setTimeout(() => {
effect.remove();
}, 500);
playSound('thunder');
}
// 播放场景音效
function playSceneSound(scene) {
// 在实际应用中,这里会播放对应场景的音效
console.log(`播放${scene}场景音效`);
}
// 播放动作音效
function playActionSound(action) {
// 在实际应用中,这里会播放对应动作的音效
console.log(`播放${action}动作音效`);
}
// 播放音效
function playSound(sound) {
// 在实际应用中,这里会播放对应音效
console.log(`播放${sound}音效`);
}
// 模拟NPC动作
function simulateNpcAction() {
gameState.npcs.forEach(npc => {
if (npc.scene === gameState.currentScene && Math.random() > 0.5) {
const actions = scenes[gameState.currentScene].actions;
const action = actions[Math.floor(Math.random() * actions.length)];
addMessage(npc.username, `${action}!`);
createMessageBubble(npc.username, action);
performAction(npc.username, action);
}
});
}
// 初始化游戏
window.onload = initGame;
</script>
</body>
</html>
游戏功能说明
-
多场景切换:
- 神魔战场、比武擂台、炼丹仙炉、打坐悟道、渡劫天雷、比武招亲
- 每个场景有独特的背景和可执行动作
-
用户参与机制:
- 用户发送消息后,系统生成角色(头像+抖音名+沙雕形象)
- 角色在场景中随机位置出现
- 用户消息显示为角色头顶的气泡
-
礼物特效系统:
- 发送特定关键词(火箭、跑车、嘉年华)触发礼物特效
- 礼物特效会对其他用户产生压制效果(角色变小变灰)
- 压制效果持续5秒后自动解除
-
大能NPC系统:
- 太上老君、魔尊重楼等特殊NPC
- 无视压制效果
- 可能反制用户的压制或动作
-
动态效果:
- 角色动作动画
- 礼物特效(烟花、金光等)
- 场景音效(在控制台模拟)
使用说明
- 在输入框中输入消息并发送
- 使用特定关键词触发特效:
- “火箭”:烟花特效
- “跑车”:金光特效
- “嘉年华”:组合特效
- 点击顶部按钮切换不同场景
- 观察NPC和用户角色的互动
这个实现包含了所有要求的功能点,并采用了沙雕动画风格。在实际抖音环境中,需要接入抖音API获取用户头像和昵称,并处理弹幕消息流。