dockapps/wmtetris/wmtetris/wmtetris.c
2017-02-21 11:15:02 +00:00

303 lines
7.6 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/xpm.h>
#include <libdockapp/wmgeneral.h>
#include "wmtetris.xpm"
#include "wmtetris-mask.xbm"
#define TEMPORAL_RESOLUTION 10000
#define INITIAL_DELAY 250000
#define FAST_MODE_DELAY 30000
#define DELAY_INCREMENT 20000
#define BLOCK_SIZE 3
#define BOARD_POS_X 4
#define BOARD_POS_Y 6
#define BOARD_WIDTH 13
#define BOARD_HEIGHT 18
#define NEXT_POS_X 46
#define NEXT_POS_Y 7
#define BUTTONC 6
#define BUTTON_NONE 0
#define BUTTON_ROTATE_LEFT 1
#define BUTTON_ROTATE_RIGHT 2
#define BUTTON_MOVE_LEFT 3
#define BUTTON_MOVE_RIGHT 4
#define BUTTON_MOVE_DOWN 5
static int buttons[6][4] = {
{ 0, 0, 64, 64},
{43, 31, 51, 40},
{52, 31, 60, 40},
{43, 41, 51, 50},
{52, 41, 60, 50},
{43, 51, 60, 60}
};
static int initial_figures[7][4][2] = {
{ {0, 1}, {1, 1}, {2, 1}, {3, 1} },
{ {0, 1}, {1, 1}, {2, 1}, {2, 2} },
{ {0, 2}, {1, 2}, {2, 2}, {2, 1} },
{ {0, 2}, {1, 1}, {1, 2}, {2, 2} },
{ {0, 2}, {1, 2}, {1, 1}, {2, 1} },
{ {0, 1}, {1, 1}, {1, 2}, {2, 2} },
{ {1, 1}, {2, 1}, {1, 2}, {2, 2} }
};
unsigned char board[BOARD_WIDTH][BOARD_HEIGHT];
int score=0;
int which_button(int x, int y);
int rotate_figure(int direction, int figure[4][2], int fig_x, int fig_y);
void draw_figure(int figure[4][2], int type, int x, int y);
void draw_next_figure(int figure[4][2], int type);
void general_draw_figure(int base_x, int base_y, int figure[4][2],
int type, int x, int y);
void full_refresh();
int check_figure_position(int fig_x, int fig_y, int figure[4][2]);
int main(int argc, char *argv[]) {
int i, x, y, step, input, fast_mode, progress,
fig_x, fig_y, new_figure=1, figure_type, next_figure_type;
int figure[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} },
next_figure[4][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
XEvent event;
srand(time(NULL));
for (y = 0; y < BOARD_HEIGHT; y++)
for (x = 0; x < BOARD_WIDTH; x++)
board[x][y] = 0;
openXwindow(argc, argv, wmtetris_xpm, (char *)wmtetris_mask_bits,
wmtetris_mask_width, wmtetris_mask_height);
copyXPMArea(64, 0, 64, 64, 0, 0);
RedrawWindow();
fast_mode=0;
figure_type = random() % 7;
for (i = 0; i < 4; i++) {
figure[i][0] = initial_figures[figure_type][i][0];
figure[i][1] = initial_figures[figure_type][i][1];
}
next_figure_type = random() % 7;
for (i = 0; i < 4; i++) {
next_figure[i][0] = initial_figures[next_figure_type][i][0];
next_figure[i][1] = initial_figures[next_figure_type][i][1];
}
draw_next_figure(next_figure, next_figure_type);
fig_x = BOARD_WIDTH / 2 - 1;
fig_y = 0;
draw_figure(figure, figure_type, fig_x, fig_y);
RedrawWindow();
while (1) {
if (check_figure_position(fig_x, fig_y + 1, figure)) {
new_figure = 0;
draw_figure(figure, -1, fig_x, fig_y);
fig_y++;
} else {
new_figure = 1;
for (i = 0; i < 4; i++) {
board [fig_x + figure[i][0]] [fig_y + figure[i][1]] = figure_type + 1;
}
progress=0;
for (y = 0; y < BOARD_HEIGHT; y++) {
for (x = 0; x < BOARD_WIDTH; x++)
if (!board[x][y])
break;
if (x == BOARD_WIDTH) {
for (i = y; i > 0; i--)
for (x = 0; x < BOARD_WIDTH; x++)
board[x][i] = board[x][i-1];
progress++;
}
}
score += progress*progress;
full_refresh();
i = score;
for (x = 3; x >= 0; x--) {
copyXPMArea(4 * (i % 10), 100, 3, 5, 44 + 4*x, 24);
i /= 10;
}
figure_type = next_figure_type;
next_figure_type = random() % 7;
for (i = 0; i < 4; i++) {
figure[i][0] = next_figure[i][0];
figure[i][1] = next_figure[i][1];
next_figure[i][0] = initial_figures[next_figure_type][i][0];
next_figure[i][1] = initial_figures[next_figure_type][i][1];
}
draw_next_figure(next_figure, next_figure_type);
fig_x = BOARD_WIDTH / 2 - 1;
fig_y = 0;
}
draw_figure(figure, figure_type, fig_x, fig_y);
RedrawWindow();
if (new_figure) {
if (!check_figure_position(fig_x, fig_y, figure)) {
copyXPMArea(64, 64, 23, 15, 12, 24);
RedrawWindow();
while (1) {
XNextEvent(display, &event);
if (event.type == ButtonPress)
break;
if (event.type == Expose)
RedrawWindow();
}
exit(0);
}
}
for (step = 0; step < (fast_mode ? FAST_MODE_DELAY / TEMPORAL_RESOLUTION : INITIAL_DELAY / TEMPORAL_RESOLUTION); step++) {
while (XPending(display)) {
input = 0;
XNextEvent(display, &event);
switch (event.type) {
case ButtonRelease:
fast_mode = 0;
break;
case ButtonPress:
if (!(input =
which_button(event.xbutton.x, event.xbutton.y))) {
/*
switch (event.xbutton.button) {
case 1:
input = BUTTON_MOVE_LEFT;
break;
case 3:
input = BUTTON_MOVE_RIGHT;
break;
case 2:
input = BUTTON_ROTATE_RIGHT;
break;
}
*/
}
}
if (input) {
draw_figure(figure, -1, fig_x, fig_y);
switch (input) {
case BUTTON_ROTATE_LEFT:
rotate_figure(0, figure, fig_x, fig_y);
break;
case BUTTON_ROTATE_RIGHT:
rotate_figure(1, figure, fig_x, fig_y);
break;
case BUTTON_MOVE_LEFT:
if (check_figure_position(fig_x - 1, fig_y, figure))
fig_x--;
break;
case BUTTON_MOVE_RIGHT:
if (check_figure_position(fig_x + 1, fig_y, figure))
fig_x++;
break;
case BUTTON_MOVE_DOWN:
fast_mode = 1;
break;
}
draw_figure(figure, figure_type, fig_x, fig_y);
RedrawWindow();
}
}
usleep(TEMPORAL_RESOLUTION);
}
}
}
int which_button(int x, int y) {
int i;
for (i = BUTTONC - 1; i >= 0; i--) {
if ((buttons[i][0] <= x && x < buttons[i][2]) &&
(buttons[i][1] <= y && y < buttons[i][3]))
break;
}
return i;
}
int rotate_figure(int direction, int figure[4][2], int fig_x, int fig_y) {
int i, temp[4][2];
for (i = 0; i < 4; i++) {
temp[i][0] = direction ? 3 - figure[i][1] : figure[i][1];
temp[i][1] = direction ? figure[i][0] : 3 - figure[i][0];
}
if (check_figure_position(fig_x, fig_y, temp)) {
for (i = 0; i < 4; i++) {
figure[i][0] = temp[i][0];
figure[i][1] = temp[i][1];
}
return 1;
} else {
return 0;
}
}
void draw_figure(int figure[4][2], int type, int x, int y) {
general_draw_figure(BOARD_POS_X, BOARD_POS_Y, figure, type, x, y);
}
void draw_next_figure(int figure[4][2], int type) {
copyXPMArea(64 + NEXT_POS_X, NEXT_POS_Y, BLOCK_SIZE * 4, BLOCK_SIZE * 4,
NEXT_POS_X, NEXT_POS_Y);
general_draw_figure(NEXT_POS_X, NEXT_POS_Y, figure, type, 0, 0);
}
void general_draw_figure(int base_x, int base_y, int figure[4][2],
int type, int x, int y)
{
int i, block_x, block_y;
for (i = 0; i < 4; i++) {
block_x = base_x + BLOCK_SIZE * (x + figure[i][0]);
block_y = base_y + BLOCK_SIZE * (y + figure[i][1]);
if (type == -1)
copyXPMArea(64 + block_x, block_y, BLOCK_SIZE, BLOCK_SIZE, block_x, block_y);
else
copyXPMArea(0, 64 + BLOCK_SIZE * type, BLOCK_SIZE, BLOCK_SIZE, block_x, block_y);
}
}
void full_refresh() {
int x, y;
for (y = 0; y < BOARD_HEIGHT; y++)
for (x = 0; x < BOARD_WIDTH; x++)
if (board[x][y])
copyXPMArea(0, 64 + BLOCK_SIZE * (board[x][y] - 1), BLOCK_SIZE, BLOCK_SIZE,
BOARD_POS_X + BLOCK_SIZE * x, BOARD_POS_Y + BLOCK_SIZE * y);
else
copyXPMArea(64 + BOARD_POS_X + BLOCK_SIZE * x, BOARD_POS_Y + BLOCK_SIZE * y,
BLOCK_SIZE, BLOCK_SIZE,
BOARD_POS_X + BLOCK_SIZE * x, BOARD_POS_Y + BLOCK_SIZE * y);
}
int check_figure_position(int fig_x, int fig_y, int figure[4][2]) {
int i, x, y;
for (i = 0; i < 4; i++) {
x = fig_x + figure[i][0];
y = fig_y + figure[i][1];
if ((x < 0) || (x >= BOARD_WIDTH) || (y < 0) || (y >= BOARD_HEIGHT))
return 0;
if (board[x][y])
return 0;
}
return 1;
}