2019独角兽企业重金招聘Python工程师标准>>>

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

概述

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

  • 环境要求: Codea + iPad

先写一个人物状态栏原型

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

最简状态类原型

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

-- 角色状态类
Status = class()function Status:init()-- 体力,内力,精力,智力,气,血self.tili = 100self.neili = 0self.jingli = 100self.zhili = 100self.qi = 100self.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 + 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 dotext(p[i],0,45)line(0,0,0,r)rotate(a)end-- 绘制圈线stroke(255, 0, 0, 102)strokeWidth(2)for i = 1,4 dolines(i,i,i,i,i,i)endendstroke(255, 32, 0, 255)strokeWidth(2)smooth()-- 设定当前各参数的值print(values())local t,n,j,z,q,x = 3,2,3,2,4,1local 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.xuelocal f = math.floorreturn 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 = 100self.neili = 90self.jingli = 70self.zhili = 100self.qi = 100self.xue = 100self.img = image(200, 300)
endfunction Status:update()-- 更新状态:自我修炼,日常休息,战斗self.neili = self.neili + 1
endfunction 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 dotext(p[i],0,45)line(0,0,0,r)rotate(a)end-- 绘制圈线stroke(255, 0, 0, 102)strokeWidth(2)for i = 1,4 dolines(i,i,i,i,i,i)endfunction values()local t,n,j,z,q,x = self.tili, self.neili, self.jingli,self.zhili, self.qi, self.xuelocal f = math.floorreturn f(t/25),f((25+math.fmod(n,100))/25),f(j/25),f(z/25),f(q/25),f(x/25)endstroke(255, 32, 0, 255)strokeWidth(2)smooth()-- 设定当前各参数的值print(values())-- local t,n,j,z,q,x = 3,2,3,2,4,1local 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() end
end

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

所有章节链接

从零开始写一个武侠练功游戏-1-状态原型
从零开始写一个武侠练功游戏-2-帧动画

---本章结束

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

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

  1. 从零开始写一个武侠冒险游戏-6-用GPU提升性能(1)

    从零开始写一个武侠冒险游戏-6-用GPU提升性能(1) ----把帧动画的实现放在GPU上 作者:FreeBlues 修订记录 2016.06.19 初稿完成. 2016.08.05 增加对 XCod ...

  2. 从零开始写一个武侠冒险游戏-8-用GPU提升性能(3)

    从零开始写一个武侠冒险游戏-8-用GPU提升性能(3) ----解决因绘制雷达图导致的帧速下降问题 作者:FreeBlues 修订记录 2016.06.23 初稿完成. 2016.08.07 增加对 ...

  3. 从零开始写一个武侠冒险游戏-2-帧动画

    从零开始写一个武侠冒险游戏-2-帧动画 ---- 用基本绘图函数实现帧动画 作者:FreeBlues 修订记录 2016.06.10 初稿完成. 2016.08.03 增加对 XCode 项目文件的说 ...

  4. 从零开始写一个武侠冒险游戏-3-地图生成

    2019独角兽企业重金招聘Python工程师标准>>> 从零开始写一个武侠冒险游戏-3-地图生成 概述 前面两章我们设计了角色的状态, 绘制出了角色, 并且赋予角色动作, 现在是时候 ...

  5. 如何搭建python框架_从零开始:写一个简单的Python框架

    原标题:从零开始:写一个简单的Python框架 Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 你为什么想搭建一个Web框架?我想有下面几个原因: 有一个 ...

  6. dotnet 从零开始写一个人工智能 从一个神经元开始

    现在小伙伴说的人工智能都是弱智能,可以基于神经网络来做.而神经网络是有多层网络,每一层网络都有多个神经元.那么最简单的神经网络就是只有一层,而这一层只有一个神经元,也就是整个神经网络只是有一个神经元. ...

  7. 编写一个C程序,实现以下功能:用一个函数实现两个字符串的比较,即自己写一个strcmp函数,函数原型为:int strcmp(char *p1,char *p2);设p1指向字符串s

    题目描述: 编写一个C程序,实现以下功能: 用一个函数实现两个字符串的比较,即自己写一个strcmp函数,函数原型为: int strcmp(char *p1,char *p2); 设p1指向字符串s ...

  8. mysql c测试程序_Linux平台下从零开始写一个C语言访问MySQL的测试程序

    Linux 平台下从零开始写一个 C 语言访问 MySQL 的测试程序 2010-8-20 Hu Dennis Chengdu 前置条件: (1) Linux 已经安装好 mysql 数据库: (2) ...

  9. 用python从零开始写一个注册机(新手也能操作)-前言

    今天开始带领大家从零开始写一个网站的账号注册机,达到批量注册的目的. 涉及到的相关知识包含: python的基本使用 playwright库的相关用法 验证码的识别 欢迎大家关注.

  10. 从零开始写一个抖音App——Apt代码生成技术、gradle插件开发与protocol协议

    1.讨论--总结前两周评论中有意义的讨论并给予我的解答 2.mvps代码生成原理--将上周的 mvps 架构的代码生成原理进行解析 3.开发一款gradle插件--从 mvps 的代码引出 gradl ...

最新文章

  1. 20160522--20160526----mybatis入门基础
  2. nagios报警延迟的解决--flapping state
  3. JS知识点笔记-常用方法
  4. mysql 字符串转时间yymmdd_mysql 日期和时间格式转换实现语句 | 很文博客
  5. mysql 从库 read only_mysql salve从库设置read only 属性
  6. mysql试题错误记录字段_MySQL这三道常见的面试题,你有被问过吗?
  7. 超音速亚原子Enterprise Java
  8. 一文告诉你 Event Loop 是什么?
  9. transferto的流这么关闭_Java 9中InputStream的transferTo()方法的重要性?
  10. C语言中的正负数及其输出
  11. VBA_输出SQL查询数据
  12. LeetCode(257)——二叉树的所有路径(JavaScript)
  13. CSS的一些基本样式的简单介绍
  14. Kubernetes K8S之Ingress详解与示例
  15. 《动手深度学习》4.5 权重衰减Weight Decay
  16. Vue进阶(幺贰叁):v-for 实现一行展示 n 个元素
  17. [车联网安全自学篇] Car Hacking之CAN总线初探
  18. java上传文件怎么设置成777权限_777权限是什么意思?文件夹权限为777如何修改设置?...
  19. android 状态栏(StatusBar)
  20. 【读书笔记】《奇特的一生》

热门文章

  1. JAVA之父,詹姆斯·高斯林传奇人生
  2. excel求回归直线方程的公式_求回归直线方程的三种方法
  3. 【知识兔】Excel教程与数值或日期相关的8个快捷键,绝对实用,收藏备用
  4. Ubalun电动牙刷拆卸及内部刨析
  5. apache common-chain 简单使用
  6. Java12之switch升级语法在Eclipse中的穿透问题
  7. JavaIO流——文件的读取与传输
  8. 小程序的转发分享功能
  9. uniapp发行为小程序分享转发功能
  10. java 英文日期转数字_Java SimpleDateFormat中英文时间格式化转换详解