GithubHelp home page GithubHelp logo

dnsbty / level10 Goto Github PK

View Code? Open in Web Editor NEW
70.0 5.0 2.0 1.29 MB

Phoenix LiveView multiplayer card game

Home Page: https://level10.games

License: MIT License

Elixir 92.01% CSS 0.22% JavaScript 1.26% HTML 6.05% Dockerfile 0.34% Shell 0.13%
elixir phoenix phoenix-liveview real-time multiplayer game websocket

level10's People

Contributors

brettbeatty avatar dependabot[bot] avatar dnsbty avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

level10's Issues

Create end game screen

Currently we show a scoring screen after every round with the scores and level. We should also create a screen for the end game that will display the final scores.

Add selected cards to groups

If a user selects a valid combination of cards and then taps on a group, those cards should be added to the specified group

Cap players in a game

We should probably put some sort of cap on the number of players that can join a game. I feel like 5 players is ideal, but we should be able to support up to 6 per game.

Add cards to completed groups

If a player selects one or more cards in their hand and then taps on a group that has already been completed, the selected cards should be attempted to be added to the specified group.

This will get a little more complicated with wilds if we want to make it so that wilds are in a static position and can't be replaced.

Use proper cursors

During the game, we should make sure that cursors always show the possibilities. The pointer cursor should be used for anything that is clickable at the moment, and the default cursor should be used otherwise.

Complete a round

Create a function that will take in a game struct and do the following:

  • calculate each player's score for that round and add it to their score
  • determine if each player completed the level and increment their current_level accordingly
  • check if anyone completed the 10th level, and end the game if so
  • clear the draw pile, discard pile, all table info, and player hands

Validate groups with wilds

Currently groups are validated, but wilds aren't taken into account. Add wild usage into the group validation logic.

Add hand length indicators

We should add an indicator to show the size of each player's hand so that it will be more obvious if someone is getting close to completing the current round. This will also take care of the problem with seeing whether or not a player has drawn yet.

Move game state to a GenServer

Having game state in an Agent was great for getting up and running quickly, but we can probably tune things a little better if we move into a GenServer.

Join lobby by URL

We should make it so that games can be joined by a URL so that you can text out the URL rather than having to send the URL and join code separately

Presence is inaccurate

Currently Presence is inaccurate if a user opens a second session with the same player ID and then leaves either session.

Rather than store only if a user is present or not, we should maintain a count of the user's presences, and only remove them if that count reaches 0.

Change creator if the original creator leaves

Right now if the creator leaves the game while in the lobby, the game becomes unplayable because no one else can start it. We should change it so that the next player in the list will become the creator at that point.

If there is no one else left in the list of players, we should then go ahead and delete the game.

Start a round

We should have a function that starts a new round. This would take in a game struct and move it to the next round. It should do the following:

  • increment the current_round
  • get the level information for each user and replace the table info with it
  • shuffle a new deck of cards and set it to the draw_pile

Display scoring page

We should display a scoring page with all of the players in a game, their current level, and current score displayed. The screen should also have a button to go to the next round as soon as all the players are ready.

We should also link the "Check the Scores" button from the "Round Complete" modal to take the players to this page.

Add telemetry events

We should probably add a bunch of telemetry events for better observability:

  • Every time a game is created
  • Every time a game is joined
  • Whenever a new round is started
  • Whenever a game is left

Detect whether a round has ended

Whenever a player discards a card or plays new cards to the table, check to see if they have any cards left in their hand. If not, mark the round as ended.

Create game struct

We'll want a struct for managing the state of the game. This will depend on #1 and #3. I'm seeing this looking something like the following:

  • current_round
  • players: list of players
  • draw pile: list of cards in the draw pile
  • discard pile: list of cards in the discard pile
  • hands: map with a list of the cards in each player's hand keyed by player name
  • scoring: map of score objects (containing level and score) keyed by player name
  • table: map of tabled cards keyed by player name to represent what's been laid out

Table Example

