Làm thế nào để buộc một phát hành viên đạn với một hình ảnh động bắn


15

Hãy nói rằng bạn có một hình ảnh động mà bạn muốn xảy ra khi bắn một viên đạn. Làm thế nào bạn có thể làm cho viên đạn xuất hiện ở phần cuối của hình ảnh động. Điều duy nhất tôi có thể tìm ra là biết độ dài thời gian của hình ảnh động và trì hoãn cài đặt vị trí đạn và đặt nó hoạt động cho đến khi khoảng thời gian đó trôi qua. Tôi chỉ tự hỏi nếu đây là cách tiếp cận tốt nhất, làm thế nào để mọi người khác xử lý việc này?

EDIT: Tôi nghĩ rằng tôi đang gặp khó khăn khi diễn đạt câu hỏi đúng.

Câu hỏi của tôi


Cảm ơn! Nhiều ý tưởng hay từ tất cả các bạn, tôi thích ý tưởng sử dụng một cuộc gọi lại. Tôi nghĩ rằng tôi sẽ thử và thực hiện điều đó, tôi thực sự không muốn dựa vào theo dõi thời gian.
tp0w3rn

Câu trả lời:


8

Về cơ bản, bạn đang đi đúng hướng - bạn cần biết một hoạt hình kéo dài bao lâu để thực hiện loại việc này. Ảnh động không chỉ là một bộ sưu tập các khung, có tất cả các loại thông tin khác xung quanh chúng mà bạn cần. Ví dụ: có bao nhiêu khung hình, vòng lặp hoạt hình, nó phát lại nhanh như thế nào (ví dụ 10 khung hình động mỗi giây hoặc 25, hoặc 60?). Mỗi hình ảnh động có thể được định nghĩa theo một vài phần dữ liệu, mà một số mã hoạt hình tổng quát có thể nhìn và phát lại. Bạn nên gói gọn phần hoạt hình trong một đoạn mã riêng, không biết gì ngoại trừ các định nghĩa hoạt hình này và cách hiển thị các khung hình ảnh riêng lẻ. Đó là, có một đối tượng hoạt hình mà bạn có thể tải, bắt đầu chơi, dừng phát và yêu cầu kết xuất tại một vị trí cụ thể trên màn hình.

Một cách tiếp cận linh hoạt là sử dụng một loại định nghĩa hoạt hình để gói gọn loại thông tin này. Vì vậy, thay vì chỉ nói "hoạt hình X là tất cả các khung hình này, chỉ cần phát qua chúng", bạn sẽ nhận được một cái gì đó phức tạp hơn một chút.

Ví dụ: với một số loại định dạng dữ liệu giả định

hình ảnh động =
{
  {name = "walk", files = "walk * .png", frameCount = "12", loop = "true"},
  {name = "fire" files = "fire * .png" frameCount = "6",
       sự kiện = {
           {name = "đạnLeavesGun", frame = "4", param1 = "43", param2 = "30"}
       }
  }
}

Vì vậy, mã của bạn nói một cái gì đó như:

currentAnimation = animations.Get("fire");
currentAnimation.Play();

Cách bạn phát hiện các sự kiện có thể bằng mã hoạt hình gọi lại cho bạn (nghĩa là khi phát hiện sự kiện mới vì hoạt hình đã phát đến một khung nhất định, nó gọi mã trò chơi của bạn để thông báo về sự kiện mới) hoặc bằng cách bỏ phiếu hoạt hình như vậy:

List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
    if (event.name == "bulletLeavesGun")
    {
        Vector2 bulletPosition = new Vector2(event.param1, event.param2);
        Vector2 actualBulletPosition = new Vector2(
                 character.x + bulletPosition.x, 
                 character.y + bulletPosition.y);
        CreateBulletAt(actualBulletPosition);
    }
}

Điểm cần lưu ý:

  • Mã hoạt hình nên tồn tại tách biệt với mã trò chơi. Bạn thực sự không muốn mã trò chơi của mình quá chặt với các đai ốc và bu lông phát lại hoạt hình.
  • Mã hoạt hình biết có lặp hay không dựa trên định nghĩa hoạt hình
  • Mã hoạt hình biết khi nào hoạt hình được hoàn thành và có thể gọi lại cho một số mã khác để nói 'này, hoạt hình được gọi là "lửa" vừa hoàn thành, bạn muốn làm gì bây giờ?'
  • Mã hoạt hình không biết gì về các sự kiện ngoài việc chúng có tên và một số dữ liệu tùy ý liên quan đến chúng (param1 và param2)
  • Mã hoạt hình biết khung hình hiện tại của nó là gì và khi nó chuyển sang khung mới, nó có thể kiểm tra và nói 'ồ, bây giờ tôi đang ở khung 4, điều đó có nghĩa là sự kiện này có tên là "lửa" vừa xảy ra, hãy thêm nó vào danh sách các sự kiện gần đây của tôi để tôi có thể nói với bất kỳ ai hỏi về nó '.

