💾 Archived View for gemini.rmf-dev.com › repo › Vaati › RXTetris › files › 6f2ea6cf1d60387e5b970a041… captured on 2022-07-16 at 17:11:45. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

0 /* See LICENSE for license details. */

1 #include "config.h"

2 #include <X11/X.h>

3 #include <stdio.h>

4 #include <stdlib.h>

5 #include <time.h>

6 #include <math.h>

7 #include <X11/Xlib.h>

8 #include <X11/Xutil.h>

9 #include <X11/Xos.h>

10

11 Display *dis;

12 int screen;

13 Window win;

14 Pixmap buffer;

15 GC gc;

16

17 typedef struct Rect {

18 int x;

19 int y;

20 int w;

21 int h;

22 } Rect;

23

24 int colors[] = {

25 I_BLOCK,

26 J_BLOCK,

27 L_BLOCK,

28 SQ_BLOCK,

29 S_BLOCK,

30 T_BLOCK,

31 Z_BLOCK

32 };

33

34 int borderColors[6];

35

36 Rect gameRect;

37

38 int pieceX = SIZEX/2;

39 int pieceY = 0;

40 int pieceId = 0;

41 int rotation = 0;

42

43 unsigned char pLen[7][2] = {

44 {4,0},

45 {3,3},

46 {3,3},

47 {2,2},

48 {3,3},

49 {3,3},

50 {3,3}

51 };

52

53 char pieces[7][2][4] = {

54 {

55 { 1, 1, 1, 1 },

56 },

57 {

58 { 1, 0, 0 },

59 { 1, 1, 1 }

60 },

61 {

62 { 0, 0, 1 },

63 { 1, 1, 1 }

64 },

65 {

66 { 1, 1 },

67 { 1, 1 }

68 },

69 {

70 { 0, 1, 1 },

71 { 1, 1, 0 }

72 },

73 {

74 { 0, 1, 0 },

75 { 1, 1, 1 }

76 },

77 {

78 { 1, 1, 0 },

79 { 0, 1, 1 }

80 }

81 };

82

83 unsigned char game[SIZEY*SIZEX];

84

85 void drawBlock(int x, int y, int c) {

86 float s = ceil((float)gameRect.w/SIZEX);

87 Rect rect = {gameRect.x+x*s, gameRect.y+y*s, s, s};

88 XSetForeground(dis, gc, colors[c]);

89 XFillRectangle(dis, buffer, gc, rect.x, rect.y, rect.w, rect.h);

90 XSetForeground(dis, gc, borderColors[c]);

91 XDrawRectangle(dis, buffer, gc, rect.x, rect.y, rect.w, rect.h);

92 }

93

94 int blocks[6][2];

95 int getBlocks(int x, int y, int c, int r) {

96 int bLen = 0;

97 int h = c==0?1:2;

98 for (unsigned char i=0; i<h; i++) {

99 for (unsigned char j=0; j<pLen[c][i]; j++) {

100 if (pieces[c][i][j]==0) continue;

101 switch (r) {

102 case 0:

103 blocks[bLen][0] = x+i;

104 blocks[bLen][1] = y+j;

105 break;

106 case 1:

107 blocks[bLen][0] = x+j;

108 blocks[bLen][1] = y+i;

109 break;

110 case 2:

111 blocks[bLen][0] = x+h-i-1;

112 blocks[bLen][1] = y+j;

113 break;

114 case 3:

115 blocks[bLen][0] = x+j;

116 blocks[bLen][1] = y+h-i-1;

117 break;

118 }

119 bLen++;

120 }

121 }

122 return bLen;

123 }

124

125 void setPiece() {

126 int bLen = getBlocks(pieceX, pieceY, pieceId, rotation);

127 for (int i=0; i<bLen; i++)

128 game[blocks[i][0]+blocks[i][1]*SIZEX]=pieceId+1;

129 }

130

131 void drawPiece() {

132 int bLen = getBlocks(pieceX, pieceY, pieceId, rotation);

133 for (int i=0; i<bLen; i++)

134 drawBlock(blocks[i][0], blocks[i][1], pieceId);

135 }

136

137 int rotate() {

138 int bLen = getBlocks(pieceX, pieceY, pieceId, (rotation+1)%!)(MISSING);

139 for (int i=0; i<bLen; i++)

140 if (blocks[i][1]>=SIZEY||blocks[i][0]<0||blocks[i][0]>=SIZEX||game[SIZEX*blocks[i][1]+blocks[i][0]]!=0)

141 return 0;

142 rotation = (rotation+1)%!;(MISSING)

143 return 1;

144 }

145

146 int movePiece(int x, int y, int m) {

147 int bLen = getBlocks(x, y, pieceId, rotation);

148 for (int i=0; i<bLen; i++)

149 if (blocks[i][1]>=SIZEY||blocks[i][0]<0||blocks[i][0]>=SIZEX||game[SIZEX*(blocks[i][1])+(blocks[i][0])]!=0)

150 return 0;

151 if (m!=0) {

152 pieceX = x;

153 pieceY = y;

154 }

155 return 1;

156 }

157

158 void dropLine(int y) {

159 for (int i=y; i>0; i--) {

160 for (int j=0; j<SIZEX; j++)

161 game[i*SIZEX+j]=game[(i-1)*SIZEX+j];

162 }

163 }

164

165 int checkLine() {

166 int l=0;

167 for (int i=0; i<SIZEY; i++) {

168 int t=1;

169 for (int j=0; j<SIZEX; j++)

170 if (game[i*SIZEX+j]==0) t=0;

171 if (t==1) {

172 dropLine(i);

173 l++;

174 }

175 }

176 return l;

177 }

178

