Giới thiệu
Trong bài viết này, tôi sẽ chia sẻ về quá trình lập trình một dự án với Raylib và cách sử dụng vector vị trí trong Zig. Tôi đã dành một buổi tối để phát triển mã cho dự án của mình, và kết quả thu được rất thú vị.
Di chuyển hình vuông
Hôm qua, tôi đã tạo một dự án Raylib sử dụng Bootstrap để chỉ hiển thị một hình vuông trên màn hình. Mục tiêu hôm nay là làm cho hình vuông đó di chuyển. Và tôi đã thành công trong việc này!
Làm thế nào tôi thực hiện điều đó?
Tôi phải thừa nhận rằng tôi không hoàn toàn mới mẻ với phát triển game. Đây không phải là lần đầu tiên tôi thử viết một trò chơi. Trước đây, tôi đã từng viết một trò chơi bằng C++ vào năm 2024 trong thời gian nghỉ việc. Tuy nhiên, việc làm quen với Zig đã mang đến cho tôi một thử thách mới.
Điều thú vị về Zig
Zig khiến tôi nhớ đến Go, nhưng cũng có những khác biệt lớn. Tôi đã cố gắng tổ chức mã của mình bằng cách sử dụng một struct cho Player.
zig
const Player = struct{
.x: usize,
.y: usize,
.width: usize,
.height: usize,
}
Struct này định nghĩa vị trí và kích thước của hình vuông trên màn hình. Nếu bạn đã từng làm việc với Raylib, bạn sẽ nhận ra một số vấn đề mà tôi sẽ đề cập sau.
Giống như Go hay Rust, bạn cũng có thể gán các phương thức cho struct của mình. Tuy nhiên, khác với Go, constructor được đặt bên trong struct. Theo quy ước, bạn sẽ khởi tạo đối tượng thông qua phương thức init:
zig
const Player = struct{
.x: usize,
.y: usize,
.width: usize,
.height: usize,
}
pub fn init() Player{
return Player{
// khởi tạo ở đây
};
}
Điều này nhìn khá giống với Rust. Bạn có thể sử dụng cú pháp const Self = @This() để tham chiếu đến lớp của bạn, nhưng tôi đã quyết định không sử dụng nó.
Tiếp theo, tôi đã thêm một hàm vẽ:
zig
pub fn draw(self: Player) void {
const origin = rl.Vector2{
.x = 0,
.y = 0,
};
const rec = rl.Rectangle{
.x = self.x,
.y = self.y,
.height = self.height,
.width = self.width,
};
rl.drawRectanglePro(rec, origin, \@as(f32, @floatFromInt(0)), .white);
}
Ở đây, tôi xác định gốc là một vector hai chiều và cập nhật hình chữ nhật dựa trên các giá trị khởi tạo. Cuối cùng, tôi chỉ cần vẽ hình vuông. rl là một bí danh cho thư viện Raylib.
Cuối cùng, tôi cần gọi một hàm cập nhật:
zig
pub fn update(self: Player) void {
self.x += 1;
}
Khám Phá Vấn Đề
Một trong những điều tôi đã làm để cố gắng căn giữa hình vuông trên màn hình là:
zig
return Player{
.x = rl.getScreenHeight() / 2,
.y = rl.getScreenWidth() / 2,
.height = 10,
.width = 10,
};
Phép toán này có thể không chính xác vì rl.getScreenHeight() trả về một i32, trong khi tất cả các hàm vẽ hình vuông của Raylib lại yêu cầu f32. Vì vậy, tôi cần chuyển đổi chúng:
zig
return Player{
.x = @as(f32, @floatFromInt(rl.getScreenHeight())) / 2,
.y = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2,
.height = 10,
.width = 10,
};
Dù không hoàn hảo do giá trị độ chính xác, nhưng điều này làm cho trình biên dịch hài lòng và tôi dự định sẽ sửa tất cả điều này sau.
Một vấn đề kỳ lạ nhất là hàm cập nhật không thể hoạt động vì nó là một hằng số! Tôi đã nhớ rằng tôi cần phải truyền địa chỉ và cập nhật địa chỉ đó. Zig làm mọi thứ thành hằng số trừ khi bạn chỉ định rõ ràng. Để sửa, tôi đã chỉnh sửa hàm như sau:
zig
pub fn update(self: *Player) void {
self.x += 1;
}
Mã của tôi giờ đây trông như sau:
zig
if (rl.isKeyDown(.d)) {
player.update();
player.draw();
}
rl.beginDrawing();
defer rl.endDrawing();
rl.clearBackground(.dark_gray);
player.draw();
Cuối cùng, tôi đã có một hình vuông có thể di chuyển khi giữ phím 'D'.
Những gì tôi đã học được
Hôm nay, tôi đã học hỏi nhiều hơn về Zig hơn là về phát triển game. Tôi đã dành vài giờ để khám phá và chơi đùa với nó. Ngày mai, tôi sẽ cố gắng vẽ thêm nhiều hình vuông và xem nếu tôi có thể làm cho hình vuông của mình nằm trên chúng. Vì vậy, có vẻ như tôi cần học một số bài học về phát hiện va chạm.
Thực Hành Tốt Nhất
- Nên sử dụng các struct để tổ chức mã cho dễ hiểu.
- Khởi tạo các đối tượng một cách rõ ràng để đảm bảo không có lỗi khi biên dịch.
- Sử dụng các phương thức cho struct để giữ mã ngắn gọn và dễ bảo trì.
Những Cạm Bẫy Thường Gặp
- Nhầm lẫn giữa kiểu dữ liệu, đặc biệt là giữa
i32vàf32khi làm việc với Raylib. - Không cập nhật đúng địa chỉ của struct có thể dẫn đến lỗi không mong muốn.
Mẹo Tối Ưu Hiệu Suất
- Sử dụng tối ưu các biến để giảm thiểu việc sử dụng bộ nhớ.
- Cố gắng hạn chế việc tạo đối tượng mới trong vòng lặp chính của trò chơi.
Xử Lý Sự Cố
Nếu bạn gặp vấn đề với việc hình vuông không di chuyển, hãy kiểm tra lại xem bạn đã cập nhật đúng địa chỉ của struct trong hàm update hay chưa.
Câu Hỏi Thường Gặp (FAQ)
Zig có khó học không?
Zig có thể khó khăn cho những người mới bắt đầu, nhưng với các khái niệm lập trình cơ bản, bạn sẽ nhanh chóng làm quen.
Làm thế nào để tôi có thể cải thiện kỹ năng lập trình game của mình?
Hãy thực hành thường xuyên và tham gia vào các dự án thực tế để nâng cao kỹ năng.
Kết Luận
Qua bài viết này, tôi đã chia sẻ hành trình tìm hiểu về vector vị trí và lập trình với Zig. Nếu bạn cũng đang bắt đầu với Zig, đừng ngần ngại thử sức với các dự án nhỏ và tiếp tục học hỏi. Hãy theo dõi để nhận thêm thông tin và mẹo trong các bài viết tiếp theo!