2018-02-19 02:41:47 +01:00
|
|
|
|
# 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.
|
|
|
|
|
|
2018-02-19 02:45:01 +01:00
|
|
|
|
![Ronery](screenshot-solitaire1.png)
|
2018-02-19 02:41:47 +01:00
|
|
|
|
|
|
|
|
|
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/).
|