1. Inheritance

To work with the CodeGym game engine, you will need to use inheritance. But what if you don't know what that is? On the one hand, you do need to understand and study this topic. On the other hand, the engine is specially designed to be very simple, so you can get by with a superficial knowledge of inheritance.

So what is inheritance? In simple terms, inheritance is a relationship between two classes. One of them acts as the parent class, and the other becomes the child (descendant) class. What's more, a parent class may not even know that it has descendant classes. In other words, the parent doesn't get much benefit from having descendant classes.

But inheritance gives many advantages to the child class. The most important of them is that all variables and methods of the parent class appear in the child class, as if the code of the parent class was copied directly into the child class. This is not entirely accurate, but it will suffice for a basic understanding of inheritance.

Here are some examples to help you better understand inheritance.

Example 1 — here's the simplest example

public class Parent
{
}
The Child class inherits the Parent class with the help of the extends keyword.
public class Child extends Parent
{
}

Example 2 — using the variables of the parent class

public class Parent
{
  public int age;
  public String name;
}
The Child class can use the age and name fields of the Parent class as if they were declared in the Child class itself.
public class Child extends Parent
{
  public void printInfo()
  {
    System.out.println(name + " " + age);
  }
}

Example 3 — using methods of the parent class

public class Parent
{
   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 the Child class. In this example, we use the getName() method.
public class Child extends Parent
{
   public void printInfo()
   {
      System.out.println(getName() + " " + age);
   }
}

Omitting some details, we can say that from the Java compiler's perspective, we simply copied the code of the parent class into the code of the child class:

public class Child extends Parent
{
   public int age;        // An inherited variable
   public String name;    // An inherited variable
   public getName() {     // An inherited method
      return name;
   }

   public void printInfo()
   {
      System.out.println(getName() + " " + age);
   }
}
Here's how the Child class appears from the compiler's point of view


2. Method overriding

Sometimes there are situations where we make our Child class inherit a very useful Parent class, causing the child to inherit all the parent's variables and methods. But some of those methods may not work quite the way we want them to or not at all the way we want them to.

What do you do in this case? We can override a method whose implementation we don't like. This is a simple thing to do: in our Child class we simply declare a method with the same signature as the method in the Parent class and then write our own code in it.

Example 1 — method overriding

public class Parent
{
   public String name;
   public void setName(String nameNew) {
      name = nameNew;
   }

   public getName() {
      return name;
   }
}
The printInfo() method will display the following phrase:
Luke, No!!!
public class Child extends Parent
{
   public void setName(String nameNew) {
      name = nameNew + ", No!!!";
   }

   public void printInfo()
   {
      setName("Luke");
      System.out.println(getName());
   }
}

Oversimplifying the situation somewhat, inheritance causes the code of the parent class to be copied into the child class. But if a descendant class already a method that exists in an ancestor class, then that method is not copied from the ancestor class. Here we say that the method in the child class overrides the method in the parent class. Look at the example below. Maybe it will help make things a little clearer:

Here's how the Child class appears from the compiler's point of view:
public class Child extends Parent
{
   public String name;    // An inherited variable

   public void setName(String nameNew)  // The overridden method replaces the inherited one
   {
      name = nameNew + ", No!!!";
   }

   public getName()    // An inherited method
   {
      return name;
   }

   public void printInfo()
   {
      setName("Luke");
      System.out.println(getName());
   }
}

Example 2 - a little inheritance magic (and method overriding)

public class Parent
{
   public getName() {
      return "Luke";
   }

   public void printInfo()
   {
      System.out.println( getName() );
   }
}
public class Child extends Parent
{
   public getName() {
      return "Luke, I am your father";
   }
}

If the printInfo() method is called on a Parent type, it in turn calls the getName() method of the Parent class.

If the printInfo() method is called on a Child object, it in turn calls the getName() method of the Child class.

In other words, the printInfo() method is declared only in the Parent class, but it calls the getName() method of the Child class if the printInfo() method is called on a Child object.

Example:

Parent parent = new Parent();
parent.printnInfo();
This code displays the following text on the screen:
Luke
Child child = new Child();
child.printnInfo();
This code displays the following text on the screen:
Luke, I am your father

And all because from the compiler's point of view (a very simplified version of it), the code of the Child class looks like this:

public class Child extends Parent
{
   public getName() {
      return "Luke, I am your father";
   }

   public void printInfo()
   {
      System.out.println(getName());
   }
}
Here's how the Child class appears from the compiler's point of view


3. Lists

Here's a brief reminder about lists (List). Lists have a lot in common with arrays:

  • They can store a lot of data of a specific type.
  • They let you get elements by their index.
  • The indices of the elements start at 0.

Advantages of lists:

Unlike arrays, lists can dynamically change size. Immediately after creation, the size of a list is 0. As items are added to the list, its size increases. Example of creating a list:

ArrayList<String> myList = new ArrayList<String>();
Creating a new ArrayList

The value indicated in the angle brackets is the data type that the list can store.

Here are some methods for working with a list:

Code Brief description
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 start of the list
String name = list.get(5);
Get an element by its index
list.set(5, "new name");
Change an element by its index
int count = list.size();
Get the number of elements in the list
list.remove(4);
Remove an element from the list

For more information about lists, you can read the following articles:



4. Random numbers

The CodeGym game engine has two methods that can be used to generate random numbers. These methods are:

int getRandomNumber(int max)
int getRandomNumber(int min, int max)

The first method — getRandomNumber(int max) — returns a random number in the range 0, 1, 2, ... max-1. Under the hood, it uses the Random class from the java.util package, but that doesn't change how you use a random number.

getRandomNumber(int) accepts an integer as an argument. This number will be the upper bound on the numbers that the random number generator can return. The lower bound is 0. Attention! The random number generator will NEVER return the value of the upper bound. For example, if you call getRandomNumber(3), it will randomly return either 0, 1, or 2. As you can see, it will not return 3. Using a random number generator in this way is rather simple, but it is suitable for many cases.

The second method — getRandomNumber(int min, int max) — returns a random integer in the range [min, max-1]. It will never return a number less than min, and it will never return a number greater than max-1.

How can these methods be used in practice?

1. Dice

Suppose you want to simulate the roll of a die and get a random number in the range 1-6. How would you do it? This can be done with code like this:

int dice = getRandomNumber(1, 7);

This method will return a random integer in the range 1-6.

2. Target practice

Suppose you want to simulate shooting at a target, and the accuracy of a shot includes a random component that varies in the range from -10 to +10 inclusive. This can be done with code like this:

int dx = getRandomNumber(-10, 11);

This method will return a random integer in the range -10 to +10.

There are many ways to use random numbers in games. You're only limited by your imagination. Write your own games, refine them, and enjoy the process.

Everyone can play games, but only programmers can create them.