Senin, 20 Juli 2015

Membatasi Ruang Gerak PacMan

Pagi hari yang cerah, burung-burung  pada lompat sana dan lompat sini menyambut pagi...


Selamat pagi rekan-rekan sekalian, senang rasanya bisa kembali menulis di blog ini, blog yang aku peruntukkan untuk membagi ilmu pemrograman grafik game.

Pada kesempatan kali ini ogut masih akan bercerita tentang vektor yang bermanfaat untuk membatasi ruang gerak suatu objek. Program yang menggunakan perhitungan skala proyeksi vektor untuk membatasi ruang gerak sebuah objek.


Contoh implementasi membatasi ruang gerak sebuah objek dapat Anda lihat pada program PacMan, tokoh pacman hanya dapat berjalan di jalur-jalur yang telah ditentukan karena ruang geraknya dibatasi.


Untuk proses pendeteksian agar pacman tidak menabrak tembok diperlukan tiga buah titik deteksi seperti yang terlihat pada gambar di atas.

Berikut kode program untuk program PacMan, perhatikanlah cara untuk menentukan tiga titik deteksi, source code dapat Anda download di link yang telah disediakan.

Tentukan nilai awal untuk PacMan dan Tembok.

    Public Sub SettingNilaiAwal()
        'PacMan
        PacMan.Ax = -45 : PacMan.Ay = -45
        PacMan.Bx = 45 : PacMan.By = -45
        PacMan.Cx = 45 : PacMan.Cy = 45
        PacMan.Dx = -45 : PacMan.Dy = 45

        PacMan.Index_Tekstur = 0
        Delay_Tekstur_Pacman = 1
        Plus_Indeks_Tekstur_Pacman = True
        'set tekstur PacMan arah kiri
        TkAx = 0 : TkAy = 0
        TkBx = 1 : TkBy = 0
        TkCx = 1 : TkCy = 1
        TkDx = 0 : TkDy = 1

        PacMan_Speed = 8

        'Tembok(0) horisontal atas
        Tembok(0).Ax = -GlControl1.Width + 10
        Tembok(0).Ay = GlControl1.Height - 70
        Tembok(0).Bx = GlControl1.Width - 10
        Tembok(0).By = Tembok(0).Ay
        Tembok(0).Cx = Tembok(0).Bx
        Tembok(0).Cy = Tembok(0).By + 50
        Tembok(0).Dx = Tembok(0).Ax
        Tembok(0).Dy = Tembok(0).Cy

        Tembok(0).VektorA.i = Tembok(0).Bx - Tembok(0).Ax
        Tembok(0).VektorA.j = Tembok(0).By - Tembok(0).Ay
        Tembok(0).VektorB.i = Tembok(0).Dx - Tembok(0).Ax
        Tembok(0).VektorB.j = Tembok(0).Dy - Tembok(0).Ay

        'Tembok(1) vertikal kiri
        Tembok(1).Ax = -GlControl1.Width + 370
        Tembok(1).Ay = -GlControl1.Height + 200
        Tembok(1).Bx = Tembok(1).Ax
        Tembok(1).By = Tembok(1).Ay + 600
        Tembok(1).Cx = Tembok(1).Bx - 50
        Tembok(1).Cy = Tembok(1).By
        Tembok(1).Dx = Tembok(1).Cx
        Tembok(1).Dy = Tembok(1).Ay

        Tembok(1).VektorA.i = Tembok(1).Bx - Tembok(1).Ax
        Tembok(1).VektorA.j = Tembok(1).By - Tembok(1).Ay
        Tembok(1).VektorB.i = Tembok(1).Dx - Tembok(1).Ax
        Tembok(1).VektorB.j = Tembok(1).Dy - Tembok(1).Ay

        'Tembok(2) vertikal kanan
        Tembok(2).Ax = -GlControl1.Width + 570
        Tembok(2).Ay = -GlControl1.Height + 400
        Tembok(2).Bx = Tembok(2).Ax
        Tembok(2).By = Tembok(2).Ay + 400
        Tembok(2).Cx = Tembok(2).Bx - 50
        Tembok(2).Cy = Tembok(2).By
        Tembok(2).Dx = Tembok(2).Cx
        Tembok(2).Dy = Tembok(2).Ay

        Tembok(2).VektorA.i = Tembok(2).Bx - Tembok(2).Ax
        Tembok(2).VektorA.j = Tembok(2).By - Tembok(2).Ay
        Tembok(2).VektorB.i = Tembok(2).Dx - Tembok(2).Ax
        Tembok(2).VektorB.j = Tembok(2).Dy - Tembok(2).Ay

        'Tembok(3) horisontal tengah
        Tembok(3).Ax = -GlControl1.Width + 520
        Tembok(3).Ay = -GlControl1.Height + 350
        Tembok(3).Bx = GlControl1.Width - 10
        Tembok(3).By = Tembok(3).Ay
        Tembok(3).Cx = Tembok(3).Bx
        Tembok(3).Cy = Tembok(3).By + 50
        Tembok(3).Dx = Tembok(3).Ax
        Tembok(3).Dy = Tembok(3).Cy

        Tembok(3).VektorA.i = Tembok(3).Bx - Tembok(3).Ax
        Tembok(3).VektorA.j = Tembok(3).By - Tembok(3).Ay
        Tembok(3).VektorB.i = Tembok(3).Dx - Tembok(3).Ax
        Tembok(3).VektorB.j = Tembok(3).Dy - Tembok(3).Ay

        'Tembok(4) horisontal terbawah
        Tembok(4).Ax = -GlControl1.Width + 10
        Tembok(4).Ay = -GlControl1.Height + 150
        Tembok(4).Bx = Tembok(4).Ax + 900
        Tembok(4).By = Tembok(4).Ay
        Tembok(4).Cx = Tembok(4).Bx
        Tembok(4).Cy = Tembok(4).By + 50
        Tembok(4).Dx = Tembok(4).Ax
        Tembok(4).Dy = Tembok(4).Cy

        Tembok(4).VektorA.i = Tembok(4).Bx - Tembok(4).Ax
        Tembok(4).VektorA.j = Tembok(4).By - Tembok(4).Ay
        Tembok(4).VektorB.i = Tembok(4).Dx - Tembok(4).Ax
        Tembok(4).VektorB.j = Tembok(4).Dy - Tembok(4).Ay

    End Sub

