我对编程完全陌生。
对于我的第一个程序,我尝试使用 Windows api 用 c 语言制作一个小游戏。
下面的代码是一个几乎可以工作的蛇,(一些错误尚未修复)
但我找不到解决该闪烁问题的可行解决方案。
(我不知道双缓冲所以我只是从这里拿走:[ http://www.codeguru.com/forum/archive/index.php/t-272723.html][1]
// snake1.02.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "snake1.02.h"
#include "stdio.h"
#define ID_MYTIMER 1234567
#define ID_BERRY 1
#define SEGMENTSIZE 10
const WCHAR szClassName[] = L"Snake1.02";
HWND hWnd;
UINT myTimer;
struct point {
int x, y;
};
point snake[500];
int dx = SEGMENTSIZE; //Change direction l=l+1
int dy = 0;
int snakelength=3;
int highscore=0;
WCHAR nachricht[100];
int map[80][60]; //Wenn Bildschirmgröße angepasst wird, auch hier anpassen!!!
// Global Variables:
HINSTANCE hInst; // current instance
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
// Initialize global strings
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
myTimer = SetTimer ( hWnd, ID_MYTIMER, 40, NULL );
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
KillTimer ( hWnd, myTimer );
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+2);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szClassName;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szClassName, szClassName, WS_OVERLAPPED,
CW_USEDEFAULT, 0, 800, 600, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
for(int i=snakelength; i>=0; i--){
snake[i].x =100-(i*SEGMENTSIZE);
snake[i].y=20;}
for(int x=0; x<78;x++){
map[x][0]=1;
map[x][56]=1;
}
for(int y=0; y<57;y++){
map[0][y]=1;
map[78][y]=1;
}
map[50][70]=2;
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
HDC memDC;
HBITMAP hMemBmp;
HBITMAP hOldBmp;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
memDC = CreateCompatibleDC(hdc); //flimmerfrei
hMemBmp = CreateCompatibleBitmap(hdc, 800, 600);
hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);
// TODO: Add any drawing code here...
for (int i = 0; i<=snakelength; i++) {
Rectangle(memDC, snake[i].x,snake[i].y,snake[i].x+10,snake[i].y+10);
}
for (int y=0; y<60;y++){
for (int x=0; x<80;x++){
if(map[x][y]==1||map[x][y]==2){
Rectangle(memDC,x*SEGMENTSIZE,y*SEGMENTSIZE,x*SEGMENTSIZE+SEGMENTSIZE,y*SEGMENTSIZE+SEGMENTSIZE);
}}
}
BitBlt(hdc, 0, 0, 800, 600, memDC, 0, 0, SRCCOPY);
SelectObject(memDC, hOldBmp);
DeleteObject(hMemBmp);
DeleteDC(memDC);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_TIMER:
switch (wParam)
{
case ID_MYTIMER: {
if (map[snake[0].x/10][snake[0].y/10]==1){ //crashcheck
KillTimer ( hWnd, myTimer );
wsprintf (nachricht,L"Game Over. Punktestand: %d",highscore);
MessageBox(hWnd, (LPCWSTR)nachricht,L"Ende",0);
}
if (map[snake[0].x/10][snake[0].y/10]==2) //grow
{
for (int i = snakelength; i>0; i--)
{
snake[i].x = snake[i-1].x;
snake[i].y = snake[i-1].y;
}
snake[0].x = snake[1].x + dx;
snake[0].y = snake[1].y + dy;
map[snake[0].x/10][snake[0].y/10]=0;
snakelength++;
highscore+=10;
}
for (int i = snakelength; i>0; i--) {
snake[i].x = snake[i-1].x;
snake[i].y = snake[i-1].y;
}
snake[0].x = snake[1].x + dx;
snake[0].y = snake[1].y + dy;
InvalidateRect(hWnd, 0,1);
return 0;
}
}
break;
case WM_KEYDOWN: {
switch (wParam) {
case VK_DOWN:{
if(dy!=-SEGMENTSIZE){
dy=SEGMENTSIZE;
dx=0;
}
}
break;
case VK_RIGHT:{
if (dx!=-SEGMENTSIZE){
dy=0;
dx=SEGMENTSIZE;
}
}
break;
case VK_UP:{
if (dy!=SEGMENTSIZE){
dy=-SEGMENTSIZE;
dx=0;
}
}
break;
case VK_LEFT:{
if(dx!=SEGMENTSIZE){
dy=0;
dx=-SEGMENTSIZE;
}
}
break;
case VK_ESCAPE:{
ExitProcess(0);
}
break;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
最佳答案
在 WndProc 的主 switch 语句中添加一个 case:
case WM_ERASEBKGND:
return TRUE;
关于c - 即使使用双缓冲,屏幕也会闪烁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2359170/