From b4d721cdb1be1dee887b0f5f27a4f252f7530170 Mon Sep 17 00:00:00 2001 From: agreiner Date: Thu, 15 Apr 2021 19:52:18 +0200 Subject: [PATCH] Praktikum 4 --- .../superpangworld/game/GameLoopManager.java | 44 ++++++++- .../superpangworld/objects/Bubble.java | 4 +- .../superpangworld/objects/Harpoon.java | 4 +- .../superpangworld/objects/LevelLabel.java | 10 +-- .../objects/LevelProgressBar.java | 6 +- .../superpangworld/objects/ScoreLabel.java | 38 ++++++++ .../superpangworld/objects/Spielfigur.java | 85 ++++++++++++++++++ .../superpangworld/game/GameLoopManager.class | Bin 1831 -> 3700 bytes .../superpangworld/objects/Bubble.class | Bin 2381 -> 2369 bytes .../superpangworld/objects/Harpoon.class | Bin 1981 -> 1969 bytes .../superpangworld/objects/LevelLabel.class | Bin 1963 -> 1951 bytes .../objects/LevelProgressBar.class | Bin 2835 -> 2837 bytes .../superpangworld/objects/ScoreLabel.class | Bin 0 -> 1472 bytes .../superpangworld/objects/Spielfigur.class | Bin 0 -> 2457 bytes 14 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/ScoreLabel.java create mode 100644 SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Spielfigur.java create mode 100644 out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/ScoreLabel.class create mode 100644 out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Spielfigur.class diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/game/GameLoopManager.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/game/GameLoopManager.java index b9c7fde..1bdddfd 100644 --- a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/game/GameLoopManager.java +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/game/GameLoopManager.java @@ -1,21 +1,26 @@ package de.thdeg.greiner.superpangworld.game; -import de.thdeg.greiner.superpangworld.objects.Bubble; -import de.thdeg.greiner.superpangworld.objects.Harpoon; -import de.thdeg.greiner.superpangworld.objects.LevelLabel; -import de.thdeg.greiner.superpangworld.objects.LevelProgressBar; +import de.thdeg.greiner.superpangworld.objects.*; import java.awt.*; +import java.awt.event.KeyEvent; +import java.security.Key; +import java.util.Arrays; /** Der Manager zur Verwaltung der Spielschleife. */ public class GameLoopManager { + private static final boolean DIAGONAL_MOVEMENT_ALLOWED = false; + private GameView gameView; private Bubble bubble; private Harpoon harpoon; private LevelProgressBar levelProgressBar; private LevelLabel levelLabel; + private ScoreLabel scoreLabel; + + private Spielfigur spielfigur; /** Erzeugt den GameLoopManager mit Standardwerten. */ public GameLoopManager() { @@ -29,6 +34,9 @@ public class GameLoopManager { this.levelProgressBar = new LevelProgressBar(gameView); this.levelLabel = new LevelLabel(gameView); + this.scoreLabel = new ScoreLabel(gameView); + + this.spielfigur = new Spielfigur(gameView); gameView.setColorForBlockImage('k',Color.LIGHT_GRAY); } @@ -36,16 +44,44 @@ public class GameLoopManager { /** Startet das Spiel. */ public void startGame() { while(true){ + updateUserInputs(); + + bubble.updatePosition(); bubble.addToCanvas(); harpoon.addToCanvas(); levelProgressBar.addToCanvas(); levelLabel.addToCanvas(); + scoreLabel.addToCanvas(); + + spielfigur.addToCanvas(); gameView.printCanvas(); } } + void updateUserInputs() { + Integer[] gedruekteTasten = gameView.getKeyCodesOfCurrentlyPressedKeys(); + if(Arrays.stream(gedruekteTasten).anyMatch(k -> k == KeyEvent.VK_SPACE)){ + spielfigur.shoot(); + } + for (int keyCode : gedruekteTasten) { + switch(keyCode) { + case KeyEvent.VK_LEFT: + spielfigur.left(); + break; + case KeyEvent.VK_RIGHT: + spielfigur.right(); + break; + default: + continue; + } + if(!DIAGONAL_MOVEMENT_ALLOWED){ + return; + } + } + } + } diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Bubble.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Bubble.java index 5e19b97..16f7000 100644 --- a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Bubble.java +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Bubble.java @@ -35,8 +35,8 @@ public class Bubble extends GameObject{ super(gameView); rotation = 90; size = 5; - width = (int) size * 12; - height = (int) size * 12; + width = 12; + height = 12; speedInPixel = 5; flyFromLeftToRight = true; } diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Harpoon.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Harpoon.java index 24e895f..49da869 100644 --- a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Harpoon.java +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Harpoon.java @@ -24,8 +24,8 @@ public class Harpoon extends GameObject{ super(gameView); speedInPixel = 10; size = 3; - width = (int) size * 11; - height =(int) size * 11; + width = 11; + height = 11; rotation = 0; getPosition().setTo(300,300); } diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelLabel.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelLabel.java index 0b69a6d..1a38a2f 100644 --- a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelLabel.java +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelLabel.java @@ -13,20 +13,20 @@ public class LevelLabel extends GameObject{ private int level; /** - * Create a progress bar with default values. - * @param gameView the {@link GameView} to display the progress bar + * Create a label for the level with default values. + * @param gameView the {@link GameView} to display the level label */ public LevelLabel(GameView gameView){ super(gameView); size = 3; - width = (int) size * 101; - height = (int) size * 8; + width = 101; + height = 8; level = 8; getPosition().setTo(GameView.WIDTH/2 - (width/2),GameView.HEIGHT-height-60); } /** - * Draws the level progress bar onto the canvas of the {@link GameView}. + * Draws the level label onto the canvas of the {@link GameView}. */ @Override public void addToCanvas(){ diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelProgressBar.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelProgressBar.java index a792597..52c59d3 100644 --- a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelProgressBar.java +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/LevelProgressBar.java @@ -21,10 +21,10 @@ public class LevelProgressBar extends GameObject{ public LevelProgressBar(GameView gameView){ super(gameView); size = 3; - width = (int) size * 101; - height = (int) size * 8; + width = 101; + height = 8; levelProgress = 30; - getPosition().setTo(GameView.WIDTH/2 - (width/2),GameView.HEIGHT-height); + getPosition().setTo(GameView.WIDTH/2 - (width/2),GameView.HEIGHT-(height*size)); } /** diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/ScoreLabel.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/ScoreLabel.java new file mode 100644 index 0000000..b6c39af --- /dev/null +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/ScoreLabel.java @@ -0,0 +1,38 @@ +package de.thdeg.greiner.superpangworld.objects; + +import de.thdeg.greiner.superpangworld.game.GameView; + +import java.awt.*; + +/** + * The label to display the score. + */ +public class ScoreLabel extends GameObject{ + + /** The score to display */ + private int score; + + /** + * Create a label for the score with default values. + * @param gameView the {@link GameView} to display the score label + */ + public ScoreLabel(GameView gameView) { + super(gameView); + score = 1300; + size = 50; + width = 100; + height = 8; + + position.setTo(GameView.WIDTH/2 - (width/2) -250,GameView.HEIGHT-height-60); + } + + @Override + public void addToCanvas() { + gameView.addTextToCanvas(Integer.toString(score),getPosition().x,getPosition().y,40, Color.YELLOW,0); + } + + @Override + public void updatePosition() { + super.updatePosition(); + } +} diff --git a/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Spielfigur.java b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Spielfigur.java new file mode 100644 index 0000000..e785341 --- /dev/null +++ b/SuperPangWorld/src/de/thdeg/greiner/superpangworld/objects/Spielfigur.java @@ -0,0 +1,85 @@ +package de.thdeg.greiner.superpangworld.objects; + +import de.thdeg.greiner.superpangworld.game.GameView; + +import java.awt.*; + +/** + * The game character controlled by the player. + */ +public class Spielfigur extends GameObject{ + + /** Flag, if the player is shooting */ + private boolean shooting; + /** Debug flag, to display X and O or the real image */ + private static boolean SHOW_X = false; + /** The pixel art of the character */ + private static String SPIELFIGUR = + " kkk \n"+ + " BBBBk \n"+ + " BBBBBB \n"+ + " BBBBBBBB \n"+ + " BBBBBBB \n"+ + " BBBBBBB \n"+ + "kBBBBBBB \n"+ + "kkBBBBBB \n"+ + "kkBBBBBBkkk\n"+ + "kkBBBBBkkkk\n"+ + " BBBBBBkk \n"+ + " BBBBBBBk \n"+ + " kBBBBBBk \n"+ + " BBBBBkb \n"+ + " bbbk kbb \n"+ + " BBBb kBBb\n"+ + " BBBk kkkB"; + + /** + * Create the game character with default values + * @param gameView the {@link GameView} to display the character + */ + public Spielfigur(GameView gameView){ + super(gameView); + position.setTo(GameView.WIDTH/2, GameView.HEIGHT/2); + shooting = false; + size = 3; + width = (int) size * 12; + height = (int) size * 12; + speedInPixel = 5; + } + + @Override + public void updatePosition(){ + + } + + @Override + public void addToCanvas(){ + if(SHOW_X) { + gameView.addTextToCanvas(shooting ? "O" : "X", position.x, position.y, 50, Color.RED, rotation); + }else{ + gameView.addBlockImageToCanvas(SPIELFIGUR, position.x, position.y, size, rotation); + } + shooting = false; + } + + /** Moves the character to the left */ + public void left(){ + position.left(speedInPixel); + } + /** Moves the character to the right */ + public void right(){ + position.right(speedInPixel); + } + /** Moves the character upwards */ + public void up(){ + position.up(speedInPixel); + } + /** Moves the character downwards */ + public void down(){ + position.down(speedInPixel); + } + /** Lets the character shoot */ + public void shoot(){ + shooting = true; + } +} diff --git a/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/game/GameLoopManager.class b/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/game/GameLoopManager.class index d5a3bca5babd27bbe0fc25308a38f9ca86a85fca..1e6a855b818ce18b24ad6b9f40c7943c0c308555 100644 GIT binary patch literal 3700 zcmbVO`F9)D75<(rdn{!V8xsQok}AXj%UR?&sk10`u!Ula$O~B5O(;#r(z86#XhxkG z*|-bc((QBuxEgD~B@`=#p2JW5si*%*|AC$!4)l97vLlQSvHOGGo2&cYz2Cj> zZvTAut+xT3MO{OSz^S54`in(bN|sz{+R{yWwW@ThhFw~AT&tKY85NlvV#n% zCF#ZxL7Rql9U3|Wx~>^ZM$+Py_v~j9#8snrd@QF^QLb} zfu6qHEt_V1*R)Hi#B2xdrX3@8(Upc59}E2zKNf$K=EtX9r{o%yiYeV1bUnwv2K#pCu*9tL{DV3kLLZ-UK9DFda9c6&$B@#{&)3>6@NvVf zI*uJf0*93TV>*r_DWENe41p8d2GEd21SbT}Y!^XJE=enRN9lQ^2E%+HgmOy9M=``8 zvNoL%IJa#~o23)n89vUAz~zj2X~l3lgq6~99v@>A1+W4h6MAQWf?I@gVFyrV3XUrq zP=-S&qdL-fgiyQ<-cF$0l1L~QcLJqqN^8L^)%aMM5K30ZqqwA?Z18pjW#d*ViU~|= zn9?zg$5wqW^9BNV}qSi2|c4Dk0)49nEJt`i;g>L zIfZhz!a6Fjw=ccPk7SJ+SQuxsl>jb<4MKb6EdeA&-6`| zIdMFtj#DHY3HPOD{DEg7{$A$2SS7pg3B{`!R|7Im1oCUB7D z>5^PYJ4NYDEu?F%D{bFenRb~XvPh06a93aA$)G3rkqm@U)H@XuBqt8pAmo2{GSpOPg8J931P>rQt;yZW)#N zqS3oKOL_-XRBjQI33@}61@7E}$Aq47YHmSZG?g3nZW?-ytCwULkMfZjjz)Dt`ioA{ z>ukrbWB3hzt6^2g@9=wp2W~yOX)iftnal+^dBa#R3clm6FhwiP)W4e1HZFw<#tpk@ zNw1glSGiVAH34TfsKKP^pZ8tNuT@i!~<(MOfu0RkF4P+$$zm8cd zK3s=F!tE2>j@EIN+sQgU#qC@j2Dgzq=DCg6QQ)T6QCxlR9~99_1;B%BOW+GcFo<0^ ziEf<2K7x<4dp(3RoC?oz96R3x>p}z8j{+GAjOw05#fK3QK5#q#@j_Ll+>yVb{1!e9 zyop*1UO+5_^4TL3N8cW99g6fs_P>I$qdk$qI-VJ7>uGyc32cM}=o`>~AQXOwSFf+4 zEByNUD%w{Oxp6%rR^NM5xjwWhbo~fHjnbAhZOPD@i<}O|*~_zR+Ls`a!y+b8#$)W9 z8Mx#s*T*U2G%fxyeu6gAUc=fBo_ql>(oALdessKpxQ3s;3yrG~@8F1tMqB<1{0D7a zF_mtiM;OE{`~o`pV$XENUxpST=GNEvSBSPfV2?I=xD!9eFUVJ#+R(E5VYV*3Oriz9 d#4FrYeEf?4{QM$8}=6X{n$O8Xyf+G%pkgQb`xQ%A?Q%ZD~uxLn2aw6d@&T6JVJ= zViQ?n!w)E1Q0+({v18L8z|UaC8W=kf=t^hi%st~d6|S0GbGXi;d&ww9O>R2e;PB<1(s*5IS)^I9Cy${b*gjrxp*$+*vCm`wYe z5LL1qupTLoS)u6x&3fd776$Z!M^WhffR;QKg0{}+%gP4fV5huHoAp`hhh+&lpZl5T z2NZoC2wm`5m0~99eU{IxO@rD%3qz6w@-_&ta!+AT73SWoF7bn9QMgP#S=+2 Gp8f^a18?jA diff --git a/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Bubble.class b/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Bubble.class index 1333e9c2e65d823f2749a645c0a09d515abb3121..972ed199a95629b0b777fdd3ce7a1393f85d78b9 100644 GIT binary patch delta 92 zcmX>rbWmu+G&a>524)5(1_lNlE$!_Lj9MZL>{}T)ffWB%20<+Wo~;ZbKyvbNHeFRo m26YB`1`P%^22BQS1}%m_pe`|pUWOosU?2}@%4SJ+6D9!nvkjF1 delta 104 zcmX>obXI7?G&aKy24)5(1_lNTE$!_Lj9MZL>{}T)ffWB%20<;YEewKv0z4U88ARah t$-CKfRplAf8MGNR7>pP+8O#~97y^MNh(XL@2x15Z@_;68=4Cfw0sugV5v>3K diff --git a/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Harpoon.class b/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Harpoon.class index 60518308e90626188f500ca46ecb7ac28d6e5c3f..d7e3b5eba79637e6e4fcf17840553711e0f2656f 100644 GIT binary patch delta 92 zcmdnXzmb2#16I{0237_p1_lNrE$!_Lj9MZL>{}T)ffWB%20<+W?yU?WKytDmo3W}S lgA9W_gDiszgB*h)kmU!|B?i&U;Li{M{}T)ffWB%20<;YEewKv0^Au}8ARah t$*gR~s`3mn4B8B`3{}T)wFFYPGVp5&a7=!~>ZmHjAkH8G ggmMg$3^oi>48B0+Vh~LXehmIV9#H${Aht+G0G)XaF#rGn delta 97 zcmbQwznXu;Ay%!a46F=H3=9mOTH4zg7_~$g*tarpYH4j@;OrAf&DhGo4`p*?On$)X ps4BrA&Y;2|!Jx$;$>6~t#o!CnDh4rt!H>Zo$O9U+*^Mod5dhZ15jg+= diff --git a/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/LevelProgressBar.class b/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/LevelProgressBar.class index dbcc8f4efb4774af36b2949c8831aeb4ed8e4785..97bfa78a933e27b37302b81b2625a20cf61e9b0d 100644 GIT binary patch delta 1105 zcmZ8g%Tg0T6g@qY%p`GuI8ebDgb;a7!b{ZflJF7*69rKaUw|ec0tqC5pkh!LEUa?V zr!8QE2WMqeD5yjgLnD91-24~wuo`~AqLQY-3m=aQO(*KnAfr)16YW0g>kE2U$!t*@jpT#9}tVBHU;hI;L~ED!h=o)0pv5VH7l`oE9fzH>o%N0pMuNi z=ikMa>Z=L{FvyUTv&*xwD1%s2JF4ppDhS~^uQ64*{T2)p;Ftv?lzJ?< zP06i7#F(z-4v(6Kng7e4X@uoRZHQq}#*$u%^K$8%b(uk6%z{<^TUzj}F{r`FYGi&W z9-E0r5{aIvcpFup6E)M@Uh)mO*py_b@S1=ETkr(o6WkrWCvyCsD}&0d;G!r)^_439CGQ}&)_E>f*S ztqy8L179D$q;+^}$K+z>R)` zFzcr0kkErCG;g|%D8sDoroEenUXne=5*ldn&(6C?=vfnN$4oHi5JfyCUIBBY8pLYG c0s$n9xMIX-MqD@I3v5uAjXGXo6K~-B3vNT5t^fc4 delta 1119 zcmZ8gO-~b16g_XIooUA@lwzv2SZXZ@(}E%*$ftZ10b4~;5kEm&L9KkWiXdur#Yz^w zxYh6vBtl8LFfnnXOZO(O{Sn6drXwY0l6&u)x$m6w&Ykzp%e~t7KZVZ#PT}>2w$5A{ zf;gliq~kEc{0ocOY8j?EQzv;)Quw@NSL$@s!{94Y)1D|AR5a>1O6zSYs5I#~j%NN- znowFqd6IX^4N99%@a=p~?gi8R5n18UF=7Rm_Qwd2T3QT^R<6F$W$q%&>o_>(U%pWbnjOi>dTzW^Ou@%4YkfGVRp3#2_=V zaK;thK9 zmTHOepb^;yGxkE=g3~ZI;aqd4X0}jn)efpF4R>G*ULy}*1^Y!k<@R)PwL+?*vNE}v zNA-ruag$(tnS$5sR}o8uFY=L_MQ^a?^9so%AP7TQ32LXaVCQm1KJ8sGyr6V}OPkBNqov!lIj@ z9l{XqnS?T`F)iG5_tMa-ipN->OIot?Y6-n)g0{;9yM-uYhIl31#{5Ox9 zN}}L_ZF&Xi>E`H>o=`#9R>7058yq*$$I!Ivlx@#;N|adL%FdNptHz`h3^0sdOOP;b zVMxJkjyo7;7_S$6l~ZaVyiJGZgs%JQ-s8BB1QjEtm#Q;pb&L7CO<|}QQSg9c6k`mr zZDZfiigYKmOvw|La0%UWHayoZSqz$#{Uyy5J*d9i3qwn**Zm=p^`)U^f@lhH^IlvV*+)2D*Qmt=jUwcKA&N6x_1STKG9 zMUA8N1Q9iAo}fdGHl3hLJw|Vg{iLZQSTtk!Wgf*E`pE1uqci5wDF#0iN&{ZeH~@u4 z`9W%>u?-!FpchdLq8;;OWofs|XT@u*kVX9Rj#Ewyt5~k)woVx{+8ZXCyYyGSBB`E2 zJI16xJ&t4g3sP;Tn6I(Rjse~D0DCG-+{dUgG1 h&dV221<)=5WIhp+U%%8Aq=Br{XRij6f30%r%^&PUSU&&& literal 0 HcmV?d00001 diff --git a/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Spielfigur.class b/out/production/SuperPangWorld/de/thdeg/greiner/superpangworld/objects/Spielfigur.class new file mode 100644 index 0000000000000000000000000000000000000000..62c02c950213150fc3f5713a17df393218a2440a GIT binary patch literal 2457 zcmb7F?^YUD5dU3)h2S+>OH6E=s!3{)m|&t!8&OLTHKZikV8}nyWPue{kfpGQ>4!c- zzUK+@H8pC^>4!c*`x1SUwlljcAoXao=PY+-cIG#~J2Ut4$KSvG4&WAE`OyWJ7j6j; z6oDH#Eo>HYT0WewYI<3#hHLeTR;{Sze8Z@ga$zI0p=HflcuC#VmMvL8nbFI-IY-gK z)inD^#y4Hw{rBA_!Q(pKbx*MQ$wI(W)67+a)?hqtm*q2w&+!Fq zuU0S&Q!nQQ#8V~evl4;}H!LxN3j*$%{pr$s9gKj49YKedurNG>Lp9+J}kUj)v%D)A6$fisjdRx+~1#HO0p zTA2rr&P@>zf&^x~gVMWa&>DS+$f_t2*nB(QOuV8k(v9UAoq_6`?V%S8}SUwVL1x zj?sX0^H4SivL|J#+2TF5Vx{zgn%`%QdE12Y?ZI~hP5Df=uZvedke6o*EL#{mx zh5|UhhoKOC8G79(3wyZOCSRt{p*@WMN(fyj((eVz4-6CP2>MAoi;MUYmk^@M>n27q zi_0jH$AFy`n<$e;`T6=GP67rh4!0|07yP#1nKm$PK}h?f10nEJGjJE(*0;4Cgx_G2 zxZj|6@C|(ZH{Zh3|1D|WT}<1{Yyi<6#7McbkMG~o2FZU1%ZHsv8?s$eR$-Wv%i8h) zZ5EiIl3u4RP9jYkc}5a%)8@G5aIBK$9NcLydj27T!pqGf#f#ecAu>E^?qHg*d8d*| z&^x}5N3AOGap!;eZcMjjk~T11C(Z)l zEFOtdZ{kc*1-L#+$W24qiIAX<+-*Zp?8@}r<{OgYc<{rtGJ+@c0l9Z1*z;=-n71w1 npjB#h4)xy3c?x(yE%Tit>!l@