%{
  "Dennis" => [
    {:set, [%Card{}, %Card{}, %Card{}]},
    {:run, [%Card{}, %Card{}, %Card{}]}
  ]
}

Allow users to play cards to the table

Allow users to send selected cards to a group on the table.

This should allow them to click on a group with the proper cards selected. It should validate that the selected cards meet the group criteria, and if they do, move them out of their hand and into the group on the table.

Add online indicator

We should add Phoenix Presence to be able to detect if a player is currently online. This way the other players will know if they need to tell them it's their turn or not.

Close out finished games

When a game is finished, it should be automatically closed out so that finished games won't use up memory on the server.

Make skip cards work

When a skip card is discarded, the player whose turn would normally be next is instead skipped over so the turn goes to the next player.

Update whether player has drawn

Once it’s a new player’s turn it should reset whether the player has already drawn or not so that they can draw again without refreshing

Close out a game

We want to be able to close out a game. This should remove the game process and its state from the server.

Properly handle join codes that don't exist

Whenever a player attempts to join a game that doesn't exist, the live view process appears to be crashing. We should handle that crash and display an error message.

I believe that we did this previously, but perhaps Horde's registry handles missing names differently or something like that.

Create player struct

We'll want a struct for representing the users in the game. For the first version I see it having the following fields:

  • name
  • key (a key for identification whenever reconnecting to the game)

Further down the road, we might want more fields like:

  • device type (iOS, Android, or web)
  • device ID (for push notifications)

Set up clustering

Elixir's Registry only works on the local process. Swap it out with Erlang's :global to set things up for clustering and make scaling possible.

:global docs: http://erlang.org/doc/man/global.html
Relevant blog post: https://scottyscripts.com/2019/11/25/erlang-in-elixir-erlangs-global-module.html
Relevant Elixir Forum thread: https://elixirforum.com/t/genserver-and-global-registration/13344

Perhaps longer term, syn should be considered instead based on these benchmarks but it seems like until we're seeing a ton of traffic, :global ought to work just fine

Store player ID in a cookie

Rather than store the player ID in the URL, we should store it in a cookie so that you can come back to the game if your battery dies or anything like that and the URL gets corrupted

Shuffle the deck

Whenever a round begins, we'll want to create and shuffle a deck. We'll probably also want to make sure we can use the shuffle functionality again in case the draw pile ever runs out so that we can shuffle the discard pile and move it to the draw pile.

So this should create a new deck:

  • 2 x each number + :wild in each color
  • 4 x blue skip cards

Then it should shuffle that deck (or a different one that is passed in) so that the cards will be in a random order.

Store all the levels

Depending on how we handle the levels in the Game struct, we'll want to have the basic templates set up for them somewhere else. Perhaps a Levels module with a get function that takes in a level number and returns something like

[set: 3, run: 4]

or

[color: 7]

Create card struct

We'll want to create a struct to represent a card.

I think these should have three keys:

  • color: :red, :yellow, :green, :blue
  • number: :one through :twelve, :wild, :skip (not sure on the key for this one, open to suggestions)
  • value: one of 5, 10, 15, 25 to be used for scoring

Turn indicator sound

We should play a sound to indicate when it's your turn and get your attention in case you're playing in the background

Validate groups

Create a function that will validate if a list of cards meets the requirements to be a group

Show turn indicator

Show an indicator in the game view of whose turn it is. Potentially it could also be shown if they've drawn yet or not

Store game state in agents

We want to store game state in agents, and then use registries to find the proper agent based on a game code.

Don't allow for wilds to be replaced

Whenever a run is played, we should track the position where each wild should belong so that it will be easier to see the range of the run. This would also allow for us to turn off wild replacement so that only the front and end of the run can be added to

sort cards on the table

Cards on the table should be sorted before being displayed so that runs will be in order and numeric cards will be most easily visible.

Add readiness indicators

On the scoring page, display indicators next to players that have marked that they're ready for the next round so that it's more obvious who you're waiting on

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.