Nếu bạn không cần việc bắn đạn xảy ra trong hoạt hình, nhưng chỉ khi nó kết thúc, bạn có thể thoát khỏi một hệ thống ít phức tạp hơn nhiều mà không có khái niệm về các sự kiện. Nhưng bạn vẫn muốn có một hệ thống mà hoạt hình tự phát lại, biết chúng dài bao nhiêu và có thể gọi lại mã trò chơi khi hoạt ảnh hoàn tất.


Tôi không đồng ý với việc giữ hình ảnh động nhận thức logic (trên khung 4 bây giờ, điều đó có nghĩa là sự kiện này được gọi là "lửa" vừa xảy ra). Ảnh động nên bị mù và câm. Tôi đã phải thực hiện một số logic bên máy chủ và xé hình ảnh động và giao diện người dùng ra khỏi trò chơi là điều tôi không muốn làm lại. Tôi thực sự khuyên bạn nên sử dụng các hình ảnh động rất ngắn và được phân đoạn, chơi chúng song song với logic để cho phép logic kích hoạt các chuỗi hoạt hình ở tốc độ được xác định bởi các logic. Không bao giờ có kiểm tra logic cho tình trạng của một hình ảnh động.
Coyote

Chia hoạt hình thành nhiều phần có vẻ không cần thiết. Tôi đồng ý không bỏ phiếu cho tình trạng của hoạt hình, nhưng điều đó vẫn để lại khuyến nghị đầu tiên của anh ấy. Tôi không biết liệu anh ta có nghĩa là một hệ thống sự kiện riêng biệt để tách mã hoạt hình khỏi phần còn lại của trò chơi (mẫu quan sát viên?) Nhưng đó là cách tôi làm điều đó. Không phải là "logic" như bạn đặt nó nên biết về mã hoạt hình, hoặc ngược lại.
jhocking

@Coyote Tôi muốn nói rằng bạn đang trộn hai thứ riêng biệt. Đúng, logic phía máy chủ phải luôn độc lập với hình ảnh (vì bạn không muốn chạy hệ thống hoạt hình chỉ để tìm ra khi nào một viên đạn được bắn), nhưng điều đó sẽ không giúp bạn xây dựng một hệ thống hoạt hình trên máy khách . Trên máy khách, bạn hoàn toàn không muốn hình ảnh bị trượt một cách vô thức vào máy chủ, bởi vì điều đó sẽ rất tệ - những viên đạn xuất hiện vào những thời điểm kỳ lạ và không đồng bộ với nhân vật bởi vì có sự chênh lệch giữa trò chơi và máy chủ . Không có lý do gì bạn không thể có cả hai (tiếp ...)
MrCranky

@Coyote (tiếp ...), lối chơi có thể được điều khiển bởi máy chủ tách rời khỏi hình ảnh. Vì vậy, viên đạn được bắn vào thời điểm X trên máy chủ và khách hàng phản ánh hành động đó bằng cách bắt đầu phát hoạt hình lửa ngay lập tức, với viên đạn bắn hình ảnh bị trễ một vài khung hình phía sau mô phỏng trò chơi viên đạn. Tất cả các loại thỏa hiệp cần phải được thực hiện giữa độ trung thực hình ảnh và mô phỏng trò chơi, vì vậy để nói rằng "hoạt hình nên bị mù và câm" chỉ đơn giản là ngây thơ. Đôi khi các sự kiện hoàn toàn cần được gắn với các khung hình động, bởi vì không có phương pháp nào khác sẽ làm cho chúng trông hoặc âm thanh đúng.
MrCranky

@Coyote Thực sự bây giờ tôi nghĩ về nó, viên đạn là một ví dụ khủng khiếp cho điều này, chủ yếu là vì câu trả lời từ thedaian dưới đây. Bắn nên xảy ra ngay lập tức. Một ví dụ tốt hơn sẽ là một VFX bụi bắn khi một nhân vật hạ cánh - máy chủ và máy khách sẽ đồng bộ hóa khi nhân vật bắt đầu nhảy, nhưng màn hình hiển thị được để lại cho máy khách. Và khi hình ảnh động chạm vào khung bên phải nơi chân chạm đất, sự kiện VFX sẽ kích hoạt. Tương tự, các sự kiện là cần thiết nếu cần đưa ra quyết định trên một khung hoạt hình nhất định xem có phân nhánh sang hoạt hình khác hay không.
MrCranky

3

Theo một cách nào đó, bạn sẽ phải đợi cho đến khi hoạt hình hoàn thành và tạo viên đạn vào thời điểm đó.

Chỉ cần đặt hẹn giờ sẽ hoạt động, nếu bạn chắc chắn rằng tốc độ hoạt hình của bạn đã được cố định. Là một biến thể nhỏ, bạn có thể có mã bên trong viên đạn khiến nó chờ đợi vô hình trong giây lát trước khi xuất hiện và di chuyển.

Tùy thuộc vào nền tảng phát triển của bạn, bạn có thể có một số loại chức năng cập nhật hoạt hình hoặc gọi lại sẽ cho phép bạn trả lời chính xác thời điểm hoạt hình đạt đến điểm mong muốn. Đây là cách tôi làm điều đó với Flixel chẳng hạn.


1
addAnimationCallbackPhương pháp của Flixel có thể được sử dụng trên thực thể bắn. Trong chức năng gọi lại, bạn có thể xem khung hình hiện tại của hoạt hình bắn có phải là khung sẽ tạo ra một thực thể dấu đầu dòng hay không. Nếu có thì bạn có thể thêm một viên đạn trên màn hình.
Người mù tuyết

2

Trả lời thẳng: Giả sử bạn có một hình ảnh động mà bạn muốn phát khi người chơi nhấn nút 'bắn', và sau đó có một viên đạn phát ra sau khi chơi xong. Tốt nhất, bạn nên tránh mã hóa cứng thời gian hoạt hình và bắn đạn khi hoạt ảnh hoàn thành (sử dụng chức năng gọi lại hoặc một cái gì đó, tùy thuộc vào nền tảng của bạn). Tôi không thể nghĩ ra bất kỳ phương pháp nào khác để làm điều này không quá phức tạp.

Câu trả lời của Thiết kế trò chơi thay thế: Trừ khi có lý do thực sự, thực sự tốt để làm như vậy, tôi sẽ tránh việc trì hoãn nhấn nút 'bắn' và xuất hiện viên đạn. Trừ khi hoạt hình thực sự rất ngắn (một hoặc hai khung hình, tối đa, về cơ bản là đèn flash mõm), nó sẽ làm cho phản ứng của nút lửa cảm thấy chậm, và nó sẽ gây khó chịu cho người chơi thông thường. Ngay cả khi bạn quyết định sử dụng hoạt hình trước khi đạn xuất hiện (game nhập vai và game chiến thuật theo lượt sẽ là lý do có thể chấp nhận để làm điều này), tôi vẫn nghĩ đến việc bao gồm tùy chọn "tắt hoạt hình" ở đâu đó, để cho phép Trò chơi để di chuyển nhanh hơn nếu người chơi muốn.


Vâng, đừng khiến ngọn lửa phản ứng chậm. Đây giống như vấn đề chung với nhảy; Các nhà làm phim hoạt hình tạo ra một cơn gió lớn, nhưng người chơi mong đợi được phát sóng ngay khi họ nhấn nút.
jhocking

2

Như MrCranky nói; giữ cho hình ảnh động và logic tách biệt.

Nhưng quan trọng nhất, logic phải vẫn là phần chính.

  • Khi nhấn nút bắn, bạn nên kích hoạt vẽ " hành động " ở trạng thái nhân vật (logic).
  • Hành động này sẽ kích hoạt hoạt hình vẽ với tất cả các tham số (thời gian tồn tại, v.v.).
  • Khi hành động bốc thăm kết thúc, bạn có thể kích hoạt hành động bắn (có thể bắn một lần hoặc nhiều hơn tùy thuộc vào vũ khí)
  • Hành động này có thể tạo ra đạn và kích hoạt hoạt hình lửa .

Hãy nhớ rằng việc kiểm soát UI từ logic là cách duy nhất để đảm bảo bạn sẽ có thể giữ, sử dụng lại và chia sẻ logic của mình sau này (trình kết xuất mới, trò chơi mới, phiên bản máy chủ mà không cần trình kết xuất ...)


1

Trước hết, tôi sẽ sử dụng một hệ thống sự kiện (mẫu quan sát viên?) Để tách các đoạn mã. Điều này không chỉ dành cho hoạt hình, nhưng chắc chắn áp dụng ở đó. Sau đó, mã hoạt hình có thể chỉ cần nói ClarkEvent (sự kiện) và một số phần khác của mã lắng nghe sự kiện đó, mà không cần một phần nào của mã cần biết về nhau.

Bây giờ mã hoạt hình cần thực sự có một tham chiếu đến bộ điều phối sự kiện (dễ dàng thực hiện với phép nội xạ phụ thuộc) và bạn cần có một số XML hoặc JSON thực sự xác định hoạt ảnh của bạn. Cái gì đó như:

{
  animation: {
    name: shoot,
    length: 12,
    spritesheet: shoot.png
    event: {
      frame: 4,
      name: bulletLeavesGun,
    },
  },
}

Đọc dữ liệu khi tải hình ảnh động và có mã hoạt hình gửi sự kiện khi nó ở trên khung đó trong khi phát lại.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.