真正的从零开始, 一段代码一段代码, 一个函数一个函数地从头开始构思/编写一个武侠练功游戏框架
咱们这个游戏以人物的状态变化为核心, 一切都从这个核心出发, 因此最早编写的就是这我的物状态原型.函数
首先定义一下角色的状态栏:体力,内力,精力,智力,气,血,写个状态类把它们表现出来. 代码:动画
-- 角色状态类 Status = class() function Status:init() -- 体力,内力,精力,智力,气,血 self.tili = 100 self.neili = 0 self.jingli = 100 self.zhili = 100 self.qi = 100 self.xue = 100 -- 申请一个 200* 300 的图片, 用来绘制状态 self.img = image(200, 300) end
为方便调试,再写一个绘制方法, 代码以下:.net
function Status:drawUI() -- 把全部内容先绘制到 self.img 上 setContext(self.img) background(119, 121, 72, 255) fill(36, 112, 111, 255) rect(5,5,200-10,300-10) fill(70, 255, 0, 255) textAlign(LEFT) text("体力: "..self.tili,50,280) text("内力: "..self.neili,50,260) text("精力: "..self.jingli,50,240) text("智力: "..self.zhili,50,220) text("气 : "..self.qi,50,200) text("血 : "..self.xue,50,180) setContext() sprite(self.img, 200,300) end
最后是一个主程序框架:调试
-- 主程序框架 function setup() displayMode(OVERLAY) myStatus = Status() end function draw() background(32, 29, 29, 255) myStatus:drawUI() end
把上述代码合起来,就是一个基本的角色状态了.code
角色的状态不可能凝固不变,所以,咱们须要为角色状态类增长一个用来更新值的方法,原型调试阶段,简单实现最基本功能就能够了:blog
function Status:update() -- 更新状态:自我修炼,平常休息,战斗 self.neili = self.neili + 10 end
暂时用触摸动做来触发这个方法,在屏幕右半部分点击一次就会调用一次,增长触摸事件:游戏
function touched(touch) -- 调试用: 点击在屏幕右侧, 会触发 Status:update() , 刷新 self.neili 的值 if touch.x > WIDTH/2 and touch.state == ENDED then myStatus:update() end end
如今已经能够初步跑起来了, 点击会刷新状态值.事件
咱们为了更直观地了解人物状态的变化, 写一个雷达图绘制函数, 具体调试过程就不赘述了, 总之是先写最简单的骨架结构, 再一步步填充丰满, 代码以下:图片
-- 角色技能雷达图 function Status:raderGraph() setContext(self.img) pushMatrix() pushStyle() fill(60, 230, 30, 255) -- 中心坐标,半径,角度 local x0,y0,r,a,s = 150,230,40,360/6,4 -- 计算右上方斜线的坐标 local x,y = r* math.cos(math.rad(30)), r* math.sin(math.rad(30)) p = {"体力","内力","精力","智力","气","血"} axis = {t={vec2(0,r/s),vec2(0,r*2/s),vec2(0,r*3/s),vec2(0,r)}, n={vec2(-x/s,y/s),vec2(-x*2/s,y*2/s),vec2(-x*3/s,y*3/s),vec2(-x,y)}, j={vec2(-x/s,-y/s),vec2(-x*2/s,-y*2/s),vec2(-x*3/s,-y*3/s),vec2(-x,-y)}, z={vec2(0,-r/s),vec2(0,-r*2/s),vec2(0,-r*3/s),vec2(0,-r)}, q={vec2(x/s,-y/s),vec2(x*2/s,-y*2/s),vec2(x*3/s,-y*3/s),vec2(x,-y)}, x={vec2(x/s,y/s),vec2(x*2/s,y*2/s),vec2(x*3/s,y*3/s),vec2(x,y)}} -- 用于绘制圈线的函数 function lines(t,n,j,z,q,x) line(axis.n[n].x, axis.n[n].y, axis.t[t].x, axis.t[t].y) line(axis.n[n].x, axis.n[n].y, axis.j[j].x, axis.j[j].y) line(axis.x[x].x, axis.x[x].y, axis.t[t].x, axis.t[t].y) line(axis.z[z].x, axis.z[z].y, axis.j[j].x, axis.j[j].y) line(axis.x[x].x, axis.x[x].y, axis.q[q].x, axis.q[q].y) line(axis.z[z].x, axis.z[z].y, axis.q[q].x, axis.q[q].y) end -- 平移到中心 (x0,y0), 方便以此为中心旋转 translate(x0,y0) -- 围绕中心点匀速旋转 rotate(30+ElapsedTime*10) -- 绘制背景圆环 fill(57, 121, 189, 84) strokeWidth(0) ellipse(0,0,2*r/s) ellipse(0,0,4*r/s) ellipse(0,0,6*r/s) ellipse(0,0,r*2) strokeWidth(2) -- noSmooth() stroke(93, 227, 22, 255) fill(60, 230, 30, 255) -- 绘制雷达图 for i=1,6 do text(p[i],0,45) line(0,0,0,r) rotate(a) end -- 绘制圈线 stroke(255, 0, 0, 102) strokeWidth(2) for i = 1,4 do lines(i,i,i,i,i,i) end end stroke(255, 32, 0, 255) strokeWidth(2) smooth() -- 设定当前各参数的值 print(values()) local t,n,j,z,q,x = 3,2,3,2,4,1 local t,n,j,z,q,x = values() lines(t,n,j,z,q,x) popStyle() popMatrix() setContext() end
基本的雷达图代码写完了, 如今绘制出来的仍是一个静态的雷达图, 咱们但愿能根据状态值的刷新而实时更新雷达图, 那么就是把这段代码修改一下, 由于这段代码只是把 3,2,3,2,4,1
这些固定值赋给这几个局部变量:
local t,n,j,z,q,x = 3,2,3,2,4,1 lines(t,n,j,z,q,x)
在函数 Status:raderGraph()
内部写一个函数, 把这几个局部变量 t,n,j,z,q,x
跟状态类的各个属性 self.tili
等关联起来, 也就是作一个赋值:
-- 处理人物状态值, 根据它的值大小将其缩减为 1,2,3,4 并返回 function values() local t,n,j,z,q,x = self.tili, self.neili, self.jingli,self.zhili, self.qi, self.xue local f = math.floor return f(t/25),f((25+math.fmod(n,100))/25),f(j/25),f(z/25),f(q/25),f(x/25) end
把这条语句
local t,n,j,z,q,x = 3,2,3,2,4,1
换成下面这条:
local t,n,j,z,q,x = values()
很好, 如今咱们的雷达图就能够随着状态值的变化而变化了
不过这种变化仍是不太明显, 咱们再增长一个旋转效果, 增长以下语句到相应位置:
-- 围绕中心点匀速旋转 rotate(30+ElapsedTime*10)
这样就会产生一个实时旋转的效果了, 所有代码以下:
-- 角色状态类 Status = class() function Status:init() -- 体力,内力,精力,智力,气,血 self.tili = 100 self.neili = 90 self.jingli = 70 self.zhili = 100 self.qi = 100 self.xue = 100 self.img = image(200, 300) end function Status:update() -- 更新状态:自我修炼,平常休息,战斗 self.neili = self.neili + 1 end function Status:drawUI() setContext(self.img) background(119, 121, 72, 255) pushStyle() fill(36, 112, 111, 255) rect(5,5,200-10,300-10) fill(70, 255, 0, 255) textAlign(RIGHT) text("体力: "..self.tili,50,280) text("内力: "..self.neili,50,260) text("精力: "..self.jingli,50,240) text("智力: "..self.zhili,50,220) text("气 : "..self.qi,50,200) text("血 : "..self.xue,50,180) sprite("Documents:B1", 100,90) popStyle() setContext() self:raderGraph() sprite(self.img, 400,300) end -- 角色技能雷达图 function Status:raderGraph() setContext(self.img) pushMatrix() pushStyle() fill(60, 230, 30, 255) -- 中心坐标,半径,角度 local x0,y0,r,a,s = 150,230,40,360/6,4 -- 计算右上方斜线的坐标 local x,y = r* math.cos(math.rad(30)), r* math.sin(math.rad(30)) p = {"体力","内力","精力","智力","气","血"} axis = {t={vec2(0,r/s),vec2(0,r*2/s),vec2(0,r*3/s),vec2(0,r)}, n={vec2(-x/s,y/s),vec2(-x*2/s,y*2/s),vec2(-x*3/s,y*3/s),vec2(-x,y)}, j={vec2(-x/s,-y/s),vec2(-x*2/s,-y*2/s),vec2(-x*3/s,-y*3/s),vec2(-x,-y)}, z={vec2(0,-r/s),vec2(0,-r*2/s),vec2(0,-r*3/s),vec2(0,-r)}, q={vec2(x/s,-y/s),vec2(x*2/s,-y*2/s),vec2(x*3/s,-y*3/s),vec2(x,-y)}, x={vec2(x/s,y/s),vec2(x*2/s,y*2/s),vec2(x*3/s,y*3/s),vec2(x,y)}} -- 用于绘制圈线的函数 function lines(t,n,j,z,q,x) line(axis.n[n].x, axis.n[n].y, axis.t[t].x, axis.t[t].y) line(axis.n[n].x, axis.n[n].y, axis.j[j].x, axis.j[j].y) line(axis.x[x].x, axis.x[x].y, axis.t[t].x, axis.t[t].y) line(axis.z[z].x, axis.z[z].y, axis.j[j].x, axis.j[j].y) line(axis.x[x].x, axis.x[x].y, axis.q[q].x, axis.q[q].y) line(axis.z[z].x, axis.z[z].y, axis.q[q].x, axis.q[q].y) end -- 平移到中心 (x0,y0), 方便以此为中心旋转 translate(x0,y0) -- 围绕中心点匀速旋转 rotate(30+ElapsedTime*10) fill(57, 121, 189, 84) strokeWidth(0) ellipse(0,0,2*r/s) ellipse(0,0,4*r/s) ellipse(0,0,6*r/s) ellipse(0,0,r*2) strokeWidth(2) -- noSmooth() stroke(93, 227, 22, 255) fill(60, 230, 30, 255) -- 绘制雷达图 for i=1,6 do text(p[i],0,45) line(0,0,0,r) rotate(a) end -- 绘制圈线 stroke(255, 0, 0, 102) strokeWidth(2) for i = 1,4 do lines(i,i,i,i,i,i) end function values() local t,n,j,z,q,x = self.tili, self.neili, self.jingli,self.zhili, self.qi, self.xue local f = math.floor return f(t/25),f((25+math.fmod(n,100))/25),f(j/25),f(z/25),f(q/25),f(x/25) end stroke(255, 32, 0, 255) strokeWidth(2) smooth() -- 设定当前各参数的值 print(values()) -- local t,n,j,z,q,x = 3,2,3,2,4,1 local t,n,j,z,q,x = values() lines(t,n,j,z,q,x) popStyle() popMatrix() setContext() end -- main 主程序框架 function setup() displayMode(OVERLAY) myStatus = Status() end function draw() background(32, 29, 29, 255) myStatus:drawUI() -- myStatus:raderGraph() fill(143, 255, 0, 255) rect(WIDTH/2,HEIGHT/2,200,200) fill(0, 55, 255, 255) text("修炼", WIDTH/2+100, HEIGHT/2+100) end function touched(touch) if touch.x > WIDTH/2 and touch.state == ENDED then myStatus:update() end end
把雷达图函数加载, 运行无误, 接下来能够选择的方向就多了--也意味着工做量和复杂度也大大增长了.
从零开始写一个武侠练功游戏-1-状态原型
从零开始写一个武侠练功游戏-2-帧动画
---本章结束