零基础学CocosCreator·第四季-基础强化

学习视频:翰者学堂-零基础学Cocos Creator/爆款游戏开发零基础答疑班
(中途觉得还是写帖子比较方便以后复习,所以1-9课只是ts文件)
使用的Cocos Creator版本是2.0.10

01.Map

/**Map**/
import callFunc = cc.callFunc;

//Key-Value键值对
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    // onLoad () {}

    start () {
        //创建Map
        var m = new Map();

        //向m中添加Key-Value
        m.set("name","bird");

        //获取key为"name"的值
        let n = m.get("name");

        //删除name键值对
        m.delete("name");

        //清空m
        m.clear();

        //遍历Map
        m.forEach(function (value,key,map){

        });

        //Map类似数组访问方式
        m["age"] = 2; //作用等价于m.set("age",2)
        let age = m["age"]; //作用等价于m.get("age")
        m["age"] = undefined; //作用等价于m.delete("age")

        /**注意**
         * 1.尽量不要使用对象作为key,要使用基础类型number string
         * 2.forEach中,不要向map添加和删除对象
        **/
        /**Map适合做什么?
         * 1.翻译字典
         * 2.花名册
         */
    }

    // update (dt) {}
}

Map和Object异同点

参考文章

大概几点:

  1. 两位都是以键值对形式进行存储
  2. Map继承于Object
  3. Map中key值可以是任意类型,Object只能是number、string、Symbol
  4. Map会保留存入顺序,Object没有

02.JSON

/**JSON**/
/**什么是JSON
 * 1.JSON指的是JavaScript对象表示法(JavaScript Object Notation)
 * 2.JSON是轻量级的文本数据交换格式
 * 3.JSON独立于语言: JSON使用JavaScript语法来描述数据对象,但是JSON仍然独立于语言和平台
 * 4.JSON具有自我描述性
 * */

class JSONDemo {
    public study(){
        let xiaoming: any = {};
        xiaoming.name = "xiaoming";
        xiaoming.age = 14;
        xiaoming.skill = ["JavaScript","C++","Python"];

        let xiaomingJson: string = JSON.stringify(xiaoming); //json格式转为字符串
        console.log(xiaomingJson); // '{"name":"xiaoming","age":14,"skill":["JavaScript","C++","Python"]}'
    	//单引号优先级大于双引号

        xiaoming.self = xiaoming;
        let xiaomingJson2: string = JSON.stringify(xiaoming); //!报错,josn中不能循环引用

        let map = new Map();
        map.set("name","cai");
        map.set("age",24);
        let mapJson: string = JSON.stringify(map);
        console.log(map); // {}
        //Map不仅可以用字符串或数字类型当key,还可以用object等当key
        //需要将Map存为JSON格式,就需要遍历Map,重新赋值到新Object变量中

        //JSON的反序列化
        let xiaoming2: any = JSON.parse(xiaomingJson);
        console.log(xiaoming2.name); //"xiaoming"
    }
}

03.Enum

/**Enum 枚举**/

//声明枚举enum
enum BirdColor{
    White,
    Red,
    Blue
}

enum BirdColor2{
    White, //0
    Red = 2, //可自定义数值
    Blue, //3
    Yellow = "y", //"y"
    // Black //Enum member must have initializer
    Black = 7, //"b" 字符串定义的enum元素后的元素必须要声明
    Green //8
    //不推荐枚举用字符串声明,就用数字
}
//枚举声明之后不可以更改

/**定义一个枚举类型 */
const BIRD_COLOR = cc.Enum(BirdColor);

const {ccclass, property} = cc._decorator;

@ccclass
export default class EnumDemo extends cc.Component {

    @property({type: BIRD_COLOR}) //枚举类型属性 下拉框
    color: BirdColor = BirdColor.White;

    // onLoad () {}

    start () {
        //enum中每个值都是默认自增1的,从0开始
        console.log("white:",BirdColor.White); //0
        console.log("white:",BirdColor.Red); //1
        console.log("white:",BirdColor.Blue); //2
        
        console.log("white:",BirdColor2.White); //0

    }

    // update (dt) {}
}

04.泛型

/**泛型 <T>**/
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    // onLoad () {}

    start () {
        let output1 = this.identity<string>("is String"); //代表此函数的T都代表string

        let output2 = this.identity(11); //省略了<number>,编译器可以类型推论


        let map: Map<number,string> = new Map<number,string>(); //代表声明了一个number作为key,string作为value的Map
        map.set(6,"value6");
        // map.set("7","value7");//error:Argument of type 'string' is not assignable to parameter of type 'number'.


    }
    
    //<T>:代表之后的T都代表某同一类型
    identity <T>(arg: T): T{
        return arg;
    }
    // update (dt) {}
}

