From d2576412a5b366e1fd99d8b1c6b1d5bb855be7f2 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Mon, 24 May 2021 19:54:20 +0300 Subject: [PATCH] arcanoid is in work --- F0-nolib/blink/blink.bin | Bin 1256 -> 1160 bytes F1-nolib/Tetris/Readme | 11 +- F1-nolib/Tetris/TETRIS.bin | Bin 20136 -> 25460 bytes F1-nolib/Tetris/arkanoid.c | 631 ++++++++++++++++++++++++++++++++++++ F1-nolib/Tetris/arkanoid.h | 25 ++ F1-nolib/Tetris/buttons.c | 2 +- F1-nolib/Tetris/fontNumb8.h | 64 +--- F1-nolib/Tetris/main.c | 12 + F1-nolib/Tetris/menu.c | 9 +- F1-nolib/Tetris/menu.h | 1 + F1-nolib/Tetris/screen.c | 2 +- F1-nolib/Tetris/screen.h | 3 + 12 files changed, 691 insertions(+), 69 deletions(-) mode change 100755 => 100644 F0-nolib/blink/blink.bin create mode 100644 F1-nolib/Tetris/arkanoid.c create mode 100644 F1-nolib/Tetris/arkanoid.h diff --git a/F0-nolib/blink/blink.bin b/F0-nolib/blink/blink.bin old mode 100755 new mode 100644 index af5480bf7ec204e3ee862892243add3369b7aac3..40e69e2145bf7a3feea5e929cb7c8cdd7ecd1660 GIT binary patch delta 662 zcmaFC*}*BmAiOkf?Wirk-_kR^=FVZYB|4bV!6biC3ff%G%H wWq1HgMhYO@0W=##0|^BNC1;Lqr;^LeoZU|GmzlY`om?(6b9Zl^&+N$v0Hj5{p#T5? delta 736 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 delta 4241 zcmb_f3vg7`89wLk5-x!(n+Fh>=Lu4EM2SraV^8Ep9tF-luDQ!%APr5hF+n0>opA@qV#nKOwqSa6! zElG-vhCHb@DLM^#3j>gL0G*sEUFg|85@Vn0S>L9{DGqRz5>u8>dUdE%$CPdK+-&Si zcjeZa-Ap~6Wa?j&T%91!8>Xa_CsMVu-h%O2oZlv97^`xYC6-0?bD64Rx*7*Y$w*T| zJY;lnNgOdc`LHO=tec%OOC=D!n9Qk*!C!jhBM&<`MoWqkr6eengNtV~5A*Y4P1aOH z09ld~oDXH2B%aKgiB*VqvrN?eBddVA^z4GPlQ=vMCd#u-61w{ALsEw%vT}N;JCswN z-T@yrCfVC1k;rLW^3;BIfaw{gDVmMrc9Jkir21?RugG?L7qJ5r`r6ObCZ;rch^t$Z0W92IiKua?x{XA{=Rg3tJ~yxQ9M6k{+M4nO`aXPh41eapG~-hKOh!O ztQft{>2<7Y_>tH&F@MHd=h{ZoZOO>C3tVl9H=SkGYn&&dgO355*0|O*oQMwWHQiR> z`DjY-xtK5g$Q|OniBo;g`je5H;+;`u(_3?ooj9da=gnGCt792o>bPD>M&67od!LEw zY&t7b`~8c~*cLa{Rd~jDR+vOJJF~~n)tS~x}-(Yr>m!+4k9xU~k z-9{6$Slm6sK66!lwWHW=b#rxbd{>yMAIF)`^2rcWuRpIh2av)skmsU0%iBnVsW(=X z7F|liA7_?74W<%#YiNdpt25%T2qq&>#hLnE^o=lA2hTIhtMHa}(c9jz1-kq=S682x zH2=?qr-I3Wg(c24#9%k_I1bqpBRWmCCG0b2Ijn94NBA9t znSa*xGFR0RM>rX|@4~7uGfH;Gl2P_g7GjEIH-=bf{$$RW%}y5wRaj&N$#MM!Q*v?`oRFBzF|ft!)K zZF-m;(8Do~Ru#wg<;USi{dYCEriL!;KPB6fkv#{9xAo<_wsdEFIhsq#)V5?~`$#TM$7mb3UNcCn z4k5RUbpFBI_DnS&Oh!bK*im5HE-EGKc<@h*j8b&nw*9bG%x%0hJS5Gr{_PmA_^8M1 z{YzMBqle};W<5H{Z!mj@!W7)tM{8LYGrB_PTd}59FJ`-LFz_3o z1l4slFnJi`lfbo@e~z9`;(GKRpdIi6e&8%HQYUs56jzfecjkKNn`TRmy)>@5V!RUJ z^!1~hnQgjr>~>w07mDf&L*7NCxk)b!g(j&*FG>pwa$3O9S5aTPrQ2AWQJajU#l*_O zZUgNu$;lP8CZ&dN6}KwOrR((KbtO+edftNLm>CnFD6MtZK{yLo2#`m51LvZ50F)zr zkELS0Q(u?s(K}_g$(xM4cp&vnCLP&V;+Nn(VpCD!T=GKRh^5!6`iybI=I#^G7JqgV z5Ak_lv*3=Gt3FLTq+@z#ySTbGD*C+Ukk7VjKW&-#hg zf&FcYRd^{=M{OdOfqhauXP!{?=oQaKGz&eRZB1HIes17a`w@}8HvZu_KU0e|zDq0<_@(w4Hk2KtF z9L9=H0q+b93`Eh(;Ay3EsRxz;RGAjo*lH7zk43{Z)A?KCXV-`V@=HYz1^iLbXD#9{^nPf)mHXa}F^g-ct|{ZoN!q3! ziqQd>q#c0On`oOqj7b*V&`(q@)jLgY(owXYD|D_+#JmZe{y>#8SJTiT2*&6TkT3m# zx%Jr^PluobG3TGnd>PL~-?hJ9dTDd-L$0(oTJHez9R{dmr_iSg%M=9#rZsw?X#*a> zvm9`Df$PAS>ZPJLHi$jtC;2fUroTUL_Z1HMF>a<^0<^-Qr(#jj>=@4iEWj(!QINF_ z;ssk{fd@5YE18`u_OBjYr>oP|%ihO4W9ub$+iqpJM%#UO&`&wM2kPqe5ham)8i$04W}|W6S!nS&S15nVs;u)fsEdsic+5T z3dTn>#HX|Vn07Z581A}mgLE{bw|Mp!d=5Dy#UOg-X7;1#*JHjGQu4AJ>*@yvfdODE zpl@Wdt+BVhaxpiNp6p3W?#bVhQYNoAh~Hn|iZCK;PBnE)=gj;5_IM(!T}dFM3;rxP zqP`!-#!SXWrsF$~`>j!tSZE<`AvH`MJ5~}!Hy8Cr?e9$#(W(qz8uK0tpdIrvmd4yc zg&MBh-~%#D?b=wCWv?vDDr2KrZmz}Q7?EYhMlsdz4;hWP4{3V83P>afp6fKYpoN(z(Ftg?nyP*X{PL+xM#?I9XR zu?2oV?u|4KXcPZs{nIHu#Hce>TF*jA7!9`Argk4yq8owJSfD)^YKLPQQ>c_vnQcC_ zYuAp=n>TBk!-u=NIy*Iu+8OA?{%gTf+qcY?2V0E~ws(@=-R^hWx;)~Xqy=5y7 zN>Z63zPM$gDS$7RA7}^KfKH$b2s(QUR(-&CtafD4pMODo*lAyBE9837y4v(Fk4fLg diff --git a/F1-nolib/Tetris/arkanoid.c b/F1-nolib/Tetris/arkanoid.c new file mode 100644 index 0000000..98cb9f0 --- /dev/null +++ b/F1-nolib/Tetris/arkanoid.c @@ -0,0 +1,631 @@ +/* + * This file is part of the TETRIS project. + * Copyright 2021 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "adcrandom.h" +#include "arkanoid.h" +#include "buttons.h" +#include "debug.h" +#include "fonts.h" +#include "proto.h" +#include "screen.h" + +// fraction of 1 for fixed point +#define FIXPOINT (1000) + +// time (in ms) for keeping racket old X speed +#define KEEPXSPEEDTIME (300) + +// max amount of balls +#define NBALLSMAX (8) +// fixed point macros: +// int to fixed +#define i2fixed(x) ((x)*FIXPOINT) +// fixed to int +#define fixed2i(x) ((x)/FIXPOINT) + +// field parameters (should be multiple of BRICK_WIDTH) +#define FIELD_WIDTH (39) +// bottom height +#define FIELD_BOTTOM (12) +// X coordinate of field start +#define X0 (1) +// active zone (with bricks) +#define FIELD_ACTIVE (SCREEN_HEIGHT - FIELD_BOTTOM) +// Y-coordinate of racket +#define RACKET_Y (SCREEN_HEIGHT - 2) +// floor (should be seen when bonus activates) +#define FLOOR_Y (SCREEN_HEIGHT - 1) + +// starting Y speed of the ball +#define BALL_NORMAL_SPEED (0.007 * FIXPOINT) +#define BALL_MIN_Y_SPEED (0.005 * FIXPOINT) +// maximal speed of the ball +#define BALL_MAX_X_SPEED (0.015 * FIXPOINT) +#define BALL_MAX_Y_SPEED (0.010 * FIXPOINT) +// racket speed delta per millisecond +#define D_RACKET_SPEED (0.002 * FIXPOINT) + +// part of racket's speed to add to ball's speed (1/frac) +#define XSPDFRAC (200) +#define YSPDFRAC (1000) + +#define BRICK_WIDTH (3) + +// colors +#define BACKGROUND_COLOR (COLOR_BLACK) +#define FOREGROUND_COLOR (COLOR_LYELLOW) +#define CUP_COLOR (COLOR_LRED) +#define RACKET_COLOR (COLOR_LGREEN) +#define BALL_COLOR (COLOR_GREEN) + +// racket widths +#define RACKET_MEDIUM (5) +#define RACKET_NARROW (3) +#define RACKET_WIDE (9) + +// starting amount of lives +#define LIVES_AT_START (3) + +// probability of bonus appears (percent) +#define BONUS_PROBABILITY (35) + +// there's a bonus inside this brick +#define BRICK_IS_BONUS (1<<7) +// and there's another free flag @ 1<<6 + reserved @ 1<<5 +// mask to get color from brick type +#define COLOR_MASK (0x3f) +typedef enum{ // brick types + BRICK_NONE = 0, // no brick + BRICK_WALL, // non-breakable brick + BRICK_GRAY, // two bricks without bonuses + BRICK_WHITE, + BRICK_FLOOR, // add floor under the racket + BRICK_ENLARGE, // enlarge the rocket (don't forget to move it's center when positioned at the edge) + BRICK_CATCH, // sticky balls + BRICK_SLOW, // slow ball + BRICK_DISRUPTION // each ball divides to three +} bricktype; + +static const uint8_t brickcolors[] = { + [BRICK_NONE] = 0, + [BRICK_WALL] = CUP_COLOR, + [BRICK_GRAY] = 0b00100101, + [BRICK_WHITE] = COLOR_WHITE, + [BRICK_FLOOR] = COLOR_LBLUE, + [BRICK_ENLARGE] = COLOR_LGREEN, + [BRICK_CATCH] = COLOR_LCYAN, + [BRICK_SLOW] = COLOR_LYELLOW, + [BRICK_DISRUPTION] = COLOR_LPURPLE, +}; + +// empty cell +#define ____ (0) +// simple bricks with no bonuses +#define _VV_ (BRICK_GRAY) +#define _WW_ (BRICK_WHITE) +// bricks with bonuses +#define _FL_ (BRICK_FLOOR) +#define _EN_ (BRICK_ENLARGE) +#define _CA_ (BRICK_CATCH) +#define _SL_ (BRICK_SLOW) +#define _DI_ (BRICK_DISRUPTION) +// wall +#define XXXX (BRICK_WALL) + +#define FIELD_SZ (FIELD_ACTIVE * FIELD_WIDTH / BRICK_WIDTH) + +#define LEVELS_AMOUNT (3) + +// empty level +#if 0 +static uint8_t levelX[FIELD_SZ] = { +/*00*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*01*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*02*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*03*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*04*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*05*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*06*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*07*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*08*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*09*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*10*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*11*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*12*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*13*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*14*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*15*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*16*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*17*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*18*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*19*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +}; +#endif + +static uint8_t level1[FIELD_SZ] = { +/*00*/ _VV_,____,____,____,____,_WW_,____,_WW_,____,____,____,____,_VV_, +/*01*/ ____,_VV_,____,____,____,____,_WW_,____,____,____,____,_VV_,____, +/*02*/ ____,____,_VV_,____,____,____,____,____,____,____,_VV_,____,____, +/*03*/ ____,_SL_,____,_VV_,____,____,____,____,____,_VV_,____,_SL_,____, +/*04*/ ____,____,____,____,_VV_,_DI_,_DI_,_DI_,_VV_,____,____,____,____, +/*05*/ ____,____,____,____,____,_VV_,_DI_,_VV_,____,____,____,____,____, +/*06*/ ____,____,____,____,_EN_,____,_VV_,____,_EN_,____,____,____,____, +/*07*/ ____,____,____,____,____,_CA_,_FL_,_CA_,____,____,____,____,____, +/*08*/ ____,____,____,____,____,____,_CA_,____,____,____,____,____,____, +/*09*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*10*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*11*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*12*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*13*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*14*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*15*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*16*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*17*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*18*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*19*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +}; +static uint8_t level2[FIELD_SZ] = { +/*00*/ ____,____,____,_WW_,____,_WW_,____,_WW_,____,_WW_,____,____,____, +/*01*/ ____,____,_WW_,_VV_,____,____,_WW_,____,____,_VV_,_WW_,____,____, +/*02*/ ____,_WW_,_WW_,____,_VV_,____,____,____,_VV_,____,_WW_,_WW_,____, +/*03*/ _WW_,____,____,_WW_,____,_VV_,____,_VV_,____,_WW_,____,____,_WW_, +/*04*/ ____,____,_VV_,____,_WW_,____,_VV_,____,_WW_,____,_VV_,____,____, +/*05*/ ____,____,____,____,____,_WW_,____,_WW_,____,____,____,____,____, +/*06*/ ____,____,____,____,____,____,_WW_,____,____,____,____,____,____, +/*07*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*08*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*09*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*10*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*11*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*12*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*13*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*14*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*15*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*16*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*17*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*18*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*19*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +}; +static uint8_t level3[FIELD_SZ] = { // w=13, h=20 +/*00*/ _WW_,_VV_,_WW_,____,____,_VV_,____,____,____,____,_VV_,____,____, +/*01*/ _VV_,_WW_,_VV_,____,_VV_,____,_VV_,____,____,____,_VV_,____,____, +/*02*/ ____,____,_WW_,_VV_,____,____,____,_VV_,____,____,_VV_,____,____, +/*03*/ ____,____,____,_WW_,_VV_,____,____,____,_VV_,____,_VV_,____,_VV_, +/*04*/ ____,____,____,____,_WW_,_VV_,____,____,____,_VV_,_VV_,_VV_,____, +/*05*/ ____,____,_WW_,____,____,_WW_,_VV_,____,____,____,_VV_,_WW_,_WW_, +/*06*/ ____,____,____,____,____,____,_WW_,_VV_,____,____,_VV_,____,____, +/*07*/ ____,____,____,_WW_,_WW_,_WW_,_WW_,_WW_,_VV_,____,_VV_,____,_VV_, +/*08*/ ____,____,____,____,____,____,____,____,_WW_,_VV_,_VV_,_VV_,_WW_, +/*09*/ ____,____,_VV_,____,____,____,____,____,____,_WW_,_VV_,_WW_,____, +/*10*/ ____,____,_VV_,_VV_,_VV_,_VV_,_VV_,_VV_,_VV_,_VV_,_VV_,_VV_,_VV_, +/*11*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*12*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*13*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*14*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*15*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*16*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*17*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*18*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +/*19*/ ____,____,____,____,____,____,____,____,____,____,____,____,____, +}; +static uint8_t *levels[LEVELS_AMOUNT] = {level1, level2, level3}; +static uint8_t currentLevel[FIELD_SZ]; // data of current level's bricks +static uint8_t paused = 0; + +// flags for theball.flags +#define ACTIVE_BALL (1<<0) +#define STICKY_BALL (1<<1) + +// !!! BALL AND RACKET COORDINATES ARE IN FIELD SYSTEM !!! +typedef struct{ // all coordinates and speeds are fixed point + int x; int y; // old/actual center coordinates + int xspeed; int yspeed; // speed + uint8_t flags; +} theball; + +extern uint32_t volatile Tms; + +// current balls amount (level ends when last ball falls) +static uint8_t Nballs; +static theball balls[NBALLSMAX]; +static uint8_t racketW; // current racket width +// all coordinates and speeds are fixed point +static int racketX; +static int racketspeed, oldracketspeed; +// level number +static uint8_t curLevNo; +// lifes amount +static uint16_t Nlives; +// total bricks amount +static uint16_t Nbricks; + +// bonuses +static uint8_t floor_activated; // ==1 if floor is active + +static void showText(){ // show score/level etc + int y = curfont->height - curfont->baseline; + PutStringAt(X0+FIELD_WIDTH+2, y, " "); + PutStringAt(X0+FIELD_WIDTH+2, y, u2str(score)); + y += curfont->height; + int w = PutStringAt(X0+FIELD_WIDTH+2, y, u2str(Nlives)); + PutStringAt(X0+FIELD_WIDTH+2+w, y, "L "); + y += curfont->height; + if(paused){ + PutStringAt(X0+FIELD_WIDTH+2, y, "PAUSE"); + }else + PutStringAt(X0+FIELD_WIDTH+2, y, " "); +} + +#ifdef EBUG +static void showcur(){ + uint8_t *targ = currentLevel; + const char *brk; + for(int y = 0; y < FIELD_ACTIVE; ++y){ + for(int x = 0; x < (FIELD_WIDTH / BRICK_WIDTH); ++x){ + uint8_t b = *targ++; + switch(b & COLOR_MASK){ + case 0: + brk = "___"; + break; + case 1: + brk = "XXX"; + break; + case 2: + brk = "_VV"; + break; + case 3: + brk = "_WW"; + break; + case 4: + brk = "_FL"; + break; + case 5: + brk = "_EN"; + break; + case 6: + brk = "_CA"; + break; + case 7: + brk = "_SL"; + break; + case 8: + brk = "_DI"; + break; + default: + brk = "????"; + break; + } + USB_send(brk); + if(b & BRICK_IS_BONUS) USB_send("+"); + else USB_send("_"); + USB_send(" "); + } + USB_send("\n"); + } +} +#else +#define showcur() +#endif + +static void draw_level(){ + if(curLevNo > LEVELS_AMOUNT) curLevNo = LEVELS_AMOUNT; + uint8_t *brickz = levels[curLevNo], *targ = currentLevel; + for(int y = 0; y < FIELD_ACTIVE; ++y){ + for(int x = 0; x < (FIELD_WIDTH / BRICK_WIDTH); ++x){ + uint8_t cur = *brickz++, curcol = cur & COLOR_MASK; + if((curcol > BRICK_WHITE) && getRand() % 100 < BONUS_PROBABILITY) cur |= BRICK_IS_BONUS; + *targ++ = cur; // copy brick data into level + if(!cur) continue; + uint8_t curclolr = brickcolors[curcol]; + int X = X0 + x*BRICK_WIDTH; + DrawPix(X+0, y, curclolr); + DrawPix(X+1, y, curclolr); + DrawPix(X+2, y, curclolr); + DBG("Brick "); DBGU(cur); DBG(" @ "); DBGU(x); DBG(" , "); DBGU(y); NL(); + if(cur != BRICK_WALL) ++Nbricks; + } + } + showcur(); + for(int y = 0; y < SCREEN_HEIGHT; ++y){ + DrawPix(X0-1, y, CUP_COLOR); + DrawPix(X0+FIELD_WIDTH, y, CUP_COLOR); + } + showText(); +} + +// x is pixel coordinate in field system +static void draw_racket(int x, uint8_t color){ + int xl = X0 + x - racketW / 2; + for(int i = 0; i < racketW; ++i){ + DrawPix(xl + i, RACKET_Y, color); + } + //DBG("Racket @"); DBGU(x); DBG(" colr "); DBGU(color); DBG(" spd "); DBGU(racketspeed); NL(); +} + +static void process_racket(int dt){ + if(!racketspeed) return; + oldracketspeed = racketspeed; + int xnew = racketX + racketspeed * dt; + int X = fixed2i(xnew), Xo = fixed2i(racketX); + if(X == Xo){ + racketX = xnew; + return; + } + int xmax = FIELD_WIDTH - 1 - racketW/2; + if(X < racketW/2){ + X = racketW/2; + xnew = i2fixed(X); + racketspeed = 0; + //DBG("Left border\n"); + }else if(X > xmax){ + X = xmax; + xnew = i2fixed(X); + racketspeed = 0; + //DBG("Right border\n"); + }else{ + draw_racket(Xo, BACKGROUND_COLOR); // clear racket + draw_racket(X, RACKET_COLOR); + } + racketX = xnew; +} + +static void startlevl(){ + racketW = RACKET_MEDIUM; + DBG("wid: "); DBGU(racketW); NL(); + racketX = i2fixed(FIELD_WIDTH / 2); + racketspeed = 0; + oldracketspeed = 0; + floor_activated = 0; + Nballs = 1; + for(int i = 1; i < NBALLSMAX; ++i) balls[i].flags = 0; + int rx = fixed2i(racketX); + balls[0] = (theball){.x = racketX, .y = i2fixed(RACKET_Y-1), .flags = STICKY_BALL|ACTIVE_BALL}; + draw_racket(rx, RACKET_COLOR); + DrawPix(X0+rx, RACKET_Y-1, BALL_COLOR); + Tlast = Tms; + showText(); // refresh Nlives text + clear_events(); +} + +// The ball gets the active field cell? +// @return 0 if ball falled out +static int process_ball(theball *ball, int dt){ // dt is time since last check, ms + if(ball->flags & STICKY_BALL){ // ball follows the racket + int Xold = fixed2i(ball->x), Xnew = fixed2i(racketX); + ball->y = i2fixed(RACKET_Y - 1); + ball->x = racketX; + if(Xold != Xnew){ // redraw ball + DrawPix(X0 + Xold, RACKET_Y - 1, BACKGROUND_COLOR); + DrawPix(X0 + Xnew, RACKET_Y - 1, BALL_COLOR); + } + return 1; + } + int DX = ball->xspeed * dt, DY = ball->yspeed * dt; + int xnew = ball->x + DX; + int ynew = ball->y + DY; + // get integer coordinates (in field's system!) + int X = fixed2i(xnew), Y = fixed2i(ynew); + int Xo = fixed2i(ball->x), Yo = fixed2i(ball->y); + if(Xo == X && Yo == Y){ // still the old cell + ball->x = xnew; + ball->y = ynew; + return 1; + } + // ball is in new cell; delete old + DrawPix(X0 + Xo, Yo, BACKGROUND_COLOR); + //DBG("Del ball @ "); DBGU(Xo); DBG(", "); DBGU(Yo); NL(); + if(X < 0){ // left border + DBG("Ball: left border\n"); + xnew = DX; X = 0; + ball->xspeed = -ball->xspeed; + }else if(X > FIELD_WIDTH - 1){ // right border + DBG("Ball: right border\n"); + X = FIELD_WIDTH-1; + xnew = i2fixed(FIELD_WIDTH) - DX; + ball->xspeed = -ball->xspeed; + }else if(Y < 0){ // upper border + DBG("Ball: upper border\n"); + ynew = DY; Y = 0; + ball->yspeed = -ball->yspeed; + }else if(Y > RACKET_Y){ // fall into the depth + if(!floor_activated){ + DBG("Ball: drop down\n"); + return 0; + } + ynew = i2fixed(RACKET_Y) - DY; Y = RACKET_Y; + ball->yspeed = -ball->yspeed; + DBG("Ball: floor\n"); + }else if(Y == RACKET_Y){ // check the racket + DBG("check the racket\n"); + int w2 = i2fixed(racketW) / 2; + if(xnew >= racketX - w2 && xnew <= racketX + w2){ // got the racket + int absrs = (oldracketspeed > 0) ? oldracketspeed : -oldracketspeed; + ynew = i2fixed(RACKET_Y) - DY; Y = RACKET_Y - 1; + ball->xspeed += oldracketspeed / XSPDFRAC; + if(ball->xspeed > BALL_MAX_X_SPEED) ball->xspeed = BALL_MAX_X_SPEED; + else if(ball->xspeed < -BALL_MAX_X_SPEED) ball->xspeed = -BALL_MAX_X_SPEED; + if(absrs){ + ball->yspeed += absrs/YSPDFRAC; + if(ball->yspeed > BALL_MAX_Y_SPEED) ball->yspeed = BALL_MAX_Y_SPEED; + }/* else{ + --ball->yspeed; + if(ball->yspeed < BALL_MIN_Y_SPEED) ball->yspeed = BALL_MIN_Y_SPEED; + }*/ + DBG("Ball: got racket, racketspeed="); DBGU(absrs); + DBG(" ballspeed: "); DBGU(ball->xspeed); DBG(", "); DBGU(ball->yspeed); NL(); + ball->yspeed = -ball->yspeed; // change ball direction + } + }else if(Y < FIELD_ACTIVE){ // ball is in brick zone, check hits + int idx = (FIELD_WIDTH * Y + X) / BRICK_WIDTH; + uint8_t cur = currentLevel[idx]; + if(cur){ + DBG("brick y="); DBGU(Y); DBG(", x="); DBGU(X); DBG(", idx="); DBGU(idx); DBG(", cur="); DBGU(cur); NL(); + /* + * Ball hits the brick, process this + * TODO: DONT FORGET ABOUT BONUSES!!! + */ + if(cur != BRICK_WALL){ // brick can be broken + // delete brick + DBG("Now delete ["); DBGU(idx); DBG("]="); DBGU(currentLevel[idx]); NL(); + currentLevel[idx] = 0; + //showcur(); + int sX = X/BRICK_WIDTH; sX *= BRICK_WIDTH; sX += X0; + DBG("sx="); DBGU(sX); NL(); + DrawPix(sX+0, Y, BACKGROUND_COLOR); + DrawPix(sX+1, Y, BACKGROUND_COLOR); + DrawPix(sX+2, Y, BACKGROUND_COLOR); + /* process bonuses here */ + score += (cur & COLOR_MASK) + 1; + if(--Nbricks == 0){ + if(++curLevNo >= LEVELS_AMOUNT){ + DBG("No more levels, you win!\n"); + return 0; // no more levels + } + // init next level + ClearScreen(); + draw_level(); + startlevl(); + return 1; + } + showText(); + } + // check from which side the ball came and change direction + if(Xo != X && Yo == Y) ball->xspeed = -ball->xspeed; + else if(Yo != Y && Xo == X) ball->yspeed = -ball->yspeed; + else{ball->xspeed = -ball->xspeed; ball->yspeed = -ball->yspeed; } + X = Xo; Y = Yo; xnew = ball->x; ynew = ball->y; + } + } + ball->x = xnew; ball->y = ynew; + DrawPix(X0 + X, Y, BALL_COLOR); + //DBG("Draw ball @ "); DBGU(X); DBG(", "); DBGU(Y); NL(); + return 1; +} + +static void fire_a_balls(){ // run sticked balls + for(int i = 0; i < NBALLSMAX; ++i){ + if(balls[i].flags & STICKY_BALL){ // this ball is alive + DBG("run a ball, racket speed = "); DBGU(oldracketspeed); NL(); + balls[i].flags &= ~STICKY_BALL; + balls[i].xspeed = oldracketspeed / XSPDFRAC; + int absrs = (oldracketspeed > 0) ? oldracketspeed : -oldracketspeed; + balls[i].yspeed = -BALL_NORMAL_SPEED - absrs/YSPDFRAC; + if(balls[i].yspeed < -BALL_MAX_Y_SPEED) balls[i].yspeed = -BALL_MAX_Y_SPEED; + if(balls[i].xspeed > BALL_MAX_X_SPEED) balls[i].xspeed = BALL_MAX_X_SPEED; + else if(balls[i].xspeed < -BALL_MAX_X_SPEED) balls[i].xspeed = -BALL_MAX_X_SPEED; + } + } +} + +void arkanoid_init(){ + setBGcolor(BACKGROUND_COLOR); + setFGcolor(FOREGROUND_COLOR); + choose_font(FONTN8); + ClearScreen(); + ScreenON(); + score = 0; + Nlives = LIVES_AT_START; + curLevNo = 0; + draw_level(); + startlevl(); +} + +/* + * BUTTONS: + * left/right - move racket + * set - fire a ball + * up - pause/resume + * menu - go to menu + */ + +int arkanoid_process(){ + static uint32_t Tracketspeed = 0; + if(Tms == Tlast) return 1; + int dt = (int)(Tms - Tlast); + Tlast = Tms; + // check buttons + keyevent evt; +#define PRESS(x) (keystate(x, &evt) && evt == EVT_PRESS) +#define HOLD(x) (keyevt(x) == EVT_HOLD) +#define RELEASE(x) (keyevt(x) == EVT_RELEASE) + if(PRESS(KEY_U)){ // UP - pause + if(paused){ + DBG("----> Arkanoid resume\n"); + paused = 0; + showText(); + }else{ + DBG("----> Arkanoid paused\n"); + paused = 1; + showcur(); + showText(); + } + } + if(paused){ + clear_events(); + return 1; + } + uint8_t released = 0; + if(PRESS(KEY_L)) racketspeed = -FIXPOINT; // single move @1pt + else if(HOLD(KEY_L)) racketspeed += -D_RACKET_SPEED; + else released = 1; + if(PRESS(KEY_R)) racketspeed = FIXPOINT; // single move @1pt + else if(HOLD(KEY_R)) racketspeed += D_RACKET_SPEED; + else ++released; + if(2 == released){ + if(racketspeed){ + Tracketspeed = Tms; + racketspeed = 0; + DBG("Racket stops @"); DBGU(oldracketspeed); NL(); + }else{ + if(Tms - Tracketspeed > KEEPXSPEEDTIME){ +#ifdef EBUG + if(oldracketspeed) USB_send("oldracspd=0\n"); +#endif + oldracketspeed = 0; + } + } + } + if(PRESS(KEY_S)){ + fire_a_balls(); + } + if(keystate(KEY_M, &evt) && evt == EVT_HOLD){ // break the game + return 0; + } +#undef PRESS +#undef HOLD + process_racket(dt); + for(int i = 0; i < NBALLSMAX; ++i){ + if(balls[i].flags & ACTIVE_BALL){ // this ball is alive + if(!process_ball(&balls[i], dt)){ // ball falls out + balls[i].flags = 0; + --Nballs; + DBG("--balls: "); DBGU(Nballs); NL(); + } + } + } + if(Nballs == 0){ // --lives + DBG("Ball falled\n"); + if(--Nlives == 0){ + DBG("no more lives\n"); + return 0; // game over + } + draw_racket(fixed2i(racketX), BACKGROUND_COLOR); // clear racket + startlevl(); + } + return 1; +} diff --git a/F1-nolib/Tetris/arkanoid.h b/F1-nolib/Tetris/arkanoid.h new file mode 100644 index 0000000..da9e4a8 --- /dev/null +++ b/F1-nolib/Tetris/arkanoid.h @@ -0,0 +1,25 @@ +/* + * This file is part of the TETRIS project. + * Copyright 2021 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#ifndef ARKANOID_H__ +#define ARKANOID_H__ + +void arkanoid_init(); +int arkanoid_process(); + +#endif // ARKANOID_H__ diff --git a/F1-nolib/Tetris/buttons.c b/F1-nolib/Tetris/buttons.c index 20e267b..7d38a55 100644 --- a/F1-nolib/Tetris/buttons.c +++ b/F1-nolib/Tetris/buttons.c @@ -26,7 +26,7 @@ uint32_t lastUnsleep = 0; // threshold in ms for press/hold #define PRESSTHRESHOLD (9) -#define HOLDTHRESHOLD (249) +#define HOLDTHRESHOLD (199) typedef struct{ keycode code; // key code diff --git a/F1-nolib/Tetris/fontNumb8.h b/F1-nolib/Tetris/fontNumb8.h index df748d2..88d0373 100644 --- a/F1-nolib/Tetris/fontNumb8.h +++ b/F1-nolib/Tetris/fontNumb8.h @@ -19,8 +19,8 @@ // this file should be included JUST ONCE! // only in fonts.c -#define FONTNUMB8BYTES 11 -#define FONTNUMB8HEIGHT 11 +#define FONTNUMB8BYTES 10 +#define FONTNUMB8HEIGHT 10 #define FONTNUMB8BASELINE 2 @@ -92,7 +92,6 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, // 1 0x20 - ' ' 4, ________, @@ -105,10 +104,8 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, // 2 0x30 - '0' 6, - ________, _XXX____, XX_XX___, X___X___, @@ -121,7 +118,6 @@ const uint8_t fontNumb8_table[] = { ________, // 3 0x31 - '1' 6, - ________, _XX_____, X_X_____, __X_____, @@ -134,7 +130,6 @@ const uint8_t fontNumb8_table[] = { ________, // 4 0x32 - '2' 6, - ________, _XXX____, X___X___, ____X___, @@ -147,7 +142,6 @@ const uint8_t fontNumb8_table[] = { ________, // 5 0x33 - '3' 6, - ________, XXXX____, ____X___, ____X___, @@ -160,7 +154,6 @@ const uint8_t fontNumb8_table[] = { ________, // 6 0x34 - '4' 7, - ________, ___XX___, ___XX___, __X_X___, @@ -173,7 +166,6 @@ const uint8_t fontNumb8_table[] = { ________, // 7 0x35 - '5' 5, - ________, XXXX____, X_______, X_______, @@ -186,7 +178,6 @@ const uint8_t fontNumb8_table[] = { ________, // 8 0x36 - '6' 6, - ________, _XXX____, X___X___, X_______, @@ -199,7 +190,6 @@ const uint8_t fontNumb8_table[] = { ________, // 9 0x37 - '7' 5, - ________, XXXX____, ___X____, __X_____, @@ -212,7 +202,6 @@ const uint8_t fontNumb8_table[] = { ________, // 10 0x38 - '8' 6, - ________, _XXX____, X___X___, X___X___, @@ -225,7 +214,6 @@ const uint8_t fontNumb8_table[] = { ________, // 11 0x39 - '9' 6, - ________, _XXX____, X___X___, X___X___, @@ -238,7 +226,6 @@ const uint8_t fontNumb8_table[] = { ________, // 12 0x41 - 'A' 6, - ________, __X_____, _X_X____, _X_X____, @@ -251,7 +238,6 @@ const uint8_t fontNumb8_table[] = { ________, // 13 0x4f - 'O' 7, - ________, __XX____, _X__X___, X____X__, @@ -264,7 +250,6 @@ const uint8_t fontNumb8_table[] = { ________, // 14 0x21 - '!' 2, - ________, X_______, X_______, X_______, @@ -278,7 +263,6 @@ const uint8_t fontNumb8_table[] = { // 15 0x22 - '"' 4, ________, - ________, X_X_____, X_X_____, X_X_____, @@ -291,7 +275,6 @@ const uint8_t fontNumb8_table[] = { // 16 0x23 - '#' 7, ________, - ________, ____X_X_, ___X_X__, XXXXXXX_, @@ -303,7 +286,6 @@ const uint8_t fontNumb8_table[] = { ________, // 17 0x24 - '$' 6, - ________, __X_____, _XXX____, X_X_X___, @@ -317,7 +299,6 @@ const uint8_t fontNumb8_table[] = { // 18 0x25 - '%' 8, ________, - ________, _XX___X_, X__X_X__, _XX_X___, @@ -330,7 +311,6 @@ const uint8_t fontNumb8_table[] = { // 19 0x26 - '&' 7, ________, - ________, _X______, X_X_____, X_X_____, @@ -343,7 +323,6 @@ const uint8_t fontNumb8_table[] = { // 20 0x27 - ''' 2, ________, - ________, X_______, X_______, X_______, @@ -355,7 +334,6 @@ const uint8_t fontNumb8_table[] = { ________, // 21 0x28 - '(' 4, - ________, __XX____, _X______, X_______, @@ -368,7 +346,6 @@ const uint8_t fontNumb8_table[] = { ________, // 22 0x29 - ')' 4, - ________, XX______, __X_____, ___X____, @@ -383,7 +360,6 @@ const uint8_t fontNumb8_table[] = { 6, ________, ________, - ________, __X_____, XXXXX___, _XXX____, @@ -396,7 +372,6 @@ const uint8_t fontNumb8_table[] = { 6, ________, ________, - ________, __X_____, __X_____, XXXXX___, @@ -413,7 +388,6 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, XX______, _X______, X_______, @@ -424,7 +398,6 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, XXXXX___, ________, ________, @@ -439,14 +412,12 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, XX______, XX______, ________, ________, // 28 0x2F - '/' 6, - ________, ____X___, ___X____, ___X____, @@ -461,7 +432,6 @@ const uint8_t fontNumb8_table[] = { 3, ________, ________, - ________, XX______, XX______, ________, @@ -475,7 +445,6 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, XX______, XX______, ________, @@ -487,7 +456,6 @@ const uint8_t fontNumb8_table[] = { 4, ________, ________, - ________, __X_____, _X______, X_______, @@ -501,7 +469,6 @@ const uint8_t fontNumb8_table[] = { ________, ________, ________, - ________, XXXX____, ________, XXXX____, @@ -513,7 +480,6 @@ const uint8_t fontNumb8_table[] = { 4, ________, ________, - ________, X_______, _X______, __X_____, @@ -524,7 +490,6 @@ const uint8_t fontNumb8_table[] = { ________, // 34 0x3F - '?' 5, - ________, _XX_____, X__X____, ___X____, @@ -537,7 +502,6 @@ const uint8_t fontNumb8_table[] = { ________, // 35 0x40 - '@' 8, - ________, ___XXX__, __X__X__, _X_XXXX_, @@ -550,7 +514,6 @@ const uint8_t fontNumb8_table[] = { ________, // 36 0x42 - 'B' 6, - ________, XXX_____, X__X____, X_X_____, @@ -563,7 +526,6 @@ const uint8_t fontNumb8_table[] = { ________, // 37 0x43 - 'C' 7, - ________, __XXX___, _X___X__, X_______, @@ -576,7 +538,6 @@ const uint8_t fontNumb8_table[] = { ________, // 38 0x44 - 'D' 6, - ________, XXX_____, X__X____, X___X___, @@ -589,7 +550,6 @@ const uint8_t fontNumb8_table[] = { ________, // 39 0x45 - 'E' 6, - ________, XXXXX___, X_______, X_______, @@ -602,7 +562,6 @@ const uint8_t fontNumb8_table[] = { ________, // 40 0x46 - 'F' 6, - ________, XXXXX___, X___X___, X_______, @@ -615,7 +574,6 @@ const uint8_t fontNumb8_table[] = { ________, // 41 0x47 - 'G' 7, - ________, __XXX___, _X___X__, X_______, @@ -628,7 +586,6 @@ const uint8_t fontNumb8_table[] = { ________, // 42 0x48 - 'H' 6, - ________, X___X___, X___X___, X___X___, @@ -641,7 +598,6 @@ const uint8_t fontNumb8_table[] = { ________, // 43 0x49 - 'I' 4, - ________, XXX_____, _X______, _X______, @@ -654,7 +610,6 @@ const uint8_t fontNumb8_table[] = { ________, // 44 0x4A - 'J' 5, - ________, XXXX____, X__X____, ___X____, @@ -667,7 +622,6 @@ const uint8_t fontNumb8_table[] = { ________, // 45 0x4B - 'K' 6, - ________, X___X___, X__X____, X_X_____, @@ -680,7 +634,6 @@ const uint8_t fontNumb8_table[] = { ________, // 46 0x4C - 'L' 6, - ________, X_______, X_______, X_______, @@ -693,7 +646,6 @@ const uint8_t fontNumb8_table[] = { ________, // 47 0x4D - 'M' 8, - ________, X_____X_, XX___XX_, X_X_X_X_, @@ -706,7 +658,6 @@ const uint8_t fontNumb8_table[] = { ________, // 48 0x4E - 'N' 6, - ________, X___X___, XX__X___, XX__X___, @@ -719,7 +670,6 @@ const uint8_t fontNumb8_table[] = { ________, // 49 0x50 - 'P' 6, - ________, XXXX____, X__XX___, X___X___, @@ -732,7 +682,6 @@ const uint8_t fontNumb8_table[] = { ________, // 50 0x51 - 'Q' 7, - ________, __XX____, _X__X___, X____X__, @@ -745,7 +694,6 @@ const uint8_t fontNumb8_table[] = { ________, // 51 0x52 - 'R' 6, - ________, XXXX____, X__XX___, X___X___, @@ -758,7 +706,6 @@ const uint8_t fontNumb8_table[] = { ________, // 52 0x53 - 'S' 6, - ________, _XX_____, X__X____, X_______, @@ -771,7 +718,6 @@ const uint8_t fontNumb8_table[] = { ________, // 53 0x54 - 'T' 6, - ________, XXXXX___, __X_____, __X_____, @@ -784,7 +730,6 @@ const uint8_t fontNumb8_table[] = { ________, // 54 0x55 - 'U' 7, - ________, X____X__, X____X__, X____X__, @@ -797,7 +742,6 @@ const uint8_t fontNumb8_table[] = { ________, // 55 0x56 - 'V' 6, - ________, X___X___, X___X___, X___X___, @@ -810,7 +754,6 @@ const uint8_t fontNumb8_table[] = { ________, // 56 0x57 - 'W' 8, - ________, X_____X_, X_____X_, X_____X_, @@ -823,7 +766,6 @@ const uint8_t fontNumb8_table[] = { ________, // 57 0x58 - 'X' 6, - ________, X___X___, X___X___, _X_X____, @@ -836,7 +778,6 @@ const uint8_t fontNumb8_table[] = { ________, // 58 0x59 - 'Y' 6, - ________, X___X___, X___X___, X___X___, @@ -849,7 +790,6 @@ const uint8_t fontNumb8_table[] = { ________, // 59 0x5A - 'Z' 6, - ________, XXXXX___, ____X___, ___X____, diff --git a/F1-nolib/Tetris/main.c b/F1-nolib/Tetris/main.c index 1a9a559..0513d46 100644 --- a/F1-nolib/Tetris/main.c +++ b/F1-nolib/Tetris/main.c @@ -17,6 +17,7 @@ */ #include "adcrandom.h" +#include "arkanoid.h" #include "balls.h" #include "buttons.h" #include "fonts.h" @@ -39,6 +40,7 @@ enum{ STATE_MENU, STATE_SNAKE, STATE_TETRIS, + STATE_ARKANOID, STATE_SLEEP, STATE_GAMEOVER } curstate = STATE_SLEEP; @@ -97,6 +99,10 @@ static void process_menu(){ tetris_init(); curstate = STATE_TETRIS; break; + case MENU_ARKANOID: + USB_send("Select 'Arkanoid'\n"); + arkanoid_init(); + curstate = STATE_ARKANOID; default: break; } @@ -158,6 +164,12 @@ int main(void){ curstate = STATE_GAMEOVER; } break; + case STATE_ARKANOID: + if(!arkanoid_process()){ + show_gameover(); + curstate = STATE_GAMEOVER; + } + break; case STATE_GAMEOVER: // show gameover screen if(keystate(KEY_M, &evt) && evt == EVT_RELEASE){ gotomenu(); diff --git a/F1-nolib/Tetris/menu.c b/F1-nolib/Tetris/menu.c index ee77e42..9fa1b91 100644 --- a/F1-nolib/Tetris/menu.c +++ b/F1-nolib/Tetris/menu.c @@ -33,10 +33,11 @@ #define midY (SCREEN_HH - 1) static const char* items[] = { - [MENU_SLEEP] = " SLEEP ", - [MENU_BALLS] = " BALLS ", - [MENU_SNAKE] = " SNAKE ", - [MENU_TETRIS] = " TETRIS " + [MENU_SLEEP] = " SLEEP ", + [MENU_BALLS] = " BALLS ", + [MENU_SNAKE] = " SNAKE ", + [MENU_TETRIS] = " TETRIS ", + [MENU_ARKANOID] = " ARKANOID ", }; static menuitem curitem = MENU_SLEEP; diff --git a/F1-nolib/Tetris/menu.h b/F1-nolib/Tetris/menu.h index 8ac68a9..1ed39f0 100644 --- a/F1-nolib/Tetris/menu.h +++ b/F1-nolib/Tetris/menu.h @@ -26,6 +26,7 @@ typedef enum{ MENU_BALLS, MENU_SNAKE, MENU_TETRIS, + MENU_ARKANOID, MENU_ITEMS, MENU_NONE } menuitem; diff --git a/F1-nolib/Tetris/screen.c b/F1-nolib/Tetris/screen.c index d770ceb..6ff022e 100644 --- a/F1-nolib/Tetris/screen.c +++ b/F1-nolib/Tetris/screen.c @@ -85,7 +85,7 @@ uint8_t DrawCharAt(int16_t X, int16_t Y, uint8_t Char){ const uint8_t *curchar = font_char(Char); if(!curchar) return 0; // now change Y coordinate to left upper corner of font - Y += 1 - curfont->height + curfont->baseline; + Y += curfont->baseline - curfont->height + 1; // height and width of letter in pixels uint8_t h = curfont->height, w = *curchar++; // now curchar is pointer to bits array uint8_t lw = curfont->bytes / h; // width of letter in bytes diff --git a/F1-nolib/Tetris/screen.h b/F1-nolib/Tetris/screen.h index 87edeea..b3a3cf5 100644 --- a/F1-nolib/Tetris/screen.h +++ b/F1-nolib/Tetris/screen.h @@ -49,6 +49,8 @@ typedef enum{ // screen states // colors #define COLOR_BLACK (0b00000000) #define COLOR_WHITE (0b11111111) +#define COLOR_GRAY (0b01101101) +#define COLOR_LGRAY (0b10110110) #define COLOR_BLUE (0b00000011) #define COLOR_LBLUE (0b00000001) #define COLOR_GREEN (0b00011100) @@ -58,6 +60,7 @@ typedef enum{ // screen states #define COLOR_CYAN (0b00011111) #define COLOR_LCYAN (0b00000101) #define COLOR_PURPLE (0b11100011) +#define COLOR_LPURPLE (0b01100001) #define COLOR_YELLOW (0b11111100) #define COLOR_LYELLOW (0b00100100)