博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从零开始写一个武侠冒险游戏-1-状态原型
阅读量:6588 次
发布时间:2019-06-24

本文共 7699 字,大约阅读时间需要 25 分钟。

hot3.png

从零开始写一个武侠冒险游戏-1-状态原型

概述

真正的从零开始, 一段代码一段代码, 一个函数一个函数地从头开始构思/编写一个武侠练功游戏

  • 环境要求: Codea + iPad

先写一个人物状态栏原型

我们这个游戏以人物的状态变化为核心, 一切都从这个核心出发, 所以最先编写的就是这个人物状态原型.

最简状态类原型

首先定义一下角色的状态栏:体力,内力,精力,智力,气,血,写个状态类把它们表现出来. 代码:

-- 角色状态类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

为方便调试,再写一个绘制方法, 代码如下:

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()endfunction draw()	background(32, 29, 29, 255)	myStatus:drawUI()end

把上述代码合起来,就是一个基本的角色状态了.

增加状态更新方法

角色的状态不可能凝固不变,因此,我们需要为角色状态类增加一个用来更新值的方法,原型调试阶段,简单实现最基本功能就可以了:

function Status:update()	-- 更新状态:自我修炼,日常休息,战斗	self.neili = self.neili + 10end

暂时用触摸动作来触发这个方法,在屏幕右半部分点击一次就会调用一次,增加触摸事件:

function touched(touch)	-- 调试用: 点击在屏幕右侧, 会触发 Status:update() , 刷新 self.neili 的值	if touch.x > WIDTH/2 and touch.state == ENDED then myStatus:update() endend

现在已经可以初步跑起来了, 点击会刷新状态值.

增加数据可视化:雷达图

基本雷达图

我们为了更直观地了解人物状态的变化, 写一个雷达图绘制函数, 具体调试过程就不赘述了, 总之是先写最简单的骨架结构, 再一步步填充丰满, 代码如下:

-- 角色技能雷达图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)endfunction Status:update()    -- 更新状态:自我修炼,日常休息,战斗    self.neili = self.neili + 1endfunction 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()endfunction 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)endfunction touched(touch)    if touch.x > WIDTH/2 and touch.state == ENDED then myStatus:update() endend

截图

把雷达图函数加载, 运行无误, 接下来可以选择的方向就多了--也意味着工作量和复杂度也大大增加了.

所有章节链接

---本章结束

转载于:https://my.oschina.net/freeblues/blog/687421

你可能感兴趣的文章
RAID 详解
查看>>
锁-概念:可重入锁、可中断锁、公平锁、读写锁
查看>>
参加培训的感想
查看>>
linux 查找并删除
查看>>
数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树
查看>>
request使用
查看>>
Win10文件管理器那些你不知道的秘密
查看>>
更改MyEclipse的默认编码
查看>>
Nordic Collegiate Programming Contest 2016
查看>>
cisco 交换机设置时区、时间、同步日志本地时间等操作
查看>>
获取网页源码
查看>>
从oracle到mysql,主从到分库,一个普通项目数据库架构的变迁
查看>>
数据结构
查看>>
一个简简单单检测http服务状态的脚本
查看>>
单例模式2014-12
查看>>
win32 ——定时器消息 小程序:打印时间
查看>>
USACO全部月赛及GateWay数据
查看>>
【AtCoder】ARC 081 E - Don't Be a Subsequence
查看>>
1 4 空格替换
查看>>
【专题】概率和期望
查看>>