2010-03-11 40 views
6

Tôi mới dùng iPhone dev, nhưng cố gắng xây dựng trò chơi 2D. Tôi đã theo dõi một cuốn sách, nhưng vòng lặp trò chơi mà nó tạo ra về cơ bản đã nói:Đây có phải là cách hay để tạo vòng lặp trò chơi cho trò chơi trên iPhone không?

function gameLoop 
    update() 
    render() 
    sleep(1/30th second) 
    gameLoop 

Lý do là điều này sẽ chạy ở tốc độ 30 khung hình/giây. Tuy nhiên, điều này có vẻ hơi tinh thần, bởi vì nếu khung hình của tôi mất 1/30 giây, sau đó nó sẽ chạy ở tốc độ 15 khung hình/giây (vì nó sẽ dành nhiều thời gian ngủ khi cập nhật).

Vì vậy, tôi đã tìm hiểu và tìm thấy lớp CADisplayLink sẽ đồng bộ hóa các cuộc gọi đến chức năng gameLoop của tôi với tốc độ làm mới (hoặc một phần nhỏ của nó). Tôi không thể tìm thấy nhiều mẫu của nó, vì vậy tôi gửi bài ở đây để xem xét lại mã :-) Có vẻ như nó hoạt động như mong đợi, và nó bao gồm việc chuyển thời gian trôi qua (frame) vào phương thức Update để logic của tôi có thể được framerate -independant (tuy nhiên tôi thực sự không thể tìm thấy trong tài liệu CADisplayLink sẽ làm gì nếu khung của tôi mất nhiều thời gian hơn để chạy - Tôi hy vọng nó chỉ làm hết sức mình để bắt kịp, và không sụp đổ!).

// 
// GameAppDelegate.m 
// 
// Created by Danny Tuppeny on 10/03/2010. 
// Copyright Danny Tuppeny 2010. All rights reserved. 
// 

#import "GameAppDelegate.h" 
#import "GameViewController.h" 
#import "GameStates/gsSplash.h" 

@implementation GameAppDelegate 

@synthesize window; 
@synthesize viewController; 

- (void) applicationDidFinishLaunching:(UIApplication *)application 
{ 
// Create an instance of the first GameState (Splash Screen) 
[self doStateChange:[gsSplash class]]; 

// Set up the game loop 
displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(gameLoop)]; 
[displayLink setFrameInterval:2]; 
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 
} 

- (void) gameLoop 
{ 
// Calculate how long has passed since the previous frame 
CFTimeInterval currentFrameTime = [displayLink timestamp]; 
CFTimeInterval elapsed = 0; 

// For the first frame, we want to pass 0 (since we haven't elapsed any time), so only 
// calculate this in the case where we're not the first frame 
if (lastFrameTime != 0) 
{ 
    elapsed = currentFrameTime - lastFrameTime; 
} 

// Keep track of this frames time (so we can calculate this next time) 
lastFrameTime = currentFrameTime; 

NSLog([NSString stringWithFormat:@"%f", elapsed]); 

// Call update, passing the elapsed time in 
[((GameState*)viewController.view) Update:elapsed]; 
} 

- (void) doStateChange:(Class)state 
{ 
// Remove the previous GameState 
if (viewController.view != nil) 
{ 
    [viewController.view removeFromSuperview]; 
    [viewController.view release]; 
} 

// Create the new GameState 
viewController.view = [[state alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT) andManager:self]; 

// Now set as visible 
[window addSubview:viewController.view]; 
[window makeKeyAndVisible]; 
} 

- (void) dealloc 
{ 
[viewController release]; 
    [window release]; 
    [super dealloc]; 
} 

@end 

Bất kỳ thông tin phản hồi sẽ được đánh giá :-)

PS. Điểm thưởng nếu bạn có thể cho tôi biết tại sao tất cả các sách sử dụng "viewController.view" nhưng đối với mọi thứ khác dường như sử dụng định dạng "[tên đối tượng]". Tại sao không [viewController view]?

+0

