RGB Jallenge

This is a clone of The Great RGB Guessing Challenge.
The challenge works like this: You are presented three numbers ranging from 0 to 255 representing a rgb color and three color bubbles. To get a point you must choose the color bubble corresponding to the rgb values. The more points you get, the higher your score.

Controls

  • Click on the bubble to choose it

Choose the correct color. That was not it... Correct!


# Python 2.7.7 Code
# Pygame 1.9.1 (for Python 2.7.7)
# Jonathan Frech 8th of July, 2016

# importing needed modules
import pygame, sys, time, math, os, random, re
pygame.font.init()

""" CLASSES """
# vector class (2-dimensional)
class Vector():
    def __init__(self, p1, p2 = None):
        # get the vector as a 2-dimensional list
        if not p2:
            self.x = p1[0]
            self.y = p1[0]
        else:
            
            # get the vector between two points
            if type(p1) == type([]):
                self.x = p2[0] - p1[0]
                self.y = p2[1] - p1[1]
            
            # get the vector as two numbers
            else:
                self.x = p1
                self.y = p2

    # calculate the vector's length
    def length(self):
        return math.sqrt(self.x**2 + self.y**2)

    # multiply the vector by n
    def multiply(self, n):
        self.x *= n
        self.y *= n

    # unify the vector (set it's length to 1)
    def unify(self):
        l = self.length()
        if l != 0:
            self.multiply(1. / l)

    # set the vector's length
    def setlength(self, n):
        self.unify()
        self.multiply(n)

    # stick the vector to a position
    def stickto(self, p):
        return p[0] + self.x, p[1] + self.y

    # angles used in degrees!
    # conversion between radians and degrees
    def radians(self, phi):
        return (phi * (math.pi/180.)) % (2*math.pi)
    def degrees(self, phi):
        return (phi * (180./math.pi)) % 360

    # get the vector's angle
    def getangle(self):
        return self.degrees( math.atan2(self.y, self.x) )

    # set the vector's angle
    def setangle(self, phi):
        l = self.length()

        self.x = l * math.cos(self.radians( phi ))
        self.y = l * math.sin(self.radians( phi ))

    # add an angle phi to current rotation
    def rotate(self, phi):
        self.setangle(self.getangle() + phi)

class Screen():
    def __init__(self, size = None):
        if not size:
            self.size = [G.Width, G.Height]
        else:
            self.size = size

        self.width, self.height = self.size[0], self.size[1]

        self.surface = pygame.Surface(self.size)

    def swap(self):
        pass

    def render(self, surface):
        pass

    def tick(self):
        pass

    def handle(self, event):
        pass

class Button():
    def __init__(self, pos):
        self.pos = pos
        self.destsize = 40
        self.size = self.destsize
        self.destcolor = [255, 255, 255]
        self.color = self.destcolor[:]

    def render(self, surface):
        pygame.draw.circle(surface, self.color, self.pos, int(self.size))

    def tick(self):
        self.size += (self.destsize - self.size) / 15.

        for c in range(0, 3):
            self.color[c] += (self.destcolor[c] - self.color[c]) / 20.

    def hovered(self, mouse):
        if Vector(mouse, self.pos).length() <= self.size:
            return True

        return False

