Commit febedac1 authored by Master Q's avatar Master Q

游戏整体逻辑添加

parent 18dd1f4c
resource/NewGuyScene/Guide1.png

62.2 KB | W: | H:

resource/NewGuyScene/Guide1.png

844 KB | W: | H:

resource/NewGuyScene/Guide1.png
resource/NewGuyScene/Guide1.png
resource/NewGuyScene/Guide1.png
resource/NewGuyScene/Guide1.png
  • 2-up
  • Swipe
  • Onion skin
{
"groups": [
{
"keys": "box1.png,box2.png,box3.png,box4.png,box5.png,box6.png,box7.png,box8.png",
"name": "Boxes"
},
{
"keys": "DFM1.png,DFMB.png",
"name": "DrawFailModal"
},
{
"keys": "DSM1.png,DSMB.png",
"name": "DrawSucModal"
},
{
"keys": "FGM1.png,FGMB.png",
"name": "FinalGiftModal"
},
{
"keys": "2b727ace1b5c959dbc6274cacb5b4e5f.png,3ed4431aad269ef7059929043bd45597.png,60377934f7cf618b52457273db65aace.png,9074d1305c0e7feb16037261986c7f4b.png,f3bde4659477f82338fcb2b134272321.png",
"name": "GameAtom"
},
{
"keys": "GOM0.png,GOM1.png,GameOverModalBack.png",
"name": "GameOverModal"
},
{
"keys": "GQM0.png,GQM1.png,GQMB.png",
"name": "GameQuitModal"
},
{
"keys": "GameResumeModalBack.png,cancelBtn.png,useRightNowBtn.png",
"name": "GameResumeModal"
},
{
"keys": "back.png,bottomAtom.png,gele1.png,goBackBtn.png,player.png,scoreboard-t.png",
"keys": "GSB.png,platform.png,rabbit.png,scoreBoardBack.png",
"name": "GameScene"
},
{
"keys": "2120075482341d7d94d8164b1a0f6d43.png,3ed4431aad269ef7059929043bd45597.png,4f4612689c9fde32a8c28c129e9f6e7d.png,60377934f7cf618b52457273db65aace.png,63b0a84f0f9b10842b5f83fa5e923534.png,f3bde4659477f82338fcb2b134272321.png",
"name": "JumpEnd"
},
{
"keys": "Guide1.png,NGSB.jpg,nextStep.png,startGameBtn.png",
"keys": "Guide1.png,Guide2.png,Guide3.png,Guide4.png",
"name": "NewGuyScene"
},
{
"keys": "2120075482341d7d94d8164b1a0f6d43.png",
"name": "PerfectJumpEnd"
},
{
"keys": "closebtn.png,giftBoxIcon.png,waitingBg.png,waitingRot.png",
"name": "common"
},
{
"keys": "786bf3500cf0986c9678f6b8a8cf24f6.png,b5d5c1070b13deb0230b0efe5c58ee9d.png,ca7b2a497afc6147cc076d55600154bd.png,d64a974a921d32ed81463c918bae137e.png,f49a78c8287be1a92ee75ce3a2b7a512.png",
"name": "countDown"
},
{
"keys": "548342251013e2f832a40380d1855bf5.png,af75d547153d9118b05d4dd8fbcfe022.png,fd0f936244fb973bddf520819997f5ba.png",
"name": "handLottie"
},
{
"keys": "nx1.jpg,ny1.jpg,nz1.jpg,px1.jpg,py1.jpg,pz1.jpg",
"name": "skybox"
},
{
"keys": "rabbit.spi",
"name": "spine"
}
],
"path": "./resource/"
......
export const ResJson = {
"groups": [
{
"keys": "box1.png,box2.png,box3.png,box4.png,box5.png,box6.png,box7.png,box8.png",
"name": "Boxes"
},
{
"keys": "DFM1.png,DFMB.png",
"name": "DrawFailModal"
},
{
"keys": "DSM1.png,DSMB.png",
"name": "DrawSucModal"
},
{
"keys": "FGM1.png,FGMB.png",
"name": "FinalGiftModal"
},
{
"keys": "2b727ace1b5c959dbc6274cacb5b4e5f.png,3ed4431aad269ef7059929043bd45597.png,60377934f7cf618b52457273db65aace.png,9074d1305c0e7feb16037261986c7f4b.png,f3bde4659477f82338fcb2b134272321.png",
"name": "GameAtom"
},
{
"keys": "GOM0.png,GOM1.png,GameOverModalBack.png",
"name": "GameOverModal"
},
{
"keys": "GQM0.png,GQM1.png,GQMB.png",
"name": "GameQuitModal"
},
{
"keys": "GameResumeModalBack.png,cancelBtn.png,useRightNowBtn.png",
"name": "GameResumeModal"
},
{
"keys": "back.png,bottomAtom.png,gele1.png,goBackBtn.png,player.png,scoreboard-t.png",
"keys": "GSB.png,platform.png,rabbit.png,scoreBoardBack.png",
"name": "GameScene"
},
{
"keys": "2120075482341d7d94d8164b1a0f6d43.png,3ed4431aad269ef7059929043bd45597.png,4f4612689c9fde32a8c28c129e9f6e7d.png,60377934f7cf618b52457273db65aace.png,63b0a84f0f9b10842b5f83fa5e923534.png,f3bde4659477f82338fcb2b134272321.png",
"name": "JumpEnd"
},
{
"keys": "Guide1.png,NGSB.jpg,nextStep.png,startGameBtn.png",
"keys": "Guide1.png,Guide2.png,Guide3.png,Guide4.png",
"name": "NewGuyScene"
},
{
"keys": "2120075482341d7d94d8164b1a0f6d43.png",
"name": "PerfectJumpEnd"
},
{
"keys": "closebtn.png,giftBoxIcon.png,waitingBg.png,waitingRot.png",
"name": "common"
},
{
"keys": "786bf3500cf0986c9678f6b8a8cf24f6.png,b5d5c1070b13deb0230b0efe5c58ee9d.png,ca7b2a497afc6147cc076d55600154bd.png,d64a974a921d32ed81463c918bae137e.png,f49a78c8287be1a92ee75ce3a2b7a512.png",
"name": "countDown"
},
{
"keys": "548342251013e2f832a40380d1855bf5.png,af75d547153d9118b05d4dd8fbcfe022.png,fd0f936244fb973bddf520819997f5ba.png",
"name": "handLottie"
},
{
"keys": "nx1.jpg,ny1.jpg,nz1.jpg,px1.jpg,py1.jpg,pz1.jpg",
"name": "skybox"
},
{
"keys": "rabbit.spi",
"name": "spine"
}
],
"path": "./resource/"
......
......@@ -4,7 +4,6 @@ import { ModalCtroller } from "./modules/ModalControl";
import { RES } from "./modules/RES";
import { ResJson } from "./ResJson";
import { GameScene } from "./scenes/GameScene/GameScene";
import { HomeScene } from "./scenes/home";
import { NewGuyScene } from "./scenes/NewGuyScene/NewGuyScene";
import { Tools } from "./tools/Tools";
import Tween = FYGE.Tween;
......@@ -109,7 +108,7 @@ export class Main {
RES.loadConfig(ResJson)
await RES.loadGroup('common')
SceneController.changeScene(Tools.PageData.isFirstGame ? NewGuyScene : GameScene)
SceneController.changeScene(GameScene)
}
initWebEvent(){
......
......@@ -190,7 +190,7 @@ export const ModalCtroller = (function() {
(_.ModalContainer as FYGE.Container).destroy();
ModalMap.delete(ModalNode)
}
console.log('closeModal config:', _.props._config, ModalMap)
// console.log('closeModal config:', _.props._config, ModalMap)
return
}
......
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import Dream from "../../Dream";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
@UsePreload({
preAction: async function() {
await RES.loadGroup('DrawFailModal')
},
loadingComponent: null
})
export class DrawFailModal extends Dream.RenderContainer {
onConfirm = () => {
this.props.onConfirm()
this.props.closeModal()
}
render() {
const roleCont = RES.getRes('DFMB.png')
const confirmbtn = RES.getRes('DFM1.png')
return (
<DreamContainer>
<DreamSprite src={roleCont} />
{/* <DreamSprite onClick={this.onConfirm} inlineProps={{
x: roleCont.width - 50,
y: -50
}} src={RES.getRes('closebtn.png')}/> */}
<DreamSprite onClick={this.onConfirm} inlineProps={{
x: roleCont.width / 2 - confirmbtn.width / 2,
y: 300
}} src={confirmbtn}/>
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import Dream from "../../Dream";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import { sendTbNet, TbNetName } from "../../tools/TbNet";
@UsePreload({
resList: [],
preAction: async function() {
await RES.loadGroup('DrawSucModal')
},
loadingComponent: null
})
export class DrawSucModal extends Dream.RenderContainer<{
closeModal: () => Promise<any>,
onConfirm: () => void
name: string,
img: string
}> {
onClose2GameOver = async () => {
await this.props.closeModal()
this.props.onConfirm()
}
onConfirm = () => {
// sendTbNet(TbNetName.goMyPrize)
this.onClose2GameOver()
}
render() {
const roleCont = RES.getRes('DSMB.png')
const confirmbtn = RES.getRes('DSM1.png')
const roleWidth = roleCont.width
const {
name,
img
} = this.props
return (
<DreamContainer>
<DreamSprite src={roleCont}></DreamSprite>
{/* <DreamSprite onClick={() => {
this.onClose2GameOver()
}} inlineProps={{
x: roleWidth - 50
}} src={RES.getRes('closebtn.png')}/> */}
<DreamSprite inlineProps={{
x: roleWidth / 2 - 100,
y: 210
}} src={img} width={200} height={200} />
<DreamTextField color="#b36d00" text={'获得 ' + name} textWidth={roleWidth} inlineProps={{
y: 445
}}></DreamTextField>
<DreamSprite onClick={this.onConfirm} src={confirmbtn} inlineProps={{
x: roleWidth / 2 - confirmbtn.width / 2,
y: 550
}} />
<DreamTextField text="奖品可在首页「我的奖品」中查看" textWidth={roleWidth} color="#ffffff" size={22} inlineProps={{
y: roleCont.height - 80
}} />
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { ModalComponent } from "../../modules/ModalComponent";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import Dream from "../../Dream";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import { sendTbNet, TbNetName } from "../../tools/TbNet";
console.log(Dream)
@UsePreload({
preAction: async function() {
await RES.loadGroup('GameOverModal')
}
})
export class GameOverModal extends ModalComponent<{
score: number
}> {
onCancel() {
sendTbNet(TbNetName.goBackHome)
this.props.closeModal()
}
onConfirm() {
sendTbNet(TbNetName.openCardTask)
}
render() {
const back = RES.getRes('GameOverModalBack.png')
const confirmbtn = RES.getRes("GOM1.png")
const cancelbtn = RES.getRes('GOM0.png')
const th = back.height - 220
const {
score
} = this.props
return (
<DreamContainer inlineProps={{
y: -50
}} className="GameOverModal">
<DreamSprite src={back}></DreamSprite>
<DreamTextField text={score+''} color="#b36d00" size={90} bold textWidth={back.width} inlineProps={{
y: 230
}} />
<DreamSprite src={confirmbtn} inlineProps={{
x: back.width / 2 - confirmbtn.width / 2,
y: th
}}
onClick={this.onConfirm}
></DreamSprite>
<DreamSprite inlineProps={{
x: back.width / 2 - cancelbtn.width / 2,
y: th + confirmbtn.height + 20
}} src={cancelbtn}
onClick={() => {
this.onCancel()
}}
></DreamSprite>
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import Dream from "../../Dream";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import { sendTbNet, TbNetName } from "../../tools/TbNet";
@UsePreload({
async preAction() {
await RES.loadGroup('GameQuitModal')
}
})
export class GameQuitModal extends Dream.RenderContainer<{
pName: string,
closeModal: () => Promise<void>
}> {
onConfirm = () => {
this.props.closeModal()
sendTbNet(TbNetName.goBackHome)
}
render() {
const roleCont = RES.getRes('GQMB.png')
const roleWidth = roleCont.width
const {
pName
} = this.props
return (
<DreamContainer>
<DreamSprite src={roleCont} />
<DreamTextField text="现在退出游戏机会就浪费了哦" size={34} textWidth={roleWidth} inlineProps={{
y: 160
}} />
<DreamTextField text={`参与游戏 ${pName}奖励等你拿!`} color="#b5720d" size={26} textWidth={roleWidth} inlineProps={{y: 230}} />
<DreamContainer inlineProps={{y: 320}}>
<DreamSprite onClick={this.props.closeModal} inlineProps={{x: 50}} src={RES.getRes('GQM0.png')} />
<DreamSprite onClick={this.onConfirm} inlineProps={{x: 300}} src={RES.getRes('GQM1.png')} />
</DreamContainer>
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import Dream from "../../Dream";
import { DreamSpriteV2 } from "../../Dream/UI";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import { sendTbNet, TbNetName } from "../../tools/TbNet";
import { throttle } from "../../tools/Tools";
@UsePreload({
preAction: async function() {
await RES.loadGroup('GameResumeModal')
},
loadingComponent: null
})
export class GameResumeModal extends Dream.RenderContainer<{
resumeNum: number,
closeModal: () => Promise<any>
onConfirm: () => void
onCancel: () => Promise<void>
}> {
countTextField: FYGE.TextField
intervalId: any
didRendered(): void {
this.intervalId = setInterval(() => {
if (this.count == 0) {
this.props.onCancel()
this.props.closeModal()
clearInterval(this.intervalId)
return
}
--this.count
}, 1000)
}
unMount(): void {
clearInterval(this.intervalId)
}
_count: number = 10
get count() {
return this._count
}
set count(v) {
this._count = v
this.countTextField.text = `${v}s`
}
/**
* 确认走复活逻辑
*/
onConfirm = throttle(async () => {
clearInterval(this.intervalId)
const {
success
} = await sendTbNet(TbNetName.reduceTools)
if (success) {
this.props.onConfirm()
this.props.closeModal()
} else {
this.props.closeModal()
}
})
render() {
const RoleContBack = RES.getRes('GameResumeModalBack.png')
const confirmBtn = RES.getRes('useRightNowBtn.png')
const RoleContWidth = RoleContBack.width
const cancelBtn = RES.getRes('cancelBtn.png')
return (
<FYGE.Container>
<DreamSpriteV2 src={RoleContBack}></DreamSpriteV2>
<DreamTextField text={`剩余复活卡:${this.props.resumeNum}张`} color="#b26f06" textWidth={RoleContBack.width} inlineProps={{
y: 230
}} />
<DreamSprite src={confirmBtn} inlineProps={{
x: RoleContWidth / 2 - confirmBtn.width / 2,
y: 320
}}
onClick={this.onConfirm}
/>
<DreamSprite src={cancelBtn}
inlineProps={{
x: RoleContWidth / 2 - cancelBtn.width / 2,
y: 320 + confirmBtn.height + 20
}}
onClick={async () => {
this.props.onCancel()
this.props.closeModal()
}}
>
<DreamTextField ref={el=> {
this.countTextField = el
}} inlineProps={{
x: 160,
y: 3
}} text={this.count + 's'} color="#7e5a32" textHeight={cancelBtn.height} />
</DreamSprite>
</FYGE.Container>
)
}
}
\ No newline at end of file
export enum BoxType {
Box1 = 'Box1',
Box2 = 'Box2',
Box3 = 'Box3',
Box4 = 'Box4',
Box5 = 'Box5',
Box6 = 'Box6',
Box7 = 'Box7',
Box8 = 'Box8',
}
export const BoxTypeList: BoxType[] = [
BoxType.Box1,
BoxType.Box2,
BoxType.Box3,
BoxType.Box4,
BoxType.Box5,
BoxType.Box6,
BoxType.Box7,
BoxType.Box8
]
import { layers } from "../../modules/layers";
export const GameConfig = {
debugger: false,
GenerateSpace: [300, 400], // 生成间距
finalGiftPart: 0.1, // 最终奖励 概率 100%
maxLen: 550,
totoalPart: 0, // 全部概率
PartList: [] as {
preSumPart: number,
type: BoxType
}[], // 概率
GenerateConfig: {
angle: Math.PI * 40 / 180,
tanNum: Math.tan(Math.PI * 40 / 180)
},
CameraConfig: {
pos: {
x: 375,
y: 1100
},
debugger: true,
offsetYLen: 180,
offsetXLen: 150,// 格子间隔
rowNum: 30, // 单个地图的显示 行数
speed: 100, // 卷轴速度
renderMapScreenNum: 200, //当卷轴 移动到视窗上面多少 会去生成地图
rabbitConfig: {
offsetX: 10,
offsetY: -203,
},
GameStagePos: {
x: 160,
y: 1200
},
boxConfig: {
[BoxType.Box1]: {
resName: 'box1.png',
addScore: 4,
oc: {
x: 142, y: 230 // 判断中心点
},
oz: 90, // height
dt: [-60, 50],
part: 10
},
[BoxType.Box2]: {
resName: 'box2.png',
addScore: 5,
oc: {
x: 142, y: 230
},
oz: 60,
dt: [-50, 50],
part: 10
},
[BoxType.Box3]: {
resName: 'box3.png',
addScore: 6,
oc: {
x: 142, y: 230
},
oz: 140,
dt: [-50, 50],
part: 10
},
[BoxType.Box4]: {
resName: 'box4.png',
addScore: 8,
oc: {
x: 142, y: 250
},
oz: 160,
dt: [-40, 40],
part: 10
},
[BoxType.Box5]: {
resName: 'box5.png',
addScore: 10,
oc: {
x: 142, y: 260
},
oz: 60,
dt: [-40, 40],
part: 10
},
[BoxType.Box6]: {
resName: 'box6.png',
addScore: 1,
oc: {
x: 142, y: 230
},
oz: 70,
dt: [-50, 50],
part: 10
},
[BoxType.Box7]: {
resName: 'box7.png',
addScore: 15,
oc: {
x: 142, y: 360
},
oz: 300,
dt: [-50, 50],
part: 4
},
[BoxType.Box8]: {
resName: 'box8.png',
addScore: 15,
oc: {
x: 142, y: 360
},
oz: 305,
dt: [-40, 40],
part: 4
}
}
}
let temp = []
for (let k in GameConfig.boxConfig) {
let kType: BoxType = k as any
temp.push(kType)
}
const tp: {
preSumPart: number,
type: BoxType
}[] = []
GameConfig.totoalPart = temp.reduce((pre, cur) => {
const tt = pre + GameConfig.boxConfig[cur].part
tp.push({
preSumPart: tt,
type: cur
})
return tt
}, 0)
GameConfig.PartList = tp
DecisionLine: [ // 判定线 当前屏幕显示区域
300, layers.stageHeight // 这里个需要后续设定
],
boxColNum: 5, // 几列格子
mapList: [
{
initPos: {
x: 2,
y: 26
},
boxMap: [
[0, 1, 0, 1, 1],
[0, 1, 1, 0, 0],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 1],
[1, 1, 0, 1, 0],
[0, 1, 1, 0, 0],
[1, 0, 0, 0, 1],
[1, 0, 1, 1, 1],
[0, 1, 0, 0, 1],
[1, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 0],
[0, 0, 1, 0, 1],
[1, 1, 0, 1, 1],
[0, 1, 0, 0, 0],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 1],
[1, 1, 0, 0, 0],
[0, 0, 1, 0, 1],
[1, 1, 0, 1, 0],
[0, 0, 0, 0, 1],
[1, 0, 1, 0, 0],
[0, 1, 0, 0, 1],
[1, 1, 0, 1, 0],
[1, 0, 0, 1, 0],
[1, 1, 0, 1, 1],
[0, 1, 1, 0, 1],
[1, 0, 0, 1, 0],
[0, 1, 1, 0, 1],
[1, 1, 1, 1, 1],
],
},
],
};
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamShape } from "../../components/DreamShape/DreamShape";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import Dream, {DreamProps } from "../../Dream";
import { fadeOutUpFactory } from "../../modules/animations";
import { RES } from "../../modules/RES";
import { BoxType, BoxTypeList, GameConfig } from "./GameConfig";
type GameEleType = DreamProps<{
type?: BoxType,
x?: number,
y?: number,
inlineProps?: Record<string, any>
isWithGift?: boolean
}, GameEle>
export class GameEle extends Dream.RenderContainer<GameEleType> {
GameBoxType: BoxType = BoxType.Box1
GiftIcon: FYGE.Sprite
constructor(props: GameEleType) {
super(props)
const {
type
} = this.props
if (type) {
this.GameBoxType = type
} else {
this.GameBoxType = BoxTypeList[Math.random() * BoxTypeList.length >> 0]
}
}
didRendered(): void {
}
onGetGift() {
if (this.GiftIcon) {
fadeOutUpFactory(500, 200)(this.GiftIcon)
}
}
render() {
const currGameBoxConfig = GameConfig.boxConfig[this.GameBoxType]
const boxRes = RES.getRes(currGameBoxConfig.resName)
const {
x,
y,
inlineProps,
isWithGift
} = this.props
const {
dt = [0, 0],
oc: {
x: ocx,
y: ocy
},
oz
} = currGameBoxConfig
const tanNum = Math.tan(GameConfig.GenerateConfig.angle)
// const offsetY = * Math.abs(spaceNum)
// console.log(boxRes, this.GameBoxType, GameConfig.boxConfig, currGameBoxConfig)
return (
<DreamContainer inlineProps={{
...inlineProps,
x,y
}}>
<DreamContainer inlineProps={{
x: -currGameBoxConfig.oc.x,
y: -currGameBoxConfig.oc.y
}}>
<DreamSprite src={boxRes}></DreamSprite>
{
isWithGift && (
<DreamSprite ref={el => {
this.GiftIcon = el
}} src={RES.getRes('giftBoxIcon.png')} inlineProps={{
x: currGameBoxConfig.oc.x - 60,
y: currGameBoxConfig.oc.y - 80 - currGameBoxConfig.oz,
}} />
)
}
{
GameConfig.debugger && (
<DreamContainer>
<DreamShape type="circle" drawData={[0,0, 8]} fillColor="#f17368" inlineProps={{
x: currGameBoxConfig.oc.x,
y: currGameBoxConfig.oc.y
}} />
<DreamShape type="circle" drawData={[0,0, 8]} fillColor="#f17368" inlineProps={{
x: ocx,
y: ocy - oz
}} />
<DreamShape type="circle" drawData={[0,0, 8]} fillColor="#f17368" inlineProps={{
x: ocx + dt[0],
y: ocy - oz + tanNum * Math.abs(dt[0])
}} ></DreamShape>
<DreamShape type="circle" drawData={[0,0, 8]} fillColor="#f17368" inlineProps={{
x: ocx + dt[1],
y: ocy - oz - tanNum * dt[1]
}} ></DreamShape>
</DreamContainer>
)
}
</DreamContainer>
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamLottie } from "../../components/DreamLottie/DreamLottie";
import { DreamShape } from "../../components/DreamShape/DreamShape";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import { DreamToast } from "../../components/DreamToast/DreamToast";
import { DreamWaiting } from "../../components/DreamWaiting/DreamWaiting";
import Dream from "../../Dream";
import { DreamSpriteV2 } from "../../Dream/UI";
import { countDown } from "../../lotties/countDown";
import { GameAtom } from "../../lotties/GameAtom";
import { handLottie } from "../../lotties/handLottie";
import { BounceOutAni, fadeOutFactory, slideTop } from "../../modules/animations";
import { layers } from "../../modules/layers";
import { ModalCtroller } from "../../modules/ModalControl";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import { DrawFailModal } from "../../panels/DrawFailModal/DrawFailModal";
import { DrawSucModal } from "../../panels/DrawSucModal/DrawSucModal";
import { FinalGiftModal } from "../../panels/FinalGiftModal/FinalGiftModal";
import { GameOverModal } from "../../panels/GameOverModal/GameOverModal";
import { GameQuitModal } from "../../panels/GameQuitModal/GameQuitModal";
import { GameResumeModal } from "../../panels/GameResumeModal/GameResumeModal";
import { PlayAudio } from "../../tools/simpleTools";
import { sendTbNet, TbNetName } from "../../tools/TbNet";
import { Tools } from "../../tools/Tools";
import { BoxType, BoxTypeList, GameConfig } from "./GameConfig";
import { GameEle } from "./GameEle";
import { Player, PlayerIns } from "./Player";
import { Stack } from "./Stack";
/**
* 获取 n-m之间的 随机数
* @param {Number} m
* @param {Number} n
* @returns
*/
function randomNum(min: number, max: number) {
var _max = max;
var _min = min;
return Math.floor(Math.random() * (_max - _min + 1)) + _min;
}
class ScoreBoard extends Dream.RenderContainer {
scoreTextField: FYGE.TextField
private _score: number = 0
get score() {
return this._score
}
set score(v) {
this._score = v
this.scoreTextField.text = v + ''
}
render() {
return (
<FYGE.Container inlineProps={this.props.inlineProps}>
<FYGE.Container inlineProps={{
x: 133
}}>
<DreamSpriteV2 src={RES.getRes('scoreboard-t.png')}></DreamSpriteV2>
</FYGE.Container>
<DreamTextField
ref={el => {
this.scoreTextField = el
}}
bold
text={this.score + ''} color="#fbdea8" size={80} textWidth={350} align={FYGE.TEXT_ALIGN.CENTER} inlineProps={{
y: 50
}} />
</FYGE.Container>
)
}
}
import { PromiseAwait } from "../../tools/Tools";
import { GameConfig } from "./GameConfig";
import { Platform } from "./Platform";
import { RabbitPlayer } from "./Player";
import { ScoreBoard } from "./ScoreBoard";
type Pos = {
x: number,
y: number
}
const {
rowNum, offsetYLen, offsetXLen
} = GameConfig
const mapHeight = rowNum * offsetYLen
@UsePreload({
preAction: async function() {
await RES.loadGroup('handLottie')
await RES.loadGroup('GameScene')
await RES.loadGroup('产品输出')
await RES.loadGroup('countDown')
// await RES.loadGroup('spine')
await RES.loadGroup('GameAtom')
await RES.loadGroup('Boxes')
await RES.loadGroup('JumpEnd')
await RES.loadGroup('PerfectJumpEnd')
}
})
export class GameScene extends Dream.RenderContainer {
ScoreBoardIns: ScoreBoard
sceneCont: FYGE.Container
GameEleContainer: FYGE.Container
GameStageContainer: FYGE.Container // 游戏舞台 主要用作视角移动的
GameEleStack: Stack<FYGE.Container & {
oz?: number
}> = new Stack()
GameDtStack: Stack<{
target: FYGE.Container,
dt: number[],
oz: number
}> = new Stack()
CurrBoxItem: FYGE.Container & {oz?: number} // 当前站着的 墩子
PlayerOfRabbit: PlayerIns // 兔子实例
PlayerTarget: FYGE.Container
isPaused: boolean = false
DecisionConfig: {
list: number[], // 判定点位,正常 就是四个,当前墩子的两个和下一个墩子的二个
score: number // 当前配置项
geleIns?: GameEle
} = {
list: [],
score: 0
}
touchPushObj = {tl: 0}
isOver: boolean = false
isCouldHaveGift: boolean = true
isWithGift: boolean = false
private _dir: 1 | -1
get dir() {
return this._dir
GameMapContainer: FYGE.Container
GameReelContainer: FYGE.Container // 当前卷轴Container 用作 卷轴
SceneContainer: FYGE.Container
_mapCount: number = 0 // 当前渲染地址个数
renderMapOffsetY: number = 0 // 当卷轴移动到当前 判定值就去渲染地图
get mapCount() {
return this._mapCount
}
set dir(v) {
this._dir = v
this.PlayerOfRabbit.turnRound(v)
set mapCount(v) {
this._mapCount = v;
this.renderMapOffsetY = layers.stageOffsetY - GameConfig.renderMapScreenNum + (v - 1) * mapHeight
console.log('renderMapOffsetY:', this.renderMapOffsetY)
}
async didRendered() {
const firstGenerateBox = BoxType.Box6
const currBoxConfig = GameConfig.boxConfig[firstGenerateBox]
const currBoxItem = this.onGenerateBox({
type: firstGenerateBox,
pos: {
x: GameConfig.GameStagePos.x,
y: GameConfig.GameStagePos.y
}
})
this.onGenerateRabbit({
pos: {
x: currBoxItem.x,
y: currBoxItem.y - currBoxConfig.oz
}
})
// await new Promise(r => setTimeout(r, 500))
// TODO 这里的 时序问题记得弄一下
await this.onShowCountDown()
this.onRealGameStart()
isPause: boolean = true
rabbitPos: Pos
rabbitContainer: FYGE.Container // 兔子Container
rabbitCloneContainer: FYGE.Container // 兔子的克隆体 做创屏幕动画的
rabbitBoxMap: number[][] = [] // 兔子地图map
this.initEvents()
set dir(v: number) {
this.rabbitContainer.scaleX = v
this.rabbitCloneContainer.scaleX = v
}
unMount(): void {
this.removeEvents()
}
didRendered(): void {
this.renderMap(true)
/**
* 绑定事件
*/
initEvents() {
if (GameConfig.debugger && document) {
document.body.addEventListener('keydown', (e) => {
if (e.code != "Space") return;
this.onActionDown();
})
}
this.sceneCont?.addEventListener(FYGE.MouseEvent.MOUSE_DOWN, this.onActionDown, this)
this.onGameStart()
}
removeEvents() {
this.sceneCont?.removeAllEventListener()
}
/**
* 按下动作
*/
onActionDown() {
if (this.isPaused || this.isOver) return
this.isPaused = true
this.PlayerOfRabbit.jumpPrepare()
const touchPushObj = this.touchPushObj = {
tl: 0
}
FYGE.Tween.get(touchPushObj)
.to({
tl: GameConfig.maxLen
}, 1600)
.call(() => {
console.log('最远距离了')
})
if (GameConfig.debugger && document) {
document.body.addEventListener('keyup', async () => {
this.onActionUp()
}, {once: true})
onGameStart() {
GameConfig.DecisionLine = [
180,
layers.stageHeight - 10
]
if (GameConfig.debugger) {
this.SceneContainer.addChild(
<DreamContainer inlineProps={{
y: layers.stageOffsetY
}}>
<DreamShape drawData={[0, GameConfig.DecisionLine[0], 750, 4]} />
<DreamShape drawData={[0, GameConfig.DecisionLine[1], 750, 4]} />
</DreamContainer>
)
}
this.sceneCont.once(FYGE.MouseEvent.MOUSE_UP, this.onActionUp, this)
this.isPause = false
}
/**
* 获取当前 跳跃的阶段
* @param fx
*/
onGetCurrJumpIndex(fx: number) {
const DecterList = this.DecisionConfig.list
const _i = DecterList.findIndex(i => i > fx)
return _i
onGameOver() {
FYGE.Tween.removeTweens(this.rabbitContainer)
this.isPause = true
}
/**
* 松开
* 开始渲染地图
* @param init 是否是初始化
*/
async onActionUp() {
const PlayerTarget = this.PlayerTarget
const touchPushObj = this.touchPushObj
renderMap(init: boolean = false) {
// TODO 随机
console.info('=========render map ===========')
const mapConfig = GameConfig.mapList[0]
const {
x: cx,
y: cy,
oz
} = this.CurrBoxItem
FYGE.Tween.removeTweens(touchPushObj)
// TODO TEST
// touchPushObj.tl = Math.random() > 0.5 ? Math.abs(this.GameEleStack.stackHead.x - this.CurrBoxItem.x) : touchPushObj.tl
let tl = Math.abs(PlayerTarget.x + touchPushObj.tl * this.dir - cx)
const _i = this.onGetCurrJumpIndex(tl)
let currTanN = GameConfig.GenerateConfig.tanNum
let py = 0 // 兔子y的值
let mh
const temp = cy - currTanN * tl
if (_i == 1) {
py = temp - oz
} else if (_i == 2) {
py = temp
} else if (_i == 3) {
// success
py = temp - this.GameDtStack.stackHead.oz
rowNum,
offsetYLen
} = GameConfig
const mapBoxes = mapConfig.boxMap
if (init) {
this.renderRabbit(mapConfig.initPos)
} else {
// 跳过了 直接 550 吧
tl = 550
py = cy - currTanN * tl
mh = this.GameEleStack.stackHead.y - this.GameEleStack.stackHead.oz
}
console.log('touchPushObj.tl:', tl, _i)
await this.onActionJump({
offsetX: cx + tl * this.dir,
offsetY: py,
maxH: mh
})
console.log('jumpEnd:', _i)
if (_i == 3) {
this.onJumpSuc()
} else if (_i == 2 || _i == -1) {
this.onGameOver()
this.rabbitPos.y += rowNum
}
}
onJumpSuc() {
console.log('onJumpSuc')
if (this.isWithGift) {
this.DecisionConfig.geleIns.onGetGift()
this.isDrawed = true
} else {
PlayAudio()
this.onAddScore()
}
this.onGenerateBox()
}
isUsed: boolean = false
onGameOver() {
this.isOver = true
let f = Tools.PageData.liveCard
console.log('GameOver')
if (f && !this.isUsed) {
ModalCtroller.showModal(GameResumeModal, {
resumeNum: Tools.PageData.liveCard,
onConfirm: () => {
this.isUsed = true
this.isOver = false
this.PlayerTarget.position.set(
this.CurrBoxItem.x,
this.CurrBoxItem.y - this.CurrBoxItem.oz
)
this.PlayerTarget.parent.addChild(this.PlayerTarget)
BounceOutAni(1000)(this.PlayerTarget)
},
onCancel: this.onShowGameOverModal
})
} else {
this.onShowGameOverModal()
}
}
isDrawed: boolean = false
onDraw() {
return new Promise<void>(async (r) => {
ModalCtroller.showModal(FinalGiftModal, {
onConfirm: async () => {
const {success, data: {type, name, image}} = await sendTbNet(TbNetName.onDrawLottery)
ModalCtroller.closeModal(FinalGiftModal)
if (success) {
if (type != 5) {
ModalCtroller.showModal(DrawSucModal, {
name,
img: image,
onConfirm: () => {
r()
}
})
} else {
ModalCtroller.showModal(DrawFailModal, {
onConfirm: () => {
r()
this.GameMapContainer.addChildAt(
<DreamContainer className="mapContainer" inlineProps={{
y: this.mapCount * rowNum * offsetYLen * -1
}}>
{
mapBoxes.map((rowItem, rowIndex) => {
return (
<DreamContainer inlineProps={{
y: rowIndex * GameConfig.offsetYLen
}}>
{
rowItem.map((colItem, colIndex) => {
// TODO type
return (
colItem ? <Platform type={1} x={colIndex * offsetXLen} /> : undefined
)
})
}
})
}
} else {
r()
}
</DreamContainer>
)
})
}
})
})
</DreamContainer>
, 0)
this.mapCount += 1
this.rabbitBoxMap.unshift(...mapBoxes)
console.log(this.rabbitBoxMap)
}
onShowGameOverModal = async () => {
if (this.isDrawed) {
await this.onDraw()
}
const submitScore = this.ScoreBoardIns.score
const {
success
} = await sendTbNet(TbNetName.submitGame, {
score: submitScore
})
if (success) {
ModalCtroller.showModal(GameOverModal, {
/**
* 渲染兔子,会再来一个clone rabbit
* @param pos
* @returns
*/
renderRabbit(pos: Pos) {
if (this.rabbitContainer) return
// TODO Player 动作集
this.rabbitContainer = this.GameMapContainer.addChild(<RabbitPlayer />)
this.rabbitCloneContainer = this.GameMapContainer.addChild(<RabbitPlayer inlineProps={{
visible: false,
className: 'clone'
}} />)
this.rabbitContainer.position.set(
pos.x * offsetXLen,
pos.y * offsetYLen
)
this.rabbitPos = pos
console.log(this.rabbitContainer)
}
score: submitScore,
})
} else {
sendTbNet(TbNetName.goBackHome)
lastTime: number = 0
onEnterFrame() {
if (this.isPause) return
const now = Date.now()
const st = (now - this.lastTime) / 1000
this.lastTime = now
if (st > 1) {
return
}
this.GameReelContainer.y += GameConfig.speed * st
if (this.GameReelContainer.y >= this.renderMapOffsetY) {
this.renderMap()
}
}
/**
* maxH 跳过了就用这个吧
* @param config
* 获取当前兔子相对于 屏幕的Y
* @returns
*/
async onActionJump(config: {
offsetX: number,
offsetY: number,
maxH?: number
}) {
return new Promise<void>(async(resolve) => {
const PlayerTarget = this.PlayerTarget
this.PlayerOfRabbit.jump()
console.log('jump config:', config)
getCurrRabbitYFromScreen() {
return this.GameReelContainer.y + this.rabbitContainer.y - layers.stageOffsetY
}
if (GameConfig.debugger) {
this.GameEleContainer.addChild(
<DreamShape inlineProps={{
x: config.offsetX,
y: config.offsetY
}} type="circle" drawData={[0,0, 8]} fillColor="#006cf9"></DreamShape>
)
/**
* 游戏场景点击, 用作逻辑处理
*/
@PromiseAwait
onGameSceneClick(e: FYGE.MouseEvent) {
if (this.isPause) return
return new Promise<void>(resolve => {
const screenRY = this.getCurrRabbitYFromScreen()
const {
stageX
} = e
const {
x: rax,
y: ray
} = this.rabbitPos
const {
rabbitBoxMap,
rabbitContainer,
rabbitCloneContainer
} = this
const {
x: rx,
y: ry
} = rabbitContainer
const dir = this.dir = (stageX > 375 ? 1 : -1)
const _willX = rax + dir
const willX = (_willX + GameConfig.boxColNum) % GameConfig.boxColNum
let shouldY = ray - (screenRY < GameConfig.DecisionLine[0] ? 0 : 1)
// console.log('========',shouldY, '\n===stageX===\n', stageX)
while(!rabbitBoxMap[shouldY][willX]) {
shouldY += 1
if (shouldY >= rabbitBoxMap.length - 1) {
break
}
}
// 0-15下蹲 15-25起跳 25-35帧落地 35-50缓冲 30帧每秒
FYGE.Tween.get(PlayerTarget, {
onChange:() => {
const _i = this.onGetCurrJumpIndex(Math.abs(PlayerTarget.x - this.CurrBoxItem.x))
const parentCont = this.GameEleContainer
if (_i == 2 && PlayerTarget._index !== 2) {
PlayerTarget._index = 2
parentCont.addChildAt(PlayerTarget, parentCont.getChildIndex(this.CurrBoxItem))
} else if (_i == -1 && PlayerTarget._index !== -1) {
PlayerTarget._index = -1
parentCont.addChildAt(PlayerTarget, parentCont.getChildIndex(this.GameEleStack.stackHead))
}
// 这里之前提前改,否则会有时序问题
this.rabbitPos = {
x: willX,
y: shouldY
}
FYGE.Tween.removeTweens(rabbitContainer)
if (rax == 4) {
rabbitCloneContainer.visible = true
rabbitCloneContainer.position.set(rabbitContainer.x - 750, rabbitContainer.y)
} else if (rax == 0) {
rabbitCloneContainer.visible = true
rabbitCloneContainer.position.set(rabbitContainer.x + 750, rabbitContainer.y)
}
const sp = shouldY - ray
const downTime = 200 * (sp > 0 ? sp : 1)
FYGE.Tween.get(rabbitContainer, {
onChange: () => {
// rabbitContainer.x = (rabbitContainer.x + 750) % 750
rabbitCloneContainer.x = rabbitContainer.x - 750 * (rax == 0 ? -1 : 1)
}
})
.to({
x: config.offsetX
}, 600)
FYGE.Tween.get(PlayerTarget)
x: _willX * offsetXLen
}, 400 + downTime)
FYGE.Tween.get(rabbitContainer, {
onChange: () => {
rabbitCloneContainer.y = rabbitContainer.y
}
})
.to({
y: Math.min(config.offsetY, PlayerTarget.y, config.maxH || 13300) - 100
y: Math.min(ry + sp * offsetYLen, ry) - 100
}, 400, FYGE.Ease.quadOut)
.to({
y: config.offsetY
}, 200, FYGE.Ease.quadIn)
.wait(300)
y: ry + sp * offsetYLen
}, downTime, FYGE.Ease.quadIn)
// .wait(300)
.call(() => {
this.isPaused = false
PlayerTarget._index = 0 // 初始化一下
// TODO 这里算的有点问题,是不是上面onChang 事件的问题呢?
if (rabbitCloneContainer.x >= -10 && rabbitCloneContainer.x <= 750) {
this.rabbitContainer = rabbitCloneContainer
this.rabbitCloneContainer = rabbitContainer
}
resolve()
})
})
}
/**
* 生成兔子
* @param config
*/
onGenerateRabbit(config: {
pos: Pos
}) {
const {
pos
} = config
this.GameEleContainer.addChild(
<DreamContainer ref={el => {
this.PlayerTarget = el
}} inlineProps={{
x: pos.x,
y: pos.y
}}>
<Player getPlayer={player => {
this.PlayerOfRabbit = player
}}/>
</DreamContainer>
)
}
onAddScore() {
const addScore = this.DecisionConfig.score
this.ScoreBoardIns.score += addScore
this.PlayerOfRabbit.showJumpEndAtom(addScore)
// ModalCtroller.showModal(GameQuitModal, {
// resumeNum: 10,
// score: 999,
// name: '奢华养肤黑霜25g',
// img: 'http://qnpic.top/yoona2.jpg',
// pName: '12123123'
// }, {
// center: true,
// hideCall: fadeOutFactory(100),
// showCall: slideTop(500),
// maskAlpha: 0.8,
// destroy: false
// })
}
onGoBack() {
ModalCtroller.showModal(GameQuitModal,{
pName: '惊喜',
})
}
async onRealGameStart() {
this.onGenerateBox()
}
/**
* 生成Box
* @param config
*/
onGenerateBox(config?: {
type?: BoxType,
pos?: {x: number,y: number}
}) {
const cfg = Object.assign({}, config)
let GenerateItem: FYGE.Container & {oz?: number}
// 这里就给 随机 box BoxTypeList[Math.random() * BoxTypeList.length >> 0]
// part => box
let randNum = Math.random() * GameConfig.totoalPart
cfg.type = cfg.type || GameConfig.PartList.find(item => {
return item.preSumPart > randNum
}).type
const {
type,
pos
} = cfg
const currBoxConfig = GameConfig.boxConfig[type]
if (!pos) {
const stackHeadBox = this.GameEleStack.stackHead
const {x: preX, y: preY} = stackHeadBox
const dir = this.dir = Math.random() > 0.5 ? 1 : -1
// 刷新
const isWithGift = this.isWithGift = this.isCouldHaveGift && Math.random() < GameConfig.finalGiftPart
this.isCouldHaveGift = false
const spaceNum = dir * randomNum(GameConfig.GenerateSpace[0], GameConfig.GenerateSpace[1])
const offsetY = Math.tan(GameConfig.GenerateConfig.angle) * Math.abs(spaceNum)
const tartgetPos = {
x: preX + spaceNum,
y: preY - offsetY
}
GenerateItem = <GameEle ref={(el) => {
this.DecisionConfig.geleIns = el
}} x={tartgetPos.x} y={tartgetPos.y} type={type} isWithGift={isWithGift} />
// 生成下一阶段的判定点位
this.DecisionConfig.list = [
0,
this.GameDtStack.stackHead.dt[1],
Math.abs(tartgetPos.x - stackHeadBox.x) + currBoxConfig.dt[0],
Math.abs(tartgetPos.x - stackHeadBox.x) + currBoxConfig.dt[1]
]
this.DecisionConfig.score = currBoxConfig.addScore
// 记录兔子当前点
this.CurrBoxItem = stackHeadBox
GenerateItem['oz'] = currBoxConfig.oz
const tPos: Pos = {
x: preX + spaceNum / 2,
y: preY - offsetY / 2
}
// 视角移动下
const _GameStageContainer = this.GameStageContainer
const relativePos: Pos = {
x: GameConfig.CameraConfig.pos.x - tPos.x,
y: GameConfig.CameraConfig.pos.y - tPos.y
}
FYGE.Tween.removeTweens(_GameStageContainer)
FYGE.Tween.get(_GameStageContainer)
.to(relativePos, 500)
} else {
GenerateItem = <GameEle x={cfg.pos.x} y={cfg.pos.y} type={type} />
GenerateItem['oz'] = currBoxConfig.oz
}
this.GameEleContainer.addChildAt(GenerateItem, 0)
if (!cfg.pos) {
BounceOutAni(1000)(GenerateItem)
// const oy = GenerateItem.position.y
// GenerateItem.position.y -= 100
// FYGE.Tween.get(GenerateItem)
// .to({
// y: oy
// }, 1000, FYGE.Ease.bounceOut)
GameJudgeFrame() {
if (this.isPause) return
// 当前兔子在屏幕上的 y
const currRabbitOffsetY = this.GameReelContainer.y + this.rabbitContainer.y - layers.stageOffsetY
if (currRabbitOffsetY >= GameConfig.DecisionLine[1]) {
this.onGameOver()
}
this.GameEleStack.pushStack(GenerateItem)
this.GameDtStack.pushStack({
target: GenerateItem,
dt: currBoxConfig.dt,
oz: currBoxConfig.oz
})
return GenerateItem
}
/**
* 游戏倒计时
* @returns
*/
async onShowCountDown() {
const addParentNode = this.sceneCont
return new Promise<void>(resolve => {
const CountDownCont = (
<DreamContainer>
<DreamShape alpha={0.5} />
<DreamLottie lottieData={countDown} ref={el => {
el.play(1, () => {
addParentNode.removeChild(CountDownCont)
resolve()
})
}} inlineProps={{
x: 145, y: 512
}} />
</DreamContainer>
)
addParentNode.addChild(CountDownCont)
})
}
render() {
const bottomAtomRes = RES.getRes('bottomAtom.png')
console.log('render GameScene')
const initReelOffsetY = (mapHeight - layers.stageOffsetY - layers.stageHeight) * -1
console.log('初始化卷轴 offsetY:', initReelOffsetY)
return (
<FYGE.Container>
<DreamContainer ref={(el: any) => {
this.sceneCont = el
}}>
<FYGE.Container inlineProps={{
alpha: 1
}} >
<DreamSpriteV2 src={RES.getRes('back.png')} ></DreamSpriteV2>
</FYGE.Container>
{/* 游戏氛围 */}
<DreamLottie lottieData={GameAtom} inlineProps={{
y: 400
}}/>
<FYGE.Container className="Header">
<ScoreBoard
ref={(el: any) => {
this.ScoreBoardIns = el
}}
inlineProps={{
x: 200,
y: 270
}} />
</FYGE.Container>
{/* 游戏主体 */}
<DreamContainer ref={el => {
this.GameStageContainer = el
<DreamContainer ref={el => this.SceneContainer = el} onEnterFrame={this.GameJudgeFrame.bind(this)} onClick={this.onGameSceneClick.bind(this)}>
<DreamSprite src={RES.getRes('GSB.png')} />
<DreamContainer onEnterFrame={this.onEnterFrame.bind(this)} className="GameReelContainer" ref={el => this.GameReelContainer = el}
inlineProps={{
y: initReelOffsetY
}}
>
<DreamContainer className="GameMapContainer" ref={el => {
this.GameMapContainer = el
}}>
{/* 游戏元素Container */}
<DreamContainer className="GameEleContainer" ref={el => {
this.GameEleContainer = el
}}>
</DreamContainer>
</DreamContainer>
{/* 视角 */}
{
GameConfig.debugger && (
<DreamShape inlineProps={{
x: GameConfig.CameraConfig.pos.x,
y: GameConfig.CameraConfig.pos.y
}} type="circle" drawData={[0,0, 8]} fillColor="#ff2727"></DreamShape>
)
}
<FYGE.Container inlineProps={{
y: 1624 - bottomAtomRes.height
}}>
<DreamSpriteV2 src={bottomAtomRes}></DreamSpriteV2>
</FYGE.Container>
</DreamContainer>
<DreamSprite className="goBackBtn" onClick={this.onGoBack} src={RES.getRes('goBackBtn.png')} inlineProps={{
y: 200
}} />
</FYGE.Container>
<ScoreBoard />
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import Dream from "../../Dream";
import { RES } from "../../modules/RES";
export class Platform extends Dream.RenderContainer<{
type: number // 1 就是默认 2 道具 3 炸弹
x: number
}> {
render() {
const backRes = RES.getRes('platform.png')
return (
<DreamContainer inlineProps={{
x: this.props.x || 0
}}>
<DreamSprite src={backRes} inlineProps={{
x: 2
}} />
</DreamContainer>
)
}
}
\ No newline at end of file
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamLottie } from "../../components/DreamLottie/DreamLottie";
import { DreamSpine, setSpineAni } from "../../components/DreamSpine/DreamSpine";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import Dream from "../../Dream";
import { JumpEnd } from "../../lotties/JumpEnd";
import { PerfectJumpEnd } from "../../lotties/PerfectJumpEnd";
import { fadeOutUpFactory } from "../../modules/animations";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import { getTbSpi } from "../../tools/simpleTools";
import { GameConfig } from "./GameConfig";
export enum PlayAniEnum {
Stand = 'daiji',
StandBy = 'dunxia1',
Jump = 'tiaoyue2'
}
const PlayerAction = {
JUMP: 'tiaoyue2',
STANDBY: 'dunxia1',
STAND: 'daiji'
}
export type PlayerIns = {
turnRound: (dir: 1 | -1) => void
jump: () => Promise<void>
jumpPrepare: () => Promise<void>
showJumpEndAtom: (score: number) => Promise<void>
}
@UsePreload({
preAction: async function() {
if (!window) {
await RES.getResAsync(getTbSpi(), () => {}, null, 'spi')
} else {
await RES.loadGroup('spine')
}
},
loadingComponent: null
})
export class Player extends Dream.RenderContainer<{
getPlayer?: (ins: PlayerIns) => void
export class RabbitPlayer extends Dream.RenderContainer<{
inlineProps?: Record<string, any>
}> {
SpineContainer: FYGE.Container
SpinePlayer: FYGE.Spine
AtomLottie: FYGE.Lottie
aniText: FYGE.TextField
didRendered(): void {
this.props.getPlayer && this.props.getPlayer({
turnRound: (dir) => {
this.SpineContainer.scaleX = dir
},
jump: () => {
return new Promise(r => {
setSpineAni(this.SpinePlayer, PlayerAction.JUMP, 1 , () => {
setSpineAni(this.SpinePlayer, PlayerAction.STAND)
r()
})
})
},
showJumpEndAtom:(score: number) => {
return new Promise(r => {
this.AtomLottie.visible = true
this.aniText.text = `+${score}`
fadeOutUpFactory(500, 100)(this.aniText)
this.AtomLottie.play(1, () => {
this.AtomLottie.visible = false
r()
})
})
},
jumpPrepare: () => {
return new Promise(r => {
setSpineAni(this.SpinePlayer, PlayerAction.STANDBY, 1 , () => {
r()
})
})
}
})
}
render() {
const PlayerSpineData = RES.getRes(!window ? getTbSpi() : 'rabbit.spi', 'spi')
return (
<DreamContainer inlineProps={{
...this.props.inlineProps
...this.props.inlineProps,
anchorX: 75
}}>
<DreamTextField ref={el=> {
this.aniText = el
}} size={32} color="#fad99e" text="+0" textWidth={300} inlineProps={{
y: -210,
x: -150,
alpha: 0
}} ></DreamTextField>
<DreamContainer ref={el => {
this.SpineContainer = el
<DreamContainer inlineProps={{
x: GameConfig.rabbitConfig.offsetX,
y: GameConfig.rabbitConfig.offsetY
}}>
<DreamLottie ref={el => {
this.AtomLottie = el
}} inlineProps={{
x: -125,
y: -230,
visible: false
}} lottieData={JumpEnd} />
<DreamSpine ref={el => {
this.SpinePlayer = el
}} aniName={PlayAniEnum.Stand} spineData={PlayerSpineData} inlineProps={{
y: 10,x: -5
}}></DreamSpine>
<DreamSprite src={RES.getRes('rabbit.png')} />
</DreamContainer>
</DreamContainer>
)
......
import { DreamContainer } from "../../components/DreamContainer/DreamContainer";
import { DreamSprite } from "../../components/DreamSprite/DreamSprite";
import { DreamTextField } from "../../components/DreamTextField/DreamTextField";
import Dream from "../../Dream";
import { layers } from "../../modules/layers";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
@UsePreload({
preAction: async() => {
await RES.loadGroup('FinalGiftModal')
export class ScoreBoard extends Dream.RenderContainer {
_score:number = 0
ScoreText: FYGE.TextField
get score() {
return this._score
}
})
export class FinalGiftModal extends Dream.RenderContainer {
onConfirm() {
this.props.onConfirm()
}
didRendered(): void {
layers.stage.once(FYGE.MouseEvent.CLICK, this.onConfirm, this)
set score(v: number) {
this._score = v
this.ScoreText.text = v + ''
}
render() {
const roleCont = RES.getRes('FGMB.png')
const confirmbtn = RES.getRes('FGM1.png')
const roleCont = RES.getRes('scoreBoardBack.png')
return (
<DreamContainer>
<DreamContainer inlineProps={{
y: layers.stageOffsetY + 50,
x: 375 - roleCont.width / 2
}}>
<DreamSprite src={roleCont} />
<DreamSprite src={confirmbtn} inlineProps={{
x: roleCont.width / 2 - confirmbtn.width / 2,
y: 500
}} />
</DreamContainer>
<DreamTextField ref={el => {
this.ScoreText = el
}} text={this.score + ''} size={36} bold textWidth={roleCont.width} color="#9a4136" textHeight={roleCont.height} />
</DreamContainer>
)
}
}
\ No newline at end of file
export class Stack<T extends any = number> {
list: T[] = []
get stackHead() {
return this.list[this.list.length - 1]
}
pushStack(item: T) {
this.list.push(item)
return item
}
popStack() {
return this.list.pop()
}
traverse(callbackfn: (value: T, index: number, array: T[]) => void) {
const sliceItems = this.list.slice(0)
sliceItems.forEach(callbackfn)
}
}
\ No newline at end of file
......@@ -6,14 +6,11 @@ import Dream from "../../Dream";
import { SceneController } from "../../modules/layers/ctrls";
import { RES } from "../../modules/RES";
import { UsePreload } from "../../modules/UseDecorator/usePreload";
import { BoxType, GameConfig } from "../GameScene/GameConfig";
import { GameScene } from "../GameScene/GameScene";
import { Player } from "../GameScene/Player";
@UsePreload({
async preAction() {
await RES.loadGroup('NewGuyScene')
await RES.loadGroup('Boxes')
}
})
export class NewGuyScene extends Dream.RenderContainer {
......@@ -31,94 +28,24 @@ export class NewGuyScene extends Dream.RenderContainer {
case 1:
this.GuideContainer.addChild(<DreamContainer onClick={nextStep}>
<DreamSprite src={RES.getRes('Guide1.png')} />
<Player inlineProps={{
x: 480,y: 1260, scaleX: -1
}}></Player>
</DreamContainer>)
break
case 2:
const n = RES.getRes('nextStep.png')
const posMap: Partial<Record<BoxType, [number, number]>> = {
[BoxType.Box3]: [130, 300],
[BoxType.Box4]: [420, 300],
[BoxType.Box1]: [40, 540],
[BoxType.Box2]: [280, 540],
[BoxType.Box5]: [500, 540]
}
const mapName = Object.keys(posMap)
this.GuideContainer.addChild(
<DreamContainer onClick={nextStep}>
<DreamShape alpha={0.7} />
<DreamContainer inlineProps={{
y: 160
}}>
{
mapName.map((item: BoxType) => {
const currConfig = GameConfig.boxConfig[item]
return (
<DreamContainer inlineProps={{
x: posMap[item][0],
y: posMap[item][1],
scaleX: 0.8,
scaleY: 0.8
}}>
<DreamSprite src={RES.getRes(currConfig.resName)} />
<DreamTextField text={`+${currConfig.addScore}`} color="#ffffff" inlineProps={{
y: 300
}} textWidth={283} size={fontSize} />
</DreamContainer>
)
})
}
</DreamContainer>
<DreamTextField inlineProps={{
y: 1100
}} text="踩到特殊格子 可获得额外得分" color="#ffffff" textWidth={750} size={32} />
<DreamSprite inlineProps={{
x: 375 - n.width / 2,
y: 1200
}} src={n} />
</DreamContainer>
)
this.GuideContainer.addChild(<DreamContainer onClick={nextStep}>
<DreamSprite src={RES.getRes('Guide2.png')} />
</DreamContainer>)
break
case 3:
const btn = RES.getRes('startGameBtn.png')
this.GuideContainer.addChild(
<DreamContainer onClick={nextStep}>
<DreamShape alpha={0.7} />
<DreamTextField text="踩到特殊道具" color="#ffffff" size={fontSize} textWidth={750} inlineProps={{
y: 700
}} />
<DreamTextField text="获得抽奖机会哦" color="#ffffff" size={fontSize} textWidth={750} inlineProps={{
y: 770
}} />
<DreamSprite src={btn} inlineProps={{
x: 375 - btn.width / 2,
y: 850
}} />
<DreamSprite src={RES.getRes('giftBoxIcon.png')} inlineProps={{
x: 133,
y: 950
}} />
<DreamSprite src={RES.getRes('box6.png')} inlineProps={{
x: 325,
y: 1095
}}></DreamSprite>
<Player inlineProps={{
x: 480,y: 1260, scaleX: -1
}}></Player>
</DreamContainer>
)
this.GuideContainer.addChild(<DreamContainer onClick={nextStep}>
<DreamSprite src={RES.getRes('Guide3.png')} />
</DreamContainer>)
break
case 4:
this.GuideContainer.addChild(<DreamContainer onClick={nextStep}>
<DreamSprite src={RES.getRes('Guide4.png')} />
</DreamContainer>)
break
case 5:
// 完成新手引导
SceneController.changeScene(GameScene)
break
......@@ -134,7 +61,6 @@ export class NewGuyScene extends Dream.RenderContainer {
<DreamContainer ref={el => {
this.SceneContainer = el
}}>
<DreamSprite src={RES.getRes('NGSB.jpg')}></DreamSprite>
<DreamContainer ref={el => {
this.GuideContainer = el
}} ></DreamContainer>
......
......@@ -113,3 +113,49 @@ export function throttleDecorator(time: number = 1000) {
descriptor.value = invokeFunc
}
}
/**
* 只有装饰方法 执行完了之后 才可以第二次执行
* @param target
* @param property
* @param descriptor
*/
export function PromiseAwait(target: any, property: string, descriptor: PropertyDescriptor) {
const func: Function = descriptor.value
// let isPromiseFulfilled = true
let waitPromise: Promise<any> | null = null
let waitPromiseResolve: (value: unknown) => void
descriptor.value = async function(...args:any[]) {
if (waitPromise) return waitPromise
waitPromise = new Promise(resolve => {
waitPromiseResolve = resolve
})
// @ts-ignore
const res = await func.apply(this, args)
waitPromiseResolve(res)
waitPromise = null
return res
}
}
/**
* PromiseAwait 闭包版本
* @param func
* @returns
*/
export function promiseAwaitFunc(func: Function) {
let waitPromise: Promise<any> | null = null
let waitPromiseResolve: (value: unknown) => void
return async function(...args: any[]) {
if (waitPromise) return waitPromise
waitPromise = new Promise(resolve => {
waitPromiseResolve = resolve
})
// @ts-ignore
const res = await func.apply(this, args)
waitPromiseResolve(res)
waitPromise = null
return res
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment