From a165bbcf289570016b166a5506d4f715348b2413 Mon Sep 17 00:00:00 2001 From: Martin Fitzpatrick Date: Mon, 19 Feb 2018 02:41:47 +0100 Subject: [PATCH] solitaire: Add README.md --- README.md | 6 ++++- paint/README.md | 6 ++--- solitaire/README.md | 60 ++++++++++++++++++++++++++++++++++++++++++ solitaire/solitaire.py | 4 +-- 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 solitaire/README.md diff --git a/README.md b/README.md index a2ec18c..19a91aa 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,12 @@ found [on my site](http://martinfitzpatrick.name/tag/pyqt). 1. [Currency converter](currency/) - "Doughnut" (PyQtGraph) 1. [Solitaire](solitaire/) - "Ronery" (QGraphicsScene) -# License +## License All code is **licensed under an MIT license**. This allows you to re-use the code freely, remixed in both commercial and non-commercial projects. The only requirement is to include the same license when distributing. + +## Other licenses + +Icons used in the applications are by [Yusuke Kamiyaman](http://p.yusukekamiyamane.com/). diff --git a/paint/README.md b/paint/README.md index 70616e9..649c6e5 100644 --- a/paint/README.md +++ b/paint/README.md @@ -6,16 +6,16 @@ ready made pictures of pie. Piecasso is a clone of the Paint programme from Windows 95 (ish) with a few additions (and subtractions). The programme features standard tools including pen, brush, fill, spray can, eraser, text and a number of -shape drawing widgets. +shapes. -![Piecasso](screenshot-paint.png) +![Piecasso](screenshot-paint2.png) You can copy from the image, with a custom shape, although pasting + floating is not supported. The canvas is a fixed size and loaded images are adjusted to fit. A stamp tool is also included which is pre-loaded with pictures of delicious pie. -![Piecasso](screenshot-paint2.png) +![Piecasso](screenshot-paint.png) > If you think this example app is neat and want to learn more about PyQt in general, [take a look at my ebook & online course diff --git a/solitaire/README.md b/solitaire/README.md new file mode 100644 index 0000000..03a1555 --- /dev/null +++ b/solitaire/README.md @@ -0,0 +1,60 @@ +# Ronery — A Solitaire game in PyQt + +The classic card Solitaire (Klondike) game with a North Korean / +'Team America: World Police' twist. The game is otherwise identical, + offering the same options. Built with PyQt, it uses QGraphicsScene + to handle the play area. + +![Ronery](screenshot-solitaire.png) + +The classic Solitaire win-screen is also implemented, although since +the play canvas is not a bitmap it doesn't "fill up". It's still +sufficiently satisfying. + +![Ronery](screenshot-solitaire2.png) + +The configuration options allow for 3-draw and 1 draw styles, with 3, 5 +or infinite rounds. + +## Code notes + +### Card handling + +The approach I used here was to treat each place where cards can be placed +as a 'stack' object, which handles the cards it currently holds. Each stack +is responsible for the layout of the cards on it's pile. + +A stack is also responsibly for accepting/rejecting an attempted drop of a +card on it. Some stacks, e.g. the deck + deal pile do not accept any drop. +Others, such as the finish piles, have specific rules. + +In most cases there is no relationship between any cards on a stack, with +the exception of the 'in play' stacks along the bottom. Here cards have +a parent-child relationship, allowing multiple cards to be dragged at once. + +### The end animation + +The end-game was a bit weird to implement. Since it happens 'outside' of +game time the first thought was to have a self contained loop, using +`QApplication.processEvents` to tick over. But that's nasty. + +Instead I used a timer, idle during play, which constantly pings an +animation step-forward endpoint. This moves cards (faking 'gravity', bouncing) +as well as re-stacking them once they're out of the play area. +Restacking uses the normal stacking code. + +The final step was to block event handling, otherwise the cards could +still be grabbed while they bounced (and dropped). The easiest way to +achieve this was to simply place an event-capturing object over the entire +window. + +## Other licenses + +The card images were made from a [freely available set of PNGs](https://github.com/hayeah/playing-cards-assets) +which were themselves auto-generated from SVGs traced from actual cards(!). +The original card designs are out of copyright. + +Note that the linked repository contains some custom art on ace cards which may still be copyrighted and so +was not used. + +Icons used in the application are by [Yusuke Kamiyaman](http://p.yusukekamiyamane.com/). diff --git a/solitaire/solitaire.py b/solitaire/solitaire.py index 4f625cf..e5db388 100644 --- a/solitaire/solitaire.py +++ b/solitaire/solitaire.py @@ -651,8 +651,8 @@ class MainWindow(QMainWindow): if card.pos().x() < - CARD_DIMENSIONS.width(): card.vector = None - drop = random.choice(self.drops) - drop.add_card(card) + # Put the card back where it started. + card.stack.add_card(card)