Laya连线小游戏

Laya连线小游戏

游戏规则

  1. 通过连接不同颜色的方块来实现连一连
  2. 连线不可重复,就是一条线不能和另外一条线撞一起
  3. 最后所有连线要占据整个空间

游戏资源

 

创建Item

 线条可以分为上左下右,通过显示和隐藏达到画线的效果。

 譬如item1到item2,通过判断两者posX,posY,item1调用方法showLine(3)显示line3,item2调用方法showLine(1)显示line1。

Item.ts。

import { ui } from "../ui/layaMaxUI";
export class Item extends ui.view.ItemUI{
    public colorType:number = 1;//定义线条颜色
    public type:number = 0;//类型
    public posX:number = 1;//位置x
    public posY:number = 1;//位置y
    public isLinkList:boolean = false;//是否已经连过了
    /* 创建item */
    public static createItem():Item{
        let item:Item = new Item();
        item.line1.visible = false;
        item.line2.visible = false;
        item.line3.visible = false;
        item.line4.visible = false;
        return item;
    }
    /* 设置线条颜色 */
    public setLineColor(value:number):void{
        this.isLinkList = true;
        this.colorType = value;
        for(let i:number = 1; i <= 4; i++){
            this["line" + i].skin = "res/ui/icon/line_line" + value + ".png";
        }
    }
    /* 设置icon */
    public setIcon(value:number):void{
        this.type = value;
        if(value > 0){
            this.icon.skin = "res/ui/icon/line_icon" + value + ".png";
        }else{
            this.icon.skin = "";
        }
    }
    /* 显示上或下或左或右线条 */
    public showLine(value:number):void{
        switch(value){
            case 1:
                this.line1.visible = true;break;
            case 2:
                this.line2.visible = true;break;
            case 3:
                this.line3.visible = true;break;
            case 4:
                this.line4.visible = true;break;
            default:
                this.line1.visible = false;
                this.line2.visible = false;
                this.line3.visible = false;
                this.line4.visible = false;
                this.isLinkList = false;
                break;
        }
    }

}

游戏界面创建

创建GameView.ts,类GameView继承自该界面

import { LinkList } from "../script/LinkList";
import { ui } from "../ui/layaMaxUI";
import { Item } from "./Item";
export class GameView extends ui.dialog.GameUI {
    private row:number = 5;//行数
    private column:number = 5;//列数
    private itemArr:Array<Item> = [];//存放item的数组
    private dataArr:Array<number> = [1,0,0,0,3,0,0,2,0,0,1,0,0,3,0,4,0,0,4,2,5,0,0,0,5];
    private ITEM_WIDTH:number = 120;//定义item宽
    private ITEM_HEIGHT:number = 120;//定义item高
    private canDraw:boolean = false;//是否能画线
    private tempPoint:Laya.Point = new Laya.Point();
    private list1:LinkList = new LinkList();//链表1
    private list2:LinkList = new LinkList();//链表2
    private list3:LinkList = new LinkList();//链表3
    private list4:LinkList = new LinkList();//链表4
    private list5:LinkList = new LinkList();//链表5
    private currentList:LinkList;
    constructor() {
        super();
        this.init();
    }

    private init():void{
        this.addEvent();
        this.initDrawLinePanel();
    }

    private addEvent():void{
        Laya.stage.on(Laya.Event.RESIZE,this,this.onResize);
        this.panelNode.on(Laya.Event.MOUSE_DOWN,this,this.onMouseDown);
        this.panelNode.on(Laya.Event.MOUSE_MOVE,this,this.onMouseMove);
        this.panelNode.on(Laya.Event.MOUSE_OUT,this,this.onMouseOut);
        this.panelNode.on(Laya.Event.MOUSE_UP,this,this.onMouseOut);
    }
    /* 初始化画线面板 */
    private initDrawLinePanel():void{
        let item:Item;
        for(let i:number = 0; i < this.row; i++){
            for(let j:number = 0; j < this.column; j++){
                item = Item.createItem();
                item.pos(j *  this.ITEM_WIDTH,i  * this.ITEM_HEIGHT);
                item.posX = j;
                item.posY = i;
                item.setIcon(this.dataArr.shift());
                this.panelNode.addChild(item);
                this.itemArr.push(item);
            }
        }
        let panelWidth:number = this.ITEM_WIDTH * this.column;
        let panelHeight:number = this.ITEM_HEIGHT * this.row;
        this.panelNode.size(panelWidth,panelHeight);
        this.panelNode.x = -0.5 * panelWidth;
        this.panelNode.y = -0.5 * panelHeight;
    }
    /* 鼠标按下 */
    private onMouseDown():void{
        //全局坐标转为panelNode局部坐标
        this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
        let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
        let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
        let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
        let index:number = posY * this.column + posX;
        let item:Item = this.itemArr[index];//拿到对应的item
        if(item.type > 0){//点击到有颜色的item
            this.canDraw = true;
            this.currentList = this["list" + item.type];
            this.currentList.clear();
            this.currentList.append(item);
        }else{//点击到没有颜色的item
            if(item.isLinkList){//连过了
                this.currentList = this["list" + item.colorType];
                let tail:Item = this.currentList.getTail().item;
                if(item == item){//判断该item是否属于链表尾节点
                    this.canDraw = true;
                }
            }
        }
    }
    /* 鼠标滑动 */
    private onMouseMove():void{
        if(!this.canDraw) return;
        //全局坐标转为panelNode局部坐标
        this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
        let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
        let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
        let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
        let index:number = posY * this.column + posX;
        let item:Item = this.itemArr[index];//拿到对应的item
        let tail:Item = this.currentList.getTail().item;//链表尾
        if((posX == tail.posX && Math.abs(posY - tail.posY) == 1) || (posY == tail.posY && Math.abs(posX - tail.posX) == 1)){//必须与链表尾相邻(上下左右)
            if(item.type <= 0 || item.type == tail.colorType){//滑动到没有颜色的节点或者是颜色一样
                let position:number = this.currentList.positionOf(item);
                if(position < 0){
                    if(item.isLinkList){//已经在其它链表里了
                        let list:LinkList = this["list" + item.colorType]
                        list.slice(list.positionOf(item) - 1);
                    }
                    this.currentList.append(item);//添加到链表
                    this.isGetVictory();//是否通关
                    if(item.type > 0){
                        this.canDraw = false;
                    }
                }else{
                    this.currentList.slice(position);//切割链表
                }
            }else{
                this.canDraw = false;
            }
        }else{
            if(item != this.currentList.getTail().item){//此时滑动到的点不是链表尾,才不能画线(在当前的点滑来滑去还是能画线)
                this.canDraw = false;
            }
        }
    }
    /* 鼠标松开 */
    private onMouseOut():void{
        this.canDraw = false;
    }
    /* 是否通过 */
    private isGetVictory():boolean{
        let count:number = 0
        for(let i:number = 1; i <= 5;i ++){//遍历所有链表,判断链表长度是否等于面板上的方格总数
            count += this["list" + i].size()
        }
        if(count == this.row * this.column){
            return true;
        }
        return false;
    }

    private onResize():void{
        this.height = Laya.stage.height;
        this.width = Laya.stage.width;
    }
}

通过行数5,列数5创建item,添加到panelNode节点上,初始化画线面板。

/* 初始化画线面板 */
    private initDrawLinePanel():void{
        let item:Item;
        for(let i:number = 0; i < this.row; i++){
            for(let j:number = 0; j < this.column; j++){
                item = Item.createItem();
                item.pos(j *  this.ITEM_WIDTH,i  * this.ITEM_HEIGHT);
                item.posX = j;
                item.posY = i;
                item.setIcon(this.dataArr.shift());
                this.panelNode.addChild(item);
                this.itemArr.push(item);
            }
        }
        let panelWidth:number = this.ITEM_WIDTH * this.column;
        let panelHeight:number = this.ITEM_HEIGHT * this.row;
        this.panelNode.size(panelWidth,panelHeight);
        this.panelNode.x = -0.5 * panelWidth;
        this.panelNode.y = -0.5 * panelHeight;
    }

通过鼠标位置,计算出posX,posY,拿到对应的item

鼠标全局位置转为panelNode局部位置,计算出posX,posY,再从itemArr拿到对应的item

 this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
 let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
 let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
 let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
 let index:number = posY * this.column + posX;
 let item:Item = this.itemArr[index];

鼠标按下

鼠标点击时,有俩种情况,才可以画线

第一种情况,点击到颜色方块

 第二种情况,不是点击到 颜色方块,但是点击到连线的末端,这时可以继续连线

/* 鼠标按下 */
private onMouseDown():void{
    //全局坐标转为panelNode局部坐标
    this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
    let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
    let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
    let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
    let index:number = posY * this.column + posX;
    let item:Item = this.itemArr[index];//拿到对应的item
    if(item.type > 0){//点击到有颜色的item
        this.canDraw = true;
        this.currentList = this["list" + item.type];
        this.currentList.clear();
        this.currentList.append(item);
    }else{//点击到没有颜色的item
        if(item.isLinkList){//连过了
            this.currentList = this["list" + item.colorType];
            let tail:Item = this.currentList.getTail().item;
            if(item == item){//判断该item是否属于链表尾节点
                this.canDraw = true;
            }
        }
    }
}

