From d7457588ebc5d417122265adec3f3cbdf5f540cc Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 16 Dec 2018 00:52:13 -0500 Subject: [PATCH] [add] basic gui for turns, battleboard scrolls --- src/components/play/Board.js | 585 +++++++++++++++++++---------------- src/components/play/index.js | 11 +- src/scss/play.scss | 29 +- 3 files changed, 345 insertions(+), 280 deletions(-) diff --git a/src/components/play/Board.js b/src/components/play/Board.js index 5344294..b78808a 100644 --- a/src/components/play/Board.js +++ b/src/components/play/Board.js @@ -5,314 +5,349 @@ import API from '../SpreadsheetData'; // array of array of accesible spaces per swift const adjacency_6 = { - 1: [2, 3], - 2: [1, 3, 4, 5], - 3: [1, 2, 5, 6], - 4: [2, 5, 7, 8], - 5: [2, 3, 4, 6, 7, 8, 9], - 6: [3, 5, 8, 9], - 7: [4, 5, 8, 10], - 8: [4, 5, 6, 7, 9, 10, 11], - 9: [5, 6, 8, 11], - 10: [7, 8, 11, 12], - 11: [8, 9, 10, 12], - 12: [10, 11] + 1: [2, 3], + 2: [1, 3, 4, 5], + 3: [1, 2, 5, 6], + 4: [2, 5, 7, 8], + 5: [2, 3, 4, 6, 7, 8, 9], + 6: [3, 5, 8, 9], + 7: [4, 5, 8, 10], + 8: [4, 5, 6, 7, 9, 10, 11], + 9: [5, 6, 8, 11], + 10: [7, 8, 11, 12], + 11: [8, 9, 10, 12], + 12: [10, 11] } @observer export default class Board extends React.Component { - @observable spaces = []; - @observable phase = "none"; - @observable source = -1; + @observable spaces = []; + @observable phase = "none"; + @observable source = -1; + @observable activeplayer = true; - constructor(props) { - super(props); - this.selectCard = this.selectCard.bind(this); + constructor(props) { + super(props); + this.selectCard = this.selectCard.bind(this); - this.spaces = Array(12).fill({ - 'creatures': [this.empty_card("creatures")], - 'battlegear': [this.empty_card("battlegear")], - 'mirage': [this.empty_card("mirage")] - }); + this.spaces = Array(12).fill({ + 'creatures': [this.empty_card("creatures")], + 'battlegear': [this.empty_card("battlegear")], + 'mirage': [this.empty_card("mirage")] + }); - // todo remove / currently simulating - this.submitChange({event: "phase", action: "movement"}); - this.loadcards(); - } + // todo remove / currently simulating + this.submitChange({event: "phase", action: "movement"}); + this.loadcards(); + } - // TODO - loadcards() { - this.spaces[4].creatures[0].data = API.cards.creatures.findOne({'gsx$name': {'$regex': new RegExp("Maxxor", 'i')}}); - this.spaces[4].battlegear[0].data = API.cards.battlegear.findOne({'gsx$name': {'$regex': new RegExp("Maxxor's Torch", 'i')}}); - this.spaces[1].creatures[0].data = API.cards.creatures.findOne({'gsx$name': {'$regex': new RegExp("Staluk", 'i')}}); - this.spaces[1].battlegear[0].data = API.cards.battlegear.findOne({'gsx$name': {'$regex': new RegExp("Vlaric Shard", 'i')}}); - for (let i = 0; i < 6; i++) { - this.spaces[i].creatures[0].controlled = true; - this.spaces[i].battlegear[0].controlled = true; - } - this.spaces[7].creatures[0].data = API.cards.creatures.findOne({'gsx$name': {'$regex': new RegExp("Chaor", 'i')}}); - this.spaces[7].battlegear[0].data = API.cards.battlegear.findOne({'gsx$name': {'$regex': new RegExp("Whepcrack", 'i')}}); - } + // TODO + loadcards() { + this.spaces[4].creatures[0].data = API.cards.creatures.findOne({'gsx$name': {'$regex': new RegExp("Maxxor", 'i')}}); + this.spaces[4].battlegear[0].data = API.cards.battlegear.findOne({'gsx$name': {'$regex': new RegExp("Maxxor's Torch", 'i')}}); + this.spaces[1].creatures[0].data = API.cards.creatures.findOne({'gsx$name': {'$regex': new RegExp("Staluk", 'i')}}); + this.spaces[1].battlegear[0].data = API.cards.battlegear.findOne({'gsx$name': {'$regex': new RegExp("Vlaric Shard", 'i')}}); + for (let i = 0; i < 6; i++) { + this.spaces[i].creatures[0].controlled = true; + this.spaces[i].battlegear[0].controlled = true; + } + this.spaces[7].creatures[0].data = API.cards.creatures.findOne({'gsx$name': {'$regex': new RegExp("Chaor", 'i')}}); + this.spaces[7].battlegear[0].data = API.cards.battlegear.findOne({'gsx$name': {'$regex': new RegExp("Whepcrack", 'i')}}); + } - empty_card(type) { - let card = { - 'data': null, - 'selected': false, - 'selectable': true, - 'controlled': false - } - if (type == "creatures") { - card.moveable = true; - } - return card; - } + empty_card(type) { + let card = { + 'data': null, + 'selected': false, + 'selectable': true, + 'controlled': false + } + if (type == "creatures") { + card.moveable = true; + } + return card; + } - // This is a wraper function for preforming changes to game state - // It preforms the change locally and propegates it higher - // So that a network listener can reflect the change on the other client - // Local changes only could use "make change" - submitChange = (change) => { - this.props.submitChange(change); - this.makeChange(change); - } + // This is a wraper function for preforming changes to game state + // It preforms the change locally and propegates it higher + // So that a network listener can reflect the change on the other client + // Local changes only could use "make change" + submitChange = (change) => { + this.props.submitChange(change); + this.makeChange(change); + } - // TODO if the board state is changed externally - // {'event': 'action'} - makeChange = (change) => { - // seriously calling without a change? - if (!change) return; - console.log(change); // TODO remove - let action = change.action; + // TODO if the board state is changed externally + // {'event': 'action'} + makeChange = (change) => { + // seriously calling without a change? + if (!change) return; + console.log(change); // TODO remove - // change the game's phase - if (change.event == "phase") { - // action: "string" - this.phase = action; - } + let action = change.action; + switch (change.event) { - // add a card to a space - else if (change.event == "add") { - // action: {space, type, card} - this.spaces[action.space][action.type] = action.card; - } + // change the active player + case "active": { + this.activeplayer = action; + this.resetCardSelection(); + // when its players turn + // make creatures moveable + if (action) { + this.spaces.forEach((space) => { + space.creatures.forEach((card) => { + card.moveable = true; + }); + }); + } + // when its opposing players turn, + // make creatures unmoveable + else { + this.spaces.forEach((space) => { + space.creatures.forEach((card) => { + card.moveable = false; + }); + }); + } + break; + } - // remove a specific card at a space - else if (change.event == "remove") { - // action: {space, type} - this.space[action.space][action.type] = this.empty_card(action.type); - } + // change the game's phase + case "phase": { + // action: "string" + this.phase = action; + break; + } - // this is a short hand for moving a creature and its battlegear - else if (change.event == "movement") { - // action: {src, dest} - let src = action.src; - let dest = action.dest; - this.spaces[dest].creatures = (this.spaces[src].creatures); - this.spaces[dest].battlegear = (this.spaces[src].battlegear); - this.spaces[src].creatures = [this.empty_card("creatures")]; - this.spaces[src].battlegear = [this.empty_card("battlegear")]; - } - } + // add a card to a space + case "add": { + // action: {space, type, card} + this.spaces[action.space][action.type] = action.card; + break; + } + + // remove a specific card at a space + case "remove": { + // action: {space, type} + this.space[action.space][action.type] = this.empty_card(action.type); + break; + } + + // this is a short hand for moving a creature and its battlegear + case "movement": { + // action: {src, dest} + let src = action.src; + let dest = action.dest; + this.spaces[dest].creatures = (this.spaces[src].creatures); + this.spaces[dest].battlegear = (this.spaces[src].battlegear); + this.spaces[src].creatures = [this.empty_card("creatures")]; + this.spaces[src].battlegear = [this.empty_card("battlegear")]; + break; + } + default: + break; + } + } - resetCardSelection() { - this.spaces.forEach((space) => { - space.battlegear.forEach((card) => { - card.selectable = true; - card.selected = false; - }); - space.creatures.forEach((card) => { - card.selectable = true; - card.selected = false; - }); - }); - this.source = -1; - } + resetCardSelection() { + this.spaces.forEach((space) => { + space.battlegear.forEach((card) => { + card.selectable = true; + card.selected = false; + }); + space.creatures.forEach((card) => { + card.selectable = true; + card.selected = false; + }); + }); + this.source = -1; + } - // TODO - canAttack(id) { - return false; - } + // TODO + canAttack(id) { + return false; + } - selectCard(e) { - let id = e.target.id.substr(1); - let type = (() => { - switch (e.target.id.charAt(0)) { - case 'b': return 'battlegear'; - case 'c': return 'creatures'; - default: return ""; - } - })(); + selectCard(e) { + let id = e.target.id.substr(1); + let type = (() => { + switch (e.target.id.charAt(0)) { + case 'b': return 'battlegear'; + case 'c': return 'creatures'; + default: return ""; + } + })(); - // When clicking a non-valid target, reset selection - if (this.spaces[id][type][0].selectable == false) { - return this.resetCardSelection(); - } + // When clicking a non-valid target, reset selection + if (this.spaces[id][type][0].selectable == false) { + return this.resetCardSelection(); + } - if (this.phase == "movement" && type == "creatures") { - // TODO combat - // TODO if self selection, check activated ability - if (this.source == id) { - return this.resetCardSelection(); - } - // moving into a space - if (this.source > 0) { - this.submitChange({event: "movement", action: {src: this.source, dest: id}}); - // Only one move per turn - this.spaces[id].creatures[0].moveable = false; - return this.resetCardSelection(); - } + if (this.phase == "movement" && type == "creatures") { + // TODO combat + // TODO if self selection, check activated ability + if (this.source == id) { + return this.resetCardSelection(); + } + // moving into a space + if (this.source > 0) { + this.submitChange({event: "movement", action: {src: this.source, dest: id}}); + // Only one move per turn + this.spaces[id].creatures[0].moveable = false; + return this.resetCardSelection(); + } - // don't select a blank space - if (this.spaces[id].creatures[0].data == null) return; - - // select a card - this.source = id; - let src_card = this.spaces[this.source].creatures[0]; + // don't select a blank space + if (this.spaces[id].creatures[0].data == null) return; + + // select a card + this.source = id; + let src_card = this.spaces[this.source].creatures[0]; - // Calculate range of spaces based on swift - let mv = ((data) => { - let swift = (new RegExp(/swift ([0-9]+)/gi).exec(data.gsx$ability)); - if (swift) return parseInt(swift[1]) + 1; - return 1; - })(this.spaces[id].creatures[0].data); + // Calculate range of spaces based on swift + let mv = ((data) => { + let swift = (new RegExp(/swift ([0-9]+)/gi).exec(data.gsx$ability)); + if (swift) return parseInt(swift[1]) + 1; + return 1; + })(this.spaces[id].creatures[0].data); - // set selectable options - this.spaces.forEach((space, i) => { - space.battlegear.forEach((card) => { - card.selectable = false; - }); - space.creatures.forEach((card) => { - let des_card = this.spaces[i].creatures[0]; - card.selectable = ((src_id, dest_id, movement) => { - // If already moved, no valid movement - if (!src_card.moveable) return false; - // No self space movement - if (src_id == dest_id) return false; + // set selectable options + this.spaces.forEach((space, i) => { + space.battlegear.forEach((card) => { + card.selectable = false; + }); + space.creatures.forEach((card) => { + let des_card = this.spaces[i].creatures[0]; + card.selectable = ((src_id, dest_id, movement) => { + // If already moved, no valid movement + if (!src_card.moveable) return false; + // No self space movement + if (src_id == dest_id) return false; - // for each level of swift, increase moveable range - // TODO account for range - let valid = adjacency_6[parseInt(src_id) + 1]; // fix offset - for (let i = 0; i < movement; i++) { - if (valid.includes(parseInt(dest_id) + 1)) { // fix offset - // Check if space occupied - if (des_card.data != null) { - // Can't move into occupied space of own tribe - if (des_card.controlled) return false; - // Check if can start combat - else return this.canAttack(); - } - return true; - } - valid.forEach((i) => { - valid = [].concat(valid, adjacency_6[i]); - }); - } + // for each level of swift, increase moveable range + // TODO account for range + let valid = adjacency_6[parseInt(src_id) + 1]; // fix offset + for (let i = 0; i < movement; i++) { + if (valid.includes(parseInt(dest_id) + 1)) { // fix offset + // Check if space occupied + if (des_card.data != null) { + // Can't move into occupied space of own tribe + if (des_card.controlled) return false; + // Check if can start combat + else return this.canAttack(); + } + return true; + } + valid.forEach((i) => { + valid = [].concat(valid, adjacency_6[i]); + }); + } - return false; // if all else its probably not moveable - })(id, i, mv); - }); - }); + return false; // if all else its probably not moveable + })(id, i, mv); + }); + }); - // creature is now selected - this.spaces[id].creatures[0].selected = true; - this.spaces[id].creatures[0].selectable = false; - } - } + // creature is now selected + this.spaces[id].creatures[0].selected = true; + this.spaces[id].creatures[0].selectable = false; + } + } - render() { - return( -
-
-
- - -
-
-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
-
-
- - -
-
-
- ); - } + render() { + return( +
+
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+ ); + } } @inject((stores, props, context) => props) @observer class Space extends React.Component { - constructor(props) { - super(props); - } + constructor(props) { + super(props); + } - render() { - if (this.props.cards[0].data) { - return ( - - ); - } - else { - return ( - - ); - } - } + render() { + if (this.props.cards[0].data) { + return ( + + ); + } + else { + return ( + + ); + } + } } diff --git a/src/components/play/index.js b/src/components/play/index.js index a9f7ae0..96079ae 100644 --- a/src/components/play/index.js +++ b/src/components/play/index.js @@ -15,11 +15,17 @@ export default class Play extends React.Component { } handleChange() { - + // When handling movement, flip the card's owner before sending network } componentDidUpdate() { // this.makeChange(); + this.makeChange({event:"active", action: true}); + } + + // TODO own GUI class + endTurn() { + this.makeChange({event: "active", action: true}); } render() { @@ -31,6 +37,9 @@ export default class Play extends React.Component { return (
+
+
+
{if (n) this.makeChange = n.makeChange}} diff --git a/src/scss/play.scss b/src/scss/play.scss index 2a9033f..efd3cbb 100644 --- a/src/scss/play.scss +++ b/src/scss/play.scss @@ -4,15 +4,35 @@ $margin_offset: 10px; $card_width: calc(350px / 2); $card_height: calc(250px / 2); + $view_height: 600px; - height: 50em; + height: $view_height; + position: relative; + + .gui { + position: absolute; + width: 100%; + height: calc(#{$view_height} - 20px); + // all children are above field + >* { + z-index: 20; + } + } + + .endturn { + position: absolute; + border: 1px solid red; + border-radius: 5px; + right: 0%; + bottom: 0%; + } .battleboard { - position: relative; + position: absolute; overflow-x: auto; display: block; width: 100%; - height: 50em; + height: $view_height; > div { height: 100%; @@ -92,7 +112,7 @@ } .r1 { - left: calc(#{$margin_offset}); + padding-left: $margin_offset; .space:first-child{ top: calc(50% - #{$card_height}/2); } @@ -145,6 +165,7 @@ } .r6 { + padding-right: $margin_offset; left: calc(#{$margin_offset} + (#{$card_width} + 25px + 10px)*5); .space:first-child{ top: calc(50% - #{$card_height}/2);