Writing a 2-d game in Java # 2
Good day to all! Continuation of the 1st lesson ( link to the first ).
Today we must create a player, and implement the movement method in it
Let's get started. First, create a new Player.java class.
Let's create some variables like int. The first is x, the second is y, and the third is speed. Let them be private, in order to avoid further errors (immediately set the values for them, x = 0, y = 0, speed = any speed, I will set 2). We also create three methods - getSpeed (), getX () and getY (). They look like this:
They will return to us the current x and y coordinates of our player, as well as the player’s speed.
Now, we need a method responsible for the movement. So we will call it - move. As long as we don’t have a key listener, we’ll just write:
We return to our Main.java class and in it, create the object of our player:
Next, in the actionPerformed () method, we write:
Now, with each timer update, the player will move with us. But now we will not see this movement, because the player’s coordinates are not used anywhere. Now I will briefly explain how the movement occurs on the screen. It’s not the picture of our player that is moving, but the background, which imitates the movement of the player. So, we go to the paint () method and there, instead of rendering coordinates, we enter player.getX () and player.getY (). It should go like this:
We start, and we see that our background is moving.
Now I will explain what we did not quite correctly do.
We must have two separate coordinates - the coordinate of the map and the coordinate of the player. What is it for? Now we draw a layer relative to the player’s coordinates. In the future, we will have objects on the map, and it will be easier to check whether the player interacts with them, having the coordinates of the map. I hope I explained it clearly, and now we are realizing it.
In a good way, we should have a separate object, Universe (Universe) which will contain information about our map (time of day, coordinates, etc.). In subsequent lessons, we will do this, but for now, just add two new variables to the player’s class: mapX and mapY, and immediately set them to 0 and 0. And, as in the case of x and y, create 2 getters.
Now we will correct our move () method.
Instead of x + = speed we write this:
And back to the paint method and change
On the:
We start, and we see that nothing has changed. This is a good sign, so we did everything right.
But we see that the picture is one, and a trace remains behind it. And so we came to such a fork. We can create a game in which the world will constantly expand, depending on which direction the player is going. Or, to make a game with a certain size a location, beyond which it is impossible to go, but the locations can change. What problems did I encounter when creating these two options. If we create a game without borders, then:
If he creates a game based on a change of locations, then:
Under this article is a survey. Do not forget to vote.
Well, while we get along without additional layers, we will create a listener for keystrokes.
In the constructor of the Main.java class, add the following line:
Some may ask why we use the “add listener” method, but add an adapter? It’s just that the adapter allows you not to use all three methods of the listener class, but suppose, as in our case, we implement only two in it:
The first method is responsible for pressing the key, and the second for releasing it. The third method responds to a short keystroke, rather than delaying it, as in the first method. Now, so that we won’t get a whitewash, and so as not to complicate our lives, we will make exactly the same two methods in the player’s class. And now in our methods located in the Main.java class we will write:
In keyPressed:
In keyReleased:
Done! Now we have a keystroke listener. Let's check its performance by simply writing the following line in each of the methods in the Player.java class:
We launch the program, look at our console, and press the keys.
If every time you press a key, numbers are written to the console, this means that you did everything correctly. Don’t be afraid, you don’t need to remember all these keys; for us, the KeyEvent class has already done this.
Now create an enum that will be responsible for the direction of the player. For those who do not know enum, this is such a variable that can have several values that we have prescribed in advance. Create an enum called Direction. In it, separated by commas, we write the following values: UP, DOWN, LEFT, RIGHT, NONE. Now, in the Player class, create a new variable of the Direction type, which we will call playerDirection (immediately set the value to Direction.NONE). Now, make sure that when you click the appropriate buttons, the player’s direction changes. By the way, we will always work with the keyPressed and keyReleased methods from the Player.java class, do not touch them in the Main.java class. So, for starters, in the keyPressed method, declare a variable of type int, which is equal to e.getKeyCode (). We do this for convenience, so that in the future we don’t prescribe the same thing each time. So,
These are conditions for how our player’s direction will change depending on the keys pressed.
Next, change the move method. It should look like this:
For those who don’t know, switch is the same as if, but in a more convenient form. We launch the program, and enjoy!
That's all for today. Again, I leave all the code for those who are confused.
Not changed in any way.
Thanks for attention! Do not forget to vote.
Tasks
Today we must create a player, and implement the movement method in it
Start
Let's get started. First, create a new Player.java class.
Let's create some variables like int. The first is x, the second is y, and the third is speed. Let them be private, in order to avoid further errors (immediately set the values for them, x = 0, y = 0, speed = any speed, I will set 2). We also create three methods - getSpeed (), getX () and getY (). They look like this:
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeed() {
return speed;
}
They will return to us the current x and y coordinates of our player, as well as the player’s speed.
Now, we need a method responsible for the movement. So we will call it - move. As long as we don’t have a key listener, we’ll just write:
public void move() {
x+= speed;
}
We return to our Main.java class and in it, create the object of our player:
Player player = new Player();
Next, in the actionPerformed () method, we write:
player.move();
Now, with each timer update, the player will move with us. But now we will not see this movement, because the player’s coordinates are not used anywhere. Now I will briefly explain how the movement occurs on the screen. It’s not the picture of our player that is moving, but the background, which imitates the movement of the player. So, we go to the paint () method and there, instead of rendering coordinates, we enter player.getX () and player.getY (). It should go like this:
g.drawImage(img, player.getX(), player.getY(),frame.getWidth(), frame.getHeight(), null);
We start, and we see that our background is moving.
Now I will explain what we did not quite correctly do.
We must have two separate coordinates - the coordinate of the map and the coordinate of the player. What is it for? Now we draw a layer relative to the player’s coordinates. In the future, we will have objects on the map, and it will be easier to check whether the player interacts with them, having the coordinates of the map. I hope I explained it clearly, and now we are realizing it.
In a good way, we should have a separate object, Universe (Universe) which will contain information about our map (time of day, coordinates, etc.). In subsequent lessons, we will do this, but for now, just add two new variables to the player’s class: mapX and mapY, and immediately set them to 0 and 0. And, as in the case of x and y, create 2 getters.
Now we will correct our move () method.
Instead of x + = speed we write this:
x-=speed;
mapX+=speed;
And back to the paint method and change
g.drawImage(img, player.getX(), player.getY(),frame.getWidth(), frame.getHeight(), null);
On the:
g.drawImage(img, player.getMapX(), player.getMapY(),frame.getWidth(), frame.getHeight(), null);
We start, and we see that nothing has changed. This is a good sign, so we did everything right.
But we see that the picture is one, and a trace remains behind it. And so we came to such a fork. We can create a game in which the world will constantly expand, depending on which direction the player is going. Or, to make a game with a certain size a location, beyond which it is impossible to go, but the locations can change. What problems did I encounter when creating these two options. If we create a game without borders, then:
- It will be necessary to generate this world, and if it has no limits, then it must be made random, i.e. there will be drawing bugs that we will encounter all the time.
If he creates a game based on a change of locations, then:
- Either it will be straightforward, with a plot, or the change of locations will be random, but in this case there is a problem number 2.
- There should be many locations so that a person is not tired of playing this game.
Under this article is a survey. Do not forget to vote.
Well, while we get along without additional layers, we will create a listener for keystrokes.
In the constructor of the Main.java class, add the following line:
frame.addKeyListener(new KeyAdapter() {
});
Some may ask why we use the “add listener” method, but add an adapter? It’s just that the adapter allows you not to use all three methods of the listener class, but suppose, as in our case, we implement only two in it:
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
The first method is responsible for pressing the key, and the second for releasing it. The third method responds to a short keystroke, rather than delaying it, as in the first method. Now, so that we won’t get a whitewash, and so as not to complicate our lives, we will make exactly the same two methods in the player’s class. And now in our methods located in the Main.java class we will write:
In keyPressed:
player.keyPressed(e);
In keyReleased:
player.keyReleased(e);
Done! Now we have a keystroke listener. Let's check its performance by simply writing the following line in each of the methods in the Player.java class:
System.out.println(e.getKeyCode());
We launch the program, look at our console, and press the keys.
If every time you press a key, numbers are written to the console, this means that you did everything correctly. Don’t be afraid, you don’t need to remember all these keys; for us, the KeyEvent class has already done this.
Now create an enum that will be responsible for the direction of the player. For those who do not know enum, this is such a variable that can have several values that we have prescribed in advance. Create an enum called Direction. In it, separated by commas, we write the following values: UP, DOWN, LEFT, RIGHT, NONE. Now, in the Player class, create a new variable of the Direction type, which we will call playerDirection (immediately set the value to Direction.NONE). Now, make sure that when you click the appropriate buttons, the player’s direction changes. By the way, we will always work with the keyPressed and keyReleased methods from the Player.java class, do not touch them in the Main.java class. So, for starters, in the keyPressed method, declare a variable of type int, which is equal to e.getKeyCode (). We do this for convenience, so that in the future we don’t prescribe the same thing each time. So,
if(key == KeyEvent.VK_W) {
playerDirection = Direction.UP;
}
if(key == KeyEvent.VK_S) {
playerDirection = Direction.DOWN;
}
if(key == KeyEvent.VK_A) {
playerDirection = Direction.LEFT;
}
if(key == KeyEvent.VK_D) {
playerDirection = Direction.RIGHT;
}
These are conditions for how our player’s direction will change depending on the keys pressed.
Next, change the move method. It should look like this:
switch(playerDirection) {
case UP:
mapY+=speed;
break;
case DOWN:
mapY-=speed;
break;
case LEFT:
mapX+=speed;
break;
case RIGHT:
mapX-=speed;
break;
default:
break;
}
For those who don’t know, switch is the same as if, but in a more convenient form. We launch the program, and enjoy!
That's all for today. Again, I leave all the code for those who are confused.
Player.java
import java.awt.event.KeyEvent;
public class Player {
private int x = 0;
private int y = 0;
private int speed = 2;
private int mapX = 0;
private int mapY = 0;
private Direction playerDirection = Direction.NONE;
public void move() {
switch(playerDirection) {
case UP:
mapY+=speed;
break;
case DOWN:
mapY-=speed;
break;
case LEFT:
mapX+=speed;
break;
case RIGHT:
mapX-=speed;
break;
default:
break;
}
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W) {
playerDirection = Direction.UP;
}
if(key == KeyEvent.VK_S) {
playerDirection = Direction.DOWN;
}
if(key == KeyEvent.VK_A) {
playerDirection = Direction.LEFT;
}
if(key == KeyEvent.VK_D) {
playerDirection = Direction.RIGHT;
}
}
public void keyReleased(KeyEvent e) {
System.out.println(e.getKeyCode());
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeed() {
return speed;
}
public int getMapX() {
return mapX;
}
public int getMapY() {
return mapY;
}
}
Main.java
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Main extends JPanel implements ActionListener {
Image img = new ImageIcon("2.png").getImage();
Timer timer = new Timer(20, this);
Player player = new Player();
JFrame frame;
public Main(JFrame frame) {
this.frame = frame;
timer.start();
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
player.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
player.keyReleased(e);
}
});
}
public void paint(Graphics g) {
g.drawImage(img, player.getMapX(), player.getMapY(),frame.getWidth(), frame.getHeight(), null);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
repaint();
player.move();
}
}
Display.java
Not changed in any way.
Thanks for attention! Do not forget to vote.
Only registered users can participate in the survey. Please come in.
Further game change
- 64.1% The game will not have borders 25
- 35.8% The game will be based on a change of locations 14