<canvas id=c width=320 height=240><script>with(Math){h=c.getContext`2d`,x=y=4,H=100,am=25,a=rc=fl=t=0,rd=random,fr="fillRect",ft="fillText",fs="fillStyle",ta="textAlign",al="ArrowLeft",ar="ArrowRight",au="ArrowUp",ad="ArrowDown",ao=o=>atan2(o.y-y,o.x-x)-a,ho=o=>hypot(o.x-x,o.y-y),SEED=rd()*100,f=(i,j)=>(abs(i-4)<4&&abs(j-4)<4)?0:((i+1e3)%7==3||(j+1e3)%7==3)?0:(n=cos(i*12.9898+j*78.233+SEED)*43758.5453,n-=n|0,n<.05?1:0),e=[{x:5,y:4,h:100},{x:4,y:5,h:100}],k={};onkeydown=e=>k[e.key]=1,onkeyup=e=>k[e.key]=0,ontouchstart=e=>{e.preventDefault(),t=1,k[e.touches[0].clientX<innerWidth/2?al:ar]=1,k[au]=1},ontouchend=e=>{t=k[al]=k[ar]=k[au]=0},onclick=_=>{if(am){am--,fl=2,rc=.2,e.forEach(o=>{let d=ho(o),r=ao(o);d<5&&abs(r)<.3&&(o.h-=50,h[fs]="#fff",h[fr](160+r*160-2,118,4,4))})}};ff=(a,b)=>f(0|a,0|b);R=_=>{rc-=rc>.02?.02:rc,fl&&fl--,e=e.filter(o=>o.h>0),h[fs]="#000",h[fr](0,0,320,240),k[al]&&(a-=.1),k[ar]&&(a+=.1),m=.1,(k[au]||k.w)&&(nx=x+cos(a)*m,ny=y+sin(a)*m,ff(nx,ny)!=1&&(x=nx,y=ny)),(k[ad]||k.s)&&(nx=x-cos(a)*m,ny=y-sin(a)*m,ff(nx,ny)!=1&&(x=nx,y=ny)),(k[au]||k.w||k[ad]||k.s||k[al]||k[ar])&&e.length<10&&rd()<.02&&(t=rd()*PI*2,d=1+rd()*2,X=x+cos(t)*d,Y=y+sin(t)*d,ff(X,Y)==0&&e.push({x:X,y:Y,h:100})),rd()<.005&&am<25&&am++,e.forEach(o=>{let d=hypot(dx=x-o.x,dy=y-o.y);d>.2&&(o.x+=dx/d*(.0015+.003/d),o.y+=dy/d*(.0015+.003/d),ff(o.x,o.y)!=1||0),d<.5&&(H--,fl=2,h[fs]="#800",h[fr](0,0,320,240))});let w=[];for(i=320;i--;){r=a+atan((i-160)/160),dx=cos(r),dy=sin(r),ix=floor(x),iy=floor(y),ddx=dx?abs(1/dx):1e30,ddy=dy?abs(1/dy):1e30,sx=dx<0?-1:1,sy=dy<0?-1:1,tmx=dx<0?(x-ix)*ddx:(ix+1-x)*ddx,tmy=dy<0?(y-iy)*ddy:(iy+1-y)*ddy,d=0;for(;;){if(tmx<tmy)ix+=sx,d=tmx,tmx+=ddx;else iy+=sy,d=tmy,tmy+=ddy;if(d>20||f(ix,iy)==1)break}d*=cos(r-a),w[i]=d,h2=min(240,240/d),g=min(255,200/d)|0,h[fs]=`rgb(${g},${g},${g}`,h[fr](i,120-h2/2+rc*20,1,h2)}e.forEach(o=>{d=ho(o),r=ao(o);if(abs(r)<1.2){sz=80/d,px=160+r*160;px>=0&&px<320&&d<w[px|0]*1.1&&(h[fs]=`#${o.h>50?4:8}00`,h[fr](px-sz/2,120-sz/2+rc*20,sz,sz*1.5),h[fs]="red",h[fr](px-sz/4,120-sz/2+rc*20,sz/8,sz/4),h[fr](px+sz/4,120-sz/2+rc*20,sz/8,sz/4))}}),fl&&(h[fs]="orange",h[fr](140,160+rc*20,40,20)),h[fs]="red",h[fr](10,10,H,10),h[fs]="#ff0",h[fr](10,25,am*4,5),h[fs]="#fff",h.font="7px Arial",h[ft]("HP",10,7),h[ft]("AMMO:"+am,10,28),h[ta]="right",h[ft]("<3 KWT",315,235),h[ta]="left",H>0?requestAnimationFrame(R):(h[fs]="red",h.font="20px Arial",h[ta]="center",h[ft]("GAME OVER",160,120))};R()}</script><style>*{margin:0;cursor:crosshair;width:100vw;height:100vh;touch-action:none
I tried to
make unreadableshrink the code and got-206bytes (2824->2535).QR code version differences:
2135- original,2127- new.Most of the tricks were taken from https://github.com/lionleaf/dwitter/wiki/ and https://github.com/jed/140bytes/wiki/Byte-saving-techniques.
Here is my timeline:
getElementByIdfunction1, assign variables to the same value:a=rc=fl=t=0andx=y=4widthandheightinside<canvas>tag#FFA500->orangeh=c.getContext("2d")->h=c.getContext`2d`t=0,k.ArrowLeft=k.ArrowRight=k.ArrowUp=0->t=k.ArrowLeft=k.ArrowRight=k.ArrowUp=0h.fillStyle=o.h>50?"#400":"#800"->h.fillStyle=`#${o.h>50?4:8}00`Math.PIconstant:6.283->PI*2rc=rc>.02?rc-.02:0->rc-=rc>.02?.02:rcfor(i=0;i<320;i++)->for(i=320;i--;)background:#000;*{margin:0;overflow:hidden;cursor:crosshair;width:100vw;height:100vh;touch-action:none}(thanks to @myfonj: Remove html tags to shave more bytes of minified html #3 (comment)), move in the end without a closing tagrd=random,fr="fillRect",fs="fillStyle",ta="textAlign", use square brackets to call/set canvas methods/properties:h.textAlign="center"->h[ta]="center"ao=o=>atan2(o.y-y,o.x-x)-a,ho=o=>hypot(o.x-x,o.y-y)<canvas id=c width=320 height=240 />#f00->red,<canvas id=c width=320 height=240>,*{margin:0;cursor:crosshair;width:100%;height:100%;touch-action:noneh[fr](160+r*160-2,120-2,4,4)->h[fr](160+r*160-2,118,4,4)au="ArrowUp",al="ArrowLeft",ar="ArrowRight",ad="ArrowDown"ff=(a,b)=>f(0|a,0|b)(warning: glitched wall collision)h[fs]=`rgb(${g},${g},${g})`->h[fs]=`rgb(${g},${g},${g}`Edited code
QR code
Footnotes
In JS, an element with an ID becomes as a global variable, see https://xem.github.io/articles/getelementbyid.html ↩
https://github.com/jed/140bytes/wiki/Byte-saving-techniques#use-reverse-loops-where-possible ↩
https://codegolf.stackexchange.com/a/61143 ↩
https://github.com/lionleaf/dwitter/wiki/Canvas-specific-Golfing-Tricks#color ↩