Matchy Snatchy

A simple card game inspired by Ittybeatty and Dirchansky's favourite animal/creatures.

A game made by ittybeatty and dirchansky!

In MATCHY SNATCHY, players are personal stylists who are tasked with building the best outfits for a suite of hot shot Clients to flaunt their looks at their next big Event!

HOW TO WIN

A stylist must accumulate the most Client cards by end of the game. To win Client cards, stylists try to score the highest amount of points by creating the best outfit for a Client, every round. The best outfits are ones that match the Event dress code, the Client’s preferences, and are the most Eco-friendly. Watch out though—the other stylists are also competing to dress the same Client for the same Event. They have their eye on your rack, and might get snatchy...

The game mechanics aren't complicated: it's a point accumulation game, where every card has a point assigned to it. It requires both strategy and luck. Hopefully when we're allowed to safely visit each other again, I can play this game with people in real life!

Background: December game jam

Over December 2020, I had the privilege and pleasure to collaborate with Bea on a wholesome card game. She was craving to create something, while I was waffling around, needing external distraction from the roaches. Bea lives on the west coast while I live on the east coast, but with the power of dropbox file syncing, jitsi meet, and cryptpad (UX tradeoffs for privacy), we were able to collaborate quite well! We agreed to dedicate 3 days a week (~5-7h/day) to make a MVP game by the end of the month. We also had a secondary goal of learning how to use the Affinity suite, so that we could both eventually wean ourselves off of the $$$ Adobe suite.

Overall, the game jam was a big success! We learned a lot about Affinity (lots of habits to unlearn from Adobe ecosystem) and we ended up going higher fidelity than we both expected; we made 2 very limited printed copies for ourselves! We also had great laughs along the way, including delighting each other with Friday Night (Yakuza 0) in the late afternoon.

v00

The premise for the game was inspired by plushies and pets in our lives. At some point Bea drew clothing over some of mine, and I was completely smitten.

photo of several animal plushes, with digitally drawn on clothing

We started our brainstorming in a shared doc, typing as we spoke to each other. We used a game design framework as a starting point to talk through goals, style, genre, etc. Then we made an asset list spreadsheet. We were both most excited by the "client" cards, so those were hashed out pretty early on, haha.

We had over 100 item cards shortlisted, an early on, an elaborate stat system linked to each item card. Our heads began to spin because we couldn't figure out how to even score our own game. We knew we had to make some fundamental changes to our original plan, which then took a few days to pare down, so that the game didn't feel like a drag to score.

This version was super scrappy and had a lot of placeholder images from the internet. We laughed because our early design work looked like those ads that you tape/staple to lamp posts on the street.

We play tested the game over webcam, but only Bea had the colour printer and cards, so we played with open hands. We started with very few "events" and "items" for this pass.

collage of screenshots of remote play testing

As we played, we took note of how the game mechanics and assets worked together, whether it was fun, and how long it took to set up/play the game.

v01

After the first play test we made adjustments to gameplay/rules and added more "events" and "items". We also balanced the number and features of cards available. I was responsible for balancing and writing instructions, while Bea took on visual design and colour palette.

I really like how Bea built in addition visual cues for item type based on the location and size of the colour fill. BRILLIANCE that really shined through when I could barely read the text off the webcam stream during the playtest.

collage of images showing the gentle progression of asset design fidelity across versions

When we did our 2nd playtest, we used the instructions as a guide along the way. This approach allowed us to see where there were inconsistencies or uncertainties in gameplay. Chosing consistent terminology was also important.

We ended up tying for win at the end of the game, so we had to think of new instructions on how to deal with ties.

v02

We both wanted to get a "slightly more professionally printed" copies for ourselves, so we let some print specs dictate the scope and quantity of cards that we would have in this iteration of the game. We added a final suite of "event" and "items" and did a design/visual pass on everything (cards, instructions, placemats, etc.). I proofread everything, while Bea did her magic on card backs and other design fine tuning. Since the game required colour matching, we added labels for any player who might have colour blindness. It was December 23rd, 2020 when we exported everything for print! Not only did we finish, but we finished early!

Screenshot of the placemat design

Screenshot of a client card, featuring Pinkey, drawn by Bea

The smaller cards were designed at standard playing card size, so we could get those printed at places that print customized decks (front and back). These cards were printed through Artscow.

photo of action and item cards

