Chuyển động Liên Tục Với DispatcherTimer - The Complete WPF Tutorial

WPF Tutorial TOC Table of Contents

Download as PDF

PDF Download this entire tutorial as PDF, plus all the code samples, right now!

Chapter/article TOC

  1. Giới thiệu
  2. Tạo khu vực trò chơi
  3. Tạo và di chuyển con rắn
  4. Chuyển động liên tục với DispatcherTimer
  5. Thêm thức ăn cho rắn
  6. Điều khiển Rắn
  7. Phát hiện va chạm
  8. Cải thiện SnakeWPF: Làm cho nó trông giống một trò chơi hơn
  9. Cải thiện SnakeWPF: Thêm danh sách high score
  10. Cải thiện SnakeWPF: Thêm âm thanh
  11. Trò chơi hoàn chỉnh & Lời kết

About WPF

  • WPF là gì?
  • WPF vs. WinForms

Bắt đầu

  • Cài đặt Visual Studio Community
  • Hello, WPF!

XAML

  • XAML là gì?
  • XAML cơ bản
  • Events (sự kiện) trong XAML

Một ứng dụng WPF

  • Giới thiệu về 1 WPF Application
  • The Window
  • Làm việc với App.xaml
  • Tham số Command-line trong WPF
  • Resources
  • Bắt lỗi trong WPF
  • Application Culture / UICulture

Các control cơ bản

  • TextBlock control
  • TextBlock control - Định dạng nội tuyến
  • Label
  • TextBox control
  • Button control
  • CheckBox control
  • RadioButton control
  • PasswordBox control
  • The Image control

Control concepts

  • Chú giải control
  • Trang trí Text trong WPF
  • Thứ tự tab
  • Access Keys (Khóa truy cập)

Panels

  • Mở đầu cho chương WPF panels
  • Control Canvas
  • The WrapPanel control
  • StackPanel
  • Dockpanel
  • Control Grid
  • The Grid - Rows & columns
  • The Grid - Units
  • The Grid - Kéo dài một control sang một ô khác (Span)
  • GridSplitter
  • Ứng dụng grid: Tạo 1 biểu mẩu

UserControls & CustomControls

  • Introduction
  • Tạo và sử dụng một UserControl

Data binding

  • Bắt đầu phần WPF data binding
  • Mở đầu về sự ràng buộc quan hệ dữ liệu trong data binding
  • Sử dụng DataContext
  • Data binding thông qua Code-behind
  • Phương thức UpdateSourceTrigger
  • Đáp ứng các thay đổi trong data binding
  • Chuyển đổi giá trị với IValueConverter
  • Thuộc tính StringFormat
  • Debugging data bindings

Các lệnh Commands

  • Giới thiệu về các lệnh WPF
  • Sử dụng WPF commands
  • Thực hiện một WPF Command tùy chỉnh

Hộp thoại

  • The MessageBox
  • Hộp thoại mở file - OpenFileDialog
  • SaveFileDialog
  • The other dialogs
  • Tạo hộp thoại nhập tùy chỉnh

Điều khiển giao diện chung

  • Điều khiển Menu WPF
  • ContextMenu trong WPF
  • Điều khiển WPF ToolBar
  • The WPF StatusBar control
  • Thanh Ribbon

Các điều khiển Rich Text

  • Tổng quan về các điều khiển WPF Rich Text
  • Control FlowDocumentScrollViewer
  • Điều khiển FlowDocumentPageViewer
  • Điều khiển FlowDocumentReader
  • Creating a FlowDocument from Code-behind
  • Advanced FlowDocument content
  • Điều khiển RichTextBox
  • How-to: Tạo một trình biên tập Rich Text

Misc. controls

  • The Border control
  • The Slider control
  • The ProgressBar control
  • The WebBrowser control
  • The WindowsFormsHost control
  • The GroupBox control
  • The Calendar control
  • Điều khiển DatePicker
  • The Expander control

TabContol

  • Sử dụng WPF TabControl
  • WPF TabControl: Tab positions
  • WPF TabControl: Tạo kiểu cho TabItems

Danh sách control

  • ItemsControl
  • ListBox control
  • Điều khiển ComboBox

ListView

  • Giới thiệu về ListView
  • Một ví dụ ListView đơn giản
  • ListView, data binding and ItemTemplate
  • ListView with a GridView
  • Làm sao để: ListView hiển thị với tên cột được căn trái
  • Phân nhóm trong ListView
  • Sắp xếp trong ListView
  • Làm sao để: sắp xếp cột với ListView
  • ListView filtering

TreeView control

  • Giới thiệu về TreeView
  • Một ví dụ TreeView đơn giản
  • TreeView, data binding and multiple templates
  • TreeView - Selection/Expansion state
  • Lazy loading TreeView items

DataGrid control

  • DataGrid control
  • DataGrid columns
  • DataGrid with row details

