clear-code-projects / PySimpleGuiUltimate

Resources for the ultimate introduction to simple python guis
93 stars 38 forks source link

The PSG Timer API #3

Open PySimpleGUI opened 1 month ago

PySimpleGUI commented 1 month ago

You can use a Window Timer to generate your 500 ms timer ticks instead of polling.

https://docs.pysimplegui.com/en/latest/documentation/module/timer_apis/

Here's the snake game code using a Window timer.

BTW, screenshots of programs like this would be great to drop into a readme! It looks nice!

image

import PySimpleGUI as sg
from random import randint

def convert_pos_to_pixel(cell):
    tl = cell[0] * CELL_SIZE, cell[1] * CELL_SIZE
    br = tl[0] + CELL_SIZE, tl[1] + CELL_SIZE
    return tl, br

def place_apple():
    apple_pos = randint(0, CELL_NUM - 1), randint(0, CELL_NUM - 1)
    while apple_pos in snake_body:
        apple_pos = randint(0, CELL_NUM - 1), randint(0, CELL_NUM - 1)
    return apple_pos

# game constants
FIELD_SIZE = 400
CELL_NUM = 10
CELL_SIZE = FIELD_SIZE / CELL_NUM

# snake
snake_body = [(4, 4), (3, 4), (2, 4)]
DIRECTIONS = {'left': (-1, 0), 'right': (1, 0), 'up': (0, 1), 'down': (0, -1)}
direction = DIRECTIONS['up']

# apple
apple_pos = place_apple()
apple_eaten = False

sg.theme('Green')
field = sg.Graph(
    canvas_size=(FIELD_SIZE, FIELD_SIZE),
    graph_bottom_left=(0, 0),
    graph_top_right=(FIELD_SIZE, FIELD_SIZE),
    background_color='black')
layout = [[field]]

window = sg.Window('Snake', layout, return_keyboard_events=True)

window.timer_start(500)     # start a repeating 500ms timer

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    if event == 'Left:37':
        direction = DIRECTIONS['left']
    if event == 'Up:38':
        direction = DIRECTIONS['up']
    if event == 'Right:39':
        direction = DIRECTIONS['right']
    if event == 'Down:40':
        direction = DIRECTIONS['down']

    if event == sg.EVENT_TIMER:

        # apple snake collision
        if snake_body[0] == apple_pos:
            apple_pos = place_apple()
            apple_eaten = True

        # snake update
        new_head = (snake_body[0][0] + direction[0], snake_body[0][1] + direction[1])
        snake_body.insert(0, new_head)
        if not apple_eaten:
            snake_body.pop()
        apple_eaten = False

        # check death
        if not 0 <= snake_body[0][0] <= CELL_NUM - 1 or \
                not 0 <= snake_body[0][1] <= CELL_NUM - 1 or \
                snake_body[0] in snake_body[1:]:
            break

        field.DrawRectangle((0, 0), (FIELD_SIZE, FIELD_SIZE), 'black')

        tl, br = convert_pos_to_pixel(apple_pos)
        field.DrawRectangle(tl, br, 'red')
        # draw snake
        for index, part in enumerate(snake_body):
            tl, br = convert_pos_to_pixel(part)
            color = 'yellow' if index == 0 else 'green'
            field.DrawRectangle(tl, br, color)

window.close()
PySimpleGUI commented 1 month ago

And for fun, a version that uses an Apple image and has a custom Icon.

image

import PySimpleGUI as sg
from random import randint

# game constants
FIELD_SIZE = 400
CELL_NUM = 10
CELL_SIZE = FIELD_SIZE / CELL_NUM

def convert_pos_to_pixel(cell):
    tl = cell[0] * CELL_SIZE, cell[1] * CELL_SIZE
    br = tl[0] + CELL_SIZE, tl[1] + CELL_SIZE
    return tl, br

def place_apple(snake_body):
    apple_pos = randint(0, CELL_NUM - 1), randint(0, CELL_NUM - 1)
    while apple_pos in snake_body:
        apple_pos = randint(0, CELL_NUM - 1), randint(0, CELL_NUM - 1)
    return apple_pos

