ホームに戻る
 横スクロールアクションゲーム試作

とりあえず動くものを作ってみました。
コード途中に数値を書きすぎています。
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;
}

inserted by FC2 system