Styles

  • Giới thiệu về WPF styles
  • Sử dụng WPF styles
  • Trigger, DataTrigger & EventTrigger
  • WPF MultiTrigger và MultiDataTrigger
  • Trigger animations

Audio & Video

  • Phát âm thanh
  • Phát video
  • Cách thực hiện: Tạo trình phát Audio / Video hoàn chỉnh
  • Tổng hợp giọng nói (làm cho WPF nói)
  • Nhận dạng giọng nói (làm cho WPF lắng nghe)

Misc.

  • DispatcherTimer
  • Đa luồng với BackgroundWorker
  • Hủy bỏ BackgroundWorker

Tạo trò chơi: SnakeWPF

  • Giới thiệu
  • Tạo khu vực trò chơi
  • Tạo và di chuyển con rắn
  • Chuyển động liên tục với DispatcherTimer
  • Thêm thức ăn cho rắn
  • Điều khiển Rắn
  • Phát hiện va chạm
  • Cải thiện SnakeWPF: Làm cho nó trông giống một trò chơi hơn
  • Cải thiện SnakeWPF: Thêm danh sách high score
  • Cải thiện SnakeWPF: Thêm âm thanh
  • Trò chơi hoàn chỉnh & Lời kết
  • WPF
  • ASP.NET MVC
  • ASP.NET WebForms
  • C#
  • CSS3
  • HTML5
  • JavaScript
  • jQuery
  • PHP5

This article has been localized into Vietnamese by the community.

If you are fluent in Vietnamese, then please help us - just point to any untranslated element (highlighted with a yellow left border - remember that images should have their titles translated as well!) inside the article and click the translation button to get started. Or have a look at the current translation status for the Vietnamese language.

If you see a translation that you think looks wrong, then please consult the original article to make sure and then use the vote button to let us know about it.

Metadata

Please help us by translating the following metadata for the article/chapter, if they are not already translated.

If you are not satisfied with the translation of a specific metadata item, you may vote it down - when it reaches a certain negative threshold, it will be removed. Please only submit an altered translation of a metadata item if you have good reasons to do so!

Please login to translate metadata! Already logged in? Please try reloading the page!
  • More info...
  • Looking for the original article in English?
Tạo trò chơi: SnakeWPF: Chapter introduction:

In this article series, we're building a complete Snake game from scratch. It makes sense to start with the Introduction and then work your way through the articles one by one, to get the full understanding.

If you want to get the complete source code for the game at once, to get started modifying and learning from it right now, consider downloading all our samples!

Chuyển động liên tục với DispatcherTimer

Trong các bài viết trước, chúng tôi đã tạo ra một khu vực trò chơi đẹp mắt cho Rắn của chúng tôi và sau đó chúng tôi đã thêm code để thực hiện việc tạo và di chuyển thực tế của con rắn. Tuy nhiên, như đã đề cập, mã chuyển động không phải là thứ nên được gọi chỉ một lần - thay vào đó, nó nên được gọi đi gọi lại, để giữ cho con rắn di chuyển chừng nào trò chơi đang chạy. Nói cách khác, chúng ta sẽ cần một Timer.

Nói chung, trong lập trình, Timer thường là một cơ chế cho phép lặp lại một tác vụ, dựa trên một khoảng thời gian. Nói cách khác, mỗi lần bộ đếm thời gian "tích tắc", một đoạn mã được thực thi và bộ đếm thời gian đánh dấu dựa trên khoảng thời gian xác định. Đây chính xác là những gì chúng ta cần để giữ cho con rắn của chúng ta di chuyển, vì vậy chúng ta sẽ thêm một DispatcherTimer vào Window của chúng ta:

