In
the "Games" section of CodeGym you will find exciting projects for writing popular computer games. Do you want to create your own version of the popular 2048, Minesweeper, Snake and other games? It's simple. We've turned game writing into a step-by-step process.
To try yourself as a game developer, you do not have to be an advanced programmer, but a certain set of Java knowledge is still required. Here you will find
information that will be useful when writing games .
1. Inheritance
Working with the CodeGym game engine involves the use of inheritance. But what if you don't know what it is? On the one hand, you need to understand this topic: it is studied at
level 11. On the other hand, the engine was specifically designed to be very simple, so you can get by with a superficial knowledge of inheritance. So what is inheritance? To put it very simply, inheritance is a relationship between two classes. One of them becomes a parent, and the second becomes a child (class-heir). In this case, the parent class may not even know that it has descendant classes. Those. it doesn't get much benefit from having derived classes. But inheritance gives many advantages to a descendant class. And the main one is that all the variables and methods of the parent class appear in the child class, as if the code of the parent class was copied into the child class. This is not entirely true, but for a simplified understanding of inheritance, it will do. Here are some examples to better understand inheritance.
Example 1:the simplest inheritance.
public class Родитель {
}
|
The Child class is inherited from the Parent class using the extends keyword . |
public class Потомок extends Родитель {
}
|
Example 2: using parent class variables.
public class Родитель {
public int age;
public String name;
}
|
The Child class can use the age and name variables of the Parent class as if they were declared in it. |
public class Потомок extends Родитель {
public void printInfo() {
System.out.println(name+" "+age);
}
}
|
Example 3: using parent class methods.
public class Родитель {
public int age;
public String name;
public getName() {
return name;
}
}
|
The Child class can use the variables and methods of the Parent class as if they were declared in it. In this example, we are using the getName () method. |
public class Потомок extends Родитель {
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
|
Here's what
the Child class looks like from the compiler's point of view:
public class Потомок extends Родитель {
public int age;
public String name;
public getName() {
return name;
}
public void printInfo() {
System.out.println(getName()+" "+age);
}
}
2. Overriding Methods
Sometimes there are situations when we inherited our Child class from some Parent class that is very useful to us, along with all the variables and methods, but some methods do not work quite the way we want. Or not at all the way we want. What to do in this situation? We can override the method we didn't like. This is done very simply: in our Child class, we simply declare a method with the same signature (header) as the Parent class method and write our code in it.
Example 1: overriding a method.
public class Родитель {
public String name;
public void setName (String nameNew) {
name = nameNew;
}
public getName() {
return name;
}
}
|
The printInfo() method will print the phrase "Luke, No!!!" to the screen. |
public class Потомок extends Родитель {
public void setName (String nameNew) {
name = nameNew + ",No!!!";
}
public void printInfo() {
setName("Luke");
System.out.println( getName());
}
}
|
Here's what
the Child class looks like from the compiler's point of view:
public Потомок extends Родитель {
public String name;
public void setName (String nameNew) {
name = nameNew + ", No!!!";
}
public getName() {
return name;
}
public void printInfo() {
setName("Luke");
System.out.println(getName());
}
}
Example 2: A bit of inheritance (and method overriding) magic.
public class Родитель {
public getName() {
return "Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
|
public class Потомок extends Родитель {
public getName() {
return "I'm your father, Luke";
}
}
|
In this example: if the method is not overridden in the Child class
printInfo
(from the Parent class), when this method is called on an object of the Child class, its method will be called
getName()
, and not
getName()
the Parent class.
Родитель parent = new Родитель ();
parent.printnInfo();
|
This code is displayed on the screen the inscription "Luke" . |
Потомок child = new Потомок ();
child.printnInfo();
|
This code displays the inscription "I'm your father, Luke;" . |
Here's what
the Child class looks like from the compiler's point of view:
public class Потомок extends Родитель {
public getName() {
return "I'm your father, Luke";
}
public void printInfo() {
System.out.println(getName());
}
}
3. Lists
If you're not familiar with Lists yet, here's a brief introduction. Full details can be found at
levels 6-7 of the CodeGym course .
Lists have a lot in common with arrays:
- can store a lot of data of a certain type;
- allow to get elements by their index/number;
- element indexes start at 0.
Advantages of lists: Unlike arrays, lists can dynamically change size. Immediately after creation, the list has a size of 0. As elements are added to the list, its size increases. List creation example:
ArrayList<String> myList = new ArrayList<String>();
The value in angle brackets is the type of data that the list can store. Here are some methods for working with a list:
Code |
Brief description of code actions |
ArrayList<String> list = new ArrayList<String>(); |
Creating a new list of strings |
list.add("name"); |
Add an element to the end of the list |
list.add(0, "name"); |
Add an element to the beginning of the list |
String name = list.get(5); |
Get an element by its index |
list.set(5, "new name"); |
Change element by its index |
int count = list.size(); |
Get the number of elements in a list |
list.remove(4); |
Remove item from list |
You can learn more about lists in these articles:
- ArrayList class
- ArrayList work in pictures
- Removing an element from an ArrayList
4. Arrays
What is a matrix? A matrix is nothing more than a rectangular table that can be filled with data. In other words, it's a two-dimensional array. As you probably know, arrays in Java are objects. A standard one-dimensional array of type
int
looks like this:
int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
Let's visualize it:
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
32 |
43 |
54 |
15 |
36 |
67 |
28 |
The top row indicates cell addresses. That is, to get the number 67, you need to refer to the array element with index 6:
int number = array[6];
Everything is very simple here. A two-dimensional array is an array of one-dimensional arrays. If you're hearing about it for the first time, stop and imagine it in your head. A two-dimensional array looks like this:
0 |
one dimensional array |
one dimensional array |
1 |
one dimensional array |
2 |
one dimensional array |
3 |
one dimensional array |
4 |
one dimensional array |
5 |
one dimensional array |
6 |
one dimensional array |
7 |
one dimensional array |
In code:
int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78},
{76, 15, 76, 91, 66, 90, 15, 77},
{65, 96, 17, 25, 36, 75, 54, 78},
{59, 45, 68, 14, 57, 1, 9, 63},
{81, 74, 47, 52, 42, 785, 56, 96},
{66, 74, 58, 16, 98, 140, 55, 77},
{120, 99, 13, 90, 78, 98, 14, 78},
{20, 18, 74, 91, 96, 104, 105, 77}
}
0 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
65 |
99 |
87 |
90 |
156 |
75 |
98 |
78 |
1 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
76 |
15 |
76 |
91 |
66 |
90 |
15 |
77 |
2 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
65 |
96 |
17 |
25 |
36 |
75 |
54 |
78 |
3 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
59 |
45 |
68 |
14 |
57 |
1 |
9 |
63 |
4 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
81 |
74 |
47 |
52 |
42 |
785 |
56 |
96 |
5 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
66 |
74 |
58 |
16 |
98 |
140 |
55 |
77 |
6 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
120 |
99 |
13 |
90 |
78 |
98 |
14 |
78 |
7 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
18 |
74 |
91 |
96 |
104 |
105 |
77 |
To get the value 47, you need to refer to the matrix element at address [4][2].
int number = matrix[4][2];
If you notice, the matrix coordinates are different from the classical rectangular coordinate system (Cartesian coordinate system).
When referring to a matrix, you first specify y and then x , while in mathematics it is customary to specify x (x, y) first. You may be wondering, “Why not flip the matrix in your imagination and access the elements in the usual way through (x, y)? The contents of the matrix will not change from this.” Yes, nothing will change. But in the world of programming, it is customary to refer to matrices in the form "first y, then x." This must be taken for granted. Now let's talk about projecting a matrix onto our engine (class
Game
). As you know, the engine has many methods that change the cells of the playing field at given coordinates. For example, the method
setCellValue(int x, int y, String value)
. It sets a certain cell with coordinates (x, y) to
value
. As you noticed, this method first takes exactly x, as in the classical coordinate system. Other methods of the engine work in a similar way. When developing games, it will often be necessary to reproduce the state of the matrix on the screen. How to do it? First, in the loop, you need to iterate over all the elements of the matrix. Second, for each of them, call the method to display with INVERTED coordinates. Example:
private void drawScene() {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
setCellValue(j, i, String.valueOf(matrix[i][j]));
}
}
}
Naturally, inversion works in two directions.
setCellValue
You can pass (i, j) to the method , but at the same time take the element [j][i] from the matrix. Inversion may seem a bit difficult, but it's something to keep in mind. And always, if there are any problems, you should take a piece of paper with a pen, draw a matrix and reproduce what processes are happening with it.
5. Random numbers
How to work with random number generator? The class
Game
has a method defined
getRandomNumber(int)
. Under the hood, it uses a class
Random
from the java.util package, but the principle of working with a random number generator does not change from this.
getRandomNumber(int)
It takes an integer as an argument . This number will be the upper bound that the generator can return. The lower bound is 0.
Important! A generator will NEVER return an upper bound number. For example, if you call
getRandomNumber(3)
it randomly, it can return 0, 1, 2. As you can see, it cannot return 3. This use of a generator is quite simple, but very effective in many cases.
You need to get a random number within some limits: Imagine that you need some three-digit number (100..999). As you already know, the minimum return value is 0. This means that you will need to add 100 to it. But in this case, you need to take care not to step over the upper limit. To get 999 as the maximum random value, call the method
getRandomNumber(int)
with the argument 1000. But we remember about the subsequent addition of 100: this means that the upper limit should also be lowered by 100. That is, the code for obtaining a random three-digit number will look like this:
int number = 100 + getRandomNumber(900);
But to simplify such a procedure, the engine provides a method
getRandomNumber(int, int)
that takes the minimum number to return as the first argument. Using this method, the previous example can be rewritten:
int number = getRandomNumber(100, 1000);
Random numbers can be used to get a random array element:
String [] names = {"Andrey", "Валентин", "Сергей"};
String randomName = names[getRandomNumber(names.length)]
Trigger certain events with a certain probability. A person's morning begins according to possible scenarios: Overslept - 50%; Got up on time - 40%; Got up an hour earlier than expected - 10%. Imagine that you are writing a human morning emulator. You need to trigger events with a certain probability. To do this, again, you need to use a random number generator. Implementations may be different, but the simplest should occur according to the following algorithm:
- set the limits in which you need to generate a number;
- generate a random number;
- process the resulting number.
So, in this case, the limit will be 10. Let's call the method
getRandomNumber(10)
and analyze what he can return to us. It can return 10 digits (from 0 to 9) and each with the same probability - 10%. Now we need to combine all possible outcomes and match them with our possible events. There can be a lot of combinations, depending on your imagination, but the most obvious one sounds: “If the random number lies within [0..4] - call the “Sleep” event, if the number is within [5..8] - “Woke up on time”, and only if the number is 9, then “I got up an hour earlier than expected”. Everything is very simple: within [0..4] there are 5 numbers, each of which can return with a probability of 10%, which in total will be 50%; within [5..8] there are 4 numbers, and 9 is the only number that appears with a probability of 10%. In code, this whole clever construction looks even simpler:
int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
System.out.println("Проспал ");
} else if (randomNumber < 9) {
System.out.println("Встал вовремя ");
} else {
System.out.println("Встал на час раньше положенного ");
}
In general, there can be a lot of options for using random numbers. It all depends on your imagination. But it is most effective to use them if you need to repeatedly get some kind of result. Then this result will be different from the previous one. With some probability, of course. That's all! If you'd like to learn more about the Games section, here's some helpful documentation to help you:
GO TO FULL VERSION