Spot The Difference Game skeleton

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
User avatar
SusanTheCat
Miko-Class Veteran
Posts: 952
Joined: Mon Dec 13, 2010 9:30 am
Location: New Brunswick, Canada
Contact:

Spot The Difference Game skeleton

#1 Post by SusanTheCat » Fri Jan 29, 2016 8:49 am

I made a system for making a "Spot the Difference" game in Ren'Py. You are welcome to use the code any way you see fit. I do not provide any support (mostly because I am currently dealing with brain lesions from cancer)

Features:
- left and right image
- click on either side
- random differences


First step is to make the base image file:
difference.png
Base File
Then make another overlay image the same size as the base image:
difference_changes.png
Overlay File
When you are making the images, try to not have the differences overlap. If you are feeling clever, you can have the overlay be transparent as long as it completely hides the original image.

Now you have to make a map of all the differences.
image_map.png
I used an Imagemap generator, then found out that DangKem made an awesome HotSpot tool http://lemmasoft.renai.us/forums/viewto ... 52&t=31723 You make rectangular HotSpots where the differences are. The HotSpot Tool will then spit out code that looks like this:

Code: Select all

    hotspot(40,252,50,80) action 
    hotspot(127,223,44,113) action 
    hotspot(265,216,53,94) action 
    hotspot(188,261,35,29) action 
You'll need to change it to look like this:

Code: Select all

init python:
    diff_items = []
    
    diff_items.append(STD_Item("images/overlay.png", 40,252,50,80))
    diff_items.append(STD_Item("images/overlay.png", 127,223,44,113))
    diff_items.append(STD_Item("images/overlay.png", 265,216,53,94)) 
    diff_items.append(STD_Item("images/overlay.png", 188,261,35,29))
STD_Item("overlay image file",x,y,width,height) makes a cutout image of just the difference and stores whether the difference is turned on on the left and/or right.

The next step is to create the SpotTheDifference image and start the interaction:

Code: Select all

    python:
        std = SpotTheDifference("images/base.png", diff_items)
        std.randomizeItems(5)
        ui.add(std)
        winner = ui.interact(suppress_overlay=False, suppress_underlay=False)
SpotTheDifference("base image file", list_of_STD_Items) Creates two images side by side
SpotTheDifference.randomizeItems(num_of_differences) randomizes the items turning on the overlay then it makes a number of differences based on the number passed.

When the user clicks on a difference, it changes the clicked side to match the other side. So if you click on the left, it changes the left image to match the right image.

Code: Select all

    image std_img = afterImage("base image file", list_of_STD_Items)
    show std_img 
afterImage("base image file", list_of_STD_Items) Creates the final image

That's the basics of using it. If I get some time, I with delve into the code to explain it a bit more. As I said before, I am dealing with brain lesions which have hampered my language skills (causing me to use words like hampered :). )

This code is provided as is. This is not the best way do get this effect, but it is the way my brain can handle.

Susan

PS: I am aware of what STD normally stands for. My dark sense of humour took over.
Attachments
SpotTheDifference-1.0-all.zip
The program -- Win, Mac, Linux source included
(24.85 MiB) Downloaded 171 times
" It's not at all important to get it right the first time. It's vitally important to get it right the last time. "
— Andrew Hunt and David Thomas

User avatar
PyTom
Ren'Py Creator
Posts: 15476
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

Re: Spot The Difference Game skeleton

#2 Post by PyTom » Sat Jan 30, 2016 2:44 am

I'd like to thank you for pushing through and making this. I'm sure many people on the forum will find this useful.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
"Silly and fun things are important." - Elon Musk
Software > Drama • https://www.patreon.com/renpytom

User avatar
SusanTheCat
Miko-Class Veteran
Posts: 952
Joined: Mon Dec 13, 2010 9:30 am
Location: New Brunswick, Canada
Contact:

Re: Spot The Difference Game skeleton

#3 Post by SusanTheCat » Sun Jan 31, 2016 8:35 pm

I made a game using this for Global Game Jam. I added scoring and a Give Up button.

http://globalgamejam.org/2016/games/scottish-game

Susan
Attachments
screenshot0002_3.png
" It's not at all important to get it right the first time. It's vitally important to get it right the last time. "
— Andrew Hunt and David Thomas

User avatar
SusanTheCat
Miko-Class Veteran
Posts: 952
Joined: Mon Dec 13, 2010 9:30 am
Location: New Brunswick, Canada
Contact:

Re: Spot The Difference Game skeleton

#4 Post by SusanTheCat » Tue Feb 09, 2016 6:42 pm

I added more comments to explain the code

difference.rpy

Code: Select all