Gerakkan PacMan sesuai dengan tombol keyboard yang ditekan user, serta hitung tiga titik deteksi tabrakan.

    Private Sub Tekan_Keyboard()
        NilaiKey = 0
        'kiri
        If (GetKeyState(Keys.J) And &H1000) Then
            NilaiKey = NilaiKey + 10000
        End If
        'kanan
        If (GetKeyState(Keys.L) And &H1000) Then
            NilaiKey = NilaiKey + 20000
        End If
        'atas
        If (GetKeyState(Keys.I) And &H1000) Then
            NilaiKey = NilaiKey + 1000
        End If
        'bawah
        If (GetKeyState(Keys.K) And &H1000) Then
            NilaiKey = NilaiKey + 2000
        End If

        '==========================================
        'proses sesuai dengan key yang ditekan user
        '==========================================

        'kiri
        If NilaiKey = 10000 Then
            TkAx = 0 : TkAy = 0
            TkBx = 1 : TkBy = 0
            TkCx = 1 : TkCy = 1
            TkDx = 0 : TkDy = 1

            '=====================================
            'tentukan titik untuk deteksi tabrakan
            '=====================================
            'titik pertama
            DeteksiTitikX1 = PacMan.Ax - PacMan_Speed
            DeteksiTitikY1 = PacMan.Ay
            'titik kedua
            DeteksiTitikX2 = PacMan.Dx - PacMan_Speed
            DeteksiTitikY2 = PacMan.Dy
            'titik tengah
            DeteksiTitikTengahX = DeteksiTitikX1
            DeteksiTitikTengahY = DeteksiTitikY1 + ((DeteksiTitikY2 - DeteksiTitikY1) / 2)
        End If

        'kanan
        If NilaiKey = 20000 Then
            TkAx = 1 : TkAy = 0
            TkBx = 0 : TkBy = 0
            TkCx = 0 : TkCy = 1
            TkDx = 1 : TkDy = 1

            '=====================================
            'tentukan titik untuk deteksi tabrakan
            '=====================================
            'titik pertama
            DeteksiTitikX1 = PacMan.Bx + PacMan_Speed
            DeteksiTitikY1 = PacMan.By
            'titik kedua
            DeteksiTitikX2 = PacMan.Cx + PacMan_Speed
            DeteksiTitikY2 = PacMan.Cy
            'titik tengah
            DeteksiTitikTengahX = DeteksiTitikX1
            DeteksiTitikTengahY = DeteksiTitikY1 + ((DeteksiTitikY2 - DeteksiTitikY1) / 2)
        End If

        'atas
        If NilaiKey = 1000 Then
            TkAx = 1 : TkAy = 0
            TkBx = 1 : TkBy = 1
            TkCx = 0 : TkCy = 1
            TkDx = 0 : TkDy = 0

            '=====================================
            'tentukan titik untuk deteksi tabrakan
            '=====================================
            'titik pertama
            DeteksiTitikX1 = PacMan.Cx
            DeteksiTitikY1 = PacMan.Cy + PacMan_Speed
            'titik kedua
            DeteksiTitikX2 = PacMan.Dx
            DeteksiTitikY2 = PacMan.Dy + PacMan_Speed
            'titik tengah
            DeteksiTitikTengahX = DeteksiTitikX2 + ((DeteksiTitikX1 - DeteksiTitikX2) / 2)
            DeteksiTitikTengahY = DeteksiTitikY1
        End If

        'bawah
        If NilaiKey = 2000 Then
            TkAx = 0 : TkAy = 1
            TkBx = 0 : TkBy = 0
            TkCx = 1 : TkCy = 0
            TkDx = 1 : TkDy = 1

            '=====================================
            'tentukan titik untuk deteksi tabrakan
            '=====================================
            'titik pertama
            DeteksiTitikX1 = PacMan.Ax
            DeteksiTitikY1 = PacMan.Ay - PacMan_Speed
            'titik kedua
            DeteksiTitikX2 = PacMan.Bx
            DeteksiTitikY2 = PacMan.By - PacMan_Speed
            'titik tengah
            DeteksiTitikTengahX = DeteksiTitikX1 + ((DeteksiTitikX2 - DeteksiTitikX1) / 2)
            DeteksiTitikTengahY = DeteksiTitikY1
        End If
    End Sub

