Skip to content

Commit

Permalink
Added moving target mode
Browse files Browse the repository at this point in the history
  • Loading branch information
dbecker1 committed Jul 6, 2020
1 parent df83e5e commit 7ec20cf
Show file tree
Hide file tree
Showing 10 changed files with 414 additions and 164 deletions.
349 changes: 190 additions & 159 deletions .idea/workspace.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/assets/targets/bullseye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 15 additions & 1 deletion src/app/slices/targetSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,24 @@ export const targetSlice = createSlice({
},
removeTargetById: (state, action) => {
return state.filter(a => a.id !== action.payload);
},
tickTargets: state => {
state.forEach(target => {
if (target.hasOwnProperty("dx")) {
target.x = target.x + target.dx
if (target.x > target.maxX || target.x < 0)
target.dx = -target.dx
}
if (target.hasOwnProperty("dy")) {
target.y = target.y + target.dy
if (target.y > target.maxY || target.y < 0)
target.dy = -target.dy
}
})
}
},
});

export const { addTarget, wipeTargets, removeTargetById } = targetSlice.actions;
export const { addTarget, wipeTargets, removeTargetById, tickTargets } = targetSlice.actions;

export default targetSlice.reducer;
2 changes: 1 addition & 1 deletion src/components/mainScreen/shooting/ShotFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import GoogleAnalyticsUtils from "../../../util/GoogleAnalyticsUtils";
import TargetCanvas from "../../TargetCanvas"

// helpful for debugging/development without an entire setup
const ENABLE_CLICK_TO_SHOOT = false
const ENABLE_CLICK_TO_SHOOT = true

