I am relatively new to java and was trying to learn how to make a program where there is this circle and I can move it around using the arrow keys. After shifting through a bunch of examples I was able to put something together. Although I am unsure how to create a KeyEvent. Any help with what I am missing would be awesome.
This is what I have so far.
import javax.swing.WindowConstants;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.event.KeyEvent;
#SuppressWarnings("serial")
public class Game extends JPanel
{
int x = 0;
int y = 0;
private void moveBallUP() {
x = x + 0;
y = y + 1;
}
private void moveBallDOWN() {
x = x + 0;
y = y - 1;
}
private void moveBallLEFT() {
x = x + 1;
y = y + 0;
}
private void moveBallRIGHT() {
x = x - 1;
y = y + 0;
}
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.red);
g2d.fillOval(y, x, 50, 50);
}
public static void main(String[] args) throws InterruptedException
{
JFrame frame = new JFrame("Sample Frame");
Game game = new Game();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if (event.getKeyCode() == KeyEvent.VK_UP)
{
game.moveBallUP();
game.repaint();
Thread.sleep(10);
}
if (event.getKeyCode() == KeyEvent.VK_DOWN)
{
game.moveBallDOWN();
game.repaint();
Thread.sleep(10);
}
if (event.getKeyCode() == KeyEvent.VK_LEFT)
{
game.moveBallLEFT();
game.repaint();
Thread.sleep(10);
}
if (event.getKeyCode() == KeyEvent.VK_RIGHT)
{
game.moveBallRIGHT();
game.repaint();
Thread.sleep(10);
}
}
}
There are several steps to solving this: first, use a KeyListener. Add the following code to the Game class; this will represent which buttons are pressed:
private boolean upPressed=false;
private boolean downPressed=false;
private boolean leftPressed=false;
private boolean rightPressed=false;
Then, add this to the main method:
frame.addKeyListener(new KeyListener() {
#Override
public void keyReleased(KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.VK_UP:
game.upPressed=false;
break;
case KeyEvent.VK_DOWN:
game.downPressed=false;
break;
case KeyEvent.VK_LEFT:
game.leftPressed=false;
break;
case KeyEvent.VK_RIGHT:
game.rightPressed=false;
break;
}
}
#Override
public void keyTyped(KeyEvent event) {
}
#Override
public void keyPressed(KeyEvent event) {
switch (event.getKeyCode()) {
case KeyEvent.VK_UP:
game.upPressed=true;
break;
case KeyEvent.VK_DOWN:
game.downPressed=true;
break;
case KeyEvent.VK_LEFT:
game.leftPressed=true;
break;
case KeyEvent.VK_RIGHT:
game.rightPressed=true;
break;
}
}
});
Basically, you are setting the variables we created to true when the buttons are pressed down and false when they are released. Finally, add a Timer in the main method:
Timer timer = new Timer(10,(e)->{
if (game.upPressed)
{
game.moveBallUP();
game.repaint();
}
if (game.downPressed)
{
game.moveBallDOWN();
game.repaint();
}
if (game.leftPressed)
{
game.moveBallLEFT();
game.repaint();
}
if (game.rightPressed)
{
game.moveBallRIGHT();
game.repaint();
}
});
timer.start();
This will fire every 10 milliseconds and call your move methods if the buttons are pressed.
I have tested this and know that it works, however your move methods move the circle in the wrong directions. I assume you can fix that.
EDIT: The mistake is in this line:
g2d.fillOval(y, x, 50, 50);
Change it to:
g2d.fillOval(x,y , 50, 50);
Related
So i am trying to move the ball using arrow keys and Key event ,but the ball doesn't move.If anyone can help i would gladly appreciate it ,and keep in mind that i am a beginner in java.Here is the code:
package prozor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.KeyEvent;
#SuppressWarnings("serial")
public class prozor extends JPanel {
public int x = 0;
public int y = 0;
public boolean up,down,left,right;
public int vx,vy;
public void update(){
vx=0;
vy=0;
if(up)vy=-5;
if(down)vy=5;
if(right)vy=-5;
if(left)vy=5;
}
public void keyPressed(KeyEvent e){
switch(e.getKeyCode()) {
case KeyEvent.VK_DOWN: down = true; break;
case KeyEvent.VK_UP: up = true; break;
case KeyEvent.VK_LEFT: left = true; break;
case KeyEvent.VK_RIGHT: right = true; break;
}
update();
}
public void moveBall() {
x +=vx;
y +=vy;
}
public void keyReleased(KeyEvent e){
switch(e.getKeyCode()) {
case KeyEvent.VK_DOWN: down = false; break;
case KeyEvent.VK_UP: up = false; break;
case KeyEvent.VK_LEFT: left = false; break;
case KeyEvent.VK_RIGHT: right = false; break;
}
update();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 20, 20);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("Sample Frame");
prozor game = new prozor();
frame.add(game);
frame.setSize(300, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.moveBall();
game.repaint();
Thread.sleep(10);
}
}
}
I got the snake running down, now I try to get the keypressed() method to work. I don't think it's listening from the keyboard. My idea is for example if the the down key is pressed, the variable direction is set to 1 and the switch case statement would handle that. I doubt that the direction variable was't read by the switch case.
My main class:
package com.bin.snake;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel{
boolean playingSnake = true;
Snake snake = new Snake();
public Game() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
snake.keyPressed(e);
}
});
setFocusable(true);
}
public void paint(Graphics g) {// inherit paint method of JPanel class with
// parameter g type Graphics
// parameter g is the object to paint things
super.paint(g); // erase latest image
Graphics2D g2d = (Graphics2D) g; // casting g to Graphics2D type
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);// rendering
// image
snake.paint(g2d);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Snake!");
frame.setVisible(true);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Game game = new Game();
frame.add(game);
while (true) {
game.updateGame();
game.repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void updateGame() {
snake.moveSnake();
}
}
My Snake Class:
package com.bin.snake;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
public class Snake {
private Game game;
int iSnakeLength = 10;
int direction = 1;
final int SIDE = 13;
int[] snakeY = new int[2000];
int[] snakeX = new int[2000];
int xs = 0;
int ys = 0;
public void moveSnake() {
switch (direction) {
case 0:// up
snakeY[0] -=1.5;
break;
case 1:// down
snakeY[0] += 1.5;
break;
case 2:// right
snakeX[0] += 1.5;
break;
case 3:// left
snakeX[0] -=1.5;
break;
}
for (int i = iSnakeLength; i > 0; i--) {
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
}
public void paint(Graphics2D g) {
g.fillRect(snakeX[0], snakeY[0], SIDE, SIDE);
for (int i = 0; i < iSnakeLength; i++) {
g.fillRect(snakeX[i + 1], snakeY[i + 1], SIDE, SIDE);
}
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_DOWN){
direction = 1;
}
if(e.getKeyCode() == KeyEvent.VK_UP){
direction = 0;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
direction = 3;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
direction = 2;
}
}
}
I don't think it's listening from the keyboard. My idea
KeyEvents are only dispatched to the component with focus. A JPanel is not focusable by default.
To make a panel focusable you use:
panel.setFocusable( true );
Other comments:
Custom painting is done by overriding the paintComponent(...) method, not the paint() method. Read the Swing tutorial on Custom Painting for more information and examples.
You should NOT be using a KeyListener. Swing was designed to be used with Key Bindings. Read the Swing tutorial on How to Use Key Bindings. You can also check out Motion Using the Keyboard which contains working examples of moving a component using Key Bindings.
For animation you should be using a Swing Timer to schedule the animation. Check the table of contents from the tutorial links I have already provided. There is a section on How to Use Swing Timers.
I am trying to create a very simple game that moves a ball up/right/left/down if you press the keys up/right/left/down. I looked up at different places, and here is what I made:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel implements KeyListener {
static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
static int width = (int)screenSize.getWidth();
static int height = (int)screenSize.getHeight();
static int x = width/2;
static int y = height/2;
boolean a=true;
boolean b=true;
public void keyTyped(KeyEvent e){
//nothing here
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch( keyCode ) {
case KeyEvent.VK_UP:
x=x+10;
case KeyEvent.VK_DOWN:
x=x-10;
case KeyEvent.VK_LEFT:
y=y+10;
case KeyEvent.VK_RIGHT :
y=y-10;
}
}
public void keyReleased(KeyEvent e){
//nothing here
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
}
public static void main(String[] args)throws InterruptedException {
JFrame frame = new JFrame("Sample");
Game game = new Game();
frame.add(game);
frame.setSize(width,height);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.keyPressed(null);
game.repaint();
}
}
}
But how do I "run" the keyPressed program? I saw some YouTube videos that said do something like"addKeyListener" or "addActionListener", but that mean adding a text field, text box, or text area, which I don't want. This is suppose to resemble a game after all. Thanks
edited version after looking at answers:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel implements KeyListener {
static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
static int width = (int)screenSize.getWidth();
static int height = (int)screenSize.getHeight();
static int x = width/2;
static int y = height/2;
boolean a=true;
boolean b=true;
static Game game;
public Game(){
addKeyListener(this);
}
public void keyTyped(KeyEvent e){
//nothing here
}
#Override
public void keyReleased(KeyEvent e) {
// nothing here
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
switch( keyCode ) {
case KeyEvent.VK_UP:
x=x+100;
case KeyEvent.VK_DOWN:
x=x-100;
case KeyEvent.VK_LEFT:
y=y+100;
case KeyEvent.VK_RIGHT :
y=y-1000;
}
game.repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, 30, 30);
}
public static void main(String[] args)throws InterruptedException {
JFrame frame = new JFrame("Sample");
game = new Game();
frame.add(game);
frame.setSize(width,height);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
In your constructor , add
Game()
{
/*your code*/
addKeyListener(this);
}
You can add the keylistener to your Game object during construction.
addKeyListener(new KeyAdapter()
{
#Override
public void keyPressed(KeyEvent e)
{
myKeyEvt(e, "keyPressed");
}
private void myKeyEvt(KeyEvent e, String text)
{
int key = e.getKeyCode();
if (key == KeyEvent.VK_KP_UP || key == KeyEvent.VK_UP)
{
//up
}
else if (key == KeyEvent.VK_KP_DOWN || key == KeyEvent.VK_DOWN)
{
//down
}
else if (key == KeyEvent.VK_KP_LEFT || key == KeyEvent.VK_LEFT)
{
//left
}
else if (key == KeyEvent.VK_KP_RIGHT|| key == KeyEvent.VK_RIGHT)
{
//right
}
}
});
Also, you will want to update your while loop to give it time to pause and refresh
while (alive)
{
update();
repaint();
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
I am trying to develop a simple game where you can move a rectangle using the left and right arrow keys and to shoot using the spacebar.
I have added a KeyListener and others, but when I run it I have nothing as the output of key pressed or others.
I have two classes:
PaintDemo class:
package game;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PaintDemo {
public static void main(String[] args) {
JFrame mainFrame = new JFrame("Game 1.1");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setBounds(10, 10, 400, 400);
mainFrame.setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
mainPanel.setBackground(Color.WHITE);
PaintComponent paintPanel = new PaintComponent();
mainFrame.add(mainPanel, BorderLayout.PAGE_START);
mainFrame.add(paintPanel, BorderLayout.CENTER);
mainFrame.setVisible(true);
}
}
PaintComponent class:
package game;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
public class PaintComponent extends JPanel implements KeyListener {
int dx = 200;
int dy = 300;
int my = 300;
public Rectangle2D rec = new Rectangle2D.Double(dx , dy, 30, 10);
public PaintComponent() {
this.addKeyListener(this);
this.setBackground(Color.white);
}
public void shoot(KeyEvent evt){
if (evt.getKeyCode() == KeyEvent.VK_SPACE){
my -= 7;
repaint();
}
}
public void moveRec(KeyEvent evt){
switch(evt.getKeyCode()){
case KeyEvent.VK_LEFT:
System.out.println("test");
dx -= 2;
rec.setRect(dx, dy, 30, 10);
repaint();
case KeyEvent.VK_RIGHT:
dx += 2;
rec.setRect(dx, dy, 30, 10);
repaint();
}
}
#Override
protected void paintComponent(Graphics grphcs){
super.paintComponent(grphcs);
Graphics2D gr = (Graphics2D) grphcs;
gr.draw(rec);
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println("2");
shoot(e);
}
#Override
public void keyPressed(KeyEvent e) {
moveRec(e);
}
#Override
public void keyReleased(KeyEvent e) {
}
}
The shooting method is not complete.
Change repaint() to paintComponent here and add Graphics g = getGraphics();
public void moveRec(KeyEvent evt){
switch(evt.getKeyCode()){
case KeyEvent.VK_LEFT:
System.out.println("test");
dx -= 2;
rec.setRect(dx, dy, 30, 10);
Graphics g = getGraphics();
paintComponent(g);
break;
case KeyEvent.VK_RIGHT:
dx += 2;
rec.setRect(dx, dy, 30, 10);
Graphics g = getGraphics();
paintComponent(g);
break;
}
}
Let me know if this works :)
EDIT:
Add this line
this.setFocusable(true);
to PaintComponent constructor, it will make keypresses go through.
You forgot to do two things, First one is your panel should be focusable, add this in your PaintComponent constructor this.setFocusable(true) and the second one is you have not break the switch case, so add the break statement for each case, then it should work.
switch (evt.getKeyCode()) {
case KeyEvent.VK_LEFT:
System.out.println("test");
dx -= 2;
rec.setRect(dx, dy, 30, 10);
repaint();
break;
case KeyEvent.VK_RIGHT:
dx += 2;
rec.setRect(dx, dy, 30, 10);
repaint();
break;
}
I made a ping pong game in Java but the paddles doesn't work, and I can't figure out the problem.
Main class: in the main class I give the thread and run the program:
package pingpong;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class PingPong extends JFrame {
int Gwidth=400,Gheight=300;
Dimension screenSize = new Dimension(Gwidth,Gheight);
//double Buffering
Image dbImage;
Graphics dbg;
//ball objects
static Ball b = new Ball(193,143);
//constructor
public PingPong() {
this.setTitle("ping pong Game");
this.setResizable(false);
this.setSize(screenSize);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setBackground(Color.black);
this.setVisible(true);
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
draw(dbg);
g.drawImage(dbImage, 0, 0, this);
}
public void draw(Graphics g) {
b.draw(g);
b.p1.draw(g);
b.p2.draw(g);
g.setColor(Color.white);
g.drawString(""+b.p1Score,15,50);
g.drawString(""+b.p2Score,370,50);
repaint();
}
//event listining class
public class AL extends KeyAdapter { //key buildings
#Override
public void keyPressed(KeyEvent e) {
b.p1.keyPressed( e);
b.p2.keyPressed( e);
}
public void keyRealesed(KeyEvent e){
b.p1.keyReleased( e);
b.p2.keyReleased( e);
}
}
public static void main(String[] args) {
PingPong pp = new PingPong();
//create and start threads
Thread ball=new Thread(b);
ball.start();
Thread p1=new Thread(b.p1);
Thread p2= new Thread(b.p2);
p1.start();
p2.start();
}
}
this is my ball class:
package pingpong;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
public class Ball implements Runnable{
//global variables
int x,y,XDir,YDir;
//score
int p1Score,p2Score;
Paddle p1=new Paddle(15 , 140, 1);
Paddle p2=new Paddle(370, 140 ,2 );
Rectangle ball;
public Ball(int x,int y){
p1Score=p2Score=0;
this.x=x;
this.y=y;
//randomly moving the ball
Random r=new Random();
int rDir = r.nextInt(1);
if (rDir == 0) {
rDir--;
}setXDir(rDir);
int yrDir = r.nextInt(1);
if (yrDir == 0) {
yrDir--;
}setYDir(yrDir);
//create 'ball'
ball = new Rectangle(this.x, this.y,7, 7);
}
public void collision(){
if(ball.intersects(p1.paddle)){
setXDir(+1);}
if(ball.intersects(p2.paddle)){
setXDir(-1);}
}
public void draw(Graphics g){
g.setColor(Color.cyan);
g.fillRect(ball.x,ball.y,ball.width,ball.height);
}
public void move(){
collision();
ball.x +=XDir;
ball.y +=YDir;
//bounce the ball when edge is detected
if(ball.x<0){
setXDir(+1);
//add to score
p1Score++; //?
}
if(ball.x>=385){
setXDir(-1);
//add to score
p2Score++; //?
}
if(ball.y<=15)
setYDir(+1);
if(ball.y>=270)
setYDir(-1);
}
public void setXDir(int xdir){
XDir=xdir;
}
public void setYDir(int ydir){
YDir=ydir;
}
public void run(){
try{
while(true){
move();
Thread.sleep(4);
}
}catch(Exception e) {System.out.println("sorry"+e.getMessage());}
}
}
and there is my paddle class :
package pingpong;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Paddle implements Runnable {
int x, y, yDir, id;
Rectangle paddle;
public Paddle(int x, int y, int id) {
this.x = x;
this.y = y;
this.id = id;
paddle = new Rectangle(x, y, 15, 50);
}
public void keyPressed(KeyEvent e) {
switch (id) {
default:
System.out.println("please enter a valid id");
break;
case 1:
if (e.getKeyCode() == e.VK_UP) {
setYDir(-1);
}
if (e.getKeyCode() == e.VK_DOWN) {
setYDir(+1);
}
break;
case 2:
if (e.getKeyCode() == e.VK_W) {
setYDir(-1);
}
if (e.getKeyCode() == e.VK_S) {
setYDir(+1);
}
break;
}
}
public void keyReleased(KeyEvent e) {
switch (id) {
default:
System.out.println("please enter a valid id");
break;
case 1:
if (e.getKeyCode() == e.VK_UP) {
setYDir(0);
}
if (e.getKeyCode() == e.VK_DOWN) {
setYDir(0);
}
break;
case 2:
if (e.getKeyCode() == e.VK_W) {
setYDir(0);
}
if (e.getKeyCode() == e.VK_S) {
setYDir(0);
}
break;
}
}
public void draw(Graphics g) {
switch (id) {
default:
System.out.println("please enter a valid id");
break;
case 2:
g.setColor(Color.YELLOW);
//draw paddle #1
g.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
break;
case 1:
g.setColor(Color.white);
// draw paddle #2
g.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
break;
}
}
public void setYDir(int ydir) {
yDir = ydir;
}
public void move() {
paddle.x += yDir;
if (paddle.y <= 15) {
paddle.y = 15;
}
if (paddle.y >= 250) {
paddle.y = 250;
}
}
#Override
public void run() {
try {
while (true) {
move();
Thread.sleep(6);
}
} catch (Exception e) {
System.out.println("try again" + e.getMessage());
}
}
}
I personally think I have a problem in the paddle but I can't figure it out.
If you're moving your paddle in Y axis (inside move, this looks wrong:
paddle.x += yDir;
Should be
paddle.y += yDir;