GRAFIKA GAME Aditya Wikan Mahastama
[email protected]
Kanvas dan Primitif Grafika
3 UNIV KRISTEN DUTA WACANA | TEKNIK INFORMATIKA – GASAL 1112
Before we
begin to draw
THE CONCEPT OF CANVAS • Sebuah bidang yang akan digunakan dalam memplot (menggambar) grafika komputer, disebut dengan kanvas • Kanvas dibatasi oleh margin kiri-kanan-atas-bawah, dan batas kanvas ditentukan sebelum mulai menggambar • Penggambaran pada koordinat di luar batas kanvas, tidak akan muncul pada kanvas, tetapi kalkulasi titik di luar kanvas masih dimungkinkan
THE CONCEPT OF CANVAS • Setiap bahasa pemrograman berbasis visual biasanya memiliki kanvas, meskipun tertuang pada jenis komponen yang berbeda • Komponen untuk kanvas pada umumnya berada pada posisi yang berbeda dari komponen untuk menampung citra yang dibuka dari file • Manipulasi piksel secara bebas hanya dapat dilakukan pada komponen kanvas, tidak pada komponen penampung citra
THE CONCEPT OF CANVAS Ilustrasi: • Visual Basic memiliki dua komponen grafika: TPicture (untuk menampung citra dari file), dan TImage (untuk menampung kanvas) • Delphi memiliki satu komponen grafika TImage saja, dengan tingkatan kelas yang berbeda TImage.TCanvas sebagai container kanvas TImage.TPicture sebagai container citra dari file
WHAT I’M USING - DELPHI Created by Borland since 1992 Uses Pascal language – a successor to Turbo Pascal It is literally a Visual Pascal Recent release Delphi 2007, resembles .NET Who resembles who? .NET is the one who actually resembles Delphi because its engineers were hijacked from Borland by *****soft
DELPHI BASICS Uses Form – like other mostly used programming tools Uses Drag-and-Drop Components – like other mostly used programming tools Uses Property Box and support OOP hierarchical properties – like other OOP languages Most users who have an experience using VB, .NET, C++ Builder, or anything else shouldn’t have any problem using Delphi
WHAT WE NEED TO DRAW A TImage Container A visual component (VCL) used to contain images, pictures, graphics – whether loaded or drawn directly. This component is Delphi-native. Supporting components Buttons, text boxes, labels to ease the use and A little knowledge of the Pascal language
HOW TO DRAW Drag a TImage component to your form. It will be named automatically as Image1 To draw a pixel, just use this statement: Image1.Canvas.Pixels[x,y] := RGB(r,g,b);
Where x : on-screen x-axis position y : on-screen y-axis position R : red colour value G : green colour value B : blue colour value
HOW TO DRAW Drag a TImage component to your form. It will be named automatically as Image1 To draw a pixel, just use this statement: Image1.Canvas.Pixels[x,y] := RGB(r,g,b);
Example: drawing a red point on [75,120] Image1.Canvas.Pixels[75,120] := RGB(255,0,0);
or, for known colours: Image1.Canvas.Pixels[75,120] := clRed;
A little knowledge of Pascal All statements end with ; Variable declarations are strict and explicit, and is placed before a program segment (begin – end) var angka: integer; kata: string; pecahan: real;
Variable casting are using these keywords: kata := inttostr(angka); >< strtoint kata := floattostr(pecahan); >< strtofloat angka := round(pecahan) or trunc(pecahan)
A little knowledge of Pascal Variable assignments uses := while comparison uses = (cf. = and == in C++ or PHP) A loop does this way: for x := 1 to 20 do image1.canvas.pixels[x,10] := clBlack;
or if it takes longer statements: for x := 1 to 20 do begin y := 2 * x; image1.canvas.pixels[x,y] := clBlack; end;
A little knowledge of Pascal Same as a branch does: if x >= 15 then image1.canvas.pixels[x,10] := clBlack;
or if it takes longer statements: if x < 20 then begin y := 2 * x; image1.canvas.pixels[x,y] := clBlack; end;
And the last, strings take ‘
‘ to enclose the text.
kata := ‘Grafkom is nice and good’;
Graphics Primitives
Point & Line
WHAT CONSIDERED PRIMITIVE? • Sekarang disebut juga Primitif Geometris, merupakan objek geometrik atomis yang paling mungkin digambar dan disimpan oleh sebuah sistem • Primitif grafika yang paling dasar: titik, garis dan segmen garis • Primitif grafika berikutnya: bidang, elips (termasuk lingkaran), poligon (segitiga, segi empat, dsb), kurva lengkung (spline curves) • Setiap citra yang dapat dijabarkan secara grafika, terdiri dari objek-objek atomis
POINT / VERTEX / NODE A single point on the Cartesian plane Described as: A (x,y) e.g. A (5, 4)
In computer graphics, it is Represented by a pixel Image1.Canvas.Pixels[x,y] := RGB(r,g,b);
DISTANCES BETWEEN TWO POINTS • EUCLIDEAN DISTANCE
• MANHATTAN DISTANCE (CITY BLOCK DISTANCE / TAXICAB GEOMETRY)
DISTANCES BETWEEN TWO POINTS
Green: Euclidean Others: Manhattan
LINE / EDGE A sequence of points plotted by a linear equation Described as
y = mx + c Where m : slope (gradien) c : constant number and x is limited within a range e.g. y = 2x + 1, 0 < x < 3
LINE / EDGE A sequence of points plotted by a linear equation Described as
y = mx + c When its drawn, it will have two points at each ends of the line. Therefore we can obtain its slope degree using this equation:
( y2 − y1 ) m= ( x2 − x1 )
∆y m= ∆x
LINE PLOTTING PROBLEM If we plot a line using integer loop, we will have a line that is not continuous
Why? Because a line plot is a linear function, which in fact plots continuous real numbers So, how we make it a smooth one?
1. MAKE A BIGGER LOOP For instance, if you want to draw a y = 3x + 1 limited by 0 < x <10, try this loop for x:= 0 to 100 do begin y := 3 * x; image1.canvas.pixels[round (x/10), round (y/10) + 1] := clRed; end;
The bigger you blow up the number, the more accurate it will plot, but it will surely makes up a huge number of redundant plot points
2. DDA ALGORITHM It has a real cool name: Digital Diferential Analyzer, while what it really did is: to draw line from known endpoints (x1, y1) and (x2, y2) considering distances and slope trend of both endpoints by: - adding the right slope for each pairs of a (x,y) repeatedly from (x1,y1) for tstep times - tstep is either dx or dy, according to the trend
2. DDA ALGORITHM x1 := 0; x2 := 10; dx := x2-x1; dy := y2-y1;
y1 := (3 * x1) + 1; y2 := (3 * x2) + 1; //manhattan distance of x //manhattan distance of y
if abs(dx)>abs(dy) then tstep:=abs(dx) else tstep:= abs(dy); add_x := dx / tstep; add_y := dy / tstep; x := x1; y := y1; //draw beginning at x1,y1 Image1.canvas.pixels[trunc(x),trunc(y)] := clRed; for i:= 1 to tstep do begin x:= x + add_x; y:= y + add_y; image1.canvas.pixels[trunc(x),trunc(y)]:=clRed; end;
3. BRESENHAM ALGORITHM It is used to draw a line with a positive slope, when the slope value is less than 1 For such a slope, Bresenham said that the equation is y = m(xk + 1) + c and comes those really buzzing equations (read by yourself in the book!), so that a decisive point P can be obtained, which is started with P0 = 2∆y - ∆x
3. BRESENHAM ALGORITHM x1 := 0; x2 := 10;
y1 := round(0.5 * x1) + 1; y2 := round(0.5 * x2) + 1;
dx := x2-x1; dy := y2-y1;
//manhattan distance of x //manhattan distance of y
p := (2*dy) - dx; if x1 > x2 then begin x := x2; xend := x1; end else begin x := x1; xend := x2; end;
y := y2;
y := y1;
3. BRESENHAM ALGORITHM //draw beginning at x,y image1.canvas.pixels[x,y] := clRed; for i:= x to xend do begin x:= x + 1; if p < 0 then p := p + (2*dy) else begin y := y + 1; p := p + (2*(dy-dx)); end; image1.canvas.pixels[x,y] := clRed; end;
4. NATIVE DELPHI KEYWORD It is known from previous algorithms, that endpoints can always be obtained from a line, for instance: x1 := 0; x2 := 10;
y1 := (3 * x1) + 1; y2 := (3 * x2) + 1;
or in a clear language:
(x1, y1) = (0, 1) (x2, y2) = (10, 31) and they’re happy pairs, always come altogether
4. NATIVE DELPHI KEYWORD (x1, y1) = (0, 1) (x2, y2) = (10, 31) Then, it becomes as simple as this: Image1.canvas.moveto(x1,y1); Image1.canvas.lineto(x2,y2);
Didn’t result in anything? Don’t forget to name the colour first! Image1.canvas.pen.color := clRed; Image1.canvas.moveto(x1,y1); Image1.canvas.lineto(x2,y2);
Primitives Descendant
Polygon & Polyline
WHAT IS POLYGON? • Sebuah bangun datar yang dibatasi oleh sirkuit (jalur tertutup) berupa sejumlah segmen garis lurus yang saling bersambung • Segmen-segmen garisnya disebut dengan sisi (sides), dan pertemuan dua segmen disebut dengan pojok (corners) • Bahasa Indonesia: POLIGON
WHAT IS POLYLINE? • Sejumlah segmen garis lurus yang saling bersambung yang tidak membentuk sirkuit tertutup • Istilah ini tidak resmi digunakan • Bahasa Indonesia: tidak ada
JENIS – JENIS POLIGON • KONVEKS (CONVEX) Jika besar setiap sudut internalnya kurang dari 180 derajat dan letak sisi-sisinya berada di dalam atau sama dengan titik terluar poligon • KONKAF (CONCAVE) Jika besar sudut internalnya ada yang melebihi 180 derajat
JENIS – JENIS POLIGON • SIMPEL (SIMPLE) Jika tidak ada segmen garis yang berpotongan dalam poligon. Disebut juga poligon Jordan • NON-SIMPEL (NON-SIMPLE) Jika ada segmen garis yang saling berpotongan
JENIS – JENIS POLIGON • EQUIANGULAR Jika besar tiap-tiap sudut pada pojoknya sama besar • CYCLIC Jika semua pojoknya terletak dalam sebuah lingkaran • EQUILATERAL Jika semua sisi-sisinya sama panjang
WELL, THEN, HOW TO DRAW A BOX? Given two endpoints as one and the other corner, separated diagonally (x1, y1) = (0, 1) (x2, y2) = (5, 7) Image1.canvas.moveto(x1,y1); Image1.canvas.lineto(x2,y1); Image1.canvas.lineto(x2,y2); Image1.canvas.lineto(x1,y2); Image1.canvas.lineto(x1,y1);
YOU’RE SMART! Well, I suppose now you can figure out the way to draw these objects too: Triangle – with three known points Trapesium – with four known points Parallelepipedum – with four known points Kite – with four known points
ANOTHER CLUE @ DELPHI Changing line colour: Image1.canvas.pen.color := RGB(200,100,50);
Changing line weight: Image1.canvas.pen.width := 3;
Changing fill colour: Image1.canvas.brush.color := RGB(200,100,50);
Filling a polygon (closed lines at endpoints): Image1.canvas.FloodFill(x,y,Tcolor,TFillStyle); TColor: expected bordering colour; TFillStyle: fsBorder – fill until meet a border with such a colour fsSurface– fill the colour until borders with another colour Image1.canvas.FloodFill(40,40,RGB(255,0,0),fsBorder);
Primitives Descendant
Ellipse & Arc
Ascend from the Primitives:
Conical Bhs Indonesia: Konik
Circle A group of points having the same distance from a centre point (xc, yc) Described as (x – xc)2 + (y – yc)2 = r2 Where r : radius (perimeter) xc, yc : centre point x, y: plot of the circle e.g. x2 + y2 = 100
How to draw a circle? We can pretend to plot it as a function of y=f(x) y = yc ± (r2 – (xc – x)2) ½ But it is rather take a thought to implement, since we have 4 quadrants; and that (x, y) itself, in fact, is a result plotted by r Then, we could use the perimeter function: x = xc + (r cosθ) y = yc + (r sinθ)
How to draw a circle? Delphi reminder Delphi operates trigonometry functions using radian instead of degree 360 degree = 2π radian So make sure you specify the θ in radian theta := 2 * PI * (deg / 360); x := xc + (r * cos(theta)); y := yc + (r * sin(theta));
1. Direct Primitive Plotting xc:=100; yc:=100; r:=50; incr := 1 / r; theta1 := 0; theta2 := 2 * PI; While (theta1 < theta2) do begin x := xc + (r * cos(theta1)); y := yc + (r * sin(theta1)); image1.canvas.pixels[trunc(x),trunc(y)]:=clRed; theta1 := theta1 + incr; end;
Circle plotting problem If we plot a line using integer loop, we will have a line that is not continuous – same problem as the line. So, how we make it a smooth one? y = yc ± (r2 – (xc – x)2) ½ Which, if we started with centre point (x,y) for just a 90 degree part, could result in: x2 + y2 = r2 x2 + y2 – r2 = 0
2. Midpoint Algorithm This algorithm draws a circle from 4 starting points, using the main axis, then develop around towards another axis Midpoint algorithm use these definitions of decisive points: P0 = 1 – r on increment of x, next P will be P = P + (2 * x) + 1 if previous P < 0 or y = y – 1 (decrease y first) P = P + (2 * (x - y)) + 1 if previous P >= 0
2. Midpoint Algorithm xc:=100; yc:=100; r:=50; x:= 0; y:= r; p:= 1-r; While (x < y) do begin image1.canvas.pixels[xc+x,yc+y]:=clRed; image1.canvas.pixels[xc+x,yc-y]:=clRed; image1.canvas.pixels[xc-x,yc+y]:=clRed; image1.canvas.pixels[xc-x,yc-y]:=clRed; image1.canvas.pixels[xc+y,yc+x]:=clRed; image1.canvas.pixels[xc+y,yc-x]:=clRed; image1.canvas.pixels[xc-y,yc+x]:=clRed; image1.canvas.pixels[xc-y,yc-x]:=clRed;
2. Midpoint Algorithm x := x + 1; if p < 0 then p := p + (2 * x) + 1 else begin y := y - 1; p := p + (2 * (x – y)) + 1; end; end;
3. Bresenham Algorithm Same as midpoint, this algorithm draws a circle from 4 starting points, using the main axis, then develop around towards another axis But Bresenham use these definitions of decisive points: P0 = 3 – (2 * r) using the current x, next P will be P = P + (4 * x) + 6 if previous P < 0 or P = P + (4 * (x - y)) + 10 if previous P >= 0 then decrease y after decisive points found, then increase x
3. Bresenham Algorithm xc:=100; yc:=100; r:=50; x:= 0; y:= r; p:= (3 – (2 * r)); While (x < y) do begin image1.canvas.pixels[xc+x,yc+y]:=clRed; image1.canvas.pixels[xc+x,yc-y]:=clRed; image1.canvas.pixels[xc-x,yc+y]:=clRed; image1.canvas.pixels[xc-x,yc-y]:=clRed; image1.canvas.pixels[xc+y,yc+x]:=clRed; image1.canvas.pixels[xc+y,yc-x]:=clRed; image1.canvas.pixels[xc-y,yc+x]:=clRed; image1.canvas.pixels[xc-y,yc-x]:=clRed;
3. Bresenham Algorithm if p < 0 then p := p + (4 * x) + 6 else begin p := p + (4 * (x – y)) + 10; y := y – 1; end; x := x + 1; end;
4. Native Delphi Keyword Delphi cannot draw a circle using centre point, instead it uses endpoints represent a rectangle outside the circle
4. Native Delphi Keyword (x1, y1) = (0, 1) (x2, y2) = (10, 31) Then, it becomes as simple as this: Image1.canvas.ellipse(x1,y1,x2,y2);
Didn’t result in anything? Don’t forget to name the colour first! Image1.canvas.pen.color := clRed; Image1.canvas.ellipse(x1,y1,x2,y2);
What makes a circle and an ellipse different? Only the radius does. An ellipse has different xand y-radius, while a circle has the same. An ellipse’s equation is described as Ax2 + By2 + Cxy + Dx + F = 0 or, to emphasise the radius difference, use the perimeter equation: x = xc + (rx cosθ) y = yc + (ry sinθ)
1. Direct Primitive Plotting xc:=100; yc:=100; rx:=100; ry:=50; theta1 := 0; theta2 := 2 * PI; incr := 1 / rx; While (theta1 < theta2) do begin x := xc + (rx * cos(theta1)); y := yc + (ry * sin(theta1)); image1.canvas.pixels[trunc(x),trunc(y)]:=clRed; theta1 := theta1 + incr; end;
2. 4-symmetry Algorithm xc:=300; yc:=300; rx:=50; ry:=50; theta1 := 0; theta2 := (2 * PI) / 4; incr := 1/rx; While (theta1 < theta2) do begin x := rx * cos(theta1); y := ry * sin(theta1); image1.canvas.pixels[trunc(xc+x),trunc(yc+y)]:=clGreen; image1.canvas.pixels[trunc(xc+x),trunc(yc-y)]:=clGreen; image1.canvas.pixels[trunc(xc-x),trunc(yc+y)]:=clGreen; image1.canvas.pixels[trunc(xc-x),trunc(yc-y)]:=clGreen;
theta1 := theta1 + incr; end;
Five topics
to choose
Stick Rotation
Stick Rotation
Gradual Rotation
Draw here deliberately
Gradual Rotation
LIPS
LIPS Fill colour musn’t white Outline colour musn’t white
Intersection
Intersection Fill colour musn’t white Outline colour must be black
Polyline and Polygon
Polyline and Polygon
Fill colour musn’t white Line colour must be black
Which one will you choose?
Discuss comprehensively with your team and PICK ONE!