def main():

    # snake
    snake_body = [(4, 4), (3, 4), (2, 4)]
    DIRECTIONS = {'left': (-1, 0), 'right': (1, 0), 'up': (0, 1), 'down': (0, -1)}
    direction = DIRECTIONS['up']

    # apple
    apple_pos = place_apple(snake_body)
    apple_eaten = False

    sg.theme('Green')
    field = sg.Graph(
        canvas_size=(FIELD_SIZE, FIELD_SIZE),
        graph_bottom_left=(0, 0),
        graph_top_right=(FIELD_SIZE, FIELD_SIZE),
        background_color='black')
    layout = [[field]]

    window = sg.Window('Snake', layout, return_keyboard_events=True, icon=icon())

    window.timer_start(500)     # start a repeating 500ms timer

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED:
            break
        if event == 'Left:37':
            direction = DIRECTIONS['left']
        if event == 'Up:38':
            direction = DIRECTIONS['up']
        if event == 'Right:39':
            direction = DIRECTIONS['right']
        if event == 'Down:40':
            direction = DIRECTIONS['down']

        if event == sg.EVENT_TIMER:

            # apple snake collision
            if snake_body[0] == apple_pos:
                apple_pos = place_apple(snake_body)
                apple_eaten = True

            # snake update
            new_head = (snake_body[0][0] + direction[0], snake_body[0][1] + direction[1])
            snake_body.insert(0, new_head)
            if not apple_eaten:
                snake_body.pop()
            apple_eaten = False

            # check death
            if not 0 <= snake_body[0][0] <= CELL_NUM - 1 or \
                    not 0 <= snake_body[0][1] <= CELL_NUM - 1 or \
                    snake_body[0] in snake_body[1:]:
                break

            field.DrawRectangle((0, 0), (FIELD_SIZE, FIELD_SIZE), 'black')

            tl, br = convert_pos_to_pixel(apple_pos)
            # field.DrawRectangle(tl, br, 'red')
            field.draw_image(data=apple(), location=tl)
            # draw snake
            for index, part in enumerate(snake_body):
                tl, br = convert_pos_to_pixel(part)
                color = 'yellow' if index == 0 else 'green'
                field.DrawRectangle(tl, br, color)

    window.close()

def icon():
    return b'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'

def apple():
    return b'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAHOElEQVR4nO2YbYhcVxnHf8+5985sZrubJpGmDa1oRJQEfMsnrbXGr0JFaOIXLYJQiq3QCmKExOn6pQhSS0GpH3ypIOouvoQi2IIY21RilVprExVt0thtst1kk8zuzp25957zPH64d2anm5nNJrSpgg8c7sy95+V3/+c5z3nOhf8bANJs4t5siKHWtP9CsGYT1/wt8SDcvh/Vt7+ZTH2bniYa/P/wU7y3+fPaE3c91JgB2LPq+aUsfj3hzBARwvee4aYcbvNd+US77T6SZ3H91VfixwB2HMWuOqA1cTM7S7hHjnCvRnw1iWRT3nW8+kqip04mPhQ2D3DsGHLVAWUKBXjkae5sTMo3FxdgqRX5udlYZo/XjEjiKOEIAHuAmasHKIA9fs/2m5ev98dn9eUvFGedzp92OjebxGdOJR5HbJnNZ/UNB6ElM3vLl3nDAK2EEkBmgO3NG+qdxWTGlilenY03LF2ImZ+NSVMXkprEAmhu9zz+wNyZ5q3EU7/DX8546/YHAzcDshfC6tZ/vnfn7qUoP/jj+sLEyTwwHgkGBHhusW73/WaqdajUGvZAtANsivUpeUlAK5VyPbDDbJkYT9w7OubHxcm57oZwenerdeGPD++6+fi/zh7+tbZmXrqBp8a8/v19PwjP7zzRHjsZ89bEs2Tw4pdhCUrQmRJyzVW9JqCBSNXBs/G1t0aBzwO3CLLVMKdQ5MJ5c/aseaZfur3RnJ/v/vU9T3YfPYN+6hz64Y6z6zJTpyXMnCBP+ki+dcD7wwMMIyFHAlrfz3bE75bTD9ad3D1eq5HVYoITNChkBVYUCJBhzMWh8DFJlCkdUVqqtE1JUQqMCEgADxqwh7pmXwK4H0xGQK61SERAn5VXvntdVPt0a2NDuxsb6hpjUeIc5gPa7uIvLOOXUvUYE4VL0lwtdWhmAohzCBFCgeGBULqKm0C+GMSN77dwF+BGqThUQYNIIPzJbfzsVkm+n107nsvWTUmyeUKiiQbEEZYXhMUUf3YRP3+efKlNitGhVKx/tZXfttK/CfgxSFKT2/cTfjYN0WsW4CjAamr5A5sn6hJe2LihcaNt22zJDVtccv1mok0TSC3GOjl+oUUxd47i1ALF3HnSIicVey0gSlpNcxgQySDUwBXwt8x01xRkK49WbFgq5AQsjuyWayS6Ka8n5sbHXDQ5TrxlktqNb6H2tutJtm0h2jxJNNHANepILSYCoqpTGVJWKRPlQAw76vB+wJpDBLsI8FBVSdVuScBc5FSiCKnFyFgNN3kNydZNuGs24OoJksRIHCGR9HtfDTUMsDKNAZz74CieixbJRyuJ1dmNZgiqmA9Y4bGsQBfb+BAI7Q6aF+V9r1iwQR/rFxgdQ6T0RcTs7SOqjF7FBhLM0G6OphlhsY1fWMTUSh/sZoRzS4SlFE27aF4QgIChrERgs/K61rZhuGuHrI/hgIeq2fBYGgR8luMuLCO1GAx0uVOtYk9oLZeQrTbBe4IwADlYwEboWEXp7ij4kQrmaqcyMYIarrUMGJoVRI1lqOKgtTuEC8sUyx1yjBzDVyX0ryXwMDwDUQCxl0f5wUWAZyqXCc5e6JhiImLBUzu/RNzuEuoJ4hwWFM1yfO7JUbIKMK8Ccg+uBztsfKGc+ljkeYCdQ9z1IsCjVaUsyHMtp1kdVw9gwVTibobr5uUGbaUyXqDABiCVHKMACltRdIh65spQ00lC+Mvg2KtfYlhjuR/kA278mUncrgCaIC5G+jGuSqf6AD31sgo0M6NbBephgJSBOsrhyFdMPyT9oV9rQ8+shyCaAs2wxwqUDqa9nSFFaVelt1N0KGG6PbgBJUfAAVgEmHBQyiA99LQ3ClABMo1+soDmXTRKUUv7YNaH7UH2AU3JbWW6R8EJRB3oqOpPq3tDKw8FnAJtgvsMS//ooL8ClRTTlT02DKg3oKKV6nVR8oHkYIiFOoghvzwAJ/ZUMzas4sgws7Pyz8KFry8GdxsiA1tW6YU9PwxWrtSiKn5k1ANK9cSDt9h9gyKsmTSv+bCXAj0o8aOTcEcX8a56qd5WpgOxzldB+RLmGxAvY9/Zb3aXlcnJyGZrftg5WkYTSa227xx2NkOjNqqDvpdWvpevA85AE4g78OK42b7mGonqugCnQPeC2096OnfcaZh4zDLMetN5yVPPigUHYuC96R33wYVjA2eeKwIEmIEwDdH+EH7RFe6uQeRK1/BD2AbzhJ6ZgY8gikFy4XMH4PfT5alueIZwOYAAe3uQqt9OhTsj6I5BLCugHiAGF5c+1b8vIA2IDeZzJ5/cr/rDJsTD0vthdlkfcnqL5muwqy5uX4CPj8EGR5mvB/hnBfXOsRKKDFKHTJuF5j7496izx+sCCP0DdwB4ALbj3McSuK5QPdyFI9vAzsK7nHO7BfJC9YkDcGJ12zfUmuCa63SPXn27AjHgChsNDkwFegys+pRBdfjpvYCu9zvM/6T9B0QuLmrphW7aAAAAAElFTkSuQmCC'

if __name__ == '__main__':
    main()