class ShotFeed extends React.Component {
constructor(props) {
Expand Down
30 changes: 30 additions & 0 deletions src/components/mainScreen/shootingModes/moving/MovingConfigure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import {Row, Col, Button, OverlayTrigger, Tooltip} from "react-bootstrap";

class MovingConfigure extends React.Component {
constructor(props) {
super(props);
this.state = {
}

}

saveSettings() {
this.props.saveSettings(this.state)
}

render() {
return (
<>
<Row style={{marginTop: "20px"}}>
<Col sm={12} className={"text-center"}>
<Button variant={"customPrimary"} onClick={() => {this.saveSettings()}} size={"lg"}>Shoot!</Button>
</Col>
</Row>

</>
)
}
}

export default MovingConfigure;
108 changes: 108 additions & 0 deletions src/components/mainScreen/shootingModes/moving/MovingShoot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import {Row, Col, Button} from "react-bootstrap";
import ShotFeed from "../../shooting/ShotFeed";
import ShotRecord from "../../shooting/ShotRecord";
import TargetUtils from "../../../../util/TargetUtils"
import {bindActionCreators} from "redux";
import {addTarget, wipeTargets, tickTargets} from "../../../../app/slices/targetSlice";
import {wipeNonTargetElements} from "../../../../app/slices/projectorSlice"
import {wipeShots} from "../../../../app/slices/shotSlice";
import {connect} from "react-redux";

class StandardShoot extends React.Component {
constructor(props) {
super(props);

this.timerRef = React.createRef();
}

componentDidMount() {
this.resetTargets()
}

resetTargets() {
this.props.wipeTargets();
this.props.wipeNonTargetElements();
this.props.wipeShots();
const {canvasWidth, canvasHeight} = this.props.canvasDimensions;
const targetName = "bullseye"
const target = TargetUtils.getTargetByName(targetName);
let targetHeight = canvasHeight * .2;
const targetWidth = TargetUtils.getTargetWidthForHeight(target.name, targetHeight)

for (let i = 0; i < 5; i++) {

let displayTarget = {
name: "bullseye",
x: Math.random() * canvasWidth * .8,
y: Math.random() * canvasHeight * .8,
width: targetWidth,
height: targetHeight,
requestedScaleRatio: targetHeight / target.defaultHeight,
id: TargetUtils.generateId(),
dx: Math.random() > .5 ? -8: 8,
dy: Math.random() > .5 ? -8 : 8,
maxX: canvasWidth - targetWidth,
maxY: canvasHeight - targetHeight
}
this.props.addTarget(displayTarget)
}

if (this.hasOwnProperty("interval"))
clearInterval(this.interval)

const fps = 40;
let delay = 1000 / fps;
this.interval = setInterval(() => {
this.props.tickTargets()
}, delay)
}

componentWillUnmount() {
if (this.hasOwnProperty("interval"))
clearInterval(this.interval)
}

getFeed() {
return <ShotFeed videoRef={this.props.videoRef} />
}

render() {
return (
<>
<Row>
<Col sm={12} className={"text-center"}>
<p>Start shooting!</p>
</Col>
</Row>
<Row>
<Col sm={4}>
<ShotRecord />
</Col>
<Col sm={8}>
{this.getFeed()}
</Col>
</Row>
<Row style={{marginTop: "30px"}}>
<Col sm={12} className={"text-center"}>
<Button variant={"customPrimary"} onClick={() => {this.resetTargets()}} size={"lg"} style={{marginBottom: "10px"}}>Reset Target</Button> <br />
<Button variant={"customPrimary"} onClick={() => {this.props.backToSettings()}} size={"lg"}>Back To Settings</Button>
</Col>
</Row>
</>
)
}
}

const mapStateToProps = state => ({
canvasDimensions: {
canvasHeight: state.projector.canvasHeight,
canvasWidth: state.projector.canvasWidth
}
})

const mapDispatchToProps = dispatch => {
return bindActionCreators({addTarget, wipeShots, wipeTargets, wipeNonTargetElements, tickTargets}, dispatch)
};

export default connect(mapStateToProps, mapDispatchToProps)(StandardShoot);
11 changes: 10 additions & 1 deletion src/components/mainScreen/shootingModes/shootingModes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import StandardConfigure from "./standard/StandardConfigure";
import StandardShoot from "./standard/StandardShoot";
import DuelingConfigure from "./duelingTree/DuelingConfigure";
import DuelingShoot from "./duelingTree/DuelingShoot";
import MovingConfigure from "./moving/MovingConfigure";
import MovingShoot from "./moving/MovingShoot"


const standard = {
Expand All @@ -18,11 +20,18 @@ const duelingTree = {
shootComponent: DuelingShoot
}

const moving = {
name: "Moving Targets",
description: "Shoot bullseye targets moving across the screen!",
configureComponent: MovingConfigure,
shootComponent: MovingShoot
}

const comingSoon = {
name: "Coming Soon!",
description: "Probably something really cool.",
configureComponent: null,
shootComponent: null
}

export const shootingModes = [standard, duelingTree, comingSoon, comingSoon]
export const shootingModes = [standard, duelingTree, moving, comingSoon]
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {addNonTargetElement, wipeNonTargetElements} from "../../../../app/slices
import { setTwoPlayerStatus } from "../../../../app/slices/configSlice";
import {wipeShots} from "../../../../app/slices/shotSlice";
import {connect} from "react-redux";
var randomstring = require("randomstring");

class StandardShoot extends React.Component {
constructor(props) {
Expand Down
20 changes: 20 additions & 0 deletions src/components/mainScreen/shootingModes/svgs/Bullseye.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';

const Bullseye = ({x=0, y=0, width=251, height=251}) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 251 251" x={x} y={y} width={width} height={height}>
<g id="Bullseye">
<path id="_4-ring" data-name="4-ring" style={{stroke: "#000", strokeMiterlimit: 10, fill: "#000"}}
d="M250.5,125.5A125,125,0,1,1,125.5.5,125,125,0,0,1,250.5,125.5Z"/>
<path id="_6-ring" data-name="6-ring" style={{stroke: "#000", strokeMiterlimit: 10, fill: "#0071bc"}}
d="M225.5,125.5a100,100,0,1,1-100-100A100,100,0,0,1,225.5,125.5Z"/>
<path id="_8-ring" data-name="8-ring" style={{stroke: "#000", strokeMiterlimit: 10, fill: "red"}}
d="M200.5,125.5a75,75,0,1,1-75-75A75,75,0,0,1,200.5,125.5Z"/>
<path id="_10-ring" data-name="10-ring" style={{stroke: "#000", strokeMiterlimit: 10, fill: "#ff0"}}
d="M175.5,125.5a50,50,0,1,1-50-50A50,50,0,0,1,175.5,125.5Z"/>
</g>
</svg>
)
}

export default Bullseye
40 changes: 39 additions & 1 deletion src/components/mainScreen/shootingModes/targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BasicSilhouette from "./svgs/BasicSilhouette"
import TreePlate from "./svgs/TreePlate"
import TreePlateFlipped from "./svgs/TreePlateFlipped"
import USPSA from "./svgs/USPSA"
import Bullseye from "./svgs/Bullseye"
//In order to create scoring zones, take your SVG image and view the raw xml of it. Each zone should be defined by a
//single <path> tag. Take the "d" attribute of this tag (the one that defines the path) and put the resultant string
// in for the "path" of the scoringZone
Expand Down Expand Up @@ -129,4 +130,41 @@ export let treePlateFlipped = {
]
}

export const all_targets = [basic_silhouette, uspsa, treePlate, treePlateFlipped];
export let bullseye = {
name: "bullseye",
fileName: "bullseye.svg",
displayName: "Bullseye",
realHeight: 12,
stationary: true,
component: Bullseye,
defaultWidth: 251,
defaultHeight: 251,
scoringZones: [
{
name: "Bullseye",
pointValue: 10,
path: "M175.5,125.5a50,50,0,1,1-50-50A50,50,0,0,1,175.5,125.5Z",
priority: 1
},
{
name: "8",
pointValue: 8,
path: "M200.5,125.5a75,75,0,1,1-75-75A75,75,0,0,1,200.5,125.5Z",
priority: 2
},
{
name: "6",
pointValue: 6,
path: "M225.5,125.5a100,100,0,1,1-100-100A100,100,0,0,1,225.5,125.5Z",
priority: 3
},
{
name: "4",
pointValue: 4,
path: "M250.5,125.5A125,125,0,1,1,125.5.5,125,125,0,0,1,250.5,125.5Z",
priority: 4
}
]
}

export const all_targets = [basic_silhouette, uspsa, treePlate, treePlateFlipped, bullseye];

0 comments on commit 7ec20cf

Please sign in to comment.