// WindowsProject3.cpp: 응용 프로그램의 진입점을 정의합니다.
//
#include "stdafx.h"
#include "WindowsProject1.h"
//openvg 헤더파일
#include "egl/egl.h"
#include "vg/openvg.h"
#include "vgLoadImage.h"
#include <Time.h>
#define MAX_LOADSTRING 100
#define KEY_DOWN(code) ((GetAsyncKeyState(code)&0x8000)?1:0)
// 전역 변수:
HINSTANCE hInst; // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING]; // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING]; // 기본 창 클래스 이름입니다.
EGLDisplay display;
EGLSurface surface;
EGLContext context;
VGImage image1;
VGImage planeImg;
VGImage bulletImg;
VGImage missileImg;
VGImage enemyImage;
struct Plane {
int x,y;
} plane;
struct Missile {
int shot, x, y;
} missiles[100];
struct Bullet {
int shot, x, y;
} bullet[100];
struct Enemy {
int x, y, playing, type ;
} enemies[100];
void timerProc();
// 이 코드 모듈에 들어 있는 함수의 정방향 선언입니다.
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 wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 여기에 코드를 입력합니다.
// 전역 문자열을 초기화합니다.
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINDOWSPROJECT1, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 응용 프로그램 초기화를 수행합니다.
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));
MSG msg;
// 기본 메시지 루프입니다.
DWORD lastTime = GetTickCount();
while (1)
{
if (PeekMessage(&msg, NULL, 0, 0, 1))
{
if (!TranslateAccelerator(msg.hwnd, NULL, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.message == WM_QUIT)
break;
}
DWORD curTime = GetTickCount();
if (curTime - lastTime >= 33) // 30 frame per second
{
lastTime = lastTime + 33;
timerProc(); //반복해서 실행할 함수
}
}
return (int)msg.wParam;
}
//
// 함수: MyRegisterClass()
//
// 목적: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW 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(hInstance, MAKEINTRESOURCE(IDI_WINDOWSPROJECT1));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINDOWSPROJECT1);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 함수: InitInstance(HINSTANCE, int)
//
// 목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
// 설명:
//
// 이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
// 주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 800, 600, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 목적: 주 창의 메시지를 처리합니다.
//
// WM_COMMAND - 응용 프로그램 메뉴를 처리합니다.
// WM_PAINT - 주 창을 그립니다.
// WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
srand((unsigned)time(NULL));
display = eglGetDisplay(GetDC(hWnd));
eglInitialize(display, NULL, NULL);
eglBindAPI(EGL_OPENVG_API);
EGLint conf_list[] = { EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_NONE };
EGLConfig config;
EGLint num_config;
eglChooseConfig(display, conf_list, &config, 1, &num_config);
surface = eglCreateWindowSurface(display, config, hWnd, NULL);
context = eglCreateContext(display, 0, NULL, NULL);
image1 = vgLoadImage(TEXT("background.png"));
planeImg = vgLoadImage(TEXT("plane.png"));
bulletImg = vgLoadImage(TEXT("bullet.png"));
missileImg = vgLoadImage(TEXT("missile.png"));
enemyImage = vgLoadImage(TEXT("enemyPlane.png"));
plane.y = 320;
for (int i = 0; i<100; i++)
missiles[i].shot = false;
for (int i = 0; i<100; i++) enemies[i].playing = false;
}
break;
case WM_KEYDOWN:
if (wParam == 'X') {
for (int i = 0; i<100; i++) {
if (missiles[i].shot == false) {
missiles[i].shot = true;
missiles[i].x = plane.x;
missiles[i].y = plane.y+15;
break;
}
}
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 메뉴 선택을 구문 분석합니다.
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다.
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
int cx = 0;
int cy = 0;
void timerProc()
{
vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgClear(0, 0, 10000, 10000);
if (cx<0) cx = 0;
cx += 2; //프레임 2씩 스크롤
int k = cx / 800;
vgLoadIdentity();
vgTranslate(k * 800 - cx, 0);
vgDrawImage(image1); //background
vgLoadIdentity();
vgTranslate((k + 1) * 800 - cx, 0);
vgDrawImage(image1); //background
vgLoadIdentity();
vgTranslate(plane.x, plane.y);
vgDrawImage(planeImg);
if (GetAsyncKeyState('Z') & 0x8000)
{
for (int i = 0; i<100; i++) {
if (bullet[i].shot == false) {
bullet[i].shot = true;
bullet[i].x = plane.x + 30;
bullet[i].y = plane.y + 15;
break;
}
}
}
for(int i=0;i<100;i++)
{
if (missiles[i].shot == true) {
vgLoadIdentity();
vgTranslate(missiles[i].x, missiles[i].y);
vgDrawImage(missileImg);
}
}
for (int i = 0; i<100; i++)
{
if (bullet[i].shot == true) {
vgLoadIdentity();
vgTranslate(bullet[i].x, bullet[i].y);
vgDrawImage(bulletImg);
}
}
for (int i = 0; i<100; i++) {
if (enemies[i].playing == true) {
vgLoadIdentity();
vgTranslate(enemies[i].x, enemies[i].y);
vgDrawImage(enemyImage);
}
}
eglSwapBuffers(display, surface);
if (GetAsyncKeyState(VK_LEFT) & 0x8000) plane.x-=10;
if (GetAsyncKeyState(VK_RIGHT) & 0x8000) plane.x+=10;
if (GetAsyncKeyState(VK_UP) & 0x8000) plane.y+=10;
if (GetAsyncKeyState(VK_DOWN) & 0x8000) plane.y-=10;
if (plane.x > 713)
plane.x -= 10;
if (plane.x < 0)
plane.x += 10;
if (plane.y > 490)
plane.y -= 10;
if (plane.y < 0)
plane.y += 10;
for (int i = 0; i<100; i++) {
if (missiles[i].shot == true) {
missiles[i].x += 5;
if (missiles[i].x>700) missiles[i].shot = 0;
}
}
for (int i = 0; i<100; i++) {
if (bullet[i].shot == true) {
bullet[i].x += 15;
if (bullet[i].x>700) bullet[i].shot = 0;
}
}
for (int i = 0; i<100; i++) {
if (enemies[i].playing) {
enemies[i].x -= 5;
if (enemies[i].x<0) enemies[i].playing = false;
}
}
if (rand() % 60 == 0) {
for (int i = 0; i<100; i++) {
if (enemies[i].playing == false) {
enemies[i].playing = true;
enemies[i].x = 1000;
enemies[i].y = rand() % 300 + 100;
enemies[i].type = rand() % 4;
break;
}
}
}
for (int i = 0; i < 100; i++) {
if (enemies[i].playing) {
if (enemies[i].x < plane.x + 80 && plane.x < enemies[i].x + 80 && enemies[i].y < plane.y + 60 && plane.y < enemies[i].y + 60) {
enemies[i].playing = false;
exit(0);
}
for (int j = 0; j < 100; j++) {
if (bullet[j].shot) {
if (bullet[j].x < enemies[i].x + 80 && enemies[i].x < bullet[j].x + 20 && bullet[j].y < enemies[i].y + 60 && enemies[i].y < bullet[j].y + 20) {
enemies[i].playing = false;
bullet[j].shot = false;
}
}
}
}
}
for (int k = 0; k<100; k++)
{
if (enemies[k].playing)
{
enemies[k].x -= 5;
if (enemies[k].x < -78) enemies[k].playing = false;
}
}
}