The rest of the materials haven't been printed yet (yes, a full year later) cause it ended up being quite expensive! It's still a MVP so it was hard to justify the cost. Someday...


Today's music post: 野良犬 by 刃頭 feat.ILL-BOSSTINO. I was making lunch and remembered this song from 2002. I'm not sure how I found it originally (was it really a Bleach connection?) but I remembering liking the beat and the sense of urgency/desperation with the voice and flow. ILL-BOSSTINO is from THA BLUE HERB, a group from Sapporo and they're still making music (e.g., ASTRAL WEEKS / THE BEST IS YET TO COME).

Renpy gallery tutorial

How I made an unlocking gallery in Ren'Py 7.0 for my visual novel/game, Come For a Drink.

Come For A Drink is my first game (ever) and also my first time using Ren'Py, a visual novel engine. I was pleasantly impressed with all the features available (especially the tutorial game packaged with the engine), however, I struggled with the official documentation, because I'm a python/game making newbie, overall it wasn't visual enough for me (a visual learner), and I also struggled to understand, architecturally, how all the rpy files worked together (or separately) when packaged.

Here's a quick visual tutorial on making a gallery in Ren'Py 7.0. Galleries are a nice way to track your progress in game (if you have multiple endings) and/or show off that fancy CG you made that would otherwise only be seen for a split second during game play.

Please note that I'm NOT an expert, I don't understand all this code, but this is working code that is in my game! It is the result of a lot of uninformed trial and error. There are 3 parts:

  • A. Create the gallery code (in gallery.rpy) and associate them with your image files
  • B. Add the link to your gallery to the game menu (screens.rpy)
  • C. Add persistent unlocks to your gameplay (in script.rpy)

A. Create the gallery code (in gallery.rpy) and associate them with your image files

What I've garnered from the internet is that it doesn't really/quite matter which rpy file you put your code into. I made an entirely new gallery.rpy file (same root folder as all your script/options/screens files) and dumped the code in there for my own sanity/testing purposes. Full code for this part is at the end of PART A.

Let's unpack each bit of the code, sequentially.

init python:

   # Step 1. Create the gallery object.
    g = Gallery()

    g.locked_button = "locked.png" #this is the thumbnail image for ALL LOCKED gallery previews, found in the images folder
   # Step 2. Add buttons and images to the gallery.

   # A button that contains an image that automatically unlocks.
    g.button("ending1") #this is the name/label associated with your button for a particular image, can be modified
    g.condition("persistent.unlock_1") #this is the requirement/condition that must be met for this gallery image to unlock
    g.image("backgroundImageName1", "foregroundImageName1") #this creates a gallery image that overlaps a foreground on top of a bg, you can also use a single flattened image here 

g.button("ABCDEFG") The ABCDEFG name/label can be whatever you want; I have "ending1", but yours could be "gallery_image01" or what have you, as long as you remember what it is, because it comes back in step 3.

g.condition("persistent.unlock_ABCDEFG") I think you could potentially change the ABCDEFG of the condition name/label; I have persistent.unlock1 (where 1 is the name of my condition), but you could maybe try persistent.unlock_insertYourNewConditionNameHere?

Sometimes you want players to meet multiple conditions to be able to unlock your fancy gallery image. In my game, the player can only unlock the bonus content if they get all 9 endings, so I have multiple conditions listed, separated by and:

    g.button("bonus10")
    g.condition("persistent.unlock_1 and persistent.unlock_2 and persistent.unlock_3 and persistent.unlock_4 and persistent.unlock_5 and persistent.unlock_6 and persistent.unlock_7 and persistent.unlock_8 and persistent.unlock_9")  
    g.image("bonus10")

g.image("ABCDEFG", "HIJKLMNOP") You can call in multiple images in order of background to foreground and create a final gallery image that is displayed when the player clicks on the (eventually unlocked) thumbnail. In this example, I have a background image named "backgroundImageName1" and a foreground image named "foregroundImageName1", both found in my images folder. You don't have to include the filename extension. You can also use a single image here if you don't want to rely on Ren'Py to generate the final gallery image for you (get rid of , "HIJKLMNOP") .

For each gallery image, you need to define:

  • unique name/label g.button("ABCDEFG")
  • condition(s) g.condition("persistent.unlock_ABCDEFG")
  • final gallery image(s) g.image("ABCDEFG", "HIJKLMNOP")

