Gosu - Thư viện game 2D cho Ruby - Phần 3

Trong bài viết này mình sẽ giới thiệu về chức năng di chuyển nhân vật bằng phím 😄 Mình thử 1 ví dụ di chuyển nhân vật bằng 4 phím điều hướng và thoát bằng phím Esc.

require 'gosu'

class GameWindow < Gosu::Window

    def initialize width, height, fullscreen
        super(width, height, fullscreen)
        self.caption = "Hello" #set title của game_window 
        @sprite = Gosu::Image.new(self, "Sprite.gif", false)
        
        @x = 20
        @y = 30
    end
    
    def update
        @x -= 1 if button_down?(Gosu::KbLeft)
        @x += 1 if button_down?(Gosu::KbRight)
        @y -= 1 if button_down?(Gosu::KbUp)
        @y += 1 if button_down?(Gosu::KbDown)
    end

    def button_down(id)
        close if id == Gosu::KbEscape
    end

    def draw
        @sprite.draw(@x, @y, 0)
    end
end
 
game_window = GameWindow.new(800, 600, false)
game_window.show

Trong đoạn code dưới, khi ấn 4 phím điều hướng sẽ tương đương với sự thay đổi toạ độ @x, @y.

    def update
        @x -= 1 if button_down?(Gosu::KbLeft)
        @x += 1 if button_down?(Gosu::KbRight)
        @y -= 1 if button_down?(Gosu::KbUp)
        @y += 1 if button_down?(Gosu::KbDown)
    end

Và cửa sổ sẽ được tắt nếu ấn phím Escape.

    def button_down(id)
        close if id == Gosu::KbEscape
    end

Nhưng về cơ bản các bạn xem hình bên dưới để hiểu rõ hơn về vòng lặp nhé.

Nhưng các bạn chú ý function draw, nó được tạo liên tục kể cả bạn không thực hiện thao tác gì cả, vì vậy nó sẽ làm hệ thống chậm đi khá nhiều với game nặng. Để ngăn chặn việc này, Gosu cung cấp hàm needs_redraw? Và bây giờ các bạn thử thêm một đoạn code như dưới để hiểu thêm về draw nhé.

  1. Trường hợp không sử dụng needs_draw?
require 'gosu'

class GameWindow < Gosu::Window

    def initialize width, height, fullscreen
        super(width, height, fullscreen)
        self.caption = "Hello" #set title của game_window 
        @sprite = Gosu::Image.new(self, "Sprite.gif", false)
        
        @x = 20
        @y = 30
        @draws = 0
    end
    
    def update
        @x -= 1 if button_down?(Gosu::KbLeft)
        @x += 1 if button_down?(Gosu::KbRight)
        @y -= 1 if button_down?(Gosu::KbUp)
        @y += 1 if button_down?(Gosu::KbDown)
    end

    def button_down(id)
        close if id == Gosu::KbEscape
    end

    def draw
        @draws += 1
        @sprite.draw(@x, @y, 0)
        @message = Gosu::Image.from_text(self,@draws, Gosu.default_font_name, 30)
        @message.draw(@x, @y, 1)
    end
end

game_window = GameWindow.new(800, 600, false)
game_window.show

Trong đoạn code trên có thêm 1 biến @draws = 0 được tạo. Đưa biến này vào phương thức draw để xem sự thay đổi. Vì gosu chỉ cho hiển thị ảnh nên mình phải chuyển @draws bằng function Image trong gosu như sau.

@message = Gosu::Image.from_text(self,@draws, Gosu.default_font_name, 30)

Chạy đoạn code ví dụ trên bạn sẽ thấy biến @draws không ngừng tăng bên cạnh nhân vật như hình dưới. AgeqzS

Để ngăn việc draw liên tục như vậy thì mình sử dụng needs_draw? như sau.

require 'gosu'

class GameWindow < Gosu::Window

    def initialize width, height, fullscreen
        super(width, height, fullscreen)
        self.caption = "Hello" #set title của game_window 
        @sprite = Gosu::Image.new(self, "Sprite.gif", false)
        
        @x = 20
        @y = 30
        @draws = 0
        @buttons_down = 0
    end
    
    def update
        @x -= 1 if button_down?(Gosu::KbLeft)
        @x += 1 if button_down?(Gosu::KbRight)
        @y -= 1 if button_down?(Gosu::KbUp)
        @y += 1 if button_down?(Gosu::KbDown)
    end

    def button_down(id)
        close if id == Gosu::KbEscape
        @buttons_down += 1
    end

    def button_up(id)
        @buttons_down -= 1
    end

    def needs_redraw?
        @draws == 0 || @buttons_down > 0 
    end

    def draw
        @draws += 1
        @sprite.draw(@x, @y, 0)
        @message = Gosu::Image.from_text(self, @draws, Gosu.default_font_name, 30)
        @message.draw(@x, @y, 1)
    end
end

game_window = GameWindow.new(800, 600, false)
game_window.show

Phương thức needs_redraw? được gọi ra khi @draws==0 hoặc khi có 1 button được ấn (@buttons_down >0) Phải tạo phương thức button_up để gosu hiểu được bạn không giữ 1 nút liên tục.

Các bạn thử làm xem kết quả thế nào nhé. Chúc các bạn vui vẻ 😄


All Rights Reserved