亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? animation.html

?? forgers-win32-tutorial
?? HTML
字號:
<HTML><LINK HREF="style.css" REL="STYLESHEET" TYPE="text/css"><HEAD><TITLE>Timers and Animation</TITLE></HEAD><BODY><FONT SIZE="-1">[ <A HREF="./index.html">contents</A>| <A HREF="http://www.winprog.org/">#winprog</A>]</FONT><HR><H1>Timers and Animation</H1><P>Example: anim_one</P><IMG SRC="images/anim_one.gif" ALT="[images/anim_one.gif]" ALIGN="right"><H2>Setting up</H2>Before we get things animated, we need to set up a structure to store the position ofthe ball between updates.  This struct will store the current position and size of the ball,as well as the delta values, how much we want it to move each frame.<P>Once we have the structure type declared, we also declare a global instance of the struct.  Thisis ok since we only have one ball, if were were going to animate a bunch of them, you'd probably wantto use an array or other container (such as a linked list in C++) to store them in a more convenientway.<PRE CLASS="SNIP">const int BALL_MOVE_DELTA = 2;typedef struct _BALLINFO {    int width;    int height;    int x;    int y;    int dx;    int dy;}BALLINFO;BALLINFO g_ballInfo;</PRE>We've also defined a constant <CODE>BALL_MOVE_DELTA</CODE> which is how far we want the ball to move oneach update.  The reason we store deltas in the <CODE>BALLINFO</CODE> structure as well is that we wantto be able to move the ball left or right and up and down independantly, <CODE>BALL_MOVE_DELTA</CODE>is just a handy name to give the value so we can change it later if we want.<P>Now we need to initialize this structure after we load our bitmaps:<PRE CLASS="SNIP">    BITMAP bm;</PRE><PRE CLASS="SNIP">    GetObject(g_hbmBall, sizeof(bm), &bm);    ZeroMemory(&g_ballInfo, sizeof(g_ballInfo));    g_ballInfo.width = bm.bmWidth;    g_ballInfo.height = bm.bmHeight;    g_ballInfo.dx = BALL_MOVE_DELTA;    g_ballInfo.dy = BALL_MOVE_DELTA;</PRE><P>The ball starts off in the top left corner, moving to the right and down according to the <CODE>dx</CODE> and <CODE>dy</CODE> members of <CODE>BALLINFO</CODE>.<H2>Setting the Timer</H2>The easiest way to add a simple timer into a window program is with <CODE>SetTimer()</CODE>, it's not the best, and it'snot recommended for real multimedia or full games, however it's good enough for simple animations like this.  When you need something better take a look at <CODE>timeSetEvent()</CODE> in MSDN; it's more accurate.<PRE CLASS="SNIP">const int ID_TIMER = 1;</PRE><PRE CLASS="SNIP">    ret = SetTimer(hwnd, ID_TIMER, 50, NULL);    if(ret == 0)        MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);</PRE>Here we've declared a timer id so that we can refer to it later (to kill it) and then set the timerin the <CODE>WM_CREATE</CODE> handler of our main window.  Each time the timer elapses, it will senda <CODE>WM_TIMER</CODE> message to the window, and pass us back the ID in <CODE>wParam</CODE>.  Since we only have one timer we don't need the ID, but it's useful if you set more than one timerand need to tell them apart.<P>We've set the timer to elapse every 50 milliseconds, which results in approximately 20 frames per second.  Approximatelybecause like I said, <CODE>SetTimer()</CODE> is a little inaccurate, but this isn't critical code, and a few millisecondshere or there won't kill us.<H2>Animating in WM_TIMER</H2>Now when we get <CODE>WM_TIMER</CODE> we want to calculate the new position for the ball and draw it's updatedposition.<PRE CLASS="SNIP">    case WM_TIMER:    {        RECT rcClient;        HDC hdc = GetDC(hwnd);        GetClientRect(hwnd, &rcClient);        UpdateBall(&rcClient);        DrawBall(hdc, &rcClient);        ReleaseDC(hwnd, hdc);    }    break;</PRE><P>I've put the code for updating and drawing the ball in their own functions.  This is good practice, andit lets us draw the ball from either <CODE>WM_TIMER</CODE> or <CODE>WM_PAINT</CODE> without duplicating code, note that the methodwe use to get the <CODE>HDC</CODE> in each case is different, so it's best to leave this code in the message handlersand pass the result into the <CODE>DrawBall()</CODE> function.<PRE CLASS="SNIP">void UpdateBall(RECT* prc){    g_ballInfo.x += g_ballInfo.dx;    g_ballInfo.y += g_ballInfo.dy;    if(g_ballInfo.x < 0)    {        g_ballInfo.x = 0;        g_ballInfo.dx = BALL_MOVE_DELTA;    }    else if(g_ballInfo.x + g_ballInfo.width > prc->right)    {        g_ballInfo.x = prc->right - g_ballInfo.width;        g_ballInfo.dx = -BALL_MOVE_DELTA;    }    if(g_ballInfo.y < 0)    {        g_ballInfo.y = 0;        g_ballInfo.dy = BALL_MOVE_DELTA;    }    else if(g_ballInfo.y + g_ballInfo.height > prc->bottom)    {        g_ballInfo.y = prc->bottom - g_ballInfo.height;        g_ballInfo.dy = -BALL_MOVE_DELTA;    }}</PRE>All this does is some basic math, we add the delta value to the x position to move the ball.  If the ball goesoutside the client area, move it back in range and change the delta value to the opposite direction so that theball "bounces" off the sides.<PRE CLASS="SNIP">void DrawBall(HDC hdc, RECT* prc){    HDC hdcBuffer = CreateCompatibleDC(hdc);    HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);    HBITMAP hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);    HDC hdcMem = CreateCompatibleDC(hdc);    HBITMAP hbmOld = SelectObject(hdcMem, g_hbmMask);    FillRect(hdcBuffer, prc, GetStockObject(WHITE_BRUSH));    BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCAND);    SelectObject(hdcMem, g_hbmBall);    BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, g_ballInfo.height, hdcMem, 0, 0, SRCPAINT);    BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);    SelectObject(hdcMem, hbmOld);    DeleteDC(hdcMem);    SelectObject(hdcBuffer, hbmOldBuffer);    DeleteDC(hdcBuffer);    DeleteObject(hbmBuffer);}</PRE>This is essentially the same drawing code as the past few examples, with the exception that it gets the position and dimentions of the ball from the <CODE>BALLINFO</CODE> structure.  There is however one important difference...<H2>Double Buffering</H2>When doing your drawing directly to the <CODE>HDC</CODE> of the window, it's entirely possible that the screenwill get updated before you're done... for example after you draw the mask and before you draw the colour imageover top, the user might see a flicker of the back background before your program has a chance to draw over itin colour.  The slower your computer and the more drawing operations that you do, the more flicker will be apparentand eventually it will look like a big jumbled mess.<P>This is terribly distracting, and we can solve it simply by doing all the drawing in memory first, and thencopying the completed masterpiece to the screen in a single <CODE>BitBlt()</CODE> so that the screen is updateddirectly from the old image, to the complete new image with none of the individual operations visible.<P>To do this, we create a temporary <CODE>HBITMAP</CODE> in memory that is the exact size of the area we are going to draw to on the screen.  We also need an <CODE>HDC</CODE> so that we can <CODE>BitBlt()</CODE> to the bitmap.<PRE CLASS="SNIP">    HDC hdcBuffer = CreateCompatibleDC(hdc);    HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);    HBITMAP hbmOldBuffer = SelectObject(hdcBuffer, hbmBuffer);</PRE>Now that we have a place to draw to in memory, all of the drawing operations use <CODE>hdcBuffer</CODE> instead of <CODE>hdc</CODE> (the window) and the results are stored on the bitmap in memory untill we are complete.  We can nowcopy the whole thing over to the window in one shot.<PRE CLASS="SNIP">    BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);</PRE>That's it, and we clean up our <CODE>HDC</CODE>s and <CODE>HBITMAP</CODE>s as usual.<H3>Faster Double Buffering</H3>In this example I am creating and destroying the bitmap used for double buffering each frame, I did this basicallybecause I wanted to be able to size the window so it's easier to just always create a new buffer than to trackwhen the window position changes and resize the buffer.  It would be more efficient to create a global double buffer bitmap and either not allow the window to resize or only resize the bitmap when the window resized, insteadof creating it and destroying it all the time.  It's up to you to implement this if you want to optimize the drawingfor a game or something.<H2>Killing the Timer</H2>When our window is destroyed, it's a good idea to release all resources we used, and in this case thatincludes the timer we set.  To stop it, we simply call <CODE>KillTimer()</CODE> and pass in the ID that we used whenwe created it.<PRE CLASS="SNIP">    KillTimer(hwnd, ID_TIMER);</PRE><HR><FONT SIZE="-1">Copyright &copy; 1998-2003, Brook Miles (<A HREF="mailto:forger(nospam)winprog.org">theForger</A>).  All rights reserved.</FONT><SCRIPT language="JavaScript"><!--   var re = /\(nospam\)/ig;   var str;   for(i = 0;i < document.links.length;i++)    {      str = "" + document.links(i).href;      if(str.search(re) != -1)         document.links(i).href = str.replace(re, "@");      str = "" + document.links(i).innerHTML;      if(str.search(re) != -1)         document.links(i).innerHTML = str.replace(re, "@");   }--></SCRIPT></BODY></HTML>

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲自拍偷拍网站| 不卡的av中国片| 91视频xxxx| 久久青草欧美一区二区三区| 一区二区三区高清在线| 国产一区91精品张津瑜| 欧美日韩国产一二三| 国产欧美日韩精品a在线观看| 亚洲国产日韩a在线播放| 成人av资源下载| 欧美不卡在线视频| 亚洲电影中文字幕在线观看| 成人av资源在线| 国产亚洲欧美在线| 免费观看成人av| 在线电影一区二区三区| 亚洲一二三四在线观看| av午夜一区麻豆| 国产精品久久久久毛片软件| 国产乱人伦精品一区二区在线观看 | 国产亚洲女人久久久久毛片| 亚洲午夜久久久久中文字幕久| 国产成人免费在线观看不卡| 欧美一区二区精品在线| 午夜伦欧美伦电影理论片| 色综合久久久久网| 亚洲精品欧美二区三区中文字幕| 不卡一区中文字幕| 中文在线一区二区 | 午夜久久久久久久久久一区二区| 91国产免费看| 亚洲国产成人av| 欧美色窝79yyyycom| 17c精品麻豆一区二区免费| av一区二区三区在线| 国产精品美女www爽爽爽| 不卡欧美aaaaa| 亚洲蜜臀av乱码久久精品| 国产精品自拍毛片| 国产精品欧美久久久久无广告| 成人黄色在线视频| 亚洲欧美国产高清| 欧美私模裸体表演在线观看| 五月激情综合网| 日韩欧美电影一区| 国产真实乱子伦精品视频| 国产欧美视频一区二区| 色综合天天性综合| 亚洲一区二区三区四区在线免费观看| 欧美亚洲丝袜传媒另类| 天堂精品中文字幕在线| 精品久久久久久久一区二区蜜臀| 久久9热精品视频| 26uuu精品一区二区三区四区在线| 精品一区二区综合| 国产欧美日韩三区| 欧美性大战久久久| 久久99国产精品成人| 日本一区二区不卡视频| 在线观看av不卡| 久久99国内精品| 亚洲欧洲三级电影| 欧美一区二区大片| 日韩va欧美va亚洲va久久| 2020国产精品自拍| 91免费观看视频在线| 久久国产欧美日韩精品| 国产精品久久国产精麻豆99网站 | 亚洲精品成人精品456| 3d动漫精品啪啪一区二区竹菊| 精品中文av资源站在线观看| 一区在线播放视频| 日韩精品一区二区三区在线观看| eeuss鲁片一区二区三区在线观看 eeuss鲁片一区二区三区在线看 | 激情另类小说区图片区视频区| 欧美国产精品劲爆| 欧美一级高清片在线观看| 国产91丝袜在线播放0| 亚洲电影你懂得| 中文字幕欧美日韩一区| 欧美一卡2卡3卡4卡| 91社区在线播放| 国产精品一区三区| 午夜不卡在线视频| 国产精品成人一区二区三区夜夜夜| 91精品国产一区二区人妖| 色综合av在线| 高清av一区二区| 蜜桃精品视频在线| 亚洲国产成人高清精品| 成人欧美一区二区三区1314 | 蜜桃久久精品一区二区| 一区二区三区美女视频| 国产精品污污网站在线观看| 91精品国产aⅴ一区二区| 欧美亚洲日本一区| 不卡高清视频专区| 国产精品原创巨作av| 久久不见久久见中文字幕免费| 亚洲午夜三级在线| 亚洲一区在线观看免费观看电影高清 | 国产成人精品一区二区三区四区| 亚洲一二三四在线观看| 亚洲精选一二三| 中文字幕在线视频一区| 久久久久久久精| 久久久精品免费网站| 久久久久久电影| 久久久另类综合| 国产欧美一区二区在线| 久久综合九色综合欧美98| 欧美一区二区三区四区在线观看 | 粗大黑人巨茎大战欧美成人| 国产在线播放一区二区三区| 久久精品国产第一区二区三区| 亚洲成人av免费| 日本午夜一区二区| 日产欧产美韩系列久久99| 日韩av在线播放中文字幕| 热久久久久久久| 久久电影网站中文字幕| 国产一区二区三区不卡在线观看 | 亚洲乱码国产乱码精品精可以看| 国产精品欧美精品| 亚洲视频一区在线观看| 亚洲一区二区三区四区在线免费观看| 玉米视频成人免费看| 亚洲一级二级三级| 奇米888四色在线精品| 久久国产精品区| 成人永久看片免费视频天堂| 成人激情动漫在线观看| 在线欧美日韩国产| 91精品一区二区三区久久久久久| 欧美大白屁股肥臀xxxxxx| 日本一区二区视频在线观看| 亚洲免费观看高清| 日本三级韩国三级欧美三级| 国产乱子伦一区二区三区国色天香| 风流少妇一区二区| 欧美在线看片a免费观看| 91精品福利在线一区二区三区 | 99久久精品免费精品国产| 91免费看视频| 欧美一级生活片| 国产精品理论片在线观看| 午夜在线电影亚洲一区| 久久97超碰色| 日本道精品一区二区三区| 欧美日韩国产高清一区二区| 久久综合999| 亚洲黄色片在线观看| 久久国产福利国产秒拍| 色综合久久88色综合天天6 | 色香蕉成人二区免费| 日韩国产欧美在线视频| 欧美国产精品中文字幕| 一区二区三区不卡在线观看 | 国产福利91精品一区| 色婷婷综合中文久久一本| 欧美mv日韩mv亚洲| 亚洲激情一二三区| 久久91精品国产91久久小草| 日本精品一级二级| 久久久久久夜精品精品免费| 午夜一区二区三区在线观看| 成人国产视频在线观看| 日韩欧美黄色影院| 一区二区三区日本| 国产成人在线视频网址| 欧美乱妇23p| 成人欧美一区二区三区在线播放| 激情图片小说一区| 欧美色视频在线| 一级做a爱片久久| www.日韩在线| 久久久精品日韩欧美| 亚洲第一激情av| 91九色02白丝porn| 亚洲欧美日韩在线播放| 丁香激情综合国产| 26uuu国产电影一区二区| 婷婷激情综合网| 欧美在线综合视频| 亚洲卡通动漫在线| 91免费观看国产| 亚洲欧美偷拍三级| 91免费国产在线| 亚洲精品视频一区二区| 99精品欧美一区二区三区综合在线| 久久先锋影音av鲁色资源网| 日韩成人精品视频| 777精品伊人久久久久大香线蕉| 一区二区三区加勒比av| 91视频一区二区| 亚洲一区二区三区四区的| 欧美日韩在线直播| 午夜精品久久久久久不卡8050| 色婷婷av一区| 亚洲第一狼人社区|