3-10 Xử lý sự kiện và chuột

3-10 Xử lý sự kiện và chuột

Về cách sử dụng bàn phím thì tôi đã giới thiệu ở những phần trước, nhưng trong khi làm game thì chắc chắn sẽ có trường hợp ta muốn dùng chuột. Phần sẽ sẽ giới thiệu sử dụng xử lý sự kiện để đưa thao tác sử dụng chuột vào trong game

Về xử lý sự kiện

Sử lý sự kiện là một chuỗi những hành động khá công phu. Có thể sẽ xảy ra những lỗi bỏ qua dòng chảy của chương trình. Chương trình tiếp theo sẽ lấy việc bấm chuột như một sự kiện và chữ sẽ hiện ra.

mouse00.rb

require 'mygame/boot'
add_event(:mouse_button_down) {puts"DOWN"}
main_loop do
# Không làm gì cả
end

Chương trình này có nghĩa là cứ khi nút của chuột được nhấn thì trên màn hình Command Promt sẽ hiện lên "DOWN". Tức là ngay khoảnh khắc nút chuột được bấm thì trên cụm tiếp theo sẽ được thực hành.

puts "DOWN"

Tuy nhiên cứ mỗi khi nút chuột được ấn thì bao nhiêu lần cũng thế, DOWN sẽ hiện ra. Lệnh [add_event] nhận loại sự kiện tại argument. Rồi tiếp theo nếu chúng ta viết một ngoặc thì ngay sau khi đưa loại argument thì nội dung trong ngoặc sẽ được thực hiện. Những lệnh sự kiện mà chúng ta có thể đưa cho [add_event] sẽ được liệt kê bằng bảng dưới đây.

Bảng 3-2 List những loại sự kiện
Nhập Nội dung sự kiện
:mouse_button_down Sự kiện xảy ra khi nút chuột được nhấn
:mouse_button_up Sự kiện phát sinh khi nút chuột được nhả ra
:mouse_motion Sự kiện phát sinh khi di chuyển chuột
:key_down Sự kiện phát sinh khi nhấn phím trên bàn phím
:key_up Sự kiên phát sinh khi nhả phím trên bàn phím

Ví dụ chúng ta muốn xử lý sự kiện phát sinh khi chuột di chuyển trong màn hình thì sẽ chạy chương trình dưới đây.

require 'mygame/boot'
add_event (:mouse_motion){puts "MOVED"}

Như vậy trong trường hợp load 'mygame/load' thì nếu không viết main_loop thì [main_loop] sẽ tự động được thực hiện.

Kiểm tra nút đã được nhấn

Nếu sử dụng loại sự kiện [:mouse_button_down] thì chúng ta có thể hiểu rằng có thể tìm kiếm đưa ra nút chuột đã được nhấn. Tuy nhiên, nếu với lệnh [:mouse_button_down] thì chúng sẽ phản ứng với tất cả nút chuột được nhấn. Chương trình dưới đây sẽ hiển thị nút chuột được nhấn khi chuột được nhấn.

mouse02.rb

require 'mygame/boot'
add_event (:mouse_button_down) {|e| puts e.button}

Hãy nhìn câu lệnh đầu tiên trong block

{|e| puts e.button}

Trong block hiển thị một kí hiệu mà chúng ta chưa hề biết

|e|

[e] ở đây chính là biến số. Trong biến số này có chưa thông tin của sự kiện. Đối với e thì lệnh sẽ được thực hiện. Chúng ta có thể có được số của nút trên chuột đã được nhấn.

puts e.button # => hiện số thứ tự nút đã được nhấn.

Các bạn hãy chú ý biến số [e] chỉ có thể dùng trong block này. Ngoài block này thì khi chúng ta sử dụng biến số [e] thì chương trình sẽ trở thành error. Trong 3 trường hợp của chuột thì lệnh [button] sẽ trả lại kết quả sau.

Nút Giá trị trả lại
Trái 1
Giữa 2
Phải 3

mouse03.rb

require 'maygame/boot'
add_event (:mouse_button_down) {|e|
  puts "Nút trái đã được nhấn" if e.button == 1
  puts "Nút giữa đã được nhấn" if e.button == 2
  puts "Nút phải đã được nhấn" if e.button ==3
}

Khi chuột được nhấn thì thông qua nút chuột được nhấn mà dòng tin nhắn sẽ được hiện ra.