05.接口

/**接口**/

//接口声明 一般命名都用I开头
//从属性层面抽离出一些共同属性,不同于继承
interface IBiology {
    name: string;
    age: number;
    leg?: any; //?代表可选属性
    food: any;
    shout?: any;
}


/**猫类
 * @implements IBiology
 */ 
class Cat implements IBiology{
    name: string = "mimi";
    age: number;
    leg: any;
    food: any;
    shout(){
        console.log("miao miao");
    }
    sex:any;
}

/**狗类
 * @implements IBiology
 */
class Dog implements IBiology {
    name: string = "zerzer";
    age: number;
    leg: any;
    food: any;
    shout(){
        console.log("wang wang");
    } 
}

const {ccclass, property} = cc._decorator;

@ccclass
export default class InterfaceDemo extends cc.Component {

    // onLoad () {}

    start () {
        let cat = new Cat();
        let dog = new Dog();
        // this.shout<Cat>(cat);
        // this.shout<Dog>(dog);
        this.shout(cat);
        this.shout(dog);

        let oldDog: Dog = this.addAge(cat);
    }

    // shout <T>(biology: T): void{
    //     biology.shout(); //error:要限定类型才能用特定属性
    // }

    shout (biology: IBiology): void{
        biology.shout(); //要限定类型才能用特定属性
    }

    //需求:涨一岁,并叫一下
    addAge<T extends IBiology>(biology: T): T{
        biology.age += 1;
        biology.shout();
        return biology;
    }

    // update (dt) {}
}

06.命名空间

/**命名空间**/
//作用:将类包装在一个空间里(包),防止多人构造了同名类产生冲突
//命名空间在任何文件夹都可以通用 可以重复引用声明
const {ccclass, property} = cc._decorator;
namespace ns1{ //将其中一个Cat类放进ns1命名空间,就不会冲突了
    //export 导出,只有导出了外部才可以引用
    export class Cat {
    
    }
}

namespace ns1 {
    export class Dog {

    }
}

class Cat {

}

namespace ns2 {
    @ccclass
    export class NewClass extends cc.Component { //命名空间里不能有default修饰符,需要先引用命名空间才能引用类
    
        // onLoad () {}
    
        start () {
            //使用命名空间里的类
            let cat = new ns1.Cat();
        }
    
        // update (dt) {}
    }
}

07.值类型与引用类型

/**值类型与引用类型 */
/**值类型:
 * string,number,boolean,enum,none,undefined
 * 1.占用空间固定,保存在栈中 **
 * 2.保存与复制的是值本身 **
 * 3.使用typeof监测数据的类型
 * 4.基本类型数据是值类型
 */
/**引用类型:
 * Object,Array,Function
 * 1.占用空间不固定,保存在堆中 **
 * 2.保存与复制的是指向对象的一个指针 **
 * 3.使用instanceof检测数据类型
 * 4.使用new()方法构造出的对象是引用型
 */


const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    start () {
        //值类型
        let a: number = 10;
        let b: number = this.add(a); //此时传的参数是10,而不是a本身
        console.log("a:",a); //10 ** 因为a是值类型
        console.log("b:",b); //11

        let num1: number = 10;
        let num2: number = num1; //只是赋值 等价于 let num2: number = 10;
        num2 ++;
        console.log("num1:",num1); //10
        console.log("num2:",num2); //11

        //引用类型
        let obj1: any = {};
        obj1.a = 10;
        console.log("obj1.a_1:",obj1.a); //10

        let obj2: any = obj1; //obj2就是obj1本身 同时指向一块内存
        console.log("obj2.a_1:",obj2.a); //10

        obj2.a ++ ;
        console.log("obj1.a_2:",obj1.a); //11
        console.log("obj2.a_2:",obj2.a); //11
    }

    add(num: number): number{
        num = num + 1;
        return num;
    }

    // update (dt) {}
}

08.类型转换

/**类型转换(伪) */
const {ccclass, property} = cc._decorator;

class Animal {

}

class Dog extends Animal {
    name: string = "zerzer";
}

@ccclass
export default class NewClass extends cc.Component {

    // onLoad () {}

