要開始實作了嗎…?別急,我們要等到第5章才會開始。
先別急著翻桌,這一章要介紹的是插件中常用的小技巧,還有必須具備的常識,免得做的時候格式錯了還得問東問西的。
這些技巧很雜,你可能會從別人的插件學習來,不過還是要有正確概念。
4.1. 物品、方塊、生物ID#
本資料取自英文WIKI,真的很重要,且它也有一直在更新。
網址在此: Pocket Edition data values
英文看不懂不打緊,它有附圖片參考。
方塊和ID要看的是Dec值那欄,Hex是該ID的16進制表示法。物品ID也是。
生物實體ID,其實你可以開啟modpescript_dump.txt翻生物代碼,不過有時代碼失效你就要來挖這裡的ID了。
4.2. 材質的作法與格式#
插件中所用的材質,我們先要有個概念:
如果你的東西是自己新增的,插件使用材質,是直接讀材質包資料夾images裡的,所以寫路徑時最前面無須把images寫出來。關於材質包的架構,請參考 這篇。
插件用材質包裡,方塊和物品以外的材質想放哪就放哪。
方塊與物品材質#
Block.defineBlock()和ModPE.setItem()會用到材質,它的格式是如何呢?
- 首先,請在images底下,新增terrain-atlas和item-opaque,2個資料夾。
前者是放方塊材質,後者是物品材質。
方塊和物品材質的命名,格式為 xxx_0.png 。
xxx是方塊或物品的名稱,藍字的部分目前只能寫這樣。
Block.defineBlock()要用材質時,只需寫出xxx,因為材質陣列中,後面都會附加一個0代表_0。
ModPE.setItem()也是只需寫xxx,因為副ID就代表了後面的_0。
如果你要直接使用遊戲中的方塊物品材質,請參考此網站,材質名稱直接填裡面給的就好。
範例:
有一個物品稱做test_0.png,插件裡只需寫ModPE.setItem(1000,“test”,0,“TS”)。
生物材質#
想放哪就放哪,格式為 XXX.png 。
Level.spawnmob()、Entity.setMobSkin()會用到,在材質字串中,只需寫"路徑/材質名稱",路徑為images底下則直接寫檔案名稱。
範例:
images/mob資料夾有creepety.png,生成該生物時只需寫Level.spawnMob(x,y,z,36,“mob/creepety.png”)。
4.3. BlockLauncher資源的運用#
前置作業中我談過modpescript_dump.txt要時常更新,不是沒有道理。
近期,作者逐漸在裡面加入一些有用的資源 (當然你不懂還是直接去問作者比較快)
一直往下翻,會看到有註解的函數列表,作者會註明哪些能用preventDefault(),或者雖不知用法,卻能先知道有哪些函數。
再後面每寫幾個東西就分段,這是一些代碼。
- ChatColor:文字顏色,比樣式代碼易讀
- ItemCategory:物品分類代碼
- ParticleType:粒子代碼
- EntityType:生物ID代碼
- EntityRenderType:生物模型代碼
- ArmorType:裝甲類別代碼
- MobEffect:藥水效果代碼
- DimensionId:玩家所處世界代碼
- BlockFace:方塊方向代碼(就是useItem()裡的side)
- UseAnimation:動畫代碼
- Enchantment:附魔效果代碼
- EnchantType:可附魔的工具代碼
- BlockRenderLayer:方塊模型代碼
4.4. 算法分享#
這裡的算法從網路上各個插件中擷取出來,方便進行運算,僅供參考用。
飛行 + 前進算法#
玩家的頭若低下,則實體會停留在原地,否則則會隨著玩家的頭方向前進/飛行。主要用於飛行物,若去掉Y則也可以用做自動前進。
var p=((Entity.getPitch(Player.getEntity())+90)*Math.PI)/180;
var y=((Entity.getYaw(Player.getEntity())+90)*Math.PI)/180;
var xx=Math.sin(p)*Math.cos(y);
var yy=Math.sin(p)*Math.sin(y);
var zz=Math.cos(p);
Entity.setVelX(nowRiding,1*xx);//這裡1都可以改掉,跟前進速度成正比。nowRiding為實體對象
Entity.setVelY(nowRiding,1*zz); //若不想飛行也可以去掉Y
Entity.setVelZ(nowRiding,1*yy);
跑步算法#
參考來源: http://www.minecraftforum.net/forums/minecraft-pocket-edition/mcpe-mods-tools/1986186-sprint-mod
以前沒有跑步時需要,現在則是能讓玩家跑得更快用。
var xSave = 0 ,ySave = 0 ,zSave = 0
;//玩家舊的座標,y可以不設定,總不會跑到飛起來吧。
var x = 0, y = 0 , z = 0;//玩家現在的座標
var power=0.7;//需要變動的只有此值,與跑步速度成正比。
function modTick(){
x = Player.getX();
y = Player.getY();
z = Player.getZ();//不斷偵測玩家座標
if (!(x-xSave==0)){ //當前座標減舊座標若>0,代表玩家移動
Entity.setVelX(Player.getEntity(),(x-xSave)*power);//將玩家往X方向推,移動值互減若>0,則玩家正向移動;反之則負向移動。Z座標同理。
xSave = x;//更新舊座標。
if (!(z-zSave==0)){ //同X
Entity.setVelZ(Player.getEntity(), (z-zSave)*power);//同X
zSave = z;//同X
}
}
}
生成礦物的算法#
資料來源:http://www.minecraftforum.net/forums/minecraft-pocket-edition/mcpe-mods-tools/2560455-how-to-generate-ores-random-with-modpe-nearly
以下的註解皆翻譯自原始文章。
var tick=0;
var curX=0;
var curY=0;
var curZ=0;
var cX=0;
var cY=0;
var cZ=0;
var count=0;
var changeBack=false;
/*
可以改動的值:
●新增的礦物 (22行),你也可以加入更多
●生成礦物的高度(186行和188行)
● 礦脈有多廣(190行)
●setTile2這個函數 (164行), 你想要的話,也可以改成什麼方塊不要被取代。
●多複製180行到229行的程式碼幾次,來生成更多礦物
●更改生成礦物的可能性(181行)
*/
try{
Block.defineBlock(220, "Copper Ore", [["copper_ore", 0]], 1, false, 0); //新增方塊,這裡的例子是銅礦
}catch(error){
print("Import the texture pack first!");
}
function modTick(){
tick++;
if(tick%100==0){ //每5秒就執行一次doTick()
doTick();
}
}
function doTick(){
if(Player.getDimension()==DimensionId.NORMAL){ //讓礦物只在主世界生成
curX=Math.floor(Player.getX());
curZ=Math.floor(Player.getZ());
for(var i=0; i<16; i++){
if(curX<0){
changeBack=true;
curX=curX*(-1);
}
if(curX%16!=0){
curX--;
}
if(changeBack){
curX=curX*(-1);
}
changeBack=false;
if(curZ<0){
changeBack=true;
curZ=curZ*(-1);
}
if(curZ%16!=0){
curZ--;
}
if(changeBack){
curZ=curZ*(-1);
}
changeBack=false;
}
curX++;
curZ++;
spawnOres();
curX=curX+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curZ=curZ+16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curX=curX-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curZ=curZ-16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
curX=curX+16;
spawnOres();
}
}
setTile2(p1, p2, p3, p4, p5){ //這裡為生成礦物添加更多可能生成的區塊,這裡僅取代石頭
if(Level.getTile(p1, p2, p3)==1){ //如果那個座標是石頭,就取代它
Level.setTile(p1, p2, p3, p4, p5);
}
}
function spawnOres(){ //生成礦物
if(Level.getTile(curX, 1, curZ)!=57){
Level.setTile(curX, 1, curZ, 57, 0);
Level.setTile(curX, 0, curZ, 7, 0);
Level.setTile(curX, 2, curZ, 7, 0);
Level.setTile(curX+1, 1, curZ, 7, 0);
Level.setTile(curX-1, 1, curZ, 7, 0);
Level.setTile(curX, 1, curZ+1, 7, 0);
Level.setTile(curX, 1, curZ-1, 7, 0);
//開始生成礦物
//從183行開始複製到229行,如果你想要更多礦物,可以多重複這步驟幾次
if(Math.floor(Math.random()*20)>7){ //計算機率,有到才開始執行以下生成礦物的程式碼
cX=curX;
cZ=curZ;
cX=cX+Math.floor(Math.random()*10)+2; //隨機的X座標
cZ=cZ+Math.floor(Math.random()*10)+2; //隨機的Z座標
cY=Math.floor(Math.random()*30)+10; //隨機的高度 (此範例是10到40) , 你可以自己設定,通常大於5比較好,免得破壞基岩
if(Level.getBiomeName(curX, curZ)=="Ocean"){ //如果要在海裡生成礦物
cY=Math.floor(Math.random()*25)+5; //隨機高度(此範例為5到30)
}
count=Math.floor(Math.random()*12)+3; //要生成多少個礦物(此範例為3到15)
setTile2(cX, cY, cZ, 220, 0); //220就是我們剛剛新增的礦物ID
for(var i=0; i<count; i++){
if(Math.floor(Math.random()*3)+1==2){
cX++;
}else{
if(Math.floor(Math.random()*3)+1==2){
//什麼也不做
}else{
cX--;
}
}
if(Math.floor(Math.random()*3)+1==2){
cZ++;
}else{
if(Math.floor(Math.random()*3)+1==2){
//什麼也不做
}else{
cZ--;
}
}
if(Math.floor(Math.random()*3)+1==2){
cY++;
if(cY>50){
cY--;
}
}else{
if(Math.floor(Math.random()*3)+1==2){
//什麼也不做
}else{
cY--;
if(cY<5){
cY++;
}
}
}
setTile2(cX, cY, cZ, 220, 0); //220就是我們剛剛新增的礦物ID
}
}
//銅礦生成的程式碼結束
//礦物生成的程式碼結束
}
//
}