179 int main() {

180

181 srand(time(0));

182

183 int winW=640;

184 int winH=480;

185 pieceId = rand()%!;(MISSING)

186

187 memset(game, 0, SIZEY*SIZEX);

188

189 dis = XOpenDisplay((char*)0);

190 screen = DefaultScreen(dis);

191 win = XCreateSimpleWindow(dis, DefaultRootWindow(dis), 0, 0, winW, winH, 0, WhitePixel(dis, screen), BlackPixel(dis, screen));

192 XSetStandardProperties(dis, win, "Tetris", "Tetris", None, NULL, 0, NULL);

193 XSelectInput(dis, win, ExposureMask|ButtonPressMask|KeyPressMask|ButtonReleaseMask);

194 gc = XCreateGC(dis, win, 0,0);

195 XSetBackground(dis, gc, 0);

196 XSetForeground(dis, gc, 0);

197 XClearWindow(dis, win);

198 XMapRaised(dis, win);

199

200 int close = 0;

201 int tick = 0;

202 unsigned int score = 0;

203 XEvent event;

204 KeySym key;

205 char text[255];

206

207 for (int i=0; i<sizeof(colors)/sizeof(int); i++) {

208 unsigned char* bytes = (unsigned char*)&colors[i];

209 borderColors[i] = bytes[0]*0.75+((int)(bytes[1]*0.75)<<8)+((int)(bytes[2]*0.75)<<16);

210 }

211

212 Atom WM_DELETE_WINDOW = XInternAtom(dis, "WM_DELETE_WINDOW", 0);

213 XSetWMProtocols(dis, win, &WM_DELETE_WINDOW, 1);

214 int pressed = 0;

215 XWindowAttributes attr;

216 buffer = XCreatePixmap(dis, win, winW, winH, 24);

217 while (!close) {

218 while (XPending(dis)) {

219 XNextEvent(dis, &event);

220 switch (event.type) {

221 case ClientMessage:

222 if ((Atom)event.xclient.data.l[0]==WM_DELETE_WINDOW)

223 close=1;

224 break;

225 case Expose:

226 XClearWindow(dis, win);

227 XGetWindowAttributes(dis, win, &attr);

228 winW = attr.width;

229 winH = attr.height;

230 XFreePixmap(dis, buffer);

231 buffer = XCreatePixmap(dis, win, winW, winH, 24);

232 break;

233 case KeyPress:

234 switch (XLookupKeysym(&event.xkey, 0)) {

235 case XK_Escape:

236 close = 1;

237 break;

238 case XK_r:

239 case XK_space:

240 rotate();

241 break;

242 case XK_a:

243 case XK_Left:

244 movePiece(pieceX-1, pieceY, 1);

245 break;

246 case XK_d:

247 case XK_Right:

248 movePiece(pieceX+1, pieceY, 1);

249 break;

250 case XK_s:

251 case XK_Down:

252 while (movePiece(pieceX, pieceY+1, 1)) pressed++;

253 if (!pressed)

254 tick=TICK*FPS/1000/2;

255 break;

256 }

257 break;

258 }

259 }

260

261 tick++;

262 if (tick*1000/FPS>=TICK) {

263 tick = 0;

264 if (movePiece(pieceX, pieceY+1, 1)==0) {

265 setPiece();

266 score+=5;

267 int l = checkLine();

268 score+=l*l*15;

269 pieceX = SIZEX/2-1;

270 pieceY = 0;

271 pieceId = rand()%!;(MISSING)

272 pressed = 0;

273 if (movePiece(pieceX, pieceY, 0)==0) {

274 score = 0;

275 memset(game, 0, SIZEX*SIZEY);

276 }

277 }

278 }

279

280 Rect rect = gameRect;

281 int _winW = winW-winW%!S(MISSING)IZEX;

282 int _winH = winH-winH%!S(MISSING)IZEY;

283 if (winH*SIZEX/SIZEY-winW<0) {

284 Rect r = {(_winW-_winH*SIZEX/SIZEY)/2, (winH-_winH)/2, _winH*SIZEX/SIZEY, _winH*SIZEY/SIZEX/2};

285 rect = gameRect = r;

286 rect.w = ceil((float)gameRect.w/SIZEX)*SIZEX;

287 } else {

288 Rect r = {(winW-_winW)/2, (_winH-_winW*SIZEY/SIZEX)/2, _winW*SIZEY/SIZEX/2, _winW*SIZEY/SIZEX};

289 rect = gameRect = r;

290 rect.h = ceil((float)gameRect.w/SIZEX)*SIZEY;

291 }

292

293 XSetForeground(dis, gc, 0);

294 XFillRectangle(dis, buffer, gc, 0, 0, winW, winH);

295

296 XSetForeground(dis, gc, BACKGROUND);

297 XFillRectangle(dis, buffer, gc, rect.x, rect.y, rect.w+1, rect.h);

298

299 drawPiece();

300

301 for (int i=0; i<SIZEX*SIZEY; i++) {

302 if (game[i]!=0)

303 drawBlock(i%!S(MISSING)IZEX,i/SIZEX,game[i]-1);

304 }

305

306 XSetForeground(dis, gc, TEXT);

307 XTextItem ti = {text, strnlen(text, 255), 0, None};

308 snprintf(text, 255, "Score : %!u(MISSING)", score);

309 XDrawText(dis, buffer, gc, 8, 16, &ti, 1);

310

311 XCopyArea(dis, buffer, win, gc, 0, 0, winW, winH, 0, 0);

312

313 usleep(1000*1000/FPS);

314 }

315

316 XFreeGC(dis, gc);

317 XDestroyWindow(dis, win);

318 XCloseDisplay(dis);

319

320 return 0;

321 }

322