grafik i drracket - ida.liu.setddc74/grafik/tddc74-grafik-2016.pdf · grafik i racket frame%...

23
Grafik i DrRacket AV TOMMY KARLSSON

Upload: vuongnguyet

Post on 09-Apr-2019

229 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Grafik i

DrRacketAV TOMMY KARLSSON

Page 2: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Upplägg

Grundläggande

grafik i racket

Frame%

Button%

Pane% & Panel%

Canvas%

Bitmap%

Kodexempel! Generella

problemlösar-

strategier

Grafisk kodstruktur

Grafisk effektivisering

Tile-baserad grafik

Olika sätt att bestämma rörelse

Page 3: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Frame%; Skapar ett objekt av typen frame% (ett fönster!)

(define *a-window* (new frame%

[width 300]

[height 200]

[label "Detta är ett fönster"]))

; Säger till vår frame att den ska synas

(send *a-window* show #t)

; En frame% är en container

(man kan placera saker i den!)

Det finns en mängd olika inargument som man kan utnyttja beroende

på vad man vill att den ska göra! Se docs.racket-lang.org!

Page 4: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Button%; Vår procedur som bestämmer vad som ska hända

(define (button-proc button event)

(send button set-label “Klick fungerade!”))

Det finns en mängd olika inargument som man kan utnyttja beroende

på vad man vill att den ska göra! Se docs.racket-lang.org!

; Skapar ett objekt av typen button% (en knapp!)

(define *a-button* (new button%

[parent *a-window*]

[label “En knapp”]

[callback button-proc])

; En button måste ha en container (som t.ex. frame)

som parent!

Page 5: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Panel% & Pane%De är båda containers, så de kan fyllas med t.ex. button eller canvas

Kan användas för att få en bättre struktur!

Underklasser:

horizontal-pane%

horizontal-panel%

vertical-pane%

vertical-panel%

Se dokumentationen

hur de används!

(PS: kanterna kring

panelerna fås genom att

sätta style till ’(border)

när man skapar

panelerna!)

Page 6: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Canvas%; Säger vad som ska ritas när canvasen uppdateras

(define (our-render-fn canvas dc)

; Innehåller någon form av kropp!

…)

; Skapar ett objekt av typen canvas% (en målarduk!)

(define *a-canvas* (new canvas%

[parent *a-window*]

[paint-callback our-render-fn]))

; En canvas är alltså en målarduk som vi kan rita figurer

eller bilder på!

Det finns en mängd olika inargument som man kan utnyttja beroende

på vad man vill att den ska göra! Se docs.racket-lang.org!

Page 7: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Exempel på dc%-

kommandonRitande Kommandon:

(send dc draw-rectangle x y width height)

(send dc draw-rounded-rectangle x y width height radius)

(send dc draw-arc x y width height start-radians end-radians)

(send dc draw-ellipse x y width height)

(send dc draw-line x1 y1 x2 y2)

(send dc draw-spline x1 y1 x2 y2 x3 y3)

(send dc draw-lines list-of-points)

(send dc draw-polygon list-of-points)

(send dc draw-text text x y)

(send dc draw-bitmap source x y)

Koordinatsystemsförändrande kommandon

(send dc translate dx dy)

(send dc rotate angle)

(send dc scale x-scale y-scale)

Färginställningar och liknande

(send dc set-pen color-name width style)

(send dc set-brush color-name style)

(send dc set-alpha opacity)

(send dc set-background color)

(send dc set-font font)

Rensa skärmen

(send dc clear)

Page 8: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Canvas: Exempel; Skapar fönstert(define *a-window* (new frame%

[width 600][height 400][label "Detta är ett fönster"]))

; Gör fönstret synligt(send *a-window* show #t)

; Vad ska ritas på vår canvas?(define (render-fn canvas dc)

(send dc set-brush "red" 'solid) ; Ändrar färg på vår pensel(send dc set-pen "green" 10 'solid) ; Ändrar färg på vår penna(send dc set-text-foreground "blue") ; Ändrar färg på vår text(send dc draw-rectangle 10 10 50 50)(send dc draw-text "Hallå där!" 200 200)(send dc set-brush (make-object color% 1 0 0) 'solid) ; Vi skapar en egen färg istället!(send dc draw-ellipse 240 240 100 100))

; Skapar vår canvas(define *a-canvas* (new canvas%

[parent *a-window*][paint-callback render-fn]))

Det finns en mängd olika inargument som man kan utnyttja beroende

på vad man vill att den ska göra! Se docs.racket-lang.org!

Page 9: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Translateringar, rotationer

och skalning

Rotation kring origo

Rotation kring vårt

nya origo!

Page 10: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Translateringar, rotationer

och skalningExempel på koordinatsystemsberoende kommandon:

(send dc translate xValue yValue) ; Förskjuter origo I den givna riktningen

(send dc rotate angle) ; Roterar den givna vinkeln kring origo

(send dc scale xFactor yFactor) ; Skalar bilden från

Ofta vill man utgå ifrån centrum av bilden:

(send dc translate (+ xValue (/ width 2)) (+ yValue (/ height 2)))

OBS!

Glöm ej att återställa koordinatsystemet

efter att ni använt det, annars blir det

riktigt jobbigt för er!

Page 11: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Bitmap%

Många användningsområden!

; Skapa en bitmap av en bildfil:

(define *our-bitmap* (make-object bitmap% ”testbild.png”)

; Dimensionerna sätts till bildens dimensioner!

; Skapar en tom bitmap

(define *our-bitmap* (make-object bitmap% 100 100)

; Dimensionerna sätts till argumenten, här 100 x 100!

; Hämta DC för bitmapen så att vi kan måla precis som på canvasen!

(define *our-dc* (new bitmap-dc% [bitmap *our-bitmap*]))

; Ritar ut en bitmap med någon dc, t.ex. på en canvas!

(send *some-dc* draw-bitmap *our-bitmap*

xPos

yPos)

Page 12: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Tangentbords och

musavkänningCanvas% innehåller funktionalitet för att känna av mus- eller

Tangentbordsinmatning, men den är normalt sett avstängd!

För att ändra på detta utnyttjar vi arv:

(define input-canvas%

(class canvas%

; Vi lägger till ytterligare inargument

; (procedurer som vi själva måste skriva!)

(init-field keyboard-handler ; ska hantera tangentbord

mouse-handler) ; ska hantera mus

; Vid ett knapptryck, anropa vår keyboard-handler

(define/override (on-char key-event)

(keyboard-handler key-event))

; Vid musrörelse, anropa vår mouse-handler

(define/override (on-event mouse-event)

(mouse-handler mouse-event))

(super-new)))

OBS! Se vad man kan göra med argumenten key-event% och

mouse-event% i dokumentationen!

Page 13: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Exempel: mus + bitmap

Page 14: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Exempel: mus + bitmap

Page 15: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Timers

Timer% kan användas för att så få procedurer att upprepas vid specifika tider

(Jämför med att en itererande procedur alltid anropar sig själv direkt när den är klar!)

60 Hz => periodtid 16,666 ms

; Vi definierar en timer som kommer anropa vår procedur ”our-update”

(define *game-timer* (new timer%

[notify-callback our-update]))

; Vi startar timern och säger att den ska anropa sin procedur varje 16 millisekund

(send *game-timer* start 16 #f) ; #f säger att den inte bara ska köras en gång!

; Vi stannar timern

(send *game-timer* stop)

Page 16: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Exempel: mus + bitmap

Page 17: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Grafisk kodstruktur

Gör looparna så lättviktiga som möjligt!

• Är det några onödiga beräkningar?

• Finns det beräkningar som inte måste ske varje iteration?

• Gör det lättläst!

Flytta specifika rit-delar till respektive objekt!

• Anropa t.ex. player’s ritprocedur istället för att skriva ritproceduren

i grafik-loopen!

• Ex:

(send player draw-player dc)

Istället för:

(send dc draw-bitmap (send player get-bitmap) …)

Detta ger ökad läsbarhet och en lättare överblick över vad

som egentligen sker i grafik-loopen!

Page 18: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Grafisk effektivisering

Vad händer om koden är för ineffektiv?

• Programmet kan frysa

• Programmet kan ”lagga”

• Vår fysikmotor kan sluta fungera! (Beror på implementation)

Hur kan man undersöka evalueringstid?

• Ex:

(define (our-update)

(let ([startTime (current-inexact-milliseconds)])

; BODY

(displayln (- (current-inexact-milliseconds) startTime))))

OBS! Testa evalueringstiden på era loopar ibland under projektets gång

Om det är någon del som är ineffektiv så är det lätt att hitta!

Page 19: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Tile-baserad grafik

Lätt att rita ut!

Lätt att göra kollisionsdetektering!

Lätt att göra kartan!

Page 20: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Tile-baserad grafik

Exempel (rita): Element på plats [3,12] har nummer 30.

• Rita bitmapen som svarar mot siffran 30 på position:

• Y = 3 * höjd-på-bitmap

• X = 12 * bredd-på-bitmap

• Klart!

Exempel (kollision): Spelaren försöker gå till position (12, 153)

• Tillåten tile att gå på?

• Koordinaterna motsvarar element:

• Rad = 153 / höjd-på-bitmap ; Avrundat neråt

• Kolumn = 12 / bredd-på-bitmap ; Avrundat neråt

• Får spelaren gå på tiles med siffran som finns på

position [rad, kolumn] ?

Page 21: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Matriser

0,0 0,1 0,2 0,3

1,0 1,1 1,2 1,3

2,0 2,1 2,2 2,3

3,0 3,1 3,2 3,3

0,0 0,1 0,2 0,31,0 1,1 1,2 1,32,0 2,1 2,2 2,33,0 3,1 3,2 3,3

Jämför med:

Hämta element r ur matrisen

Hämta element k ur det

=> Element (r,k)!

Page 22: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Olika sätt att bestämma rörelse

Lästa textfil och bygga tile-baserad karta

• Det är lättare att redigera en txt-fil än att skriva en tile-baserad

karta direkt i racket!

Vektorbaserad rörelse

• Linjär algebra:

• Vi vill gå från punk (a.b) till (c,d).

• Normerad riktningsvektor: (c-a , d-b) / Vektorns längd

• Ny kooridnat:

• xPos = xPos + Normerad-riktningsvektor-x * ΔS

• yPos = yPos + Normerad-riktningsvektor-y * ΔS

• Klart!

Waypoints

• Ex: Lista med koordinater: ( (1.1) , (1 . 2) , (3 . 2) , …)

• Riktning: Från nuvarande position till (1.1)!

• När avståndet mellan nuvarande position och (1.1) < något värde

• Lista med koordinater = ( (1 . 2) , (3 . 2) , …)

• Börja om!

Page 23: Grafik i DrRacket - ida.liu.seTDDC74/grafik/tddc74-grafik-2016.pdf · grafik i racket Frame% Button% ... (send dc draw -arc x y width height start-radians end-radians) (send dc draw-ellipse

Allmänna tips! Dela upp grafik och fysik?

Fördelar:

Fysik (som är viktigare) kan uppdateras oftare.

Kortare evalueringstid – Fysik och grafik måste inte evalueras samtidigt!

Ex:

; Hantera all fysik, t.ex. rörelse och kollision(define (physics-update) ; Kan köras med högre frekvens (OBS!

; inte för hög frekvens!)

; Rita bara ut saker på koordinater som redan är uträknade(define (graphics-update) ; Körs med frekvens på 60Hz

Jämn rörelse?

Icket FPS-beroende hastighet:

Utnyttja ΔT och hastighetsformeln ΔS = V * ΔT

Börja med icket-grafik

Större delen av projektet går att skriva utan grafik

Testa programmera enkla grafiska problem innan ni börjar med grafiken i projektet.