Deteksi tabrakan antara PacMan dan Tembok.

    Private Sub Render_PacMan()
        'membuat animasi mulut PacMan bergerak
        Delay_Tekstur_Pacman = Delay_Tekstur_Pacman + 1
        If Delay_Tekstur_Pacman > 2 Then
            Delay_Tekstur_Pacman = 1

            If Plus_Indeks_Tekstur_Pacman = True Then
                PacMan.Index_Tekstur = PacMan.Index_Tekstur + 1
                If PacMan.Index_Tekstur > 3 Then
                    PacMan.Index_Tekstur = 2
                    Plus_Indeks_Tekstur_Pacman = False
                End If
            Else
                'minus
                PacMan.Index_Tekstur = PacMan.Index_Tekstur - 1
                If PacMan.Index_Tekstur = -1 Then
                    PacMan.Index_Tekstur = 1
                    Plus_Indeks_Tekstur_Pacman = True
                End If
            End If
        End If

        '===================================
        'deteksi tabrakan dengan tembok
        '(3 titik untuk mendeteksi tabrakan)
        '===================================
        Dim i As Integer
        Dim SkalaPro1, SkalaPro2 As Single
        Dim Vektor_PacMan As Vektor_Properties
        Dim OK_Translasi_PacMan As Boolean

        OK_Translasi_PacMan = True

        For i = 0 To 4
            'deteksi tabrakan titik pertama
            Vektor_PacMan = Create_Vektor(Tembok(i).Ax, Tembok(i).Ay, DeteksiTitikX1, DeteksiTitikY1)
            'hitung skala proyeksi
            SkalaPro1 = Dot_Product(Vektor_PacMan, Tembok(i).VektorA) / (Panjang_Vektor(Tembok(i).VektorA) * Panjang_Vektor(Tembok(i).VektorA))
            SkalaPro2 = Dot_Product(Vektor_PacMan, Tembok(i).VektorB) / (Panjang_Vektor(Tembok(i).VektorB) * Panjang_Vektor(Tembok(i).VektorB))

            If (SkalaPro1 >= 0 And SkalaPro1 <= 1 And SkalaPro2 >= 0 And SkalaPro2 <= 1) Then
                'PacMan menabrak tembok
                OK_Translasi_PacMan = False
            Else
                'deteksi tabrakan titik kedua
                Vektor_PacMan = Create_Vektor(Tembok(i).Ax, Tembok(i).Ay, DeteksiTitikX2, DeteksiTitikY2)
                'hitung skala proyeksi
                SkalaPro1 = Dot_Product(Vektor_PacMan, Tembok(i).VektorA) / (Panjang_Vektor(Tembok(i).VektorA) * Panjang_Vektor(Tembok(i).VektorA))
                SkalaPro2 = Dot_Product(Vektor_PacMan, Tembok(i).VektorB) / (Panjang_Vektor(Tembok(i).VektorB) * Panjang_Vektor(Tembok(i).VektorB))

                If (SkalaPro1 >= 0 And SkalaPro1 <= 1 And SkalaPro2 >= 0 And SkalaPro2 <= 1) Then
                    'PacMan menabrak tembok
                    OK_Translasi_PacMan = False
                Else
                    'deteksi tabrakan titik tengah
                    Vektor_PacMan = Create_Vektor(Tembok(i).Ax, Tembok(i).Ay, DeteksiTitikTengahX, DeteksiTitikTengahY)
                    'hitung skala proyeksi
                    SkalaPro1 = Dot_Product(Vektor_PacMan, Tembok(i).VektorA) / (Panjang_Vektor(Tembok(i).VektorA) * Panjang_Vektor(Tembok(i).VektorA))
                    SkalaPro2 = Dot_Product(Vektor_PacMan, Tembok(i).VektorB) / (Panjang_Vektor(Tembok(i).VektorB) * Panjang_Vektor(Tembok(i).VektorB))

                    If (SkalaPro1 >= 0 And SkalaPro1 <= 1 And SkalaPro2 >= 0 And SkalaPro2 <= 1) Then
                        'PacMan menabrak tembok
                        OK_Translasi_PacMan = False
                    End If
                End If
            End If
        Next

        '==============================================
        'translasi PacMan karena tidak terjadi tabrakan
        '==============================================
        If OK_Translasi_PacMan = True Then
            Translasi_PacMan()
        End If

        GL.Enable(EnableCap.Blend)
        GL.BlendFunc(BlendingFactorSrc.DstColor, BlendingFactorDest.Zero)

        'Mask
        GL.BindTexture(TextureTarget.Texture2D, PacManBMP_Mask(PacMan.Index_Tekstur))
        GL.Begin(BeginMode.Quads)
        GL.TexCoord2(TkAx, TkAy) : GL.Vertex2(PacMan.Ax, PacMan.Ay)
        GL.TexCoord2(TkBx, TkBy) : GL.Vertex2(PacMan.Bx, PacMan.By)
        GL.TexCoord2(TkCx, TkCy) : GL.Vertex2(PacMan.Cx, PacMan.Cy)
        GL.TexCoord2(TkDx, TkDy) : GL.Vertex2(PacMan.Dx, PacMan.Dy)
        GL.End()

        GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.One)
        'BMP
        GL.BindTexture(TextureTarget.Texture2D, PacManBMP(PacMan.Index_Tekstur))
        GL.Begin(BeginMode.Quads)
        GL.TexCoord2(TkAx, TkAy) : GL.Vertex2(PacMan.Ax, PacMan.Ay)
        GL.TexCoord2(TkBx, TkBy) : GL.Vertex2(PacMan.Bx, PacMan.By)
        GL.TexCoord2(TkCx, TkCy) : GL.Vertex2(PacMan.Cx, PacMan.Cy)
        GL.TexCoord2(TkDx, TkDy) : GL.Vertex2(PacMan.Dx, PacMan.Dy)
        GL.End()

        GL.Disable(EnableCap.Blend)

        If CheckBox2.Checked = True Then
            'warna merah untuk garis
            GL.BindTexture(TextureTarget.Texture2D, Red)

            GL.Begin(BeginMode.LineLoop)
            GL.Vertex2(PacMan.Ax, PacMan.Ay)
            GL.Vertex2(PacMan.Bx, PacMan.By)
            GL.Vertex2(PacMan.Cx, PacMan.Cy)
            GL.Vertex2(PacMan.Dx, PacMan.Dy)
            GL.End()
        End If
    End Sub

    Private Sub Translasi_PacMan()
        '=====================================
        'proses translasi tidak memakai vektor
        '=====================================
        'kiri
        If NilaiKey = 10000 Then
            PacMan.Ax = PacMan.Ax - PacMan_Speed
            PacMan.Bx = PacMan.Bx - PacMan_Speed
            PacMan.Cx = PacMan.Cx - PacMan_Speed
            PacMan.Dx = PacMan.Dx - PacMan_Speed
        End If
        'kanan
        If NilaiKey = 20000 Then
            PacMan.Ax = PacMan.Ax + PacMan_Speed
            PacMan.Bx = PacMan.Bx + PacMan_Speed
            PacMan.Cx = PacMan.Cx + PacMan_Speed
            PacMan.Dx = PacMan.Dx + PacMan_Speed
        End If
        'atas
        If NilaiKey = 1000 Then
            PacMan.Ay = PacMan.Ay + PacMan_Speed
            PacMan.By = PacMan.By + PacMan_Speed
            PacMan.Cy = PacMan.Cy + PacMan_Speed
            PacMan.Dy = PacMan.Dy + PacMan_Speed
        End If
        'bawah
        If NilaiKey = 2000 Then
            PacMan.Ay = PacMan.Ay - PacMan_Speed
            PacMan.By = PacMan.By - PacMan_Speed
            PacMan.Cy = PacMan.Cy - PacMan_Speed
            PacMan.Dy = PacMan.Dy - PacMan_Speed
        End If
    End Sub

Ok rekan-rekan sekalian sampai disini dulu artikel kali ini pada kesempatan lain kita sambung lagi obrolan tentang vektor, matematika, game dan grafik programming.

Update 2 Jan 2016

Game lain yang pernah ogut buat dengan VB 6



Salam Sukses Selalu


Heriady
heriady.yoh@gmail.com




Artikel terkait

Mendeteksi Posisi dengan Vektor Proyeksi

Deteksi Tabrakan dengan Proyeksi Vektor

Deteksi Tabrakan dengan Panjang Vektor / Radius

Vektor R2

Tidak ada komentar:

Posting Komentar