Commit b812e83c authored by XieChuanJin's avatar XieChuanJin

移植打星球,基本改掉语法错误

parent 2d0906a1
declare namespace RES {
function getRes(uuid: string): engine.Texture;
}
declare interface Math {
clamp(target: number, min: number, max: number): number;
}
declare namespace engine {
interface Point {
length: number;
}
}
\ No newline at end of file
import MoveObjcet from "./MoveObject";
import Collider, { CircleCollider, ColliderGroup } from "./Collider";
import { MConfigs } from "./MConfigs";
import { getBallScore, getProp } from "./GUtils";
import Pool, { PoolElement } from "./Pool";
import { MConst } from "./MConst";
import Drop from "./Drop";
import Bullet from "./Bullet";
import { MUtils } from "./MUtils";
import GameMgr from "./GameMgr";
import MTimer from "./MTimer";
import SoundMgr from "./SoundMgr";
import MovieClipMgr from "./MovieClipMgr";
import MTweenMgr from "./MTween";
import Game from "./Game";
let tempPower: number = null;
let tempIndexOffset: number = null;
export default class Ball extends MoveObjcet implements PoolElement {
private colorIndex = 0;
private sizeIndex = 0;
private bitmap: engine.Image = null;
public static textures: engine.Texture[] = [];
private labelScore: engine.Label = null;
private mCenterX = 0;
private scaleRatio: number = 1;
private initScore: number = null;
private initColorIndex: number = 0;
public collider: CircleCollider = null;
private isBornStage = false;
private _score = 0;
public get score() {
return this._score;
}
public set score(v: number) {
if (v < 0) v = 0;
//分数标签更新
if (this._score != v) {
this.scoreUpdateFlag = true;
}
this._score = v;
}
private onScoreIsZero() {
if (GameMgr.instance.guideFlag == true) {
this.drop();
} else {
if (this.sizeIndex > 0) {
this.split();
} else {
this.drop();
}
}
this.playBoomEffect();
SoundMgr.instance.playEffect("boom_mp3");
this.context._ballPool.destroy(this);
}
public destroyed = false;
constructor(context: Game) {
super(context);
this.bitmap = new engine.Image();
this.addChild(this.bitmap);
this.labelScore = new engine.Label();
this.labelScore.size = 100;
this.addChild(this.labelScore);
let collider = this.addComponent(CircleCollider) as CircleCollider;
collider.group = ColliderGroup.Ball;
this.collider = collider;
}
init(direction: 1 | -1, colorIndex: number, sizeIndex: number, score?: number): Ball {
let scaleRatio = MConfigs.size[sizeIndex]; //整体缩放系数
if (typeof scaleRatio == "undefined" || scaleRatio > 5 || colorIndex < 0) {
console.error("invalid params", sizeIndex, scaleRatio, colorIndex);
return;
}
this.scaleRatio = scaleRatio;
this.colorIndex = colorIndex;
this.initColorIndex = colorIndex;
this.sizeIndex = sizeIndex;
//创建图像
//TODO
let texture = RES.getRes(`ball_${colorIndex}_png`)
this.bitmap.texture = texture;
//设置图像大小
this.bitmap.width = texture.width * scaleRatio;
this.bitmap.height = texture.height * scaleRatio;
let bitmapWidth = this.bitmap.width;
let bitmapHeight = this.bitmap.height;
this.mCenterX = bitmapWidth / 2;
//创建文字
let textScore = this.labelScore;
textScore.text = "0";
textScore.scaleX = textScore.scaleY = scaleRatio;
textScore.x = bitmapWidth / 2 - textScore.width / 2 * scaleRatio;
textScore.y = bitmapHeight / 2 - textScore.height / 2 * scaleRatio;
//添加碰撞器
let collider = this.getComponent(CircleCollider) as CircleCollider;
collider.setData(bitmapWidth / 2, bitmapHeight / 2, bitmapHeight / 2);
if (!score) {
//设置初始分数
this.initScore = getBallScore(this.context._BulletScore, this.context._PowerScore, this.colorIndex);
this.score = this.initScore;
} else {
this.initScore = score;
this.score = this.initScore;
}
this.physics.rotateVelocity = direction * MConst.BallRotateSpeed * Math.pow(1 / scaleRatio, 0.5);
return this;
}
startBornStage(dir: 1 | -1) {
this.isBornStage = true;
if (dir == 1) {
this.x = 0 - this.width / 2 - 10;
} else if (dir == -1) {
this.x = MConst.DesignResolution.x + this.width / 2 + 10;
}
this.y = MConst.BallInitPosY;
this.physics.velocity.x = this.getRandomVelocityX(dir) + 1 * dir;
this.dir = dir;
this.physics.onMoved = this.onBornStageMoved.bind(this)
}
private dir: 1 | -1 = 1;
private onBornStageMoved(owner: Ball) {
if (this.dir == 1) {
if (this.x > this.width / 2) {
this.startGravityStage(this.dir);
this.physics.onMoved = null;
}
} else if (this.dir == -1) {
if (this.x < MConst.DesignResolution.x - this.width / 2) {
this.startGravityStage(this.dir);
this.physics.onMoved = null;
}
}
}
private getRandomVelocityX(direction: 1 | -1) {
return direction * MConst.BallVelocityX * (1 + ((1 / this.scaleRatio) - 1) * MUtils.random(0, MConst.BallVelocityXRandomFactor));
}
startGravityStage(direction: 1 | -1) {
this.isBornStage = false;
this.physics.velocity.x = this.getRandomVelocityX(direction);
this.physics.acceleration.y = MConst.Gravity;
}
onCollisionEnter(other: Collider) {
if (this.destroyed) {
console.error(2);
}
if (other.group == ColliderGroup.Bullet) {
tempPower = (other.owner as Bullet).power;
this.score = this.score - tempPower;
this.context._score += tempPower;
}
if (other.group == ColliderGroup.Ground) {
this.physics.velocity.y = -(MConst.BallVelocityY * (1 + ((1 / this.scaleRatio) - 1) * MUtils.random(0, MConst.BallVelocityYRandomFactor)));
//播放灰尘动画
let clip = MovieClipMgr.instance.get("duang");
clip.x = this.x - 160 * this.scaleRatio;
clip.y = this.y + 12 * this.scaleRatio;
clip.scaleX = clip.scaleY = 1.76 * this.scaleRatio;
this.context._animationLayer.addChild(clip);
clip.autoRecyclePlay("duang");
//判断是否会震动地面
if (this.sizeIndex >= MConfigs.size.length - 2) {
this.context._shake();
SoundMgr.instance.playEffect("dong_mp3");
}
}
if (other.group == ColliderGroup.Wall && !this.isBornStage) {
this.physics.velocity.x = -this.physics.velocity.x;
this.physics.rotateVelocity = -this.physics.rotateVelocity;
}
}
onCollisionStay(other: Collider) {
if (other.group == ColliderGroup.Wall && !this.isBornStage) {
let dir: 1 | -1 = other.owner.x < 0 ? 1 : -1;
this.physics.velocity.x = dir * Math.abs(this.physics.velocity.x);
this.physics.rotateVelocity = dir * Math.abs(this.physics.rotateVelocity);
}
}
/**@inheritdoc */
onElementRecycle() {
this.visible = false;
this.physics.velocity.y = 0;
this.physics.velocity.x = 0;
this.physics.acceleration.y = 0;
this.physics.acceleration.x = 0;
this.disableAllComponents();
}
onElementInit() {
this.visible = true;
this.enableAllComponents();
}
private split() {
let sizeIndex = this.sizeIndex - 1;
let score = Math.ceil(this.initScore / 2 * (Math.random() * 0.4 + 0.8));
let colorIndex = Math.max(this.initColorIndex - 1, 0);
let callback = (direction: 1 | -1) => {
let ball = this.context._ballPool.create(this.context).init(direction, colorIndex, sizeIndex, score);
ball.x = this.x;
ball.y = this.y;
ball.startGravityStage(direction);
ball.physics.velocity.y = -MConst.BallSplitVelocityY;
}
callback(1);
callback(-1);
}
private scoreUpdateFlag = false;
public updateScoreLabel() {
if (this.scoreUpdateFlag == true) {
const score = this.score;
if (score >= 1000) {
this.labelScore.text = (Math.floor(score / 100) / 10).toString() + "k";
} else {
this.labelScore.text = score.toString();
}
this.labelScore.x = this.mCenterX - this.labelScore.width / 2 * this.scaleRatio;
this.scoreUpdateFlag = false;
//判断是否需要更改颜色
if (this.initScore == null) return;
if (score > 0) {
tempIndexOffset = Math.floor((this.initScore - score) / this.initScore / (1 / (this.initColorIndex + 1)));
if (this.initColorIndex - tempIndexOffset != this.colorIndex) { //目标颜色和当前颜色不一致
//更新颜色
this.colorIndex = this.initColorIndex - tempIndexOffset;
this.bitmap.texture = RES.getRes(`ball_${this.colorIndex}_png`)
}
} else {
this.onScoreIsZero();
}
}
}
private drop() {
//掉落数
let index = 1;
//根据子弹分数判断索引
let bulletScore = this.context._BulletScore;
if (bulletScore <= 30) index = 0;
else if (bulletScore > 30 && bulletScore <= 70) index = 1;
else if (bulletScore > 70) index = 2;
//根据索引获取配置
let config: {
num: number,
factor: object
} = MConfigs.dropPool[index];
let keys = Object.keys(config.factor);
let values = keys.map(e => config.factor[e]);
let dropIds = getProp(keys, values, config.num);
let drops: Drop[] = [];
for (let id of dropIds) {
drops.push(this.context._dropPool.create(this.context).init(id));
}
let dir = this.x > MConst.DesignResolution.x / 2 ? -1 : 1;
for (let i = 0; i < drops.length; i++) {
let drop = drops[i];
drop.x = this.x - drop.bitmap.width / 2;
drop.y = this.y - drop.bitmap.height / 2;
let offsetRatio = (i - 1) + (2 - (drops.length - 1));
let x = MConst.DropVelocityX.x + offsetRatio * MConst.DropVelocityX.offset;
x *= MUtils.random(1 - MConst.DropRandomFactor, 1 + MConst.DropRandomFactor);
drop.physics.velocity.x = dir * x;
drop.physics.velocity.y = -(x * 5 * MUtils.random(0.9, 1.1));
if (GameMgr.instance.guideFlag && i == 1) {
MTimer.set(20, () => {
GameMgr.instance.runGuide(1, drop.x, drop.y, true);
});
}
}
}
private playBoomEffect() {
const color = MConfigs.boomEffectColor[MUtils.randomInt(0, MConfigs.boomEffectColor.length)];
const scaleRatio = this.scaleRatio;
//星星
const range = MConst.DefaultBallWidth * 1.5 * this.scaleRatio;
for (let i = 0; i <= 7; i++) {
const star = this.starPool.get().init(color);
const randomMax = 0.5 + (scaleRatio - 0.3125) / 2;
const scale = MUtils.random(randomMax - 0.64 * scaleRatio, randomMax);
star.width = MConst.DefaultStarSize.width * scale;
star.height = MConst.DefaultStarSize.height * scale;
star.x = this.x - star.width / 2;
star.y = this.y - star.height / 2;
MTweenMgr.instance.get(star)
.to({
x: this.x + MUtils.random(-1, 1) * range - star.width / 2,
y: this.y + MUtils.random(-1, 1) * range - star.height / 2,
alpha: 0
}, BoomEffectDuration, false)
.call(() => {
this.starPool.recycle(star);
});
}
//环
for (let i = 0; i <= 2; i++) {
let ring = this.ringPool.get().init(color);
ring.width = MConst.DefaultRingWidth * scaleRatio;
ring.height = MConst.DefaultRingWidth * scaleRatio;
ring.anchorX = ring.width / 2;
ring.anchorY = ring.height / 2;
ring.x = this.x;
ring.y = this.y;
ring.scaleX = ring.scaleY = 0.186 * (i + 1);
MTweenMgr.instance.get(ring)
.to({
scaleX: ring.scaleX * 1.792,
scaleY: ring.scaleY * 1.792,
alpha: 0
}, BoomEffectDuration + (i - 1) * BoomEffectDuration * 0.33, false)
.call(() => {
this.ringPool.recycle(ring);
});
}
}
private starPool = new EffectBitmapPool(this.context._animationLayer, "star_png");
private ringPool = new EffectBitmapPool(this.context._animationLayer, "ring_png");
}
const BoomEffectDuration = 400;
class EffectBitmapPool extends Pool<EffectBitmap>{
private layer: engine.Container = null;
private resName: string = null;
constructor(layer: engine.Container, resName: string) {
super();
this.layer = layer;
this.resName = resName;
}
createElement() {
let star = new EffectBitmap(RES.getRes(this.resName));
this.layer.addChild(star);
return star;
}
}
class EffectBitmap extends engine.Image implements PoolElement {
init(color: number) {
MUtils.setColorFilter(this, color);
return this;
}
onElementInit() {
this.visible = true;
this.alpha = 1;
}
onElementRecycle() {
this.visible = false;
}
}
import { PoolElement } from "./Pool";
import MoveObjcet from "./MoveObject";
import { MConst } from "./MConst";
import GameObject from "./GameObject";
import Collider, { CircleCollider, ColliderGroup, PointCollider } from "./Collider";
import Game from "./Game";
export default class Bullet extends MoveObjcet implements PoolElement {
public power: number = 1;
constructor(context: Game) {
super(context);
this.addChild(new engine.Image(RES.getRes("bullet_png")));
this.anchorY = 0;
let collider = this.addComponent(PointCollider) as PointCollider;
collider.group = ColliderGroup.Bullet;
collider.setData(2, 0);
this.physics.velocity.y = -MConst.BulletSpeedValue;
}
init(power: number) {
this.power = power;
return this;
}
onElementInit() {
this.enableAllComponents();
this.visible = true;
}
onElementRecycle() {
this.disableAllComponents();
this.visible = false;
}
onCollisionEnter(other: Collider) {
if (other.group == ColliderGroup.Ball || other.group == ColliderGroup.Top) {
this.context._bulletPool.destroy(this);
}
}
}
\ No newline at end of file
import GameObject from "./GameObject";
import Collider, { RectCollider, ColliderGroup } from "./Collider";
import { MConst } from "./MConst";
import Bullet from "./Bullet";
import MTweenMgr from "./MTween";
import SoundMgr from "./SoundMgr";
import MTimer from "./MTimer";
import Game from "./Game";
export default class Car extends GameObject {
private imgGun: engine.Image = null;
private imgParticel: engine.Image = null;
private fireTimer: number = null;
public touchWall: 1 | -1 | 0 = 0;
public onDied: () => void;
private isDied: boolean = false;
private invincibleDuration = 0;
constructor(context: Game) {
super(context);
this.x = 124;
this.y = 145;
this.createPart("car_shadow_png", 4.96, 138.69);
this.createPart("car_part_0_png", 12.5, 102.5);
this.imgGun = this.createPart("car_gun_png", 33.5, 120);
this.createPart("car_wheel_png", 0, 97.5);
this.imgParticel = this.createPart("car_particle_png", 15.98, 1.33);
// this.imgParticel.alpha = 0;
this.imgGun.anchorY = 100;
this.addEventListener(engine.Event.ENTER_FRAME, this.onEnterFrame, this);
let collider = this.addComponent<RectCollider>(RectCollider);
collider.setData(29, 20, 63, 150);
collider.group = ColliderGroup.Car;
this.addEventListener(engine.Event.REMOVED_FROM_STAGE, this.onDestroy, this);
}
private createPart(source: string, x: number, y: number) {
let bitmap = new engine.Image(RES.getRes(source) as engine.Texture);
bitmap.x = x;
bitmap.y = y;
this.addChild(bitmap);
return bitmap;
}
private fire() {
SoundMgr.instance.playEffect("shoot_mp3");
// let column = this.context.fireBulletNumConfig[this.fireBulletNumConfigIndex];
// this.fireBulletNumConfigIndex = this.fireBulletNumConfigIndex == 0 ? 1 : 0; //0/1交替
const column = this.context._fireBulletNumConfig;
const numb = MConst.BulletDisperseFrameNum;
let bullets: Bullet[] = [];
for (let i = 0; i < column; i++) {
const bullet = this.context._bulletPool.create(this.context).init(Math.floor(this.context._PowerScore / 100));
bullet.posY = this.posY - this.height + 26;
bullet.posX = this.posX;
let offsetX = (i - (column - 1) / 2) * MConst.BulletWidth;
bullet.physics.velocity.x = offsetX / numb;
/* MTweenMgr.instance.get(bullet).wait(MConst.BulletDisperseFrameNum, true).call(() => {
bullet.physics.velocity.x = 0;
}); */
bullets.push(bullet);
}
MTimer.set(numb, () => {
for (let i of bullets) {
i.physics.velocity.x = 0;
}
});
}
private die() {
if (this.isDied) return;
this.isDied = true;
if (this.invincibleDuration > 0) return;
this.onDied && this.onDied();
}
onCollisionEnter(other: Collider) {
if (other.group == ColliderGroup.Ball) {
this.die();
}
if (other.group == ColliderGroup.Wall) {
this.touchWall = other.owner.x < 0 ? 1 : -1;
}
}
onCollisionStay(other: Collider) {
if (other.group == ColliderGroup.Ball) {
this.die();
}
if (other.group == ColliderGroup.Wall) {
this.touchWall = other.owner.x < 0 ? 1 : -1;
}
}
private onceBlink() {
MTweenMgr.instance.get(this)
.to({ alpha: 0 }, 1, true)
.wait(2)
.to({ alpha: 1 }, 1, true)
.wait(2)
.call(() => { this.onceBlink(); });
}
revive() {
this.invincibleDuration = MConst.ReviveInvincibleDuration * 1000;
MTweenMgr.instance.removeTweens(this);
this.onceBlink();
MTimer.set(MConst.ReviveInvincibleDuration * 60, () => {
//无敌结束
this.alpha = 1;
MTweenMgr.instance.removeTweens(this);
});
}
move(deltaX: number) {
if (this.touchWall == 1 && deltaX <= 0) {
return;
} else if (this.touchWall == -1 && deltaX >= 0) {
return;
}
this.x += deltaX;
}
onCollisionExit(other: Collider) {
if (other.group == ColliderGroup.Wall) {
this.touchWall = 0;
}
}
private frameTimer = 0;
private onEnterFrame() {
if (this.context.pause) return;
if (this.invincibleDuration > 0) {
this.invincibleDuration -= MTimer.deltaTime;
}
this.fireTimer += 1 * MTimer.dtFactor;
if (this.fireTimer >= 60 / this.context._fireSpeed) {
this.fire();
this.fireTimer = 0;
}
if (this.frameTimer % 3 == 0) {
this.imgParticel.visible = !this.imgParticel.visible;
}
this.frameTimer++;
}
onDestroy() {
this.removeEventListener(engine.Event.ENTER_FRAME, this.onEnterFrame, this);
MTweenMgr.instance.removeTweens(this);
}
}
\ No newline at end of file
import GameComponent from "./GameComponent";
import GameObject from "./GameObject";
import PhycicsSystem from "./PhycicsSystem";
import Physics from "./Physics";
export default abstract class Collider extends GameComponent {
public physics: Physics = null;
private _group: ColliderGroup = null;
set group(group: ColliderGroup) {
if (this._group == null) {
this._group = group;
PhycicsSystem.instance.addCollider(this);
} else {
this._group = group;
}
}
get group() {
return this._group;
}
public type: ColliderType = null;
setData(...ags: any[]): void {
this.physics && this.physics.onColliderResize(this);
}
onEnabled() {
//自动设置物理组件
if (this.group)
PhycicsSystem.instance.addCollider(this);
let physics = this.owner.getComponent<Physics>(Physics);
if (physics) {
this.physics = physics;
physics.collider = this;
}
}
protected worldPos: engine.Point = new engine.Point();
abstract getWorldPosition(out: number[]): void;
onDisabled() {
PhycicsSystem.instance.removeCollider(this);
}
/**获取碰撞器的中心的节点坐标 */
abstract getCenter(): number[];
}
export class CircleCollider extends Collider {
public radius: number = 0
public center: number[] = []
constructor(owner: GameObject) {
super(owner);
this.type = ColliderType.Circle;
}
setData(x: number, y: number, radius: number) {
this.radius = radius;
this.center[0] = x;
this.center[1] = y;
super.setData();
}
getCenter() {
return this.center;
}
private t = {
x: 0,
y: 0
};
getWorldPosition(out: number[]) {
out[0] = this.owner.x - this.owner.anchorX + this.center[0];
out[1] = this.owner.y - this.owner.anchorY + this.center[1];
}
}
export class RectCollider extends Collider {
public rect: engine.Rectangle = new engine.Rectangle();
constructor(owner: GameObject) {
super(owner);
this.type = ColliderType.Rect;
}
setData(x: number, y: number, width: number, height: number) {
this.rect.x = x;
this.rect.y = y;
this.rect.width = width;
this.rect.height = height;
super.setData();
}
getCenter() {
return [this.rect.x + this.rect.width / 2, this.rect.y + this.rect.height / 2];
}
getWorldPosition(out: number[]) {
out[0] = this.owner.x - this.owner.anchorX + this.rect.left;
out[1] = this.owner.y - this.owner.anchorY + this.rect.top;
}
}
export class PointCollider extends Collider {
public center: number[] = [];
constructor(owner: GameObject) {
super(owner);
this.type = ColliderType.Point;
}
setData(x: number, y: number) {
this.center[0] = x;
this.center[1] = y;
super.setData();
}
getCenter() {
return this.center;
}
getWorldPosition(out: number[]) {
let owner = this.owner;
out[0] = this.owner.x + this.center[0];
out[1] = this.owner.y + this.center[1];
}
}
export enum ColliderGroup {
None = 0,
Ball = 1,
Bullet = 2,
Wall = 3,
Ground = 4,
Drop = 5,
Car = 6,
Top = 7
}
export enum ColliderType {
Circle,
Rect,
Point
}
/* import GameMgr from "./GameMgr";
export default class DebugMgr extends engine.Container {
public enabled: boolean = false;
public enabledGraphic: boolean = false;
private shapeMap = {};
private graphicDebugLayer: engine.Container = null;
private uiLayer: engine.UILayer = null;
private log: engine.Label = null;
public test: any = null;
public onClick = () => { }
constructor() {
super();
if (!this.enabled) return;
//创建图形调试层
this.graphicDebugLayer = new engine.Container();
this.graphicDebugLayer.touchEnabled = false;
this.addChild(this.graphicDebugLayer);
//创建UI层
this.uiLayer = new engine.UILayer();
this.uiLayer.touchThrough = true;
this.addChild(this.uiLayer);
//创建日志标签
this.log = new engine.Label("Log");
this.log.horizontalCenter = 0;
this.log.top = 50;
this.log.textColor = 0xffffff;
this.log.stroke = 0.5;
this.log.size = 32;
this.uiLayer.addChild(this.log);
//创建调试按钮
let button = new engine.Label("调试");
button.textColor = 0x000000;
button.borderColor = 0x000000;
button.border = true;
button.top = 30;
button.right = 50;
this.uiLayer.addChild(button);
button.onTap(this, () => {
this.onClick();
});
}
public setLog(msg: string) {
if (!this.enabled) return;
this.log.text = msg;
}
public drawRect(rect: engine.Rectangle, style: GraphicDebug.Style = { color: 0xff0000, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape = new engine.Shape();
shape.graphics.lineStyle(style.lineSize, style.color);
shape.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
this.graphicDebugLayer.addChild(shape);
}
public drawCircle(x: number, y: number, radius: number, style: GraphicDebug.Style = { color: 0xff0000, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape = new engine.Shape();
shape.graphics.lineStyle(style.lineSize, style.color);
shape.graphics.drawCircle(x, y, radius);
this.graphicDebugLayer.addChild(shape);
}
public drawLine(line: GraphicDebug.Line, style: GraphicDebug.Style = { color: 0xff0000, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape = new engine.Shape();
shape.graphics.lineStyle(style.lineSize, style.color);
shape.graphics.moveTo(line.startX, line.startY);
shape.graphics.lineTo(line.endX, line.endY);
this.graphicDebugLayer.addChild(shape);
}
public updateLine(key: string, line: GraphicDebug.Line, style: GraphicDebug.Style = { color: 0xff0000, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape: engine.Shape = this.shapeMap[key];
if (!shape) {
shape = new engine.Shape();
this.graphicDebugLayer.addChild(shape);
this.shapeMap[key] = shape;
}
shape.graphics.clear();
shape.graphics.lineStyle(style.lineSize, style.color);
shape.graphics.moveTo(line.startX, line.startY);
shape.graphics.lineTo(line.endX, line.endY);
}
public updateRect(key: string, rect: engine.Rectangle, style: GraphicDebug.Style = { color: 0xff0000, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape: engine.Shape = this.shapeMap[key];
if (!shape) {
shape = new engine.Shape();
this.graphicDebugLayer.addChild(shape);
this.shapeMap[key] = shape;
}
shape.graphics.clear();
shape.graphics.lineStyle(style.lineSize, style.color);
shape.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
}
public updateCircle(key: string, x: number, y: number, radius: number, style: GraphicDebug.Style = { color: 0xff0000, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape: engine.Shape = this.shapeMap[key];
if (!shape) {
shape = new engine.Shape();
this.graphicDebugLayer.addChild(shape);
this.shapeMap[key] = shape;
}
shape.graphics.clear();
shape.graphics.lineStyle(style.lineSize, style.color);
shape.graphics.drawCircle(x, y, radius);
}
public clearShape(key: string) {
if (!this.enabled || !this.enabledGraphic) return;
let shape: engine.Shape = this.shapeMap[key];
if (!shape) {
console.warn("collider is nonexistent");
return;
}
delete this.shapeMap[key];
shape.destroy();
}
private static _instance: DebugMgr = null;
public static get instance(): DebugMgr {
if (!this._instance) {
if (engine.gameStage) {
this._instance = new DebugMgr();
engine.gameStage.addChild(this._instance);
} else {
console.error("stage is null,DebugMgr can not instantiate");
}
}
return this._instance;
}
}
export namespace GraphicDebug {
export interface Style {
color: number;
lineSize: number;
}
export interface Line {
startX: number;
startY: number;
endX: number;
endY: number;
}
}
*/
\ No newline at end of file
import MoveObjcet from "./MoveObject";
import { MConfigs } from "./MConfigs";
import Collider, { ColliderGroup, PointCollider } from "./Collider";
import MTweenMgr from "./MTween";
import SoundMgr from "./SoundMgr";
import DropBlinkMgr from "./DropBlinkMgr";
import Game from "./Game";
export default class Drop extends MoveObjcet {
private type: string = null;
private label: engine.Label = null;
public bitmap: engine.Image = null;
private scoreValue: number = null;
private collider: PointCollider = null;
private isGround: boolean = false;
private stayGroundCount = 0;
constructor(context: Game) {
super(context);
//图像
let bitmap = new engine.Image();
this.addChild(bitmap);
this.bitmap = bitmap;
//文字
let label = new engine.Label();
label.size = 24;
this.addChild(label);
this.label = label;
this.collider = this.addComponent<PointCollider>(PointCollider);
this.collider.group = ColliderGroup.Drop;
}
init(id: number) {
let config: {
type: string,
value: number,
textColor: number,
fileIndex: string
} = MConfigs.drop[id];
this.type = config.type;
this.scoreValue = config.value;
this.physics.acceleration.y = 0.3;
let texture = RES.getRes(`drop_${config.type}_${config.fileIndex}_png`) as engine.Texture;
this.bitmap.texture = texture;
let str = "+" + config.value;
if (config.type == "power") str = str + "%";
let label = this.label;
label.text = str;
label.fillColor = config.textColor;
label.visible = false;
label.x = texture.width + 2;
label.y = texture.height / 2 - label.height / 2;
this.collider.setData(texture.width / 2, texture.height / 2);
return this;
}
private eated() {
SoundMgr.instance.playEffect("collect_mp3");
this.physics.rotateVelocity = 0;
DropBlinkMgr.instance.remove(this);
this.visible = true;
this.rotation = 0;
this.physics.enabled = false;
this.getComponent(PointCollider).enabled = false;
this.label.visible = true;
if (this.type == "bullet") {
this.context._BulletScore += this.scoreValue;
} else if (this.type == "power") {
this.context._PowerScore += this.scoreValue;
}
MTweenMgr.instance.removeTweens(this);
MTweenMgr.instance.get(this)
.to({ y: this.y - 200, alpha: 0 }, 1000, false)
.call(() => {
this.context._dropPool.destroy(this);
});
}
onCollisionEnter(other: Collider) {
if (other.group == ColliderGroup.Car) {
this.eated();
}
if (other.group == ColliderGroup.Ground && !this.isGround) {
this.stayGroundCount = 0;
this.physics.velocity.y = -(this.physics.velocity.y * 0.4);
}
if (other.group == ColliderGroup.Wall) {
this.physics.velocity.x = - this.physics.velocity.x;
if (this.isGround) {
this.physics.rotateVelocity = -this.physics.rotateVelocity
}
}
}
onCollisionStay(other: Collider) {
if (other.group == ColliderGroup.Ground && !this.isGround) {
this.stayGroundCount++;
if (this.stayGroundCount > 2) {
this.isGround = true;
this.physics.velocity.y = 0;
this.physics.acceleration.y = 0;
this.physics.velocity.x *= 0.5;
DropBlinkMgr.instance.add(this);
this.physics.rotateVelocity = this.physics.velocity.x * (180 / (Math.PI * 13));
}
}
}
onCollisionExit(other: Collider) {
if (other.group == ColliderGroup.Ground) {
this.stayGroundCount = 0;
}
}
/* destroy() {
DropBlinkMgr.instance.remove(this);
super.destroy();
} */
/* onElementInit() {
this.alpha = 1;
this.visible = true;
this.stayGroundCount = 0;
this.isGround = false;
this.enableAllComponents();
}
onElementRecycle() {
this.visible = false;
this.disableAllComponents();
} */
}
\ No newline at end of file
import Drop from "./Drop";
import { arrayRemove } from "./GUtils";
export default class DropBlinkMgr {
private static _instance: DropBlinkMgr = null;
public static get instance(): DropBlinkMgr {
if (!this._instance) {
this._instance = new DropBlinkMgr();
}
return this._instance;
}
private list: {
drop: Drop,
count: number
}[] = [];
public add(drop: Drop) {
this.list.push({
drop: drop,
count: 0
});
}
public remove(drop: Drop) {
this.list = this.list.filter(e => e.drop !== drop);
}
public static init() {
engine.gameStage.addEventListener(engine.Event.ENTER_FRAME, DropBlinkMgr.instance.onUpdate, DropBlinkMgr.instance);
}
private frameTimer: number = 0;
public onUpdate() {
if (this.frameTimer % BlinkDuration == 0) {
let temp: {
drop: Drop,
count: number
} = null;
for (let i in this.list) {
temp = this.list[i];
temp.drop.visible = !temp.drop.visible;
temp.count++;
}
this.list = this.list.filter(e => {
if (e.count < 60 / BlinkDuration * 2) {
return true;
} else {
e.drop.destroy();
return false;
}
});
}
this.frameTimer++;
}
}
const BlinkDuration = 3;
\ No newline at end of file
import { MUtils } from "./MUtils";
import { MConst } from "./MConst";
import { MConfigs } from "./MConfigs";
import Net from "./Net";
import { NetUtils } from "./NetUtils";
export const getResPath = () => window['resPath'] || '';
export const getSkinPath = (key: any) => `resource/skins/${key}Skin.exml`
let shareImg: HTMLElement = null;
export function setShareImg(imgUrl: string, rect: engine.Rectangle, visible: boolean = true) {
shareImg = shareImg || document.getElementById('shareImg');
shareImg.style.position = 'absolute';
shareImg.style.display = 'block';
shareImg.style.visibility = "visible";
shareImg.style.opacity = visible ? "1" : "0";
let scaler = document.body.clientWidth / 750;
shareImg.style.width = (scaler * rect.width).toString() + "px";
shareImg.style.height = (scaler * rect.height).toString() + "px";
shareImg.style.left = (rect.x * scaler).toString() + "px";
shareImg.style.top = (rect.y * scaler).toString() + "px";
shareImg['src'] = imgUrl;
}
export function clearShareImg() {
if (!shareImg) {
console.log("shareImg is null");
return;
}
shareImg.style.width = "0px";
shareImg.style.height = "0px";
shareImg.style.visibility = "hidden";
}
export function getBallScore(bulletScore: number, powerScore: number, colorIndex: number): any {
let getScoreFromRange = ([a, b]) => {
a = Math.ceil(a * MConfigs.difficultyFactor);
b = Math.ceil(b) * MConfigs.difficultyFactor;
let n = Math.abs(b - a) + 1;
n = Math.floor(n / 6);
const m = [];
for (let i = 0; i < 5; i++) {
m.push([a + n * i, a + n * i + n - 1]);
}
m.push([a + n * 4 + n, b])
const [a0, b0] = m[colorIndex]; //1-10
let result = Math.ceil(Math.random() * (b0 - a0 + 1)) + a0
return result;
}
if (bulletScore <= 20)
return getScoreFromRange([0.01 * powerScore, 0.2 * powerScore]);
if (bulletScore > 20 && bulletScore <= 40) {
return getScoreFromRange([0.2 * powerScore, 0.6 * powerScore]);
}
let getRange = (list: any[], props: any[]) => {
return getScoreFromRange(getProp(list, props)[0]);
}
if (bulletScore > 40 && bulletScore <= 60) {
const list = [
[0.2 * powerScore, 0.6 * powerScore],
[0.6 * powerScore, 0.8 * powerScore],
[0.8 * powerScore, 1.5 * powerScore],
]
return getRange(list, [3, 5, 2]);
}
if (bulletScore > 60 && bulletScore <= 80) {
const list = [
[0.6 * powerScore, 0.8 * powerScore],
[0.8 * powerScore, 1.5 * powerScore],
[1.5 * powerScore, 2.2 * powerScore],
]
return getRange(list, [2, 5, 2]);
}
if (bulletScore > 80 && bulletScore <= 100) {
const list = [
[1.5 * powerScore, 2.2 * powerScore],
[2.2 * powerScore, 3.2 * powerScore],
[3.2 * powerScore, 4.2 * powerScore],
]
return getRange(list, [1, 5, 4]);
}
if (bulletScore > 100 && bulletScore <= 120) {
const list = [
[2.2 * powerScore, 3.2 * powerScore],
[3.2 * powerScore, 4.2 * powerScore],
[4.2 * powerScore, 5.2 * powerScore],
]
return getRange(list, [1, 4, 5]);
}
const list = [
[2.2 * powerScore, 3.2 * powerScore],
[3.2 * powerScore, 4.2 * powerScore],
[4.2 * powerScore, 5.2 * powerScore],
]
return getRange(list, [1, 3, 6]);
}
export function getProp(items: any[], props: number[], n = 1) {
let pool = [];
for (let i in items) {
for (let j = 0; j < props[i]; j++) {
pool.push(items[i]);
}
}
const result = [];
for (let i = 0; i < n; i++) {
result.push(pool[MUtils.randomInt(0, pool.length)]);
}
return result;
}
export function createPropsCard(id: string): engine.Container {
let bgUrl = "score_card_bg_png";
if (id == MConst.ReviveCardId) {
bgUrl = "revive_card_bg_png"
}
let group = new engine.Container();
group.addChild(new engine.Image(RES.getRes(bgUrl)));
let label = new engine.Label();
label.text = MConfigs.props[id].name;
label.fillColor = 0x0a703e;
label.size = 24;
label.offsetX = 0;
label.offsetY = 0;
group.addChild(label);
return group;
}
export function getPropsTypeName(type: 0 | 1): string {
switch (type) {
case 0: return "原地复活卡";
case 1: return "加分卡";
default: return null;
}
}
export function restart() {
}
export function arrayRemove(array: any[], target: any): any[] {
let newArray = [];
for (let i = 0; i < array.length; i++) {
if (array[i] !== target) {
newArray.push(array[i]);
}
}
return newArray;
}
export function isWeiXin() {
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i)) {
return true
} else {
return false
}
}
export function wxConfig(): Promise<void> {
return new Promise<void>(resolve => {
Net.sendGet("/wechatShare/getShareInfo/v2", {
wxdebug: false,
url: window.location.href
}, (res) => {
wx.config({
debug: false,
appId: res.wxappid,
timestamp: res.wxtimestamp,
nonceStr: res.wxnonceStr,
signature: res.wxsignature,
jsApiList: ['checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage']
});
wx.error(function (res: any) {
console.error("wx error", res);
});
wx.ready(function () {
resolve();
});
}, () => { resolve(); });
});
}
export function invokeWX(onSuccess?: () => void, onCancel?: () => void) {
let share = window["shareData"];
wx.onMenuShareTimeline({
title: share.title,
desc: share.desc,
link: share.url + NetUtils.getProjectId(),
imgUrl: share.imgUrl,
success: function () {
onSuccess && onSuccess();
},
cancel: function () {
onCancel && onCancel();
}
});
wx.onMenuShareAppMessage({
title: share.title,
desc: share.desc,
link: share.url + NetUtils.getProjectId(),
imgUrl: share.imgUrl,
success: function () {
onSuccess && onSuccess();
},
cancel: function () {
onCancel && onCancel();
}
});
}
export function getAppLocation() {
return new Promise<engine.Point>((resolve, reject) => {
window["getClientLocation"] = function (latitudeC: number, longitudeC: number) {
resolve(new engine.Point(longitudeC, latitudeC));
};
setTimeout(() => {
resolve(null);
}, 1000);
window["App"].getLocation();
});
}
export function getCookie(cookieName: string) {
var strCookie = document.cookie;
var arrCookie = strCookie.split("; ");
for (var i = 0; i < arrCookie.length; i++) {
var arr = arrCookie[i].split("=");
if (cookieName == arr[0]) {
return arr[1];
}
}
return "";
}
export function login() {
return new Promise<void>((resolve, reject) => {
Net.sendGet(`/ctool/getProjectUserInfo`, undefined, (res) => {
window["$"]("body").append(res.data.loginJs);
if (window['requirelogin']) {
window['requirelogin']();
resolve();
} else {
reject("no function requirelogin");
}
}, () => {
reject();
});
})
}
import Car from "./Car";
import { MConst } from "./MConst";
import PlayerController from "./PlayerController";
import Ball from "./Ball";
import Physics from "./Physics";
import GameObject from "./GameObject";
import { RectCollider, ColliderGroup } from "./Collider";
import { MConfigs } from "./MConfigs";
import PoolMgr from "./PoolMgr";
import MTweenMgr from "./MTween";
import Drop from "./Drop";
import { MUtils } from "./MUtils";
import { arrayRemove } from "./GUtils";
import MTimer from "./MTimer";
import PhycicsSystem from "./PhycicsSystem";
import Bullet from "./Bullet";
export default class Game {
/****** property ******/
/**
*
* 当前得分
* @readonly
*/
public get score(): number {
return this._score;
}
/**
* 当前计时器时间
* @readonly
*/
public get timer() {
return this._timer;
}
/**
* 子弹分数
* @readonly
*/
public get bulletScore(): number {
return this._bulletScore;
}
/**
* 火力分数
* @readonly
*/
public get powerScore(): number {
return this._powerScore;
}
/**设置游戏暂停状态 */
public set pause(v: boolean) {
this._pause = v;
this.timing = !this._pause; //取反
PhycicsSystem.instance.pause = this._pause;
MTweenMgr.instance.pause = this._pause;
}
public get pause() {
return this._pause;
}
private _pause: boolean = false;
/**游戏结束回调函数 */
public onGameOver: () => void;
/**分数改变时的回调函数 delta是分数的变化量 */
public onScoreChange: (delta: number) => void;
/****** public method ******/
/**复活 */
public revive() {
this._car.revive();
this.pause = false;
}
/**结束游戏 */
public destroy() {
this.scene.destroy();
PhycicsSystem.instance.enabled = false;
}
constructor(parent: engine.Container) {
PhycicsSystem.instance.enabled = true;
this.pause = false;
//创建墙和地面
this.createWall();
parent.addChild(this.scene);
this.scene.width = MConst.DesignResolution.x;
this.scene.height = MConst.DesignResolution.y;
let bg = new engine.Image(RES.getRes("main_bg_jpg"));
bg.x = -10;
bg.y = -10;
this.scene.addChild(bg);
//子弹层
this.scene.addChild(this._bulletLayer);
//炮车
let car = new Car(this);
car.anchorY = 1;
car.posX = this.scene.width / 2;
car.posY = MConst.GroundLine;
this.scene.addChild(car);
car.addComponent(Physics);
car.onDied = () => {
this.over();
};
this._car = car;
//球的层
this.scene.addChild(this._ballLayer);
//掉落物层
this.scene.addChild(this._dropLayer);
//动画层
this.scene.addChild(this._animationLayer);
//玩家控制器
let playerController = new PlayerController();
playerController.onTouchMove = (deltaX) => {
if (!this.pause) {
car.move(deltaX);
}
};
this.scene.addChild(playerController);
//添加监听器
this.scene.addEventListener(engine.Event.ENTER_FRAME, this.onUpdate, this);
this.scene.addEventListener(engine.Event.REMOVED_FROM_STAGE, () => {
this.scene.removeEventListener(engine.Event.ENTER_FRAME, this.onUpdate, this);
}, this);
//开始倒计时
this.timing = true;
}
/****** private method ******/
private over() {
this.pause = true;
this.onGameOver && this.onGameOver();
}
private createWall() {
let topWall = new GameObject();
topWall.x = -500;
topWall.y = -500
this.scene.addChild(topWall);
//添加天花板碰撞器
let topWallCollider = topWall.addComponent<RectCollider>(RectCollider);
topWallCollider.setData(0, 0, MConst.DesignResolution.x + 1000, 490);
topWallCollider.group = ColliderGroup.Top;
//创建地面节点
let ground = new GameObject();
ground.x = -500;
ground.y = MConst.GroundLine;
this.scene.addChild(ground);
//添加地面碰撞器
let groundCollider = ground.addComponent<RectCollider>(RectCollider);
groundCollider.setData(0, 0, MConst.DesignResolution.x + 1000, 1000);
groundCollider.group = ColliderGroup.Ground;
//创建左墙节点
let leftWall = new GameObject();
leftWall.x = -500;
leftWall.y = -500
this.scene.addChild(leftWall);
//添加左墙碰撞器
let leftWallCollider = leftWall.addComponent<RectCollider>(RectCollider);
leftWallCollider.setData(0, 0, 500, MConst.DesignResolution.y + 1000);
leftWallCollider.group = ColliderGroup.Wall;
//创建右墙节点
let rightWall = new GameObject();
rightWall.x = MConst.DesignResolution.x;
rightWall.y = -500
this.scene.addChild(rightWall);
//添加右墙碰撞器
let rightWallCollider = rightWall.addComponent<RectCollider>(RectCollider);
rightWallCollider.setData(0, 0, 500, MConst.DesignResolution.y + 1000);
rightWallCollider.group = ColliderGroup.Wall;
}
private createBall() {
let size = MUtils.randomInt(0, MConfigs.size.length);
/* if (GameMgr.instance.guideFlag == true) {
size = 3;
} */
let color = MUtils.randomInt(size, MConst.MaxColorIndex);
let ball = this._ballPool.create(this);
let dir: 1 | -1 = Math.random() > 0.5 ? -1 : 1;
ball.init(dir, color, size);
ball.startBornStage(dir);
this.createBallCD = 1500;
}
private onUpdate() {
for (let i = 0; i < this.ballList.length; i++) {
this.ballList[i].updateScoreLabel();
}
//分数更新
if (this.bulletScoreUpdateFlag) {
let score = this._BulletScore;
//更新最大球共存数量
this.updateMaxBallNum(score);
//更新开火速度
if (score <= 20) {
const max = MConst.BulletFireSpeed.max;
const min = MConst.BulletFireSpeed.min;
this._fireSpeed = min + (max - min) * (score / 20);
} else {
this._fireSpeed = MConst.BulletFireSpeed.max;
}
this._fireBulletNumConfig = Math.ceil((Math.clamp(score, 15, 140) / 2) / 10);
this.bulletScoreUpdateFlag = false;
}
//检查球的创建
if (this.createBallCD > 0) {
this.createBallCD -= MTimer.deltaTime;
}
if (this.ballCount < this.curMaxBallNum) {
if (this.createBallCD <= 0) {
this.createBall();
}
}
//倒计时
if (this.timing) {
if (this._timer > 0) {
this._timer -= MTimer.deltaTime;
} else {
this._timer = 0;
this.timing = false;
//时间到
this.pause = true;
this.onGameOver && this.onGameOver();
}
}
}
private updateMaxBallNum(bulletScore: number) {
let num = 0;
if (bulletScore <= 20) num = 1;
else if (bulletScore <= 60) num = 2;
else if (bulletScore <= 100) num = 3
else if (bulletScore <= 130) num = 4;
else if (Math.random() < 0.3) num = 6;
else num = 7;
this.curMaxBallNum = num;
}
/**
* Ball类专用
* 不建议调用
*/
public _shake() {
MTweenMgr.instance.removeTweens(this.scene);
let count = 0;
let callback = () => {
if (count > 1) return;
count++;
this.scene.x = 10;
MTweenMgr.instance.get(this.scene)
.wait(1, true)
.to({ x: 0, y: -10 }, 1, true)
.to({ x: -10, y: 0 }, 1, true)
.to({ x: 0, y: 10 }, 1, true)
.to({ x: 0, y: 0 }, 1, true)
.call(callback);
}
callback();
}
/****** private field ******/
/**不建议使用 */
public _ballLayer: engine.Container = new engine.Container();
/**不建议使用 */
public _bulletLayer: engine.Container = new engine.Container(); //子弹层
/**不建议使用 */
public _dropLayer: engine.Container = new engine.Container();
/**不建议使用 */
public _animationLayer = new engine.Container();
/**不建议使用 */
public _fireSpeed: number = MConst.BulletFireSpeed.min;
/**不建议使用 */
public _fireBulletNumConfig: number = 1;
/**不建议使用 */
public get _score(): number {
return this.__score;
}
public set _score(v: number) {
this.onScoreChange && this.onScoreChange(v - this.__score);
this.__score = v;
}
/**不建议使用 */
public _car: Car = null;
private __score: number = 0;
private ballCount = 0;
private curMaxBallNum = 1;
private timing = false;
private createBallCD: number = 0;
private bulletScoreUpdateFlag = false;
private ballList: Ball[] = [];
private _timer: number = MConfigs.countDown * 1000;
private scene: engine.Container = new engine.Container();
/**不建议使用 */
public get _BulletScore(): number {
return this._bulletScore;
}
public set _BulletScore(v: number) {
if (v == this._bulletScore) return;
v = Math.max(v, 0);
this._bulletScore = v;
this.bulletScoreUpdateFlag = true;
}
private _bulletScore: number = 0;
/**不建议使用 */
public get _PowerScore(): number {
return this._powerScore;
}
public set _PowerScore(v: number) {
v = Math.max(v, 100);
this._powerScore = v;
}
private _powerScore: number = 100;
/****** inner class ******/
/**
* 球内存池
* 不建议使用
*/
public _ballPool = new class extends PoolMgr<Ball>{
createElement([context]: [Game]) {
return new Ball(context);
}
destroy(ball: Ball) {
super.destroy(ball);
this.context.ballCount--;
this.context.ballList = arrayRemove(this.context.ballList, ball);
}
private context: Game = null;
constructor(context: Game) {
super(context._ballLayer);
this.context = context;
}
create(context: Game) {
context.ballCount++;
let ball = super.create(context);
this.context.ballList.push(ball);
return ball;
}
}(this);
/**
* 掉落物内存池
* 不建议使用
*/
public _dropPool = new class DropPool {
private layer: engine.Container = null;
constructor(layer: engine.Container) {
this.layer = layer;
}
create(context: Game) {
let d = new Drop(context); //暂时不对掉落物进行内存池处理
this.layer.addChild(d);
return d;
}
destroy(drop: Drop) {
drop.destroy();
}
}(this._dropLayer);
/**
* 子弹内存池
* 不建议调用
*/
public _bulletPool = new class {
private data: Bullet[] = [];
private layer: engine.Container = null;
constructor(layer: engine.Container) {
this.layer = layer;
}
create(context: Game) {
if (this.data.length > 0) {
let e = this.data.pop();
e.onElementInit();
return e;
} else {
let b = new Bullet(context);
this.layer.addChild(b);
return b;
}
}
destroy(bullet: Bullet) {
bullet.onElementRecycle();
this.data.push(bullet);
}
}(this._bulletLayer);
}
import GameObject from "./GameObject";
export default abstract class GameComponent {
public get enabled(): boolean {
return this._enabled;
}
public set enabled(v: boolean) {
if (v == true && this._enabled == false) {
this.onEnabled();
this._enabled = v;
} else if (v == false && this._enabled == true) {
this.onDisabled();
this._enabled = v;
}
}
private _enabled: boolean = false;
public get owner(): GameObject {
return this._owner;
}
private _owner: GameObject = null;
constructor(owner: GameObject) {
this._owner = owner;
}
protected abstract onEnabled(): void;
protected abstract onDisabled(): void;
}
\ No newline at end of file
import PoolMgr from "./PoolMgr";
import Ball from "./Ball";
import PhycicsSystem from "./PhycicsSystem";
import MTweenMgr from "./MTween";
import SoundMgr from "./SoundMgr";
import { MConfigs } from "./MConfigs";
import GuideMask from "./GuideMask";
import SceneCtrl from "./MSceneCtrl";
export default class GameMgr {
private static _instance: GameMgr = null;
public static get instance(): GameMgr {
if (!this._instance) {
this._instance = new GameMgr();
}
return this._instance;
}
public t: number = 0;
public dropNum: number = 0;
private mainScene: MainScene = null;
init(mainScene: MainScene) {
this.mainScene = mainScene;
}
public switchSound() {
SoundMgr.instance.musicEnabled = !SoundMgr.instance.musicEnabled;
SoundMgr.instance.effectEnabled = !SoundMgr.instance.effectEnabled;
}
public get guideFlag(): boolean {
return localStorage.getItem("guide") != "false";
}
public set guideFlag(v: boolean) {
localStorage.setItem("guide", v ? "true" : "false");
}
private currentGuideMask: GuideMask = null;
public runGuide(index: number, x: number, y: number, end: boolean = false) {
this.mainScene.game.pause = true;
this.currentGuideMask = new GuideMask(index, x, y);
this.currentGuideMask.onClick = () => {
this.currentGuideMask && this.currentGuideMask.destroy();
this.mainScene.game.pause = false;
if (end) {
this.guideFlag = false;
}
};
SceneCtrl.instance.parent.addChild(this.currentGuideMask);
}
public minEnableCaptchaScore: number = null;
public leftTimes: number = null;
public leftShareTimes: number = null;
public allPeriodEnd: number = null;
public isWenzhouUser: boolean = false;
}
\ No newline at end of file
import GameComponent from "./GameComponent";
import { MUtils } from "./MUtils";
import Collider from "./Collider";
import Game from "./Game";
export default class GameObject extends engine.Container {
public name: string = "";
private _position: engine.Point = new engine.Point();
public get position() {
this._position.x = this.x;
this._position.y = this.y;
return this._position;
}
public addComponent<T extends GameComponent>(cls: any): T {
if (this.getComponent(cls) != null) {
console.error("component is existent");
return;
}
let ins = new cls(this);
ins.enabled = true;
this.componentList.push(ins);
return ins;
}
public getComponent<T extends GameComponent>(cls: any): T {
for (let i of this.componentList) {
if (i instanceof cls) {
return i as T;
}
}
return null;
}
public removeComponent(cls: any) {
for (let i of this.componentList) {
if (i instanceof cls) {
i.enabled = false;
this.componentList = this.componentList.filter(e => e != i);
return;
}
}
}
private componentList: GameComponent[] = [];
protected context: Game = null;
constructor(context?: Game) {
super();
this.anchorX = 0.5;
this.anchorY = 0.5;
this.context = context;
this.touchEnabled = false;
this.touchChildren = false;
this.addEventListener(engine.Event.REMOVED_FROM_STAGE, this.disableAllComponents, this);
}
/**锚点X轴 */
public get anchorX(): number {
return this._anchorX;
}
public set anchorX(v: number) {
this._anchorX = Math.clamp(v, 0, 1);
}
private _anchorX: number = 0;
/**锚点Y轴 */
public get anchorY(): number {
return this._anchorY;
}
public set anchorY(v: number) {
this._anchorY = Math.clamp(v, 0, 1);
}
private _anchorY: number = 0;
public get posX(): number {
return this.x + this.width * this.scaleX * this.anchorX;
}
public set posX(v: number) {
this.x = v - this.width * this.scaleX * this.anchorX;
}
public get posY(): number {
return this.y + this.height * this.scaleY * this.anchorY;
}
public set posY(v: number) {
this.y = v - this.height * this.scaleY * this.anchorY;
}
protected disableAllComponents() {
Object.keys(this.componentList).forEach(e => this.componentList[e].enabled = false);
}
protected enableAllComponents() {
Object.keys(this.componentList).forEach(e => this.componentList[e].enabled = true);
}
public onCollisionEnter(other: Collider) {
}
public onCollisionStay(other: Collider) {
}
public onCollisionExit(other: Collider) {
}
}
\ No newline at end of file
// export const MConfigs: any = window;
export namespace MConfigs {
export function updateConfig() {
let mconfig = window["mconfig"];
if (typeof mconfig != "object") return;
Object.keys(mconfig).forEach(e => {
MConfigs[e] = mconfig[e];
});
}
export const appId = "123";
export const size = [0.3125, 0.5357, 0.7321, 1];
export const drop = {
0: {
type: "bullet",
value: 1,
textColor: 0x5dcefa,
fileIndex: "0"
},
1: {
type: "bullet",
value: 2,
textColor: 0x69e7fc,
fileIndex: "1"
},
2: {
type: "power",
value: 30,
textColor: 0xe83cf7,
fileIndex: "2"
},
3: {
type: "power",
value: 20,
textColor: 0xeb3924,
fileIndex: "1"
},
4: {
type: "power",
value: 10,
textColor: 0xfef552,
fileIndex: "0"
}
}
export const dropPool = {
0: {
num: 3,
factor: {
0: 40,
1: 0,
2: 0,
3: 15,
4: 50
}
},
1: {
num: 2,
factor: {
0: 40,
1: 0,
2: 5,
3: 15,
4: 50
}
},
2: {
num: 1,
factor: {
0: 40,
1: 0,
2: 5,
3: 15,
4: 50
}
}
}
export const props: {
[key: string]: {
id: string,
type: 0 | 1
value: number,
name: string
}
} = {
"sp_1": {
id: "sp_1",
type: 0,
value: null,
name: "复活卡"
},
"sp_2": {
id: "sp_2",
type: 1,
value: 100,
name: "1万分"
},
"sp_3": {
id: "sp_3",
type: 1,
value: 200,
name: "2万分"
},
"sp_4": {
id: "sp_4",
type: 1,
value: 300,
name: "3万分"
},
"sp_5": {
id: "sp_5",
type: 1,
value: 600,
name: "6万分"
},
"sp_6": {
id: "sp_6",
type: 1,
value: 800,
name: "8万分"
}
}
export const boomEffectColor = [
0xe41014,
0xff9600,
0x0090ff,
0x8aff00,
0xffe720
]
/**倒计时秒数 */
export const countDown = 300;
/**毫秒 */
export const GameOverPanelStayTime = 60000;
export const rewardList = [
{
rank: 1,
url: ""
},
{
rank: 2,
url: ""
},
{
rank: 3,
url: ""
},
{
rank: 4,
url: ""
},
{
rank: 5,
url: ""
}
]
export const guide: {
[key: number]: {
mask: string,
text: {
str: string,
offsetToMask: {
x: number,
y: number
}
}
}
} = {
0: {
mask: "guide_mask_0_png",
text: {
str: "左右移动炮车进行射击和躲避",
offsetToMask: {
x: 41,
y: 240
}
}
},
1: {
mask: "guide_mask_1_png",
text: {
str: "拾取金币可获得更多的炮弹输出和得分加成",
offsetToMask: {
x: 41,
y: 394
}
}
},
}
export const difficultyFactor = 0.1;
export const lastRankListType = "20191104";
export const rewardRecordUrl = "http://activity.m.duibatest.com.cn/projectx/p98a3fa4c/f09ba186f.html";
export const onlineDate = "2019-10-31 14:50:49:123";
export const urlMore = "http://www.baidu.com"
export const wxRule = `结构一节将帮助你了解常见库的格式以及如何为每种格式
书写正确的声明文件。 如果你在编辑一个已经存在的文件,那么你可能不需要阅读此章节。 如果你在书写新的声明
文件,那么你必须阅读此章节以理解库的不同格式是如何影响声明文件的书写的。
结构一节将帮助你了解常见库的格式以及如何为每种格式书写正确的声明文件。 如果你在
编辑一个已经存在的文件,那么你可能不需要阅读此
章节。 如果你在书写新的声明文件,那么你必须阅读此章节以理解库的不同格式是如何影响
声明文件的书写的。`;
export const appRule = `结构一节将帮助你了解常见库的格式以及如何为每种格式
书写正确的声明文件。 如果你在编辑一个已经存在的文件,那么你可能不需要阅读此章节。 如果你在书写新的声明
文件,那么你必须阅读此章节以理解库的不同格式是如何影响声明文件的书写的。
结构一节将帮助你了解常见库的格式以及如何为每种格式书写正确的声明文件。 如果你在
编辑一个已经存在的文件,那么你可能不需要阅读此
章节。 如果你在书写新的声明文件,那么你必须阅读此章节以理解库的不同格式是如何影响
声明文件的书写的。`
export const share = {
title: "分享标题",
desc: "分享描述",
imgUrl: "http://duiba.oss-cn-hangzhou.aliyuncs.com/db_games/activity/zhaohang_bill_2019/share.png",
url: "http://activity-2.m.duiba.com.cn/customShare/share?id=3651"
}
export const toAppUrl = "http://www.baidu.com"
export const wxMoreUrl="http://www.baidu.com"
}
export namespace MConst {
export const MaxColorIndex = 5;
export const DesignResolution = {
x: 750,
y: 1624
};
export const GroundLine = 1110;
export const BulletSpeedValue = 20;
export const BulletFireSpeed = {
min: 10,
max: 20
}
export const Gravity = 0.15;
export const BallVelocityX = 2;
export const BallVelocityY = 11;
export const BallSplitVelocityY = 6.8;
export const DropVelocityX = {
x: 2,
offset: 0.5
}
export const BallRotateSpeed = 0.7;
export const BulletWidth = 14;
export const BulletDisperseFrameNum = 4;
export const BallInitPosY = 1206 * 0.25;
export const CreateBallInterval = 1000;
export const ReviveCardId = "sp_1";
export const ConstantSubmitScoreNum = 30000;
export const DefaultBallWidth = 224;
export const DefaultRingWidth = 672 * 0.744;
export const DefaultStarSize = {
width: 76 * 0.744,
height: 72 * 0.744
};
export const captchaId = "a869bfdfb9bd4cdf88e1ff2f8667a114";
export const BallVelocityXRandomFactor = 0.1;
export const BallVelocityYRandomFactor = 0.08;
export const DropRandomFactor = 0.07;
/**
* 单位:秒
*/
export const ReviveInvincibleDuration = 3;
export const WenzhouLocation: engine.Rectangle = new engine.Rectangle(119.37, 27.03, 1.81, 1.33);
export const HangzhouLocation: engine.Rectangle = new engine.Rectangle(118.21, 29.11, 2.09, 1.22);
}
\ No newline at end of file
const DefaultDtFactor = 60 / 1000;
export default class MTimer {
private static onFrameList: ((dt: number, self: Function) => void)[] = [];
private static timerList: ((self: Function) => void)[] = [];
public static deltaTime: number = 0;
public static get dtFactor() {
return MTimer.deltaTime * DefaultDtFactor;
}
public static init() {
engine.gameStage.addEventListener(engine.Event.ENTER_FRAME, () => {
for (let i = 0; i < MTimer.onFrameList.length; i++) {
MTimer.onFrameList[i](MTimer.deltaTime, MTimer.onFrameList[i]);
}
for (let i = 0; i < MTimer.timerList.length; i++) {
MTimer.timerList[i](MTimer.timerList[i]);
}
}, MTimer);
}
private static removeOnFrame(callback: Function) {
MTimer.onFrameList = MTimer.onFrameList.filter(e => e != callback);
}
public static set(frame: number, onTimeOut: () => void) {
let count = 0;
MTimer.timerList.push((self: Function) => {
count += MTimer.dtFactor;
if (count >= frame) {
onTimeOut();
MTimer.timerList = MTimer.timerList.filter(e => e != self);
}
});
}
public static onFrame(callback: (deltaTime: number, remove?: () => void) => void, frameCount?: number) {
if (typeof frameCount != "undefined") {
let count = 0;
MTimer.onFrameList.push((deltaTime: number, self: Function) => {
callback(deltaTime);
count += MTimer.dtFactor;
if (count >= frameCount) {
MTimer.removeOnFrame(self);
}
});
} else {
MTimer.onFrameList.push((deltaTime: number, self: Function) => {
callback(deltaTime, () => {
MTimer.removeOnFrame(self);
});
});
}
}
}
\ No newline at end of file
import { MUtils } from "./MUtils";
import MTimer from "./MTimer";
class MTween {
public static readonly frameRate = 60;
private tweenList: MTweenBase[] = [];
public currentTween: MTweenBase = null;
public target: object = null
constructor(target: object) {
this.target = target;
}
public wait(duration: number, isFrameCount = true, callback?: () => void) {
this.addTween(new WaitTween(isFrameCount ? duration : this.toFrameRate(duration), this, callback));
return this;
}
private addTween(tween: MTweenBase) {
if (this.currentTween == null) {
this.currentTween = tween;
} else {
this.tweenList.push(tween);
}
}
public to(props: object, duration: number, isFrameCount = true) {
this.addTween(new LinearTween(props, isFrameCount ? duration : this.toFrameRate(duration), this));
return this;
}
public call(callback: () => void) {
this.addTween(new CallbackTween(callback, 0, this));
return this;
}
private toFrameRate(duration: number) {
return duration / 1000 * MTween.frameRate;
}
public update() {
if (!this.currentTween) return;
this.currentTween.apply(MTimer.dtFactor);
if (this.currentTween.frameCount <= 0) {
if (this.tweenList.length > 0) {
this.currentTween = this.tweenList.shift();
} else {
this.currentTween = null;
}
}
}
}
abstract class MTweenBase {
private started = false;
public frameCount: number = 0;
protected tweenObjet: MTween = null;
constructor(frameCount: number, tweenObject: MTween) {
this.tweenObjet = tweenObject;
this.frameCount = frameCount;
}
protected start() { }
public apply(dtFactor?: number) {
if (this.started == false) {
this.start();
this.started = true;
}
this.frameCount--;
}
}
class LinearTween extends MTweenBase {
private once: object = null;
constructor(props: object, frameCount: number, tweenObject: MTween) {
super(frameCount, tweenObject);
this.once = props;
}
public start() {
Object.keys(this.once).forEach(key => {
this.getOnceValue(this.once, key, this.once[key]);
});
}
private getOnceValue(props: object, key: string, value: number) {
if (typeof value == "undefined" || value == null) return props[key] = value;
if (this.frameCount == 0) {
return props[key] = value;
} else {
if (typeof this.tweenObjet.target[key] == "number") {
let delta = value - this.tweenObjet.target[key];
let once = delta / this.frameCount;
props[key] = once;
} else {
console.error("prop is not number");
delete props[key];
}
}
}
public apply(dtFactor: number) {
super.apply(dtFactor);
Object.keys(this.once).forEach(key => {
this.tweenObjet.target[key] += this.once[key] * dtFactor;
});
}
}
class WaitTween extends MTweenBase {
private callback: () => void = null;
constructor(frameCount: number, tweenObject: MTween, callback?: () => void) {
super(frameCount, tweenObject);
this.callback = callback;
}
apply() {
super.apply();
this.callback && this.callback();
}
}
class CallbackTween extends MTweenBase {
private callback: () => void = null;
constructor(callback: () => void, frameCount: number, tweenObject: MTween) {
super(frameCount, tweenObject);
this.callback = callback;
}
public start() {
this.callback();
this.callback = null;
}
}
export default class MTweenMgr {
public pause: boolean = false;
private static _instance: MTweenMgr = null;
public static get instance(): MTweenMgr {
if (!this._instance) {
this._instance = new MTweenMgr();
}
return this._instance;
}
private tweenObjectList: MTween[] = [];
private removeQueue: any[] = [];
private isTraversing = false;
public init() {
// engine.startTick(this.update, this);
engine.gameStage.addEventListener(engine.Event.ENTER_FRAME, this.update, this);
}
public removeTweens(target: object) {
if (this.isTraversing) {
this.removeQueue.push(target);
} else {
this.tweenObjectList = this.tweenObjectList.filter(e => e.target !== target);
}
}
public get(target: object) {
let tween = new MTween(target);
this.tweenObjectList.push(tween);
return tween;
}
private update() {
if (this.pause) return;
this.isTraversing = true;
for (let i = 0; i <= this.tweenObjectList.length - 1; i++) {
this.tweenObjectList[i].update();
}
this.isTraversing = false;
this.tweenObjectList = this.tweenObjectList.filter((tween) => {
if (tween.currentTween == null) return false;
for (let removeTarget of this.removeQueue) {
if (removeTarget === tween.target) {
return false;
}
}
return true;
});
this.removeQueue = [];
return false;
}
}
\ No newline at end of file
export namespace MUtils {
/**左闭右开 */
export function random(min: number, max: number) {
return Math.random() * (max - min) + min;
}
/**左闭右开 */
export function randomInt(min: number, max: number) {
return Math.floor(Math.random() * (max - min) + min);
}
export function toRadians(degrees: number) {
return degrees / 180 * Math.PI;
}
export function toDegress(radians: number) {
return radians / Math.PI * 180;
}
export function degreesAngelAdd(a: number, b: number) {
return (a + b) % 360;
}
export function dot(vec1: engine.Point, vec2: engine.Point): number {
return vec1.x * vec2.x + vec1.y * vec2.y;
}
export function getAngle(point: engine.Point) {
let radians = Math.acos(point.x / point.length);
radians = point.y > 0 ? radians : -radians;
return toDegress(radians);
}
/**
* 根据角度创建单位向量
* @param angle 角度制的角度
*/
export function getVector(angle: number) {
angle = toRadians(angle);
return new engine.Point(Math.cos(angle), Math.sin(angle));
}
export function stringOverEllipsis(str: string, limit: number) {
if (str.length > limit) {
return str.substring(0, limit) + "...";
} else {
return str;
}
}
export function getClassName(cls: any) {
return cls["prototype"]["constructor"]["name"];
}
export function getInstanceClassName(instance: any) {
return getClassName(instance["constructor"]);
}
export function setColorFilter(image: engine.DisplayObject, color: number) {
//TODO 颜色滤镜实现
// 将16进制颜色分割成rgb值
/* let spliceColor = (color: number) => {
let result = { r: -1, g: -1, b: -1 };
result.b = color % 256;
result.g = Math.floor((color / 256)) % 256;
result.r = Math.floor((color / 256) / 256);
return result;
}
let result = spliceColor(color);
let colorMatrix = [
1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0
];
colorMatrix[0] = result.r / 255;
colorMatrix[6] = result.g / 255;
colorMatrix[12] = result.b / 255;
let colorFilter = new engine.ColorMatrixFilter(colorMatrix);
image.filters = [colorFilter]; */
}
}
\ No newline at end of file
import GameObject from "./GameObject";
import Physics from "./Physics";
import Game from "./Game";
export default class MoveObjcet extends GameObject {
public physics: Physics = null;
constructor(context?: Game) {
super(context);
this.physics = this.addComponent(Physics);
}
}
\ No newline at end of file
import Pool, { PoolGroup, PoolElement } from "./Pool";
export default class MovieClipMgr {
private static _instance: MovieClipMgr = null;
public static get instance(): MovieClipMgr {
if (!this._instance) {
this._instance = new MovieClipMgr();
}
return this._instance;
}
private movieClipData: { [name: string]: engine.MovieClipData } = {};
private pool = new class extends PoolGroup<PoolMovieClip>{
createPool(key: string) {
return new class extends Pool<PoolMovieClip>{
createElement() {
return MovieClipMgr.instance.create(key);
}
}();
}
}();
public load(name: string): boolean {
if (typeof this.movieClipData[name] == "undefined") {
const data = RES.getRes(name + "_json");
const txtr = RES.getRes(name + "_png");
if (!data || !txtr) {
console.error("can not load clip res:" + name);
return false;
}
this.movieClipData[name] = new engine.MovieClipDataFactory(data, txtr).generateMovieClipData(name);
return true;
} else
return true;
}
public create(name: string) {
if (typeof this.movieClipData[name] == "undefined") {
if (!this.load(name)) {
return null;
}
}
return new PoolMovieClip(this.movieClipData[name]);
}
public get(name: string): PoolMovieClip {
return this.pool.get(name);
}
public recycle(name: string, clip: PoolMovieClip) {
this.pool.recycle(name, clip);
clip.destroy();
}
}
class PoolMovieClip extends engine.MovieClip implements PoolElement {
onElementInit() { }
onElementRecycle() { }
playOnComplete(): Promise<void> {
this.gotoAndPlay(0, 1);
return new Promise<void>(resolve => {
this.once(engine.Event.COMPLETE, resolve, this);
});
}
autoRecyclePlay(name: string) {
this.playOnComplete().then(() => {
MovieClipMgr.instance.recycle(name, this);
});
}
}
\ No newline at end of file
import { NetUtils } from "./NetUtils";
import { ToastPanel } from "./ShootPlanet";
const projectId = NetUtils.getProjectId();
export default class Net {
public static cache: object = {};
/**
*
* @param uri URL
* @param param 参数
* @param onSuccess 返回成功时的回调
* @param onFail 返回失败是的回调 | 是否使用默认失败回调函数
* @param pollingCheck 每次轮询回调
* @param pollingCount 轮询最大次数
*/
public static sendGet(uri: string, param: any, onSuccess: (res: any) => void, onFail?: ((res: any) => any) | boolean, pollingCheck?: (res: any) => boolean, pollingCount?: number) {
this.mSend({
type: "get",
uri: uri,
param: param,
onSuccess: onSuccess,
onFail: onFail,
pollingCheck: pollingCheck,
pollingCount: pollingCount
});
}
/**
*
* @param uri URL
* @param param 参数
* @param onSuccess 返回成功时的回调
* @param onFail 返回失败是的回调 | 是否使用默认失败回调函数
* @param pollingCheck 每次轮询回调
* @param pollingCount 轮询最大次数
*/
public static sendPost(uri: string, param: any, onSuccess: (res: any) => void, onFail?: ((res: any) => any) | boolean, pollingCheck?: (res: any) => boolean, pollingCount?: number) {
this.mSend({
type: "post",
uri: uri,
param: param,
onSuccess: onSuccess,
onFail: onFail,
pollingCheck: pollingCheck,
pollingCount: pollingCount
});
}
private static mSend(net: INetData) {
if (net.pollingCheck) {
//TODO
// Loading.instace.show();
}
window['$'].ajax({
type: net.type,
url: net.uri,
dataType: 'json',
data: net.param,
async: true,
success: (result: any) => {
Net.onResponse(net, result);
},
error: (message: any) => {
Net.onError(net, message);
}
});
console.log("requset", net.uri, net.param);
}
private static onResponse(net: INetData, result: any): void {
//数据处理
if (net.pollingCheck) {
console.log('polling:', result);
}
if (net.pollingCount && net.pollingCheck(result)) { //轮询
net.pollingCount -= 1;
//轮询接口特殊处理
setTimeout(() => {
Net.mSend(net);
}, 500);
} else { //接口成功或失败
if (net.pollingCheck && !net.pollingCount && net.pollingCheck(result)) {
Net.onError(net, result);
} else {
net.onSuccess(result);
}
}
}
private static onError(net: INetData, res: any) {
console.warn("response", net.uri, res);
let errorMsg = res && ((res["desc"] || res["message"]) || ((res["code"] && "network error:" + res["code"]) || "network error")) || "network error";
if (typeof net.onFail == "function") {
if (!net.onFail(res)) { //若客户没有处理错误码,怎么默认显示错误消息或描述文字的弹窗
ToastPanel.show(errorMsg);
}
} else {
if (typeof net.onFail == "boolean" && net.onFail == true) {
Net.defaultOnFail && Net.defaultOnFail(res);
}
ToastPanel.show(errorMsg);
}
}
public static defaultOnFail: (res: any) => void = () => {
//TODO:默认网络异常处理
console.error("defaultOnFail");
}
public static urlReplace() {
for (let i of Object.keys(Net.Url)) {
for (let j of Object.keys(Net.urlReplaceConfig)) {
Net.Url[i] = Net.Url[i].replace(new RegExp(j, "g"), Net.urlReplaceConfig[j]);
}
}
}
private static urlReplaceConfig = {
"{projectId}": projectId
}
public static readonly Url = {
signData: "/projectx/{projectId}/join_1/data.do",
signIn: "/projectx/{projectId}/join_1/join.do",
queryProps: "/projectx/{projectId}/scoring_1/spData.do",
start: "/projectx/{projectId}/scoring_1/start.do",
finalSubmit: "/projectx/{projectId}/scoring_1/submit.do",
revive: "/projectx/{projectId}/scoring_1/revive.do",
constantSubmit: "/projectx/{projectId}/scoring_1/push.do",
rankList: "/projectx/{projectId}/join_2/data.do",
queryRankListData: "/projectx/{projectId}/getRanking.query",
queryNickname: "/projectx/{projectId}/join_3/userInfoList.do",
visit: "/projectx/{projectId}/scoring_1/visit.do",
share: "/projectx/{projectId}/join_2/join.do"
}
}
interface INetData {
type: string,
uri: string,
param: any,
onSuccess: (res: any) => void,
onFail?: ((res: any) => any) | boolean,
pollingCheck?: (res: any) => boolean,
pollingCount?: number
}
\ No newline at end of file
import Net from "./Net";
import { NetManager } from "../../../libs/tw/manager/NetManager";
import { Buried } from "../../../libs/tw/util/Buried";
import { MUtils } from "./MUtils";
import GameMgr from "../Mgr/GameMgr";
export namespace NetUtils {
export function createSgin(ticketId: number, score: number, gameData: any, submitToken: string): string {
return window['duiba_md5'](ticketId + '' + score + '' + gameData + '' + submitToken);
}
export function getOrderId() {
return Net.cache[NetUtils.getCFG()["doJoin"]]["orderId"];
}
export function gameSubmit(params: {
orderId: any,
score: any,
submitToken: any
}, onSuccess: (res: any) => void, onFail?: (res: any) => any) {
let sgin = createSgin(params.orderId, params.score, "[]", params.submitToken);
Net.sendPost('/hdtool/recon/ngame/ngameSubmit', {
orderId: params.orderId,
score: params.score,
gameData: "[]",
sgin: sgin,
dynamicData: JSON.stringify(`{t2:${new Date().getTime()}}`),
rankId: window["rankId"]
}, onSuccess, onFail);
}
export function ajaxElement(onSuccess: (res: any) => void, onFail?: (res: any) => void) {
let cfg = NetUtils.getCFG();
Net.sendPost(cfg["getElement"], {
hdType: cfg["hdType"],
hdToolId: cfg["hdToolId"],
actId: cfg["actId"],
preview: cfg["preview"]
}, onSuccess, onFail);
}
function doBuried(appIdParam: string, netManager: NetManager, callback: string) {
//初始化埋点数据
Buried.init();
var appId = NetUtils.getCFG()["appId"];
var oaId = NetUtils.getCFG()["appId"];
let data = Buried.createExposure(appId + `.110.${appIdParam}.1`, `202.${oaId}.0.0`);
netManager[callback](data);
console.log("exposure", data);
}
export function doClickBuried(appIdParam: string) {
doBuried(appIdParam, NetManager.ins, "clickLog");
}
export function doShowBuried(appIdParam: string) {
doBuried(appIdParam, NetManager.ins, "showLog");
}
export function encryptSeq(seq: number) {
return Math.round(5 * seq - MUtils.random(0, 4));
}
export function md5(str: string) {
return window['duiba_md5'](str);
}
export function getTimestamp() {
return Date.now();
}
export function getCFG(): object {
return window['CFG'];
}
const projectxString = "projectx/";
export function getProjectId(): string {
let windowUrl = window.location.href;
let splitArr = windowUrl.split(projectxString);
if (splitArr.length != 2) {
return "projectId"
}
let start = windowUrl.indexOf(projectxString) + projectxString.length;
let end = splitArr[1].indexOf("/");
return windowUrl.substr(start, end);
}
export function visit() {
return new Promise<any>((resolve, reject) => {
Net.sendGet(Net.Url.visit, undefined, (res) => {
GameMgr.instance.allPeriodEnd = res.data.allPeriodEnd;
GameMgr.instance.leftTimes = res.data.leftTimes;
GameMgr.instance.leftShareTimes = res.data.leftShareTimes;
GameMgr.instance.minEnableCaptchaScore = res.data.minEnableCaptchaScore;
resolve(res);
}, (res) => {
reject(res);
})
});
}
}
\ No newline at end of file
import Pool from "./Pool";
import Bullet from "./Bullet";
import { MConst } from "./MConst";
import PoolMgr from "./PoolMgr";
import GameMgr from "./GameMgr";
import GameObject from "./GameObject";
/* export default class ParticleMgr {
private data: Bullet[] = [];
private layer: engine.Container = null;
constructor(layer: engine.Container) {
this.layer = layer;
}
create(context: MainScene) {
if (this.data.length > 0) {
let e = this.data.pop();
e.onElementInit();
return e;
} else {
let b = new Bullet(context);
this.layer.addChild(b);
return b;
}
}
destroy(bullet: Bullet) {
bullet.onElementRecycle();
this.data.push(bullet);
}
} */
\ No newline at end of file
import Physics from "./Physics";
import Collider, { CircleCollider, RectCollider, ColliderType, ColliderGroup, PointCollider } from "./Collider";
import { arrayRemove } from "./GUtils";
import MTimer from "./MTimer";
let instanceId1: number = null;
let instanceId2: number = null;
export default class PhycicsSystem {
private static _instance: PhycicsSystem = null;
public static get instance(): PhycicsSystem {
if (!this._instance) {
this._instance = new PhycicsSystem();
}
return this._instance;
}
public static init() {
const ins = PhycicsSystem.instance;
engine.gameStage.addEventListener(engine.Event.ENTER_FRAME, ins.onUpdate, ins);
}
private _enabled: boolean = false;
public set enabled(v: boolean) {
this._enabled = v;
if (this._enabled == true)
this.pause = false;
this.clear();
}
public get enabled() {
return this._enabled;
}
public pause: boolean = false;
private phycicsList: Physics[] = [];
private clear() {
for (let i = 0; i <= GroupMaxIndex; i++) {
this.colliderList[i] = [];
}
this.phycicsList = [];
}
private onUpdate() {
if (this.pause) return;
for (let i of PhycicsSystem.instance.phycicsList) {
if (this.enabled == false) return;
i.onFixedUpdate(MTimer.dtFactor);
}
this.detectCollision();
return false;
}
public add(phycics: Physics) {
this.phycicsList.push(phycics);
}
public remove(phycics: Physics) {
this.phycicsList = arrayRemove(this.phycicsList, phycics);
}
private colliderList: Collider[][] = [];
private collisions: number[][] = [];
/**
* 判断两个碰撞器之前是否发生过碰撞
* @returns 未找到返回-1
*/
private getCollisionIndex(collider1: number, collider2: number): number {
for (let i = 0; i < this.collisions.length; i++) {
if ((this.collisions[i][0] == collider1 && this.collisions[i][1] == collider2) || (this.collisions[i][0] == collider2 && this.collisions[i][1] == collider1)) {
return i;
}
}
//未碰撞
return -1;
}
public addCollider(collider: Collider) {
if (typeof this.colliderList[collider.group] == "undefined") {
this.colliderList[collider.group] = [];
}
this.colliderList[collider.group].push(collider);
}
public removeCollider(collider: Collider) {
this.collisions = this.collisions.filter(e => {
if (e[0] != collider.owner.instanceId && e[1] != collider.owner.instanceId) {
return true;
} else
return false;
});
this.colliderList[collider.group] = arrayRemove(this.colliderList[collider.group], collider);
}
/**检测碰撞 */
public detectCollision() {
//查找所有碰撞
let i = 0,
j = 0,
m = 0,
n = 0,
length = this.colliderList.length,
group1: Collider[] = null,
group2: Collider[] = null;
for (i = 0; i <= length - 1; i++) {
for (j = i + 1; j <= length - 1; j++) {
if (CollisionMap[i] & 1 << j) {
if (this.enabled == false) return;
group1 = this.colliderList[i];
group2 = this.colliderList[j];
for (m = 0; m <= group1.length - 1; m++) {
for (n = 0; n <= group2.length - 1; n++) {
// if (this.enabled == false) return;
this.detectTraverse(group1[m], group2[n]);
}
}
}
}
}
}
private detectTraverse(collider1: Collider, collider2: Collider) {
instanceId1 = collider1.owner.instanceId;
instanceId2 = collider2.owner.instanceId;
let collisionIndex = this.getCollisionIndex(instanceId1, instanceId2);
if (callDetectFunc(collider1, collider2)) { //发生碰撞
if (collisionIndex >= 0) { //之前就发生了碰撞
collider1.owner.onCollisionStay(collider2);
collider2.owner.onCollisionStay(collider1);
} else { //之前没有碰撞
//添加到索引表
this.collisions.push([instanceId1, instanceId2]);
collider1.owner.onCollisionEnter(collider2);
collider2.owner.onCollisionEnter(collider1);
}
} else { //未发生碰撞
//碰撞退出
if (collisionIndex >= 0) { //之前有发生碰撞
//在碰撞列表中删除这一对碰撞
this.collisions.splice(collisionIndex, 1);
collider1.owner.onCollisionExit(collider2);
collider2.owner.onCollisionExit(collider1);
}
}
}
}
function callDetectFunc(collider1: Collider, collider2: Collider): boolean {
if (collider1.type == ColliderType.Circle) {
if (collider2.type == ColliderType.Circle) {
return circleToCircle(collider1 as CircleCollider, collider2 as CircleCollider);
} else if (collider2.type == ColliderType.Rect) {
return circleToRect(collider1 as CircleCollider, collider2 as RectCollider);
} else if (collider2.type == ColliderType.Point) {
return circleToPoint(collider1 as CircleCollider, collider2 as PointCollider)
}
} else if (collider1.type == ColliderType.Rect) {
if (collider2.type == ColliderType.Circle) {
return circleToRect(collider2 as CircleCollider, collider1 as RectCollider);
} else if (collider2.type == ColliderType.Rect) {
return rectToRect(collider1 as RectCollider, collider2 as RectCollider);
} else if (collider2.type == ColliderType.Point) {
return pointToRect(collider2 as PointCollider, collider1 as RectCollider);
}
} else if (collider1.type == ColliderType.Point) {
if (collider2.type == ColliderType.Circle) {
return circleToPoint(collider2 as CircleCollider, collider1 as PointCollider);
} else if (collider2.type == ColliderType.Rect) {
return pointToRect(collider1 as PointCollider, collider2 as RectCollider);
}
}
return false;
}
let tempPoint1: number[] = [];
let tempPoint2: number[] = [];
function distance(p1: number[], p2: number[]) {
return Math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]));
}
function circleToCircle(collider1: CircleCollider, collider2: CircleCollider): boolean {
collider1.getWorldPosition(tempPoint1);
collider2.getWorldPosition(tempPoint2);
return distance(tempPoint1, tempPoint2) < (collider1.radius + collider2.radius);
}
function circleToRect(circleCollider: CircleCollider, rectCollider: RectCollider) {
circleCollider.getWorldPosition(tempPoint1);
rectCollider.getWorldPosition(tempPoint2);
let closestPoint = new engine.Point();
if (tempPoint1[1] < tempPoint2[1]) {
closestPoint.y = tempPoint2[1];
} else if (tempPoint1[1] > tempPoint2[1] + rectCollider.rect.height) {
closestPoint.y = tempPoint2[1] + rectCollider.rect.height;
} else {
closestPoint.y = tempPoint1[1];
}
if (tempPoint1[0] < tempPoint2[0]) {
closestPoint.x = tempPoint2[0];
} else if (tempPoint1[0] > tempPoint2[0] + rectCollider.rect.width) {
closestPoint.x = tempPoint2[0] + rectCollider.rect.width;
} else {
closestPoint.x = tempPoint1[0];
}
return distance([closestPoint.x, closestPoint.y], tempPoint1) < circleCollider.radius;
}
function rectToRect(collider1: RectCollider, collider2: RectCollider) {
let rect1 = collider1.rect,
rect2 = collider2.rect;
collider1.getWorldPosition(tempPoint1);
collider2.getWorldPosition(tempPoint2);
let rectW1 = tempPoint1[0] + rect1.width,
rectW2 = tempPoint2[0] + rect2.width,
rectH1 = rect1.height + tempPoint1[1],
rectH2 = tempPoint2[1] + rect2.height;
if (tempPoint1[0] <= rectW2 &&
rectW1 >= tempPoint2[0] &&
tempPoint1[1] <= rectH2 &&
rectH1 >= tempPoint2[1]) { //发生碰撞
return true;
} else
return false;
}
function circleToPoint(circle: CircleCollider, point: PointCollider) {
circle.getWorldPosition(tempPoint1);
point.getWorldPosition(tempPoint2);
if (distance(tempPoint1, tempPoint2) < circle.radius) {
return true;
} else {
return false;
}
}
function pointToRect(point: PointCollider, rect: RectCollider) {
rect.getWorldPosition(tempPoint1);
point.getWorldPosition(tempPoint2);
if (tempPoint2[1] < tempPoint1[1] + rect.rect.height
&& tempPoint2[1] > tempPoint1[1]
&& tempPoint2[0] > tempPoint1[0]
&& tempPoint2[0] < tempPoint1[0] + rect.rect.width
) {
return true;
} else {
return false;
}
}
const CollisionMap = {
0: 0b00000000,
1: 0b01011100,
2: 0b10000010,
3: 0b01100010,
4: 0b00100010,
5: 0b01011000,
6: 0b00101010,
7: 0b00000010
}
const GroupMaxIndex = 7
\ No newline at end of file
import GameComponent from "./GameComponent";
import GameObject from "./GameObject";
import PhycicsSystem from "./PhycicsSystem";
import Collider from "./Collider";
export default class Physics extends GameComponent {
/**旋转速度
* @单位 (弧度制)度/帧
* @方向 正值表示顺时针旋转,负表示逆时针旋转
**/
public rotateVelocity: number = 0;
/**每帧速率的增量
* x坐标表示对应坐标轴方向上速率的增量(标量)
* @单位 像素/帧
**/
public acceleration: engine.Point = new engine.Point();
/**速度 单位:像素/帧 */
public velocity: engine.Point = new engine.Point();
public get collider() {
return this._collider;
}
public set collider(v: Collider) {
this._collider = v;
v.physics = this;
}
public _collider: Collider = null;
public onFixedUpdate(dtFactor: number) {
this.velocity.x += this.acceleration.x * dtFactor;
this.velocity.y += this.acceleration.y * dtFactor;
if (this.velocity.length > 0) {
this.moveTo(
this.owner.x += this.velocity.x * dtFactor,
this.owner.y += this.velocity.y * dtFactor
);
}
//旋转
if (this.rotateVelocity != 0) {
this.owner.rotation += this.rotateVelocity * dtFactor;
}
}
public moveTo(x: number | engine.Point, y?: number) {
if (typeof x == "number") {
if (!y) {
console.error("invalid param");
return;
}
this.owner.x = x;
this.owner.y = y;
} else {
this.owner.x = x.x;
this.owner.y = x.y;
}
this.onMoved && this.onMoved(this.owner);
}
public onMoved: (owner: GameObject) => void;
protected onDisabled() {
PhycicsSystem.instance.remove(this);
}
protected onEnabled() {
PhycicsSystem.instance.add(this);
}
public onColliderResize(collider: Collider) {
let center = collider.getCenter();
this.owner.anchorX = center[0];
this.owner.anchorY = center[1];
}
}
\ No newline at end of file
export default class PlayerController extends engine.Container {
public onTouchMove: (deltaX: number) => void = null;
private touchId: number = null;
private lastX: number = null;
constructor() {
super();
this.width = engine.gameStage.width;
this.height = engine.gameStage.height;
this.addEventListener(engine.MouseEvent.MOUSE_DOWN, (e: engine.MouseEvent) => {
this.touchId = e.instanceId;
this.lastX = e.stageX;
}, this);
this.addEventListener(engine.MouseEvent.MOUSE_MOVE, (e: engine.MouseEvent) => {
if (e.instanceId != this.touchId || this.touchId == null || this.lastX == null) return;
this.onTouchMove && this.onTouchMove(e.stageX - this.lastX)
this.lastX = e.stageX;
}, this);
this.removeEventListener(engine.MouseEvent.MOUSE_UP, (e: engine.MouseEvent) => {
if (e.instanceId != this.touchId) return;
this.touchId = null;
this.lastX = null;
}, this);
}
}
\ No newline at end of file
import { MUtils } from "./MUtils";
import MTweenMgr from "./MTween";
export default abstract class Pool<T extends PoolElement>{
private data: T[] = [];
public get(...args: any[]): T {
if (this.data.length > 0) {
let e = this.data.pop();
e.onElementInit();
return e;
} else {
return this.createElement(...args);
}
}
public recycle(element: T) {
MTweenMgr.instance.removeTweens(element);
element.onElementRecycle();
for (let i of this.data) {
if (i === element) return;
}
this.data.push(element);
}
protected abstract createElement(...args: any[]): T;
}
export abstract class PoolGroup<T extends PoolElement>{
private data: {
[key: string]: Pool<T>
} = {};
public get(key: string): T {
return this.getValue(key).get();
}
public recycle(key: string, element: T) {
this.getValue(key).recycle(element);
}
private getValue(key: string) {
this.data[key] = this.data[key] || this.createPool(key);
return this.data[key];
}
protected abstract createPool(key: string): Pool<T>;
}
export interface PoolElement {
/**回收元素时的调用 */
onElementRecycle(): void;
onElementInit(): void;
}
\ No newline at end of file
import Pool, { PoolElement } from "./Pool";
import GameObject from "./GameObject";
export default abstract class PoolMgr<T extends PoolElement & engine.Container>{
protected layer: engine.Container = null;
private pool: Pool<T> = new class extends Pool<T>{
private context: PoolMgr<T> = null;
constructor(context: PoolMgr<T>) {
super();
this.context = context;
}
createElement(...args: any[]) {
return this.context.createElement(args);
}
}(this);
constructor(layer: engine.Container) {
this.layer = layer;
}
create(...args: any[]): T {
let element = this.pool.get(...args);
this.layer.addChild(element);
return element;
}
destroy(element: T) {
this.pool.recycle(element);
}
abstract createElement(...args: any[]): T;
}
\ No newline at end of file
/**
* Created by rockyl on 2019-11-22.
*/
export class ShootPlanet extends engine.Container {
constructor() {
super();
this.init();
let rect = new engine.Rect();
rect.width = 100;
rect.height = 100;
this.addChild(rect);
}
private init() {
RES.getRes = function (uuid: string) {
return engine.Texture.from(uuid);
}
Math.clamp = function (target: number, min: number, max: number) {
if (target > max) target = max;
if (target < min) target = min;
return target;
}
Object.defineProperty(engine.Point, 'length', {
get: function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
});
}
}
export class ToastPanel {
public static show(msg: string) {
console.log("toast:" + msg);
}
}
import MTimer from "./MTimer";
export default class SoundMgr {
private static _instance: SoundMgr = null;
public static get instance(): SoundMgr {
if (!this._instance) {
this._instance = new SoundMgr();
}
return this._instance;
}
public effectEnabled = false;
private _enabled: boolean = false;
public set enabled(v: boolean) {
this.musicEnabled = v;
this.effectEnabled = v;
this._enabled = v;
}
public get enabled() {
return this._enabled;
}
private _musicEnabled: boolean = false;
public get musicEnabled() {
return this._musicEnabled;
}
public set musicEnabled(v: boolean) {
if (v == true) {
this.playMusic();
} else {
this.stopMusic();
}
this._musicEnabled = v;
}
private music: engine. = null;
private musicChannel: engine.SoundChannel = null;
private loopChannelMap: { [name: string]: engine.SoundChannel } = {}
private effectPool: { [name: string]: PoolSound[] } = {}
public firstSeted = false;
public setMusic(url: string) {
this.music = RES.getRes(url);
/* if (this.musicChannel) {
this.playMusic();
} */
}
public playMusic() {
if (this.music == null) {
console.warn("music do not set");
return;
}
this.musicChannel && this.musicChannel.stop();
this.musicChannel = this.music.play(0, 0);
}
public stopMusic() {
this.musicChannel && (this.musicChannel.stop());
}
public playEffect(name: string, loop: boolean = false) {
if (!this.effectEnabled) return;
let poolSound = this.createSound(name, loop);
let channel = poolSound.sound.play(0, loop ? 0 : 1);
if (loop) {
if (this.loopChannelMap[name]) {
this.loopChannelMap[name].stop();
}
this.loopChannelMap[name] = channel;
} else {
return new Promise<void>(resolve => {
channel.addEventListener(engine.Event.SOUND_COMPLETE, () => {
this.recycleSound(poolSound);
resolve();
}, this);
});
}
}
public stopLoopEffect(name: string) {
if (this.loopChannelMap[name]) {
this.loopChannelMap[name].stop();
}
}
private t: number = 0;
private createSound(name: string, loop: boolean): PoolSound {
let soundList = this.effectPool[name];
if (!soundList || soundList.length <= 0) {
let poolSound = new PoolSound(name, RES.getRes(name), loop);
if (poolSound.name == "shoot_mp3") {
this.t++;
}
return poolSound;
} else {
return soundList.pop();
}
}
private recycleSound(poolSound: PoolSound) {
delete this.loopChannelMap[poolSound.name];
this.effectPool[poolSound.name] = this.effectPool[poolSound.name] || [];
this.effectPool[poolSound.name].push(poolSound);
}
}
class PoolSound {
private loop = false;
public onRecycle = (sound: PoolSound) => { }
public sound: engine.Sound = null;
public name: string = null;
constructor(name: string, sound: engine.Sound, loop: boolean) {
this.name = name;
this.sound = sound;
this.loop = loop;
}
}
\ No newline at end of file
/**
* Created by rockyl on 2019-11-20.
*/
import { ShootPlanet } from "./ShootPlanet";
export default function (options) {
let instance = new ShootPlanet();
return instance;
}
{
"name": "Test1",
"props": {
},
"assets": [
{
"url": "//yun.duiba.com.cn/aurora/af90069732223c75818c4799b3130bd0f0ad4ff8.png",
"ext": ".png"
}
]
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment