ホームに戻る
横スクロールアクションゲーム試作
とりあえず動くものを作ってみました。
コード途中に数値を書きすぎています。
BCC32 と OpenGL を使用しています。
左右キーで移動、上キーでジャンプ。
/*
* 横スクロールアクションゲーム
*/
#include <windows.h>
#include <GL/gl.h>
#define SCREEN_WIDTH 512
#define SCREEN_HEIGHT 288
#define BLOCK_WIDTH 16
#define BLOCK_HEIGHT 9
#define ID_MYTIMER 1000
static RECT g_rect;
void nmgl_init(void){
glClearColor(0.0, 0.0, 0.0, 0.0);
}
double scrool_x = 0.0;
double scrool_y = 0.0;
int jx = 0, jy = 32 * 7;
int stage[9][32] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1}
};
void nmgl_resize(int w, int h){
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-256.0, 256.0, -144.0, 144.0, 1.0, 3.0);
glMatrixMode(GL_MODELVIEW);
}
void draw_jiki(int x, int y){
double cx = x - 240;
double cy = -y + 128;
glPushMatrix();
glTranslated(cx, cy, 0.0);
glBegin(GL_QUADS);
glColor3d(0.0, 1.0, 0.0);
glVertex3d(-16.0, 16.0, 0.0);
glVertex3d(-16.0, -16.0, 0.0);
glVertex3d(16.0, -16.0, 0.0);
glVertex3d(16.0, 16.0, 0.0);
glEnd();
glPopMatrix();
}
void draw_block(int x, int y){
double cx = x * 32 - 240;
double cy = -y * 32 + 128;
glPushMatrix();
glTranslated(cx, cy, 0.0);
glBegin(GL_QUADS);
glColor3d(1.0, 0.0, 0.0);
glVertex3d(-16.0, 16.0, 0.0);
glVertex3d(-16.0, -16.0, 0.0);
glVertex3d(16.0, -16.0, 0.0);
glVertex3d(16.0, 16.0, 0.0);
glEnd();
glPopMatrix();
}
void nmgl_paint(void){
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslated(-scrool_x, scrool_y, -2.0);
draw_jiki(jx, jy);
for(int y = 0; y < 9; y++){
for(int x = 0; x < 32; x++){
if(stage[y][x] == 1){
draw_block(x, y);
}
}
}
glFinish();
}
#define ID_TIMER1 100
#define TIMER_BLANK 30 /* msec */
/* Timer1 */
void CALLBACK Timer1(UINT wID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
static int jump_flag = 0;
static int jump_time = 0;
// ジャンプの計算
int d = 0;
if(jump_flag == 1){
int h1 = 100 - (10 - jump_time) * (10 - jump_time);
int h2 = 100 - (10 - (jump_time + 1)) * (10 - (jump_time + 1));
d = h2 - h1;
jump_time++;
jy -= d;
}
// 左に移動
if(GetAsyncKeyState(VK_LEFT)){
if(jx > 0)jx -= 4;
}
// 右に移動
if(GetAsyncKeyState(VK_RIGHT)){
if(jx < 1024 - 64)jx += 4;
}
if(GetAsyncKeyState(VK_UP)){
if(jump_flag == 0){
jump_flag = 1;
jump_time = 0;
}
}
// 床の判定
int flag = 0;
for(int y = 0; y < 9; y++){
for(int x = 0; x < 32; x++){
if(stage[y][x] == 1){
int bx = x * 32;
int by = y * 32;
int cx = jx;
int cy = jy;
if(cx > bx - 32 && cx < bx + 32 && cy < by && cy + 32 > by){
if(jump_flag == 1 && jump_time >= 10){
flag |= 1 << 1;
break;
}
}
}
}
}
// ジャンプ中に床があるとき
if(flag & 1 << 1){
jump_flag = 0;
jump_time = 0;
jy = jy - (jy % 32);
}
// 歩行中に床がないとき
if(flag == 0){
if(jump_flag == 0){
jump_flag = 1;
jump_time = 10;
}
}
// スクロール制御
scrool_x = jx - 256;
if(scrool_x < 0)scrool_x = 0;
if(scrool_x > 512 - 32)scrool_x = 512 - 32;
scrool_y = jy - 32 * 2;
if(scrool_y >= 0)scrool_y = 0;
}
#define ID_THREAD1 1000
typedef struct{
HWND hWnd;
BOOL thread_end;
}DATA, *PDATA;
DWORD WINAPI Thread1(LPVOID data)
{
PDATA pData;
static BOOL th_flag = FALSE;
pData = (PDATA)data;
if(!th_flag){
th_flag = TRUE;
while(!pData->thread_end){
InvalidateRect(pData->hWnd, &g_rect, FALSE);
UpdateWindow(pData->hWnd);
}
}
return (DWORD)0;
}
BOOL bSetupPixelFormat(HDC hdc);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR cmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
char *wdName = "OpenGL on Win32API";
HWND hWnd;
MSG msg;
if(!hPrevInstance){
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = wdName;
wcex.hIconSm = NULL;
if(!RegisterClassEx(&wcex)){
return 0;
}
}
RECT rect;
rect.left = 50;
rect.top = 50;
rect.right = 50 + SCREEN_WIDTH;
rect.bottom = 50 + SCREEN_HEIGHT;
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, FALSE);
hWnd = CreateWindow(
wcex.lpszClassName,
wdName,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, // ウインドウのスタイル
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HDC hdc;
static HGLRC hrc;
static DATA data1;
static HANDLE hThread1;
static TIMECAPS tc;
static unsigned int timer1;
switch (message) {
case WM_CREATE:
{
DWORD thId1;
hdc = GetDC(hWnd);
bSetupPixelFormat(hdc);
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
nmgl_init();
data1.hWnd = hWnd;
data1.thread_end = FALSE;
hThread1 = CreateThread(
NULL, 0,
(LPTHREAD_START_ROUTINE)Thread1,
(LPVOID)&data1, 0, &thId1);
timeGetDevCaps(&tc, sizeof(TIMECAPS));
timeBeginPeriod(tc.wPeriodMin);
timer1 = timeSetEvent(
TIMER_BLANK, tc.wPeriodMin,
(LPTIMECALLBACK)Timer1,
ID_TIMER1, TIME_PERIODIC);
}
break;
case WM_PAINT:
{
nmgl_paint();
SwapBuffers(hdc);
}
break;
case WM_SIZE:
{
RECT rect;
GetClientRect(hWnd, &rect);
nmgl_resize(rect.right, rect.bottom);
}
break;
case WM_DESTROY:
{
wglMakeCurrent(hdc, 0);
wglDeleteContext(hrc);
ReleaseDC(hWnd, hdc);
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL bSetupPixelFormat(HDC hdc)
{
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
1, /* version number */
PFD_DRAW_TO_WINDOW | /* support window */
PFD_SUPPORT_OPENGL | /* support OpenGL */
PFD_DOUBLEBUFFER, /* double buffered */
PFD_TYPE_RGBA, /* RGBA type */
24, /* 24-bit color depth */
0, 0, 0, 0, 0, 0, /* color bits ignored */
0, /* no alpha buffer */
0, /* shift bit ignored */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits ignored */
32, /* 32-bit z-buffer */
0, /* no stencil buffer */
0, /* no auxiliary buffer */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0 /* layer masks ignored */
};
int pixelformat;
if((pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0){
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
return FALSE;
}
if(SetPixelFormat(hdc, pixelformat, &pfd) == FALSE) {
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return FALSE;
}
return TRUE;
}