I have 11 in total. Once you have defined the above for each gallery item, we need the code that defines how the gallery appears on screen/in-game.

    #Step 3: generate the gallery and how it looks
screen gallery:

   # Ensure this replaces the main menu.
    tag menu

   # The background.
    add "bg_ceiling" #this is the bg image for the gallery; found in the images folder

By default the gallery replaces your game menu screen, which makes sense to me. To be honest, I only modified the background image of the gallery to be "bg_ceiling" (again, no file extension needed) found in my images folder.

Next we put our gallery thumbnails onto the gallery screen. I used a 4 (horizontal) x 3 (vertical) grid, which means I'd have 12 spots total for thumbnails...well, that's what I thought, but I only have spots for 11 images because it appears that one of the spots might be taken up by the "Return" link. Truth be told, I modified the amount of gallery content I had based on the fact that I couldn't figure out how to get the grid to work, HAHA.

# A grid of buttons.
    grid 4 3:

        xfill True
        yfill True

        # Call make_button to show a particular button.
        add g.make_button("ending1", "unlock1.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending2", "unlock2.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending3", "unlock3.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending4", "unlock4.png", xalign=0.5, yalign=0.5)

        add g.make_button("ending5", "unlock5.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending6", "unlock6.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending7", "unlock7.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending8", "unlock8.png", xalign=0.5, yalign=0.5) 

        add g.make_button("ending9", "unlock9.png", xalign=0.5, yalign=0.5)  
        add g.make_button("bonus10", "unlock10.png", xalign=0.5, yalign=0.5)      
        add g.make_button("bonus11", "unlock11.png", xalign=0.5, yalign=0.5)  

        #return to main menu
        textbutton "Return" action Return() xalign 0.5 yalign 0.5

The variables here are:

  • unique name/label (e.g., ending1), which should be the SAME as the unique name/label you defined in Step 2
  • unlocked thumbnail image file (e.g., unlock1.png, also found in your images folder)
  • position within the grid (e.g., xalign=0.5, yalign=0.5, which in this case horizontally and vertically centre aligns the image to the midpoint of the grid cell)

Here's what the gallery grid looks like when it's up and running. Sorry, my gallery is completely unlocked, so I had to mosaic images out, so it looks extra ugly. In your version, if everything is working out, it's likely that the "locked.png" thumbnail is shown here in lieu of my gross mosaic images, since you haven't coded in the unlock conditions into your game script yet. Also to note, you have no real way to navigate/get to your gallery screen yet to test if it works/looks the way you want, but that will be addressed in Part B.

This was the hardest part of the tutorial. Save and close out of gallery.rpy!

Full code for this gallery.rpy part is below, which includes 11 gallery items.

###############GALLERY##################
init python:

   # Step 1. Create the gallery object.
    g = Gallery()

    g.locked_button = "locked.png" #this is the thumbnail image for ALL LOCKED gallery previews, found in the images folder

   # Step 2. Add buttons and images to the gallery.

   # A button that contains an image that automatically unlocks.
    g.button("ending1") #this is the name/label associated with your button for a particular image
    g.condition("persistent.unlock_1") #this is the requirement/condition that must be met for this gallery image to unlock
    g.image("backgroundImageName1", "foregroundImageName1") #this creates a gallery image that overlaps a foreground on top of a bg, you can also use a single flattened image here 

    g.button("ending2")
    g.condition("persistent.unlock_2")
    g.image("backgroundImageName2", "foregroundImageName2")

    g.button("ending3")
    g.condition("persistent.unlock_3")
    g.image("backgroundImageName3", "foregroundImageName3")

    g.button("ending4")
    g.condition("persistent.unlock_4") 
    g.image("backgroundImageName4", "foregroundImageName4")

    g.button("ending5")
    g.condition("persistent.unlock_5")
    g.image("backgroundImageName5", "foregroundImageName5") 

    g.button("ending6")
    g.condition("persistent.unlock_6")
    g.image("backgroundImageName6", "foregroundImageName6")

    g.button("ending7")
    g.condition("persistent.unlock_7")
    g.image("backgroundImageName7", "foregroundImageName7")

    g.button("ending8")
    g.condition("persistent.unlock_8")  
    g.image("endingImageName8") 

    g.button("ending9")
    g.condition("persistent.unlock_9")  
    g.image("endingImageName9")

    g.button("bonus10")
    g.condition("persistent.unlock_1 and persistent.unlock_2 and persistent.unlock_3 and persistent.unlock_4 and persistent.unlock_5 and persistent.unlock_6 and persistent.unlock_7 and persistent.unlock_8 and persistent.unlock_9")  
    g.image("bonus10")

    g.button("bonus11")
    g.condition("persistent.unlock_1 and persistent.unlock_2 and persistent.unlock_3 and persistent.unlock_4 and persistent.unlock_5 and persistent.unlock_6 and persistent.unlock_7 and persistent.unlock_8 and persistent.unlock_9")  
    g.image("bonus11")  

    #Step 3: generate the gallery and how it looks