public partial class SnakeWPFSample : Window { private System.Windows.Threading.DispatcherTimer gameTickTimer = new System.Windows.Threading.DispatcherTimer(); ....

Với vị trí đó, bây giờ chúng ta cần đăng ký vào một sự kiện duy nhấtt: Sự kiện Tick. Chúng tôi sẽ làm điều đó trong hàm tạo của Window:

public SnakeWPFSample() { InitializeComponent(); gameTickTimer.Tick += GameTickTimer_Tick; }

Và đây là việc thực hiện sự kiện:

private void GameTickTimer_Tick(object sender, EventArgs e) { MoveSnake(); }

Vì vậy, mỗi khi đồng hồ bấm giờ, sự kiện Tick được gọi, đổi lại gọi phương thức MoveSnake() mà chúng ta đã triển khai trước đó. Để cuối cùng thấy kết quả của tất cả lao động vất vả của chúng tôi và có một con rắn di chuyển trực quan, về cơ bản chúng tôi chỉ cần tạo ra các bộ phận rắn ban đầu và sau đó bắt đầu hẹn giờ. Chúng tôi sẽ tạo một phương thức gọi là StartNewGame(), chúng tôi sẽ sử dụng để bắt đầu cả trò chơi đầu tiên cũng như bất kỳ số lượng trò chơi mới bổ sung nào khi người chơi chết. Mặc dù vậy, chúng ta sẽ bắt đầu với một phiên bản rất cơ bản của nó, và sau đó tôi sẽ mở rộng nó với nhiều chức năng hơn khi chúng ta di chuyển - bây giờ, hãy để con rắn này di chuyển!

Bước đầu tiên là thêm một bộ hằng số khác, chúng ta sẽ sử dụng để bắt đầu trò chơi mới:

public partial class SnakeWPFSample : Window { const int SnakeSquareSize = 20; const int SnakeStartLength = 3; const int SnakeStartSpeed = 400; const int SnakeSpeedThreshold = 100; ......

Chỉ có ba hằng số đầu tiên được sử dụng tại thời điểm này, để kiểm soát kích thước, chiều dài và tốc độ bắt đầu của Rắn. Chúng ta sẽ sử dụng SnakeSpeedThreshold sau, nhưng bây giờ, hãy thêm một cách thực hiện đơn giản phương thức StartNewGame() như đã hứa:

private void StartNewGame() { snakeLength = SnakeStartLength; snakeDirection = SnakeDirection.Right; snakeParts.Add(new SnakePart() { Position = new Point(SnakeSquareSize * 5, SnakeSquareSize * 5) }); gameTickTimer.Interval = TimeSpan.FromMilliseconds(SnakeStartSpeed); // Draw the snake DrawSnake(); // Go! gameTickTimer.IsEnabled = true; }

Chúng tôi bắt đầu bằng cách đặt snakeLengthsnakeDirection dựa trên các giá trị ban đầu. Sau đó, chúng tôi thêm một phần duy nhất vào Danh sách snakeParts(nhiều hơn về sau), tạo cho nó một vị trí bắt đầu tốt để di chuyển sang phải - một lần nữa chúng ta sẽ sử dụng hằng số SnakeSquareSize để giúp tính toán vị trí thích hợp. Với vị trí đó, chúng ta có thể vẽ con rắn bằng cách gọi phương thức DrawSnake() và sau đó kích hoạt bộ đếm thời gian, về cơ bản sẽ bắt đầu chuyển động của con rắn.

Bây giờ chúng ta cuối cùng đã đến lúc chúng ta gần như có thể ngồi lại và thưởng thức phiên bản đầu tiên của một thứ thực sự trông giống như một trò chơi - thực tế, tất cả những gì chúng ta phải làm bây giờ là gọi phương thức StartNewGame(). Tất nhiên điều này nên được thực hiện khi người dùng đã sẵn sàng, nhưng bây giờ, để kiểm tra xem mọi thứ có hoạt động không, chúng tôi sẽ đơn giản thực hiện ngay khi mọi thứ khác được khởi chạy - một lần nữa chúng tôi sẽ dựa vào sự kiện ContentRendered của Window, mà chúng tôi đã thêm vào một trong những bài viết đầu tiên. Chỉ cần thêm một cuộc gọi vào phương thức StartNewGame() của chúng tôi và cuối cùng chúng tôi đã sẵn sàng để biên dịch và chạy:

private void Window_ContentRendered(object sender, EventArgs e) { DrawGameArea(); StartNewGame(); }

Nếu bạn đã làm mọi thứ như mô tả, bây giờ bạn sẽ có thể bắt đầu trò chơi và thấy con rắn được tạo ra và ngay lập tức bắt đầu di chuyển:

Chú ý cách con rắn xuất hiện từ không có gì, như một hình vuông duy nhất, và sau đó phát triển đến chiều dài ba hình vuông. Điều đó xảy ra bởi vì chúng tôi chỉ thêm một phần vào danh sách snakeParts, nhưng mỗi lần phương thức MoveSnake() được gọi bởi timer, một phần mới được thêm vào (để làm cho nó phát triển), trong khi chỉ xóa phần đuôi nếu độ dài hiện tại là sắp vượt quá chiều dài mong muốn của con rắn, bắt đầu từ 3 (được quyết định bởi hằng số SnakeStartLength).

Tổng kết

Bây giờ chúng tôi có một con rắn di chuyển, đó là thực sự tuyệt vời! Nhưng như bạn có thể thấy từ hình ảnh hoạt hình ở trên, vẫn còn nhiều việc phải làm - không có thức ăn cho rắn ăn, và khi con rắn đập vào tường, không có gì xảy ra. Chúng tôi sẽ làm việc trên các khía cạnh này trong các bài viết tiếp theo.

Creating & moving the Snake Previous Adding food for the Snake Next This article has been fully translated into the following languages:
  • Chinese
  • Czech
  • French
  • German
  • Italian
  • Polish
  • Portuguese
  • Russian
  • Spanish
  • Vietnamese
Is your preferred language not on the list? Click here to help us translate this article into your language!

Từ khóa » Bộ đếm Thời Gian Trong C#