Skip to content

Instantly share code, notes, and snippets.

@moduscreate
Created August 7, 2017 17:18
Show Gist options
  • Save moduscreate/417911e6ec522e3a2947391e0f0cc03c to your computer and use it in GitHub Desktop.
Save moduscreate/417911e6ec522e3a2947391e0f0cc03c to your computer and use it in GitHub Desktop.
Full file for React Native Shooter, EVADE (prototype).
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Dimensions,
PanResponder
} from 'react-native';
const dimensions = Dimensions.get('window'),
halfScreenWidth = dimensions.width / 2;
var {
MCModPlayerInterface
} = require('NativeModules');
import GLOBALS from './Globals';
import Enemy from './Enemy';
import Boss1 from './Boss1';
import Boss2 from './Boss2';
import Boss3 from './Boss3';
import EnemyBullet from './EnemyBullet';
//import Controller from './Controller';
import Starfield from './Starfield';
import Player from './Player';
import PlayerBullet from './PlayerBullet';
import StatusBar from './StatusBar';
export default class EVADE extends Component {
enemies = [];
enemyBullets = [];
/* Used to track multi-touch gestures */
movePlayerX = null;
movePlayerY = null;
movePlayer = true;
numTouches = -1; // -1 not touching, 1: One finger fire laser, 2: double touch -> fire blast!
constructor(props) {
super(props);
this.state = {};
}
respondTrue = (evt, gestureState) => true;
componentWillMount() {
this.panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder : this.respondTrue,
onStartShouldSetPanResponderCapture : this.respondTrue,
onMoveShouldSetPanResponder : this.respondTrue,
onMoveShouldSetPanResponderCapture : this.respondTrue,
onPanResponderGrant : this.onPanResponderGrant,
onPanResponderMove : this.onPanResponderMove,
onPanResponderTerminationRequest : this.respondTrue,
onPanResponderRelease : this.onPanResponderRelease,
onPanResponderTerminate : this.onPanResponderRelease
})
}
onPanResponderGrant = (evt, gestureState) => {
const { nativeEvent } = evt,
{
identifier,
touches
} = nativeEvent;
if (identifier > 2) {
return;
}
this.numTouches = touches.length
if (! this.movePlayerTouchID) {
this.movePlayerTouchID = identifier;
this.movePlayerX = gestureState.x0;
this.movePlayerY = gestureState.y0;
}
else if (identifier == this.movePlayerTouchID) {
this.movePlayerX = gestureState.moveX;
this.movePlayerY = gestureState.moveY;
}
}
onPanResponderMove = (evt, gestureState) => {
// console.log(JSON.stringify(gestureState, null,4))
// The most recent move distance is gestureState.move{X,Y}
// The accumulated gesture distance since becoming responder is
// gestureState.d{x,y}
const { nativeEvent } = evt,
{
identifier,
touches
} = nativeEvent;
if (identifier > 2) {
return;
}
this.numTouches = touches.length
if (identifier == this.movePlayerTouchID) {
this.movePlayerX = gestureState.moveX;
this.movePlayerY = gestureState.moveY;
}
}
onPanResponderRelease = (evt, gestureState) => {
// The user has released all touches while this view is the
// responder. This typically means a gesture has succeeded
const { nativeEvent } = evt,
{
identifier,
touches
} = nativeEvent;
if (identifier > 2) {
return;
}
this.numTouches = touches.length
if (identifier == this.movePlayerTouchID) {
this.movePlayerTouchID = null;
this.movePlayerX = null;
this.movePlayerY = null;
}
}
componentDidMount() {
setTimeout(this.run, 10);
}
handleControls() {
var buttonState = this.buttonState,
player = this.player;
if (buttonState.up) {
player.moveUp();
}
if (buttonState.down) {
player.moveDown();
}
if (buttonState.left) {
player.moveLeft();
}
if (buttonState.right) {
player.moveRight()
}
if (buttonState.fireA) {
player.fireA();
}
if (buttonState.fireB) {
player.fireB();
}
}
checkImpactOnPlayer(enemyBullet, player) {
if (enemyBullet.checkImpact(player)) {
player.takeDamage();
GLOBALS.LIVES_REMAIN--;
MCModPlayerInterface.sfx('explodePlayer', true);
if (GLOBALS.LIVES_REMAIN < 0) {
GLOBALS.GAME_OVER_FRAME = GLOBALS.CURRENT_FRAME;
console.log('GAME OVER!')
}
else {
this.statusBar.updateLives();
}
}
}
updateScore(newScore) {
if (newScore > GLOBALS.PLAYER_SCORE) {
GLOBALS.PLAYER_SCORE = newScore;
this.statusBar.updateScore();
}
}
stepPlayer() {
var playerScore = GLOBALS.PLAYER_SCORE;
const { player, playerBullet1, playerBullet2 } = this;
player.update();
// If touch is happening, and the player is not dead and hte player is not dying and the last life is not lost
if (this.movePlayerTouchID && ! player.isDead && player.dying == 0 && GLOBALS.GAME_OVER_FRAME == -1) {
player.stepTo(this.movePlayerX, this.movePlayerY);
let {x, y, halfHeight, halfWidth} = player,
shootX = x + halfWidth,
shootY = y + halfHeight;
if (! playerBullet1.isVisible()) {
playerBullet1.shoot(shootX, shootY);
}
// if (! playerBullet2.isVisible() && GLOBALS.CURRENT_GUN_CHARGE >= GLOBALS.GUN_SHOT_COST) {
// playerBullet2.shoot(x + halfWidth, y + halfHeight);
// GLOBALS.CURRENT_GUN_CHARGE -= GLOBALS.GUN_SHOT_COST;
// if (GLOBALS.CURRENT_GUN_CHARGE < 0) {
// GLOBALS.CURRENT_GUN_CHARGE = 0;
// }
// }
}
playerBullet2.update();
playerBullet1.update();
// Handle score
if (GLOBALS.CURRENT_FRAME % GLOBALS.PLAYER_POINT_FRAME_MOD == 0) {
playerScore++;
}
// Handle gun charge stuff.
this.handleGunRecharge();
}
stepEnemies() {
var playerScore = GLOBALS.PLAYER_SCORE;
const { player, playerBullet1, playerBullet2 } = this;
const { boss1, boss2, boss3, boss1Bullet } = this;
/* Handle enemies */
var numVisibleEnemies = 0;
this.enemies.forEach((enemy, index) => {
const enemyBullet = this.enemyBullets[index];
if (playerBullet1.checkImpact(enemy)) {
playerBullet1.hide();
playerScore += GLOBALS.BULLET1_DAMAGE;
let isDead = enemy.takeDamage(GLOBALS.BULLET1_DAMAGE);
if (isDead) {
GLOBALS.NUM_KILLS++;
playerScore += GLOBALS[enemy.healthType];
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
if (playerBullet2.checkImpact(enemy)) {
playerBullet2.hide();
playerScore += GLOBALS.BULLET2_DAMAGE;
let isDead = enemy.takeDamage(GLOBALS.BULLET2_DAMAGE);
if (isDead) {
GLOBALS.NUM_KILLS++;
playerScore += GLOBALS[enemy.healthType];
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
var shouldShoot = enemy.update();
if (shouldShoot) {
let {x, y, halfHeight, width} = enemy;
enemyBullet.shoot(x, y + halfHeight);
}
enemyBullet.update();
this.checkImpactOnPlayer(enemyBullet, player);
if (enemy.isVisible()) {
numVisibleEnemies++;
}
});
this.updateScore(playerScore);
GLOBALS.NUM_VISIBLE_ENEMIES = numVisibleEnemies;
}
// TODO: Split Step() into 3 functions: stepPlayer, stepEnemies, stepBosses
stepBoss() {
const { GAME_LEVEL, NUM_VISIBLE_ENEMIES, BOSS_LEVEL } = GLOBALS;
const allEnemiesDead = NUM_VISIBLE_ENEMIES == 0;
const {
boss1,
boss2,
boss3,
boss1Bullet,
player,
playerBullet1,
playerBullet2
} = this;
boss1Bullet.update();
this.checkImpactOnPlayer(boss1Bullet, player);
if (GLOBALS.BOSS_LEVEL == 0 || allEnemiesDead == false) {
return;
}
var playerScore = GLOBALS.PLAYER_SCORE;
// if (noVisibleEnemies) {
// bossToSpawn = 1;
// }
// else if (GLOBALS.GAME_LEVEL == 2 && allEnemiesDead) {
// bossToSpawn = 2;
// }
// else if (GLOBALS.GAME_LEVEL == 3 && allEnemiesDead) {
// bossToSpawn = 3;
// }
/* Handle bosses */
// TODO: REfactor so it's not so much copy/paste code!!!! -- JG
if (BOSS_LEVEL == 1) {
let shouldShoot = boss1.update();
if (shouldShoot) {
let {x, y, halfHeight, width} = boss1;
boss1Bullet.shoot(x, y + halfHeight);
}
if (boss1.inPlay) {
if (playerBullet1.checkImpact(boss1)) {
playerScore += GLOBALS.BULLET1_DAMAGE;
let isDying = boss1.takeDamage(GLOBALS.BULLET1_DAMAGE);
if (isDying) {
playerScore += GLOBALS.BOSS_1_HEALTH;
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
if (playerBullet2.checkImpact(boss1)) {
playerScore += GLOBALS.BULLET2_DAMAGE;
let isDying = boss1.takeDamage(GLOBALS.BULLET2_DAMAGE);
if (isDying) {
playerScore += GLOBALS.BOSS_1_HEALTH;
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
}
if (boss1.isDead && boss1.dying == 0) {
console.log('BOSS1 Is dead!!')
GLOBALS.BOSS_ALIVE = false;
GLOBALS.GAME_LEVEL++;
GLOBALS.NUM_KILLS = 0;
GLOBALS.BOSS_LEVEL = 0;
GLOBALS.STOP_SPAWNING_ENEMIES = false;
}
}
else {
boss1.offScreen = true;
boss1.hide();
}
if (GAME_LEVEL == 2) {
let shouldShoot = boss2.update();
if (shouldShoot) {
let {x, y, halfHeight} = boss2;
boss1Bullet.shoot(x, y + halfHeight);
}
if (boss2.inPlay) {
if (playerBullet1.checkImpact(boss2)) {
playerScore += GLOBALS.BULLET1_DAMAGE;
let isDying = boss2.takeDamage(GLOBALS.BULLET1_DAMAGE);
if (isDying) {
playerScore += GLOBALS.BOSS_1_HEALTH;
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
if (playerBullet2.checkImpact(boss2)) {
playerScore += GLOBALS.BULLET2_DAMAGE;
let isDying = boss2.takeDamage(GLOBALS.BULLET2_DAMAGE);
if (isDying) {
playerScore += GLOBALS.BOSS_2_HEALTH;
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
}
if (boss2.isDead && boss2.dying == 0) {
console.log('BOSS2 Is dead!!')
GLOBALS.BOSS_ALIVE = false;
GLOBALS.GAME_LEVEL++;
GLOBALS.NUM_KILLS = 0;
GLOBALS.BOSS_LEVEL = 0;
GLOBALS.STOP_SPAWNING_ENEMIES = false;
}
}
else {
boss2.offScreen = true;
boss2.hide();
}
// TODO: Needs 2x bullets!
if (GAME_LEVEL == 3) {
let shouldShoot = boss3.update();
if (shouldShoot) {
let {x, y, halfHeight} = boss3;
boss1Bullet.shoot(x, y + halfHeight);
}
if (boss3.inPlay) {
if (playerBullet1.checkImpact(boss3)) {
playerScore += GLOBALS.BULLET1_DAMAGE;
let isDying = boss3.takeDamage(GLOBALS.BULLET1_DAMAGE);
if (isDying) {
playerScore += GLOBALS.BOSS_3_HEALTH;
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
if (playerBullet2.checkImpact(boss3)) {
playerScore += GLOBALS.BULLET2_DAMAGE;
let isDying = boss3.takeDamage(GLOBALS.BULLET2_DAMAGE);
if (isDying) {
playerScore += GLOBALS.BOSS_3_HEALTH;
MCModPlayerInterface.sfx('explodeEnemy', true);
}
}
}
if (boss3.isDead && boss3.dying == 0) {
console.log('BOSS3 Is dead!!')
GLOBALS.BOSS_ALIVE = false;
GLOBALS.NEXT_ITERATION_FRAME = GLOBALS.CURRENT_FRAME;
GLOBALS.GAME_LEVEL++;
GLOBALS.NUM_KILLS = 0;
GLOBALS.BOSS_LEVEL = 0;
GLOBALS.STOP_SPAWNING_ENEMIES = false;
}
}
else {
// if (boss3.isDead && boss3.dying == 0) {
// console.log('BOSS3 is f\'ing dead')
// GLOBALS.BOSS_ALIVE = false;
// GLOBALS.GAME_LEVEL = 4;
// GLOBALS.NUM_KILLS = 0;
// boss3.hide();
// }
// boss3.updateDeathSequence();
// boss3.offScreen = true;
// boss3.update();
// boss3.hide();
}
// if (playerScore > GLOBALS.PLAYER_SCORE) {
// GLOBALS.PLAYER_SCORE = playerScore;
// this.statusBar.updateScore();
// }
this.updateScore(playerScore);
}
handleGunRecharge() {
if (GLOBALS.CURRENT_FRAME % 5 == 0 && GLOBALS.CURRENT_GUN_CHARGE < GLOBALS.MAX_GUN_CHARGE) {
GLOBALS.CURRENT_GUN_CHARGE++;
if (GLOBALS.CURRENT_GUN_CHARGE > GLOBALS.MAX_GUN_CHARGE) {
GLOBALS.CURRENT_GUN_CHARGE = GLOBALS.MAX_GUN_CHARGE;
}
this.statusBar.updatePewBar();
}
}
run = () => {
if (GLOBALS.GAME_IN_PLAY) {
GLOBALS.CURRENT_FRAME++;
// var playerScore = GLOBALS.PLAYER_SCORE;
const player = this.player,
gameLevel = GLOBALS.GAME_LEVEL;
this.starfield.step();
this.stepPlayer();
if (gameLevel == 1 && GLOBALS.NUM_KILLS >= GLOBALS.BOSS1_MIN_KILLS) {
GLOBALS.BOSS_LEVEL = 1;
GLOBALS.STOP_SPAWNING_ENEMIES = true;
}
else if (gameLevel == 2 && GLOBALS.NUM_KILLS >= GLOBALS.BOSS2_MIN_KILLS) {
GLOBALS.BOSS_LEVEL = 2;
GLOBALS.STOP_SPAWNING_ENEMIES = true;
}
else if (gameLevel == 3 && GLOBALS.NUM_KILLS >= GLOBALS.BOSS3_MIN_KILLS) {
GLOBALS.BOSS_LEVEL = 3;
GLOBALS.STOP_SPAWNING_ENEMIES = true;
}
else if (gameLevel == 4) {
if (GLOBALS.CURRENT_FRAME - GLOBALS.NEXT_ITERATION_FRAME >= 200) {
GLOBALS.GAME_IN_PLAY = false;
return;
}
}
else {
GLOBALS.BOSS_LEVEL = 0;
}
if (gameLevel < 4) {
this.stepEnemies();
this.stepBoss();
}
// Handle the countdown to the last few frames
if (GLOBALS.GAME_OVER_FRAME > -1) {
if (GLOBALS.CURRENT_FRAME - GLOBALS.GAME_OVER_FRAME >= 150) {
GLOBALS.GAME_IN_PLAY = false;
}
}
requestAnimationFrame(this.run);
}
else {
console.log('GLOBALS.GAME_LEVEL', GLOBALS.GAME_LEVEL)
if (GLOBALS.GAME_LEVEL < 4) {
console.log("GAME OVER!!!")
}
else {
console.log('NEXT Level!!')
}
}
}
buttonState = {
up : false,
down : false,
left : false,
right : false,
fireA : false,
fireB : false
}
onPress = (buttonType, pressed) => {
this.buttonState[buttonType] = pressed;
// this.setState({
// info : JSON.stringify(this.buttonState, null, 4)
// })
}
render() {
var enemies = [],
enemyBullets = [];
for (var i = 0; i < GLOBALS.MAX_ENEMIES; i++) {
enemies.push(<EnemyBullet speed={20} bulletType={3} key={`enemyBullet${i}`} ref={c => this.enemyBullets.push(c) }/>);
enemies.push(<Enemy key={`enemy${i}`} ref={c => this.enemies.push(c)}/>);
}
const statusBarStyle = {
height : GLOBALS.STATUS_BAR_HEIGHT,
// backgroundColor : 'rgba(0,0,255,.3)',
width : dimensions.width,
position : 'absolute',
top : 0,
left : 0
}
return (
<View style={styles.container}>
{/* Top section for lives, charge meter, score, pause button */}
<StatusBar style={statusBarStyle} ref={c => this.statusBar = c} />
{/* Rest of the gameboard. Player, enemies, bosses, Starfield */}
<View style={{flex:1}} {...this.panResponder.panHandlers}>
<Starfield ref={c => this.starfield = c}/>
{/*
<View style={{backgroundColor : 'rgba(255, 255, 255, .01)', height : 225, width : dimensions.width}}>
<Text style={{fontSize: 15, color : '#FFF'}}>
{this.state.info || ''}
</Text>
</View>
*/}
<PlayerBullet bulletType={1} speed={25} ref={c => this.playerBullet1 = c}/>
<PlayerBullet bulletType={2} speed={20} ref={c => this.playerBullet2 = c}/>
{enemies}
{enemyBullets}
{/* TODO: Refactor Boss classses so that it is one component and not 3 */}
<Boss1 ref={c => this.boss1 = c}/>
<Boss2 ref={c => this.boss2 = c}/>
<Boss3 ref={c => this.boss3 = c}/>
<EnemyBullet ref={c => this.boss1Bullet = c}/>
<Player ref={c => this.player = c}/>
{/* <Controller onPress={this.onPress}/> */}
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container : {
flex : 1,
// borderWidth : 1, borderColor: '#0F0'
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment