Sebelumnya kita telah berlatih untuk menampilkan dan menggerakan bet dengan menggunakan mouse dan keyboad. Sekarang mari kita lanjutkan latihannya dengan gerakan bolanya. Tidak seperti gerakan bet yang hanya bergerak pada sumbu y, gerakan bola bisa kesemua arah. Baik di sumbu x maupun y.
Ok, kita mulai dengan menambahkan variable terlebih dahulu
Vector2 ballLoc = new Vector2(400.0f, 240.0f);Vector2 ballTraj = new Vector2();
bool playing = false;Variable ballLoc kita gunakan untuk menyimpan lokasi/posisi bola. Kita menggunakan Vector2 karena kita akan menyimpan koordinat bola yang terdiri dari komponen x dan y. Lokasi bola kita inisiasi di tengah-tengah layar, yaitu koordinat (400,240).
Variable ballTraj akan kita gunakan untuk menyimpan nilai trajectory/lintasan bola. Nilai dari variable ini akan kita gunakan untuk mengubah/mengupdate posisi bola dengan cara menambah atau mengurangi nilai x dan y.
Terakhir, variable playing akan gunakan untuk menentukan status bola. Apabila playing=true, berarti bola sedang dimainkan, dan posisi bola akan kita update. Apabila playing=false, bola dalam keadaan diam.
Btw, kita akan mendefinisikan dulu hal2 yang menyangkut pergerakan bola.
- Bola diupdate berdasarkan nilai variable ballTraj.
- Jika bola membentur batas atas/bawah, maka bola akan memantul.
- Jika bola membentur bet, maka bola akan memantul.
- Jika bola melewati batas kanan dan kiri layar, maka status playing=false. Kalo mau, kita bisa menghitung skor disini.
Kita tambahkan koding berikut pada prosedur Update
if (!playing)
{
if (kb.IsKeyDown(Keys.Space))
{
playing = true;
ballLoc = new Vector2(400.0f, 240.0f);
ballTraj = new Vector2(0.25f, -0.25f);
}
}
Jika status playing=false, kita cek status tombol Spasi. Jika Spasi ditekan, kita rubah status playing=true, dan kita set ulang lokasi bola. Arah awal bola kita rencanakan ke kanan atas, sehingga ballTraj kita inisiasi dengan nilai X positif, dan Y negatif. Oh ya, koordinat (0,0) berada di sudut kiri atas. Nilai positif ke kanan dan ke bawah. Sedikit berbeda dengan koordinat kartesius yang biasa kita kenal, nilai makin gede (positif) ke kanan dan keatas.
Ok, kita mulai dengan point pertama.
Bola diupdate berdasarkan nilai ballTraj. Update ini dilakukan jika status playing=true.
Tambahkan koding berikut pada prosedur Update
if (playing)Seperti pada update posisi bet dengan kontrol keyboard, kita juga mengupdate bola dengan melibatkan variable gameTime. Ini ditujukan agar kecepatan gerak bola kita stabil meskipun fps-nya berubah akibat load komputer yang berat/tinggi.
{
ballLoc += ballTraj * (float)gameTime.ElapsedGameTime.Milliseconds;
}
Next, kita coba tambahkan koding untuk menampilkan bola, agar kita bisa melihat hasilnya.
Update prosedur Draw dengan menambahkan koding menampilkan bola, seperti yang sudah kita bahas pada part 2.
spriteBatch.Draw(Sekarang kita test program kita dengan pencet F5. Kemudian tekan tombol Spasi untuk mulai menggerakan bola. Tampak bola akan bergerak ke kanan atas, hingga akhrinya menghilang setelah melewati batas layar.
spritesTexture,
new Rectangle((int)ballLoc.X - 16, (int)ballLoc.Y - 16, 32, 32),
new Rectangle(64, 0, 64, 64),
Color.White);
Ok, sekarang kita masuk ke point 2, agar bola bisa memantul jika menabrak batas atas/bawah layar.
Update prosedur Update dengan koding berikut
if (playing)Apabila koordinat bola telah mencapai 16 atau 464, itu berarti bola telah mencapai batas atas/bawah. Maka arah bola pada sumbu Y harus kita balik
{
ballLoc += ballTraj * (float)gameTime.ElapsedGameTime.Milliseconds;
if (ballLoc.Y < 16 || ballLoc.Y > 464) ballTraj.Y = -ballTraj.Y;
}
Pencet F5 untuk melihat perubahannya..
Sekarang kita lihat, bola kita sudah memantul ketika menabrak dinding atas/bawah. Tapi masih menembus bet. Nah, sekarang kita masuk point 3, bola memantul jika menabrak bet.
Kita coba latihan untuk bet 2 dulu ya, biar lebih mudah untuk ditest.
Skenarionya adalah, jika bola memasuki area bola, dan bola bersinggungan dengan bet, maka arah bola pada sumbu x kita balik.
Ok, kita update lagi koding kita pada prosedur update
if (playing)
{
ballLoc += ballTraj * (float)gameTime.ElapsedGameTime.Milliseconds;
if (ballLoc.Y < 16 || ballLoc.Y > 464) ballTraj.Y = -ballTraj.Y;
if (ballLoc.X > 752 && ballTraj.X > 0)
{
if (ballLoc.Y < betLoc[1] + 64 && ballLoc.Y > betLoc[1] - 64)
{
ballTraj.X = -ballTraj.X;
}
}
}
Mari pencet F5 untuk testing. Tekan Spasi untuk mulai menggerakan bola, kemudian coba naikkan bet 2 dengan menekan tombol panah atas agar bola mengenai bet 2. Aku menambahkan ballTraj.X > 0 untuk test, apakah bola benar2 sedang bergerak ke kanan.
Sekarang, kita sudah bisa memantulkan bola pada bet. Tapi tunggu dulu. Sebelum kita lanjutkan, aku pingin memodifikasi pantulan bola pada bet, agar lebih seru. Skenarionya adalah, posisi tempat bola memantul pada bet akan mempengaruhi arah bola pada sumbu Y. (Tapi kayaknya pong yang asli jg kayak gitu kali ya ^_^)
Ok, kita update koding kita
if (ballLoc.X > 752 && ballTraj.X > 0)Dengan logika yang sama, kita bisa melakukannya untuk pantulan pada bet 1
{
if (ballLoc.Y < betLoc[1] + 64 && ballLoc.Y > betLoc[1] - 64)
{
ballTraj.X = -ballTraj.X;
ballTraj.Y = (ballLoc.Y - betLoc[1]) * 0.01f;
}
}
if (ballLoc.X < 48 && ballTraj.X < 0)Coba sekarang kita test dengan F5. Nampaknya bola sudah memantul dengan benar. Tapi tunggu dulu! Barusan aq liat, kalo bola membentur bet dari samping, masih bisa memantul kedepan.
{
if (ballLoc.Y < betLoc[0] + 64 && ballLoc.Y > betLoc[1] - 64)
{
ballTraj.X = -ballTraj.X;
ballTraj.Y = (ballLoc.Y - betLoc[0]) * 0.01f;
}
}
Ok, kita tambahkan sedikit modifikasi seperti berikut.
//bola memantul pada bet 1Logikanya, bola hanya akan memantul pada bet jika bola masih dalam batas koordinat Y bet, dan bola masih berada di permukaan bet.
if (ballLoc.X < 48 && ballTraj.X < 0)
{
if (ballLoc.Y < betLoc[0] + 64 && ballLoc.Y > betLoc[1] - 64)
{
if (ballLoc.X > 40) ballTraj.X = -ballTraj.X;
ballTraj.Y = (ballLoc.Y - betLoc[0]) * 0.01f;
}
}
//bola memantul pada bet 2
if (ballLoc.X > 752 && ballTraj.X > 0)
{
if (ballLoc.Y < betLoc[1] + 64 && ballLoc.Y > betLoc[1] - 64)
{
if (ballLoc.X < 760) ballTraj.X = -ballTraj.X;
ballTraj.Y = (ballLoc.Y - betLoc[1]) * 0.01f;
}
}
Terakhir, point 4, jika bola melewati batas kanan/kiri, playing=false.
Mudah saja, kita cukup cek apakah koordinat x bola melewati batas max/min layar.
if (ballLoc.X < 0 || ballLoc.X > 800) playing = false;Done! Gameplay utama pong telah selesai kita buat. Sebenernya masih banyak kekurangan, kamu bisa improve sendiri yak. :)
Oh ya, latihan kita masih panjang kq. Kita belum berlatih menambahkan suara, effek, dll.
Sampai jumpa di latihan berikutnya kawan..
Source code (part1):
BalasHapus----------
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Pong
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D spritesTexture;
float[] betLoc = new float[] { 240.0f, 240.0f };
Vector2 ballLoc = new Vector2(400.0f, 240.0f);
Vector2 ballTraj = new Vector2(0.25f, -0.25f);
bool playing = false;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
spritesTexture = Content.Load(@"gfx/sprites");
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
Source code (part2):
BalasHapus----
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
MouseState mouse = Mouse.GetState();
betLoc[0] = mouse.Y;
if (betLoc[0] < 64.0f) betLoc[0] = 64.0f;
if (betLoc[0] > 416.0f) betLoc[0] = 416.0f;
KeyboardState kb = Keyboard.GetState();
if (kb.IsKeyDown(Keys.Up)) betLoc[1] -= (float)gameTime.ElapsedGameTime.Milliseconds * 0.5f;
if (kb.IsKeyDown(Keys.Down)) betLoc[1] += (float)gameTime.ElapsedGameTime.Milliseconds * 0.5f;
if (betLoc[1] < 64.0f) betLoc[1] = 64.0f;
if (betLoc[1] > 416.0f) betLoc[1] = 416.0f;
if (!playing)
{
if (kb.IsKeyDown(Keys.Space))
{
playing = true;
ballLoc = new Vector2(400.0f, 240.0f);
ballTraj = new Vector2(0.25f, -0.25f);
}
}
//jika status playing
if (playing)
{
//update lokasi bola
ballLoc += ballTraj * (float)gameTime.ElapsedGameTime.Milliseconds;
//bola memantul pada batas layar atas dan bawah
if (ballLoc.Y < 16 || ballLoc.Y > 464) ballTraj.Y = -ballTraj.Y;
//bola memantul pada bet 1
if (ballLoc.X < 48 && ballTraj.X < 0)
{
if (ballLoc.Y < betLoc[0] + 64 && ballLoc.Y > betLoc[1] - 64)
{
if (ballLoc.X > 40) ballTraj.X = -ballTraj.X;
ballTraj.Y = (ballLoc.Y - betLoc[0]) * 0.01f;
}
}
//bola memantul pada bet 2
if (ballLoc.X > 752 && ballTraj.X > 0)
{
if (ballLoc.Y < betLoc[1] + 64 && ballLoc.Y > betLoc[1] - 64 )
{
if (ballLoc.X < 760) ballTraj.X = -ballTraj.X;
ballTraj.Y = (ballLoc.Y - betLoc[1]) * 0.01f;
}
}
if (ballLoc.X < 0 || ballLoc.X > 800) playing = false;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
// TODO: Add your drawing code here
spriteBatch.Begin();
//gambar paddle
spriteBatch.Draw(spritesTexture, new Vector2(0, betLoc[0] - 64), new Rectangle(0, 0, 32, 128), Color.White);
spriteBatch.Draw(spritesTexture, new Vector2(768, betLoc[1] - 64), new Rectangle(32, 0, 32, 128), Color.White);
//gambar bola
spriteBatch.Draw(spritesTexture,
new Rectangle((int)ballLoc.X - 16, (int)ballLoc.Y - 16, 32, 32),
new Rectangle(64, 0, 64, 64),
Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}