Số 53
HỒ LÔ BIẾN

Dành cho U16: Làm quen với C# và .NET
Lên mây xuống gió với Harry Potter

Anh SI SÁP

- Tí Cận này, lúc sáng, anh gọi điện thoại cho em nhưng không có ai trả lời. Bộ lúc đó còn “nướng” trên giường hả?

- Dạ đâu có! Không hiểu sao dạo này em mê “xập xình”, ủa lộn, mê lập trình quá nên không để ý đến chung quanh.

- Í, thiệt vậy không? Mê lập trình thì tốt rồi. Nhưng em đang “lập trình” cái gì vậy?

- Lần trước anh hướng dẫn em lập trình cho “Harry Potter” bay hay dừng theo ý định của người dùng. Em nghĩ nếu mình lập trình thêm cho Harry “cất cánh và hạ cánh” thì chương trình sẽ hấp dẫn hơn. Anh đã điều khiển cho Harry bay về bên trái bằng cách thay đổi trị của thuộc tính Left của khung hình sau mỗi tình huống Tick nên em nghĩ rằng mình có thể làm cho Harry “lên mây, xuống gió” bằng cách thay đổi thuộc tính Top của khung hình cũng trong tình huống Tick bằng cách thêm một đoạn mã như vầy (đoạn mã 1).

Đoạn mã 1

...

// Harry chưa đụng “nóc”

if ((picHarry.Top - 5) > this.ClientRectangle.Top)

// Tiếp tục cho bay lên

picHarry.Top -= 5;

// Harry đã đụng nóc

else

picHarry.Top = 0;

...

- À... Em làm vậy là đúng hướng, nhưng chưa đúng cách. Theo cách của em, Harry chỉ bay lên cho đến khi đụng “nóc”. Vậy rốt cuộc chỉ có bay ngang mà thôi! Dù sao, em mới làm quen C# mà tự viết được như thế là rất đáng khen! Anh sẽ giúp em bổ sung “DHA và các khoáng chất cần thiết”! Cụ thể, anh sẽ thêm vào hàm tạo dựng Form1() và hàm timer1-Tick(). Em xem nhé... (đoạn mã 2).

Đoạn mã 2

public class

Form1:System.Windows.Forms.Form

{

...

private bool bBay=false;

// Bước dịch chuyển của Harry

private const int buoc = 5;

private int yBandau;

private bool bLen;

public Form1()

{

InitializeComponent();

// Lưu lại tọa độ y ban đầu

yBandau = picHarry.Top;

// Xuất phát theo hướng bay lên

bLen = true;

}

...

private void timer1-Tick(object

sender,

System.EventArgs e)

{

// Giấu khung hình

picHarry.Visible = false;

// Nếu chưa chạm khung bên phải, tiếp tục “xung phong”

if (picHarry.Left + picHarry.Width + buoc < this.ClientRectangle.Width)

picHarry.Left += buoc;

// Đã chạm khung bên phải

else

picHarry.Left = 0;

// Harry đang bay lên

if (bLen)

// Harry chưa đụng “nóc”

if ((picHarry.Top - buoc) > this.ClientRectangle.Top)

// Tiếp tục cho bay lên

picHarry.Top -= buoc;

// Harry đã đụng nóc

else

{

// Ở Tick tiếp theo Harry sẽ hạ xuống

bLen = false;

picHarry.Top = 0;

}

// Harry đang hạ cánh

else

// Chưa đáp xuống ngang vị trí xuất phát

if ((picHarry.Top + buoc) < yBandau)

// Tiếp tục hạ xuống

picHarry.Top += buoc;

// Đã ngang vị trí xuất phát

else

{

// Ở Tick tiếp theo Harry sẽ bay lên

bLen = true;

picHarry.Top = yBandau;

}

// Cho hiện lại khung hình

picHarry.Visible = true;

}

- Ủa, anh khai báo thêm các biến mới trong hàm tạo dựng Form1() làm chi dzậy? Mà tại sao phải giấu khung hình rồi cho hiện lại?

- Trước đây mình dùng hằng số 5 trong câu lệnh picHarry.Left += 5. Viết như vậy nghĩa là sau mỗi Tick, Harry “nhảy cóc” về bên trái với bước nhảy dài 5 pi-xeo (pixel) trên màn hình. Để tiện cho việc điều chỉnh sau này, anh thay hằng số 5 bằng hằng số buoc có trị ban đầu là 5. Ngoài ra, anh còn khai báo thêm biến yBandau và biến bLen. Biến yBandau dùng để lưu lại tọa độ xuất phát ban đầu theo trục tung (trục y) của Harry để mình dễ dàng kiểm soát, không cho Harry hạ xuống thấp hơn tọa độ y ban đầu này. Biến bLen dùng để kiểm soát hướng bay hiện hành là lên (true) hay xuống (false). Nhằm tránh hiện tượng “cà giựt” khi Harry bay, anh cho khung hình ẩn trước khi thay đổi tọa độ và cho hiện lại sau khi hoàn tất. Tuy nhiên, việc thoắt ẩn thoắt hiện như vậy lại gây ra hiện tượng chớp chớp, hơi khó chịu. Để khắc phục hiện tượng này, anh nghĩ mình nên dùng một kỹ thuật gọi là “vùng đệm kép” (double buffering) bằng cách thêm ba dòng lệnh như thế này vào hàm tạo dựng Form1()... (đoạn mã 3). Vậy là xong! Em biên dịch rồi cho chạy thử xem sao.

Đoạn mã 3

public Form1()

{

InitializeComponent();

// Kích hoạt vùng đệm kép

SetStyle(ControlStyles.UserPaint, true);

SetStyle(ControlStyles.AllPaintingInWmPaint, true);

SetStyle(ControlStyles.DoubleBuffer, true);

// Lưu lại tọa độ y ban đầu

yBandau = picHarry.Top;

// Xuất phát theo hướng bay lên

bLen = true;

}

- A... “Nó” bay tốt quá! “Gia đình chúng tôi xin cảm ơn và... hậu tạ”! Anh có thích “chè đậu đen, bột báng, nước dừa” hông? Em “trân trọng kính mời” anh một chầu đầu hẻm, nghen!

[Đầu trang]
Trang chủ
Thư ngỏ
Nội lực "Peter Pan"
Cầu nối Intel Việt Nam
Chuyện trong tuần
Nhóm Frontpage
Cõi người ta
Kim cương doanh nghiệp
Bình luận thị trường
Cõi Mô-bai
Chuyên đề
Bổ ngửa
Nuôi hồn Robot
Túi càn khôn IT
Hồ lô biến
Cảm về Game
Nhật ký e-CHÍP
Bản quyền VASC Orient, Công ty phát triển phần mềm VASC
99 Triệu Việt Vương HN; Tel: (04) 9782235 • email: echip@vasc.com.vn