init python:

    import pygame
    
    # this keeps track of the potential images
    # and there current state on either side
    class STD_Item(renpy.Displayable):
        def __init__(self,myimage,x,y,w,h, **kwargs):

            # Pass additional properties on to the renpy.Displayable
            # constructor.
            renpy.Displayable.__init__(self, **kwargs)

            self.myimage = im.Crop(myimage,x,y,w,h)

            self.x = x
            self.y = y
            self.w = w
            self.h = h
            
            self.left = False
            self.right = False
    

            
    class SpotTheDifference(renpy.Displayable):

        def __init__(self, child, diff_items, **kwargs):

            # Pass additional properties on to the renpy.Displayable
            # constructor.
            super(SpotTheDifference, self).__init__(**kwargs)

            # The child.
            self.child = renpy.displayable(child)

            # The width and height of us, and our child.
            self.width = 0
            self.height = 0
            self.width_offset = 0
            self.height_offset = 0
            
            self.diff_items = diff_items

        def render(self, width, height, st, at):

            # Create a render from the child.
            child_render = renpy.render(self.child, width, height, st, at)

            # Get the size of the child.
            self.width, self.height = child_render.get_size()
            self.x_offset = width/2 - self.width
            self.y_offset = height/2 - self.height/2

            # Create the render we will return.
            # twice the width of the child since there are two images.  
            # The extra hundred at the bottom is to show the stats
            render = renpy.Render(self.width*2, self.height+100)

            # Blit (draw) the child's render to our render.
            # two copies of just the base image
            render.blit(child_render, (0 + self.x_offset, 0 + self.y_offset))
            render.blit(child_render, (self.width + self.x_offset, 0 + self.y_offset))
            
            
            # Now we are going through all the potential differences.
            # Each difference knows whether to add the new image to both sides,
            # neither side, or if the sides are actually different
            for index,i in enumerate(self.diff_items):
                # Create a render from the child.
                diff_render = renpy.render(i.myimage, width, height, st, at)
                if (i.left):
                    render.blit(diff_render, (i.x + self.x_offset, i.y + self.y_offset))
                if (i.right):
                    render.blit(diff_render, (i.x+self.width + self.x_offset, i.y + self.y_offset))
                    
            # get score and display it under the images
            score = self.count_differences()
            score_txt = Text("Differences: %d" % (score), size=24)
            score_img = renpy.render(score_txt, width, height,  st, at)
            render.blit(score_img, (self.width - 100 + self.x_offset,self.height+ 10 + self.y_offset))

            # Return the render.
            return render
            
            
        def count_differences(self):
            # here we are running through the potential differences, 
            # and counting the ones theat are actually different
            myscore = 0
            for index,i in enumerate(self.diff_items): 
                if i.right != i.left:
                    myscore += 1
            return myscore
            
        def event(self, ev, x, y, st):
            if ev.type == pygame.MOUSEBUTTONUP: 
            # it's a mouse click
            # Check if one of the items
                for index,i in enumerate(self.diff_items): 
                    if i.left != i.right:
                        #left side
                        if (i.x + self.x_offset <= x <= i.x + i.w + self.x_offset) and (i.y + self.y_offset <= y <= i.y + i.h + self.y_offset) :  
                            i.left = i.right
                            renpy.sound.play("sounds/cartoon009.wav", channel=1)
                        #right side
                        elif (i.x + self.x_offset + self.width <= x <= i.x + self.width + i.w + self.x_offset) and (i.y <= y <= i.y + i.h + self.y_offset):   
                            i.right = i.left 

                            renpy.sound.play("sounds/cartoon009.wav", channel=1)                  
                            
               
                
                if self.count_differences() == 0:
                    # There is no reason this is 10
                    return (10)
                # update the image
                renpy.redraw(self,0) 
        def visit(self):
            return [ self.child ]
            
        def randomizeItems(self, difference_count):
            #randomzing at start:
            # both sides are still the same
            for index,i in enumerate(self.diff_items): 
                i.left = i.right = renpy.random.choice([True, False])
                
            # I count interations incase the computer can't make enough differences
            # or is taking too long
            iterations = 0
            while self.count_differences() < difference_count and iterations < 100:
                # Pick one of the items
                i = renpy.random.choice(self.diff_items)
                # randomize the left side
                i.left = renpy.random.choice([True, False])
                # make the right side the opposite
                i.right = not i.left
                iterations += 1
                
    # This just displays the image with the given differences            
    class afterImage(renpy.Displayable):
        def __init__(self, child, diff_items, **kwargs):

            # Pass additional properties on to the renpy.Displayable
            # constructor.
            super(afterImage, self).__init__(**kwargs)

            # The child.
            self.child = renpy.displayable(child)

            # The width and height of us, and our child.
            self.width = 0
            self.height = 0
            
            self.diff_items = diff_items
            
            
        def render(self, width, height, st, at):

            # Create a render from the child.
            child_render = renpy.render(self.child, width, height, st, at)

            # Get the size of the child.
            self.width, self.height = child_render.get_size()

            # Create the render we will return.
            render = renpy.Render(self.width, self.height)

            # Blit (draw) the child's render to our render.
            render.blit(child_render, (0, 0))
            
            
            for index,i in enumerate(self.diff_items):
                # Create a render from the child.
                diff_render = renpy.render(i.myimage, width, height, st, at)
                if (i.left):
                    render.blit(diff_render, (i.x, i.y))

            # Return the render.
            return render

The code I used the the game jam is better with more bells and whistles. You can download the source code if you want to take a look.

Example gameplay:
https://youtu.be/EkYTr1xtYJg

Susan
" It's not at all important to get it right the first time. It's vitally important to get it right the last time. "
— Andrew Hunt and David Thomas

Post Reply

Who is online

Users browsing this forum: Google [Bot]