鼠标滑动,连线

 连线时,只有跟该线线尾相邻才可以连接

 滑到不同颜色节点时断开连接

 如果滑动到的已经连接过了,就切割该链表

 如果滑动到的节点已经被其它节点连接过了,就切割连接过的链表

/* 鼠标滑动 */
private onMouseMove():void{
    if(!this.canDraw) return;
    //全局坐标转为panelNode局部坐标
    this.tempPoint.setTo(Laya.MouseManager.instance.mouseX,Laya.MouseManager.instance.mouseY);
    let point:Laya.Point = this.panelNode.globalToLocal((this.tempPoint));
    let posX:number = Math.floor(point.x / this.ITEM_WIDTH);
    let posY:number = Math.floor(point.y / this.ITEM_HEIGHT);
    let index:number = posY * this.column + posX;
    let item:Item = this.itemArr[index];//拿到对应的item
    let tail:Item = this.currentList.getTail().item;//链表尾
    if((posX == tail.posX && Math.abs(posY - tail.posY) == 1) || (posY == tail.posY && Math.abs(posX - tail.posX) == 1)){//必须与链表尾相邻(上下左右)
        if(item.type <= 0 || item.type == tail.colorType){//滑动到没有颜色的节点或者是颜色一样
            let position:number = this.currentList.positionOf(item);
            if(position < 0){
                if(item.isLinkList){//已经在其它链表里了
                    let list:LinkList = this["list" + item.colorType]
                    list.slice(list.positionOf(item) - 1);
                }
                this.currentList.append(item);//添加到链表
                this.isGetVictory();//是否通关
                if(item.type > 0){
                    this.canDraw = false;
                }
            }else{
                this.currentList.slice(position);//切割链表
            }
        }else{
            this.canDraw = false;
        }
    }else{
        if(item != this.currentList.getTail().item){//此时滑动到的点不是链表尾,才不能画线(在当前的点滑来滑去还是能画线)
            this.canDraw = false;
        }
    }
}

判断是否连接完成

 只需要遍历所有链表,判断链表长度是否等于面板上的方格总数

/* 是否通过 */
private isGetVictory():boolean{
    let count:number = 0
    for(let i:number = 1; i <= 5;i ++){//遍历所有链表,判断链表长度是否等于面板上的方格总数
        count += this["list" + i].size()
    }
    if(count == this.row * this.column){
        return true;
    }
    return false;
}

item链表

LinkList.ts

import { Item } from "../view/Item";
export class Node{
    public item:Item;//节点数据
    public next:Node = null;//指向下一个节点 
    constructor(item:Item){
        this.item = item;
    }
}
export class LinkList{
    private head:Node = null;//链表头
    private tail:Node = null;//链表尾
    private length:number = 0;//链表长度
    /* 向链表添加新节点 */
    public append(item:Item):void{
        let node:Node = new Node(item);
        if(this.length <= 0){//如果当前链表为空,则将head,tail指向node
            item.setLineColor(item.type);
            this.head = node;
            this.tail = node;
        }else{//否则在链表尾添加新元素
            item.setLineColor(this.head.item.colorType);
            let prevItem:Item = this.tail.item;
            this.tail.next = node;
            this.tail = node;
            this.setLine(prevItem,this.tail.item);
        }
        this.length++;//链表长度+1
    }
    
    /* 截取链表,包含position */
    public slice(position:number):boolean{
        if(position < 1 || position > this.length){
            return false;
        }
        console.log(position);
        let currentNode:Node = this.head;
        let currentPosition:number = 1;
        let sliceNode:Node;
        let prevNode:Node;
        while(currentNode){
            if(currentPosition == position - 1){
                prevNode = currentNode;
            }
            else if(currentPosition == position){
                this.length = position;
                sliceNode = currentNode;
                currentNode.item.showLine(0);
                currentNode.item.isLinkList = true;
            }else if(currentPosition > position){
                currentNode.item.showLine(0);
            }
            currentNode = currentNode.next;
            currentPosition++;
        }
        sliceNode.next = null;
        if(prevNode){
            this.setLine(prevNode.item,sliceNode.item);
        }
        this.tail = sliceNode;
        
    }
    /* 设置线条 */
    private setLine(item1:Item,item2:Item):void{
        let prevX:number = item1.posX;
        let prevY:number = item1.posY;
        let nextX:number = item2.posX;
        let nextY:number = item2.posY;
        if(prevX == nextX){
            if(prevY > nextY){
                item1.showLine(1);
                item2.showLine(3);
            }else{
                item1.showLine(3);
                item2.showLine(1);
            }
        }
        if(prevY == nextY){
            if(prevX > nextX){
                item1.showLine(4);
                item2.showLine(2);
            }else{
                item1.showLine(2);
                item2.showLine(4);
            }
        }
    }

