动态NFT的最大优势就如其名—高度的变化性和延展性。它可以呈现出比静态NFT更多的元素,比如动画、声音、互动式图像等,而且能随着时间或条件产生元数据(Metadata)的变动。举例来说,一个动态NFT的艺术品可以在不同的时间点呈现不同的风格或表现出不同的情感;一个动态NFT的游戏道具可以随着游戏进程升级,提高了游戏的互动性和可玩性。
动态NFT可以更新Metadata的内容,从而改变NFT的外观和属性。
这主要功亏于其对数据的接受性,您可以透过「链上数据」或「链下数据」来更改您NFT的属性。其中链上数据可以通过智能合约直接访问,链下数据则需透过预言机(Oracle)进行网上数据抓取后,再添加到区块链中。
如何建造你自己的动态NFT
写动态NFT需要具备一定的技术知识和专业技能,因此下文将针对基础的建构步骤协助您筹备项目。
步骤一:确定您的设计
首先,你需要确定您的NFT设计。请注意,这边不单单只你的NFT图像,而是涵盖这个项目的所有计画(白皮书、路线图等等),因为这会直接影响未来dNFT的变化形式以及智能合约的撰写。举例来说,你的dNFT可以是艺术品、游戏道具、音乐作品或是实体资产绑定等等。你需要考虑元素的可变化性和互动性,以及它们如何为持有者提供更多的价值和体验。
步骤二:选择你的公链
接下来,您需要选择你欲发布的公链。像是以太坊、币安链、Polygon等等,这些平台都支援动态NFT的创建和发行。但请注意,你选择的链会直接影响撰写智能合约时所使用的程式语言。
步骤三:编写智能合约
编写智能合约是创建动态NFT的关键步骤。你需要使用Solidity或其他支持NFT创建的程式语言(eg Rust、Vyper和Move)来创建智能合约,这个合约会结合metadata来定义NFT的属性、图像。在创建动态NFT时,你需要确定动态元素的变化方式和变化频率,以及它们发布后如何与智能合约互动。
//Vanilla JS
//PLAY IN FULL PAGE VIEW!
window.addEventListener("DOMContentLoaded",game);
//General sprite load
var sprite=new Image();
var spriteExplosion=new Image();
sprite.src='img/sprite.png';
window.onload=function(){
spriteExplosion.src='img/explosion.png';
};
//Game
function game(){
//Canvas
var canvas=document.getElementById('canvas'),
ctx=canvas.getContext('2d'),
cH=ctx.canvas.height=window.innerHeight,
cW=ctx.canvas.width=window.innerWidth;
//Game
var bullets=[],
asteroids=[],
explosions=[],
destroyed=0,
record=0,
count=0,
playing=false,
gameOver=false,
_planet={deg:0};
//Player
var player={
posX:-35,
posY:-(100+82),
width:70,
height:79,
deg:0
};
canvas.addEventListener('click',action);
canvas.addEventListener('mousemove',action);
window.addEventListener("resize",update);
function update(){
cH=ctx.canvas.height=window.innerHeight;
cW=ctx.canvas.width=window.innerWidth;
}
function move(e){
player.deg=Math.atan2(e.offsetX-(cW/2),-(e.offsetY-(cH/2)));
}
function action(e){
e.preventDefault();
if(playing){
var bullet={
x:-8,
y:-179,
sizeX:2,
sizeY:10,
realX:e.offsetX,
realY:e.offsetY,
dirX:e.offsetX,
dirY:e.offsetY,
deg:Math.atan2(e.offsetX-(cW/2),-(e.offsetY-(cH/2))),
destroyed:false
};
bullets.push(bullet);
}else{
var dist;
if(gameOver){
dist=Math.sqrt(((e.offsetX-cW/2)(e.offsetX-cW/2))+((e.offsetY-(cH/2+45+22))(e.offsetY-(cH/2+45+22))));
if(dist<27){
if(e.type=='click'){
gameOver=false;
count=0;
bullets=[];
asteroids=[];
explosions=[];
destroyed=0;
player.deg=0;
canvas.removeEventListener('contextmenu',action);
canvas.removeEventListener('mousemove',move);
canvas.style.cursor="default";
}else{
canvas.style.cursor="pointer";
}
}else{
canvas.style.cursor="default";
}
}else{
dist=Math.sqrt(((e.offsetX-cW/2)(e.offsetX-cW/2))+((e.offsetY-cH/2)(e.offsetY-cH/2)));
if(dist<27){
if(e.type=='click'){
playing=true;
canvas.removeEventListener("mousemove",action);
canvas.addEventListener('contextmenu',action);
canvas.addEventListener('mousemove',move);
canvas.setAttribute("class","playing");
canvas.style.cursor="default";
}else{
canvas.style.cursor="pointer";
}
}else{
canvas.style.cursor="default";
}
}
}
}