?? gapisnake.cpp
字號:
// gapi snake sample
// gapisnake.cpp
#include <windows.h>
#include <windowsx.h>
#include <aygshell.h>
#include "resource.h"
#include <gx.h>
//#include <vibrate.h> PPC Not Support
#define MENU_HEIGHT 20
#define MAX_LOADSTRING 100
#define SAKNE_SIZE 4
#define MOVE_UP 1
#define MOVE_DOWN 2
#define MOVE_LEFT 3
#define MOVE_RIGHT 4
// Global Variables:
HINSTANCE hInst; // The current instance
HWND hwndCB; // The command bar handle
// Global GAPI variables:
GXDisplayProperties gx_displayprop;
GXKeyList gx_keylist;
unsigned short *framebuf = NULL; //screen buffer, same as OFF SCREEN
// Global variables for this program (line drawing stuff only)
int x1=10,x2=100,y1=40,y2=80, dx1=4,dy1=-4, dx2=3,dy2=3;
typedef struct tag_snakebody *LPSNAKEBODY;
typedef struct tag_snakehead
{
int x;
int y;
int next_m;
int pre_m;
int eat;
LPSNAKEBODY next;
}SNAKEHEAD;
typedef struct tag_snakebody
{
int x;
int y;
int next_m;
int pre_m;
LPSNAKEBODY next;
LPSNAKEBODY pre;
}SNAKEBODY;
typedef struct tag_food
{
int x;
int y;
}FOODINFO,LPFOODINFO;
static SHACTIVATEINFO s_sai;
SNAKEHEAD snakehead;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass (HINSTANCE, LPTSTR);
BOOL InitInstance (HINSTANCE, int);
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
void ClearScreen(unsigned short * buffer,int r, int g, int b);
void RunVibrate(int time);
void Run(HWND hwnd);
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccelTable;
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd = NULL;
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name
hInst = hInstance; // Store instance handle in our global variable
// Initialize global strings
wcscpy(szWindowClass,_T("G_Snake"));
wcscpy(szTitle,_T("GAPI_Snake"));
//If it is already running, then focus on the window
hWnd = FindWindow(szWindowClass, szTitle);
if (hWnd)
{
SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01));
return 0;
}
MyRegisterClass(hInstance, szWindowClass);
RECT rect;
GetClientRect(hWnd, &rect);
hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
//When the main window is created using CW_USEDEFAULT the height of the menubar (if one
// is created is not taken into account). So we resize the window after creating it
// if a menubar is present
{
RECT rc;
GetWindowRect(hWnd, &rc);
rc.bottom -= MENU_HEIGHT;
if (hwndCB)
MoveWindow(hWnd, rc.left, rc.top, rc.right, rc.bottom, FALSE);
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// GAPI Stuff
// Attempt to take over the screen
if (GXOpenDisplay( hWnd, GX_FULLSCREEN) == 0)
return FALSE;
// Get display properties
gx_displayprop = GXGetDisplayProperties();
// Check for 16 bit color display
if (gx_displayprop.cBPP != 16)
{
// Only dealing with 16 bit color in this code
GXCloseDisplay();
MessageBox(hWnd,L"Sorry, only supporting 16bit color",L"Sorry!", MB_OK);
return FALSE;
}
//alloc screen buf, use it to save all element of a full frame;
framebuf = (unsigned short*)malloc(sizeof(short)*gx_displayprop.cxWidth*gx_displayprop.cyHeight);
if(framebuf==NULL)
return FALSE;
//clear white screen
ClearScreen(framebuf,0x00,0xff,0xff);
// Take over button handling
GXOpenInput();
// Get default buttons for up/down etc.
gx_keylist = GXGetDefaultKeys(GX_NORMALKEYS);
return TRUE;
}
//get 16bit color RGB at point(x,y)
void Get16Pixel(unsigned short *buffer,int x, int y,int *r, int *g, int *b)
{
unsigned short *pixeladd;
int address = (x * gx_displayprop.cbxPitch>>1) + (y * gx_displayprop.cbyPitch>>1);
pixeladd = (buffer+address);
if (gx_displayprop.ffFormat & kfDirect565)//565 format
{
unsigned short PixelCol;
PixelCol = (*pixeladd);
*r = (PixelCol & 0xf800) >> 11;
*g = (PixelCol & 0x07e0) >> 5;
*b = (PixelCol & 0x001f);
}
else//555 format
{
unsigned short PixelCol;
PixelCol = (*pixeladd);
*r = (PixelCol & 0x7c00) >> 11;
*g = (PixelCol & 0x03e0) >> 5;
*b = (PixelCol & 0x001f);
}
}
// Plot a pixel given video memory address, color, x and y co-ords
void PlotPixel(unsigned short *buffer, int x, int y, int r, int g, int b)
{
int address = (x * gx_displayprop.cbxPitch>>1) + (y * gx_displayprop.cbyPitch>>1);
unsigned short PixelCol;
if (gx_displayprop.ffFormat & kfDirect565)
{
PixelCol = (unsigned short) (r & 0xff) << 11 | (g & 0xff) << 5 | (b & 0xff);
}
else
{
PixelCol = (unsigned short) (r & 0xff) << 10 | (g & 0xff) << 5 | (b & 0xff);
}
*(unsigned short *)(buffer+address) = PixelCol;
}
// Simple midpoint line algorithm.
void DrawLine(unsigned short *buffer, int x0, int y0, int x1, int y1, int r, int g, int b)
{
int x;
if (x0>x1) {x=x1; x1=x0; x0=x;}
if (y0>y1) {x=y1; y1=y0; y0=x;}
float dx,dy,y,m;
dy=y1-y0;
dx=x1-x0;
m=dy/dx;
y=y0;
for (x=x0; x<x1; x++)
{
PlotPixel(buffer,x,(int)y,r,g,b);
y+=m;
}
}
void DrawBlock(unsigned short *buffer, int x, int y, int w, int h, int r, int g, int b)
{
int dx,dy;
if(y<0 || w<0 ||h<0)
return;
for(dy = y; dy<y+h; dy++)
{
for(dx = x; dx<x+w; dx++)
{
PlotPixel(buffer,dx,dy,r,g,b);
}
}
}
// Clear the screen to a color desribed by the red, green, blue values
void ClearScreen(unsigned short * buffer,int r, int g, int b)
{
unsigned short * line_buffer = buffer;
if (buffer == NULL) return;
// Calculate the pixel color from the r,g,b components.
unsigned short PixelCol;
if (gx_displayprop.ffFormat & kfDirect565)
{
PixelCol = (unsigned short) (r & 0xff) << 11 | (g & 0xff) << 5 | (b & 0xff);
}
else
{
PixelCol = (unsigned short) (r & 0xff) << 10 | (g & 0xff) << 5 | (b & 0xff);
}
// Use two loops to fill the entire screen with the necessary color
for (unsigned int y=0; y<gx_displayprop.cyHeight; y++)
{
unsigned short * pixel = buffer;
for (unsigned int x=0; x<gx_displayprop.cxWidth; x++)
{
*pixel = PixelCol;
pixel += gx_displayprop.cbxPitch >> 1;
}
buffer += gx_displayprop.cbyPitch >> 1;
}
}
void InitSnake()
{
LPSNAKEBODY snaketrack;
snakehead.x=100;
snakehead.y=100;
snakehead.next_m=MOVE_UP;
snakehead.pre_m=MOVE_UP;
snakehead.next=NULL;
snaketrack = (LPSNAKEBODY)malloc(sizeof(SNAKEBODY));
snaketrack->next_m = MOVE_UP;
snaketrack->pre_m = MOVE_UP;
snaketrack->next = NULL;
snaketrack->pre = NULL;
snaketrack->x = snakehead.x;
snaketrack->y = snakehead.y + SAKNE_SIZE;
snakehead.next = snaketrack;
//init snake's boby length is 30 body(block)
for(int i = 0; i <30; i++)
{
snaketrack->next = (LPSNAKEBODY)malloc(sizeof(SNAKEBODY));
snaketrack->next->next = NULL;
snaketrack->next->pre = snaketrack;
snaketrack = snaketrack->next;
snaketrack->next_m = snaketrack->pre->next_m;
snaketrack->pre_m = snaketrack->pre->next_m;
snaketrack->x = snaketrack->pre->x;
snaketrack->y = snaketrack->pre->y + SAKNE_SIZE;
}
}
//destroy snake's resource alloc memory previously
void ReleaseSnake()
{
LPSNAKEBODY snaketrack,last;
snaketrack = snakehead.next;
while(snaketrack)
if(snaketrack->next != NULL)
snaketrack = snaketrack->next;
else
break;
while(snaketrack)
{
last = snaketrack->pre;
free(snaketrack);
snaketrack = last;
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
InitSnake();
SetTimer(hWnd,1,100,NULL);
break;
case WM_TIMER:
Run(hWnd);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
HDC hdc = BeginPaint(hWnd,&ps);
GetClientRect(hWnd,&rect);
rect.top = 80;
DrawText(hdc,_T("snake has died\nplease push left softkey EXIT"),-1,&rect,DT_CENTER );
EndPaint(hWnd,&ps);
}
break;
case WM_KEYDOWN:
if (wParam == (unsigned) gx_keylist.vkUp)
{
snakehead.next_m = MOVE_UP;
}
if (wParam == (unsigned) gx_keylist.vkDown)
{
snakehead.next_m = MOVE_DOWN;
}
if (wParam == (unsigned) gx_keylist.vkLeft)
{
snakehead.next_m = MOVE_LEFT;
}
if (wParam == (unsigned) gx_keylist.vkRight)
{
snakehead.next_m = MOVE_RIGHT;
}
if(wParam == (unsigned) gx_keylist.vkA)
{
KillTimer(hWnd,1);
SendMessage(hWnd,WM_CLOSE,0,0);
ReleaseSnake();
}
break;
case WM_DESTROY:
if(framebuf!=NULL)
free(framebuf);
GXCloseInput();
GXCloseDisplay();
PostQuitMessage(0);
break;
case WM_KILLFOCUS:
GXSuspend();
break;
case WM_SETFOCUS:
GXResume();
break;
case WM_SETTINGCHANGE:
SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void ChangeDirection()
{
LPSNAKEBODY traceon,temp1,temp2;
traceon = snakehead.next;
if(traceon != NULL)
{
traceon->next_m = snakehead.pre_m;
snakehead.pre_m = snakehead.next_m;
traceon = traceon->next;
while(traceon)
{
traceon->next_m = traceon->pre->pre_m;
traceon->pre->pre_m = traceon->pre->next_m;
traceon = traceon->next;
}
}
}
void SortAll()
{
/* sort all food,include snake head,and virtual place */
LPSNAKEBODY traceon;
void *buf;
int size;
switch(snakehead.next_m)
{
case MOVE_UP:
snakehead.y -= SAKNE_SIZE;
break;
case MOVE_LEFT:
snakehead.x -= SAKNE_SIZE;
break;
case MOVE_DOWN:
snakehead.y += SAKNE_SIZE;
break;
case MOVE_RIGHT:
snakehead.x += SAKNE_SIZE;
break;
default:
break;
}
traceon = snakehead.next;
while(traceon)
{
switch(traceon->next_m)
{
case MOVE_UP:
traceon->y -= SAKNE_SIZE;
break;
case MOVE_LEFT:
traceon->x -= SAKNE_SIZE;
break;
case MOVE_DOWN:
traceon->y += SAKNE_SIZE;
break;
case MOVE_RIGHT:
traceon->x += SAKNE_SIZE;
break;
default:
break;
}
traceon = traceon->next;
}
}
BOOL RedrawSnake()
{
unsigned short * buffer = (unsigned short *) GXBeginDraw();
if(buffer == NULL)
{
return FALSE;
}
int i = 0;
LPSNAKEBODY snaketrack;
ClearScreen(framebuf,0xff,0x00,0xff);
snaketrack = snakehead.next;
DrawBlock(framebuf,snakehead.x,snakehead.y,SAKNE_SIZE,SAKNE_SIZE,0,0,0);
while(snaketrack)
{ i+=1;
DrawBlock(framebuf,snaketrack->x,snaketrack->y,SAKNE_SIZE,SAKNE_SIZE,32,16,i);
snaketrack = snaketrack->next;
}
memcpy(buffer,framebuf, sizeof(short)*gx_displayprop.cxWidth*gx_displayprop.cyHeight);
// End the drawing code
GXEndDraw();
return TRUE;
}
int JudgeDeath(unsigned short * buffer)
{
/* return 1 means will die,and return 0 means will survive */
int tempx,tempy,r,g,b;
switch(snakehead.next_m)
{
case MOVE_UP:
tempx = snakehead.x;
tempy = snakehead.y - SAKNE_SIZE;
break;
case MOVE_LEFT:
tempx = snakehead.x - SAKNE_SIZE;
tempy = snakehead.y;
break;
case MOVE_DOWN:
tempx = snakehead.x;
tempy = snakehead.y + SAKNE_SIZE;
break;
case MOVE_RIGHT:
tempx = snakehead.x + SAKNE_SIZE;
tempy = snakehead.y;
break;
default:
break;
}
if((tempx < 0) || (tempx > gx_displayprop.cxWidth) ||
(tempy < 0) || (tempy > gx_displayprop.cyHeight))
return 1;
Get16Pixel(buffer,tempx,tempy,&r,&g,&b);
// if point color is not same as backcolor, it thinks snake is dead.
// it is simple to deal with color infomation.
// because device is 16 color bit(565 format), 0x1f is equal to RGB's R value(0xff)
// and g = 3f is equal to G max value, b = 1f is equal to B max value.
if( r != 0x1f && g != 0x3f && b != 0x1f)
{
MessageBeep(-1);
return 1;
}
return 0; /* survive */
}
void Run(HWND hwnd)
{
if(1 == JudgeDeath(framebuf))
{
KillTimer(hwnd,1);
// RunVibrate(1000);
SendMessage(hwnd,WM_PAINT,0,0);
InvalidateRect(hwnd,NULL,TRUE);
}
ChangeDirection();
SortAll();
RedrawSnake();
}
//use vibrate character, PPC 2003 SDK not support
/*
void RunVibrate(int time)
{
TCHAR buf[20];
int caps = -1;
caps = VibrateGetDeviceCaps(VDC_AMPLITUDE);
if(caps<=0)
return;
HRESULT hr = Vibrate(0, NULL, TRUE, INFINITE);
if(hr == E_FAIL)
{
MessageBox(NULL,L"E_FAIL",L"",MB_OK);
}
else if(hr == E_NOTIMPL)
{
MessageBox(NULL,L"E_NOTIMPL",L"",MB_OK);
}
Sleep(1000);
VibrateStop();
}
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -