Mer interaktiv grafikk
Innholdet på denne siden er ikke en del av pensum i INF100 dette semesteret, og vil ikke komme på eksamen. Vi publiserer det her slik at dem som ønsker å jobbe med åpen oppgave kan få inspirasjon og lære mer om mulighetene som finnes i
uib_inf100_graphics
-rammeverket.
- Innebygde tastaturbindinger
- Brukerstyrte hendelser
- Dialogbokser og popup
- Bilder
- Animerte bilder
- Modus (ulike skjermer)
- Scrolling
- Spille av lyder
Innebygde tastaturbindinger
from uib_inf100_graphics import *
def app_started(app):
app.counter = 0
def timer_fired(app):
app.counter += 1
def redraw_all(app, canvas):
canvas.create_text(200, 50,
text='Tastaturbindinger demo',
font='Arial 20',
fill='black')
canvas.create_text(200, 100,
text='Trykk ctrl-p for pause', fill='black')
canvas.create_text(200, 150,
text='Trykk ctrl-s for å ta skjermbilde', fill='black')
canvas.create_text(200, 200,
text='Trykk ctrl-q for å lukke', fill='black')
canvas.create_text(200, 250,
text='Trykk ctrl-x for å avslutte alt', fill='black')
canvas.create_text(200, 300, text=f'{app.counter}', fill='black')
run_app(width=400, height=400) # ctrl-q fortsetter videre, ctrl-x gjør ikke
run_app(width=600, height=600)
Brukerstyrte hendelser
from uib_inf100_graphics import *
def app_started(app):
app.messages = ['app_started']
def app_stopped(app):
app.messages.append('app_stopped')
print('app_stopped!')
def key_pressed(app, event):
app.messages.append('key_pressed: ' + event.key)
def key_released(app, event):
app.messages.append('key_released: ' + event.key)
def mouse_pressed(app, event):
app.messages.append(f'mouse_pressed {(event.x, event.y)}')
def mouse_released(app, event):
app.messages.append(f'mouse_released {(event.x, event.y)}')
def mouse_moved(app, event):
app.messages.append(f'mouse_moved {(event.x, event.y)}')
def mouse_dragged(app, event):
app.messages.append(f'mouse_dragged {(event.x, event.y)}')
def size_changed(app):
app.messages.append(f'size_changed {(app.width, app.height)}')
def redraw_all(app, canvas):
font = 'Arial 20 bold'
canvas.create_text(app.width/2, 30, text='Brukerstyrte hendelser',
font=font, fill='black')
n = min(10, len(app.messages))
i0 = len(app.messages)-n
for i in range(i0, len(app.messages)):
canvas.create_text(app.width/2, 100+50*(i-i0),
text=f'#{i}: {app.messages[i]}',
font=font, fill='black')
run_app(width=600, height=600)
Dialogbokser og popup
from uib_inf100_graphics import *
def app_started(app):
app.message = 'Klikk med musen for å starte!'
app.count = 0
def timer_fired(app):
app.count += 1
def mouse_pressed(app, event):
name = app.get_user_input('Hva heter du?')
if (name == None):
app.message = 'Du avbrøt!'
else:
app.show_message('Du skrev: ' + name)
app.message = f'Hei, {name}!'
def redraw_all(app, canvas):
font = 'Arial 24 bold'
canvas.create_text(app.width/2, app.height/2,
text=app.message, font=font, fill='black')
canvas.create_text(app.width/2, app.height*5/6,
text=f"{app.count}", font=font, fill='black')
run_app(width=500, height=300)
Bilder
# Vis et bilde hentet fra internett
from uib_inf100_graphics import *
def app_started(app):
url = 'https://tinyurl.com/inf100logo-png'
app.image1 = app.load_image(url)
app.image2 = app.scale_image(app.image1, 2/3) # Skalérer bildet
def redraw_all(app, canvas):
canvas.create_image(200, 300, pil_image=app.image1)
canvas.create_image(500, 300, pil_image=app.image2)
run_app(width=700, height=600)
For å vise et bilde lagret lokalt på datamaskinen, husk at filstien til bildet er relativ til mappen programmet kjøres fra, en mappe som ikke nødvendigvis er den samme mappen hvor programmet ligger. For å kjøre eksempelkoden under, last ned testbilde.gif.
# Vis et bilde lagret lokalt på datamaskinen
from uib_inf100_graphics import *
def app_started(app):
app.image1 = app.load_image('testbilde.gif')
app.image2 = app.scale_image(app.image1, 2/3)
def redraw_all(app, canvas):
canvas.create_image(200, 300, pil_image=app.image1)
canvas.create_image(500, 300, pil_image=app.image2)
run_app(width=700, height=600)
# Ankeret bestemmer hvor bildet tegnes i forhold til koordinatet (x, y)
from uib_inf100_graphics import *
def app_started(app):
url = 'https://tinyurl.com/inf100logo-png'
app.image1 = app.load_image(url)
app.image2 = app.scale_image(app.image1, 1/2) # Skalérer bildet
def redraw_all(app, canvas):
x, y = app.width/2, app.height/2
# Prøv ulike verdier for anchor:
# "n", "s", "e", "w", "ne", "nw", "se", "sw", "center"
canvas.create_image(x, y, pil_image=app.image2, anchor="n")
canvas.create_image(x, y, pil_image=app.image2, anchor="sw")
canvas.create_oval(x-10, y-10, x+10, y+10, fill="yellow")
run_app(width=700, height=600)
# Finn bildet sin størrelse
from uib_inf100_graphics import *
def app_started(app):
url = 'https://tinyurl.com/inf100logo-png'
app.image1 = app.load_image(url)
app.image2 = app.scale_image(app.image1, 2/3)
def draw_image_with_size_below_it(app, canvas, image, cx, cy):
canvas.create_image(cx, cy, pil_image=image)
image_width, image_height = image.size
msg = f'Bildestørrelse: {image_width} x {image_height}'
canvas.create_text(cx, cy + image_height/2 + 20,
text=msg, font='Arial 20 bold', fill='black')
def redraw_all(app, canvas):
draw_image_with_size_below_it(app, canvas, app.image1, 200, 300)
draw_image_with_size_below_it(app, canvas, app.image2, 500, 300)
run_app(width=700, height=600)
# Bruk transpose-metoden for å snu eller flippe et bilde
from uib_inf100_graphics import *
def app_started(app):
url = 'https://tinyurl.com/inf100logo-png'
org_image = app.load_image(url)
org_image = app.scale_image(org_image, 1/4)
# Rotere et bilde 90 grader
rotated_image = org_image.transpose(Image.ROTATE_90)
app.images = [org_image, rotated_image]
# Flere måter å rotere/flippe et bilde på
app.images += [org_image.transpose(tp_method) for tp_method in (
Image.ROTATE_180,
Image.ROTATE_270,
Image.FLIP_LEFT_RIGHT,
Image.TRANSPOSE,
Image.FLIP_TOP_BOTTOM,
Image.TRANSVERSE,
)]
def redraw_all(app, canvas):
allocated_width_per_image = app.width / len(app.images)
for i, img in enumerate(app.images):
x = (i + 0.5) * allocated_width_per_image
y = app.height / 2
canvas.create_image(x, y, pil_image=img)
run_app(width=700, height=200)
# Hent farger med getpixel, og manipulér eller tegn nye bilder med putpixel
from uib_inf100_graphics import *
def app_started(app):
url = 'https://tinyurl.com/inf100logo-png'
app.image1 = app.load_image(url)
# la oss lage en kopi som kun bruker rødfarge
app.image1 = app.image1.convert('RGB')
app.image2 = Image.new(mode='RGB', size=app.image1.size)
for x in range(app.image2.width):
for y in range(app.image2.height):
r,g,b = app.image1.getpixel((x,y))
app.image2.putpixel((x,y),(r,0,0))
def redraw_all(app, canvas):
canvas.create_image(200, 300, image=ImageTk.PhotoImage(app.image1))
canvas.create_image(500, 300, image=ImageTk.PhotoImage(app.image2))
run_app(width=700, height=600)
# Bruk ImageDraw for å lage nye bilder og tegne på dem
from uib_inf100_graphics import *
def app_started(app):
image_width, image_height = app.width//3, app.height//2
bg_color = (0, 255, 255) # cyan
app.image1 = Image.new('RGB', (image_width, image_height), bg_color)
# Nå som vi har laget et nytt bilde, bruk ImageDraw for å tegne i det
# Se https://pillow.readthedocs.io/en/stable/reference/ImageDraw.html
draw = ImageDraw.Draw(app.image1)
draw.line((0, 0, image_width, image_height), width=10, fill=(255, 0, 0))
draw.line((0, image_height, image_width, 0), width=10, fill=(0, 0, 255))
# Så lager vi en skalert kopi for å vise at dette er et helt vanlig bilde
app.image2 = app.scale_image(app.image1, 2/3)
def redraw_all(app, canvas):
canvas.create_image(200, 300, pil_image=app.image1)
canvas.create_image(500, 300, pil_image=app.image2)
run_app(width=700, height=600)
# Bruk get_snapshot og save_snapshot for å ta bilde av programmet
# Merk: dette er litt ustabilt på noen operativsystemer, og kan
# kreve at du gir programmet spesiell tilgang for å ta screenshot
from uib_inf100_graphics import *
def app_started(app):
app.image = None
def key_pressed(app, event):
if (event.key == 'g'):
snapshotImage = app.get_snapshot()
app.image = app.scale_image(snapshotImage, 0.4)
elif (event.key == 's'):
app.save_snapshot()
def redraw_all(app, canvas):
canvas.create_text(350, 20, text='Press g to getSnapshot', fill='black')
canvas.create_text(350, 40, text='Press s to saveSnapshot', fill='black')
canvas.create_rectangle(50, 100, 250, 500, fill='cyan')
if (app.image != None):
canvas.create_image(525, 300, image=ImageTk.PhotoImage(app.image))
run_app(width=700, height=600)
Animerte bilder
En sprite er et bilde/en tegning som representerer en (liten) del av skjermbildet. I sammenheng med dataspill vil en sprite typisk være knyttet til et logisk element i spillet, slik som en figur, et hus, en fiende, en energidrikk, et stykke med gress eller lignende. Det er vanlig at sprites er animert; for eksempel en animasjon av at figuren går. En slik animasjon består av en sekvens med bilder som spilles av i ring. Under er et eksempel på en bildefil som representerer en animert figur.
Bilde: CC0, Walkin man figure av JayNick, via freesvg.org.
For å animere denne spriten, klipper vi opp bildet i 8 like store biter, og viser dem frem etter hverandre i et sirkulært mønster.
# En demo for å animere sprites med bruk av Pillow/PIL
# crop-metoden klipper ut en del av bildet
# Se her for flere detaljer:
# https://pillow.readthedocs.io/en/stable/reference/Image.html
from uib_inf100_graphics import *
def app_started(app):
# Bilde av JayNick, CC0, https://freesvg.org/walking-man-figure
url = 'https://tinyurl.com/inf100-strekmann-png'
spritestrip = app.load_image(url)
# Vi lager en liste som inneholder hvert av 8 bildene separat
app.sprites = []
image_width, image_height = spritestrip.size
sprite_width = image_width / 8 # det er 8 bilder i denne animasjonen
for i in range(8):
left_x = i * sprite_width
right_x = left_x + sprite_width
sprite = spritestrip.crop((left_x, 0, right_x, image_height))
app.sprites.append(sprite)
app.sprite_counter = 0
def timer_fired(app):
# Gå til neste bilde i bilde-sekvensen
app.sprite_counter = (1 + app.sprite_counter) % len(app.sprites)
def redraw_all(app, canvas):
# Bakgrunnsfarge
canvas.create_rectangle(0, 0, app.width, app.height,
fill="papaya whip", width=0)
# Tegn strekmann
sprite = app.sprites[app.sprite_counter]
canvas.create_image(200, 200, pil_image=sprite)
run_app(width=400, height=400)
Gif er en type bilder som er animert i utgangspunktet, slik som bildet under. Vi kan bruke animerte gif’er for å lage en animert sprite. Merk at timing-informasjon som egentli er lagret i gif’en ikke blir inkludert når vi bruker funksjonen for å importere den vist under.
Bilde: CC0, Kurtkaiser via Wikimedia Commons.
For å kjøre koden under, last ned ild-sprite.gif og ha den i samme mappe som programmet kjøres fra.
# En demo for å vise animert gif sprites med bruk av Pillow/PIL
# Timing-informasjon fra gif går tapt med denne metoden
from uib_inf100_graphics import *
def app_started(app):
app.timer_delay = 30
app.sprite_images = load_animated_gif('ild-sprite.gif')
app.sprite_counter = 0
def load_animated_gif(path):
# vi laster første bilde utenfor try/except slik at vi krasjer så fort
# som mulig hvis vi ikke finner noe bilde i det hele tatt.
sprite_images = [ PhotoImage(file=path, format='gif -index 0') ]
i = 1
while True:
try:
options = f'gif -index {i}'
sprite_images.append(PhotoImage(file=path, format=options))
i += 1
except Exception as e:
return sprite_images
def timer_fired(app):
app.sprite_counter = (1 + app.sprite_counter) % len(app.sprite_images)
def redraw_all(app, canvas):
photo_image = app.sprite_images[app.sprite_counter]
canvas.create_image(app.width/2, app.height/2, image=photo_image)
run_app(width=500, height=500)
Modus (ulike skjermer)
# Demonstrasjon av mode (ulike skjermer).
from uib_inf100_graphics import *
import random
##########################################
# Splash-skjerm -modus
##########################################
def splash_screen_mode_redraw_all(app, canvas):
font = 'Arial 26 bold'
canvas.create_text(app.width/2, 150, text='Demo av en modal applikasjon!',
font=font, fill='black')
canvas.create_text(app.width/2, 200, text='Dette er en modal skjem!',
font=font, fill='black')
canvas.create_text(app.width/2, 250, text='Trykk en tast for å starte!',
font=font, fill='black')
def splash_screen_mode_key_pressed(app, event):
app.mode = 'game_mode'
##########################################
# Spill -modus
##########################################
def game_mode_redraw_all(app, canvas):
font = 'Arial 26 bold'
canvas.create_text(app.width/2, 20, text=f'Poeng: {app.score}',
font=font, fill='black')
canvas.create_text(app.width/2, 60, text='Klikk på rundingen!',
font=font, fill='black')
canvas.create_text(app.width/2, 100, text='Trykk h for hjelpe-skjerm',
font=font, fill='black')
canvas.create_text(app.width/2, 140, text='Trykk v for å bryte MVC',
font=font, fill='black')
canvas.create_oval(app.x-app.r, app.y-app.r, app.x+app.r, app.y+app.r,
fill=app.color)
if app.make_MVC_violation:
app.ohNo = 'Et brudd med MVC!'
def game_mode_timer_fired(app):
move_dot(app)
def game_mode_mouse_pressed(app, event):
d = ((app.x - event.x)**2 + (app.y - event.y)**2)**0.5
if (d <= app.r):
app.score += 1
randomize_dot(app)
elif (app.score > 0):
app.score -= 1
def game_mode_key_pressed(app, event):
if (event.key == 'h'):
app.mode = 'help_mode'
elif (event.key == 'v'):
app.make_MVC_violation = True
##########################################
# Hjelpeskjerm -modus
##########################################
def help_mode_redraw_all(app, canvas):
font = 'Arial 26 bold'
canvas.create_text(app.width/2, 150, text='Her er hjelpeskjermen!',
font=font, fill='black')
canvas.create_text(app.width/2, 250, text='(Hjelpsom melding her)',
font=font, fill='black')
canvas.create_text(app.width/2, 350, text='Trykk en tast for å snu',
font=font, fill='black')
def help_mode_key_pressed(app, event):
app.mode = 'game_mode'
##########################################
# Felles hjelpefunksjoner
##########################################
def randomize_dot(app):
app.x = random.randint(20, app.width-20)
app.y = random.randint(20, app.height-20)
app.r = random.randint(10, 20)
app.color = random.choice(['red', 'orange', 'yellow', 'green', 'blue'])
app.dx = random.choice([+1,-1])*random.randint(3,6)
app.dy = random.choice([+1,-1])*random.randint(3,6)
def move_dot(app):
app.x += app.dx
if (app.x < 0) or (app.x > app.width): app.dx = -app.dx
app.y += app.dy
if (app.y < 0) or (app.y > app.height): app.dy = -app.dy
##########################################
# Oppstart av applikasjonen
##########################################
def app_started(app):
app.mode = 'splash_screen_mode'
app.score = 0
app.timer_delay = 50
app.make_MVC_violation = False
randomize_dot(app)
run_app(width=600, height=500)
Scrolling
# Sidelengs scrolling (hele verden beveger seg):
from uib_inf100_graphics import *
import random
def app_started(app):
app.scroll_x = 0
app.dots = [(random.randrange(app.width),
random.randrange(60, app.height)) for _ in range(50)]
def key_pressed(app, event):
if (event.key == "Left"): app.scroll_x -= 5
elif (event.key == "Right"): app.scroll_x += 5
def redraw_all(app, canvas):
# Tegn spilleren (som alltid er midt på skjermen)
cx, cy, r = app.width/2, app.height/2, 10
canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill='cyan')
# Tegn prikkene, sideforskjøvet med et offset scroll_x
for (cx, cy) in app.dots:
cx -= app.scroll_x # <-- Her sideforskyver vi prikkene på lerretet
canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill='lightGreen')
# Tegn x- og y-aksen
x = app.width/2 - app.scroll_x # <-- Her sideforskyver vi
y = app.height/2
canvas.create_line(x, 0, x, app.height)
canvas.create_line(0, y, app.width, y)
# Tegn instruksjoner og debug-informasjon
x = app.width/2
canvas.create_text(x, 20, text='Bruk piltaster for å flytte spilleren',
fill='black')
canvas.create_text(x, 40, text=f'{app.scroll_x = }',
fill='black')
run_app(width=300, height=300)
# Sidelengs scrolling når figuren er på vei ut av skjermen
from uib_inf100_graphics import *
import random
def app_started(app):
app.scroll_x = -app.width/2 # Initiell scroll slik at x=0 er sentrert
app.scroll_margin = 50
app.player_x = 0 # spillerens initielle posisjon
app.dots = [(random.choice(range(-app.width//2, app.width//2)),
random.choice(range(60, app.height))) for _ in range(50)]
def make_player_visible(app):
# scroll skjermen så mye som nødvendig for at spilleren vises
if (app.player_x < app.scroll_x + app.scroll_margin):
app.scroll_x = app.player_x - app.scroll_margin
if (app.player_x > app.scroll_x + app.width - app.scroll_margin):
app.scroll_x = app.player_x - app.width + app.scroll_margin
def move_player(app, dx, dy):
app.player_x += dx
make_player_visible(app)
def key_pressed(app, event):
if (event.key == "Left"): move_player(app, -5, 0)
elif (event.key == "Right"): move_player(app, +5, 0)
def redraw_all(app, canvas):
# Tegn spilleren, sideforskjøvet med et offset scroll_x
cx, cy, r = app.player_x, app.height/2, 10
cx -= app.scroll_x # <-- Her sideforskyver vi spilleren
canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill='cyan')
# Tegn prikkene, sideforskjøvet med et offset scroll_x
for (cx, cy) in app.dots:
cx -= app.scroll_x # <-- Her sideforskyver vi prikkene
canvas.create_oval(cx-r, cy-r, cx+r, cy+r, fill='lightGreen')
# Tegn x- og y-aksen
x = -app.scroll_x # <-- Her sideforskyver vi y-aksen
y = app.height/2
canvas.create_line(x, 0, x, app.height)
canvas.create_line(0, y, app.width, y)
# Tegn instruksjoner og debug-informasjon
x = app.width/2
canvas.create_text(x, 20, text='Use arrows to move left or right',
fill='black')
canvas.create_text(x, 40, text=f'app.scroll_x = {app.scroll_x}',
fill='black')
run_app(width=300, height=300)
# Sidelengs scrolling når figuren er på vei ut av skjermen
# Kollisjonsdeteksjon for spilleren
from uib_inf100_graphics import *
def app_started(app):
# Scrolling
app.scroll_margin = 50
app.scroll_x = -app.scroll_margin
app.scroll_y = -app.height / 2
# Spiller - koordinate for hjørnet til venstre nederst
app.player_x = 0
app.player_y = 0
app.player_width = 10
app.player_height = 20
# Murer
app.walls = 5
app.wall_points = [0]*app.walls
app.wall_width = 20
app.wall_height = 40
app.wall_x_positions = [90 * (i + 1) for i in range(app.walls)]
app.current_wall_hit = -1 # -1 når ingen mur er truffet
def get_player_bounds(app):
# returnerer absolutt-posisjon til spiller på et uendelig lerret
# tar ikke hensyn til scrolling
(x0, y1) = (app.player_x, app.player_y)
(x1, y0) = (x0 + app.player_width, y1 - app.player_height)
return (x0, y0, x1, y1)
def get_wall_bounds(app, wall):
# returnerer absolutt-posisjon til en mur på et uendelig lerret
# tar ikke hensyn til scrolling
(x0, y1) = (app.wall_x_positions[wall], 0)
(x1, y0) = (x0 + app.wall_width, y1 - app.wall_height)
return (x0, y0, x1, y1)
def get_wall_hit(app):
# returnerer hvilken mur spilleren er over for øyeblikket
# merk: i større spill bør denne funksjonen optimeres til å kun
# sjekke de objektene som er synlige.
player_bounds = get_player_bounds(app)
for wall in range(app.walls):
wall_bounds = get_wall_bounds(app, wall)
if bounds_intersect(app, player_bounds, wall_bounds):
return wall
return -1
def bounds_intersect(app, bounds_a, bounds_b):
# return l2<=r1 and t2<=b1 and l1<=r2 and t1<=b2
(ax0, ay0, ax1, ay1) = bounds_a
(bx0, by0, bx1, by1) = bounds_b
return ((ax1 >= bx0) and (bx1 >= ax0) and
(ay1 >= by0) and (by1 >= ay0))
def check_for_new_wall_hit(app):
# sjekk om vi treffer en ny mur for første gang
wall = get_wall_hit(app)
if (wall != app.current_wall_hit):
app.current_wall_hit = wall
if (wall >= 0):
app.wall_points[wall] += 1
def make_player_visible(app):
# scroll for å gjøre spilleren synlig
m = app.scroll_margin
if (app.player_x < app.scroll_x + m):
app.scroll_x = app.player_x - m
if (app.player_x > app.scroll_x + app.width - m - app.player_width):
app.scroll_x = app.player_x - app.width + m + app.player_width
if (app.player_y < app.scroll_y + m + app.player_height):
app.scroll_y = app.player_y - m - app.player_height
if (app.player_y > app.scroll_y + app.height - m):
app.scroll_y = app.player_y - app.height + m
def move_player(app, dx, dy):
app.player_x += dx
app.player_y += dy
make_player_visible(app)
check_for_new_wall_hit(app)
def size_changed(app):
make_player_visible(app)
def mouse_pressed(app, event):
app.player_x = event.x + app.scroll_x - app.player_width/2
app.player_y = event.y + app.scroll_y + app.player_height/2
make_player_visible(app)
check_for_new_wall_hit(app)
def key_pressed(app, event):
if (event.key == "Left"): move_player(app, -5, 0)
elif (event.key == "Right"): move_player(app, +5, 0)
elif (event.key == "Up"): move_player(app, 0, -5)
elif (event.key == "Down"): move_player(app, 0, +5)
def redraw_all(app, canvas):
sx = app.scroll_x
sy = app.scroll_y
# Tegn x-aksen
line_y = -sy
line_height = 5
canvas.create_rectangle(0, line_y, app.width, line_y+line_height,
fill="black")
# Tegn murene
# (Merk: kan optimiseres til å kun tegne synlige murer)
for wall in range(app.walls):
(x0, y0, x1, y1) = get_wall_bounds(app, wall)
fill = "orange" if (wall == app.current_wall_hit) else "pink"
canvas.create_rectangle(x0-sx, y0-sy, x1-sx, y1-sy, fill=fill)
(cx, cy) = ((x0+x1)/2 - sx, (y0 + y1)/2 - sy)
canvas.create_text(cx, cy, text=str(app.wall_points[wall]),
fill='black')
cy = line_y + 5
canvas.create_text(cx, cy, text=str(wall), anchor=N, fill='black')
# Tegn spilleren
(x0, y0, x1, y1) = get_player_bounds(app)
canvas.create_oval(x0 - sx, y0 - sy, x1 - sx, y1 - sy, fill="cyan")
# Tegn instruksjonene
msg = "Bruk pilene eller musen for å flytte"
canvas.create_text(app.width/2, 20, text=msg, fill='black')
run_app(width=300, height=300)
Spille av lyder
For å spille av lyder må du først installere pygame, og så laste ned uib_inf100_music.py og legge den i samme mappe som filen du kjører (ved siden av uib_inf100_graphics.py). For å installere pygame:
- bruk kommandoen
pip install pygame
i terminalen (eksakt kommando kan variere litt mellom ulike operativsystem og hvordan python er installert på maskinen. Bruk samme type kommando du brukte da du installerte pillow og requests i grafikk 1)
For at eksempelet under skal virke, må du også laste ned button.mp3 i samme mappe programmet kjøres fra (som ikke nødvendigvis er samme mappe hvor programmet ligger).
from uib_inf100_graphics import *
from uib_inf100_music import load_sound
def app_started(app):
app.sound = load_sound("button.mp3")
def app_stopped(app):
app.sound.stop()
def key_pressed(app, event):
if (event.key == 's'):
if app.sound.is_playing(): app.sound.stop()
else: app.sound.start()
elif (event.key == 'l'):
app.sound.start(loops=-1)
elif event.key.isdigit():
app.sound.start(loops=int(event.key))
def timer_fired(app):
pass
def redraw_all(app, canvas):
font = "Arial 20"
for i, text in enumerate((
f'{app.sound.path} ({app.sound.loops = })',
f'{app.sound.is_playing() = }',
'Trykk s for å starte/stoppe lyd',
'Trykk et tall for å spille lyden så mange ganger',
'Trykk l for å spille av i evig løkke',
)):
canvas.create_text(app.width/2, (i+1) * 30, text=text,
font=font, fill='black')
run_app(width=600, height=200)