Commit b5a62234 authored by zhangjinzhou's avatar zhangjinzhou

打星球调整

parent 22fc6f6c
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* Created by rockyl on 2019-12-16.
*/
const customId = 'rbcxbingqiu';
(async function () {
let customModule = await fetch(`../meta.json`);
customModule = await customModule.json();
console.log(customModule);
await loadAssets(customModule.assets);
launchWithCustomModule(customModule);
})();
function launchWithCustomModule(customModule) {
//engine.registerCustomCodeModule(customModule);
engine.registerCustomModule(customId, window[customId]);
const {props: propsOption, assets} = customModule;
let props = engine.computeProps(customModuleProps, propsOption);
const customModuleIns = {
id: customId,
props,
assets,
};
engine.registerCustomModules([customModuleIns]);
engine.launchWithConfig({
options: {
entrySceneView: 'entry',
},
assets: [],
views: [{
name: 'entry',
type: 'node',
}],
}, null, function () {
setTimeout(() => {
engine.addCustomModule(customId, engine.gameStage.sceneContainer.getChildAt(0));
}, 100);
setTimeout(() => {
engine.globalEvent.dispatchEvent('game-create', {
});
}, 500);
setTimeout(() => {
engine.globalEvent.dispatchEvent('game-start', {
guide:true
});
}, 510);
engine.globalEvent.addEventListener('game-start', (e) => {
console.log(e.type, e.data);
});
});
}
function getAssetByUUID(uuid) {
return engine.resolveCustomAsset(customId, uuid);
}
function getProps() {
return engine.getProps(customId);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>打星球</title>
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="full-screen" content="true"/>
<meta name="screen-orientation" content="portrait"/>
<meta name="x5-fullscreen" content="true"/>
<meta name="360-fullscreen" content="true"/>
<style>
html,
body {
padding: 0;
margin: 0;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
background-color: transparent;
}
</style>
</head>
<body>
<div id="game-container" style="line-height:0;font-size:0"></div>
<script crossorigin="anonymous" src="//yun.duiba.com.cn/editor/zeroing/libs/engine.50cdcef6ebe4e8c0fbc624f9d4fbf225102c5750.js"></script>
<script crossorigin="anonymous" src="//yun.duiba.com.cn/editor/zeroing/libs/svga.fd3923ae6e664251ca7981801a65809cc5f36bc3.js"></script>
<!-- <script src="http://localhost:4002/debug/engine.js"></script>
<script src="http://localhost:4003/debug/engine-svga.js"></script> -->
<!--<script src="//yun.duiba.com.cn/editor/zeroing/libs/engine.9a9dbfda4cb2dd5508ecddfe3d95dfd88063f7b5.js"></script>-->
<script src="app.js"></script>
<script src="props.js"></script>
<script src="load-assets.js"></script>
<script src="main.js"></script>
<script>
</script>
</body>
\ No newline at end of file
/**
* Created by rockyl on 2020-01-21.
*/
const assets = [
{
"name": "橘色转盘",
"url": "//yun.duiba.com.cn/aurora/assets/5bdcac217a30d87361b2fb86378f60bf1d8cea7b.png",
"uuid": "b6ed99bc-2da1-4e6d-840e-54371be041aa",
"ext": '.png'
},
];
function loadAssets(customModuleAssets, onProgress, onComplete){
return engine.loadAssets(assets.concat(...customModuleAssets), onProgress, onComplete);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* Created by rockyl on 2020-01-21.
*/
let customModuleProps = {
};
{
"name": "打星球",
"desc": "打星球模块哟",
"props": {
"guideText0": {
"alias": "引导文本0",
"type": "string",
"default": "左右移动炮车进行射击和躲避"
},
"guideText1": {
"alias": "引导文本1",
"type": "string",
"default": "拾取金币可获得更多的炮弹输出和得分加成"
},
"guideFlagKey": {
"alias": "引导标识名",
"type": "string",
"default": "test"
},
"fontName": {
"alias": "字体名",
"type": "string",
"default": "shoot-planet-num",
"desc": "球体上所用位图文本的字体"
},
"carCollidePaddingX": {
"alias": "小车碰撞横向边距",
"type": "number",
"default": 55
},
"carCollidePaddingY": {
"alias": "小车碰撞纵向边距",
"type": "number",
"default": 5
}
},
"events": {
"in": {
"game-create": {
"alias": "初始化游戏"
},
"game-destroy": {
"alias": "销毁游戏"
},
"game-pause": {
"alias": "暂停游戏"
},
"game-resume": {
"alias": "恢复游戏"
},
"game-revive": {
"alias": "复活"
}
},
"out": {
"game-start": {
"alias": "游戏开始"
},
"game-update": {
"alias": "游戏更新",
"data": {
"score": "分数",
"bulletScore":"子弹分数",
"powerScore": "火力分数"
}
},
"game-over": {
"alias": "游戏结束",
"data": {
"score": "分数",
"bulletScore":"子弹分数",
"powerScore": "火力分数"
}
}
}
},
"assets": [
{
"name": "背景图",
"url": "//yun.duiba.com.cn/aurora/assets/73490e5f8f5d606d050cb3e539e391461f58e60c.jpg",
"uuid": "d99368b8-af5d-4d9e-981e-7bce3e1c1e84",
"ext": ".jpg"
},
{
"name": "车身",
"url": "//yun.duiba.com.cn/aurora/assets/62293c514c0b1ea5f3a7adc222e282028da1daec.png",
"uuid": "ddf5128e-be66-4c00-8505-e4167aac37bc",
"ext": ".png"
},
{
"name": "轮子",
"url": "//yun.duiba.com.cn/aurora/assets/9a9dfe818fd24bac74d03ac012fcf4f535f1bbb4.png",
"uuid": "12729a51-65bd-4e5a-9829-7d6d794e76e8",
"ext": ".png"
},
{
"name": "炮口烟雾",
"url": "//yun.duiba.com.cn/aurora/assets/c768cb730b8cbf57c40274fb1702379ee7e8367b.png",
"uuid": "d8daa113-0d75-4139-9e81-c54b7522c890",
"ext": ".png"
},
{
"name": "星球图0",
"url": "//yun.duiba.com.cn/aurora/assets/0de6101f96b0655c5b32c8647869faf10e57fc3d.png",
"uuid": "39843f75-8caa-4cee-bff5-91fb759b691b",
"ext": ".png"
},
{
"name": "星球图1",
"url": "//yun.duiba.com.cn/aurora/assets/360da650d34af0e9928ebf784446281d67260d9e.png",
"uuid": "bd94b3e6-3c99-490f-95ef-ca0c056d7727",
"ext": ".png"
},
{
"name": "星球图2",
"url": "//yun.duiba.com.cn/aurora/assets/0de6101f96b0655c5b32c8647869faf10e57fc3d.png",
"uuid": "d8eab9fc-104e-4b39-88d6-455ed8632703",
"ext": ".png"
},
{
"name": "星球图3",
"url": "//yun.duiba.com.cn/aurora/assets/eb9d1952db92ee371d1dd898aa7c07b6f3fe27e8.png",
"uuid": "48f98d84-d30e-4dfe-aa92-c45bde5cefd8",
"ext": ".png"
},
{
"name": "星球图4",
"url": "//yun.duiba.com.cn/aurora/assets/9fbb59b246f9e6ea521068144ec5004afa78ae37.png",
"uuid": "8d42fd9e-907b-4587-9a6f-a634909b8b8a",
"ext": ".png"
},
{
"name": "子弹",
"url": "//yun.duiba.com.cn/aurora/assets/cba178077d7850e7ecdc8d413bc14ff1b6131753.png",
"uuid": "09bdff41-2fe3-4298-ad3a-1d2eaf6af778",
"ext": ".png"
},
{
"name": "色环0",
"url": "//yun.duiba.com.cn/aurora/assets/b496f6d0a7c0592910f8e401fec85132846791d4.png",
"uuid": "64e64fd6-0426-493e-b003-dcafc7e06eb5",
"ext": ".png"
},
{
"name": "色环1",
"url": "//yun.duiba.com.cn/aurora/assets/69b2f45bc53b8cf619516dc003142ea53a231650.png",
"uuid": "15c46813-ac79-4c5f-8a52-e8cded6dadff",
"ext": ".png"
},
{
"name": "色环2",
"url": "//yun.duiba.com.cn/aurora/assets/ba722374a8d157b8c8d383c7fcab67ae13f3a7cc.png",
"uuid": "49092176-3b1c-4ea5-8e02-6050fc5809dd",
"ext": ".png"
},
{
"name": "色环3",
"url": "//yun.duiba.com.cn/aurora/assets/8a9ed6505d18483361890f0f5a843824fb4a3457.png",
"uuid": "134e2eec-e393-4ba3-b8cc-f72270bf17c2",
"ext": ".png"
},
{
"name": "色环4",
"url": "//yun.duiba.com.cn/aurora/assets/d6391cb9b2d00689bb510137796e8731ea98634e.png",
"uuid": "b3c78176-5650-4d49-bc00-cfaf048c5940",
"ext": ".png"
},
{
"name": "星星0",
"url": "//yun.duiba.com.cn/aurora/assets/579d259f801eaa795ead6fe4d51ea3c767e6f392.png",
"uuid": "2aaa2535-d4b9-44c4-8fc2-700c8310e534",
"ext": ".png"
},
{
"name": "星星1",
"url": "//yun.duiba.com.cn/aurora/assets/42bc95fc3d175e621e48fb18294e0b2aa0448089.png",
"uuid": "c5743fdf-aadf-4139-b03a-cfd047f85220",
"ext": ".png"
},
{
"name": "星星2",
"url": " //yun.duiba.com.cn/aurora/assets/afff371d4452f4e857b282a25828ed3f500fa849.png",
"uuid": "999d65ba-f7c8-4939-9868-5f974a278752",
"ext": ".png"
},
{
"name": "星星3",
"url": "//yun.duiba.com.cn/aurora/assets/2bbe18fa5bb36cc585eae9a09266045e2e7c7d2e.png",
"uuid": "1a1b529f-bf68-42cb-8a3e-01b21119b322",
"ext": ".png"
},
{
"name": "星星4",
"url": "//yun.duiba.com.cn/aurora/assets/3f62afe9aeace2a22926f95e6852ab995d4d3ff8.png",
"uuid": "e79f4e51-dbca-45fb-b95a-f52a708e0990",
"ext": ".png"
},
{
"name": "掉落金币0",
"url": "//yun.duiba.com.cn/aurora/assets/d78ae1cdf7b1ec97d0ced03d951ac1cc0d470303.png",
"uuid": "f7221f86-f376-40ce-b0e8-f7ea573ec780",
"ext": ".png"
},
{
"name": "掉落金币1",
"url": "//yun.duiba.com.cn/aurora/assets/c1ead1db79f52451d56cee78a5a082b1843723ab.png",
"uuid": "c9dbd728-1844-4910-b1ef-e84ce10dc422",
"ext": ".png"
},
{
"name": "掉落金币2",
"url": "//yun.duiba.com.cn/aurora/assets/c9f54a0d8e101b21678c56dcd8aea138b7d32240.png",
"uuid": "41182131-7050-4b95-9dce-45275b70738d",
"ext": ".png"
},
{
"name": "掉落金币3",
"url": "//yun.duiba.com.cn/aurora/assets/31a53bf1acc00b0eef773044d684391106f55b5b.png",
"uuid": "17d8e000-b290-4972-bcab-cb819a6cf51b",
"ext": ".png"
},
{
"name": "掉落金币4",
"url": "//yun.duiba.com.cn/aurora/assets/55f1745d1f11585b7b4926a70123279c623235d6.png",
"uuid": "3f7faebf-64da-44a4-8152-0c35fcc29fe5",
"ext": ".png"
},
{
"name": "弹动动画配置",
"url": "//yun.duiba.com.cn/aurora/assets/8c3dd17a4e69adf2ec9a9a15bf04ad620e215989.json",
"uuid": "763d2430-ad16-42c6-8bf0-d7337b05b247",
"ext": ".json"
},
{
"name": "弹动动画图",
"url": "//yun.duiba.com.cn/aurora/assets/146264ea11a3cbb28b6d22b3ee19e98c71fe9273.png",
"uuid": "217164f4-a185-429c-8706-818137a4e438",
"ext": ".png"
},
{
"name": "爆炸动画配置",
"url": "//yun.duiba.com.cn/aurora/assets/14b65a55a4e7f54019a27b59c764c9cf23384062.json",
"uuid": "b82d6a84-8423-4be2-add5-ed9129e8c700",
"ext": ".json"
},
{
"name": "爆炸动画图",
"url": "//yun.duiba.com.cn/aurora/assets/5fd194c102e8612cd39ce6001347b38b2d0c8a92.png",
"uuid": "53c65221-3fbc-41d9-8cef-8a846876fe06",
"ext": ".png"
},
{
"name": "烟花0线条0",
"url": "//yun.duiba.com.cn/aurora/assets/a50ab9c665f406c9b871fbc253c571b19800c949.png",
"uuid": "c76f6d87-7f84-45ed-a9ac-cf8d4dd47026",
"ext": ".png"
},
{
"name": "烟花0线条1",
"url": "//yun.duiba.com.cn/aurora/assets/9ffe79cc377c2e76744f1794c1d6f3c3539bb25e.png",
"uuid": "1fc4fb96-73b7-4250-8886-3c6976eb1139",
"ext": ".png"
},
{
"name": "烟花0线条2",
"url": "//yun.duiba.com.cn/aurora/assets/79e8a046f640c98fd449cec18bbefb12e7684235.png",
"uuid": "65be7718-f6cd-44d9-89d0-5daf81068316",
"ext": ".png"
},
{
"name": "烟花1线条0",
"url": "//yun.duiba.com.cn/aurora/assets/704c371640166a3400d99e9eb8b56f64a3da7683.png",
"uuid": "10901339-4976-4d38-a3b9-47b7e9025144",
"ext": ".png"
},
{
"name": "烟花1线条0",
"url": "//yun.duiba.com.cn/aurora/assets/9c8d28ad86b02f9250f395ddfabfbc587e0bc4cf.png",
"uuid": "0692b423-6f14-4ba7-884a-7c177f1583c8",
"ext": ".png"
},
{
"name": "烟花1线条0",
"url": "//yun.duiba.com.cn/aurora/assets/dd5a9c4b4cb94bd0049890c0aad320ec539a7e16.png",
"uuid": "2ddd9477-12de-4f13-bb35-5b255f1624bd",
"ext": ".png"
},
{
"name": "引导箭头",
"url": "//yun.duiba.com.cn/aurora/assets/905239e8db76682f47339668e7d9279b2ec4f0e2.png",
"uuid": "93992a62-e3c4-46d5-99f4-f7ba35fe4f4f",
"ext": ".png"
},
{
"name": "引导遮罩图",
"url": "//yun.duiba.com.cn/aurora/assets/27a2114a58406d13df48dfd20fd548a0cf9e964b.png",
"uuid": "3cc0aa86-0581-4caa-b662-266e58fd39b7",
"ext": ".png"
},
{
"name": "新引导遮罩图",
"url": "//yun.duiba.com.cn/aurora/assets/d7ee289610fd8c0c22bd113fc74a962db8ba6e0e.png",
"uuid": "d268f82e-d1b9-44c6-b40f-4a08e11aab75",
"ext": ".png"
},
{
"name": "子弹发射音效",
"url": "//yun.duiba.com.cn/aurora/assets/78d86205f37e736f922bf476a4b278dd4c5d029c.mp3",
"uuid": "b01dc39a-2886-4887-b3bb-0f8c801003a9",
"ext": ".mp3"
},
{
"name": "金币收集音效",
"url": "//yun.duiba.com.cn/aurora/assets/564b39022bfe147f9eb4bdf6a6b95142186df265.mp3",
"uuid": "7004616a-0aba-4826-9245-895e7fdf8d31",
"ext": ".mp3"
},
{
"name": "球撞击音效",
"url": "//yun.duiba.com.cn/aurora/assets/f259780c1de05136d15c0aa4b5a72b91ff871f16.mp3",
"uuid": "7fc04e43-1465-4336-92a3-d6039ee88cb3",
"ext": ".mp3"
},
{
"name": "球爆炸音效",
"url": "//yun.duiba.com.cn/aurora/assets/ed6f41a38d28e03acf791dd3672c0364e6754821.mp3",
"uuid": "ca6b799f-be85-4e94-99df-812f31801490",
"ext": ".mp3"
}
]
}
\ No newline at end of file
import GameMgr from "../Mgr/GameMgr";
import { DataMgr } from "../Mgr/DataMgr";
import {getTexture} from "../utils";
/* type AltaData = {
key: string,
frameRate: number,
frames: {
x: number, //x,y,w,h为图集上的切图位置数据
y: number,
w: number,
h: number
}[]
} */
interface Frame {
x: number,
y: number,
texture: engine.Texture
}
export class FrameAnimationMgr extends GameMgr {
constructor() { super("FrameAnimationMgr") }
public playingAnimations: FrameAnimation[] = [];
protected onUpdate() {
if (this.pause) return;
const filters: FrameAnimation[] = [];
let anim: FrameAnimation = null;
for (let i = 0; i < this.playingAnimations.length; i++) {
anim = this.playingAnimations[i];
anim.onUpdate();
if (anim.curPos >= anim.frameCount) {
anim.onCompleted && anim.onCompleted();
} else {
filters.push(anim);
}
}
this.playingAnimations = filters;
}
}
export default class FrameAnimation extends engine.Container {
private frames: Frame[] = [];
public frameCount: number = 0;
public curPos: number = 0;
private frameTimer: number = 0;
private frameRate: number = 60;
private sprite: engine.Sprite = new engine.Sprite;
private static caches: {
[key: string]: {
frameCount: number,
frameRate: number,
frames: Frame[]
}
} = {};
public static loadRes(texture: engine.Texture, egretData: any) {
let name: string = null;
const mc = egretData.mc;
for (let key in mc) { name = key; break; }
if (!FrameAnimation.caches[name]) {
let altaData = {};
for (let i in egretData.res) {
altaData[name + "_" + i] = egretData.res[i];
}
engine.createTextureSheet(texture.baseTexture, altaData);
let frames: Frame[] = [];
const framesData = mc[name].frames;
for (let i in framesData) {
frames[i] = {
x: framesData[i].x,
y: framesData[i].y,
texture: getTexture(name + "_" + framesData[i].res)
}
}
FrameAnimation.caches[name] = {
frameRate: mc[name].frameRate,
frameCount: Object.keys(altaData).length,
frames: frames
}
}
}
constructor(key: string) {
super();
if (!FrameAnimation.caches[key]) {
console.error("unloaded animation:" + key);
return;
}
this.frames = FrameAnimation.caches[key].frames;
this.frameCount = Object.keys(this.frames).length;
this.frameRate = FrameAnimation.caches[key].frameRate;
this.addChild(this.sprite);
}
onUpdate() {
if (this.frameTimer >= 60 / this.frameRate) {
if (this.curPos >= this.frameCount) {
return;
} else {
const frameData = this.frames[this.curPos];
this.sprite.texture = frameData.texture;
this.sprite.x = frameData.x;
this.sprite.y = frameData.y;
}
this.curPos++;
this.frameTimer = 0;
} else {
this.frameTimer++;
}
}
play() {
DataMgr.game._animationMgr.playingAnimations.push(this);
}
onCompleted: () => void;
}
\ No newline at end of file
interface MEventData<T> {
callback: T,
thisObj: any,
bindFunc?: any
}
export default class MEvent<T extends Function>{
private list: MEventData<T>[] = [];
private isTraversing = false;
private deleteList: MEventData<T>[] = [];
public add(callback: T, thisObj?: any) {
this.list.push({
callback: callback,
thisObj: thisObj,
bindFunc: thisObj ? callback.bind(thisObj) : undefined
});
}
public clear() {
if (this.isTraversing) {
this.deleteList.concat(this.list);
} else {
this.list = [];
}
}
public remove(callback: T, thisObj?: any) {
if (this.isTraversing) {
this.deleteList.push({
callback: callback,
thisObj: thisObj
});
} else {
this.list = this.list.filter(e => e.callback !== callback || e.thisObj !== thisObj);
}
}
public call(...args: any[]) {
this.isTraversing = true;
let item: MEventData<T> = null;
for (let i = 0; i < this.list.length; i++) {
item = this.list[i];
if (item.bindFunc) {
item.bindFunc(...args);
} else {
item.callback(...args);
}
}
for (let i = 0; i < this.deleteList.length; i++) {
this.list = this.list.filter(e => e.callback !== this.deleteList[i].callback || e.thisObj !== this.deleteList[i].thisObj);
}
this.deleteList = [];
this.isTraversing = false;
}
}
\ No newline at end of file
export abstract class PoolGroup<T extends PoolElement>{
constructor(protected layer: engine.Container) { }
protected data: { [key: string]: Pool<T> } = {}
public recycle(key: string, element: T) {
this.data[key].recycle(element);
}
public abstract spwan(...args: any[]): T;
}
export abstract class Pool<T extends PoolElement>{
constructor(protected layer: engine.Container) { }
protected data: T[] = [];
public recycle(element: T) {
element.onElementRecycle();
this.data.push(element);
}
public abstract spwan(...args: any[]): T;
}
export interface PoolElement {
/**回收元素时的调用 */
onElementRecycle(): void;
onElementInit(): void;
poolKey?: string;
}
\ No newline at end of file
import { MConst } from "../Global/MConst";
export default class UILayer extends engine.Container {
constructor() {
super();
this.width = MConst.DesignResolution.width;
this.height = MConst.DesignResolution.height;
}
}
\ No newline at end of file
import MoveObjcet from "./MoveObject";
import Collider, {CircleCollider, ColliderGroup} from "../Phycics/Collider";
import {MConfigs} from "../Global/MConfigs";
import {getBallScore, getProp} from "../Global/GUtils";
import {PoolElement} from "../Component/Pool";
import {MConst} from "../Global/MConst";
import Drop from "./Drop";
import Bullet from "./Bullet";
import {MUtils} from "../Global/MUtils";
import SoundMgr from "../Mgr/SoundMgr";
import {DataMgr} from "../Mgr/DataMgr";
import GuideMgr from "../Mgr/GuideMgr";
import MTimer from "../Global/MTimer";
import {getTexture} from "../utils";
import {props} from "../../props";
let tempPower: number = null;
let tempIndexOffset: number = null;
const imageNames = [
"39843f75-8caa-4cee-bff5-91fb759b691b",
"bd94b3e6-3c99-490f-95ef-ca0c056d7727",
"d8eab9fc-104e-4b39-88d6-455ed8632703",
"48f98d84-d30e-4dfe-aa92-c45bde5cefd8",
"8d42fd9e-907b-4587-9a6f-a634909b8b8a",
];
const textureSize = {
width: 210,
height: 213
};
export default class Ball extends MoveObjcet implements PoolElement {
private colorIndex = 0;
private sizeIndex = 0;
private bitmap: engine.Sprite = null;
public static textures: engine.Texture[] = [];
// private labelScore: engine.BitmapText = null;
private labelScore:engine.Label = null;
// private labelScoreShadow: engine.Label = null;
private scaleRatio: number = 1;
private initScore: number = null;
private initColorIndex: number = 0;
public collider: CircleCollider = null;
private isBornStage = false;
public poolKey: string = null;
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 static ballTextures: engine.Texture[] = [];
/* public static loadTextures() {
for (let i in imageNames) {
Ball.ballTextures[i] = getTexture(imageNames[i]);
}
} */
private onScoreIsZero() {
if (GuideMgr.instance.guideFlag == true) {
this.drop();
} else {
if (this.sizeIndex > 0) {
this.split();
} else {
this.drop();
}
}
DataMgr.game._playBoomEffect(this.position, this.scaleRatio);
SoundMgr.instance.playEffect("boom");
DataMgr.game._pool.ball.recycle(this.poolKey, this);
}
constructor(sizeIndex: number) {
super();
//获取配置
let scaleRatio = MConfigs.size[sizeIndex]; //整体缩放系数
//创建图像
const bitmapWidth = textureSize.width * scaleRatio;
const bitmapHeight = textureSize.height * scaleRatio;
this.bitmap = new engine.Sprite();
this.addChild(this.bitmap);
this.bitmap.width = bitmapWidth;
this.bitmap.height = bitmapHeight;
this.anchorX = bitmapWidth / 2;
this.anchorY = bitmapHeight / 2;
this.bitmap.x = -bitmapWidth / 2;
this.bitmap.y = -bitmapHeight / 2;
//创建文字
// let labelScore = new engine.BitmapText();
// labelScore.font = props.fontName;
// labelScore.scaleX = labelScore.scaleY = scaleRatio;
// this.addChild(labelScore);
let labelScore = new engine.Label();
// labelScore.font = props.fontName;
labelScore.size = 55;
labelScore.bold = true;
labelScore.scaleX = labelScore.scaleY = scaleRatio;
this.addChild(labelScore);
//添加碰撞器
let collider = this.addComponent(CircleCollider) as CircleCollider;
collider.group = ColliderGroup.Ball;
this.collider = collider;
collider.setData(0, 0, bitmapHeight / 2);
//初始化属性
this.scaleRatio = scaleRatio;
this.sizeIndex = sizeIndex;
this.labelScore = labelScore;
}
init(colorIndex: number, direction: 1 | -1, score: number): Ball {
this.colorIndex = colorIndex;
this.initColorIndex = colorIndex;
// console.log("替换球tex",colorIndex);
this.bitmap.texture = getTexture(imageNames[colorIndex]);
this.initScore = score;
this.score = score;
this.physics.rotateVelocity = direction * MConst.BallRotateSpeed * Math.pow(1 / this.scaleRatio, 0.5);
let color:string;
if(this.colorIndex==0||this.colorIndex==2||this.colorIndex==4){//黑色
color = "rgba(0,0,0,1)";
}else{//白色
color = "rgba(255,255,255,1)";
}
this.labelScore.fillColor = color;
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.width + 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.width - 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 (other.group == ColliderGroup.Bullet) {
tempPower = (other.owner as Bullet).power;
this.score = this.score - tempPower;
DataMgr.game._score += tempPower;
}
if (other.group == ColliderGroup.Ground) {
this.physics.velocity.y = -(MConst.BallVelocityY * (1 + ((1 / this.scaleRatio) - 1) * MUtils.random(0, MConst.BallVelocityYRandomFactor)));
//播放灰尘动画
const clip = DataMgr.game._createAnimation("duang");
clip.x = this.x - 140 * this.scaleRatio;
clip.y = this.y - 50 * this.scaleRatio;
clip.scaleX = clip.scaleY = this.scaleRatio;
clip.play();
//判断是否会震动地面
if (this.sizeIndex >= MConfigs.size.length - 2) {
DataMgr.game._shake();
SoundMgr.instance.playEffect("dong");
}
}
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 = DataMgr.game._pool.ball.spwan(sizeIndex).init(colorIndex, direction, 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 labelScore = this.labelScore;
const score = this.score;
if (score >= 1000) {
labelScore.text = (Math.floor(score / 100) / 10).toString() + "k";
} else {
labelScore.text = score.toString();
}
labelScore.x = -labelScore.width / 2;
labelScore.y = -labelScore.height / 2+4;
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 = Ball.ballTextures[this.colorIndex];
}
} else {
this.onScoreIsZero();
} */
if (this.score <= 0) {
this.onScoreIsZero();
}
}
}
private drop() {
//掉落数
let index = 1;
//根据子弹分数判断索引
let bulletScore = DataMgr.game.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: number[] = getProp(keys, values, config.num);
let drops: Drop[] = [];
for (let id of dropIds) {
drops.push(DataMgr.game._pool.drop.spwan(id.toString()));
}
let dir = this.x > MConst.DesignResolution.width / 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 (GuideMgr.instance.guideFlag && i == 1) {
MTimer.setFrameTimer(20, () => {
GuideMgr.instance.runGuide(1, Math.floor(drop.x), Math.floor(drop.y), true);
});
}
}
}
}
\ No newline at end of file
import {PoolElement} from "../Component/Pool";
import MoveObjcet from "./MoveObject";
import {MConst} from "../Global/MConst";
import GameObject from "./GameObject";
import Collider, {CircleCollider, ColliderGroup, PointCollider} from "../Phycics/Collider";
import Game from "./Game";
import {DataMgr} from "../Mgr/DataMgr";
import MTimer from "../Global/MTimer";
import GameMgr from "../Mgr/GameMgr";
import {getTexture} from "../utils";
const bulletSpeedValue = 20;
/**顾名思义 */
const frameCountThatBulletsMoveInX = 4;
export default class Bullet extends MoveObjcet implements PoolElement {
public power: number = 1;
constructor() {
super();
this.addChild(new engine.Image(getTexture("09bdff41-2fe3-4298-ad3a-1d2eaf6af778")));
let collider = this.addComponent(PointCollider) as PointCollider;
collider.group = ColliderGroup.Bullet;
collider.setData(2, 0);
this.physics.velocity.y = -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) {
DataMgr.game._pool.bullet.recycle(this);
}
}
}
export class BulletGroup {
private moveDatas: { bullet: Bullet, frameOffset: number }[] = [];
public restFrameCountThatBulletsMoveInX: number = frameCountThatBulletsMoveInX;
constructor(position: engine.Point, rowBulletNum: number) {
for (let i = 0; i < rowBulletNum; i++) {
const bullet = DataMgr.game._pool.bullet.spwan().init(Math.floor(DataMgr.game.powerScore / 100));
bullet.x = position.x - bullet.width / 2;
bullet.y = position.y + bullet.height / 2;
let frameOffset = ((i - (rowBulletNum - 1) / 2) * (bullet.width + 3)) / frameCountThatBulletsMoveInX;
this.moveDatas.push({
bullet: bullet,
frameOffset,
});
}
DataMgr.game._horizontalMoveMgr.movingList.push(this);
}
public onUpdate() {
let data: { bullet: Bullet, frameOffset: number } = null;
for (let i = 0; i < this.moveDatas.length; i++) {
data = this.moveDatas[i];
data.bullet.x += data.frameOffset;
}
this.restFrameCountThatBulletsMoveInX--;
}
}
export class HorizontalMoveMgr extends GameMgr {
constructor() {
super("HorizontalMoveMgr")
}
public movingList: BulletGroup[] = [];
protected onUpdate() {
if (this.pause) return;
for (let i = 0; i < this.movingList.length; i++) {
this.movingList[i].onUpdate();
}
this.movingList = this.movingList.filter(e => e.restFrameCountThatBulletsMoveInX > 0);
}
}
\ No newline at end of file
import GameObject from "./GameObject";
import Collider, {RectCollider, ColliderGroup} from "../Phycics/Collider";
import {MConst} from "../Global/MConst";
import Bullet, {BulletGroup} from "./Bullet";
import SoundMgr from "../Mgr/SoundMgr";
import MTimer from "../Global/MTimer";
import {props} from "../../props";
import {DataMgr} from "../Mgr/DataMgr";
import {clamp, getTexture} from "../utils";
export default class Car extends GameObject {
private imgParticel: engine.Sprite = null;
private fireTimer: number = null;
public touchWall: 1 | -1 | 0 = 0;
public onDied: () => void;
private isDied: boolean = false;
private fireParticleTimer = 0;
private invincible = false;
/**每排子弹的个数 */
private rowBulletNum: number = 1;
private fireSpeed: number = MConst.BulletFireSpeed.min;
private collider: RectCollider;
//轮子
private lefthwheel:engine.Image;
private leftbwheel:engine.Image;
private righthwheel:engine.Image;
private rightbwheel:engine.Image;
private wheeleng:number;
//误差偏移
private wuchax = -2;
private spritewidth = 0;
constructor() {
super();
// this.x = 124;
// this.y = 145;
const {carCollidePaddingX, carCollidePaddingY} = props;
let wheeltex = getTexture("12729a51-65bd-4e5a-9829-7d6d794e76e8");
let wheelwid = wheeltex.width;
let wheelhei = wheeltex.height
this.wheeleng = 2*Math.PI*wheelhei;
this.lefthwheel = new engine.Image(wheeltex);
this.lefthwheel.anchorX = wheelwid/2;
this.lefthwheel.anchorY = wheelhei/2;
this.leftbwheel = new engine.Image(wheeltex);
this.leftbwheel.anchorX = wheelwid/2;
this.leftbwheel.anchorY = wheelhei/2;
this.righthwheel = new engine.Image(wheeltex);
this.righthwheel.anchorX = wheelwid/2;
this.righthwheel.anchorY = wheelhei/2;
this.rightbwheel = new engine.Image(wheeltex);
this.rightbwheel.anchorX = wheelwid/2;
this.rightbwheel.anchorY = wheelhei/2;
this.leftbwheel.x = 0;
this.leftbwheel.y = 150;
// this.addChild(this.leftbwheel);
this.rightbwheel.x = 115;
this.rightbwheel.y = 150;
// this.addChild(this.rightbwheel);
//车身
let sprite = new engine.Sprite(getTexture("ddf5128e-be66-4c00-8505-e4167aac37bc"));
sprite.x = 0;
sprite.y = 16;
this.addChild(sprite);
this.lefthwheel.x = 0;
this.lefthwheel.y = 155;
this.addChild(this.lefthwheel);
this.righthwheel.x = 115;
this.righthwheel.y = 155;
this.addChild(this.righthwheel);
let particle = new engine.Sprite(getTexture("d8daa113-0d75-4139-9e81-c54b7522c890"));
particle.x = (sprite.width - particle.width) / 2+this.wuchax;
particle.y = -20;
this.addChild(particle);
this.imgParticel = particle;
MTimer.onFrame("Car", this.onUpdate, this);
this.spritewidth = sprite.width+5;
let collider = this.collider = this.addComponent<RectCollider>(RectCollider);
collider.setData(carCollidePaddingX, carCollidePaddingY, sprite.width - carCollidePaddingX * 2, sprite.height - carCollidePaddingY * 2);
collider.group = ColliderGroup.Car;
//车底
engine.globalEvent.addEventListener("CarDiToCarWall0",this.CarDiToCarWall0,this);
engine.globalEvent.addEventListener("CarDiToCarDie",this.CarDiToCarDie,this);
engine.globalEvent.addEventListener("CarDiToCarWall",this.CarDiToCarWall,this);
// let rect1 = new engine.Shape();
// rect1.beginFill(0xff0000,1);
// rect1.drawRect(0,0,this.spritewidth,dihei);
// rect1.endFill();
// this.addChild(rect1);
}
/* private createPart(source: string, x: number, y: number) {
let bitmap = new engine.Image(getTexture(source) as engine.Texture);
bitmap.x = x;
bitmap.y = y;
this.addChild(bitmap);
return bitmap;
} */
private fire() {
// return;
SoundMgr.instance.playEffect("shoot");
let wuchax = this.wuchax;
let mwid = 98;
// console.log(this.x,this.width/2,wuchax);
new BulletGroup(new engine.Point(this.x + mwid+wuchax, this.y), this.rowBulletNum);
}
private die() {
if (this.invincible) return;
if (this.isDied) return;
this.isDied = true;
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() {
engine.Tween.get(this)
.to({alpha: 0}, 1)
.wait(100)
.to({alpha: 1}, 1)
.wait(100)
.call(() => {
this.onceBlink();
});
}
revive() {
this.invincible = true;
this.isDied = false;
engine.Tween.removeTweens(this);
this.onceBlink();
MTimer.setFrameTimer(MConst.ReviveInvincibleDuration * 60, () => {
//无敌结束
this.invincible = false;
this.alpha = 1;
engine.Tween.removeTweens(this);
});
}
move(deltaX: number) {
if (this.touchWall == 1 && deltaX <= 0) {
return;
} else if (this.touchWall == -1 && deltaX >= 0) {
return;
}
const {carCollidePaddingX} = props;
// const {x, width} = this.collider.rect;
const x = this.x;
const width = this.spritewidth;
let startx = this.x;
this.x = Math.max(-x, Math.min(750 - width, this.x + deltaX));
let endx = this.x;
let passx = startx - endx;
let nroa = this.lefthwheel.rotation;
let changeroa = 360*(passx/this.wheeleng)*-1.5;
let toroa = nroa+changeroa;
this.leftbwheel.rotation = toroa;
this.lefthwheel.rotation = toroa;
this.rightbwheel.rotation = toroa;
this.righthwheel.rotation = toroa;
engine.globalEvent.dispatchEvent("carDiMove",{
x:endx
});
}
onCollisionExit(other: Collider) {
if (other.group == ColliderGroup.Wall) {
this.touchWall = 0;
}
}
private onUpdate() {
if (DataMgr.game.pause) return;
const score = DataMgr.game.bulletScore;
//更新开火速度
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.rowBulletNum = Math.ceil((clamp(score, 15, 140) / 2) / 10);
//开火计时流逝
this.fireTimer += 1 * MTimer.dtFactor;
if (this.fireTimer >= 60 / this.fireSpeed) {
this.fire();
this.fireTimer = 0;
}
if (this.fireParticleTimer % 3 == 0) {
this.imgParticel.visible = !this.imgParticel.visible;
}
this.fireParticleTimer++;
}
CarDiToCarWall0(e){
// console.log("CarDiToCarWall0",e);
if(e.data){
let mx = e.data.mx;
// console.log("mx",mx);
this.touchWall = mx<0?1:-1;
}
}
CarDiToCarDie(e){
// console.log("CarDiToCarDie");
this.die();
}
CarDiToCarWall(e){
// console.log("CarDiToCarWall",e);
this.touchWall = 0;
}
}
\ No newline at end of file
import GameObject from "./GameObject";
import Collider, {RectCollider, ColliderGroup} from "../Phycics/Collider";
import MTimer from "../Global/MTimer";
import {props} from "../../props";
import {DataMgr} from "../Mgr/DataMgr";
export default class CarDi extends GameObject{
private collider: RectCollider;
public onDied: () => void;
constructor(wid,hei) {
super();
const {carCollidePaddingX, carCollidePaddingY} = props;
engine.globalEvent.addEventListener("carDiMove",this.carDiMove,this);
let rect = new engine.Shape();
rect.beginFill(0xff0000,0.5);
rect.drawRect(0,0,wid,hei);
rect.endFill();
this.addChild(rect);
// //rect
// console.log("rect",rect);
let collider = this.collider = this.addComponent<RectCollider>(RectCollider);
collider.setData(0, 0, wid, hei);
collider.group = ColliderGroup.Car;
MTimer.onFrame("CarDi", this.onUpdate, this);
}
onCollisionEnter(other: Collider) {
if (other.group == ColliderGroup.Ball) {
this.die();
}
if (other.group == ColliderGroup.Wall) {
// this.touchWall = other.owner.x < 0 ? 1 : -1;
this.changeWall(other.owner.x);
}
}
onCollisionStay(other: Collider) {
if (other.group == ColliderGroup.Ball) {
this.die();
}
if (other.group == ColliderGroup.Wall) {
// this.touchWall = other.owner.x < 0 ? 1 : -1;
this.changeWall(other.owner.x);
}
}
onCollisionExit(other: Collider) {
if (other.group == ColliderGroup.Wall) {
// this.touchWall = 0;
engine.globalEvent.dispatchEvent("CarDiToCarWall0");
}
}
die(){
engine.globalEvent.dispatchEvent("CarDiToCarDie");
}
changeWall(mx){
engine.globalEvent.dispatchEvent("CarDiToCarWall",{
mx:mx
});
}
private onUpdate(){
if (DataMgr.game.pause) return;
}
carDiMove(e){
let x = e.data.x;
this.x = x;
}
}
\ No newline at end of file
import MoveObjcet from "./MoveObject";
import { MConfigs } from "../Global/MConfigs";
import Collider, { ColliderGroup, PointCollider } from "../Phycics/Collider";
import SoundMgr from "../Mgr/SoundMgr";
import { PoolElement } from "../Component/Pool";
import { DataMgr } from "../Mgr/DataMgr";
import {getTexture} from "../utils";
const dropImgNames = [
"f7221f86-f376-40ce-b0e8-f7ea573ec780",
"c9dbd728-1844-4910-b1ef-e84ce10dc422",
"41182131-7050-4b95-9dce-45275b70738d",
"17d8e000-b290-4972-bcab-cb819a6cf51b",
"3f7faebf-64da-44a4-8152-0c35fcc29fe5"
];
export default class Drop extends MoveObjcet implements PoolElement {
private type: "bullet" | "power" = 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;
private id: number = null;
constructor(id: number) {
super();
this.id = id;
//图像
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;
const config = MConfigs.drop[id];
this.type = config.type;
this.scoreValue = config.value;
this.physics.acceleration.y = 0.3;
let texture = getTexture(dropImgNames[id]) as engine.Texture;
this.bitmap.texture = texture;
let str = "+" + config.value;
if (config.type == "power") str = str + "%";
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);
}
private eated() {
SoundMgr.instance.playEffect("collect");
this.physics.rotateVelocity = 0;
DataMgr.game._dropBlinkMgr.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") {
DataMgr.game._BulletScore += this.scoreValue;
} else if (this.type == "power") {
DataMgr.game._PowerScore += this.scoreValue;
}
engine.Tween.removeTweens(this);
engine.Tween.get(this)
.to({ y: this.y - 200, alpha: 0 }, 1000)
.call(() => {
DataMgr.game._pool.drop.recycle(this.id.toString(), this);
engine.Tween.removeTweens(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;
DataMgr.game._dropBlinkMgr.add(this);
this.physics.rotateVelocity = this.physics.velocity.x * (180 / (Math.PI * 13));
}
}
}
onCollisionExit(other: Collider) {
if (other.group == ColliderGroup.Ground) {
this.stayGroundCount = 0;
}
}
onElementInit() {
this.visible = true;
this.stayGroundCount = 0;
this.isGround = false;
this.enableAllComponents();
this.label.visible = false;
this.physics.acceleration.y = 0.3;
}
onElementRecycle() {
this.alpha = 1;
this.visible = false;
this.disableAllComponents();
}
}
\ No newline at end of file
import Car from "./Car";
import CarDi from "./CarDi";
import {MConst} from "../Global/MConst";
import PlayerController from "./PlayerController";
import Ball from "./Ball";
import Physics from "../Phycics/Physics";
import GameObject from "./GameObject";
import {RectCollider, ColliderGroup} from "../Phycics/Collider";
import {MConfigs} from "../Global/MConfigs";
import Drop from "./Drop";
import {MUtils} from "../Global/MUtils";
import {arrayRemove, getBallScore} from "../Global/GUtils";
import MTimer from "../Global/MTimer";
import PhycicsSystem from "../Phycics/PhycicsSystem";
import Bullet, {HorizontalMoveMgr} from "./Bullet";
import {BallPoolGroup} from "../Pools/BallPool";
import AnimationPoolGroup from "../Pools/AnimationPool";
import FrameAnimation, {FrameAnimationMgr} from "../Component/FrameAnimation";
import GuideMgr from "../Mgr/GuideMgr";
import {Pool, PoolGroup, PoolElement} from "../Component/Pool";
import {BulletPool} from "../Pools/BulletPool";
import SpBoomEffectPoolGroup, {SpBoomEffectMgr} from "./SpBoomEffect";
import DropPoolGroup from "../Pools/DropPool";
import DropBlinkMgr from "../Mgr/DropBlinkMgr";
import GameMgr from "../Mgr/GameMgr";
import {DataMgr} from "../Mgr/DataMgr";
import {getAsset, getTexture} from "../utils";
type LayerName = "Bullet" | "Ball" | "Drop" | "Effect";
export default class Game {
/****** property ******/
/**
*
* 当前得分
* @readonly
*/
public get score(): number {
return this._score;
}
/**
* 子弹分数
* @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; //取反
for (let mgr of this.mgrs) {
mgr.pause = this._pause;
}
}
public get pause() {
return this._pause;
}
private _pause: boolean = false;
private _updateData = {};
/**游戏结束回调函数 */
public onGameOver: () => void;
/**分数改变时的回调函数 delta是分数的变化量 */
public onScoreChange: (delta: number) => void;
/****** public method ******/
/**复活 */
public revive() {
this._car.revive();
this.pause = false;
}
/**销毁游戏 */
public destroy() {
try{
this.node.dispose();
for (let mgr of this.mgrs) {
mgr.onDestroy();
}
MTimer.removeOnFrame("Game");
MTimer.removeOnFrame("Car");
MTimer.removeOnFrame("CarDi");
// this.node.destroy();
}catch(e){
console.error("destroy===233");
}
}
private mgrs: GameMgr[] = [];
public _phycicsSystem: PhycicsSystem = new PhycicsSystem();
public _boomEffectMgr: SpBoomEffectMgr = new SpBoomEffectMgr();
public _animationMgr: FrameAnimationMgr = new FrameAnimationMgr();
public _horizontalMoveMgr: HorizontalMoveMgr = new HorizontalMoveMgr();
private needSubmitCount = 0; //实际分数减去ConstantSubmitScoreNum的次数
private _localScore: number = 0;
public get localScore(): number {
return this._localScore;
}
public set localScore(v: number) {
this._localScore = v;
if (this._localScore >= MConst.ConstantSubmitScoreNum) {
let count = Math.floor(this._localScore / MConst.ConstantSubmitScoreNum);
this.needSubmitCount += count;
this._localScore -= MConst.ConstantSubmitScoreNum * count;
}
}
private loadRes() {
FrameAnimation.loadRes(
getTexture("217164f4-a185-429c-8706-818137a4e438"),
getAsset('763d2430-ad16-42c6-8bf0-d7337b05b247')
);
FrameAnimation.loadRes(
getTexture("53c65221-3fbc-41d9-8cef-8a846876fe06"),
getAsset('b82d6a84-8423-4be2-add5-ed9129e8c700')
);
}
private initMgrs() {
this.mgrs = [
this._dropBlinkMgr,
this._phycicsSystem,
this._boomEffectMgr,
this._animationMgr,
this._horizontalMoveMgr
];
for (let mgr of this.mgrs) {
mgr.onInit();
}
}
constructor(parent: engine.Container) {
DataMgr.game = this;
this.initMgrs();
this.pause = false;
this.loadRes();
parent.addChild(this.node);
GuideMgr.instance.container = parent;
this.node.width = MConst.DesignResolution.width;
this.node.height = MConst.DesignResolution.height;
let bg = new engine.Image(getTexture("d99368b8-af5d-4d9e-981e-7bce3e1c1e84"));
this.node.addChild(bg);
//子弹层
this.node.addChild(this.layers.bullet);
//炮车
let car = new Car();
car.x = Math.floor(this.node.width / 2 - car.width / 2);
car.y = Math.floor(MConst.GroundLine - car.height + 30);
this.node.addChild(car);
car.addComponent(Physics);
car.onDied = () => {
this.over();
};
this._car = car;
//炮车底
let carwid = car.width;
let carhei = car.height;
let cardiwid = carwid;
let cardihei = 100;
let cardiy = 155;
let cardi = new CarDi(cardiwid,cardihei);
cardi.x = car.x;
cardi.y = car.y+cardiy;
this.node.addChild(cardi);
cardi.addComponent(Physics);
cardi.onDied = ()=>{
this.over();
}
this._cardi = cardi;
//球的层
this.node.addChild(this.layers.ball);
//掉落物层
this.node.addChild(this.layers.drop);
//特效层
this.node.addChild(this.layers.effect);
//动画层
this.node.addChild(this.layers.animation);
//禁用层级交互事件
for (let k in this.layers) {
this.layers[k].mouseChildren = false;
this.layers[k].mouseEnabled = false;
}
//玩家控制器
let playerController = new PlayerController();
playerController.onTouchMove = (deltaX) => {
if (!this.pause) {
car.move(deltaX);
}
};
this.node.addChild(playerController);
//添加监听器
MTimer.onFrame("Game", this.onUpdate, this);
this.createPools();
//创建墙和地面
this.createWall();
//开始倒计时
this.timing = true;
// this._BulletScore = 140;
// this._PowerScore = 2000;
}
/****** private method ******/
private over() {
this.pause = true;
engine.globalEvent.dispatchEvent("game-over", this._updateData);
this.onGameOver && this.onGameOver();
}
private createWall() {
let topWall = new GameObject();
topWall.x = -500;
topWall.y = -500;
this.node.addChild(topWall);
//添加天花板碰撞器
let topWallCollider = topWall.addComponent<RectCollider>(RectCollider);
topWallCollider.setData(0, 0, MConst.DesignResolution.width + 1000, 490);
topWallCollider.group = ColliderGroup.Top;
//创建地面节点
let ground = new GameObject();
ground.x = -500;
ground.y = MConst.GroundLine;
this.node.addChild(ground);
//添加地面碰撞器
let groundCollider = ground.addComponent<RectCollider>(RectCollider);
groundCollider.setData(0, 0, MConst.DesignResolution.width + 1000, 1000);
groundCollider.group = ColliderGroup.Ground;
//创建左墙节点
let leftWall = new GameObject();
leftWall.x = -500;
leftWall.y = -500
this.node.addChild(leftWall);
//添加左墙碰撞器
let leftWallCollider = leftWall.addComponent<RectCollider>(RectCollider);
leftWallCollider.setData(0, 0, 500, MConst.DesignResolution.height + 1000);
leftWallCollider.group = ColliderGroup.Wall;
//创建右墙节点
let rightWall = new GameObject();
rightWall.x = MConst.DesignResolution.width;
rightWall.y = -500
this.node.addChild(rightWall);
//添加右墙碰撞器
let rightWallCollider = rightWall.addComponent<RectCollider>(RectCollider);
rightWallCollider.setData(0, 0, 500, MConst.DesignResolution.height + 1000);
rightWallCollider.group = ColliderGroup.Wall;
}
private createBall() {
let size = MUtils.randomInt(0, MConfigs.size.length);
if (GuideMgr.instance.guideFlag == true) {
size = 3;
}
let color = MUtils.randomInt(size, MConst.MaxColorIndex);
let ball = this._pool.ball.spwan(size);
let dir: 1 | -1 = Math.random() > 0.5 ? -1 : 1;
const score = getBallScore(this._BulletScore, this._PowerScore, color);
ball.init(color, dir, score);
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);
this.bulletScoreUpdateFlag = false;
}
//检查球的创建
if (this.createBallCD > 0) {
this.createBallCD -= MTimer.deltaTime;
}
if (this._ballList.length < this.curMaxBallNum) {
if (this.createBallCD <= 0) {
this.createBall();
}
}
if (!this.pause) {
this.outputEvent();
}
}
private outputEvent() {
let updateData = {
score: this.score,
bulletScore: this.bulletScore,
powerScore: this.powerScore,
};
let needSend = false;
for (let key in updateData) {
if (updateData[key] != this._updateData[key]) {
this._updateData[key] = updateData[key];
needSend = true;
}
}
if (needSend) {
engine.globalEvent.dispatchEvent("game-update", updateData);
}
}
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() {
let count = 0;
let callback = () => {
if (count > 1) return;
count++;
this.node.x = 10;
engine.Tween.get(this.node)
.wait(1, true)
.to({x: 0, y: -10}, 1)
.to({x: -10, y: 0}, 1)
.to({x: 0, y: 10}, 1)
.to({x: 0, y: 0}, 1)
.call(callback);
};
callback();
}
public _pool: {
ball: BallPoolGroup,
bullet: BulletPool,
boomEffect: SpBoomEffectPoolGroup
animation: AnimationPoolGroup,
drop: DropPoolGroup
} = null;
private createPools() {
this._pool = {
ball: new BallPoolGroup(this.layers.ball),
bullet: new BulletPool(this.layers.bullet),
animation: new AnimationPoolGroup(this.layers.animation),
boomEffect: new SpBoomEffectPoolGroup(this.layers.effect),
drop: new DropPoolGroup(this.layers.drop)
};
}
public _playBoomEffect(position: engine.Point, size: number) {
const effect = this._pool.boomEffect.spwan(MUtils.randomInt(0, 3), size);
effect.position = position;
}
public _createAnimation(key: string) {
const clip = this._pool.animation.spwan(key);
clip.onCompleted = () => {
this._pool.animation.recycle(key, clip);
}
return clip;
}
/****** private field ******/
public _dropBlinkMgr = new DropBlinkMgr();
private layers = {
bullet: new engine.Container(),
ball: new engine.Container(),
drop: new engine.Container(),
effect: new engine.Container(),
animation: new engine.Container()
};
/**不建议使用 */
public get _score(): number {
return this.__score;
}
public set _score(v: number) {
this.localScore += (v - this.__score);
this.__score = v;
}
/**不建议使用 */
public _car: Car = null;
private __score: number = 0;
private curMaxBallNum = 1;
private timing = false;
private createBallCD: number = 0;
private bulletScoreUpdateFlag = false;
/**不建议使用 */
public _ballList: Ball[] = [];
private node: engine.Container = new engine.Container();
//车底
public _cardi:CarDi = null;
/**不建议使用 */
public get _BulletScore(): number {
return this._bulletScore;
}
public onGuideDone() {
engine.globalEvent.dispatchEvent('game-start');
}
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;
}
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 GameComponent from "./GameComponent";
import Collider from "../Phycics/Collider";
import Game from "./Game";
export default class GameObject extends engine.Container {
public name: string = "";
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[] = [];
constructor() {
super();
// this.addEventListener(engine.Event.REMOVED_FROM_STAGE, this.disableAllComponents, this);
this.mouseEnabled = false;
this.mouseChildren = false;
}
/**销毁时禁用所有组件 */
dispose() {
this.destroy();
this.disableAllComponents();
}
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
import {MConfigs} from "../Global/MConfigs";
import {MConst} from "../Global/MConst";
import {getTexture} from "../utils";
import {props} from "../../props";
const padding = 10;
export default class GuideMask extends engine.Container {
constructor(index: number, x1: number, y1: number) {
super();
const config = MConfigs.guide[index];
let mask = new engine.Sprite(getTexture("d268f82e-d1b9-44c6-b40f-4a08e11aab75"));
const w = Math.floor(mask.width/2), h = Math.floor(mask.height/2);
mask.width = w*2;
mask.height = h*2;
// console.log(x1,y1,index);
// x1 = Math.floor(x1);
// y1 = Math.floor(y1);
const x = x1 - w;
const y = y1 - h;
mask.x = x;
mask.y = y;
this.addChild(mask);
const sw = MConst.DesignResolution.width, sh = MConst.DesignResolution.height;
let color = 0x000000;
let alpha = 0.75;
let top = new engine.Shape();
top.beginFill(color, alpha);
top.drawRect(0, 0, sw, y);
top.endFill();
this.addChild(top);
console.log("长短配置1",sw,sh,y,x,mask.height);
let bottom = new engine.Shape();
bottom.beginFill(color, alpha);
bottom.drawRect(0, y+mask.height, sw, sh-(y+mask.height));
bottom.endFill();
this.addChild(bottom);
// let left = new engine.Shape();
// left.beginFill(color, alpha);
// left.drawRect(0, y, x, sh - y);
// left.endFill();
// this.addChild(left);
// let right = new engine.Shape();
// right.beginFill(color, alpha);
// right.drawRect(x + w, y, sw - x - w, sh - y);
// right.endFill();
// this.addChild(right);
// let offsetToMask = config.text.offsetToMask;
// let label = new engine.Label();
// label.text = props['guideText' + index];//config.text.str;
// label.size = 24;
// label.fillColor = "rgba(255,255,255,1)";
// label.x = mask.x + (w - label.width) / 2;
// label.y = offsetToMask.y + mask.y;
// this.addChild(label);
// if (index == 0) {
// let left = new engine.Sprite(getTexture("93992a62-e3c4-46d5-99f4-f7ba35fe4f4f"));
// left.x = x1 + 200;
// left.y = y1 - left.height / 2;
// this.addChild(left);
// let right = new engine.Sprite(getTexture("93992a62-e3c4-46d5-99f4-f7ba35fe4f4f"));
// right.x = x1 - 200;
// right.scaleX = -1;
// right.y = y1 - right.height / 2;
// this.addChild(right);
// }
// if (label.x < padding) {
// label.x = padding;
// } else if (label.x + label.width > 750 - padding) {
// label.x = 750 - label.width - padding;
// }
this.addEventListener(engine.MouseEvent.MOUSE_DOWN, () => {
this.onClick && this.onClick(this);
}, this);
}
onClick: (context: GuideMask) => void;
}
\ No newline at end of file
import GameObject from "./GameObject";
import Physics from "../Phycics/Physics";
import Game from "./Game";
export default class MoveObjcet extends GameObject {
public physics: Physics = null;
constructor() {
super();
this.physics = this.addComponent(Physics);
}
}
\ No newline at end of file
import { MConst } from "../Global/MConst";
import { MConfigs } from "../Global/MConfigs";
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 = MConst.DesignResolution.width;
this.height = MConst.DesignResolution.height;
this.addEventListener(engine.MouseEvent.MOUSE_DOWN, (e: engine.MouseEvent) => {
this.touchId = e.instanceId;
this.lastX = e.clientX;
}, 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.clientX - this.lastX)
this.lastX = e.clientX;
}, this);
this.addEventListener(engine.MouseEvent.MOUSE_UP, (e: engine.MouseEvent) => {
if (e.instanceId != this.touchId) return;
this.touchId = null;
this.lastX = null;
}, this);
let rect = new engine.Rect();
rect.width = 750;
rect.height = 1624;
rect.fillColor = "rgba(255,255,255,1)"
rect.alpha = 0;
this.addChild(rect);
}
}
\ No newline at end of file
import {TextureMgr} from "../Mgr/TextureMgr";
import {MUtils} from "../Global/MUtils";
import MTimer from "../Global/MTimer";
import {Pool, PoolGroup, PoolElement} from "../Component/Pool";
import {DataMgr} from "../Mgr/DataMgr";
import GameMgr from "../Mgr/GameMgr";
const InitSpeedValue: number = 0.08;
const alphaDuration: number = 300;
const alphaPerFrame: number = 1 / (alphaDuration / (1000 / 60));
const InitAcceleration: number = -0.00005;
const noAlphaDuration: number = 200 / (1000 / 60);
class Line {
public sprite: engine.Sprite = null;
private direction: engine.Point = null;
private speedValue: number = InitSpeedValue;
constructor(parent: engine.Container, type: number, color: number, rotation: number) {
const sprite = new engine.Sprite(TextureMgr.get(("fireworks_line_" + type) as any, color));
parent.addChild(sprite);
sprite.anchorX = sprite.width / 2;
sprite.rotation = rotation;
this.sprite = sprite;
//计算方向
let dir = MUtils.getVector(rotation + 90)
this.direction = dir;
}
private frameTimer = 0;
public init() {
this.sprite.y = -this.sprite.height;
this.sprite.alpha = 1;
this.sprite.x = 0;
this.sprite.y = 0;
this.frameTimer = 0;
this.speedValue = InitSpeedValue;
}
public onUpdate(dt: number) {
this.sprite.x += this.direction.x * this.speedValue * dt;
this.sprite.y += this.direction.y * this.speedValue * dt;
if (this.frameTimer > noAlphaDuration) {
this.sprite.alpha -= alphaPerFrame * MTimer.dtFactor;
}
this.frameTimer++;
}
}
export class SpBoomEffectMgr extends GameMgr {
constructor() {
super("SpBoomEffectMgr")
}
public list: SpBoomEffect[] = [];
protected onUpdate(dt: number) {
if (this.pause) return;
let filter: SpBoomEffect[] = [];
for (let i of this.list) {
if (i.onUpdate(dt)) {
filter.push(i);
}
}
this.list = filter;
}
}
class SpBoomEffect extends engine.Container implements PoolElement {
private lines: Line[] = [];
public onUpdate(dt: number) {
for (let i of this.lines) {
i.onUpdate(dt);
}
if (this.lines[0].sprite.alpha <= 0) {
DataMgr.game._pool.boomEffect.recycle(this.poolKey, this);
return false;
}
return true;
}
constructor(color: number, size: number) {
super();
this.scaleX = this.scaleY = 0.5 * size + 0.5;
this.rotation = MUtils.random(0, 90);
for (let i = 0; i < 16; i++) {
let line = new Line(this, i % 2, color, i * 22.5);
this.lines.push(line);
}
DataMgr.game._boomEffectMgr.list.push(this);
}
onElementInit() {
this.visible = true;
this.alpha = 1;
for (let i of this.lines) {
i.init();
}
DataMgr.game._boomEffectMgr.list.push(this);
}
onElementRecycle() {
this.visible = false;
}
poolKey: string;
}
class SpBoomEffectPool extends Pool<SpBoomEffect> {
public spwan(color: number, size: number): SpBoomEffect {
if (this.data.length > 0) {
const element = this.data.shift();
element.onElementInit();
return element;
} else {
const e = new SpBoomEffect(color, size);
this.layer.addChild(e);
return e;
}
}
}
export default class SpBoomEffectPoolGroup extends PoolGroup<SpBoomEffect> {
public spwan(color: number, size: number) {
const key = color.toString() + size;
if (!this.data[key]) {
this.data[key] = new SpBoomEffectPool(this.layer)
}
const element = this.data[key].spwan(color, size);
element.poolKey = key;
return element;
}
}
import { MUtils } from "./MUtils";
import { MConst } from "./MConst";
import { MConfigs } from "./MConfigs";
import {getTexture} from "../utils";
export function getBallScore(bulletScore: number, powerScore: number, colorIndex: number): any {
let getScoreFromRange = ([a, b]) => {
a = Math.ceil(a * 0.1);
b = Math.ceil(b * 0.1);
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 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 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 size = [0.3125, 0.5357, 0.7321, 1];
export const drop: {
[key: number]: {
type: "bullet" | "power",
value: number,
textColor: number,
fileIndex: string
}
} = [
{
type: "bullet",
value: 1,
textColor: 0x5dcefa,
fileIndex: "0"
},
{
type: "bullet",
value: 2,
textColor: 0x69e7fc,
fileIndex: "1"
},
{
type: "power",
value: 30,
textColor: 0xe83cf7,
fileIndex: "2"
},
{
type: "power",
value: 20,
textColor: 0xeb3924,
fileIndex: "1"
},
{
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 boomEffectColor = [
0xe41014,
0xff9600,
0x0090ff,
0x8aff00,
0xffe720
] */
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: 8,
y: 290
}
}
},
1: {
mask: "guide_mask_1_png",
text: {
str: "拾取金币可获得更多的炮弹输出和得分加成",
offsetToMask: {
x: -65,
y: 290
}
}
},
}
}
export namespace MConst {
export const MaxColorIndex = 5;
export const DesignResolution = {
width: 750,
height: 1624
};
export const GroundLine = 1110;
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 BallInitPosY = 1206 * 0.25;
export const CreateBallInterval = 1000;
export const ReviveCardId = "sp_1";
export const ConstantSubmitScoreNum = 100;
export const DefaultBallWidth = 224;
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
import MEvent from "../Component/MEvent";
export default class MTimer {
public static init() {
startTime = Date.now();
engine.gameStage.addEventListener(engine.Event.ENTER_FRAME, onUpdate, MTimer);
document.addEventListener("visibilitychange", onVisibilityChange);
}
public static destroy() {
_onFrame.clear();
engine.gameStage.removeEventListener(engine.Event.ENTER_FRAME, onUpdate, MTimer);
document.removeEventListener("visibilitychange", onVisibilityChange);
}
/**
* 帧间隔
*/
public static get deltaTime(): number {
return _deltaTime;
}
/**
* 帧间隔系数:当前帧间隔与标准帧间隔(60帧)的比值
*/
public static get dtFactor() {
return MTimer.deltaTime / DefaultDeltaTime;
}
/**
* 注册帧回调函数
*/
/* public static get onFrame(): MEvent<(dt: number) => void> {
return _onFrame;
} */
public static onFrame(key: string, callback: (dt: number) => void, thisObj?: any) {
if (key) {
if (onFrameCaches[key]) {
_onFrame.remove(onFrameCaches[key].callback, onFrameCaches[key].thisObj);
delete onFrameCaches[key];
}
onFrameCaches[key] = {
callback: callback,
thisObj: thisObj
};
}
_onFrame.add(callback, thisObj);
}
public static removeOnFrame(key: string) {
if (onFrameCaches[key]) {
_onFrame.remove(onFrameCaches[key].callback, onFrameCaches[key].thisObj);
delete onFrameCaches[key];
}
}
/**
* 设置帧计时器
*/
public static setFrameTimer(frame: number, onTimeOut: () => void) {
let count = 0;
const callback = () => {
if (count >= frame) {
onTimeOut();
timerTickEvent.remove(callback);
} else {
count += MTimer.dtFactor;
}
}
timerTickEvent.add(callback);
}
}
const onFrameCaches: {
[key: string]: {
callback: (dt: number) => void,
thisObj?: any
}
} = {};
const _onFrame: MEvent<(dt: number) => void> = new MEvent();
const timerTickEvent: MEvent<() => void> = new MEvent();
const DefaultDeltaTime = 1000 / 60;
let _deltaTime: number = 0;
let startTime = 0;
let lastTime = 0;
let curTime = 0;
function updateDeltaTime() {
lastTime = curTime;
curTime = Date.now() - startTime;
_deltaTime = curTime - lastTime;
}
function onVisibilityChange() {
if (document.visibilityState == "visible") {
curTime = Date.now() - startTime;
}
}
function onUpdate() {
updateDeltaTime();
_onFrame.call(MTimer.deltaTime);
timerTickEvent.call();
}
\ 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 Game from "../Game/Game"
export namespace DataMgr {
export let game: Game = null;
export let minEnableCaptchaScore: number = null;
}
\ No newline at end of file
import UILayer from "../Component/UILayer";
import MTimer from "../Global/MTimer";
export default class DebugMgr extends UILayer {
public enabled: boolean = true;
public enabledGraphic: boolean = true;
private shapeMap = {};
private graphicDebugLayer: engine.Container = null;
private uiLayer: engine.Container = null;
private log: engine.Label = null;
public test: any = null;
private labelFPS = new engine.Label();
public onClick = () => { }
constructor() {
super();
if (!this.enabled) return;
//创建图形调试层
this.graphicDebugLayer = new UILayer();
this.addChild(this.graphicDebugLayer);
//创建UI层
this.uiLayer = new engine.Container();
this.addChild(this.uiLayer);
//创建帧率标签
this.labelFPS.size = 30;
this.labelFPS.fillColor = "rgba(255,255,255,1)";
this.labelFPS.text = "0";
this.labelFPS.x = 20;
this.labelFPS.y = 20;
this.uiLayer.addChild(this.labelFPS);
/* 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: 0x00ff00, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape = new engine.Shape();
shape.beginStroke(style.color);
shape.drawRect(rect.x, rect.y, rect.width, rect.height);
shape.endStroke();
this.graphicDebugLayer.addChild(shape);
}
public drawCircle(x: number, y: number, radius: number, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape = new engine.Shape();
shape.beginStroke(style.color);
shape.drawCircle(x, y, radius);
shape.endStroke();
this.graphicDebugLayer.addChild(shape);
}
public drawLine(line: GraphicDebug.Line, style: GraphicDebug.Style = { color: 0x00ff00, lineSize: 1 }) {
if (!this.enabled || !this.enabledGraphic) return;
let shape = new engine.Shape();
shape.beginStroke(style.color);
shape.moveTo(line.startX, line.startY);
shape.lineTo(line.endX, line.endY);
shape.endStroke();
this.graphicDebugLayer.addChild(shape);
}
public updateLine(key: string, line: GraphicDebug.Line, style: GraphicDebug.Style = { color: 0x00ff00, 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.clear();
shape.beginStroke(style.color);
shape.moveTo(line.startX, line.startY);
shape.lineTo(line.endX, line.endY);
shape.endStroke();
}
public updateRect(key: string, rect: engine.Rectangle, style: GraphicDebug.Style = { color: 0x00ff00, 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.clear();
shape.beginStroke(style.color);
shape.drawRect(rect.x, rect.y, rect.width, rect.height);
shape.endStroke();
}
public updateCircle(key: string, x: number, y: number, radius: number, style: GraphicDebug.Style = { color: 0x00ff00, 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.clear();
shape.beginStroke(style.color);
shape.drawCircle(x, y, radius);
shape.endStroke();
}
public clearShape(key: string) {
if (!this.enabled || !this.enabledGraphic) return;
let shape: engine.Shape = this.shapeMap[key];
if (!shape) {
return;
}
delete this.shapeMap[key];
shape.dispose();
}
init(context: engine.Container) {
context.addChild(this);
MTimer.onFrame("DebugMgr", this.onUpdate, this);
}
private lastFrameData: { runTime: number, frameCount: number } = { runTime: 0, frameCount: 0 };
private curFrameData: { runTime: number, frameCount: number } = { runTime: 0, frameCount: 0 };
private resetTimer = 0;
private onUpdate(dt: number) {
this.curFrameData.runTime += dt;
this.curFrameData.frameCount += 1;
this.resetTimer += dt;
let average = (this.curFrameData.runTime + this.lastFrameData.runTime) / (this.curFrameData.frameCount + this.lastFrameData.frameCount)
if (this.resetTimer > 200) {
this.labelFPS.text = Math.round(1000 / average).toString();
this.lastFrameData.runTime = this.curFrameData.runTime;
this.lastFrameData.frameCount = this.curFrameData.frameCount;
this.curFrameData.runTime = 0;
this.curFrameData.frameCount = 0;
this.resetTimer = 0;
}
}
private static _instance: DebugMgr = null;
public static get instance(): DebugMgr {
if (!this._instance) {
this._instance = new DebugMgr();
}
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 Drop from "../Game/Drop";
import MTimer from "../Global/MTimer";
import GameMgr from "./GameMgr";
export default class DropBlinkMgr extends GameMgr {
constructor() {
super("DropBlinkMgr");
}
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);
}
private frameTimer: number = 0;
public onUpdate() {
if (this.pause) return;
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.dispose();
return false;
}
});
}
this.frameTimer++;
}
}
const BlinkDuration = 3;
\ No newline at end of file
import MTimer from "../Global/MTimer";
export default abstract class GameMgr {
constructor(private name: string) { }
public onInit(): void {
MTimer.onFrame(this.name, this.onUpdate, this);
}
public onDestroy() {
MTimer.removeOnFrame(this.name);
}
protected onUpdate(dt: number) {
}
public pause: boolean = false
}
\ No newline at end of file
import {props} from "../../props";
import GuideMask from "../Game/GuideMask";
import { ShootPlanet } from "../ShootPlanet";
import { DataMgr } from "./DataMgr";
import {MConfigs} from "../Global/MConfigs";
export default class GuideMgr {
private static _instance: GuideMgr = null;
public static get instance(): GuideMgr {
if (!GuideMgr._instance) {
GuideMgr._instance = new GuideMgr();
}
return GuideMgr._instance;
}
public get guideFlag(): boolean {
return localStorage.getItem("shoot-planet_" + props.guideFlagKey) != "false";
}
public set guideFlag(v: boolean) {
localStorage.setItem("shoot-planet_" + props.guideFlagKey, v ? "true" : "false");
}
set container(c){
this._container = c;
}
private done: number[] = [];
private _container: engine.Container;
get guideDone(){
return !this.guideFlag || this.done.length >= Object.keys(MConfigs.guide).length;
}
private currentGuideMask: GuideMask = null;
public runGuide(index: number, x: number, y: number, end: boolean = false) {
// if (this.done[index] || this.guideFlag == false) return;
this.done.push(index);
DataMgr.game.pause = true;
this.currentGuideMask = new GuideMask(index, x, y);
this.currentGuideMask.onClick = (context) => {
context.dispose();
DataMgr.game.pause = false;
if(this.done.length >= Object.keys(MConfigs.guide).length){
DataMgr.game.onGuideDone();
}
if (end) {
this.guideFlag = false;
}
};
this._container.addChild(this.currentGuideMask);
}
}
\ No newline at end of file
import MTimer from "../Global/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 get enabled() {
return engine.env.soundEnabled;
}
public playEffect(name: string, loop: boolean = false) {
if (!this.enabled) return;
engine.playSound(getAssetByUUID(nameToUuid[name]).uuid, {
loop: false,
keep: true
}, name);
}
}
const nameToUuid = {
shoot: "b01dc39a-2886-4887-b3bb-0f8c801003a9",
collect: "7004616a-0aba-4826-9245-895e7fdf8d31",
dong: "7fc04e43-1465-4336-92a3-d6039ee88cb3",
boom: "ca6b799f-be85-4e94-99df-812f31801490"
}
\ No newline at end of file
import {getTexture} from "../utils";
type ImgType = "star" | "ring" | "fireworks_line_0" | "fireworks_line_1";
export namespace TextureMgr {
const uuids: {
[key in ImgType]: string[]
} = {
"star": [
"e79f4e51-dbca-45fb-b95a-f52a708e0990",
"1a1b529f-bf68-42cb-8a3e-01b21119b322",
"999d65ba-f7c8-4939-9868-5f974a278752",
"c5743fdf-aadf-4139-b03a-cfd047f85220",
"2aaa2535-d4b9-44c4-8fc2-700c8310e534"
],
"ring": [
"b3c78176-5650-4d49-bc00-cfaf048c5940",
"134e2eec-e393-4ba3-b8cc-f72270bf17c2",
"49092176-3b1c-4ea5-8e02-6050fc5809dd",
"15c46813-ac79-4c5f-8a52-e8cded6dadff",
"64e64fd6-0426-493e-b003-dcafc7e06eb5"
],
"fireworks_line_0": [
"c76f6d87-7f84-45ed-a9ac-cf8d4dd47026",
"1fc4fb96-73b7-4250-8886-3c6976eb1139",
"65be7718-f6cd-44d9-89d0-5daf81068316"
],
"fireworks_line_1": [
"10901339-4976-4d38-a3b9-47b7e9025144",
"0692b423-6f14-4ba7-884a-7c177f1583c8",
"2ddd9477-12de-4f13-bb35-5b255f1624bd"
]
};
/* const caches: {
[uuid: string]: engine.Texture
} = {}; */
export function get(type: ImgType, index: number) {
const uuid = uuids[type][index];
/* if (!caches[uuid]) {
caches[uuid] = ;
} */
return getTexture(uuid);
}
}
\ No newline at end of file
import GameComponent from "../Game/GameComponent";
import GameObject from "../Game/GameObject";
import PhycicsSystem from "./PhycicsSystem";
import Physics from "./Physics";
import { DataMgr } from "../Mgr/DataMgr";
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;
DataMgr.game._phycicsSystem.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)
DataMgr.game._phycicsSystem.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() {
DataMgr.game._phycicsSystem.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.center[0];
out[1] = this.owner.y + 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.rect.left;
out[1] = this.owner.y + 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 = 0,
Rect = 1,
Point = 2
}
import Physics from "./Physics";
import Collider, { CircleCollider, RectCollider, ColliderType, ColliderGroup, PointCollider } from "./Collider";
import { arrayRemove } from "../Global/GUtils";
import MTimer from "../Global/MTimer";
import DebugMgr from "../Mgr/DebugMgr";
import GameMgr from "../Mgr/GameMgr";
let instanceId1: number = null;
let instanceId2: number = null;
export default class PhycicsSystem extends GameMgr {
/* 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;
} */
constructor() { super("PhycicsSystem"); }
private phycicsList: Physics[] = [];
onInit() {
super.onInit();
for (let i = 0; i <= GroupMaxIndex; i++) {
this.colliderList[i] = [];
}
}
public onDestroy() {
super.onDestroy();
for (let i = 0; i <= GroupMaxIndex; i++) {
this.colliderList[i] = [];
}
this.phycicsList = [];
}
protected onUpdate() {
if (this.pause) return;
for (let i of this.phycicsList) {
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;
});
// DebugMgr.instance.clearShape(collider.owner.instanceId.toString());
this.colliderList[collider.group] = arrayRemove(this.colliderList[collider.group], collider);
}
/**检测碰撞 */
public detectCollision() {
/* for (let i of this.colliderList) {
for (let j of i) {
this.drawCollider(j);
}
} */
//查找所有碰撞
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) {
group1 = this.colliderList[i];
group2 = this.colliderList[j];
for (m = 0; m <= group1.length - 1; m++) {
for (n = 0; n <= group2.length - 1; n++) {
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);
}
}
}
private drawCollider(collider: Collider) {
switch (collider.type) {
case ColliderType.Circle:
let circleCollider = collider as CircleCollider;
let worldCenter = [];
collider.getWorldPosition(worldCenter)
DebugMgr.instance.updateCircle(collider.owner.instanceId.toString(), worldCenter[0], worldCenter[1], circleCollider.radius);
break;
case ColliderType.Rect:
let rectCollider = collider as RectCollider;
let worldPos = [];
rectCollider.getWorldPosition(worldPos);
DebugMgr.instance.updateRect(rectCollider.owner.instanceId.toString(), new engine.Rectangle(worldPos[0], worldPos[1], rectCollider.rect.width, rectCollider.rect.height));
break;
}
}
}
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 "../Game/GameComponent";
import GameObject from "../Game/GameObject";
import PhycicsSystem from "./PhycicsSystem";
import Collider from "./Collider";
import { DataMgr } from "../Mgr/DataMgr";
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() {
DataMgr.game._phycicsSystem.remove(this);
}
protected onEnabled() {
DataMgr.game._phycicsSystem.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
import FrameAnimation from "../Component/FrameAnimation";
import { Pool, PoolGroup, PoolElement } from "../Component/Pool";
export class PoolFrameAnimation extends FrameAnimation implements PoolElement {
onElementInit() {
this.visible = true;
this.curPos = 0;
}
onElementRecycle() {
this.visible = false;
}
}
class AnimationPool extends Pool<PoolFrameAnimation> {
public spwan(key: string): PoolFrameAnimation {
if (this.data.length > 0) {
const element = this.data.shift();
element.onElementInit();
return element;
} else {
let anim = new PoolFrameAnimation(key);
this.layer.addChild(anim);
return anim;
}
}
}
export default class AnimationPoolGroup extends PoolGroup<PoolFrameAnimation> {
public spwan(key: string) {
if (!this.data[key]) {
this.data[key] = new AnimationPool(this.layer);
}
const element = this.data[key].spwan(key);
return element;
}
}
\ No newline at end of file
import { Pool, PoolGroup } from "../Component/Pool";
import Ball from "../Game/Ball";
import { DataMgr } from "../Mgr/DataMgr";
class BallPool extends Pool<Ball>{
public spwan(sizeIndex: number) {
let element: Ball = null;
if (this.data.length > 0) {
element = this.data.shift();
element.onElementInit();
} else {
element = new Ball(sizeIndex);
this.layer.addChild(element);
}
DataMgr.game._ballList.push(element);
return element;
}
public recycle(element: Ball) {
super.recycle(element);
DataMgr.game._ballList = DataMgr.game._ballList.filter(e => e !== element);
}
};
export class BallPoolGroup extends PoolGroup<Ball>{
public spwan(sizeIndex: number) {
const key = sizeIndex.toString();
if (!this.data[key]) {
const ball =
this.data[key] = new BallPool(this.layer)
}
let element = this.data[key].spwan(sizeIndex);
element.poolKey = key;
return element;
}
}
\ No newline at end of file
import Bullet from "../Game/Bullet";
import { Pool } from "../Component/Pool";
export class BulletPool extends Pool<Bullet> {
public spwan() {
if (this.data.length > 0) {
const element = this.data.shift();
element.onElementInit();
return element;
} else {
const b = new Bullet();
this.layer.addChild(b);
return b;
}
}
}
\ No newline at end of file
import { Pool, PoolGroup } from "../Component/Pool";
import Drop from "../Game/Drop";
class DropPool extends Pool<Drop> {
public spwan(id: number) {
if (this.data.length > 0) {
const element = this.data.shift();
element.onElementInit();
return element;
} else {
const d = new Drop(id);
this.layer.addChild(d);
return d;
}
}
}
export default class DropPoolGroup extends PoolGroup<Drop>{
public spwan(id: string) {
if (!this.data[id]) {
this.data[id] = new DropPool(this.layer);
}
return this.data[id].spwan(id);
}
}
\ No newline at end of file
import Game from "./Game/Game";
import MTimer from "./Global/MTimer";
import DebugMgr from "./Mgr/DebugMgr";
import GuideMgr from "./Mgr/GuideMgr";
/**
* Created by rockyl on 2019-11-22.
*/
export class ShootPlanet extends engine.Container {
public game: Game = null;
testbtn:engine.Shape;
constructor() {
super();
this.customProperty();
this.width = 750;
this.height = 1624;
this.init();
engine.globalEvent.addEventListener('game-create', this.onActive, this);
engine.globalEvent.addEventListener('game-destroy', this.onSleep, this);
engine.globalEvent.addEventListener('game-revive', this.onRevive, this);
engine.globalEvent.addEventListener('game-pause', this.onPause, this);
engine.globalEvent.addEventListener('game-resume', this.onResume, this);
engine.globalEvent.addEventListener("game-start",this.onStart,this);
engine.globalEvent.addEventListener("game_reset",this.onReset,this);
// this.testbtn = new engine.Shape();
// this.testbtn.beginFill(0xff0000,1);
// this.testbtn.drawRect(0,0,200,200);
// this.testbtn.endFill();
// this.addChild(this.testbtn);
// this.testbtn.addEventListener(engine.MouseEvent.CLICK,this.changeStage,this);
}
//stage测试233
ntype = "game-create";
changeStage(){
if(this.ntype=="game-create"){
this.onSleep();
this.ntype = "game-destroy"
}else{
this.onActive();
this.ntype = "game-create";
}
}
public onActive() {
if(!this.game){
this.game = new Game(this);
}
// this.setChildIndex(this.testbtn,100);
// if (GuideMgr.instance.guideFlag == true) {
// const car = this.game._car;
// GuideMgr.instance.runGuide(0, car.x + car.width / 2, car.y + car.height / 2 /* - 130 */);
// }
// if (GuideMgr.instance.guideDone) {
// this.game.onGuideDone();
// }
}
public onSleep() {
this.game.destroy();
this.game = null;
}
public onStart(e){
if(e.data){
let guide = e.data.guide;
console.log("guide",guide);
if(guide){
const car = this.game._car;
GuideMgr.instance.runGuide(0, Math.floor(car.x + car.width / 2), Math.floor(car.y + car.height / 2-110) /* - 130 */);
}
}
}
//reset回收
public onReset(){
}
public onRevive() {
this.game.revive();
}
public onPause() {
this.game.pause = true;
}
public onResume() {
this.game.pause = false;
}
private init() {
MTimer.init();
DebugMgr.instance.init(this);
}
private customProperty() {
Object.defineProperty(engine.Point.prototype, 'length', {
get: function () {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
});
engine.DisplayObject.prototype.dispose = function () {
this.parent.removeChild(this);
}
}
}
{
"mc": {
"boom": {
"frameRate": 60,
"events": [
],
"frames": [
{
"res": "1ECDAB2E",
"x": 109,
"y": 109
},
{
"res": "7D1C3EA6",
"x": 104,
"y": 104
},
{
"res": "32FD22BF",
"x": 99,
"y": 99
},
{
"res": "8D21D7FD",
"x": 94,
"y": 94
},
{
"res": "AA99D248",
"x": 89,
"y": 89
},
{
"res": "EB300D3B",
"x": 84,
"y": 84
},
{
"res": "2D80AF70",
"x": 79,
"y": 79
},
{
"res": "D5989DA4",
"x": 74,
"y": 74
},
{
"res": "F357A8ED",
"x": 69,
"y": 69
},
{
"res": "84EE6F80",
"x": 64,
"y": 64
},
{
"res": "49BA3EE3",
"x": 59,
"y": 59
},
{
"res": "1F12115",
"x": 54,
"y": 54
},
{
"res": "DD77F7EA",
"x": 49,
"y": 49
},
{
"res": "8587C4D",
"x": 44,
"y": 44
},
{
"res": "9C93A4AF",
"x": 39,
"y": 39
},
{
"res": "9B8ABD91",
"x": 34,
"y": 34
}
]
}
},
"res": {
"F357A8ED": { "x": 1501, "y": 1, "w": 458, "h": 458 },
"8D21D7FD": { "x": 1389, "y": 481, "w": 407, "h": 407 },
"DD77F7EA": { "x": 521, "y": 1, "w": 498, "h": 498 },
"84EE6F80": { "x": 1, "y": 1521, "w": 468, "h": 468 },
"32FD22BF": { "x": 920, "y": 1389, "w": 397, "h": 397 },
"7D1C3EA6": { "x": 1389, "y": 890, "w": 387, "h": 387 },
"EB300D3B": { "x": 491, "y": 1389, "w": 427, "h": 427 },
"49BA3EE3": { "x": 1021, "y": 1, "w": 478, "h": 478 },
"9C93A4AF": { "x": 1, "y": 1, "w": 518, "h": 518 },
"1ECDAB2E": { "x": 1319, "y": 1279, "w": 377, "h": 377 },
"2D80AF70": { "x": 511, "y": 950, "w": 437, "h": 437 },
"1F12115": { "x": 1, "y": 1031, "w": 488, "h": 488 },
"8587C4D": { "x": 1, "y": 521, "w": 508, "h": 508 },
"D5989DA4": { "x": 521, "y": 501, "w": 447, "h": 447 },
"AA99D248": { "x": 970, "y": 501, "w": 417, "h": 417 },
"9B8ABD91": { "x": 1, "y": 1991, "w": 5, "h": 5 }
}
}
\ No newline at end of file
{
"mc": {
"duang": {
"frameRate": 60,
"events": [
],
"frames": [
{
"res": "3EABE380",
"x": 114,
"y": 116
},
{
"res": "D2951B4",
"x": 104,
"y": 107
},
{
"res": "DB5323C3",
"x": 94,
"y": 97
},
{
"res": "D708FEB1",
"x": 84,
"y": 87
},
{
"res": "F89427A9",
"x": 74,
"y": 78
},
{
"res": "C986141",
"x": 65,
"y": 68
},
{
"res": "567BF25C",
"x": 55,
"y": 58
},
{
"res": "21928374",
"x": 45,
"y": 48
},
{
"res": "412C16BB",
"x": 35,
"y": 39
},
{
"res": "3D32B0AA",
"x": 25,
"y": 29
},
{
"res": "3AC6F4E4",
"x": 16,
"y": 20
},
{
"res": "AB94C69F",
"x": 5,
"y": 8
}
]
}
},
"res": {
"21928374": { "x": 594, "y": 1, "w": 237, "h": 168 },
"412C16BB": { "x": 326, "y": 1, "w": 266, "h": 185 },
"D708FEB1": { "x": 450, "y": 340, "w": 122, "h": 97 },
"3D32B0AA": { "x": 1, "y": 223, "w": 294, "h": 203 },
"F89427A9": { "x": 297, "y": 340, "w": 151, "h": 114 },
"DB5323C3": { "x": 1, "y": 428, "w": 93, "h": 79 },
"3AC6F4E4": { "x": 1, "y": 1, "w": 323, "h": 220 },
"C986141": { "x": 833, "y": 1, "w": 179, "h": 132 },
"D2951B4": { "x": 96, "y": 428, "w": 64, "h": 61 },
"AB94C69F": { "x": 594, "y": 171, "w": 5, "h": 5 },
"567BF25C": { "x": 326, "y": 188, "w": 208, "h": 150 },
"3EABE380": { "x": 536, "y": 188, "w": 36, "h": 44 }
}
}
\ No newline at end of file
{
"frames": {
".": {
"x": 3,
"y": 215,
"w": 16,
"h": 17,
"ox": 7,
"oy": 49,
"sw": 29,
"sh": 66
},
"k": {
"x": 155,
"y": 3,
"w": 42,
"h": 65,
"ox": 6,
"oy": 0,
"sw": 48,
"sh": 66
},
"0": {
"x": 3,
"y": 144,
"w": 44,
"h": 65,
"ox": 2,
"oy": 1,
"sw": 48,
"sh": 66
},
"1": {
"x": 145,
"y": 74,
"w": 27,
"h": 65,
"ox": 7,
"oy": 0,
"sw": 48,
"sh": 66
},
"2": {
"x": 53,
"y": 74,
"w": 41,
"h": 64,
"ox": 3,
"oy": 1,
"sw": 48,
"sh": 66
},
"3": {
"x": 100,
"y": 74,
"w": 39,
"h": 65,
"ox": 5,
"oy": 1,
"sw": 48,
"sh": 66
},
"4": {
"x": 3,
"y": 3,
"w": 48,
"h": 64,
"ox": 0,
"oy": 1,
"sw": 48,
"sh": 66
},
"5": {
"x": 53,
"y": 144,
"w": 39,
"h": 65,
"ox": 5,
"oy": 1,
"sw": 48,
"sh": 66
},
"6": {
"x": 106,
"y": 3,
"w": 43,
"h": 65,
"ox": 3,
"oy": 1,
"sw": 48,
"sh": 66
},
"7": {
"x": 203,
"y": 3,
"w": 42,
"h": 64,
"ox": 3,
"oy": 1,
"sw": 48,
"sh": 66
},
"8": {
"x": 3,
"y": 73,
"w": 44,
"h": 65,
"ox": 2,
"oy": 1,
"sw": 48,
"sh": 66
},
"9": {
"x": 57,
"y": 3,
"w": 43,
"h": 65,
"ox": 2,
"oy": 1,
"sw": 48,
"sh": 66
}
}
}
\ No newline at end of file
/**
* Created by rockyl on 2020-01-02.
*/
export function getTexture(uuid: string): engine.Texture {
let config = getAssetByUUID(uuid);
return engine.Texture.from(config ? config.uuid : uuid);
}
export function getAsset(uuid: string) {
let config = getAssetByUUID(uuid);
return engine.globalLoader.get(config.uuid);
}
export function clamp(target: number, min: number, max: number) {
return Math.min(max, Math.max(min, target));
}
/**
* Created by rockyl on 2019-11-20.
*/
import { ShootPlanet } from "./game/ShootPlanet";
import {injectProps, prepareProps} from "./props";
export default function (props) {
prepareProps();
injectProps(props);
let instance = new ShootPlanet();
return instance;
}
/**
* Created by rockyl on 2020-01-21.
*/
export let props: any = {};
export function prepareProps() {
let metaProps = getProps();
engine.injectProp(props, metaProps);
}
export function injectProps(p) {
engine.injectProp(props, p);
}
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