LoginSignup
1
0

More than 3 years have passed since last update.

React Native ゲーム開発 Whack-A-Mole(もぐらたたき) 第二回

Last updated at Posted at 2020-04-21

Whack-A-Mole(もぐらたたき) 第二回

フロントエンジニアの、YAMATAKUです。
前回、ベースUIの実装まで行いました。今回は、ゲームの核である「もぐら」の実装をしていきます。

もぐらクラス作成

Mole.js

import React, { Component } from 'react';
import { 
  View,
  StyleSheet,
  Button,
  Image,
  TouchableWithoutFeedback
} from 'react-native';
import Images from './assets/Images';
import SpriteSheet from 'rn-sprite-sheet';
import Constants from './Constants';

export default class Mole extends Component {
  constructor(props) {
    super(props);

    this.mole = null;
  }

  pop = () => {
    this.isPopping = true;
    this.mole.play({
      type: "appear",
      fps: 24,
      onFinish: () => {
        this.actionTimeout = setTimeout(() => {
          this.mole.play({
            type: "hide",
            fps: 24,
            onFinish: () => {
              this.isPopping= false;
              this.props.onFinishPopping(this.props.index);
            }
          })
        }, 1000);
      }
    })
  }

  whack = () => {

  }

  render() {
    return (
      <View style={{flex: 1}}>
        <SpriteSheet
          ref={ref => (this.mole = ref)}
          source={Images.sprites}
          columns={6}
          rows={8}
          width={100}
          animations={{
            idle: [0],
            appear: [1, 2, 3, 4],
            hide: [4, 3, 2, 1, 0],
            dizzy: [36, 37, 38],
            faint: [42, 43, 44, 0],
            attack: [11, 12, 13, 14, 15, 16],
            heal: [24, 25, 26, 27, 28, 29, 30, 31, 32, 33],å
          }}
        />
        <TouchableWithoutFeedback onPress={this.whack} style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0}}>
          <View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0}} />
        </TouchableWithoutFeedback>
      </View>
    )
  }
} 

App.js修正

App.js

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React, { Component } from "react";

// 省略 //

import Mole from './Mole';

const DEFAULT_TIME = 20;
const DEFAULT_STATE = {
  // 省略 //
}

export default class MainScreen extends Component {
  constructor(props){
    super(props);
    this.state = DEFAULT_STATE;
    this.moles = [];
    this.molesPopping = 0;
    this.interval = null;
    this.timeInterval = null;
  }

  componentDidMount = () => {
    //setStateで状態更新、第2引数はcallback関数
    this.setState(DEFAULT_STATE, this.setupTicks);  
  }

  setupTicks = () => {
    //もぐらの更新スピード決定
    let speed = 750 - (this.state.level * 50);
    if (speed < 350) {
      speed = 350;
    }

    //もぐら更新スタート
    this.interval = setInterval(this.popRanndomMole, speed);

    //時間カウントスタート
    this.timeInterval = setInterval(this.timerTick, 1000);
  }

   //もぐら位置抽選
  randomBetween = (min, max) => {
    return Math.floor(Math.random() * (max - min + 1) + min);
  }

  //もぐらアクション終了で表示もぐらカウントをマイナス
  onFinishPopping = (index) => {
    this.molesPopping -= 1;
  }

  //表示するもぐら抽選して表示
  popRanndomMole = () => {
    //12匹の準備ができているかチェック
    if (this.moles.length != 12) {
      return;
    }

    let randomIndex = this.randomBetween(0, 11);  //表示もぐら抽選
    //当選したもぐら位置が非表示かつ、表示中のもぐらが3匹以下なら表示する
    if (!this.moles[randomIndex].isPopping && this.molesPopping < 3) {
      this.molesPopping += 1;
      this.moles[randomIndex].pop();
    }
  }

  //時間更新
  timerTick = () => {
    if (this.state.time === 0) {
      clearInterval(this.interval);
      clearInterval(this.timeInterval);
      this.setState({
        cleared: true
      })
    }
    else {
      this.setState({
        time: this.state.time - 1
      })
    }

  }

  render() {
    let healthBarWidth = (Constants.MAX_WIDTH - Constants.XR * 100 - Constants.XR * 60 - Constants.XR * 6) * this.state.health / 100;
    return (
      <View style={styles.container}>
        <Image style={styles.backgroundImage} resizeMode="stretch" source={Images.background} />
        <View style={styles.topPanel}>
          <SafeAreaView >
            // 省略 // 
          </SafeAreaView>
        </View>
        <View style={styles.playArea}>

          {//縦に4段
          Array.apply(null, Array(4)).map((el, rowIdx) => {
            return (
              <View style={styles.playRow} key={rowIdx}>
                {//横に3列
                Array.apply(null, Array(3)).map((el, colIdx) => {
                  let moleIdx = (rowIdx * 3) + colIdx;

                  return (
                    <View style={styles.playCell} key={colIdx}>
                      <Mole
                        index={moleIdx}
                        ref={(ref) => { this.moles[moleIdx] = ref }}
                        onFinishPopping={this.onFinishPopping}
                      />
                    </View>
                  )
                })}
              </View>
            )
          })}
        </View>
      </View> 
    )
  }
 }

const styles = StyleSheet.create({

// 省略 //

  playArea: {
    width: Constants.MAX_WIDTH,
    marginTop: Constants.YR * 250,
    height: Constants.MAX_HEIGHT - Constants.YR * 250 - Constants.YR * 112,
    flexDirection: 'column',
  },
  playRow: {
    height: (Constants.MAX_HEIGHT - Constants.YR * 250 - Constants.YR * 112) / 4,
    width: Constants.MAX_WIDTH,
    flexDirection: 'row',
  },
  playCell: {
    width: Constants.MAX_WIDTH / 3,
    height: (Constants.MAX_HEIGHT - Constants.YR * 250 - Constants.YR * 112) / 4,
    alignItems: 'center'
  }
})

確認

$ react-native run-android

タイトルなし.gif

もぐらがアニメーションして現れます。
次回の記事で、もぐらを叩く機能を実装してゲーム完成させようと思います。

おまけ

今回、TEAM用に新しくGitHubアカウントを開設しましたが、自分のMacで作成した鍵が、別のGitHubと衝突したため、以下の様な設定を行いましたので、メモとして残します。

以下、Macの場合

1. 鍵作成(hogeは適宜置き換え)
$ ssh-keygen -f ~/.ssh/hoge_key

2. Gitにhoge_keyを登録

3. 設定ファイル修正
$ vi  ~/.ssh/config 

host github.hogehoge.com
 HostName github.com
 IdentityFile ~/.ssh/hoge_key
 User git
 TCPKeepAlive yes
 IdentitiesOnly yes

//保存
:wq + Enter

//適用
$ source ~/.ssh/config 

[設定完了]

・remote addの場合
$ git remote add origin git@github.hogehoge.com:******/******.git

・cloneの場合
$ git clone git@github.hogehoge.com:******/******.git

これで、複数のGitHubの設定が有効になり、リモート操作も可能になります

すいません、Windowの場合も基本は同じだと思われます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0