-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pokemon game #4
base: master
Are you sure you want to change the base?
Pokemon game #4
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,13 @@ | ||
# Pick your own project | ||
|
||
Build an app of your choice. | ||
|
||
- You are free to use any technologies covered so far, but feel free to try new technologies you find interesting. | ||
- Keep it simple. Aim to get the basic functionality working on day one. You can then extend it on days two and three. | ||
- Feel free to use an external API to provide additional functionality to your app. Use an API that either does not have any authentication or uses API keys. | ||
- This is an opportunity to practice the parts you have challenging so far and improve your understanding of them. | ||
- Use pen and paper to draw a diagram of the webpage layout before starting to code. Have a think about what components you will need in advance. | ||
- Use prop-types and stateless components where appropriate. | ||
- Try to use Sass to create a separate stylesheet for each component. | ||
- Try to add some unit testing. Some parts will be easier to test than others, focus on those first. | ||
- Think about how to organise your data in advance | ||
- Make sure your app is responsive | ||
- Commit frequently | ||
- Create pull request at the end | ||
- Demos will be at 4pm on Friday | ||
- Keep it simple | ||
|
||
## Technical notes | ||
|
||
* Run `npm install` after cloning to download all dependencies | ||
* Use `npm run dev -- --watch` to build React | ||
* Use `npm test` or `npm test -- --watchAll` to run tests | ||
|
||
## README | ||
|
||
* Produce a README.md which explains | ||
* what the project does | ||
* what technologies it uses | ||
* how to build it and run it | ||
* any unresolved issues the user should be aware of | ||
|
||
## Inspiration | ||
|
||
- Take a look at [https://public-apis.jeremyfairbank.com/](https://public-apis.jeremyfairbank.com/) or [https://github.com/toddmotto/public-apis](https://github.com/toddmotto/public-apis) for possible APIs to use. | ||
|
||
## Default option | ||
|
||
If you are struggling to think of a project to build. Try to create a Top Trumps using the [Star Wars API](https://swapi.co/) which allows one user to play the game against the computer. | ||
|
||
- On load, fetch all vehicles from [https://swapi.co/api/vehicles/](https://swapi.co/api/vehicles/) end point. | ||
- Randomise the cards and deal half to player and half to computer. | ||
- Display top card to user | ||
- Allow user to pick an attribute from their card such as `cost_in_credits`, `length`, `max_atmosphering_speed`, `crew`, `passengers`, `cargo_capacity`. | ||
- If the value for chosen attribute is higher on the user's card than on computer's top card, they win the computer's card and it should be taken from computer's deck and added to the bottom of the user's deck. If the attribute is higher on the computer's top card, then user's card should be taken from the user's deck and added to the bottom of computer's deck. | ||
- Game continues until either user or computer has all the cards. | ||
- Implement some features of your choosing. | ||
This is a pokemon game where: | ||
-you can search for pokemon and view their stats | ||
-select up to 6 for your team (these can be removed and changed as needed) | ||
-you can view you Team | ||
-then you can play a top trumps type game against the computer (only you make selections though) | ||
|
||
Tech stuff | ||
-Uses pokeapi | ||
-There are no tests due to a tough week | ||
-scss was used in a last min rush | ||
-little attention was given to BEM, pure functions |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,132 @@ | ||
import React from 'react'; | ||
import Search from './Search.js'; | ||
import SearchResults from './SearchResults.js' | ||
import Team from './Team.js' | ||
import Game from './Game.js' | ||
|
||
import '../styles/components/app.scss'; | ||
|
||
class App extends React.Component { | ||
|
||
constructor(){ | ||
super(); | ||
|
||
this.state = { | ||
pokemonList: [], | ||
searchQuery: "", | ||
searchList: [], | ||
searchListDetails: [], | ||
team: [], | ||
opponent: [], | ||
play: false | ||
} | ||
|
||
this.handleSearchSubmit = this.handleSearchSubmit.bind(this); | ||
this.handleSearchChange = this.handleSearchChange.bind(this); | ||
this.addPokemonToTeam = this.addPokemonToTeam.bind(this); | ||
this.removePokemonFromTeam = this.removePokemonFromTeam.bind(this); | ||
this.handleClick = this.handleClick.bind(this); | ||
this.generateComputerCard = this.generateComputerCard.bind(this); | ||
} | ||
|
||
componentDidMount(){ | ||
fetch(`https://pokeapi.co/api/v2/pokemon/`) | ||
.then(response => response.json()) | ||
.then (body => { | ||
console.log(body.results) | ||
this.setState({ | ||
pokemonList: body.results | ||
}) | ||
}) | ||
} | ||
|
||
|
||
handleSearchSubmit(){ | ||
this.setState({ | ||
searchList: this.state.pokemonList.filter((item) => { | ||
return item.name.includes(this.state.searchQuery.toLowerCase()) | ||
}) | ||
}, () => { | ||
|
||
Promise.all(this.state.searchList.map(pokemon => | ||
fetch(pokemon.url).then(response => response.json()) | ||
)) | ||
.then(results => { | ||
console.log("test", results); | ||
this.setState({ | ||
searchListDetails: results | ||
}) | ||
}) | ||
|
||
|
||
}) | ||
|
||
} | ||
|
||
handleSearchChange(searchQuery){ | ||
this.setState({ | ||
searchQuery: searchQuery | ||
}, () => { | ||
console.log(this.state.searchQuery) | ||
}) | ||
} | ||
|
||
addPokemonToTeam(pokemon){ | ||
if (this.state.team.length < 6){ | ||
this.setState({ | ||
team: this.state.team.concat(pokemon) | ||
}) | ||
} else { | ||
alert("You can only have 6 pokemon in a team!") | ||
} | ||
} | ||
|
||
|
||
removePokemonFromTeam(pokemon){ | ||
const filteredTeam = this.state.team.filter( currentTeam => { | ||
return currentTeam.id !== pokemon.id | ||
}) | ||
|
||
this.setState({ | ||
team: filteredTeam | ||
}) | ||
} | ||
|
||
generateComputerCard(){ | ||
let randomPokemonNumber = Math.floor(Math.random() * (800 - 1 + 1)) + 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 800 - 1 + 1 ? |
||
fetch(`https://pokeapi.co/api/v2/pokemon/${randomPokemonNumber}/`) | ||
.then(response => response.json()) | ||
.then (body => { | ||
this.setState({ | ||
opponent: this.state.opponent.concat(body) | ||
}) | ||
}) | ||
.catch(error => { | ||
console.log(error); | ||
}) | ||
} | ||
|
||
|
||
handleClick(){ | ||
for(let i =0; i<6; i++){ | ||
this.generateComputerCard() | ||
this.setState({ | ||
play: !this.state.play | ||
}) | ||
} | ||
console.log(this.state.opponent) | ||
} | ||
|
||
render(){ | ||
return ( | ||
<div className="app"> | ||
App goes here | ||
|
||
{this.state.play ? <div><Game opponent={this.state.opponent} team={this.state.team}/></div>:<div> | ||
<Search pokemonList={this.state.pokemonList} handleSearchSubmit={this.handleSearchSubmit} handleSearchChange={this.handleSearchChange} /> | ||
<SearchResults searchListDetails={this.state.searchListDetails} team={this.state.team} addPokemonToTeam={this.addPokemonToTeam} removePokemonFromTeam={this.removePokemonFromTeam}/> | ||
<Team removePokemonFromTeam={this.removePokemonFromTeam} team={this.state.team}/> | ||
<button onClick={event => this.handleClick()}>Play</button> | ||
</div>} | ||
</div> | ||
) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import React from 'react'; | ||
|
||
import '../styles/components/Cards.scss'; | ||
|
||
class Cards extends React.Component{ | ||
constructor(){ | ||
super(); | ||
|
||
this.state = { | ||
currentCardIndex: 0 | ||
} | ||
|
||
|
||
} | ||
|
||
|
||
render(){ | ||
return( | ||
<div> | ||
<div className="card"> | ||
{this.props.playerCard.name}<br></br> | ||
<img className="sprite" src={this.props.playerCard.sprites.front_shiny} /><br></br> | ||
Speed: {this.props.playerCard.stats[0].base_stat}<button stat={this.props.playerCard.stats[0].base_stat} name="speed" onClick={ event => this.props.handleClick(this.props.playerCard.stats[0].base_stat, this.props.computerCard.stats[0].base_stat) }>Select</button><br></br> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this might better generated using a loop rather than code duplication. The only difference between the rows is the label and index. You could create an array of labels, map over them and generate each button using the label from array and its index |
||
Special Defense: {this.props.playerCard.stats[1].base_stat}<button stat={this.props.playerCard.stats[1].base_stat} name="specialDefense" onClick={ event => this.props.handleClick(this.props.playerCard.stats[1].base_stat, this.props.computerCard.stats[1].base_stat) }>Select</button><br></br> | ||
Special Attack: {this.props.playerCard.stats[2].base_stat}<button stat={this.props.playerCard.stats[2].base_stat} name="specialAttack" onClick={ event => this.props.handleClick(this.props.playerCard.stats[2].base_stat, this.props.computerCard.stats[2].base_stat) }>Select</button><br></br> | ||
Defense: {this.props.playerCard.stats[3].base_stat}<button stat={this.props.playerCard.stats[3].base_stat} name="defense" onClick={ event => this.props.handleClick(this.props.playerCard.stats[3].base_stat, this.props.computerCard.stats[3].base_stat) }>Select</button><br></br> | ||
Attack: {this.props.playerCard.stats[4].base_stat}<button stat={this.props.playerCard.stats[4].base_stat} name="attack" onClick={ event => this.props.handleClick(this.props.playerCard.stats[4].base_stat, this.props.computerCard.stats[4].base_stat) }>Select</button><br></br> | ||
HP: {this.props.playerCard.stats[5].base_stat}<button stat={this.props.playerCard.stats[5].base_stat} name="HP" onClick={ event => this.props.handleClick(this.props.playerCard.stats[5].base_stat, this.props.computerCard.stats[5].base_stat) }>Select</button><br></br> | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
} | ||
|
||
export default Cards |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import React from 'react' | ||
import Cards from './Cards.js' | ||
|
||
import '../styles/components/Game.scss'; | ||
|
||
class Game extends React.Component{ | ||
constructor(){ | ||
super() | ||
|
||
this.state = { | ||
playerScore: 0, | ||
computerScore: 0, | ||
playerTurn: true, | ||
playerCard: {}, | ||
computerCard: {}, | ||
cardIndex: 0 | ||
} | ||
|
||
this.handleClick = this.handleClick.bind(this); | ||
|
||
} | ||
|
||
|
||
handleClick(playerStat, computerStat){ | ||
const playerCard = this.props.team[this.state.cardIndex]; | ||
const computerCard = this.props.opponent[this.state.cardIndex]; | ||
if (playerStat > computerStat){ | ||
this.setState({ | ||
playerScore: this.state.playerScore + 1, | ||
cardIndex: this.state.cardIndex + 1 | ||
}) | ||
alert(`${playerCard.name} beat ${computerCard.name}`) | ||
|
||
} else if (playerStat < computerStat){ | ||
this.setState({ | ||
computerScore: this.state.computerScore + 1, | ||
cardIndex: this.state.cardIndex + 1 | ||
}) | ||
alert(`${computerCard.name} beat ${playerCard.name}`) | ||
} | ||
|
||
if (this.state.playerScore === 3){ | ||
alert("Player Wins") | ||
let win = new Audio('win.mp3'); | ||
win.play(); | ||
} | ||
|
||
} | ||
|
||
render(){ | ||
const playerCard = this.props.team[this.state.cardIndex]; | ||
const computerCard = this.props.opponent[this.state.cardIndex]; | ||
return( | ||
<div className="game"> | ||
<div className="scores"><h6>Player Score: {this.state.playerScore} --- Computer Score: {this.state.computerScore} </h6></div> | ||
<div className="gameCard"><Cards handleClick={this.handleClick} team={this.props.team} playerCard={playerCard} computerCard={computerCard}/></div> | ||
</div> | ||
) | ||
} | ||
|
||
|
||
} | ||
export default Game |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
|
||
class Cards extends React.Component{ | ||
constructor(){ | ||
super(); | ||
|
||
this.state = { | ||
currentCardIndex: 0 | ||
} | ||
|
||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
|
||
handleClick(){ | ||
console.log("the") | ||
} | ||
|
||
|
||
render(){ | ||
return( | ||
<div> | ||
{this.props.team[${this.state.currentCardIndex}].name} | ||
{pokemon.stats[${this.state.currentCardIndex}].stat.name}{pokemon.stats[${this.state.currentCardIndex}].base_stat}<button onClick={event => this.handleClick(pokemon)}>Select</button> | ||
</div> | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indentation could be better here |
||
} | ||
|
||
} | ||
|
||
export default Cards |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import React from 'react'; | ||
|
||
class Pokemon extends React.Component { | ||
constructor(){ | ||
super(); | ||
|
||
this.state= { | ||
|
||
} | ||
|
||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
|
||
handleClick(){ | ||
if(this.props.onTeam){ | ||
this.props.removePokemonFromTeam(this.props.pokemon); | ||
} else { | ||
this.props.addPokemonToTeam(this.props.pokemon); | ||
} | ||
} | ||
|
||
render(){ | ||
return( | ||
<div> | ||
<table border = "1"> | ||
<tbody> | ||
<tr> | ||
<th>{this.props.pokemon.name}</th> | ||
<th>{this.props.pokemon.stats[0].stat.name}</th> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some loops could reduce code duplication here |
||
<th>{this.props.pokemon.stats[1].stat.name}</th> | ||
<th>{this.props.pokemon.stats[2].stat.name}</th> | ||
<th>{this.props.pokemon.stats[3].stat.name}</th> | ||
<th>{this.props.pokemon.stats[4].stat.name}</th> | ||
<th>{this.props.pokemon.stats[5].stat.name}</th> | ||
</tr> | ||
<tr> | ||
<td><img src={this.props.pokemon.sprites.front_shiny} /></td> | ||
<td>{this.props.pokemon.stats[0].base_stat}</td> | ||
<td>{this.props.pokemon.stats[1].base_stat}</td> | ||
<td>{this.props.pokemon.stats[2].base_stat}</td> | ||
<td>{this.props.pokemon.stats[3].base_stat}</td> | ||
<td>{this.props.pokemon.stats[4].base_stat}</td> | ||
<td>{this.props.pokemon.stats[5].base_stat}</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
<h4>{this.props.pokemon.species.name}</h4> | ||
<button onClick={this.handleClick}>{ this.props.onTeam ? 'Remove from team' : 'Add to team'}</button> | ||
</div> | ||
) | ||
} | ||
|
||
} | ||
|
||
export default Pokemon |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to pre-calculate the
searchList
. That way you can set it in state and use it the fetch after without needing the use the callback in setState. Keeps code simpler