选用的游戏框架
egret
为什么选egret?因为目前看来比较成熟,社区活跃度也有。
react 基础框架如何引入egret
引入库
手动引入egret的库 放在了libs/modules/目录下,在index.html中引入
<script src="../libs/modules/egret/egret.js"></script>
<script src="../libs/modules/egret/egret.web.js"></script>
<script src="../libs/modules/game/game.js"></script>
<script src="../libs/modules/tween/tween.js"></script>
<script src="../libs/modules/assetsmanager/assetsmanager.js"></script>
<script src="../libs/modules/promise/promise.js"></script>
创建游戏
创建一个游戏需要有dom元素,如下代码中className为egret-player的DOM元素。
点击开始游戏,调用egret.runEgret的方法开始,这只是demo,在正常的游戏开发中,开始游戏的按钮和游戏页面经常不在一个页面里,所以这个部分的代码&逻辑按需求放到对应的地方。
import React from 'react'
import './index.scss'
import Main from '@/game/Main'
class Game extends React.Component {
componentDidMount() {
egret.registerClass(Main, 'Main')
window['Main'] = Main
}
start = () => {
egret.runEgret({ renderMode: 'webgl', audioType: 0 })
}
render() {
return (
<div>
<div onClick={this.start}>开始游戏</div>
<div
className="egret-player game-demo"
data-entry-class="Main"
data-orientation="auto"
data-scale-mode="noScale"
data-frame-rate="60"
data-content-width="640"
data-content-height="960"
data-show-paint-rect="true"
data-multi-fingered="2"
data-show-fps="true"
data-show-log="false"
data-log-filter=""
data-show-fps-style="x:0,y:0,size:20,textColor:0x00c200,bgAlpha:0.8"
/>
</div>
)
}
}
export default Game
注意的tips:
对应react网页应用来说,期望的是根据路由能够控制页面的生命周期,但是由于目前的用的egret不支持销毁重新开始,所以多次玩游戏的,只是把游戏页面隐藏再展示。也就是说以下代码的Game class需要被放到最外层的App.tsx里面直接渲染。然后在Game页根据当前的URL来判断是否展示游戏。
import React from 'react'
import { withRouter, RouteComponentProps } from 'react-router-dom'
import Main from '@/game/Main'
import { gameState } from './GameConfig'
import './index.scss'
class Game extends React.Component<RouteComponentProps> {
componentDidMount() {
egret.registerClass(Main, 'Main')
// tslint:disable-next-line:no-string-literal
window['Main'] = Main
}
render() {
const { history } = this.props
const isHidden = !history.location.pathname.includes('/game')
if (isHidden && gameState.clearGame) {
gameState.clearGame()
}
return (
<div
className="egret-player game-demo"
data-entry-class="Main"
data-orientation="portrait"
data-scale-mode="noScale"
data-frame-rate="60"
data-content-width="640"
data-content-height="960"
data-show-paint-rect="true"
data-multi-fingered="1"
data-show-fps="false"
data-show-log="false"
data-log-filter=""
data-show-fps-style="x:0,y:0,size:20,textColor:0x00c200,bgAlpha:0.8"
hidden={isHidden}
/>
)
}
}
export default withRouter(Game)
手机浏览器兼容
使用rem
目前设计师是按照375*609设计的,所以使用rem的方式就如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello World</title>
<meta name="viewport" content="width=device-width,initial-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" />
<script>
;(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'onorientationchange' in window ? 'onorientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth
if (!clientWidth) return
if (clientWidth >= 375) {
docEl.style.fontSize = '100px'
} else {
docEl.style.fontSize = 100 * (clientWidth / 375) + 'px'
}
}
if (!doc.addEventListener) return
win.addEventListener(resizeEvt, recalc, false)
doc.addEventListener('DOMContentLoaded', recalc, false)
})(document, window)
</script>
</head>
<body>
<div id="root"></div>
</body>
</html>
px转rem
使用了 postcss-loader 和 postcss-plugin-px2rem
postcss.config.js的配置如下:
module.exports = {
plugins: [
require('autoprefixer')(),
require('cssnano')(),
require('postcss-plugin-px2rem')({
remValue: 200,
mediaQuery: true,
propBlackList:['font-size'],
exclude: /(node_module)/,
}),
],
}
propBlackList:['font-size’]
这是为了排除font-size被转成rem,但是后面考虑到适配不同的手机,font-size如果不转的话,会出现有些地方字体太小或太大,所以后来删掉了。
其他
- enzyme + jest测试框架
- husky加Git hook
- stylelint样式风格检查
- tslint代码风格检查
- babel + webpack编译打包(区分不同的环境)
基础的代码框架在egret-react-framework