    start () {
        let animal: Animal = this.newAnimal();
        // this.getName(animal); //报错 因为编译器认为animal是Animal类型,而Animal类中没有name
        this.getName(animal as Dog); //将Animal类型转为Dog类型,仅仅是告诉编译器这是什么类型,并没有真正的改变类型

        let num: number = 0;
        // this.getName(num as Dog); //报错 因为编译器不傻,number类型不可能转换为Dog类型

        let num2: any = 0;
        this.getName(num2 as Dog); //只时就行了。。。因为any有可能可以转换为Dog类型

        //所以 as 不要乱用
    }

    newAnimal(): Animal{
        return new Dog();
    }

    getName(dog: Dog){
        console.log("name:",dog.name);
    }

    // update (dt) {}
}

09.static

/**Static 静态*/
//是一个修饰符
//可以声明在任何变量和函数前
//被static修饰的变量或函数会被整个类的对象共享一份
//被static修饰的变量或函数属于类不属于变量
const {ccclass, property} = cc._decorator;

class Dog{
    static age: number = 0;

    age2: number = 0;

    trace(i: number){
        Dog.age ++;
        console.log("i:",i,"age:",Dog.age); //每个数打印一遍 共有一个age

        Dog.die();
        //这里的this指代Dog对象
    }

    static die(){
        // this.trace(); //报错 静态方法里不能使用非静态变量 或调用非静态方法
        //这里的this指代Dog类
    }
}

@ccclass
export default class NewClass extends cc.Component {

    arr: Dog[] = [];

    // onLoad () {}

    start () {
        for (var i = 0; i < 5; i++){
            this.arr.push(new Dog());
        }
    }

    update (dt: number) {
        for (var i = 0; i < 5; i++){
            let dog = this.arr[i];
            dog.age2 ++;
            // console.log("i:",i,"age:",dog.age2);//每个数打印5编  每个对象都有属于自己的age2

            dog.trace(i);
        }
    }
}

10.堆栈与内存

  • 内存:程序可直接使用的部分,读取写入速度快,重启后内容丢失

  • 硬盘/闪存:程序不可以直接使用,需要把数据读取加载到内存中使用,读写速度比内存慢,重启后内容不丢失

  • 栈(Stack)与堆(Heap):

    1. 栈与堆都是物理内存中的一部分
    2. 内存是需要释放的
    3. 栈(Stack)由编译器自动分配释放,不需要我们管理,存储局部数据,访问速度快
    4. 堆(seap)一般需要有程序员操作释放,存储对象,访问速度比栈慢,可以持久化保存数据对象
  • 栈 Stack

    1. 一种后进先出的结构,连续的(代码块后放不了图…)
	// 每执行一个方法体就会压入栈中
    start () {
        for (let i = 0;i< 5;i ++){
            this.enabledInHierarchy.push(new Dog());
        }
        console.log("finish");
    }
  • 堆 Heap
    1.数据对象保存的地方,不连续

11.内存管理-垃圾回收机制

  • 垃圾回收 Garbage Collecation (GC)

    1. JS的垃圾回收机制是一种内存管理机制,防止内存泄漏
    2. 垃圾回收是由JS引擎执行
    3. 垃圾回收不定期进行,根据机器性能,内存压力,执行环境不同而不同
  • 老旧的机制 引用计数 Reference Count**

let obj: any = {}; //引用计数为1
//引用计数为1代表 当前有一个变量指向了{}所在的内存地址

let obj2 = obj; //引用计数为2
//代表有两个变量指向了{}所在内存地址

obj = null; //引用计数为1
obj2 = null; //引用计数为0
引用计数的问题-循环引用
func() {
	let obj1 = {};
	let boj2 = {};
	
	obj1.a = obj2; //ojb1引用obj2
	obj2.a = obj1; //ojb2引用obj1
	//此时obj1,obj2引用计数都为2
}
// 方法体结束后除obj1和obj2外,外界无法访问到它们
  • 新的方式 标记-清除 (mark and sweep)

工作中回收:
当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”
当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
function test(){
	let a = {}; //被标记,进入环境
	let b = {}; //被标记,进入环境
}
test(); //执行完毕后 a、b又被标记离开环境,判断是否被其他变量引用,被回收
周期性回收: 可达性算法
  1. 垃圾回收器,在开始回收的时候,从会给存储在内存中的所有变量都加上标记(从root节点开始)
  2. 去掉环境中的变量以及被环境中的变量引用的变量的标记
  3. 垃圾回收器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间
  4. 缺点:耗时
思考: 如何优化标记法垃圾回收?
  1. 分代回收:分为临时对象区,持久对象区。多扫描临时对象区,少扫描持久对象区,缺点是回收不全
  2. 增量GC:一次处理一部分内存区域
    注:这些都是JS引擎的工作,我们无法影响

尽量减少创建对象,不用的对象清空引用

//执行一次垃圾回收
cc.sys.garbageCollect()

12.数据结构

  1. 计算机存储、组织数据方式
  2. 程序设计 = 数据结构 + 算法

数组

1.一段连续的内存

let a:string[] = ["a","c","d","g"];
//假设一个字符占4字节,且a[0]所在内存地址为0x004
//那么a所指向的地址就是a[0]所在地址0x004
//a[1]所在地址为0x008 a[2]所在地址为0x00c(16进制)
  1. 优先:查询效率高
  2. 缺点:插入删除速度慢

链表

在这里插入图片描述

//单链表
class LinkNode{
	next: LinkNode; //指向下一个链表元素的内存地址
	content: any; //存放的内容
}
  1. 优点:插入删除效率高
  2. 缺点:检索效率低

class TreeNode{
	children: TreeNode[]; //子节点
	content: any;
}

Map

map

  1. 通过HASH算法,将Key散列在一段连续的内存中
    如果两个值都存放在同一内存a15中,那就会将先存进的元素转为链表元素,指向后存进的元素地址

13.算法练习

  1. 判断是不是翻转字符串 “abcd” “dcba”
isReversString(str0: string,str1: string): boolean{
	//应该还先判断str0和str1都不为空
	if (!str0 || !str1) return false;
	//先判断长度是否相等
	if (str0.length != str1.length) return false;
	//将str0的第一个字符和str1的最后一个字符比较,依次。。
	for (let i = 0;i < str0.length;i ++){
		let charStr0 = str0.charAt(i);
		let charStr1 = str1.charAt(str1.length - i - 1);
		if (charStr0 != charStr1){
			return false;
		}
	}
	return true;
}

isReversString("abcd","dcba")
  1. 翻转字符串
    * Given “abcdefg” *
    * offset = 0 => “abcdefg”
    * offset = 1 => “gabcdef”
    * offset = 2 => “fgabcde”
    * offset = 3 => “efgabcd”

    reversString(str: string, offset: number): string{
        //写方法之前想一想边界条件
        //如果offset值大于str长度,就抛出异常
        if (offset >= str.length){
            throw Error("hey,offset can not bigger than str.length!")
        }
        let str1: string = "";
        //先将后面要颠倒的字符拿出来
        for (let i = 0;i < offset;i ++){
            str1 += str.charAt(str.length - offset + i);
        }
        //再合并前面的字符
        for(let i = 0;i < str.length - offset;i ++){
            str1 += str.charAt(i);
        }
        return str1;
    }
  1. 将数组按从小到大的顺序排序
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cocos分层是指在Cocos游戏引擎中,将游戏场景或游戏对象按照不同的层级进行管理和渲染的一种技术。通过分层可以实现游戏元素的层次感和深度感,同时也方便了游戏对象的管理和控制。 在Cocos中,可以通过以下方式进行分层: 1. 场景层(Scene Layer):场景层是最底层的分层,用于管理整个游戏场景。一个游戏通常包含多个场景,每个场景都有自己的层级结构。场景层可以包含多个其他类型的层,如UI层、游戏对象层等。 2. UI层(UI Layer):UI层用于管理游戏中的用户界面元素,如按钮、标签、进度条等。UI层通常位于最上方,不受游戏对象的渲染顺序影响。通过UI层可以实现游戏中的菜单、设置界面等功能。 3. 游戏对象层(Game Object Layer):游戏对象层用于管理游戏中的各种游戏对象,如角色、敌人、道具等。游戏对象层可以根据需要创建多个,每个对象层可以控制不同类型的游戏对象的渲染顺序和行为。 4. 特效层(Effect Layer):特效层用于管理游戏中的特效效果,如爆炸、闪电等。特效层通常位于游戏对象层之上,可以通过特效层实现游戏中的动态效果和视觉冲击。 5. 背景层(Background Layer):背景层用于管理游戏中的背景元素,如地图、背景图片等。背景层通常位于最底部,用于呈现游戏的背景环境。 以上是Cocos分层的一些常见方式,通过合理的分层可以提高游戏的性能和可维护性,同时也能够更好地控制游戏元素的显示和交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值