Private
Public Access
1
0

created basic game w/ table and animations

This commit is contained in:
2016-10-11 22:11:21 +02:00
parent 8583be9d2a
commit 91bf6aa737
18 changed files with 327 additions and 29 deletions

View File

@@ -17,6 +17,6 @@ This is a Symfony 3 project w/ React JS in standalone mode and w/ WebSocket.
$ nohup bin/console gos:websocket:server & $ nohup bin/console gos:websocket:server &
2.) React JS WebPack watch generator w/ babel presets: es2015 2.) React JS WebPack watch generator w/ babel presets: es2015, react
$ webpack --progress --colors --watch $ webpack --progress --colors --watch

View File

@@ -1,3 +1,5 @@
@import 'https://fonts.googleapis.com/css?family=Open+Sans:700';
#mine-wrapper, #mine-wrapper,
#mine-wrapper * { #mine-wrapper * {
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
@@ -7,26 +9,228 @@
#mine-wrapper .grid { #mine-wrapper .grid {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-wrap: wrap;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-wrap: wrap;
width: 642px; width: 642px;
border: 1px solid red; border: 1px solid #51c2fe;
margin: 0 auto;
cursor: none;
} }
#mine-wrapper .grid .field { #mine-wrapper .grid .field-wrapper {
background: #fff; position: relative;
}
#mine-wrapper .grid .field-wrapper > img.field-target {
position: absolute;
display: none;
width: 45px;
top: -2.5px;
left: -2.5px;
z-index: 100;
}
#mine-wrapper .grid .field-wrapper:hover > img.field-target {
display: block;
}
#mine-wrapper .grid .field-wrapper > img.field-blue-last,
#mine-wrapper .grid .field-wrapper > img.field-red-last {
position: absolute;
display: none;
width: 100%;
top: 0;
left: 0;
z-index: 99;
}
#mine-wrapper .grid .field-wrapper > img.field-blue-last.last-clicked,
#mine-wrapper .grid .field-wrapper > img.field-red-last.last-clicked {
display: block;
}
#mine-wrapper .grid .field-wrapper .field {
background: #61defa;
background: -moz-linear-gradient(left, #61defa 0%, #119dec 100%);
background: -webkit-linear-gradient(left, #61defa 0%, #119dec 100%);
background: linear-gradient(to right, #61defa 0%, #119dec 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61defa', endColorstr='#119dec', GradientType=1);
width: 40px; width: 40px;
height: 40px; height: 40px;
border: 1px solid red; border: 2px solid #51c2fe;
font-family: 'Open Sans', sans-serif;
font-weight: bold;
font-size: 35px;
text-align: center;
line-height: 35px;
} }
#mine-wrapper .grid .field.active { #mine-wrapper .grid .field-wrapper .field .field-corner {
background: blue; background: url('/bundles/mineseeker/images/bg-corner-outbg.png') no-repeat top left;
color: #FFFFFF; background-size: 100%;
width: 100%;
height: 100%;
} }
#mine-wrapper .grid .field.active.mine { #mine-wrapper .grid .field-wrapper .field.active {
background: red; background: #fde717;
color: #FFFFFF; background: -moz-linear-gradient(left, #fde717 0%, #f5b807 100%);
background: -webkit-linear-gradient(left, #fde717 0%, #f5b807 100%);
background: linear-gradient(to right, #fde717 0%, #f5b807 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fde717', endColorstr='#f5b807', GradientType=1);
border: 2px solid #f6d762;
color: #000;
}
#mine-wrapper .grid .field-wrapper .field.active .flag-number {
-webkit-animation: bubbleNumber 500ms cubic-bezier(.36, .07, .19, .97) both;
animation: bubbleNumber 500ms cubic-bezier(.36, .07, .19, .97) both;
-webkit-transform: scale(1);
transform: scale(1);
}
@keyframes bubbleNumber {
0% {
background: #61defa;
background: -moz-linear-gradient(left, #61defa 0%, #119dec 100%);
background: -webkit-linear-gradient(left, #61defa 0%, #119dec 100%);
background: linear-gradient(to right, #61defa 0%, #119dec 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61defa', endColorstr='#119dec', GradientType=1);
-webkit-border-radius: 50%;
border-radius: 50%;
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
-webkit-border-radius: 50%;
border-radius: 50%;
-webkit-transform: scale(0);
transform: scale(0);
}
100% {
-webkit-border-radius: 0;
border-radius: 0;
-webkit-transform: scale(1);
transform: scale(1);
}
}
#mine-wrapper .grid .field-wrapper .field.active .flag-mine {
position: relative;
overflow: hidden;
}
#mine-wrapper .grid .field-wrapper .field.active .flag-mine > img {
width: 65%;
margin-left: 15px;
margin-bottom: 5px;
-ms-transform: rotate(7deg); /* IE 9 */
-webkit-transform: rotate(7deg); /* Chrome, Safari, Opera */
transform: rotate(7deg);
-webkit-animation: mineFlagLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
animation: mineFlagLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
}
@keyframes mineFlagLoad {
0% {
margin-bottom: 0;
margin-left: 15px;
-ms-transform: rotate(9deg); /* IE 9 */
-webkit-transform: rotate(9deg); /* Chrome, Safari, Opera */
transform: rotate(9deg);
}
50% {
margin-bottom: -5px;
margin-left: 7px;
}
100% {
margin-bottom: 3px;
margin-left: 0;
-ms-transform: rotate(-9deg); /* IE 9 */
-webkit-transform: rotate(-9deg); /* Chrome, Safari, Opera */
transform: rotate(-9deg);
}
}
#mine-wrapper .grid .field-wrapper .field.active .flag-mine .flag-mine-base {
position: absolute;
background: #000000;
width: 25px;
height: 22px;
bottom: -12px;
left: 50%;
margin-left: -10.5px;
-webkit-border-radius: 50%;
border-radius: 50%;
-webkit-animation: mineBaseLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
animation: mineBaseLoad 500ms cubic-bezier(.36, .07, .19, .97) both;
}
@keyframes mineBaseLoad {
0% {
margin-bottom: 0;
}
50% {
margin-bottom: -5px;
}
100% {
margin-bottom: 0;
}
}
/*#mine-wrapper .grid .field-wrapper .field.active .field-corner {*/
/*-webkit-transform: scale(1);*/
/*transform: scale(1);*/
/*}*/
#mine-wrapper .grid .field-wrapper .field.active.mine {
background: #61defa;
background: -moz-linear-gradient(left, #61defa 0%, #119dec 100%);
background: -webkit-linear-gradient(left, #61defa 0%, #119dec 100%);
background: linear-gradient(to right, #61defa 0%, #119dec 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#61defa', endColorstr='#119dec', GradientType=1);
border: 2px solid #51c2fe;
}
#mine-wrapper .grid .field-wrapper .field.active.color-1 {
color: #0000ff;
}
#mine-wrapper .grid .field-wrapper .field.active.color-2 {
color: #079433;
}
#mine-wrapper .grid .field-wrapper .field.active.color-3 {
color: #fd1400;
}
#mine-wrapper .grid .field-wrapper .field.active.color-4 {
color: #0c099e;
}
#mine-wrapper .grid .field-wrapper .field.active.color-5 {
color: #7b4c01;
}
#mine-wrapper .grid .field-wrapper .field.active.color-6 {
color: #008388;
}
#mine-wrapper .grid .field-wrapper .field.active.color-7 {
color: #000000;
}
#mine-wrapper .grid .field-wrapper .field.active.color-8 {
color: #ff0000;
}
#mine-wrapper .grid .field-wrapper .field img {
width: 80%;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -11,7 +11,11 @@ class GridControl extends React.Component {
this.state = { this.state = {
grid: grid.state.grid, grid: grid.state.grid,
updated: [] updated: [],
lastClicked: {
red: null,
blue: null
}
}; };
} }
@@ -28,12 +32,13 @@ class GridControl extends React.Component {
var currentField = this.refs[this.refString(row, col)]; var currentField = this.refs[this.refString(row, col)];
currentField.setState({ currentField.setState({
currentImage: this.state.grid[row][col],
currentObj: this.state.grid[row][col], currentObj: this.state.grid[row][col],
active: true active: true
}); });
/** /**
* ez azért kell, mert amíg nem fut le a showAppropriateFields(), addig nem updatelődik a GridField.state * TODO ez azért kell, mert amíg nem fut le a showAppropriateFields(), addig nem updatelődik a GridField.state
*/ */
if ( if (
this.state.grid[row][col] !== 0 && this.state.grid[row][col] !== 0 &&
@@ -99,17 +104,56 @@ class GridControl extends React.Component {
/** /**
* Player control method * Player control method
* @param currentObject * @param currentObject
* @param x
* @param y
*/ */
handlePlayers(currentObject) { handleGridField(currentObject, x, y) {
var userControl = this.refs.userControl, var userControl = this.refs.userControl,
gridFieldControl = this.refs[this.refString(x, y)],
activePlayer = userControl.state.activePlayer ? 'blue' : 'red'; activePlayer = userControl.state.activePlayer ? 'blue' : 'red';
if (currentObject === 'm') { /** update last cliked grid field */
userControl.refs[activePlayer].setState({ if (this.state.lastClicked[activePlayer] !== null) {
mines: userControl.refs[activePlayer].state.mines + 1 this.refs[this.refString(this.state.lastClicked[activePlayer][0], this.state.lastClicked[activePlayer][1])].setState({
lastClickedRed: false,
lastClickedBlue: false
});
}
if (!gridFieldControl.state.active) {
this.state.lastClicked[activePlayer] = [x, y];
/** If you found mine */
if (currentObject === 'm') {
userControl.setState({
mines: userControl.state.mines - 1
});
userControl.refs[activePlayer].setState({
mines: userControl.refs[activePlayer].state.mines + 1
});
this.state.lastClicked[activePlayer] = [x, y];
gridFieldControl.setState({
currentImage: gridFieldControl.state.icons.root + gridFieldControl.state.icons.flag[activePlayer]
});
} else {
userControl.state.activePlayer = userControl.state.activePlayer ? 0 : 1;
/** It is a number */
if (!isNaN(currentObject)) {
gridFieldControl.setState({
currentImage: currentObject
});
}
}
/** set-up last clicked */
gridFieldControl.setState({
lastClickedRed: activePlayer === 'red',
lastClickedBlue: activePlayer === 'blue'
}); });
} else {
userControl.state.activePlayer = userControl.state.activePlayer ? 0 : 1;
} }
} }
@@ -120,7 +164,7 @@ class GridControl extends React.Component {
onClick(coords) { onClick(coords) {
var currentField = this.refs[this.refString(coords[0], coords[1])]; var currentField = this.refs[this.refString(coords[0], coords[1])];
this.showAppropriateFields(currentField, coords[0], coords[1]); this.showAppropriateFields(currentField, coords[0], coords[1]);
this.handlePlayers(this.state.grid[coords[0]][coords[1]]); this.handleGridField(this.state.grid[coords[0]][coords[1]], coords[0], coords[1]);
} }
renderGrid() { renderGrid() {
@@ -131,7 +175,6 @@ class GridControl extends React.Component {
grid.push( grid.push(
<GridField row={i} <GridField row={i}
col={k} col={k}
obj={this.state.grid[i][k]}
ref={this.refString(i, k)} ref={this.refString(i, k)}
key={i + k * Math.random() * 0.5} key={i + k * Math.random() * 0.5}
onClick={this.onClick.bind(this, [i, k])} onClick={this.onClick.bind(this, [i, k])}

View File

@@ -6,21 +6,71 @@ class GridField extends React.Component {
this.state = { this.state = {
currentObj: 'w', currentObj: 'w',
obj: this.props.obj, currentImage: null,
active: false active: false,
lastClickedRed: false,
lastClickedBlue: false,
icons: {
root: 'bundles/mineseeker/images/',
water: {
1: 'bg-wave-1-outbg.png',
2: 'bg-wave-1-outbg.png',
3: 'bg-wave-2-outbg.png'
},
flag: {
red: 'bg-flag-red-outbg.png',
blue: 'bg-flag-blue-outbg.png'
},
target: {
lastBlue: 'bg-last-blue-outbg.png',
lastRed: 'bg-last-red-outbg.png',
crosshair: 'bg-target-outbg.png',
crosshairBomb: 'bg-target-bomb-outbg.png'
}
}
}; };
} }
isActive() { componentWillMount() {
var wave = Math.floor(Math.random() * 3) + 1;
this.setState({
currentImage: this.state.icons.root + this.state.icons.water[wave]
});
}
classNameWhenActive() {
return 'field' return 'field'
+ (this.state.active === true ? ' active' : '') + (this.state.active === true ? ' active' : '')
+ (this.state.active === true && this.state.obj === 'm' ? ' mine' : ''); + (this.state.active === true && this.state.currentObj === 'm' ? ' mine' : '')
+ ' color-' + this.state.currentObj;
}
currentImage() {
return isNaN(this.state.currentImage)
? <div className="flag-mine"><img src={this.state.currentImage}/><div className="flag-mine-base"></div></div>
: this.state.currentImage ? <div className="flag-number">{this.state.currentImage}</div> : '';
}
lastClickedRed() {
return 'field-red-last' + (this.state.lastClickedRed ? ' last-clicked' : '');
}
lastClickedBlue() {
return 'field-blue-last' + (this.state.lastClickedBlue ? ' last-clicked' : '');
} }
render() { render() {
return ( return (
<div className={this.isActive()} onClick={this.props.onClick}> <div className="field-wrapper">
{this.state.currentObj} <img className="field-target" src="/bundles/mineseeker/images/bg-target-outbg.png" alt="target" onClick={this.props.onClick}/>
<img className={this.lastClickedRed()} src="/bundles/mineseeker/images/bg-last-red-outbg.png" alt="red last"/>
<img className={this.lastClickedBlue()} src="/bundles/mineseeker/images/bg-last-blue-outbg.png" alt="blue last"/>
<div className={this.classNameWhenActive()}>
<div className="field-corner">
{this.currentImage()}
</div>
</div>
</div> </div>
); );
} }

View File

@@ -19,6 +19,7 @@ class UserControl extends React.Component {
return ( return (
<div> <div>
<User ref="blue" name={this.props.blue}/> <User ref="blue" name={this.props.blue}/>
<div>Active mines: {this.state.mines} pcs</div>
<User ref="red" name={this.props.red}/> <User ref="red" name={this.props.red}/>
</div> </div>
); );