screen gallery:

   # Ensure this replaces the main menu.
    tag menu

   # The background.
    add "bg_ceiling" #this is the bg image for the gallery; found in the images folder

   # A grid of buttons.
    grid 4 3:

        xfill True
        yfill True

        # Call make_button to show a particular button.
        add g.make_button("ending1", "unlock1.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending2", "unlock2.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending3", "unlock3.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending4", "unlock4.png", xalign=0.5, yalign=0.5)

        add g.make_button("ending5", "unlock5.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending6", "unlock6.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending7", "unlock7.png", xalign=0.5, yalign=0.5)
        add g.make_button("ending8", "unlock8.png", xalign=0.5, yalign=0.5) 

        add g.make_button("ending9", "unlock9.png", xalign=0.5, yalign=0.5)  
        add g.make_button("bonus10", "unlock10.png", xalign=0.5, yalign=0.5)      
        add g.make_button("bonus11", "unlock11.png", xalign=0.5, yalign=0.5)  

        #return to main menu
        textbutton "Return" action Return() xalign 0.5 yalign 0.5

B. Add the link to your gallery to the game menu (screens.rpy)

Assuming you haven't made any big modifications to the language in your screens.rpy, open the file, search for the code screen navigation():, and navigate down to the else: statement, add the last line of code in the snippet below:

       else:

            #textbutton _("History") action ShowMenu("history")

            textbutton _("Save") action ShowMenu("save")

        textbutton _("Load") action ShowMenu("load")

        textbutton _("Settings") action ShowMenu("preferences")

        textbutton _("Gallery") action ShowMenu("gallery") #GALLERY LINK ADDED HERE

Last line of code adds the Gallery menu item to the game screen. In my version of the code, I commented-out the History link that were there by default, but you can keep yours in if you want.

FYI, the name "gallery" is arbitrary, but you need to call it the same thing between your gallery.rpy screens.rpy files.

Now you can save and close your screens.rpy file, reload your game, and click the "Gallery" link. It should bring you to the gallery page.

C. Add persistent unlocks to your gameplay (in script.rpy)

So your gallery screen works, but the gallery images are all LOCKED. Time to code in the conditions that the player needs to meet in order for the special image to be unlocked. In my game, the conditions were pretty straightforward, e.g., they had to get to a specific point in the dialogue. I just dumped the unlock code in the appropriate spot in my script.rpy file where the player needed to get to (in the dialogue) in order for the unlock to happen.


    p "Hello, I'm person p. Do you want to go out with me?" #fake dialogue

    y "I would love to!!!!!!!!!!"  #fake dialogue

    $ persistent.unlock_9 = True #once this interaction between person p and y has happened, they have met the condition for ending 9 to be unlocked.

If you recall from working on gallery.rpy, persistent.unlock_9 is the condition that needs to be met in order to unlock the gallery image 9.

For purposes of testing, I saved and closed out of script.rpy and reloaded the game,

I played through the game, knowing and making choices that will meet that conditions required to unlock ending 9 (aka reach the point in the dialogue where the game will know that $ persistent.unlock_9 = True), then revisited the gallery afterwards to see if the image was unlocked. After I felt confident that things were in working order, I added the rest of the $ persistent.unlock_ABCDEFG = True (for gallery images 1-11) throughout the script.

One thing to note is that when you package the file for distro/playing, you computer keeps your persistent data on your harddrive, so when you re-open your packaged game to play, you'll see that your game remembers what you've unlocked. Internet tells me that since the persistent data it's unique to your HD, other people won't have that presistent data on their HD when they download and play it on their computer, therefore, they will only see locked images until they themselves, meet the right conditions through game play.

That's all for now! More info/tutorials related to gallery making are below: