在不思议创造制作卡牌游戏———by鸡块
关于在不思议创造制作卡牌游戏(1)
写在前面:
本篇教程面向有一定基础的制作者,但教程并不希望读者只学会一个复制粘贴。所以,本篇的脚本内容并不会很多,而更多的希望制作者自己来编写。
卡牌游戏以 杀戮尖塔 与 炉石传说 为代表,大致分为两类,本篇教程主要是复刻关于杀戮尖塔的游戏方式,而看完并能像模像样做出一个的,可以挑战更复杂的随从体系。
杀戮尖塔的游戏流程可以分为以下几步
我方回合开始
出牌
我方回合结束
敌方回合开始
敌方行动
敌方回合结束
看起来很简单,对吧。
我们首先来确定一下布局。
左边为我们的主角 右边放敌人 下面是卡牌 上面是状态栏
可用的空间差不多就用完了。
(关于想做横屏要删去上下底的,可以跳至最后,但我正着写攻略,到最后说不定就忘了这事,还是请开源地图搜索鸡块)
首先 我们如上图那样添加俩冈布奥。
为方便添加动画,我们使用创造自带的函数。
首先在物品栏里的怪物里复制两个怪物,换成需要的冈布奥图片。
然后新建一个高级脚本。
大概就像这样。
很好理解 第一行获取房间大小,下面依次创建主角敌人。
关于createmonster系列函数的运用,可以在开源图里搜索单位动画演示。
做成图片是为了...亲手打一遍更有感觉?
为方便想要扫描图片的,后面我会做成文本形式。
接下来我们来做一张卡牌。
随便写一个最基础的模板。
首先我们需要一个牌库来存放卡牌信息。
dataCards = {}
放入一张卡牌。
local t = {id=1,name="平A",ima=getusericon(),desc="造成5点伤害"}
table.insert(dataCards,t)
能想到的信息都写进去,卡牌编号,名字,使用的图片和描述。
以后需要什么可以再向内补充。
我们可能需要添加大量的卡牌,所以可以进行初步的封装。
local new = function(id,name,ima,desc)
local t = {id=id,name=name,ima=ima,desc=desc}
table.insert(dataCards,t)
return t
end
就是这样。
local t = new(1,"平A",getusericon(),"造成5点伤害。")
使用事件可以先留空,在有一个大致思路后回来填写。
t.trigger = function() end
在实际的卡牌显示中,可能出现因当前情况特殊而与最基本的描述不同,如杀戮尖塔中牌的伤害随你的力量而变化,如果不希望在更改时影响到你的基本描述,我们需要一个克隆函数。
随便在网上复制一个就好了。
function clone(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local newObject = {}
lookup_table[object] = newObject
for key, value in pairs(object) do
newObject[_copy(key)] = _copy(value)
end
return setmetatable(newObject, getmetatable(object))
end
return _copy(object)
end
那么这个函数是干什么用的?这里为不了解lua特性的读者解答,红字部分可直接跳过。
我们先来假设一个情况
a={}
a.b = 1
c=a
c.b = 2
这个时候,我们使用alert(a.b)
返回的结果是2
也就是说 当你认为你只是修改你复制后的表的时候,原来的表也发生了变化。
lua参考手册中是这样解释的:
表、函数、线程、以及完全用户数据在 Lua 中被称为 对象: 变量并不真的 持有 它们的值,而仅保存了对这些对象的 引用。 赋值、参数传递、函数返回,都是针对引用而不是针对值的操作, 这些操作均不会做任何形式的隐式拷贝。
用吃饭大佬的话简单来说,表就像一张写了门牌号的纸,你通过门牌号可以找到这个门,你可以拿另一张纸把门牌号抄录下来,但不会多出别的门。
所以 这个函数帮我们解决了这个问题。
然后显示的事交给精灵完成
displayc = function(Card)
local t = clone(Card)
local display = createsprite("images/editor/white.png",10000)
local x,y = getscenesize()
display.x,display.y = x/2,y/4
display:setcolor(0,0,0,200)
display:setsize(150,220)
local w,h = display:getsize()
local ima = createsprite(t.ima,10001)
display:addChild(ima)
ima.x,ima.y = w/2,h*13/18
ima:setsize(w/2,w/2)
display.ima = ima
local deco = createsprite("images/ui/common_bg/airship.png",10001)
display:addChild(deco)
deco:setanchor(0,1)
deco.x,deco.y = 0,h
deco:setsize(w*2/3,w/2)
display.deco = deco
local name = createlabel(t.name,10003)
display:addChild(name)
name.x,name.y = w/2,h*6/13
name.fontsize = w/6
display.name = name
local desc = createlabel("",10003)
local str = t.desc
desc:settext(str)
display:addChild(desc)
desc:setanchor(0.5,1)
desc.x,desc.y = w/2,h*1/3
desc.fontsize = w/8
display.desc = desc
return display
end
因为比较麻烦所以不写成注释,我们看看这段代码,定义一个函数,复制我们的卡牌信息表,第一个display为卡面,createsprite(image,layer)创建一个精灵,同样我们获取房间大小使它位于屏幕中央。为什么在这里给卡牌大小和位置赋值?我们总该在辛苦后先看到我们的成果。
下面也同样创建,这里有几个函数解释一下。
sprite.x,sprite.y=x,y 确定精灵的位置,不思议创造中一格宽128,高118(单位:像素)
getusericon() 是创造自带,获取用户头像
sprite:addChild(sprite) 把作为参数的精灵设置成第一个精灵的子精灵。子精灵以父精灵的坐标为它的坐标原点,同时若你对父精灵执行一个函数,对子精灵同样执行。在此处的用途还暂时只能看到方便坐标设置。
sprite:setanchor(x,y) 也是创造自带,原来的是:setAnchorPoint(),设置锚点。
参数在0-1之间,就是锚点在这个精灵中所占的位置
顾名思义,这个点把精灵定住,若使精灵旋转则围绕它的锚点旋转,一般默认在中心(0.5,0.5)处,(0,0)则为左下角,(0,1)则为左上角,以此类推。
比较好用的是,你设置精灵的xy坐标,其实就是在设置锚点坐标,我们需要用这个方式来避免以中心为锚点的不确定因素,上面的代码已经是一个实例说明了。
sprite:setsize(w,h) 设置精灵的大小,w为宽多少,h为高多少(单位:像素)
对于非正方形的精灵,在放缩时避免变形,可以使用
sprite:setscale(a,b) 其中的两个参数则是与原图片尺寸之比,当两值相同时则不会变形。
sprite:setcolor(r,g,b,blend) 颜色,每个参数范围0-255,就是六位颜色,第四个参数为透明度,0为完全透明,255为完全不透明
顺带一提,当你将透明值设置成257时,与1的效果是相同的。
下面两个createlabel() 则是创建文字精灵,sprite:settext设置内容,sprite.fontsize设置大小,还有个sprite.fontcolor设置函数,不过:setcolor是通用的,也就不说了。
(其实大部分都是通用的)
其中有两个图片"images/editor/white.png"和"images/ui/common_bg/airship.png",是创造自带,第一个是大小1个像素的白色,第二个是一个边框
更详细或者更多的用法,可以看看群文件或者直接百度cocos-2d api。
总之,5个精灵组成了一张简单卡牌的所有元素。
现在看看我们的成果,调用一下之前的函数。
a = displayc(t)
我们就这样完成了第一步,然后讲一下上下底的事。
我也不多说了,以下是实现内容:
local dialog = createdialog()
thread(function()
showdialog(dialog)
end)
local scene = dialog:getScene()
hidedialog(dialog)
dialog = nil
local main = nil
while(1) do
main = scene:getFormByName("UIDungeonMainC")
if(main and main:getUserPanel()) then
break
end
wait(0)
end
main:hideMenu()
main:showTop()
local ct = main.node:getChildByName("CT1")
ct:getChildren()[5]:setVisible(false)
ct:getChildren()[6]:setVisible(false)
那么这次攻略告一段落,第二期有缘再会
2020.2.7
鸡块