class mainScreen(Screen):
    def __init__(self):
        Screen.__init__(self)

        self.font = pygame.font.Font(pygame.font.match_font("Times"), 50)

        self.buttons = []
        for x in range(0, 3):
            self.buttons.append(Button([
                self.width/3*x+self.width/6,
                self.height/3*2
            ]))

        self.game = True
        self.failed = False
        self.score = 0
        self.colornames = []
        self.selectedcolor = 0
        self.resetcolors()

    def resetcolors(self):
        self.colornames = []
        for b in self.buttons:
            color = [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]
            b.destcolor = color[:]
            self.colornames.append(color[:])

        self.selectedcolor = random.randint(0, 2)

    def resetbuttons(self):
        for b in self.buttons:
            b.destsize = 40

    def render(self, surface):
        self.surface.fill([20, 20, 20])

        txt1 = self.font.render("Score: " + str(self.score), True, [255, 255, 255])
        rct1 = txt1.get_rect()
        pos1 = [(self.width-rct1.right)/2, 20]

        txt2 = self.font.render(re.sub("\[", "(", re.sub("\]", ")", "rgb" + str(self.colornames[self.selectedcolor]))), 200, [255, 255, 255])
        rct2 = txt2.get_rect()
        pos2 = [(self.width-rct2.right)/2, 20 + rct1.bottom + 20 + 20]

        if self.game:
            self.surface.blit(txt1, pos1)
            self.surface.blit(txt2, pos2)

        for b in self.buttons:
            b.render(self.surface)

        if not self.game:
            if not self.failed:
                txt3 = self.font.render("That's right!", True, [255, 255, 255])
                rct3 = txt3.get_rect()
                pos3 = [(self.width-rct3.right)/2, 20]
                self.surface.blit(txt3, pos3)
            else:
                txt4 = self.font.render("Too bad :(", True, [255, 255, 255])
                rct4 = txt4.get_rect()
                pos4 = [(self.width-rct4.right)/2, 20]

                txt5 = self.font.render("Score: " + str(self.score), True, [255, 255, 255])
                rct5= txt5.get_rect()
                pos5 = [(self.width-rct5.right)/2, 20 + rct4.height + 20 + 20]
                
                self.surface.blit(txt4, pos4)
                self.surface.blit(txt5, pos5)


        surface.blit(self.surface, [0, 0])

    def tick(self):
        if self.game:
            for b in self.buttons:
                if b.hovered(intpos(pygame.mouse.get_pos())):
                    b.destsize = 50
                else:
                    b.destsize = 40

        for b in self.buttons:
            b.tick()

    def handle(self, event):
        if self.game:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    for b in self.buttons:
                        if b.hovered(intpos(pygame.mouse.get_pos())):
                            self.game = False
                            b.destsize = (self.width + self.height)
                            self.buttons.remove(b)
                            self.buttons.append(b)
                            
                            if b.destcolor == self.colornames[self.selectedcolor]:
                                self.score += 1
                            else:
                                self.failed = True

                            break

        else:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    self.resetcolors()
                    self.resetbuttons()
                    
                    self.game = True
                    if self.failed:
                        self.score = 0
                        self.failed = False

""" FUNCTIONS """
# returns an integer version of given position
def intpos(_pos):
    return [int(_pos[0]), int(_pos[1])]

""" GAME """
# game class
class Game():
    def __init__(self):
        # screen (class)
        self.screenname = "main"
        

        # screen (window)
        self.Width, self.Height = 600, 400
        self.Size = [self.Width, self.Height]
        self.Screen = pygame.display.set_mode(self.Size)

        # running variables
        self.ticks = 0
        self.running = True

        # functions
        pygame.display.set_caption("RGB Jallenge")
    
    # further initialization
    def init(self):
        self.screens = {
            "main": mainScreen()
        }

    # get the screen based on name
    def screen(self):
        if self.screenname in self.screens:
            return self.screens[self.screenname]
        else:
            return Screen()

    def swapscreen(self, name = ""):
        self.screenname = name
        self.screen().swap()

    # tick function
    def tick(self):
        # handle events
        for event in pygame.event.get():
            
            # quit when window is closed
            if event.type == pygame.QUIT:
                self.quit()

            # handle key presses
            if event.type == pygame.KEYDOWN:
                # F12 quits
                if event.key == pygame.K_F12:
                    self.quit()

                # F1 screenshots
                if event.key == pygame.K_F1:
                    self.screenshot()

            # handle screen
            self.screen().handle(event)

        # tick screen
        self.screen().tick()

    # render function
    def render(self):
        # fill
        self.Screen.fill([0, 0, 0])
        
        #render screen
        self.screen().render(self.Screen)
        
        # flip
        pygame.display.flip()
    
    # quits
    def quit(self):
        self.running = False

    # takes a screenshot
    def screenshot(self):
        # define path
        path = os.getcwd() + "/out/"
        
        # try to save
        try:
            # create path
            if not os.path.isdir(path):
                os.mkdir(path)
            
            # define name
            name = "img" + str(len(os.listdir(path))) + ".png"

            # save image
            pygame.image.save(self.Screen, path + name)
        
        # save failed somehow
        except:
            pass

    # run function (uses tick() and render())
    def run(self):
        ticksPerSecond = 60
        lastTime = time.time() * 1000000000
        nsPerTick =  1000000000.0 / float(ticksPerSecond)
    
        ticks = 0
        frames = 0
    
        lastTimer = time.time() * 1000
        delta = 0.0
        
        while self.running:
            now = time.time() * 1000000000
            delta += float(now - lastTime) / float(nsPerTick)
            lastTime = now
            shouldRender = False
                    
            while delta >= 1:
                ticks += 1
                self.ticks += 1
                self.tick()
                delta -= 1
                shouldRender = True
            
            if shouldRender:
                frames += 1
                self.render()
            
            if time.time() * 1000 - lastTimer >= 1000:
                lastTimer += 1000
            
                frames = 0
                ticks = 0

# start game
G = Game()
G.init()
G.run()
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s