Remotion LabRemotion Lab
返回模板庫

挑選遊戲引擎的兩個條件

動畫展示挑選遊戲引擎的兩大標準:必須完全透過程式碼生成(不需 GUI)、以及支援 MCP 串接,附帶 SVG 圖示動畫。

遊戲開發引擎選擇MCP程式碼生成
提示詞(可直接修改內容)
import React from "react";
import {
  AbsoluteFill,
  useCurrentFrame,
  useVideoConfig,
  interpolate,
  spring,
} from "remotion";

const colors = {
  background: "#0A0E14",
  backgroundGradient: "linear-gradient(135deg, #0A0E14 0%, #131A24 100%)",
  text: "#FFFFFF",
  accent: "#00D4AA",
  accentSecondary: "#4DA3FF",
  warning: "#FFB547",
  danger: "#FF6B6B",
  dimmed: "rgba(255, 255, 255, 0.6)",
  cardBg: "rgba(255, 255, 255, 0.05)",
  border: "rgba(0, 212, 170, 0.3)",
};
const fonts = { main: "'Inter', 'Noto Sans TC', sans-serif" };

const CodeIcon: React.FC<{ progress: number; size?: number }> = ({ progress, size = 80 }) => {
  const pathLen = 200;
  const dashOffset = pathLen * (1 - progress);
  return (
    <svg width={size} height={size} viewBox="0 0 60 60" fill="none">
      <polyline points="20,12 8,30 20,48" stroke={colors.accent} strokeWidth="4" strokeLinecap="round" strokeLinejoin="round" fill="none" strokeDasharray={pathLen} strokeDashoffset={dashOffset} />
      <polyline points="40,12 52,30 40,48" stroke={colors.accent} strokeWidth="4" strokeLinecap="round" strokeLinejoin="round" fill="none" strokeDasharray={pathLen} strokeDashoffset={dashOffset} />
      <line x1="34" y1="10" x2="26" y2="50" stroke={colors.accentSecondary} strokeWidth="3" strokeLinecap="round" strokeDasharray={pathLen} strokeDashoffset={dashOffset} />
    </svg>
  );
};

const NoGuiIcon: React.FC<{ progress: number; crossProgress: number; size?: number }> = ({ progress, crossProgress, size = 80 }) => {
  const pathLen = 400;
  const dashOffset = pathLen * (1 - progress);
  return (
    <svg width={size} height={size} viewBox="0 0 60 60" fill="none">
      <rect x="6" y="8" width="48" height="38" rx="6" stroke={colors.dimmed} strokeWidth="2.5" strokeDasharray={pathLen} strokeDashoffset={dashOffset} fill="none" opacity={0.5} />
      <line x1="6" y1="18" x2="54" y2="18" stroke={colors.dimmed} strokeWidth="1.5" opacity={progress * 0.3} />
      <circle cx="14" cy="13" r="2" fill={colors.danger} opacity={progress * 0.6} />
      <circle cx="22" cy="13" r="2" fill={colors.warning} opacity={progress * 0.6} />
      <circle cx="30" cy="13" r="2" fill={colors.accent} opacity={progress * 0.6} />
      {crossProgress > 0 && (
        <>
          <line x1="12" y1="12" x2={12 + 36 * crossProgress} y2={12 + 36 * crossProgress} stroke={colors.danger} strokeWidth="4" strokeLinecap="round" opacity={0.8} />
          <line x1="48" y1="12" x2={48 - 36 * crossProgress} y2={12 + 36 * crossProgress} stroke={colors.danger} strokeWidth="4" strokeLinecap="round" opacity={0.8} />
        </>
      )}
    </svg>
  );
};

const McpPlugIcon: React.FC<{ progress: number; connected: boolean; size?: number }> = ({ progress, connected, size = 80 }) => {
  const pathLen = 300;
  const dashOffset = pathLen * (1 - progress);
  const plugOffset = connected ? 0 : 12;
  return (
    <svg width={size} height={size} viewBox="0 0 60 60" fill="none">
      <g transform={`translate(${-plugOffset}, 0)`}>
        <rect x="6" y="20" width="20" height="20" rx="4" stroke={colors.accentSecondary} strokeWidth="2.5" fill="none" strokeDasharray={pathLen} strokeDashoffset={dashOffset} />
        <line x1="26" y1="26" x2="30" y2="26" stroke={colors.accentSecondary} strokeWidth="3" strokeLinecap="round" opacity={progress} />
        <line x1="26" y1="34" x2="30" y2="34" stroke={colors.accentSecondary} strokeWidth="3" strokeLinecap="round" opacity={progress} />
      </g>
      <g transform={`translate(${plugOffset}, 0)`}>
        <rect x="34" y="20" width="20" height="20" rx="4" stroke={colors.accent} strokeWidth="2.5" fill="none" strokeDasharray={pathLen} strokeDashoffset={dashOffset} />
        <circle cx="40" cy="26" r="2" fill={colors.accent} opacity={progress * 0.7} />
        <circle cx="40" cy="34" r="2" fill={colors.accent} opacity={progress * 0.7} />
      </g>
      {connected && progress > 0.8 && <circle cx="30" cy="30" r="4" fill={colors.warning} opacity={0.7} />}
      <text x="30" y="54" textAnchor="middle" fontSize="10" fontWeight="bold" fontFamily="monospace" fill={colors.accent} opacity={progress}>MCP</text>
    </svg>
  );
};

