Jump to content
  • Advertisement

Daniel Ricci

  • Content Count

  • Joined

  • Last visited

  • Days Won


Daniel Ricci last won the day on November 8

Daniel Ricci had the most liked content!

Community Reputation

10 Neutral

About Daniel Ricci

  • Rank

Personal Information

  • Interests


  • Github
  1. Daniel Ricci

    Art Update 1 (Stock, Foundation)

    In my last post, I implemented the Draw Three feature, which allows you to play the Solitaire game using three cards at a time. This game mode is a lot more challenging since you must answer the right-most card first before moving to the next one. The next feature that I said that I would work on was the `Undo` feature which lets you go back to the last move played. I also said that I would update some of the art in the game. This post is to show what was done on the art side of things before I start implementing the Undo feature which will be explained in my next post. There were a few places where the art in the game did not exist, so I put placeholders there until I had time to extract the actual game art. I also did the implementation for doing the highlighting when playing the game in `Outline` mode. 1. Foundation View You now have the foundation view art available, instead of the white rectangular placeholder art that was there before. You can now drag a card in outline mode over any of the foundations, and the proper rendering colors will appear. This was done by applying an XOR bitmask during the rendering phase before performing my draw call if there is a valid collision between a card and the Foundation when there are no cards in that view. 2. Stock View There is now an `O` and an `X` that is shown when the deck is to be recycled or when the deck can no longer be recycled, respectively. My next task is to implement the Undo feature, where every time you make a move, you are able to undo that move, and of course, there are scoring consequences if you use the Undo button. You can always follow my progress by following the game located at https://github.com/danielricci/solitaire, and if you have any questions I will do my best to answer them. Take care, until my next blog post.
  2. Daniel Ricci

    Draw Three

    In my last post, I implemented the `Card Back` deck selection feature, which allows you to choose between 12 built-in deck images that would change the card backs of all the cards in the game. The next feature that I implemented was the ability to play Solitaire using the `Draw Three` game mode, which allows you to play the game using three cards at a time. I also added the functionality for scoring when in this mode for both `Vegas` and `Standard`. Here is what the `Draw Three` game mode looks like, and how to set the game for this mode. From the `File` menu, choose `Options`. When the dialog opens, click on the `Draw Three` radio button, and then click on `OK`. You will notice that your game will restart, and you will now have three cards drawn at a time when you click on your Stock card. This feature took quite a while for me to implement as there were a lot of small things that I had to change. Here is the list of features/functionalities that I had to work on to get my game to support the `Draw Three` game mode. 1. When clicking on the Stock card, three cards should be loaded at a time instead of one. This was simply a matter of taking the `blank card` that I use to partition my deck when playing in `Draw One`, and have it skip three cards at a time instead of one. At this point, all three cards will be stacked on top of each other, however, my next task would fix that up even further by applying an offset to each card. 2. When three cards are shown, they should be rendered next to each other. This task was done to compliment my first task. When loading three cards at a time, all that I needed to do was iterate through each card, and multiply the x-axis location of the card by (iteration * 12px). Because of the GridBagLayout that I use to render the different piles in the game, I had some trouble with this at first, mostly with the view chopping off the two right-most cards because the view was initially only ever sized for rendering at most one card. I tried to take row 0, column 1 and column 2, and merge them both together using a `colspan` in one of my GridBagConstraints, however this would cause some alignment problems, so I instead played with the insets and padding of the view, so that three cards could be rendered without any of the cards being chopped. Here is some of the code that I wrote to achieve this. TalonView talonView = viewFactory.add(new TalonView(cards), true); GridBagConstraints talonConstraints = (GridBagConstraints)gameConstraints.clone(); // Get a reference to the current constraints and subtract 20 from the right so that // it is positioned at an offset to the right of +20, then increase the size // by 20 to create enough room to potentially fit cards when playing in `draw three` talonConstraints.insets = new Insets(10, 0, 0, -30); talonConstraints.ipadx = 30; this.add(talonView, talonConstraints, 0); So as shown above, I first create my talon view. After that, I clone the GridBagConstraints that are currently in use, and I modify/use it locally just for that view. I provide a -30px off to the right for the insets, and then I add 30 px to the padding over the x-axis, and then I apply those constraints to the view. Doing this gives my view enough room to render 3 cards without the cards being chopped off. 3. When three cards are loaded, the right-most card should be the only card that can be interacted with. This was a little bit tricky because I didn't want to introduce a flag and then have to manage that depending on the different states of the game. Experience has taught me just how difficult it can be to manage the many different states of an object, and the more flags that you add to a class, the more things can go wrong. Therefore, I overwrote the setEnabled method of my view, and I would instead toggle mouse events associated with that view. I had to do this for both the CardView and the CardProxyView since they both do not have a common class that they inherit from as of yet, apart from the generic PanelView class that is Engine specific and I didn't want to put the game-specific code in the engine. @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); // Propagate the state change to the proxy. Ensure that no circular reference could ever occur if(_cardProxy.isEnabled() != enabled) { _cardProxy.setEnabled(enabled); } draggableListener.setEnabled(enabled); _collisionListener.setEnabled(enabled); } The above code also exists in the CardProxyView class. Therefore, the first thing that I do is go through fully with the state of the method by calling super, this will avoid the circular reference for the next line of code, where I check the enabled state of the proxy and then set that accordingly. Finally, I set the state of the draggable listener and the collision listener, in charge of dragging and handling collision respectively. Therefore, once this code has executed, if the enabled flag was set to false, that means that the card will not be draggable or collidable with. 4. When a single card from the three card pile moves to the Tableau or the Foundation pile, the next right-most card should now be playable. This involved two sub-tasks that I needed to introduce into the game. The first was to introduce a `mouseReleased` event on a card within the Talon deck, such that when the event would occur, I would verify if the card that was just dragged still exists in the Talon. If the card existed then the move was invalid, so do nothing with the other cards. If the card was moved then take the right-most card and enable it. If there are no more cards left, show the at-most-three cards last played and enable the right-most card there. 5. When playing using the `Vegas` scoring style, you should only be able to go through the entire deck at most three times This code was actually already in place, however, there is currently no art to show that the deck can no longer be recycled. Here is the task for adding the required art to the Stock view. https://github.com/danielricci/solitaire/issues/39 6. When playing using the `Draw Three` game mode using the `Standard` scoring style, 20 points should be taken off of the score whenever a deck has been recycled. This was very straight-forward, here is the code for doing this. public void updateScoreDeckFinished() { OptionsPreferences preferences = new OptionsPreferences(); preferences.load(); if(preferences.drawOption == DrawOption.THREE && preferences.scoringOption == ScoringOption.STANDARD) { SCORE = Math.max(0, SCORE - 20); } else { SCORE = Math.max(0, SCORE - 100); } scoreValue.setText(toString()); } So, here I load the option preferences, and if the Draw Three option is selected and we are using the standard scoring model, set the score to be whatever it currently is and subtract 20, however if the result is less than 0, use 0 instead to avoid the score going into the negatives since the Standard score model allows for a minimum value of 0. 7. When playing using the `Draw Three` game mode, showing three cards should hide the currently shown cards. By default, all cards are now marked as not having any visibility. When the three cards come into play, their visibility is shown, and when the card deck re-cycles, their visibility is set back to hidden. When the next set of three cards is shown, the previous at-most-three cards have their visibility set to hidden. 8. When playing using the `Draw Three` game mode, if you move the three currently shown cards, the previously shown cards should now be made visible to you. This involves looking for my hidden `Blank Card` that keeps tabs of where I am in the current deck. When all three cards have been dragged to one of the other piles (Foundation or Tableau) in the game, I use the blank card index to look for the three cards with a layer of +1,+2, and +3 to that of the blank card. Obviously, this will go up to at most three cards, to avoid any `IndexOutOfBoundsException` issues from being occurring. Here is the code related to that bit. // If the card is no longer associated to the talon, then remove its association to this event if(!(cardView.getParentIView() instanceof TalonView)) { cardView.removeMouseListener(this); // The top-most card cannot be the layered pane boolean cond1 = layeredPane.highestLayer() != JLayeredPane.getLayer(_blankCard); // There must not be any more visible cards (excluding the blank card) boolean cond2 = Arrays.asList(layeredPane.getComponents()).stream().anyMatch(z -> !z.equals(_blankCard) && z.isVisible()); if(cond1 && !cond2) { for(int iterations = 0, layerId = JLayeredPane.getLayer(_blankCard) + 1; layerId <= layeredPane.highestLayer() || iterations < 3; ++layerId, ++iterations) { Component component = layeredPane.getComponentsInLayer(layerId)[0]; component.setVisible(true); } } } Over here, I check if the current card does not have a parent of type TalonView, indicating that the card is either in the Foundation or the Tableau. From there, I remove the current event from the card since it can no longer be part of the Talon pile any longer, and I don't want the event to continue firing anymore. I then create two booleans that store the state of the two conditions that I need to know about when searching back for the cards that I want. Firstly, I need to know if the top-most card is my blank card, if it is then there are no more cards to go back to. Secondly, I need to know if there are any cards that are still being shown to the user, so I don't try to fetch other cards until the three cards that are currently shown have been dragged somewhere. Provided that both of these are true, I go through the list of cards starting from the blank card, and I find the cards that have a layer identifier of +1, +2, and +3 with respect to the blank card layer, and I set those cards' visibility to true. Here are the other issues that I worked on. I have linked the bug issues that I logged, in there I have included screenshots of the actual issue, and you can also go and take a look at the changeset that solves that issue. 1. You can now press on the `Enter` key when in the Options dialog instead of clicking on the `OK` button Issue - https://github.com/danielricci/solitaire/issues/104 Changeset - https://github.com/danielricci/solitaire/commit/832891bb9c00635073401ce60d51f11fb3d8495d 2. I fixed a bug where when you would play using the `Draw Three` game mode using the `Outline` option, you could drag all three cards` outline instead of just the right-most card. Issue - https://github.com/danielricci/solitaire/issues/105 Changeset - https://github.com/danielricci/solitaire/commit/ea65c2b68d07d0811758016ecc37cb61a8183753 3. I fixed a bug where when you were using the `Outline` option, after performing a double-click on a card, if you were to hold the mouse down on the second click and keep it held, the outline would still be visible on the card. This was more of a rendering artifact, however, I still wanted to correct it. Issue - https://github.com/danielricci/solitaire/issues/106 Changeset - https://github.com/danielricci/solitaire/commit/014727604b27205a1ec7be23aa6c7f4b30406751 4. I fixed a bug where while playing using the `Draw Three` game mode, if you were to move one card and then play through the entire deck, the next time that you would play through the deck, one of the cards` visibility properties would not properly reset, causing the cards currently shown to be offset at the wrong coordinates. Issue - https://github.com/danielricci/solitaire/issues/108 Changeset - https://github.com/danielricci/solitaire/commit/a03a05d08fbf103c6f5021513fad427943014cd7 5. Added some enhanced logging to better debug the `Draw-Three` game mode. I linked the changeset under the main task for the `Draw Three` game mode, however, I will give an explanation below on how this all works and what the symbols actually mean. https://github.com/danielricci/solitaire/issues/12 When you are in debug mode and you play the game, pressing F1 on the keyboard will output to the console all the cards from all the views, here is an example of the Talon View =======TALON VIEW=========== [V] [F] 8 of HEARTS [24] [V] [F] 3 of HEARTS [23] [V] [F] 11 of DIAMONDS [22] [=======BLANK=======] [21] [H][F] 10 of SPADES [20] What the above tells me is that within the TalonView, the 8 of Hearts is on layer identifier #24, it is [V] visible to the user, and has the [F] frontside of the card shown. The blank card is a PanelView type card that exists just to keep track of where I am in the deck. So that's all that there is. Sorry that I took so long to write this blog, there were a lot of changes that I had to make, and this feature is pretty much my last major feature before the release of the game. My next task is to implement the Undo feature, where every time you make a move, you are able to undo that move, and of course, there are scoring consequences if you use the Undo button. I will also add in some of the game art. The three tasks are linked below if you would like to follow the progress. Undo - https://github.com/danielricci/solitaire/issues/7 Foundation View Art - https://github.com/danielricci/solitaire/issues/86 Stock View Art - https://github.com/danielricci/solitaire/issues/39 You can always follow my progress by following the game located at https://github.com/danielricci/solitaire, and if you have any questions I will do my best to answer them. Take care, until my next blog post.
  3. Daniel Ricci

    rotating sprites

    If you say so. Once again, someone that stumbles onto this thread will not have learned anything, maybe you should provide your code for clarity with some comments and an explanation of what the issue is and where you had to make changes to get your code to work.
  4. Daniel Ricci

    Deck Selection Dialog

    Good suggestion. Right now they are the built in images, but once the game is done, I would love to implement that feature for everyone to try out. Yes I am https://github.com/danielricci/solitaire/issues/25
  5. Daniel Ricci

    Deck Selection Dialog

    In my last post, I gave an overview of the Solitaire project that I am working on, along with an explanation of the features that I have currently implemented, and the feature that I was to work on next. The next feature of Solitaire that I wanted to implement is the deck selection dialog, where you choose from a list of predefined deck images, the image you would like to use on your deck backside when playing the game. Here is what my dialog looks like. The goal of this dialog is to try to mimic the original Solitaire deck selection dialog. Here is a list of features that were required for me to implement for this task. 1. I had to implement the initial dialog window along with its dimensions and specifications, such as making it a modal window, not allowing the window to be resized, and other options like that. This was pretty straightforward as I have done this many times before, and was simply a matter of testing the old dialog to see what I could and could not do. 2. I had to create the skeleton of the dialog, so I used a BoxLayout with a Y-Axis alignment, this is where I added two panel types, one that holds the deck button images, and the other that holds the OK and Cancel button. The first panel within my BoxLayout was a JPanel that uses a GridBagLayout with two rows and six columns. The second JPanel uses a FlowLayout centered about the x-axis. Note: The 2 row 6 column deck images that you see are actually JButton components. Here is how the dimensions of a button looks like from up close. The button size is 45px in width by 74px in height. The border is removed by default on all buttons except for the one that was last selected. Within the button is the icon image, this is 39px wide by 68 px in height. When the button is selected, a 2px blue border is rendered around the button, leaving a gap of a few pixels between the button image and the border itself, similar to what was done in the original Solitaire game, or at least what I thought was implemented based on my research. I also disabled some events such as hovering your mouse over a button to prevent the background image from changing color because the mouse hovered over the button. I also disabled that same effect when clicking on the button. 3. Clicking on a button should show a border, and `deselect` any other button that was previously selected. This was very straightforward to do. 4. Fetch the deck images and load them into the button. 5. Adding events to the button such as double-clicking on a button to choose a deck image, or pressing on the `enter` key in the dialog to simulate an `OK` button click. 6. Update the deck images of all the cards in the game, including the image of the Stock view (the card at the top-left of the game) when a selected took place and the `OK` button was selected. To get this done, I had all my CardModel objects register to an event that I created called `EVENT_UPDATE_BACKSIDE` public static final String EVENT_UPDATE_BACKSIDE = "EVENT_UPDATE_BACKSIDE"; Here is the code that the CardModel uses for registering this event addSignalListener(EVENT_UPDATE_BACKSIDE, new ISignalReceiver<EventArgs>() { @Override public void signalReceived(EventArgs event) { OptionsPreferences preferences = new OptionsPreferences(); preferences.load(); _cardEntity.setBackside(preferences.deck); refresh(); } }); So I look at the options preferences, and based on what was saved from the deck selection dialog, I go into my card entity (a reference that each CardModel owns) and I set the deck to be whatever was saved. I then issue a refresh on the model that causes all the views that are data-bound to my model to perform an update(), which will then render their backside which will show the updated deck image. Here is how I make the call so that the registered event above gets fired // Update all the backsides of all the cards in the game EventArgs args = new EventArgs(this, CardModel.EVENT_UPDATE_BACKSIDE); AbstractFactory.getFactory(ModelFactory.class).multicastSignalListeners(CardModel.class, args); So what I do here is I create an EventArgs which is a base class for passing arguments around in my game. I indicate the sender and the signal name which is the same signal name that was used to register the event listener in the CardModel from above. I then perform a call onto all CardModel type objects that have been registered by my ModelFactory. This will dispatch my EventArgs to all the CardModel types that were created with my factory, that are listening in to the specified message. From there, the information is updated within each CardModel, and the view(s) that are bound to those models are updated accordingly, very straightforward stuff. The code that I wrote above comes from my own take on a much friendlier version of the Observer design pattern. I first started using the Observer provided to me by the Java SDK about two years ago, however over time I found it to be very limiting, so I eventually wrote my own version of it, and one day I will write an article outlining what I did and why I like it a lot more, but for now this is what I have been using in it's place for two years and it has worked out great for me. 7. Persist the selected deck image for future games played. So that's all that there is. My next task is to implement the Draw Three feature, where every time you click on the Stock view (top-left card), three cards come into play instead of one. You can always follow my progress by following the game located at https://github.com/danielricci/solitaire, and if you have any questions I will do my best to answer them. Take care, until my next blog post.
  6. Daniel Ricci

    rotating sprites

    Unfortunately, I cannot just make your application work by looking at this one method, assuming this is even where the problem is, and give you a magic line of code or a series of lines of code to make your problem go away. I can however try and point you in the right direction, so I will do just that. I think you need to learn what it means to rotate an object about a particular point in space, on any given axis. I think that googling this will give you enough information to do just that. Furthermore, I think you need to write more informative code, for starters you need to write comments on your code so that someone like myself can look at it and know what you are trying to do. Thirdly, I think that when you post examples, you should at the very least have tried to debug your code to see where the problem is, and if you have trouble finding a bug, I would create a dummy application to try things out in, and then at that point in time if things still aren't adding up, to come onto this forum and ask us a particular question about why some lines of code is not working. This doesn't mean that I am trying to defer answering the problem by telling you to solve it yourself, I am simply saying that I don't see how anyone could solve your problem by looking at what you have done, and judging by how you decided to go from one method implementation to the other so naively without doing the proper research, I still don't see how anyone can help you solve your problem.
  7. Daniel Ricci

    rotating sprites

    What exactly are you expecting us to answer here? It sounds like you are trying to hack together an assignment problem.
  8. There is nothing wrong with wanting to do a `good job` from a programmers point of view, such as adding good comments, re-using code, refactoring other code to work better, all in the event to solve your problem. Obviously you want to show off your skills, however keep in mind that programming is the simple break down of the english vocabulary of the problem you are trying to solve, and generally speaking if it's too complicating the work you are doing, chances are that you are overthinking the solution. When someone does my code review, I don't go into technical details of the code that I wrote, because my code is simple enough and the comments are very well written to the point where anyone with a general background in programming can get the idea of what I am doing, however I never back down on giving a good explanation of the code that I write. When you work with other people that have different disciplines, remember that you are one part of the big picture, and the world doesn't revolve around Singletons and Factory design patterns, or Big Endian vs Little Endian, it revolves around "This customer is willing to pay us good money for this product". So there should be a fine line between the solution you are trying to apply, and when you are satisfied you have gone far enough and are ready to hand it in. This doesn't mean that you should make every variable and function static just to get the product in the hands of the customer, it just means that with years of experience you start to develop a sixth sense for knowing something can be done better and faster, and easier.
  9. Daniel Ricci

    Status Update

    Yes, once the game is complete I would ideally like to branch off from the original design and come up with some new ideas that would make the game even more fun to play.
  10. Daniel Ricci

    Status Update

    For the past year during my spare time, I have been working on re-creating the Windows 98 version of Solitaire using Java. Prior to working on Solitaire, I made a few others board games while re-using a code base that I have built up over time that makes Swing a bit more bearable and re-usable. I recently remade a Windows 98 version of Minesweeper, available on my GitHub as well. I have decided to try and keep an updated blog on this website, posting updates about my progress as a Computer Scientist. Hopefully, the work that I am doing is able to help motivate others in completing their own personal projects, and I hope everyone is able to make use of some of the work that I am doing. Before I go into where I am at right now for the Solitaire remake, I want to share with everyone a bit of background history. For the past two years since I left my full-time job working at a gaming company in Montreal, I decided to go back to my roots and work on some games that would teach me the fundamental concepts of completing a project, among other core experiences such as not losing focus on a task, and always moving forward even when there are roadblocks. Fast-forward to today, and I have completed a few games such as Tic-Tac-Toe, Checkers, Chess, Minesweeper, and am currently working on a Solitaire game. I have been learning a lot about myself during my experiences making these games, and I am using that knowledge to make bigger and better things, and posting it all on GitHub for everyone to use, hopefully to one day make an impact in other peoples lives. I could spend a lot more time talking about myself and my journey, however right now at this time I want to show off a bit of the Solitaire game that I am working on and where I am at right now. Maybe in other blog posts, I will go a bit more into my own details as a Computer Scientist. This is what the game looks like right now in its current state. I will go through the features that I have implemented so far, and will then go through what I am working on right now. So far I have implemented the following. 1. The options menu. I have implemented everything in the options menu except for the `Draw Three` feature, and the sub-features associated to `Draw Three` such as the number of times you can go through the deck, scoring with respect to `Draw Three`, etc. You can play a timed game, change the visibility of the status bar at the bottom of the game, you can go from an outline view to a non-outline view when dragging the cards, and you can choose between three scoring modes along with a cumulative scoring option when playing in `Vegas` 2. Outline vs non-outline dragging Here is outline dragging and non-outline dragging when playing the game. I tried to make the outline highlight work the same as the original game, which was simply by using an XOR bit-mask whenever a collision between the border of the proxy card was dragged over a particular card, as you can see with the Queen of Diamonds and the Jack of Spades. Here is a non-outline drag. Notice that the card is moved and you can see the backside of the card that it was originally hiding. Here is a list of other features that I worked on so far. Setting up the board and where the cards will be positioned Being able to cycle through the cards at the top-left Being able to drag a card from one location to another Being able to place a card somewhere, the logic and architecture used to detect when this is possible and to place the card or put it back where it started from Placing a card on the foundation stacks (the four placeholder squares that you see right now), and determining if the game has been won The options menu shown above Timed game, which will show at the bottom right of your screen when you have a status bar that is visible Scoring Standard which uses some basic rules, I just had to research them and implement it Vegas scoring. I also looked this up and implemented it, also some slight formatting changes Cumulative scoring, this wasn't too difficult to implemented, it was just a matter of persisting your score when playing a new game Saving the options chosen within the options menu, and when certain options would change such as how many cards were drawn, a game reset would occur Outline dragging. This was by far one of the most interesting things that I implemented throughout this game. Normal dragging. I implemented this first before going into the outline dragging mode Double-clicking on a card to auto move it to the foundation pile (if applicable) Lots of bug fixes along the way Right now I am working on being able to choose which deck image you want to play the game with. I have the images on hand and I have imported them into my game, all that is left is to mock up the dialog window and position the images similar to the original game. So far this is where I am at with my game. You can always follow my progress by following the game located at https://github.com/danielricci/solitaire Sorry that I did not go into any technical details, this is my first blog post and I am nervous enough as it is. I hope you all enjoy reading this, and I will try to answer any questions in the comments. Take care, until my next blog post.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!