本帖最后由 脑的研发记录 于 2023-11-10 16:45 编辑
“数据结构课作业笔记”#005-数组-投产练习-做一个地刺
所用编辑器版本0.25.0.4
目录总览:
零.前瞻
壹.第一个投产数组
贰.所需语法
叁.应用说明
肆.相关参考链接
伍.优化说明
零.前瞻
昨天写完关于数组的栈起源,完善,落地应用,不过还是有点距离,这次就着原有的代码写一个地刺脚本。
今天早上8:30-9:15找到靠谱函数。其中故事详见
江湖救急——不用现成的对象池代码,如何动态生成方块? 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)
然后下午2:00-5:00写代码。大概阶段是
第一次开发,使用靠谱的函数,重写代码,希望一次成功,然后成功报错,物体不生成,
第二次开发,不想一步步重写,就抽样检测代码片段,发现抽样合格,但是物体不生成,
第三次开发,检测所有能输出数字的变量,穷举检测每一步,但是输出其他类型的变量信息就不懂了,于是用最原始的代码写,风格像极了前一节开头的“自由数组”,能跑,物体生成了,但是物体不消失。
第四次开发,改数字,加入数字变量,看日志输出,发现数字不按计划改变,追溯有关控制数字的语句,重读语句代码。删除观察,物体不生成,倒退成第一次开发的情形。确认了问题函数。
第五次开发,改函数位置,改函数内部的默认数字,输出检测,发现不输出变量数字,以为是函数失效,在执行过程中没有分配内存。
第六次开发,扩大问题范围,内存级别的问题,非常态级别的问题,网络问题,物体同步问题。复制,粘贴,删除旧位置的函数,一步到位成功使得物体消失。
第七次开发,因为物体不能反复消失出现,打包正常函数,然后重新检查函数变量,重复第四次开发的过程。
第八次开发,重读函数,把1改成0,交换了两个函数的位置,跑起来了,物体能反复消失出现了。
第九次开发,新建工程,复制粘贴,看看是不是偶然成功,发现寄了,一行行比对,发现是改错文件了,开发过程中副本太多了,然后依然失败,想起求助帖子里
“
所以里面生成的代码应该是这个,记得spawn之前需要先加载资源 | ”。
坏了,加载资源不会,但是,想到写不出来帖子技术没有落地应用,前面的帖子有点寄,就知道,不会也能会.......之前代码能跑,没有用代码预先加载生成.......只是拖进去方块......懂了,拖进方块,跑代码,物体生成了,我又懂了,
第十次开发,改参数,10,30,看到地刺长度改变,1000,200,20,看到地刺生长速度改变。发现有一段地刺消失不了,尝试,未果。
好像学一个东西就像是,无中生有一个熟悉的东西,代码熟悉,地刺熟悉,用代码写地刺,不认得。
难怪学东西难,写个靠谱的代码文案,光描述完整的故事情节就字数挺多的。
开发途中没有记录,全靠感受,时候回忆,历历在目。
什么是学习?那个时候的情景下,没有时间记录描述,忙着穷举试探,这些使人忙的来不及一心二用边说话边敲代码的状态就是学习。
以前觉得老师带着讲,总是有着成熟的计划,没有和同学一样,在有限知识情况下,面对相同,以学生的角色代入题目中,讲出来感觉有些突兀。总想着能自然而然,应该有其他讲述的样子,知识不能是凭空蹦出来的吧?现在做了一点测试,连续四天写新的东西,连续四天学习新东西,很多困难都是隔着一层纸,材料都够了,剩下的就是穷举,排列组合,成功了就是知识。知识的真相应该像这样,省略了故事的知识,应该像是产品手册。
学习,应该还有一层,学习如何控制自己的学习——自己穷举出方式,来让自己感受以前不曾感受到的事情的,学习的矛盾,属于自己特有的矛盾,如此如此。
最后晚上6:00-8:15写帖子。
一天写一篇文案的精力去向统计完毕。
壹.第一个投产数组
代码能跑就行,其他见招拆招。
首先,场景里拖进去一个正方体,
然后不多说,上代码,新建脚本复制粘贴,跑就完事
class ooh {
n: Gameplay.GameObject;
id: string;
}
@Core.Class
export default class adds extends Core.Script {
protected build: Array<ooh> = new Array(100);
protected i: number = -1;
protected flag_grow: number = 1;
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected onStart(): void {
// for (this.i = 0; this.i < this.build.length; this.i++) {
for (var j = 0; j < this.build.length; j++) {
this.build[j] = new ooh();
// this.build[j].n = new Gameplay.GameObject();
}
// for (this.i = 0; this.i < this.build.length; this.i++) {
// let obj = Gameplay.GameObject.spawn({
// guid: "197386",
// replicates: true,
// transform: new Transform(new Vector(0, this.i * 100, this.i * 25),
// new Rotation(0, 0, 0),
// new Vector(1, 1, 1))
// //写需要设置的Transform
// });
// this.build[this.i].n = obj
// this.build[this.i].n.setCollision(Type.PropertyStatus.On, true);
// this.build[this.i].n.setVisibility(Type.PropertyStatus.On, true);
// this.build[this.i].id = "ooh"+this.i;
// }
for (var j = 0; j < this.build.length; j++) {
let obj = Gameplay.GameObject.spawn({
guid: "197386",
replicates: true,
transform: new Transform(new Vector(0, j * 100, j * 25),
new Rotation(0, 0, 0),
new Vector(1, 1, 1))
//写需要设置的Transform
});
// this.build[this.i].n = obj;
this.in(obj);
this.build[j].n.setCollision(Type.PropertyStatus.On, true);
this.build[j].n.setVisibility(Type.PropertyStatus.On, true);
this.build[j].id = "ooh" + this.i;
}
this.build[3].n.setCollision(Type.PropertyStatus.Off, true);
this.build[3].n.setVisibility(Type.PropertyStatus.Off, true);
var timer = setInterval(() => {
console.log(this.i);
// console.log(this.flag_grow);
console.log(this.build.length);
if (this.flag_grow == 0) {
var have: ooh = this.out();
have.n.setCollision(Type.PropertyStatus.Off, true);
have.n.setVisibility(Type.PropertyStatus.Off, true);
if (this.i == -1) {
// this.i++;
this.flag_grow = 1;
}
}
if (this.flag_grow == 1) {
if (this.i == this.build.length) {
// this.i--;
this.flag_grow = 0;
console.log("over");
}
var have: ooh = this.show();
have.n.setCollision(Type.PropertyStatus.On, true);
have.n.setVisibility(Type.PropertyStatus.On, true);
// if (this.i >= this.build.length) {
// // this.i--;
// this.flag_grow = 0;
// }
}
// if (this.i >= this.build.length) {
// // this.i--;
// this.flag_grow = 0;
// }
// if (this.flag_grow == 0 && this.i == -1) {
// this.i++;
// this.flag_grow = 1;
// } else if (this.flag_grow == 1 && this.i == this.build.length) {
// this.i--;
// this.flag_grow = 0;
// }
// this.build[3].n.setCollision(Type.PropertyStatus.Off, true);
// this.build[3].n.setVisibility(Type.PropertyStatus.Off, true);
}, 20);
}
public in(obj: Gameplay.GameObject) {
this.i++;
this.build[this.i].n = obj;
}
public show(): ooh {
this.i++;
var have = this.build[this.i];
return have;
}
public out(): ooh {
var have = this.build[this.i];
this.i--;
return have;
}
}
代码实现了地刺依次延伸,可以用来做天梯,也可以用来做章鱼触手的攻击,多个地刺可以围出牢笼,也可以把地刺缩小,形成有深度的炮坑,也可放在巨大的场景里作为横梁骨架,如果配上物理模拟可以设计一个以见证高塔倒塌为主题的场景交互游戏
不多说,代码拆解 看到这一部分绿色的。
// for (this.i = 0; this.i < this.build.length; this.i++) {
// let obj = Gameplay.GameObject.spawn({
// guid: "197386",
// replicates: true,
// transform: new Transform(new Vector(0, this.i * 100, this.i * 25),
// new Rotation(0, 0, 0),
// new Vector(1, 1, 1))
// //写需要设置的Transform
// });
// this.build[this.i].n = obj
// this.build[this.i].n.setCollision(Type.PropertyStatus.On, true);
// this.build[this.i].n.setVisibility(Type.PropertyStatus.On, true);
// this.build[this.i].id = "ooh"+this.i;
// }
其实和下面的循环是一样的作用,这次对标号隔离,减少this.i的使用次数,这样在其他地方调用函数的时候就不用非要使用这个脚本里的this.i变量了。
for (var j = 0; j < this.build.length; j++) {
// let obj = Gameplay.GameObject.spawn({
// guid: "197386",
// replicates: true,
// transform: new Transform(new Vector(0, j * 100, j * 25),
// new Rotation(0, 0, 0),
// new Vector(1, 1, 1))
// //写需要设置的Transform
// });
// this.build[this.i].n = obj;
this.in(obj);
this.build[j].n.setCollision(Type.PropertyStatus.On, true);
this.build[j].n.setVisibility(Type.PropertyStatus.On, true);
this.build[j].id = "ooh" + this.i;
}
物体消失出现的函数,脚本里两行是用来验证数组是否有方块数据,这样如果第三方块消失了,说明数组里有数据,如果数组里没有数据,方块就不消失
设置物体不可被碰撞感知
设置物体不可见
this.build[3].n.setCollision(Type.PropertyStatus.Off, true);
this.build[3].n.setVisibility(Type.PropertyStatus.Off, true);
下面是计时器,里面实现的是按顺序出现,按顺序消失,绿色的代码是之前开发解决问题时留下的测试代码。
像上一节提到的,只在一段进行出入,从100出到1,然后如果再出,就到0,再出,如果出到-1,就说明数组里没有数据了,用两个if进行隔离,另一个if语句里换一个顺序,可以从0到100,这样新增数据了,这样在两个模式中反复横跳,每过100次,就转换一次,实现地刺突进与回退消失。
var timer = setInterval(() => {
console.log(this.i);
// console.log(this.flag_grow);
console.log(this.build.length);
if (this.flag_grow == 0) {
var have: ooh = this.out();
have.n.setCollision(Type.PropertyStatus.Off, true);
have.n.setVisibility(Type.PropertyStatus.Off, true);
if (this.i == -1) {
// this.i++;
this.flag_grow = 1;
}
}
if (this.flag_grow == 1) {
if (this.i == this.build.length) {
// this.i--;
this.flag_grow = 0;
console.log("over");
}
var have: ooh = this.show();
have.n.setCollision(Type.PropertyStatus.On, true);
have.n.setVisibility(Type.PropertyStatus.On, true);
// if (this.i >= this.build.length) {
// // this.i--;
// this.flag_grow = 0;
// }
}
// if (this.i >= this.build.length) {
// // this.i--;
// this.flag_grow = 0;
// }
// if (this.flag_grow == 0 && this.i == -1) {
// this.i++;
// this.flag_grow = 1;
// } else if (this.flag_grow == 1 && this.i == this.build.length) {
// this.i--;
// this.flag_grow = 0;
// }
// this.build[3].n.setCollision(Type.PropertyStatus.Off, true);
// this.build[3].n.setVisibility(Type.PropertyStatus.Off, true);
}, 20);
最后是三个打包起来的函数,in是数组中进入数据,out是数组中弹出数据,show是按in的格式写的,也是弹出数据,就是地刺生长,
入栈只能在第一次初始化进入,其他的方块生成都是需要弹出数据,不过可以看到数据中this.i++,变量this.i变化时,数组数据对应的物体,在初始化的时的顺序。
public in(obj: Gameplay.GameObject) {
this.i++;
this.build[this.i].n = obj;
}
public show(): ooh {
this.i++;
var have = this.build[this.i];
return have;
}
public out(): ooh {
var have = this.build[this.i];
this.i--;
return have;
}
最终成果
class ooh {
n: Gameplay.GameObject;
id: string;
}
@Core.Class
export default class adds extends Core.Script {
protected build: Array<ooh> = new Array(100);
protected i: number = -1;
protected flag_grow: number = 0;
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected onStart(): void {
for (var j = 0; j < this.build.length; j++) {
this.build[j] = new ooh();
}
// AssetUtil.assetLoaded("197386");
// AssetUtil.asyncDownloadAsset("197386");
for (var j = 0; j < this.build.length; j++) {
let obj = Gameplay.GameObject.spawn({
guid: "197386",
replicates: true,
transform: new Transform(new Vector(0, j * 100, j * 25),
new Rotation(0, 0, 0),
new Vector(1, 1, 1))
//写需要设置的Transform
});
// this.build[++this.i].n = obj;
this.in(obj);
this.build[j].n.setCollision(Type.PropertyStatus.On, true);
this.build[j].n.setVisibility(Type.PropertyStatus.On, true);
this.build[j].id = "ooh" + this.i;
}
setTimeout(() => {
var timer = setInterval(() => {
console.log(this.i);
// console.log(this.flag_grow);
console.log(this.build.length);
if (this.flag_grow == 0) {
var have: ooh = this.out();
have.n.setCollision(Type.PropertyStatus.Off, true);
have.n.setVisibility(Type.PropertyStatus.Off, true);
if (this.i == -1) {
this.flag_grow = 1;
}
} else if (this.flag_grow == 1) {
if (this.i == this.build.length) {
this.flag_grow = 0;
}
var have: ooh = this.show();
have.n.setCollision(Type.PropertyStatus.On, true);
have.n.setVisibility(Type.PropertyStatus.On, true);
}
}, 20);
}, 3000);
}
public in(obj: Gameplay.GameObject) {
this.i++;
this.build[this.i].n = obj;
}
public show(): ooh {
this.i++;
var have = this.build[this.i];
return have;
}
public out(): ooh {
var have = this.build[this.i];
this.i--;
return have;
}
}
对比上一篇“数据结构课作业笔记”#004-数组-简单排列的变量和它们必然命运(下) 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)的最终成果,可以发现多了一个包装的函数,也多了一个变量flag_grow, worldlocation的所有者从人变成物体,而且worldlocation退化成了一个向量Vector的参数,没有了名字。
class seetest变成了class ooh,名字变了,里面的变量成员也变了,a变量成员从number类型变成 Gameobject 类型,check变量从Vector 类型变成string类型。
上一篇的最终成果代码,复制粘贴,横向比较
class seetest {
public a: number;
public check: Vector;
}
@Core.Class
export default class add extends Core.Script {
public arr_names: Array<seetest> = new Array(6)
public i: number = 0;
/** 当脚本被实例后,会在第一帧更新前调用此函数 */
protected onStart(): void {
// 对每一个铭牌分配一个seetest户型的房子
for (this.i = 0; this.i < this.arr_names.length; this.i++) {
this.arr_names[this.i] = new seetest();
}
// 每个铭牌指定的房子里安排进家具
for (this.i = 0; this.i < this.arr_names.length;) {
this.in(new Vector(500 * this.i, 0, 300), this.i * 2);
}
var chara: Gameplay.Character;
setTimeout(() => {
chara = Gameplay.getCurrentPlayer().character;
// chara.worldLocation = this.arr_names[this.i].check;
chara.worldLocation = this.out().check;
var timer = setInterval(() => {
if (this.i < 0) {
// 如果i小于0,就清除定时器
clearInterval(timer);
}
chara.worldLocation = this.out().check;
}, 500);
}, 2000);
}
public in(check: Vector, a: number) {
this.arr_names[this.i].a = a
this.arr_names[this.i].check = check;
console.log(this.arr_names[this.i].check.x)
this.i++;
}
public out(): seetest {
this.i--;
var now: seetest = new seetest();
now = this.arr_names[this.i];
return now;
}
}
贰.所需语法
详情
江湖救急——不用现成的对象池代码,如何动态生成方块?
帖子下拉详情靠谱同志,讨论区里的代码实际应用起来就是这样
let obj = Gameplay.GameObject.spawn({
guid: "197386",
replicates: true,
transform: new Transform(new Vector(0, j * 100, j * 25),
new Rotation(0, 0, 0),
new Vector(1, 1, 1))
//写需要设置的Transform
});
Vector 改写的是x,y,z坐标,
Rotation写的是旋转角度
(1,1,1)那个是放大倍数:
第一个1是指x方向上是默认的1倍,
第二个1是指y方向上是默认的1倍,
第三个1是指z方向上是默认的1倍。
叁.应用说明
“代码实现了地刺依次延伸,可以用来做天梯,也可以用来做章鱼触手的攻击,多个地刺可以围出牢笼,也可以把地刺缩小,形成有深度的炮坑,也可放在巨大的场景里作为横梁骨架,如果配上物理模拟可以设计一个以见证高塔倒塌为主题的场景交互游戏。”
也可以做一点别的,结合特效,多个方向的地刺可以实现爆炸挤压碰撞,
结合触发器,可以实现自动延伸的桥梁
有没有一种可能,做一个只有地刺场景的跑酷游戏,大地刺,小地刺,长地刺,短地刺,变色地刺,减速地刺,加速地刺,反重力地刺。
肆.相关参考链接
返回主站
普通大学生“数据结构”课作业笔记#000-目录-逻辑结构与存储结构 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)
这下面几节别太认真看
底层实现
2:16“游戏里的像素都可以破坏掉”理想中的游戏效果参考
伍.优化说明
功能实现上
把脚本挂到方块上,然后这俩整体设置为预制体,批量生产地刺
脚本可以加上属性栏目,不用打开脚本,在右侧对象栏目中,点击脚本看到脚本属性栏目,改数字长度,改方向,改角度,实现地刺生长方向自由
代码组织上
终极形态应该说是对象池,但是目前项目样例是基于栈的只在一个端口实现出入操作,对象池可以给一个序号,就能查到需要的物体。
软件设计上
另一饼是上上篇“数据结构课作业笔记”#003-数组-简单排列的变量和它们必然命运(中) 口袋方舟论坛|面向全年龄的UGC互动内容平台与交流社区 (ark.online)的第三节提到
崩坏三的角色闪现,
而这个栈和动态生成物体的组合,在物体模型上的是crlt+z撤销错误的模型设计。
模型的角度参数,也是装进一个数组里,然后根据数组的三个坐标秒点,连线,依次点亮像素点。就像刚才的物体出现又消失那样的。
|