Mặc dù mã này hoạt động, có vẻ như nói lắp một chút. Tốc độ khung hình không thấp, nó không có vẻ trơn tru. Tôi nghĩ rằng điều này có thể là vì tôi đang đồng bộ với tốc độ khung hình và sau đó * cập nhật * trong vòng lặp trò chơi của tôi. Kết xuất được thực hiện trong drawRect. Tôi nghĩ mã của tôi nên được vẽ trực tiếp trong phương thức được gọi (và có thể cập nhật sẽ được thực hiện sau khi vẽ), nhưng tôi không thể tìm thấy bất kỳ ví dụ hay về CADisplayLink. –

+0

Tôi đã thay đổi chuyển động của các sprites của tôi thành 30 pixel mỗi giây, và nó có vẻ hoàn toàn trơn tru (với khung hình rất thường xuyên bị rớt), vì vậy tôi nghĩ nó đã giảm xuống tốc độ tôi muốn đặt - ví dụ. di chuyển nhiều hơn một pixel trên mỗi khung hình, điều đó có nghĩa là cuối cùng nó sẽ nhảy hai điểm ảnh trong một khung hình, làm cho nó trông không đồng đều. Tôi đoán điều này là không thể tránh khỏi. –

Trả lời

2

Bạn có Cocos2D được liệt kê dưới dạng thẻ trong câu hỏi của mình nhưng bạn không thực sự sử dụng bất kỳ mã Cocos2D nào. Bạn đã cân nhắc thực hiện triển khai Cocos2D cho trò chơi của mình chưa? Nó sẽ giúp bạn tiết kiệm một số rắc rối không cần thiết.

Đối với cú pháp câu hỏi của bạn [myObject view] được sử dụng để gọi các phương pháp trên myObject khi myObject.view được sử dụng để cài đặt/nhận các biến Ví dụ tiếp xúc như tài sản. Tôi không nhớ nếu bạn có thể lấy các biến mẫu bằng cách sử dụng [myObject view], nhưng nếu nó hoạt động thì tôi đoán sự khác biệt duy nhất giữa hai là cú pháp và bạn có thể sử dụng cả hai phương thức để lấy các biến mẫu.

Hy vọng một số điều rambling đó sẽ hữu ích cho bạn.

+0

Rất tiếc! Nói với bạn tôi không biết tôi đang làm gì! Đã xóa thẻ ngay bây giờ. Đã đọc một số điều về cú pháp, hãy hiểu nó tốt hơn ngay bây giờ. Dường như [thuộc tính myclass] và myclass.property có thể làm những việc khác nhau. Đầu tiên là một thuộc tính (có thể thực thi mã, mặc dù trong hầu hết các trường hợp, tôi nghi ngờ nó chỉ trả về biến) trong khi dấu chấm đang truy cập trực tiếp biến (và sẽ không có mã tùy chỉnh). Có vẻ như sự khác biệt giữa việc hiển thị trường riêng tư và thuộc tính trong C#, chỉ ở đây cả hai đều có thể có cùng tên! –

+0

Trên thực tế, bây giờ tôi đang bối rối, vì tôi gặp lỗi: truy cập phương thức getter 'rect' không xác định Điều này khiến tôi nghĩ rằng việc sử dụng dấu chấm chính xác giống như sử dụng các phương thức get/set! –

+0

Nếu bạn sử dụng dấu chấm, bạn cần xác định biến mẫu mà bạn muốn truy xuất dưới dạng thuộc tính và sau đó tổng hợp nó. Cú pháp tra cứu cho các cuộc gọi "@property" và "@synthesize". Phương pháp Getter/setter được tạo ngầm cho bạn nhưng chỉ sau khi sử dụng @synthesize. Đây là lý do tại sao bạn đang nhận được một phương pháp getter 'rect' không rõ. –

-2

Từ nhiều ví dụ GL của Apple, tôi nghĩ bạn nên sử dụng bộ hẹn giờ.

animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0/60.0) 
                target:self 
               selector:@selector(updateAndRender) 
               userInfo:nil 
               repeats:TRUE]; 
+0

Tôi tin rằng CADisplayLink đã được thêm vào như một cách tốt hơn, nhưng vì nó chỉ mới được thêm vào gần đây, có vẻ như có ít tài liệu/mẫu :( –

Các vấn đề liên quan