     /* 查找某个元素所在的节点位置 */
     public positionOf(item:Item):number{
        let currentNode:Node = this.head;
        let currentPosition:number = 1;
        while(currentNode){
            if(currentNode.item == item){
                return currentPosition;
            }
            currentPosition++;
            currentNode = currentNode.next;
        }
        return -1;
    }
    /*  返回某位置的节点*/
    public getNodeAt(position:number):Node{
        if(position < 1 || position > this.length){//越界
            return null;
        }
        let currentNode:Node = this.head;
        let currentPositon:number = 1;
        while(currentPositon < position){//遍历链表,找到节点
            currentNode = currentNode.next;
            currentPositon++;
        }
        return currentNode;
    }
    /* 链表是否为空 */
    public isEmpty():boolean{
        return this.length == 0;
    }
    /*  返回链表长度 */
    public size():number{
        return this.length;
    }
    /* 返回链表头 */
    public getHead():Node{
        return this.head;
    }
    /* 返回链表尾 */
    public getTail():Node{
        return this.tail;
    }
    /* 清空链表 */
    public clear():void{
        let currentNode:Node = this.head;
        while(currentNode){
            currentNode.item.showLine(0);
            currentNode = currentNode.next;
        }
        this.head = null;
        this.tail = null;
        this.length = 0;
    }
}

设置线条

通过比较链表前后节点的item,显示对应的线条

/* 设置线条 */
    private setLine(item1:Item,item2:Item):void{
        let prevX:number = item1.posX;
        let prevY:number = item1.posY;
        let nextX:number = item2.posX;
        let nextY:number = item2.posY;
        if(prevX == nextX){
            if(prevY > nextY){
                item1.showLine(1);
                item2.showLine(3);
            }else{
                item1.showLine(3);
                item2.showLine(1);
            }
        }
        if(prevY == nextY){
            if(prevX > nextX){
                item1.showLine(4);
                item2.showLine(2);
            }else{
                item1.showLine(2);
                item2.showLine(4);
            }
        }
    }

item链表添加节点

需要设置一下当前节点跟上一个节点的线条

/* 向链表添加新节点 */
public append(item:Item):void{
    let node:Node = new Node(item);
    if(this.length <= 0){//如果当前链表为空,则将head,tail指向node
        item.setLineColor(item.type);
        this.head = node;
        this.tail = node;
    }else{//否则在链表尾添加新元素
        item.setLineColor(this.head.item.colorType);
        let prevItem:Item = this.tail.item;
        this.tail.next = node;
        this.tail = node;
        this.setLine(prevItem,this.tail.item);
    }
    this.length++;//链表长度+1
}

item链表截取节点

 

/* 截取链表,包含position */
public slice(position:number):boolean{
    if(position < 1 || position > this.length){
        return false;
    }
    console.log(position);
    let currentNode:Node = this.head;
    let currentPosition:number = 1;
    let sliceNode:Node;
    let prevNode:Node;
    while(currentNode){
        if(currentPosition == position - 1){
            prevNode = currentNode;
        }
        else if(currentPosition == position){
            this.length = position;
            sliceNode = currentNode;
            currentNode.item.showLine(0);
            currentNode.item.isLinkList = true;
        }else if(currentPosition > position){
            currentNode.item.showLine(0);
        }
        currentNode = currentNode.next;
        currentPosition++;
    }
    sliceNode.next = null;
    if(prevNode){
        this.setLine(prevNode.item,sliceNode.item);
    }
    this.tail = sliceNode;
    
}

清空item链表

将链表清空,item线条全部隐藏

/* 清空链表 */
public clear():void{
    let currentNode:Node = this.head;
    while(currentNode){
        currentNode.item.showLine(0);
        currentNode = currentNode.next;
    }
    this.head = null;
    this.tail = null;
    this.length = 0;
}

 

原文地址:https://www.cnblogs.com/kootimloe/p/14221527.html