基于React Native 的 跨三端(Android、iOS、Web)配对游戏
目录
第一章 需求分析和功能
我们知道现在有很多小游戏,但是这些小游戏要么只能Android运行,要么只能iOS运行,要么只能Web端运行。所以我想到了,要是能一次性编码解决跨端游戏开发就好了。
于是我就用React -Native来实现此次跨端小游戏的开发。
跨端小游戏的功能很简单,我主要实现游戏卡片的配对并计数。
刘海屏和全面屏底部的兼容
首先是头部的title,由于不能影响到有的刘海屏手机,所以我们要进行兼容考虑。
主页面中的图片反转业务逻辑
如果两次翻转的不一样,就会使两个图片还原,并统计次数。
如果全部翻转完了,进行关卡升级,增加图片个数。
第二章 框架架构和编码实现
框架架构
本项目是基于React-Native,所以首先需要进行React-Native环境配置(nodejs和react-native)
然后我们需要初始化一个React-Native项目
npx react-native init MatchingGame
- App.js 进行项目主要数据、逻辑、组件、样式的引入和实现
- Card.js 代表翻转的卡片组件,以备之后调用
之后我们在React-Native框架上进行开发就好啦
React-Native 简略讲解
React-Native是基于React.JS的移动开发框架,使用React.JS能够实现通过Javascript一次开发多端运行。
1. React-Native数据流基于MVVM、框架基于React
- MVVM
Model层代表数据模型,View代表UI组件,ViewModel是View和Model层的桥梁,数据会绑定到viewModel层并自动将数据渲染到页面中,视图变化的时候会通知viewModel层更新数据。 - React
React是Javascript的构建页面的框架
2. React实现方式
编程语言是JSX
JSX是综合HTML和JS的编程方式,也就是能够在JS语言中使用HTML,JSX在编译时会自动转成JS
React开发组件
父组件可以调用子组件
例如本项目就在header组件下面、footer上面也就是main组件中间插入Card卡片组件
也就是:
<View style={
styles.main }>
<View style={
styles.gameBoard }>
{
this.state.cardSymbolsInRand.map((symbol, index) => {
return (
<Card
key={
index }
onPress={
() => this.cardPressHandler(index) }
style={
styles.button }
fontSize={
30 }
title={
symbol }
cover="❓"
isShow={
this.state.isOpen[index] }
/>
)
})
}
</View>
</View>
而这里Card组件创建如下
class Card extends Component {
render () {
return (
<TouchableOpacity onPress={
this.props.onPress } style={
{
...this.props.style }}>
{
/* TouchableOpacity:点击时,有半透明的回馈 */}
<Text
style={
{
fontSize: this.props.fontSize || 32 }}
>{
this.props.isShow ? this.props.title : this.props.cover }</Text>
</TouchableOpacity>
)
}
}
3.React数据流
类似事件捕获,数据流是自上而下单向地从父节点传递到子节点,所以组件是简单且容易把握的,他们只需要从父节点提供的props中获取数据并渲染即可。如果顶层组件的某个prop改变了,React会递归地向下遍历整棵组件数,重新渲染所有使用这个属性的组件。
改变组件样式的props属性
props类似于css的属性,它是组件里面的属性,能够从父组件中进行修改
例如card里面的Text组件里面就有之前我们引入的TouchableOpacity组件的属性
<TouchableOpacity onPress={
this.props.onPress } style={
{
...this.props.style }}>
{
/* TouchableOpacity:点击时,有半透明的回馈 */}
<Text
style={
{
fontSize: this.props.fontSize || 32 }}
>{
this.props.isShow ? this.props.title : this.props.cover }</Text>
</TouchableOpacity>
能够进行组件事件响应从而改变数据的state事件(view-model层)
例如本项目的图标点击事件
从view视图层绑定的监听事件触发过后能够传给view-model层,cardPressHandler函数就是这个view-model层,进行通过this.setState({ })
进行数据修改。
// 每一次点击图标的事件
cardPressHandler = (index) => {
let isOpen = [...this.state.isOpen]
// 如果点击的是已被翻开的图标,不执行后续代码
if (isOpen[index]) {
return
}
isOpen[index] = true
if (this.state.firstPickedIndex == null && this.state.secondPickedIndex == null) {
this.setState({
isOpen,
firstPickedIndex: index
})
} else if (this.state.firstPickedIndex != null && this.state.secondPickedIndex == null) {
this.setState({
isOpen,
secondPickedIndex: index
})
}
this.setState({
steps: this.state.steps + 1
})
}
事件触发后进行DOM更新
这是一个React组件实现组件可交互所需的流程,
- render()输出虚拟DOM,
- 虚拟DOM转为DOM,
- 再在DOM上注册事件,
- 事件触发setState()修改数据,
- 在每次调用setState方法时,React会自动执行render方法来更新虚拟DOM,如果组件已经被渲染,那么还会更新到DOM中去。
在本项目中:我们首先render输出了集有各种组件的虚拟DOM,然后进行虚拟DOM到DOM的转换,然后绑定按钮监听事件cardPressHandler
,事件触发后通过setState修改数据,然后进行更新
4.组件的生命周期
- 本项目涉及生命周期的地方有:
- 初次载入界面渲染过后对卡片顺序进行打乱也就是通过
componentDidMount ()
进行卡片顺序打乱
initGame = () => {
let newCardsSymbols = [...this.state.cardSymbols, ...this.state.cardSymbols]
// 将 16 个 emoji 的顺序打乱
let cardSymbolsInRand = this.shuffleArray(newCardsSymbols)
// 存储打开状态
let isOpen = []
for (let i = 0; i < newCardsSymbols.length; i++) {
isOpen.push(false)
}
this.setState({
cardSymbolsInRand,
isOpen
})
}