《MFC遊戲開發》筆記五 定時器和簡單動畫

2022-07-20 12:30:20 字數 3634 閱讀 2423

9332377

上一節筆記中,我們講解了鍵盤響應和滑鼠響應,實現了對於玩家的操作,程式做出正確的響應。但是大家在玩遊戲的過程中,應該會注意到,在大家沒有操作的時候,程式的畫面仍然不是靜止的,比如npc會四處走動,怪物仍然會跑過來攻擊玩家等,也就是說,畫面仍然在隨著時間不斷的更新。這一點在程式中對應的就是無時無刻不在更新著遊戲資訊和繪製畫面,以便及時的反映出遊戲的狀態。

在win 32程式中,一般大家會把繪製程式放到訊息迴圈之中,但是在mfc中由於對win 32高度的封裝和訊息印射機制,我們很難找到訊息迴圈的位置,所以我們就需要採用別的辦法。大家現在已經知道,我們繪圖都是在onpaint裡進行的,那麼我們不斷的執行onpaint函式不就行了嗎?實現的方法就是今天要講解的定時器了。

定時器(timer)物件可以每隔一段時間發出乙個時間訊息,程式一旦接收到此訊息之後,便可以決定接下來要做哪些事情。霧央先說一下定時器大概會有5毫秒左右的誤差,精度不夠,在實際遊戲開發中,很少使用到,但是對於我們初學者來說,這個對於遊戲性幾乎沒有任何影響,還很方便大家的開發,所以我們仍然使用了定時器。

下面來介紹如何建立與刪除定時器。

1.建立定時器

windows api 的settimer()函式可為視窗建立乙個定時器,並每隔一段時間就發出wm_timer訊息,此函式的定義是

uint_ptrsettimer(

uint_ptrnidevent, //定時器代號

uintuelapse, //時間間隔

timerproclptimerfunc //處理函式

);

settimer()函式的第1個引數是定時器的代號,這個代號在同乙個視窗中必須是唯一的,且值不為0,第2個引數則是定時器發出wm_timer訊息的時間間隔:第3個參則用於設定由系統呼叫處理wm_timer訊息的相應函式,如果不用響應函式處理wm_timer訊息,則此引數應設為null。

一句話概括,就是settimer函式會建立乙個id為第乙個引數的定時器,它每隔第二個引數的時間就會執行一次第三個引數指向的函式。

如果不需要自己定義處理函式,第三個引數設定為null,我們可以使用預設的訊息處理函式。

下面是設定乙個每隔100毫秒發出wm_timer訊息的定時器的程式**。

settimer(1,100,null);

2.刪除定時器

定時器建立後,就會一直自動地按照定義設定的時間間隔發出wm_timer訊息,如果要停用某個定時器,必須使用下面的這個函式:

bool   killtimer(int 定時器代號);

在mfc中,大家要使用定時器,需要先通過類嚮導新增「wm_timer」訊息,新增的具體過程如果有不會的同學請閱讀上一節筆記:滑鼠響應和鍵盤響應。

在新增完定時器訊息後,cchildview.cpp中會出現

void cchildview::ontimer(uint_ptr nidevent)

這個函式,這就是定時器訊息處理函式了,它的引數nidevent就是表示執行ontimer函式的定時器的id了。

霧央要強調一下關於建立定時器的位置,大家基本可以在任何地方建立,比如在onpaint中等,但是千萬不要在precreatewindow函式中建立定時器,否則大家就會發現程式一執行就會彈出來乙個出錯框了。

如果大家希望在視窗一建立的時候就建立定時器,比如驅動我們視窗繪製的定時器等,那麼我們可以新增「wm_create」訊息,在這裡面進行建立。

在示例程式中我們要實現的是按下t鍵人物自動向右移動,按下i鍵定值移動。大家如果自己執行一下程式,就會感覺這有幾分動畫的影子了。事實上,如果讓人物移動的時候,變化一下,比如幾張跑動的不斷的切換,那麼就是乙個真正意義上的動畫了。

另外,霧央有乙個感到非常抱歉的事情要和大家說明一下,在之前的**中,霧央漏掉了一句很重要的**,在onpaint函式中釋放dc即releasedc之前要加上validaterect(&m_client);這個函式的作用是使繪圖區變得有效。在windows中,如果我們的視窗被遮擋了什麼的,視窗那部分就變得無效,就會產生wm_paint訊息,當繪製完畢後,必須要使視窗變得有效,否則

系統將周而復始的產生

wm_paint

訊息,使得

cpu佔用率非常高,而且還會出現很多莫名其妙的問題,比如使用

messagebox

會導致程式失去響應等。

下面貼**

標頭檔案

// childview.h : cchildview 類的介面

//#pragma once

// cchildview 視窗

class cchildview : public cwnd

;

cpp檔案

// childview.cpp : cchildview 類的實現

//#include "stdafx.h"

#include "gamemfc.h"

#include "childview.h"

#ifdef _debug

#define new debug_new

#endif

//定時器的名稱用巨集比較清楚

#define timer_paint 1

#define timer_heromove 2

// cchildview

cchildview::cchildview()

cchildview::~cchildview()

begin_message_map(cchildview, cwnd)

on_wm_paint()

on_wm_keydown()

on_wm_lbuttondown()

on_wm_timer()

on_wm_create()

end_message_map()

//將png貼圖透明

void transparentpng(cimage *png) }}

// cchildview 訊息處理程式

bool cchildview::precreatewindow(createstruct& cs)

void cchildview::onpaint()

//按鍵響應函式

void cchildview::onkeydown(uint nchar, uint nrepcnt, uint nflags)

}//滑鼠左鍵單擊響應函式

void cchildview::onlbuttondown(uint nflags, cpoint point)

//定時器響應函式

void cchildview::ontimer(uint_ptr nidevent)

break; }}

int cchildview::oncreate(lpcreatestruct lpcreatestruct)

《MFC遊戲開發》筆記一 系列簡介

分類 c c 遊戲開發 2013 07 11 12 05 13084人閱讀收藏 舉報遊戲開發 mfc2darpg c 鑑於有同學需要 學習,我以後會把 整體的貼上出來,以方便大家參考,但是還是建議大家自己動手寫一遍。在筆記二中調整視窗的 寫完後,在本系列教程中大家就只用關注cchildview.h和...

MFC學習筆記之多對話方塊中使用定時器

各位,我有這樣乙個問題 我要做乙個多對話方塊的工程,裡面有兩個以上的對話方塊,後台有乙個執行緒進行串列埠通訊,每個對話方塊都會根據讀入串列埠的內容進行更新。比如乙個對話方塊顯示資料,乙個對話方塊繪製波形。我的通訊會採用定時方式,比如100毫秒收發一次,然後對話方塊的內容也是100ms更新一次。現在我...

EVC 定時器和edit box使用筆記

這兩天更新了一下原來的test utilitly,使串列埠和紅外資料可以定時自動傳送,其中要用到定時器.並更正了接受視窗用到的edit box控制項中的乙個小問題,在此作個筆記.1.evc 中應用簡單的定時器 在send按鈕的函式裡加入了裝載定時器函式 啟動1s定時器,用於定時向com 傳送資料 m...