Grafik i Racket
Grafik i Racket
Grafik i Racket
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Grafik</strong><br />
med <strong>Racket</strong><br />
TDDC74 Mikael Silvén 2013
Dagens föreläsning<br />
Förkunskaper<br />
2D <strong>Grafik</strong><br />
- Grunderna<br />
- Målare och målarduk<br />
- <strong>Grafik</strong> i <strong>Racket</strong><br />
- Två typer av renderingssystem<br />
- Världens enklaste spelmotor<br />
Kort om numerisk integration<br />
Exempelprogram
Förkunskaper<br />
OOP<br />
- <strong>Grafik</strong>biblioteken är objektorienterade<br />
- ((sak 'msg) x), (ask sak 'msg x),<br />
(send sak msg x)<br />
- Arv används för att komma åt input (se pdf)<br />
Samplingsteori<br />
- Vi måste sampla tillräkligt snabbt för att<br />
kunna återskapa animationer.
2D-<strong>Grafik</strong><br />
Pixel<br />
- Picture Element<br />
- Minsta beståndsdelen av en skärm<br />
- Beskrivs med 3 värden, R G B mellan 0-255<br />
Bild<br />
- En mängd pixlar, en bredd, en höjd<br />
- R G B, Kanske A, för alpha/genomskinlighet<br />
2D-<strong>Grafik</strong> är konsten att bygga intressanta<br />
bilder genom att manipulera dess pixlar
2D-<strong>Grafik</strong> II<br />
Super Mario Bros 3 av Nintendo
2D-<strong>Grafik</strong> III
2D-<strong>Grafik</strong> IV
2D-<strong>Grafik</strong> V
2D-<strong>Grafik</strong> VI<br />
Kortfattat<br />
- Målarduken målas på<br />
- Målaren förändrar målarduken<br />
Men kod då?<br />
Instans av canvas% behöver en paint-callback<br />
som får canvas samt drawing-contex som<br />
argument: (define (draw-stuff canvas dc) ...)
Minimalt Exempel<br />
(define *my-window* (new frame%<br />
[width 300] [height 200] [label "En ram"]))<br />
(define (render-fn canvas dc)<br />
(let-values ([(w h) (send canvas get-virtual-size)])<br />
(send dc draw-rectangle 4 4 (- w 8) (- h 8))))<br />
(define *my-canvas* (new canvas%<br />
[parent *my-window*]<br />
[paint-callback render-fn]))<br />
(send *my-window* show #t)
Mer man kan göra?<br />
(send dc draw-rectangle x y width height)<br />
(send dc draw-rounded-rectangle x y width height radius)<br />
(send dc draw-arc x y width height start end)<br />
(send dc draw-ellipse x y width height)<br />
(send dc draw-line x1 y1 x2 y2)<br />
(send dc draw-text text x y)<br />
(send dc set-alpha opacity)<br />
(send dc set-background color)<br />
...<br />
;; Kanske mest intressant<br />
(send dc translate dx dy)<br />
(send dc rotate angle)<br />
(send dc scale x-scale y-scale)<br />
(send dc draw-bitmap source x y)
Måla bilder<br />
(send dc translate x y)<br />
(send dc rotate angle)<br />
(send dc draw-bitmap image<br />
(/ (- (send image get-width)) 2)<br />
(/ (- (send image get-height)) 2))<br />
(send dc rotate (- angle))<br />
(send dc translate (- x) (- y))<br />
// Javakod nedan, visst är det likt?<br />
g.translate(x, y);<br />
g.rotate(angle);<br />
g.drawImage(image, -image.getWidth(null) /2,<br />
-image.getHeight(null)/2, null);<br />
g.rotate(-angle);<br />
g.translate(-x, -y);<br />
// g är ett graphics-objekt, motsvarar dc
<strong>Grafik</strong>motorer<br />
Kod som målar ut saker på skärmen.<br />
För enklare projekt finns det två kategorier:<br />
- Tillståndsmaskiner, måla varje gång du<br />
byter tillstånd. T.ex. efter giltigt drag som svar<br />
på musklick i Schack eller varje gång en figur<br />
förflyttas i Tetris.<br />
- Simuleringar, updatera och måla så ofta<br />
som möjligt. T.ex: När en fågel flyger i Angry<br />
Birds eller en match i FIFA.
<strong>Grafik</strong>motorer II<br />
Kommer inte föreläsa om finita<br />
tillståndsmaskiner<br />
Absoluta majoriteten av spel är av den senare<br />
kategorin<br />
Enklare att implementera animationer<br />
Tekniken är densamma: (send *my-canvas* refresh)
<strong>Grafik</strong>motorer III<br />
Låt oss anta koden från tidigare slide:<br />
(define *my-window* ...)<br />
(define (render-fn ...)<br />
(define *my-canvas* ...)<br />
(send *my-window* show #t)<br />
Lägg nu till:<br />
(define (tick!)<br />
(send *my-canvas* refresh))<br />
(define *my-timer* (new timer% [notify-callback tick!]))<br />
(send *my-timer* start 16) ;; 16 ms intervall ger ~60 FPS
<strong>Grafik</strong>motorer IV<br />
Det händer inte så mycket... Vi provar en<br />
intressantare renderingsfunktion:<br />
(define *angle* 0.0)<br />
(define (render-fn canvas dc)<br />
(send dc translate 50 50)<br />
(send dc rotate *angle*)<br />
(send dc draw-rectangle -25 -25 50 50)<br />
(send dc rotate (- *angle*))<br />
(send dc translate (- 50) (- 50)))<br />
(tick!) blir nu:<br />
(define (tick!)<br />
(set! *angle* (+ *angle* (/ 1 6.28))))<br />
(send *my-canvas* refresh))
<strong>Grafik</strong>motorer V<br />
Resultatet blir en roterande ruta:<br />
Men det är jobbigt ha lägga<br />
till en massa saker såhär...<br />
Tänk istället om vi kapslade<br />
in beteendet för utmålning<br />
Om varje sak kunde uppdatera och måla sig<br />
själv behöver vi bara ha en lista med saker
<strong>Grafik</strong>motorer VI<br />
(define *all-things* '())<br />
(define (make-thing ...)<br />
(define (update) ...)<br />
(define (render canvas dc) ...)<br />
(lambda (cmd)<br />
(cond ((eq? cmd 'update) update)<br />
((eq? cmd 'render) render))))<br />
(define (render-fn canvas dc)<br />
(define (render-one thing)<br />
((thing 'render) canvas dc))<br />
(for-each render-one *all-things*))<br />
(define (tick!)<br />
(define (update-one! thing)<br />
((thing 'update))) ;;Kanske vill skicka med saker här<br />
(for-each update-one! *all-things*)<br />
(send *my-canvas* refresh))
<strong>Grafik</strong>motorer VII<br />
(define (rotating-square x y)<br />
(let ((angle 0))<br />
(define (update)<br />
(set! angle (+ angle (/ 1 6.28))))<br />
(define (render canvas dc)<br />
(send dc translate x y)<br />
(send dc rotate angle)<br />
(send dc draw-rectangle -25 -25 50 50)<br />
(send dc rotate (- angle))<br />
(send dc translate (- x) (- y)))<br />
(define (dispatch cmd)<br />
(cond<br />
((eq? cmd 'update) update)<br />
((eq? cmd 'render) render)))<br />
dispatch))<br />
(set! *all-things* (cons (rotating-square 50 50)<br />
*all-things*))
<strong>Grafik</strong>motorer VIII<br />
Vi har nu grunden till världens enklaste<br />
spelmotor<br />
Koden lite huller om buller, bättre ordning i<br />
fristående pdf<br />
Att lägga till lager och olika skärmar lämnas<br />
som övning<br />
http://commons.wikimedia.org/wiki/File:Parallax-scroll-example-2.png
Simuleringar<br />
De flesta spel är<br />
simuleringar. Saker<br />
händer hela tiden<br />
och objekt måste<br />
uppdateras<br />
P = P + v * dt<br />
v = v + a * dt<br />
a = a + F / m<br />
http://en.wikipedia.org/wiki/Euler_method
Tack för er tid<br />
Frågor?