const CriteriaCard: React.FC<{ number: number; text: string; highlight: string; icon: React.ReactNode; progress: number; y: number }> = ({ number, text, highlight, icon, progress, y }) => {
  const scale = interpolate(progress, [0, 0.5, 1], [0.8, 1.02, 1]);
  const opacity = interpolate(progress, [0, 0.3], [0, 1], { extrapolateRight: "clamp" });
  const slideX = interpolate(progress, [0, 1], [-60, 0]);
  return (
    <div style={{ position: "absolute", left: "50%", top: y, transform: `translate(-50%, -50%) translateX(${slideX}px) scale(${scale})`, opacity, display: "flex", alignItems: "center", gap: 54, width: 1650 }}>
      <div style={{ width: 96, height: 96, borderRadius: "50%", background: `linear-gradient(135deg, ${colors.accent}, ${colors.accentSecondary})`, display: "flex", alignItems: "center", justifyContent: "center", fontSize: 48, fontWeight: 800, fontFamily: fonts.main, color: "#000", flexShrink: 0 }}>{number}</div>
      <div style={{ flex: 1, background: colors.cardBg, border: `1.5px solid ${colors.border}`, borderRadius: 16, padding: "24px 32px", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 36 }}>
        <div style={{ fontSize: 51, fontWeight: 600, fontFamily: fonts.main, color: colors.text, lineHeight: 1.5, letterSpacing: 1 }}>
          {text}<span style={{ color: colors.accent, fontWeight: 700 }}>{highlight}</span>
        </div>
        <div style={{ flexShrink: 0 }}>{icon}</div>
      </div>
    </div>
  );
};

export const Scene04-EngineCriteria: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();

  const titleSpring = spring({ frame: Math.max(0, frame - 5), fps, config: { damping: 14, mass: 0.8, stiffness: 100 } });
  const titleY = interpolate(titleSpring, [0, 1], [50, 0]);
  const titleOpacity = interpolate(frame, [5, 25], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  const cond1Spring = spring({ frame: Math.max(0, frame - 40), fps, config: { damping: 12, mass: 0.8, stiffness: 90 } });
  const codeIconDraw = interpolate(frame, [50, 90], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const noGuiDraw = interpolate(frame, [60, 95], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const crossDraw = interpolate(frame, [90, 110], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  const cond2Spring = spring({ frame: Math.max(0, frame - 120), fps, config: { damping: 12, mass: 0.8, stiffness: 90 } });
  const mcpDraw = interpolate(frame, [130, 170], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const mcpConnected = frame > 170;

  const fadeOut = interpolate(frame, [210, 240], [1, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  return (
    <AbsoluteFill style={{ background: colors.backgroundGradient }}>
      <AbsoluteFill style={{ opacity: fadeOut }}>
        <div style={{ position: "absolute", top: 100, left: 0, right: 0, textAlign: "center", fontSize: 84, fontWeight: 700, color: colors.text, fontFamily: fonts.main, letterSpacing: 4, transform: `translateY(${titleY}px)`, opacity: titleOpacity }}>
          挑選引擎的
          <span style={{ background: `linear-gradient(90deg, ${colors.accent}, ${colors.accentSecondary})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" }}>兩個條件</span>
        </div>
        <CriteriaCard number={1} text="完全透過程式碼生成," highlight="不需要操作 GUI" y={380} progress={cond1Spring} icon={<div style={{ display: "flex", alignItems: "center", gap: 12 }}><CodeIcon progress={codeIconDraw} size={105} /><NoGuiIcon progress={noGuiDraw} crossProgress={crossDraw} size={105} /></div>} />
        <CriteriaCard number={2} text="GUI 介面有 " highlight="MCP 可以串接更好" y={600} progress={cond2Spring} icon={<McpPlugIcon progress={mcpDraw} connected={mcpConnected} size={120} />} />
      </AbsoluteFill>
    </AbsoluteFill>
  );
};

登入後查看完整程式碼