Kiểm tra vị trí con trỏ chuột

Chúng ta cũng có thể có được vị trí con trỏ chuột trên màn hình. Chương trình dưới đây, mỗi khi chuột được nhấn thì trên màn hình máy tính sẽ hiện tọa độ con trỏ chuột.

require 'mygame/boot'
add_event (:mouse_button_down) {|e| puts "x:#{e.x} y:#{e.y}"}

Trong obeject sự kiện thì lệnh [x] và lệnh [y] khi được chạy sẽ hiện lên tọa độ của con trở chuột.

puts e.x # tọa độ x của con trỏ chuột
puts e.y # tọa độ y của con trỏ chuột

Mặt khách, nếu dùng lệnh [state] thì chúng ta có thể biến được trạng thái của con trỏ chuột.

Biểu thị ình ảnh trên vị trí của con trở chuột

Phần này sẽ giới thiệu phương pháp di chuyển vị trí của hình ảnh kết hợp với vị trí của con trỏ chuột. Lần này chỉ định loại sự kiện sẽ là [:mouse_motion]. [Mouse_motion] chính là sự kiện xảy ra khi con chuột được di chuyển.

mouse04.rb

require 'mygame/boot'
img = Image.new("sample.bmp")
add_event (:mouse_motion){|e|
  img.x = e.x
  img.y = e.y
}
main_loop do
img.render
end

Chúng ta lập obejct hình ảnh, rồi trong loop thì ra lệnh hiển thị hình ảnh. Tiếp theo khi sự kiện xảy ra thì tọa độ của hình ảnh có trong block sẽ được thay đổi. Tọa độ của con trỏ chuột sẽ biểu thị cho tọa độ của hình ảnh. Chương trình trên thì góc trên bên trái của hình ảnh sẽ vào vị trí con trỏ chuột khi con chuột được nhấn. Để tọa độ con trỏ chuột vào chính giữa bức ảnh thì chúng ta làm như sau.

mouse05.rb

require 'mygame/boot'
img = Image.new("sample.bmp")
add_event (:mouse_motion) {|e|
  img.x = e.x - img.w/2
  img.y = e.y - img.h/2
}
main_loop do
  img.render
end
Hình 3-27 Tọa độ của con trỏ tại vị trí chính giữa hình ảnh

15.png

Trong trường hợp này chúng ta lấy tọa độ của con chuột trừ đi một nửa kích thước của hình ảnh. Như vậy thì vị trí của con chuột sẽ kết hợp được với trung tâm của bức ảnh.

Hiển thị Font và chuột

Đây là chương trình ví dụ hiển thị trên màn hình thông tin sự kiện của con chuột.

require 'mygame/boot'
fnt = Font.new("UP")
fnt_pos = Font.new("POS", :x => 0, :y => 20)
add_event(:mouse_button_up) {fnt.string = "UP"}
add_event(:mouse_button_down){fnt.string = "DOWN"}
add_event(:mouse_motion) {|e| fnt_pos.string = "POS x:#{e.x} y:#{e.y}"}
main_loop do
  fnt.render
  fnt_pos.render
end

Khi sự kiện trên con chuột được thực hiện, đối với font object thì lệnh [string=] được chạy và dãy chữ mới sẽ được vẽ ra.

Dùng biến số bên trong block

Nếu muốn dùng biến số bên trong block ở bên ngoài block thì chúng ta cần có vài chú ý. Trong trường hợp này nhất định chúng ta tạo nội dung đó ngay trước block. Chương trình tiếp theo đây, nội dung của [a] được hiển thị trong loop, cứ mỗi khi nút chuột được nhấn thì a lại được cộng thêm giá trị.

require 'mygame/boot'
a = 0
add_event(:mouse_button_down) {a += 1}
main_loop do
  puts a
end

Trong block có sử dụng a nhưng ngay trước block chúng ta đã nêu ra giá tị a nên chương trình được chạy đúng. Nếu chúng ta nêu ra biến số a trong block trước khi tạo biến a thì khi sự kiện hình thành, mỗi khi nội dung trong block được chạy thì sẽ xảy ra lỗi.

require 'mygame/boot'
add_event(:mouse_button_down) {a+=1}
a = 0
main_loop do
  puts a
end

Khi phân vân về giới hạn sử dụng của biến số có trong block thì các bạn hãy nhớ ra ví dụ điển hình này.