528 lines
17 KiB
TypeScript
528 lines
17 KiB
TypeScript
import Config from "./Config";
|
|
import LineLogic from "./LineLogic";
|
|
import Model from "./Model";
|
|
import MetaballMgr from "./MetaballMgr";
|
|
import Ball from "./Ball";
|
|
import TipLine from "./TipLine";
|
|
import {TrackingManager, TrackingType} from "./Tracking/TrackingManager";
|
|
const { ccclass, property } = cc._decorator;
|
|
|
|
@ccclass
|
|
export default class GameDraw extends cc.Component {
|
|
|
|
@property(cc.Prefab)
|
|
Ball: cc.Prefab = null;
|
|
|
|
@property(cc.Prefab)
|
|
TopUI: cc.Prefab = null;
|
|
|
|
@property(cc.Prefab)
|
|
BottomUI: cc.Prefab = null;
|
|
|
|
@property(cc.Prefab)
|
|
Cup: cc.Prefab = null;
|
|
|
|
@property(cc.Prefab)
|
|
Line: cc.Prefab = null;
|
|
|
|
@property(cc.Node)
|
|
metaBall: cc.Node = null;
|
|
|
|
lock: boolean = false;
|
|
|
|
@property(cc.Node)
|
|
waterPipe: cc.Node = null;
|
|
|
|
@property(cc.Node)
|
|
progressNode: cc.Node = null;
|
|
|
|
@property(cc.Node)
|
|
waterContainer: cc.Node = null;
|
|
|
|
@property(cc.Prefab)
|
|
SmokeEff: cc.Prefab = null;
|
|
|
|
@property({type:cc.AudioClip})
|
|
winClip: cc.AudioClip = null;
|
|
|
|
@property({type:cc.AudioClip})
|
|
waterClip: cc.AudioClip = null;
|
|
|
|
currentLine: cc.Node
|
|
|
|
cup: cc.Node
|
|
|
|
@property([cc.Prefab])
|
|
allObjs: cc.Prefab[] = []
|
|
|
|
totalInk = 40;
|
|
totalWater = 50
|
|
waterCount = 0
|
|
|
|
waters: any = []
|
|
|
|
faceChange: boolean = false;
|
|
|
|
linePosY: number = 0;
|
|
//记录动态的物体,画线后才变动态,之前为静态
|
|
dynamicObjs = []
|
|
redObjs = []
|
|
|
|
//在水杯中的水滴数量
|
|
|
|
cupInWaterObj: any = {};
|
|
cupWater: number = 0;
|
|
|
|
@property(cc.Node)
|
|
tip: cc.Node = null;
|
|
|
|
colliderPoints: cc.Vec2[];
|
|
//已经绘制的长度,由于可以绘制多条
|
|
hasDrawLen: number = 0
|
|
|
|
onLoad() {
|
|
Config.init()
|
|
Model.game.selectedModel = 4
|
|
|
|
//开启物理效果
|
|
cc.director.getPhysicsManager().enabled = true
|
|
cc.director.getPhysicsManager().gravity = new cc.Vec2(0, -1200);
|
|
cc.director.getActionManager()['enabledAccumulator'] = true;
|
|
cc.director.getActionManager()['FIXED_TIME_STEP'] = 1 / 30;
|
|
cc.director.getPhysicsManager()['VELOCITY_ITERATIONS'] = 8;
|
|
// cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_jointBit | cc.PhysicsManager.DrawBits.e_shapeBit;
|
|
|
|
this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
|
|
this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
|
|
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
|
this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
|
|
|
|
var size = cc.view.getVisibleSize();
|
|
if (size.height / size.width > 2) {
|
|
this.progressNode.getComponent(cc.Widget).top = 200
|
|
} else {
|
|
this.progressNode.getComponent(cc.Widget).top = 145
|
|
}
|
|
this.createWorld()
|
|
|
|
var top = cc.instantiate(this.TopUI)
|
|
this.node.addChild(top)
|
|
|
|
this.metaBall.getComponent(MetaballMgr).waters = this.waters;
|
|
|
|
var bottom = cc.instantiate(this.BottomUI)
|
|
this.node.addChild(bottom);
|
|
bottom.on('showTip', this.showTip, this);
|
|
|
|
//开启抗锯齿
|
|
// cc.macro.ENABLE_WEBGL_ANTIALIAS=true;
|
|
|
|
this.progressNode.zIndex = 100
|
|
this.tip.zIndex = 100
|
|
this.node.getChildByName('gameTip').active = Model.game.selectedLevel == 1
|
|
}
|
|
createWorld() {
|
|
|
|
//createCup
|
|
var level = Model.game.selectedLevel;
|
|
var data = Config.drawLevels[level];
|
|
var cupPos = data[0]
|
|
|
|
var cup = cc.instantiate(this.Cup);
|
|
cup.getComponent(cc.RigidBody).type = cc.RigidBodyType.Static;
|
|
cup.x = cupPos[0]
|
|
cup.y = cupPos[1]
|
|
this.waterContainer.addChild(cup)
|
|
this.cup = cup;
|
|
if (cupPos.length > 2) {
|
|
cup.angle = -cupPos[2]
|
|
}
|
|
|
|
var cupData = Config.cupDatas[1]
|
|
// for (var i = 0; i < cupData.polygonColliderList.length; i++) {
|
|
// var collider = cup.addComponent(cc.PhysicsPolygonCollider)
|
|
// collider.points = cupData.polygonColliderList[i]
|
|
// collider.density = 10
|
|
// collider.apply()
|
|
// }
|
|
cup.getComponent(cc.RigidBody).enabledContactListener = true
|
|
cup.getComponent(cc.RigidBody).onBeginContact = (contact, selfCollider, otherCollider) => {
|
|
this.onBeginContact(contact, selfCollider, otherCollider)
|
|
}
|
|
this.linePosY = cupData.linePosY + cup.y;
|
|
//添加一个传感器用于检测水杯中的水滴
|
|
var collider = this.cup.addComponent(cc.PhysicsPolygonCollider);
|
|
this.colliderPoints = [cc.v2(-43, -82), cc.v2(43, -82), cc.v2(72, 70), cc.v2(-69, 70)]
|
|
collider.points = this.colliderPoints
|
|
collider.sensor = true
|
|
collider.apply()
|
|
|
|
|
|
//水龙头
|
|
var pipeInfo = data[1]
|
|
this.waterPipe.x = pipeInfo[0]
|
|
this.waterPipe.y = pipeInfo[1]
|
|
this.waterPipe.angle = -pipeInfo[2]
|
|
|
|
this.totalInk = data[3]
|
|
this.totalWater = data[4]
|
|
|
|
//平台
|
|
for (var i = 5; i < data.length; i++) {
|
|
var brickType = data[i][0]
|
|
var brick = cc.instantiate(this.allObjs[brickType - 1])
|
|
brick.x = data[i][1]
|
|
brick.y = data[i][2]
|
|
|
|
if (brickType == 3 || brickType == 8 || brickType == 11 || brickType == 13)//矩形
|
|
{
|
|
brick.setContentSize(cc.size(data[i][3], data[i][4]))
|
|
brick.getComponent(cc.PhysicsBoxCollider).size = cc.size(cc.size(data[i][3], data[i][4]))
|
|
brick.getComponent(cc.PhysicsBoxCollider).apply()
|
|
|
|
//火焰特殊处理
|
|
if (brickType == 11) {
|
|
brick.getComponent(cc.RigidBody).onBeginContact = (contact, selfCollider, otherCollider) => {
|
|
this.onBeginContact(contact, selfCollider, otherCollider)
|
|
}
|
|
}
|
|
if (brickType == 13) {
|
|
var size = brick.getComponent(cc.PhysicsBoxCollider).size
|
|
var points = [cc.v2(brick.x - size.width * 0.5, brick.y - size.height * 0.5),
|
|
cc.v2(brick.x + size.width * 0.5, brick.y - size.height * 0.5),
|
|
cc.v2(brick.x + size.width * 0.5, brick.y + size.height * 0.5),
|
|
cc.v2(brick.x - size.width * 0.5, brick.y + size.height * 0.5)]
|
|
this.redObjs.push(points)
|
|
}
|
|
|
|
} else if (brickType == 7 || brickType == 4)//圆
|
|
{
|
|
brick.setContentSize(cc.size(data[i][3], data[i][4]))
|
|
brick.getComponent(cc.PhysicsCircleCollider).radius = data[i][3] * 0.5
|
|
brick.getComponent(cc.PhysicsCircleCollider).apply()
|
|
}
|
|
brick.angle = -data[i][5]
|
|
if (brickType == 13)
|
|
this.waterContainer.addChild(brick, -1)
|
|
else
|
|
this.waterContainer.addChild(brick)
|
|
|
|
if (brick.getComponent(cc.RigidBody) != null) {
|
|
if (brick.getComponent(cc.RigidBody).type == cc.RigidBodyType.Dynamic) {
|
|
this.dynamicObjs.push(brick);
|
|
}
|
|
brick.getComponent(cc.RigidBody).type = cc.RigidBodyType.Static
|
|
}
|
|
if (Model.game.selectedLevel == 32 && brickType == 6)//特殊处理下这个球
|
|
{
|
|
brick.getComponent(cc.PhysicsCircleCollider).density = 0.01
|
|
brick.getComponent(cc.PhysicsCircleCollider).apply()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
start() {
|
|
//提示
|
|
var level = Model.game.selectedLevel;
|
|
var data = Config.drawLevels[level];
|
|
this.tip.getComponent(TipLine).points = data[2]
|
|
this.tip.active = false;
|
|
}
|
|
checkInRed(pos: cc.Vec2) {
|
|
var size = cc.view.getVisibleSize();
|
|
for (var temp of this.redObjs) {
|
|
|
|
if (cc.Intersection.pointInPolygon(cc.v2(pos.x - size.width * 0.5, pos.y - size.height * 0.5), temp)) {
|
|
console.log('lllllllllllllllllllll')
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
canMove: boolean = true;
|
|
onTouchStart(e) {
|
|
if (this.lock) return;
|
|
var pos = e.getLocation();
|
|
if (this.checkInRed(pos)) {
|
|
this.canMove = false;
|
|
return
|
|
} else {
|
|
this.canMove = true;
|
|
}
|
|
|
|
if (this.currentLine != null) {
|
|
this.hasDrawLen += this.currentLine.getComponent(LineLogic).points.length
|
|
}
|
|
var line = cc.instantiate(this.Line);
|
|
this.node.addChild(line);
|
|
this.currentLine = line
|
|
|
|
this.currentLine.getComponent(LineLogic).onTouchStart(e)
|
|
return true
|
|
}
|
|
onTouchMove(e) {
|
|
if (!this.canMove)
|
|
return
|
|
|
|
var totalLen = this.currentLine.getComponent(LineLogic).points.length + this.hasDrawLen;
|
|
if (totalLen <= this.totalInk) {
|
|
this.currentLine.getComponent(LineLogic).onTouchMove(e)
|
|
|
|
var p = (this.totalInk - totalLen) / this.totalInk;
|
|
this.progressNode.getComponent(cc.ProgressBar).progress = p;
|
|
this.progressNode.getChildByName('progress_label').getComponent(cc.Label).string = Math.floor(p * 100) + '%'
|
|
|
|
if (p < 0.8) {
|
|
this.progressNode.getChildByName('star3').active = false;
|
|
this.progressNode.getChildByName('stargray3').active = true;
|
|
}
|
|
if (p < 0.6) {
|
|
this.progressNode.getChildByName('star2').active = false;
|
|
this.progressNode.getChildByName('stargray2').active = true;
|
|
}
|
|
if (p < 0.1) {
|
|
this.progressNode.getChildByName('star1').active = false;
|
|
this.progressNode.getChildByName('stargray1').active = true;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
onTouchEnd(e) {
|
|
if (!this.canMove)
|
|
return
|
|
this.currentLine.getComponent(LineLogic).onTouchEnd(e)
|
|
this.cup.getComponent(cc.RigidBody).type = cc.RigidBodyType.Dynamic;
|
|
for (var obj of this.dynamicObjs) {
|
|
obj.getComponent(cc.RigidBody).type = cc.RigidBodyType.Dynamic;
|
|
}
|
|
|
|
this.startDropWater()
|
|
}
|
|
|
|
//开始滴水
|
|
startDropWater() {
|
|
console.log('开始创建水')
|
|
this.schedule(this.createWater, 0.06)
|
|
}
|
|
waterSoundDelay = 0.2;
|
|
waterSoundDelayCount = 10;
|
|
createWater() {
|
|
if (this.waterCount < this.totalWater) {
|
|
this.waterCount++
|
|
var ball = cc.instantiate(this.Ball);
|
|
this.waterSoundDelayCount += 0.06
|
|
if (this.waterSoundDelayCount > this.waterSoundDelay) {
|
|
this.waterSoundDelayCount = 0
|
|
cc.audioEngine.playEffect(this.waterClip, false)
|
|
}
|
|
|
|
|
|
// console.log(this.waterPipe.rotation)
|
|
if (this.waterPipe.angle == 0) {
|
|
ball.x = this.waterPipe.x + Math.random() * 8 - 16
|
|
ball.y = this.waterPipe.y + Math.random() * 5 - 75
|
|
ball.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, -0)
|
|
} else if (this.waterPipe.angle >= 181 && this.waterPipe.angle <= 178) {
|
|
ball.x = this.waterPipe.x + Math.random() * 8 - 16
|
|
ball.y = this.waterPipe.y + Math.random() * 5 + 75
|
|
ball.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, 100)
|
|
|
|
} else {
|
|
|
|
var center = this.cup.getComponent(cc.RigidBody).getWorldCenter();
|
|
var sign = this.waterPipe.angle < 0 ? -1 : 1
|
|
ball.x = this.waterPipe.x + 60 * sign + Math.random() * 8 - 4
|
|
ball.y = this.waterPipe.y + Math.random() * 10 - 5
|
|
|
|
ball.getComponent(cc.RigidBody).linearVelocity = cc.v2(sign * 150, 0)
|
|
// ball.getComponent(cc.RigidBody).applyLinearImpulse(cc.v2(200000,200000), cc.v2(center.x, center.y), true);
|
|
// ball.getComponent(cc.RigidBody).applyForce(cc.v2(1000,0),center,true)
|
|
}
|
|
|
|
|
|
|
|
ball.getComponent(Ball).id = this.waterCount
|
|
ball.getComponent(cc.PhysicsCircleCollider).density = 1
|
|
ball.getComponent(cc.PhysicsCircleCollider).restitution = 0.2
|
|
ball.getComponent(cc.PhysicsCircleCollider).apply()
|
|
this.waterContainer.addChild(ball, -1)
|
|
this.waters.push(ball);
|
|
} else {
|
|
this.unschedule(this.createWater)
|
|
this.schedule(this.checkGame, 0.1)
|
|
}
|
|
|
|
}
|
|
showFace(type: number) {
|
|
this.cup.getChildByName('facenormal').active = false;
|
|
this.cup.getChildByName('facewin').active = false;
|
|
this.cup.getChildByName('facelose').active = false;
|
|
if (type == 2) {
|
|
this.cup.getChildByName('facewin').active = true;
|
|
} else if (type == 1) {
|
|
this.cup.getChildByName('facelose').active = true;
|
|
} else if (type == 0) {
|
|
this.cup.getChildByName('facenormal').active = true;
|
|
}
|
|
}
|
|
|
|
update(dt) {
|
|
|
|
if (this.waterCount > 0) {
|
|
this.metaBall.getComponent(MetaballMgr).draw()
|
|
|
|
for (var i = 0; i < this.waters.length; i++) {
|
|
if (this.waters[i].y < -1000) {
|
|
this.waters.splice(i, 1)
|
|
i--
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
checkGame() {
|
|
if (this.lock) return
|
|
|
|
//检测胜利
|
|
if (this.waters.length >= 39) {
|
|
var newRect = []
|
|
for (var a of this.colliderPoints) {
|
|
newRect.push(cc.v2(this.cup.x + a.x, a.y + this.cup.y))
|
|
}
|
|
var count = 0
|
|
for (var temp of this.waters) {
|
|
if (cc.Intersection.pointInPolygon(temp.position, newRect)) {
|
|
count++;
|
|
}
|
|
}
|
|
//console.log(count);
|
|
if (count >= 39) {
|
|
this.gameWin();
|
|
}
|
|
}
|
|
//失败检测
|
|
this.checkLose();
|
|
}
|
|
checkLose() {
|
|
if (this.waters.length <= 15) {
|
|
this.gameLose()
|
|
return;
|
|
}
|
|
|
|
var allSleep: boolean = true
|
|
for (var ball of this.waters) {
|
|
if (ball.getComponent(cc.RigidBody).awake) {
|
|
allSleep = false
|
|
break
|
|
}
|
|
}
|
|
if (allSleep) {
|
|
this.gameLose()
|
|
}
|
|
}
|
|
gameWin() {
|
|
if (this.lock) return
|
|
this.unscheduleAllCallbacks()
|
|
this.lock = true
|
|
Model.game.win = true
|
|
this.showFace(2)
|
|
this.scheduleOnce(this.delayShowEnd, 1)
|
|
cc.audioEngine.playEffect(this.winClip, false)
|
|
this.saveData();
|
|
}
|
|
gameLose() {
|
|
if (this.lock) return
|
|
this.unscheduleAllCallbacks()
|
|
this.lock = true
|
|
Model.game.win = false
|
|
this.showFace(1)
|
|
this.scheduleOnce(this.delayShowEnd, 1)
|
|
}
|
|
delayShowEnd() {
|
|
|
|
cc.director.loadScene('gameEnd')
|
|
|
|
|
|
}
|
|
showTip() {
|
|
console.log('显示提示')
|
|
this.tip.active = true
|
|
TrackingManager.send(TrackingType.Tip);
|
|
}
|
|
|
|
onBeginContact(contact, selfCollider, otherCollider) {
|
|
|
|
|
|
// console.log(selfCollider.node.name, otherCollider.node.name)
|
|
|
|
if ((selfCollider instanceof cc.PhysicsBoxCollider) && selfCollider.node.name == 'Cup3' && otherCollider.node.name == 'Ball') {
|
|
|
|
//selfCollider.getAABB()
|
|
// if (this.cupInWaterObj[otherCollider.node.getComponent(Ball).id] == null) {
|
|
// this.cupInWaterObj[otherCollider.node.getComponent(Ball).id] = true
|
|
// this.cupWater++
|
|
// // console.log(this.cupWater,'aaaaa')
|
|
// if (this.cupWater >= 30) {
|
|
// this.gameWin()
|
|
// }
|
|
// }
|
|
|
|
if (!this.faceChange) {
|
|
this.faceChange = true
|
|
this.showFace(1);
|
|
}
|
|
|
|
}
|
|
//火焰
|
|
if (selfCollider.node.name == 'r11' && otherCollider.node.name == 'Ball') {
|
|
for (var i = 0; i < this.waters.length; i++) {
|
|
if (this.waters[i] == otherCollider.node) {
|
|
this.waters.splice(i, 1)
|
|
i--
|
|
this.createSmokeEff(otherCollider.node.x, otherCollider.node.y)
|
|
otherCollider.node.destroy()
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
saveData() {
|
|
var star = 0;
|
|
|
|
if (this.progressNode.getChildByName('star1').active) star++
|
|
if (this.progressNode.getChildByName('star2').active) star++
|
|
if (this.progressNode.getChildByName('star3').active) star++
|
|
Model.game.getStar = star;
|
|
//存储
|
|
if (Model.game.selectedLevel == Model.game.drawLevel) {
|
|
Model.game.drawLevelInfo[Model.game.selectedLevel - 1] = star
|
|
Model.game.drawLevelInfo[Model.game.selectedLevel] = -1
|
|
|
|
Model.game.drawLevel = Model.game.selectedLevel + 1;
|
|
Model.game.saveDraw()
|
|
|
|
} else {
|
|
if (star > Model.game.drawLevelInfo[Model.game.selectedLevel - 1]) {
|
|
Model.game.drawLevelInfo[Model.game.selectedLevel - 1] = star
|
|
Model.game.saveDraw();
|
|
}
|
|
// Model.game.selectedLevel++
|
|
}
|
|
}
|
|
createSmokeEff(x, y) {
|
|
var eff = cc.instantiate(this.SmokeEff);
|
|
eff.x = x;
|
|
eff.y = y;
|
|
this.node.addChild(eff);
|
|
}
|
|
|
|
checkFace() {
|
|
|
|
}
|
|
}
|