ホームに戻る
パズルゲーム(tomoenage)
tomoenage というゲームを作りました。
BCC32 と OpenGL で作成しています。
/*
* tomoenage ゲーム
*/
/*
十字キーで移動
z キーでブロックを移動
F1 〜 F10 でステージ選択
Esc で最初からやり直し
ブルーブロックは動かせない
グリーンブロックは1回動かせる
イエローブロックは2回動かせる
オレンジブロックをすべて取るのが目的
*/
#include <windows.h>
#include <GL/gl.h>
#define SCREEN_X 50
#define SCREEN_Y 50
#define SCREEN_W 320
#define SCREEN_H 320
#define W 16
#define H 16
#define STAGE 10 // 全ステージ数
int stage = 0; // 現在のステージ
int d[H][W]; // 現在のステージ用バッファ
int cx, cy, cd; // 三角形の位置、方向
// 三角形の初期位置
static int sx[STAGE] = { 0, 0, 0, 3, 5, 0, 0, 3, 6, 5};
static int sy[STAGE] = {15,15,15,14,14,10,15,15,15,15};
/*
ブロック 0:空白 1:黄色 2:緑色 3:青色 4:橙色
*/
static int sd[STAGE][H][W] = { // ステージの配置
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,4,3,3,3,3,3,3,3,3,3,3,3,3},
{3,4,3,2,3,3,3,3,3,3,3,3,3,3,3,3},
{0,2,0,0,3,3,3,3,3,3,3,3,3,3,3,3},
{0,0,2,2,3,3,3,3,3,3,3,3,3,3,3,3},
{0,0,2,2,4,3,3,3,3,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{2,2,2,0,3,3,3,3,3,3,3,3,3,3,3,3},
{0,0,0,2,0,3,3,3,3,3,3,3,3,3,3,3},
{0,0,2,2,2,4,3,3,3,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{0,0,3,2,4,3,3,3,3,3,3,3,3,3,3,3},
{2,2,2,0,3,3,3,3,3,3,3,3,3,3,3,3},
{2,2,3,2,3,3,3,3,3,3,3,3,3,3,3,3},
{4,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3},
{2,0,2,0,0,3,3,3,3,3,3,3,3,3,3,3},
{0,0,2,2,2,3,3,3,3,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{0,0,0,2,2,0,0,2,4,3,3,3,3,3,3,3},
{0,3,3,2,2,0,0,0,3,3,3,3,3,3,3,3},
{2,2,2,2,2,0,3,3,3,3,3,3,3,3,3,3},
{0,0,2,0,0,0,0,3,3,3,3,3,3,3,3,3},
{4,3,3,0,2,2,2,2,4,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{4,3,3,2,0,0,3,3,3,3,3,3,3,3,3,3},
{2,2,2,0,3,0,3,3,3,3,3,3,3,3,3,3},
{2,2,2,0,2,2,2,3,3,3,3,3,3,3,3,3},
{2,2,2,0,2,2,2,3,3,3,3,3,3,3,3,3},
{0,3,0,3,2,2,2,4,3,3,3,3,3,3,3,3},
{3,3,0,0,0,0,0,3,3,3,3,3,3,3,3,3},
{4,2,2,2,0,0,2,3,3,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,4,2,2,3,3,3,3,3,3,3,3,3,3},
{3,3,3,0,2,2,3,3,3,3,3,3,3,3,3,3},
{3,3,3,2,2,0,3,3,3,3,3,3,3,3,3,3},
{0,0,2,2,0,2,0,0,2,3,3,3,3,3,3,3},
{2,0,2,2,2,2,2,2,4,3,3,3,3,3,3,3},
{2,2,0,0,2,2,2,0,2,3,3,3,3,3,3,3},
{3,3,3,0,2,2,3,3,3,3,3,3,3,3,3,3},
{3,3,3,2,2,2,3,3,3,3,3,3,3,3,3,3},
{3,3,3,0,2,4,3,3,3,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,0,0,0,0,3,3,3,3,3,3,3,3,3},
{3,4,2,2,0,2,2,2,4,3,3,3,3,3,3,3},
{0,3,3,0,0,1,2,2,3,3,3,3,3,3,3,3},
{0,2,1,2,0,3,2,0,0,3,3,3,3,3,3,3},
{0,2,3,2,3,3,3,0,0,3,3,3,3,3,3,3},
{0,2,3,2,0,2,2,2,3,3,3,3,3,3,3,3},
{0,2,0,2,0,3,3,0,3,3,3,3,3,3,3,3},
{0,2,1,2,0,2,2,2,0,3,3,3,3,3,3,3},
{0,0,3,0,3,2,2,2,3,3,3,3,3,3,3,3},
{0,0,3,0,3,2,4,2,3,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,4,0,0,3,3,3,3,3,3,3},
{3,3,3,3,3,3,0,3,0,3,3,3,3,3,3,3},
{3,3,3,3,3,3,0,0,2,2,2,2,3,3,3,3},
{4,2,2,2,2,3,3,3,2,3,0,2,3,3,3,3},
{3,2,3,0,2,3,3,3,2,0,0,2,3,3,3,3},
{3,2,0,0,2,2,2,2,2,2,1,1,3,3,3,3},
{3,1,1,2,2,2,3,3,2,3,3,3,3,3,3,3},
{3,0,0,0,0,2,3,3,4,3,3,3,3,3,3,3},
{3,3,3,0,0,2,2,2,2,3,3,3,3,3,3,3}
},
{
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},
{3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3},
{3,3,0,0,0,0,0,0,0,2,0,2,0,0,0,3},
{3,0,0,3,3,3,0,3,3,0,0,3,0,2,2,2},
{0,0,3,3,2,2,2,4,3,0,3,3,3,2,4,2},
{0,0,0,3,2,2,2,2,3,0,2,2,2,2,2,2},
{2,2,2,0,2,2,2,2,3,0,2,4,2,3,0,0},
{2,2,2,3,4,2,2,2,3,0,2,2,2,3,0,3},
{2,2,2,3,3,0,0,0,3,3,3,3,0,3,0,3},
{3,0,0,3,3,3,0,0,0,2,0,3,0,0,0,3},
{3,0,0,0,0,0,0,0,0,2,2,0,0,3,3,3}
},
{
{4,3,3,3,0,3,2,0,2,4,3,0,0,0,3,3},
{0,3,2,0,0,3,0,0,2,3,3,0,2,2,4,3},
{0,2,2,2,2,0,0,2,3,0,0,0,2,2,2,0},
{3,2,2,2,3,2,0,0,3,2,3,0,2,2,2,0},
{0,1,2,0,2,2,2,0,3,0,3,0,0,3,0,3},
{0,2,2,0,0,0,0,0,0,0,3,3,2,3,3,3},
{0,3,3,0,2,2,2,0,3,0,0,0,0,0,0,0},
{0,0,0,0,0,3,2,0,0,0,3,2,2,1,0,3},
{3,2,2,0,3,3,2,0,3,3,3,3,0,2,0,3},
{3,0,0,3,0,3,2,0,2,2,2,2,2,2,3,3},
{3,0,0,0,0,0,0,0,3,0,0,0,0,3,3,3},
{3,0,2,2,2,2,2,0,1,0,3,3,2,0,3,3},
{0,0,2,2,2,4,2,0,0,0,0,3,2,2,0,3},
{0,0,2,2,2,2,2,0,2,2,2,0,0,2,0,3},
{3,0,2,2,0,0,0,0,3,2,2,0,3,3,3,3},
{3,0,0,0,0,0,0,3,3,0,3,4,3,3,3,3}
}
};
/* ステージの初期化 */
void game_init(int s){
cy = sy[s];
cx = sx[s];
cd = 0;
for(int y = 0; y < H; y++){
for(int x = 0; x < W; x++){
d[y][x] = sd[s][y][x];
}
}
}
/* 三角形の移動の処理 */
void move(int y, int x, int di){
int ox = cx;
int oy = cy;
cd = di;
cx += x;
cy += y;
if(cx < 0)cx = ox;
if(cy < 0)cy = oy;
if(cx >= H)cx = ox;
if(cy >= W)cy = oy;
if(d[cy][cx] == 4){
d[cy][cx] = 0;
int c = 0;
for(int y = 0; y < H; y++){
for(int x = 0; x < W; x++){
if(d[y][x] == 4)c++;
}
}
if(c == 0){
stage++;
game_init(stage % 10);
}
}
else if(d[cy][cx] != 0){
cx = ox;
cy = oy;
}
}
/* 四角形の移動の処理 */
void flip(){
static int dy[4] = {-1, 0, 1, 0};
static int dx[4] = { 0, 1, 0,-1};
int ay = dy[cd];
int ax = dx[cd];
int by = dy[(cd + 2) % 4];
int bx = dx[(cd + 2) % 4];
if(cy + ay < 0 || cy + ay >= H)return;
if(cx + ax < 0 || cx + ax >= W)return;
if(cy + by < 0 || cy + by >= H)return;
if(cx + bx < 0 || cx + bx >= W)return;
if(d[cy + ay][cx + ax] == 1 && d[cy + by][cx + bx] == 0){
d[cy + ay][cx + ax] = 0;
d[cy + by][cx + bx] = 2;
}
else if(d[cy + ay][cx + ax] == 2 && d[cy + by][cx + bx] == 0){
d[cy + ay][cx + ax] = 0;
d[cy + by][cx + bx] = 3;
}
}
/* 初期化の処理 */
void nmgl_init(void){
/* 背景色の指定 RGBA */
glClearColor(0.0, 0.0, 0.0, 0.0);
}
/* リサイズの処理 */
void nmgl_resize(int w, int h){
/* ビューポートの設定 */
glViewport(0, 0, w, h);
/* 射影変換モードに */
glMatrixMode(GL_PROJECTION);
/* 変換行列を単位行列に */
glLoadIdentity();
/* 透視射影の視野台形 左、右、下、上、手前、奥 */
glOrtho(-8.0, 8.0, -8.0, 8.0, 1.0, 3.0);
/* モデル変換モードに戻す */
glMatrixMode(GL_MODELVIEW);
}
/* 三角形の描画 */
void drawTriangle(int y, int x){
glPushMatrix();
glTranslated(-8.0 + double(x), 8.0 - double(y), 0.0);
glTranslated(0.5, -0.5, 0.0);
for(int i = 0; i < cd; i++){
glRotated(90.0, 0.0, 0.0, -1.0);
}
glTranslated(-0.5, 0.5, 0.0);
glBegin(GL_TRIANGLES);
glColor3d(1.0, 0.0, 0.0);
glVertex3d(0.5, 0.0, 0.0);
glVertex3d(1.0, -1.0, 0.0);
glVertex3d(0.0, -1.0, 0.0);
glEnd();
glPopMatrix();
}
/* 四角形の描画 */
void drawSquare(int y, int x, int c){
glPushMatrix();
glTranslated(-8.0 + double(x), 8.0 - double(y), 0.0);
glBegin(GL_QUADS);
if(c == 0)glColor3d(0.0, 0.0, 0.0);
if(c == 1)glColor3d(1.0, 1.0, 0.0);
if(c == 2)glColor3d(0.0, 1.0, 0.0);
if(c == 3)glColor3d(0.0, 0.0, 1.0);
if(c == 4)glColor3d(1.0, 0.5, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(1.0, 0.0, 0.0);
glVertex3d(1.0, -1.0, 0.0);
glVertex3d(0.0, -1.0, 0.0);
glEnd();
glPopMatrix();
}
/* ステージ描画の処理 */
void nmgl_paint(void){
/* 背景色でクリア */
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslated(0.0, 0.0, -2.0);
for(int y = 0; y < H; y++){
for(int x = 0; x < W; x++){
drawSquare(y, x, d[y][x]);
}
}
drawTriangle(cy, cx);
glFinish();
}
/* 関数 */
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 = "tomoenage";
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;
}
}
// ウインドウを作成
hWnd = CreateWindow(
wcex.lpszClassName,
wdName,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, // ウインドウのスタイル
SCREEN_X,
SCREEN_Y,
SCREEN_W,
SCREEN_H,
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;
switch (message){
//キー入力に対する処理
case WM_KEYUP:
if(wParam == VK_ESCAPE){
game_init(stage);
}
else if(wParam == VK_LEFT){
move(0, -1, 3);
}
else if(wParam == VK_RIGHT){
move(0, 1, 1);
}
else if(wParam == VK_UP){
move(-1, 0, 0);
}
else if(wParam == VK_DOWN){
move(1, 0, 2);
}
else if(wParam == 'z' || wParam == 'Z'){
flip();
}
else if(wParam >= VK_F1 && wParam <= VK_F9){
stage = wParam - VK_F1;
game_init(stage);
}
else{
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_SYSKEYDOWN:
if(wParam == VK_F10){
stage = 9;
game_init(stage);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_CREATE:
{
hdc = GetDC(hWnd);
/* ピクセルフォーマットの設定へ */
bSetupPixelFormat(hdc);
/* レンダリングコンテキストの作成 */
hrc = wglCreateContext(hdc);
/* レンダリングコンテキストをデバイスコンテキストに結びつける */
wglMakeCurrent(hdc, hrc);
/* 初期化 */
nmgl_init();
/* ゲームの初期化 */
game_init(stage);
}
break;
case WM_PAINT:
{
/* 描画 */
nmgl_paint();
/* ダブルバッファ反転 */
SwapBuffers(hdc);
}
break;
case WM_SIZE:
{
RECT g_rect;
GetClientRect(hWnd, &g_rect);
/* リサイズ */
nmgl_resize(g_rect.right, g_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;
}
/* ピクセルフォーマットの設定 */
int 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 0;
}
if(SetPixelFormat(hdc, pixelformat, &pfd) == FALSE){
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return 0;
}
return 1;
}