From aad127ce5b932106bc2ddde0309688a0613f1587 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 24 Jan 2008 23:54:19 +1100 Subject: [PATCH] Proper redraw and scoring. --- Makefile | 4 +- images/0.png | Bin 0 -> 2039 bytes images/1.png | Bin 0 -> 559 bytes images/2.png | Bin 0 -> 1505 bytes images/3.png | Bin 0 -> 1823 bytes images/4.png | Bin 0 -> 1070 bytes images/5.png | Bin 0 -> 1418 bytes images/6.png | Bin 0 -> 2189 bytes images/7.png | Bin 0 -> 1224 bytes images/left-won.png | Bin 0 -> 6416 bytes images/right-won.png | Bin 0 -> 7820 bytes prpong.c | 416 ++++++++++++++++++++++++++++++++++--------- 12 files changed, 334 insertions(+), 86 deletions(-) create mode 100644 images/0.png create mode 100644 images/1.png create mode 100644 images/2.png create mode 100644 images/3.png create mode 100644 images/4.png create mode 100644 images/5.png create mode 100644 images/6.png create mode 100644 images/7.png create mode 100644 images/left-won.png create mode 100644 images/right-won.png diff --git a/Makefile b/Makefile index 11d33b3..f3e0240 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ #! /usr/bin/make CFLAGS:=-Wall -Wmissing-prototypes -Wmissing-declarations -g -I../ccan #-g #-O2 -g -LDFLAGS:=-lSDL -lcwiid -prpong: prpong.c stdrusty.h +LDFLAGS:=-lSDL -lSDL_image -lcwiid +prpong: prpong.c stdrusty.h ../ccan/talloc/talloc.o wiimote: wiimote.c stdrusty.h diff --git a/images/0.png b/images/0.png new file mode 100644 index 0000000000000000000000000000000000000000..b29a2fe9e1b6bb665d8b645051b893b3ac84020f GIT binary patch literal 2039 zcmbVNX*iS(7oMT)vdb*VBa&@2BSu+@8OxA08D*4)5k-xyFl2v>jL_gq8VOk{nrw+M zUSgV*k|bnb%a+%czTSDK|KG3gI@f)c`#R^xeVre7nv0XIv;q?C@@a>L&nK zOhk}X&G7Al0u6JswSrW?LoNsg5we3V9>V_>$mpCJ!VByxD;kc{8!IUfE5L_tbLO8`w?RsE%fSN7A(S?|>XRqMQ zjexgwj~rTJ1qTpMBfF0m6jVP{SBSXeo_7qZe;-rNPz|>c-_(((6)i$}H4L$2F{$&r zcH7J2*PZaXj!cbUEBsjljMhyhXfglA6Okz;8+$t@M=EP zT!Mys3I&Oxpe%Hq1IKt=Y24%MXZmsT1Ej%+P{vElU5g z<(+*YYX}$7MUl;9W>f76T4R}!SjDa~F!)O2vXWM&5F+LckLfXv8nc(gp3yt-456{icco1;qO&N?$>t zIVRZ33|ulLgCEjSzdyA$`ac1}7O&@T+<9R^vY-zYTtc#(9glSO+p{-}6lM|0D-ki` z^YK7KYAw8GR^>(*YYKc~MDi-golgSKxi2*W&tc@@`zhnuBJFKcqFU1EJ1S7NdG+|4PAn0pxAHQs%itQKnsqM^U`nYY%nVE0MR8p!c-74w+4Rv5fiMhD zZOsJ=!{|sSSnt|DX6r4!kzJuXH20C4WuLh6x`f(!3RnCMr8PO5F`3i1T3Qa?v!@O6 zUS$;+N}L2qNf&kp&^2pQ4+h(%U^KLJZX5ftElJFB@Cdwm-(o1Zy)!sG8wx5G163#l z#-yZh_A;np;V10^PIq!jrJvnv9aydel)uI@jXT%0sj1~)cw-QK=3|0xAv{#`yy5gs z3?B4j0S^g?V&Kg)sb}vO{;XRQ5PjL#c87-dfstdBrN zUFh%bexT}a+pl@wH&BJ_*nuvDk&gzh2b=|wyh9v4?sWPTNuXAQIF%3Ng|%#!QS4eQ zr`>y{UUX1{FLl$`H6sn=>yar2iYd;Zt7Kp4j#YKxyzSnfZf${20Gp5bs8`zMQ&P@S z`PrYSO0Tk5;8?*_8lcQF{isY!0$7Ii)lfk5Ys(~tSpEA$gGdCXe^ z{q<=K2WpSudf7pY-qPy+Ggm7iJ3a$YPY2bO={vwvIQeLbux2L21CeOLFfCyJl7HDj zhriJwMxQonsEKmemp0`XMESd`Dd(FPTZz#dt>CTsAya8ZqeAhUVl6ut^|op9ok+<) z3npBduA*~XyDf6b@(PLdbpS5hY`0^5_|K+a$v@sDN4%4I`+VL^W`r)PhZPyxaEcB|WVXFQ2gFD^9}?btB}>&}XB5Ss zM4nXlglFQ2<_#SqZWoaaHBZd7yf4T9;{IODBKut1_KY<;XkMl9a^mTs2mGzHRhzEY zA>)Wd9(IGXKqY^1TGbyfqTa@)_&9$eO~$dBAlr)0KM$3iTd?=am|KTh^ePw*WRJRf zq`67N%)EdV{MdSuciAE;cBvBP6-z7TQMS)6- ze^Grf%8jZB?S)=MqKm~NjoYL0vF;GvzYw=`<#gG(lUxU0{G2aI^n2Bkq+#93=dITt zi5Va7muqp~ZmUxJ41GE=2qxDJ)JzuN^T9?t4n9hdn;1Gx)Rno<7;35)m`tKjhxD%I kK7)#ev1ohXiQX1r`h;SUcgXt$Y&y1px=7zyJUM literal 0 HcmV?d00001 diff --git a/images/1.png b/images/1.png new file mode 100644 index 0000000000000000000000000000000000000000..7ce4af0f855fa52b2c397e86473998e7c6ad06c2 GIT binary patch literal 559 zcmeAS@N?(olHy`uVBq!ia0vp^DL{OJgAGW^*|;18QjEnx?oJHr&dIz4a@dl*-CY>| zgW!U_%O?XxI14-?iy0WWg+Z8+Vb&Z8pdfpRr>`sf4MqtLHRZ4O4xRxDNtU=qlsM<- z=BDPAFgO>bCYGe8D3oWGWGJ|M`UZqI@`(ej>hg4P45_&F_U=Zn!vPX)57%$wYUOKc z?w+mSbn)B2^@~JV=avY&&)ww_BV^H{m&Bj@__M=_S%31+d0Lq=0xiJ?R%DhOxL!6b zWnRk6l)yRX*{k+@PCD5bbKKSN%ex)EMZfNcok-!={6|P>L}nS;3B{x$l}Q22&2Fv)R&N)5c_|BMe>sR*(*hpPCKDkj0nL6@7cfY WP<_8CeDxDhkb1iMxvXdR4zM1>@4@nt%tGZ(vgu%Q_=n`ss2RdI*x=L z%q8VADVI7FQ4*1K6D=pXoGv=TS#Qsq^ZYK~=lgknuYNDS=iObMuxLCQ27_T4&JLb3 zJtCX?3Mkp$YVFV^6S){qCpxTdQ1gS#pn{oB4zTr~ReD>LEhCCi&b~1)*ap>~BL^!K zs>>h{%W!c7#^lr$^eE9R{w5jHh;{UdwdWo?#)*uD*&pWw#d402PK3vXk(?MV?%tph z4hBP7GaP<7z7TYGPQ7=r{=HYxIjR>^&5fbkRKaotIV$IgTydmfS{qaA52KW} z`{n|;*)?ryN?A9$%DgXGN;_~gUb(-~xOSl2+~e8YTRS?AAb50Ru6;hqZlOan{_FSK zf8Q}%FGyG;F)r);PhXfln4M^a%!lts>dCSB*`P-!g+-z$NCC~|-Z9_@=A*briDlNH zGR7gT56H8&M7dh{fw?BjdvEbC@xOHLVO{JEG~L>YxYz#shR(zJAp4{W-%hpkV~?_yQw>`_DseV_s>ep z634NpQ4!UZKJf?GyB2T_9r)Fn4U#vVRUWy!$Uyp=X)0Mnc&oKE$ z{2|7QCA?LIr)u>C>GZ&DeM7^>eF2w7AYS$jsh%@;>-c?hp)zNW2w( z#vgRcwwE+y!NY+7V8$!bc!YyG$p|J9@LHLcEK^EdPiWdM7?4db@OnnGM6`HDUbjrH z$)@{ywa{$EmEu!FyhvAtcO*)q()z=_IV+^}$OO9niBfZWJ~tT@-+&}DNW{4JfTsRX zZm$`wgiFicSE8jv;hY(2`P<1W>-xZCzgodG(cKTt<1487RSNoQxk6vvL zP81K%PmzP_zJrwJ(0M4(H!6`e(LxTaGq_hGR}!iiW3x$N%KPY=w%augro@XU28~+; zk`kS-QFmjR`JsmvTBfkfe34znGsZiq)g$VRB#+ku=q4Q`DhZ;~mO^qjVUW$pOBsMM zy99Us1O^|h5%YraV8VJBN1bN;Xlg3RrM`bV zUn_W(em0ldYgi~HPwZ>4(t_%1{@Q{hJ1ekvMzvKyx6bo`Qbdm4V|1Iz8^0+^RJx1_ zc{R}XoKH&VLYEJgxYbD?mci7Z$U0#wmYr1r6){{pz5`^=i}6mbVvzV|PIRdIO8`n; z#Mm}zSf)2Z9_CP<^v>EP7dCo#Kf673@>I7T+%9vt^?2qqR6rY~2hR^%7 zyO#xH%;GX*a|u}sB0nwn;A|%_C6|a;wo!u3^eM4vPLcf(rP*sfbr2h5KAk=aZMNCr zH<<6yiBk;v2zR|9G~FTh`wqbnN*KPIz0dPxuhZS-;>M+$aM$viqZd;bfoTf_Qb_aV z8sdABUTgPjn3c7i%t(#qqx`j-GE!B!bBUh|CM3CLA^IFnbC~)${%_>ahl`znV$e;m z!awy(k-VK+vUiA7H&X;pylvPjbrZ4!)~_pN5aqC+ewZ@n`!GcL)F?DX7~G~&yIXsY z_k0FM_0C3jOhX@lcA;7iwO?a6k0+8Rr09M?Sm&wrOqtL0U2PgFS`tR=Q?FS_n8*yc zH}Q^0eB|v^2oDnPN3*f<-!P}F44|gvg_yA?<&;rxTo$@@rvZc=Ih>cgN3%F%bAhO~ ydOS{maXQF~#CI1V(OO@&X literal 0 HcmV?d00001 diff --git a/images/3.png b/images/3.png new file mode 100644 index 0000000000000000000000000000000000000000..9e5ca84fd08bf8ae0912d7c34106006bdb6fb478 GIT binary patch literal 1823 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 literal 0 HcmV?d00001 diff --git a/images/5.png b/images/5.png new file mode 100644 index 0000000000000000000000000000000000000000..5c7f21723aa76a00edf7230e250b0e24878f5211 GIT binary patch literal 1418 zcmah}dpOez82+)$FzPfhg=d9DRO5uo<@9aNRKDgywZN+J?G zWE?ERa|B#gb*%}1$w-do;eZFq+O@-l|d)3G!ExP>)x?MDtN{ONacCnNIIwcsB5JnHhIFMZ2yg@Zh z0N5}=A{;)JI4Bu$VRJpTTNdWnAKNOWX6JwDO6z;o?@VyVHy+txf(YAG!PCc@oIq?- zxk4n;^>%~@1a+}k_MRHypzFz-hPx;Sby9hrd~BL&QHV+VqlJU`4n|T3ZSot*HAFhh zm|Yo}lnm3pYwDA-|2Ios<$Q<>k%+7Z*PL^j4j~EfK#bWY*mV$n8Tsr`Feb0(qWlu? zCE6PQ)9Alz|DGKCT|r^C2QS9^+XywLX7PY{D=T zRp~zGO(K++H}z}g!_vl52hlh+Z8<*ZH;#(i8M9evR&5TgR7iCNJui-ki;f?_H-nnY z6o2x2!T1*F{zCF^C*Qh%(h)vx2a&L>7P-1{>00Y%v6^@-1J4kA=H=AS&g%<{nC`vR zi5UYvhYi2X85q%w4E9Kl?3HRlgiu zE=VYCH|5lZFdw3-{iv9gq7AV*;5*Au4CMevC@F?#kA{wk*kJI|UD*qOtC{?E6&$DD z=eAIC6GRhReFh4rv%t2uGc0PoC1E->t(+hZ~|a|PsfViu_Wm; z4Yk#rr7g3uPjGXKEpJ&kTPew=Jf+()eCC15qOOjgJ4863a0}JAtR=_}5#7PjObs~R zl4fgHJ@s~H^0k;-5A?h~15eTx+L6-LR!wjMOB}FQ?>cbB)-=%SkT1 z{kdeQ%KTi;Bf}o^yImH4%=5n&)0j^mL0pJ&OmuUW zy+3(j2akBcYa%!8o{$|mWD3s?&vT;%U$EvPVd>vHv52PDYtI%_#*bIsm^W6sDj#CA z>I;=l?oUPwm`>ovk14E5$ASK<25&0bUgM(nNHw}~$igtHc1_7=!N|(yX5DV=OD!Vb z!tS2>!^?T06F6IWi&xaj$}OpA*z8XA)>1AFRAh2l89i}of$B9`8eervCZOFAEjPXD z&!<;MbfYO&j?Wxv&V=ny)nDam03)^m$@Q9vUeqv;r%cE1Kov-Hvj+t literal 0 HcmV?d00001 diff --git a/images/6.png b/images/6.png new file mode 100644 index 0000000000000000000000000000000000000000..a965c686c07933a4d71cbabba41492bfd6c80a81 GIT binary patch literal 2189 zcmbW3c{~%0AIE1K8gpAlj^)T1mLsubb8a4fcnHlg$I3BmQSKahoQcY#!+j-0CTUNu zEq9|yavwu(GRKpO^3(snzkaXp>+|`%zVFxT`}gOYW@l?Dz$e8A000EAR%Q;z>3gi+ z6FkQ*i!x&z2Un~5yyklJO6Us=rn1rrlBpGJz5@s3_6hsUT1DIYXdW8{v5#jz}eh5pfjh%CXpv3Xn z3f2tm7%{O~;7Yn|F5VLd6UO_itME{q9qsHGdbq@NW0hwN0Rdwb$Ts5{M3bVVl8C>v zo?%^TuYe?Up4CjnO`#d?cEvDC3C6xtp1??v{G-2v>vZ9$k_XQb0oL%Y=!~ulLt{1Kl{j7cI z%d8@Lex>vZPTpcC@s2eK>=b|wR(ULp$=cOMpceAhSbB39*xU%Q&W)6A|tq$YIOY1VB4_0cRIPoqXVLys~Cy>H?rW5oK^4 zY&6!vad>Xzf|HtsPJK-^Qra1g@9}f;8XI2^=RtZn!;%+ce5`y^tF<+DGj%8;*=3om zyXfk-^;15=KDpIe8k2xaQs4_tPVihYsQ00XzCXC)dxi7c$mD3-T?Gx1R5el{CCdqx zOw2~#A*x)3wJ;55$nDOm6kGH3L_bxW z-0BnyO&)e56v3~pa)sOU5^C5;_x5$)84tPJh)}5D9&cR*s%r2QwN+0* zl)2_bW0|m@0={YjuY%;hv8-cMKJV+_{wwN|+S+o;TF2q?;Pj}%t0<8N2lYMpLsas)LBD`l-lw-oL>P0R@jHwMfeJzGm*|x9BZ+eSQQ?*^>bK zsoH#QsSL^0$~a@8&3YnD&$8atjksaq-LH7}Rhv6m(*2}oTmMHkOfvNY#!V~nE2EW{ z`b}3u%O|eaBzrwI3t~|uJHQ<5rh7lOfOq!3;y}=6{6%yUv(1LU*8R1kdBB`RP22- z#_c-R2X+mlHJuScJ3KK}>>J?|o!5=u6s?wH%D3jC!2a6CD-L4i(Hn_LeoC#PqP{)v z5mvKFU}}rmfsz*bYPdXFqv=*&B_g*Z@F)pyR{V_Otr)}rJdp4x z7fhl{6UOsVWeJE{YqW=!P0&k;rfc}1qJbl zWq4fyK8X=+A8Bi@4r`hX53MK#~J4-Q#RM=6({*e#-^W(dCuTCea@#0qt~cG z%HM+TbvrLyE^`bx%oO4C9w?XcYy>&`Oe&IQQ#%a+`?-Vn;~gV7!%?J}JX%;o=_+4K z5J^U;Ylr#7H_R6YHl9kjI55w40k1A9V{#i;`1u>-+yKa@B9cB-Hg))NuCJ&u$ie z=^IPHxc|e@Q|`vu`7HxNJ2WPrD<6xo^n~(^*cE1KO@c$R?CH!-{lL8z@tFc)m3z-=A_e?v8!> kPkh!-9qa$yu4c+}T9gb5>| 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≥v>~fDx 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 literal 0 HcmV?d00001 diff --git a/images/right-won.png b/images/right-won.png new file mode 100644 index 0000000000000000000000000000000000000000..49dbf2612bd1ee9f7ca769dbe9a06e6cb638546b GIT binary patch literal 7820 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 NrMc~2gzMf9{}0F$*h&BZ literal 0 HcmV?d00001 diff --git a/prpong.c b/prpong.c index 7799f63..ddf4afb 100644 --- a/prpong.c +++ b/prpong.c @@ -9,14 +9,24 @@ #include #include "stdrusty.h" #include "list/list.h" +#include "talloc/talloc.h" +#include "container_of/container_of.h" #include +#include #include #include #include +#define EXPIRY_SECS 3 + #define MAX_X CWIID_IR_X_MAX #define MAX_Y CWIID_IR_Y_MAX +#define LEFT_PLAYER 1 +#define RIGHT_PLAYER 2 + +static LIST_HEAD(objects); + struct coord { double x; @@ -475,18 +485,48 @@ static void line(SDL_Surface *s, } } +/* Bounding box to be updated. */ +static bool needs_update; +static struct coord start_update, end_update; + +struct object +{ + /* List of all objects. */ + struct list_node list; + /* Bounding box. */ + struct coord start, end; + + void (*redraw)(SDL_Surface *s, struct object *me); +}; + struct ball { + struct object object; + struct coord pos; struct coord move; + SDL_Surface *image; }; struct line_segment { + struct object object; + struct coord start, end; struct list_node list; bool ignore; struct timeval expires; + /* Does someone score if they hit this line ? */ + struct score *score; +}; + +struct score +{ + struct object object; + + SDL_Surface *image; + unsigned int value; + SDL_Surface *won; }; static void thick_line(SDL_Surface *s, const struct line_segment *l, @@ -599,10 +639,10 @@ static void bounce(struct ball *ball, const struct line_segment *line, } static struct line_segment border[] = { - { { 0, 0, }, { MAX_X-1, 0 } }, - { { MAX_X-1, 0, }, { MAX_X-1, MAX_Y-1 } }, - { { MAX_X-1, MAX_Y-1, }, { 0, MAX_Y-1 } }, - { { 0, MAX_Y-1, }, { 0, 0 } }, + { .start = { 0, 0, }, .end = { MAX_X-1, 0 } }, + { .start = { MAX_X-1, 0, }, .end = { MAX_X-1, MAX_Y-1 } }, + { .start = { MAX_X-1, MAX_Y-1, }, .end = { 0, MAX_Y-1 } }, + { .start = { 0, MAX_Y-1, }, .end = { 0, 0 } }, }; static inline float deg_to_rad(float degrees) @@ -749,31 +789,218 @@ static bool map_coord(unsigned int x, unsigned int y, return true; } -static struct line_segment *new_line(unsigned int startx, unsigned int starty, - unsigned int endx, unsigned int endy, - const struct coord calib[]) +static void add_update(const struct object *obj) { - struct line_segment *l = malloc(sizeof(*l)); + if (!needs_update) { + start_update = obj->start; + end_update = obj->end; + needs_update = true; + return; + } + if (obj->start.x < start_update.x) + start_update.x = obj->start.x; + if (obj->start.y < start_update.y) + start_update.y = obj->start.y; + if (obj->end.x > end_update.x) + end_update.x = obj->end.x; + if (obj->end.y > end_update.y) + end_update.y = obj->end.y; +} + +static void destroy_object(struct object *object) +{ + list_del(&object->list); + add_update(object); +} + +static void add_object(struct list_head *list, + struct object *obj, + unsigned int startx, unsigned int starty, + unsigned int width, unsigned int height, + void (*redraw)(SDL_Surface *s, struct object *me)) +{ + list_add_tail(list, &obj->list); + obj->start.x = startx; + obj->start.y = starty; + obj->end.x = startx + width; + obj->end.y = starty + height; + obj->redraw = redraw; + add_update(obj); +} + +static void redraw_line(SDL_Surface *s, struct object *me) +{ + struct line_segment *l = container_of(me, struct line_segment, object); + + thick_line(s, l, 0); +} + +static int destroy_line(struct line_segment *l) +{ + list_del(&l->list); + destroy_object(&l->object); + return 0; +} + +static void line_object_setup(struct list_head *lines, + struct list_head *objects, + struct line_segment *l) +{ + unsigned int tmp, startx, endx, starty, endy; + + list_add_tail(lines, &l->list); + + startx = l->start.x; + starty = l->start.y; + endx = l->end.x; + endy = l->end.y; + + /* Find bounding box */ + if (startx > endx) { + tmp = endx; + endx = startx; + startx = tmp; + } + if (starty > endy) { + tmp = endy; + endy = starty; + starty = tmp; + } + /* Padding for thick lines (beware underflow) */ + if (startx > 0) + startx--; + if (starty > 0) + starty--; + endx++; + endy++; + + add_object(objects, &l->object, startx, starty, + endx - startx, endy - starty, redraw_line); +} + +static void add_line(struct list_head *lines, + unsigned int startx, unsigned int starty, + unsigned int endx, unsigned int endy, + const struct coord calib[]) +{ + struct line_segment *l = talloc(NULL, struct line_segment); + struct timeval now; - l->ignore = false; if (!map_coord(startx, starty, calib, &l->start) || !map_coord(endx, endy, calib, &l->end)) { - free(l); - return NULL; + talloc_free(l); + return; } - return l; + + l->ignore = false; + l->score = NULL; + gettimeofday(&now, NULL); + l->expires = now; + l->expires.tv_sec += EXPIRY_SECS; + + line_object_setup(lines, &objects, l); + talloc_set_destructor(l, destroy_line); +} + +static void redraw_ball(SDL_Surface *s, struct object *me) +{ + struct ball *b = container_of(me, struct ball, object); + SDL_Rect rect = { .x = b->pos.x - b->image->w/2, + .y = b->pos.y - b->image->h/2 }; + + SDL_BlitSurface(b->image, NULL, s, &rect); +} + +static void redraw_score(SDL_Surface *s, struct object *me) +{ + struct score *score = container_of(me, struct score, object); + SDL_Rect rect = { .x = score->object.start.x, + .y = score->object.start.y }; + + SDL_BlitSurface(score->image, NULL, s, &rect); +} + +static SDL_Surface *score(struct score *s) +{ + char filename[40]; + + s->value++; + SDL_FreeSurface(s->image); + sprintf(filename, "images/%u.png", s->value); + s->image = IMG_Load(filename); + /* No more images? You won! */ + if (!s->image) + return s->won; + + add_update(&s->object); + return NULL; +} + +/* Due to rounding, we exaggerate bounding box by 1 here. */ +static void do_updates(struct list_head *objects, SDL_Surface *screen) +{ + struct object *i; + unsigned int y, startx, starty, endx, endy; + + /* Clip */ + if (start_update.x <= 0) + startx = 0; + else + startx = start_update.x - 1; + if (start_update.y <= 0) + starty = 0; + else + starty = start_update.y - 1; + + endx = end_update.x+1; + endy = end_update.y+1; + + if (endx > screen->w) + endx = screen->w; + if (endy > screen->h) + endy = screen->h; + + SDL_LockSurface(screen); + /* First we clear the area to white. */ + for (y = starty; y < endy; y++) { + memset(screen->pixels + y * screen->pitch + + screen->format->BytesPerPixel * startx, + 0xFF, + (endx - startx) * screen->format->BytesPerPixel); + } + SDL_UnlockSurface(screen); + + /* Now redraw everything which overlaps it */ + list_for_each(objects, i, list) { + if (i->end.x < startx) + continue; + if (i->end.y < starty) + continue; + if (i->start.x > endx) + continue; + if (i->start.y > endy) + continue; + i->redraw(screen, i); + } + + SDL_UpdateRect(screen, startx, starty, endx - startx, endy - starty); + + /* Reset bounding box */ + needs_update = false; } +static bool same_side(const struct ball *ball, unsigned int x) +{ + return (ball->pos.x >= MAX_X/2) == (x >= MAX_X/2); +} int main(int argc, char *argv[]) { struct ball ball; - SDL_Surface *screen, *ballsur, *savesur = NULL; + SDL_Surface *screen; Uint8 video_bpp; Uint32 videoflags; unsigned int i, time_since_last_ir = INT_MAX; - SDL_Rect rect; - struct timeval line_life = { 3, 0 }; cwiid_wiimote_t *wiimote; struct cwiid_state state; struct coord calib[4]; @@ -781,7 +1008,7 @@ int main(int argc, char *argv[]) bool mouse = false, needs_calibration = true, drawing = false; LIST_HEAD(lines); struct cwiid_ir_src *ir, last_ir = { .valid = 0 }; - struct line_segment *n; + struct score left, right; videoflags = SDL_SWSURFACE; @@ -817,17 +1044,10 @@ int main(int argc, char *argv[]) argv++; } - if (argc != 5) - errx(1, "Usage: %s [--fullscreen] [--calib=x,y,x,y,x,y,x,y] [--mouse] ballx bally ballangle ballspeed\n" - " Where ballangle is 0 for north, 90 for east, etc\n", + if (argc != 2) + errx(1, "Usage: %s [--fullscreen] [--calib=x,y,x,y,x,y,x,y] [--mouse] speed\n", argv[0]); - ball.pos.x = atol(argv[1]); - ball.pos.y = atol(argv[2]); - ball.move.x = sin(deg_to_rad(atof(argv[3]))) * atol(argv[4]); - ball.move.y = cos(deg_to_rad(atof(argv[3]))) * atol(argv[4]); - printf("ball move = %f,%f\n", ball.move.x, ball.move.y); - /* Initialize SDL */ if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); @@ -846,13 +1066,13 @@ int main(int argc, char *argv[]) errx(1, "Can't set IR repeat mode"); } - if ( (screen=SDL_SetVideoMode(MAX_X,MAX_Y,video_bpp,videoflags)) == NULL ) { + if ((screen=SDL_SetVideoMode(MAX_X,MAX_Y,video_bpp,videoflags)) == NULL) { errx(1, "Couldn't set %dx%dx%d video mode: %s", MAX_X, MAX_Y,video_bpp, SDL_GetError()); } /* Set the surface pixels and refresh! */ - if ( SDL_LockSurface(screen) < 0 ) { + if (SDL_LockSurface(screen) < 0) { errx(1, "Couldn't lock the display surface: %s", SDL_GetError()); } @@ -870,16 +1090,44 @@ int main(int argc, char *argv[]) calibrate(screen, wiimote, &calib[3], 0, MAX_Y - 1); } - /* Draw borders, put them in list. */ + /* Create borders, put them in list. */ for (i = 0; i < ARRAY_SIZE(border); i++) { border[i].ignore = false; border[i].expires.tv_sec = LONG_MAX; border[i].expires.tv_usec = 0; - list_add(&lines, &border[i].list); - thick_line(screen, &border[i], 0); + line_object_setup(&lines, &objects, &border[i]); } - ballsur = ball_surface(screen); + /* Set up scores. */ + left.value = right.value = 0; + left.image = IMG_Load("images/0.png"); + left.won = IMG_Load("images/left-won.png"); + right.image = IMG_Load("images/0.png"); + right.won = IMG_Load("images/right-won.png"); + if (!left.image || !right.image || !left.won || !right.won) + err(1, "Opening score images"); + + add_object(&objects, &left.object, + MAX_X/6 - left.image->w/2, 10, + left.image->w, left.image->h, redraw_score); + add_object(&objects, &right.object, + MAX_X - MAX_X/6 - left.image->w/2, 10, + left.image->w, left.image->h, redraw_score); + + /* Hit right border = score to left, and vice versa. */ + border[1].score = &left; + border[3].score = &right; + + srandom(time(NULL)); + ball.pos.x = MAX_X/2; + ball.pos.y = MAX_Y/2; + ball.move.x = (random() % 2 ? -1 : 1) * atoi(argv[1]); + ball.move.y = 0; + ball.image = ball_surface(screen); + add_object(&objects, &ball.object, + ball.pos.x - ball.image->w/2, + ball.pos.y - ball.image->h/2, + ball.image->w, ball.image->h, redraw_ball); for (;;) { struct coord new, isect, move = ball.move; @@ -893,13 +1141,8 @@ int main(int argc, char *argv[]) /* Expire lines */ list_for_each_safe(&lines, l, next, list) { - if (timercmp(&l->expires, &now, <)) { - printf("Deleting line %p\n", l); - list_del(&l->list); - /* FIXME: Undraw properly. */ - thick_line(screen, l, 0xFFFFFFFF); - free(l); - } + if (timercmp(&l->expires, &now, <)) + talloc_free(l); } again: @@ -934,6 +1177,24 @@ int main(int argc, char *argv[]) /* Don't hit the same line twice. */ printf("Ignoring that line\n"); best_l->ignore = ignored = true; + if (best_l->score) { + SDL_Surface *won = score(best_l->score); + if (won) { + SDL_Rect rect; + + rect.x = MAX_X/2 - won->w/2; + rect.y = MAX_Y/2 - won->h/2; + rect.w = won->w; + rect.h = won->h; + SDL_BlitSurface(won, NULL, screen, + &rect); + SDL_UpdateRect(screen, + rect.x, rect.y, + rect.w, rect.h); + SDL_Delay(3000); + exit(0); + } + } goto again; } @@ -943,28 +1204,22 @@ int main(int argc, char *argv[]) move.x, move.y, new.x, new.y); } - /* Restore what was there before ball. */ - if (savesur) { - SDL_BlitSurface(savesur, NULL, screen, &rect); - SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h); - } else { - savesur = sub_surface(screen, ballsur->w, ballsur->h); - } + /* We also need to redraw under old ball. */ + add_update(&ball.object); - /* Save away image under new ball. */ - rect.w = ballsur->w; - rect.h = ballsur->h; - rect.x = new.x - ballsur->w/2; - rect.y = new.y - ballsur->h/2; - SDL_BlitSurface(screen, &rect, savesur, NULL); - - /* Draw new ball */ - SDL_BlitSurface(ballsur, NULL, screen, &rect); - SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h); - /* That SDL_BlitSurface can crop rect. */ - rect.x = new.x - ballsur->w/2; - rect.y = new.y - ballsur->h/2; + /* Move ball. */ ball.pos = new; + ball.object.start.x = ball.pos.x - ball.image->w/2; + ball.object.start.y = ball.pos.y - ball.image->h/2; + ball.object.end.x = ball.pos.x + ball.image->w/2; + ball.object.end.y = ball.pos.y + ball.image->h/2; + + /* Need to draw under new ball. */ + add_update(&ball.object); + + /* Clears, redraws and resets the updates */ + do_updates(&objects, screen); + SDL_Delay(25); while (SDL_PollEvent(&event)) { @@ -983,23 +1238,17 @@ int main(int argc, char *argv[]) drawing = false; break; case SDL_MOUSEMOTION: - if (!drawing) + if (!drawing || + !same_side(&ball, event.motion.x)) break; - n = new_line(event.motion.x, - event.motion.y, - event.motion.x - + event.motion.xrel, - event.motion.y - + event.motion.yrel, - calib); - - if (n) { - timeradd(&now, &line_life, - &n->expires); - list_add_tail(&lines, &n->list); - thick_line(screen, n, 0); - } + add_line(&lines, event.motion.x, + event.motion.y, + event.motion.x + + event.motion.xrel, + event.motion.y + + event.motion.yrel, + calib); } } } @@ -1015,23 +1264,22 @@ int main(int argc, char *argv[]) for (i = 0; i < CWIID_IR_SRC_COUNT; i++) { if (!state.ir_src[i].valid) continue; + /* Only look at dots on same side as ball */ + if (!same_side(&ball, state.ir_src[i].pos[0])) + continue; if (!ir->valid || state.ir_src[i].size > ir->size) ir = &state.ir_src[0]; } if (ir->valid) { /* Give it some slack for missing one or two... */ - if (time_since_last_ir <= 5) { - n = new_line(last_ir.pos[0], - last_ir.pos[1], - ir->pos[0], - ir->pos[1], - calib); - if (n) { - timeradd(&now, &line_life, &n->expires); - list_add_tail(&lines, &n->list); - thick_line(screen, n, 0); - } + if (time_since_last_ir <= 5 + && same_side(&ball, last_ir.pos[0])) { + add_line(&lines, last_ir.pos[0], + last_ir.pos[1], + ir->pos[0], + ir->pos[1], + calib); } time_since_last_ir = 0; last_ir = *ir; -- 2.39.2